Merge remote branch 'origin/master' into nv50-compiler
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Thu, 2 Sep 2010 16:31:49 +0000 (18:31 +0200)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Thu, 2 Sep 2010 16:31:49 +0000 (18:31 +0200)
Conflicts:
src/gallium/drivers/nv50/nv50_program.c

1079 files changed:
Makefile
SConstruct
bin/minstall
bin/mklib
configs/autoconf.in
configs/default
configs/linux-dri
configs/linux-llvm
configure.ac
docs/MESA_drm_image.spec [new file with mode: 0644]
docs/contents.html
docs/developers.html
docs/intro.html
docs/news.html
docs/relnotes-7.9.html
docs/shading.html
docs/subset-A.html
include/EGL/eglext.h
include/GL/internal/dri_interface.h
include/c99/inttypes.h [new file with mode: 0644]
include/c99/stdint.h
scons/gallium.py
src/SConscript
src/egl/docs/EGL_MESA_screen_surface
src/egl/drivers/dri2/egl_dri2.c
src/egl/main/Makefile
src/egl/main/SConscript
src/egl/main/egl.def [new file with mode: 0644]
src/egl/main/eglapi.c
src/egl/main/eglapi.h
src/egl/main/eglconfig.c
src/egl/main/eglcontext.c
src/egl/main/egldisplay.h
src/egl/main/egldriver.c
src/egl/main/eglmisc.c
src/egl/main/eglsync.c [new file with mode: 0644]
src/egl/main/eglsync.h [new file with mode: 0644]
src/egl/main/egltypedefs.h
src/gallium/auxiliary/Makefile
src/gallium/auxiliary/SConscript
src/gallium/auxiliary/draw/draw_cliptest_tmp.h [new file with mode: 0644]
src/gallium/auxiliary/draw/draw_context.c
src/gallium/auxiliary/draw/draw_context.h
src/gallium/auxiliary/draw/draw_decompose_tmp.h
src/gallium/auxiliary/draw/draw_gs.c
src/gallium/auxiliary/draw/draw_gs_tmp.h
src/gallium/auxiliary/draw/draw_llvm.c
src/gallium/auxiliary/draw/draw_llvm.h
src/gallium/auxiliary/draw/draw_pipe.c
src/gallium/auxiliary/draw/draw_pipe_validate.c
src/gallium/auxiliary/draw/draw_pipe_vbuf.c
src/gallium/auxiliary/draw/draw_private.h
src/gallium/auxiliary/draw/draw_pt.c
src/gallium/auxiliary/draw/draw_pt.h
src/gallium/auxiliary/draw/draw_pt_elts.c [deleted file]
src/gallium/auxiliary/draw/draw_pt_emit.c
src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
src/gallium/auxiliary/draw/draw_pt_post_vs.c
src/gallium/auxiliary/draw/draw_pt_so_emit.c
src/gallium/auxiliary/draw/draw_pt_util.c
src/gallium/auxiliary/draw/draw_pt_varray.c [deleted file]
src/gallium/auxiliary/draw/draw_pt_varray_tmp.h [deleted file]
src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h [deleted file]
src/gallium/auxiliary/draw/draw_pt_vcache.c [deleted file]
src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h [deleted file]
src/gallium/auxiliary/draw/draw_pt_vsplit.c [new file with mode: 0644]
src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h [new file with mode: 0644]
src/gallium/auxiliary/draw/draw_so_emit_tmp.h
src/gallium/auxiliary/draw/draw_split_tmp.h [new file with mode: 0644]
src/gallium/auxiliary/draw/draw_vs_llvm.c
src/gallium/auxiliary/gallivm/lp_bld_arit.c
src/gallium/auxiliary/gallivm/lp_bld_debug.c
src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
src/gallium/auxiliary/gallivm/lp_bld_misc.cpp
src/gallium/auxiliary/gallivm/lp_bld_pack.h
src/gallium/auxiliary/gallivm/lp_bld_sample.c
src/gallium/auxiliary/gallivm/lp_bld_sample.h
src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
src/gallium/auxiliary/gallivm/lp_bld_type.h
src/gallium/auxiliary/os/os_stream.c [new file with mode: 0644]
src/gallium/auxiliary/os/os_stream.h
src/gallium/auxiliary/os/os_stream_log.c
src/gallium/auxiliary/os/os_stream_null.c
src/gallium/auxiliary/os/os_stream_stdc.c
src/gallium/auxiliary/os/os_stream_str.c
src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
src/gallium/auxiliary/rtasm/rtasm_cpu.c
src/gallium/auxiliary/rtasm/rtasm_x86sse.c
src/gallium/auxiliary/rtasm/rtasm_x86sse.h
src/gallium/auxiliary/tgsi/tgsi_dump.h
src/gallium/auxiliary/tgsi/tgsi_exec.c
src/gallium/auxiliary/tgsi/tgsi_info.h
src/gallium/auxiliary/tgsi/tgsi_parse.c
src/gallium/auxiliary/tgsi/tgsi_parse.h
src/gallium/auxiliary/tgsi/tgsi_sse2.h
src/gallium/auxiliary/translate/translate.c
src/gallium/auxiliary/translate/translate.h
src/gallium/auxiliary/translate/translate_generic.c
src/gallium/auxiliary/translate/translate_sse.c
src/gallium/auxiliary/util/u_bitmask.h
src/gallium/auxiliary/util/u_blit.c
src/gallium/auxiliary/util/u_blit.h
src/gallium/auxiliary/util/u_blitter.c
src/gallium/auxiliary/util/u_blitter.h
src/gallium/auxiliary/util/u_cpu_detect.c
src/gallium/auxiliary/util/u_debug_describe.c [new file with mode: 0644]
src/gallium/auxiliary/util/u_debug_describe.h [new file with mode: 0644]
src/gallium/auxiliary/util/u_debug_refcnt.c [new file with mode: 0644]
src/gallium/auxiliary/util/u_debug_refcnt.h [new file with mode: 0644]
src/gallium/auxiliary/util/u_debug_symbol.c
src/gallium/auxiliary/util/u_debug_symbol.h
src/gallium/auxiliary/util/u_dirty_surfaces.h
src/gallium/auxiliary/util/u_draw.h
src/gallium/auxiliary/util/u_dynarray.h
src/gallium/auxiliary/util/u_gen_mipmap.c
src/gallium/auxiliary/util/u_inlines.h
src/gallium/auxiliary/util/u_linkage.c [new file with mode: 0644]
src/gallium/auxiliary/util/u_linkage.h [new file with mode: 0644]
src/gallium/auxiliary/util/u_math.h
src/gallium/auxiliary/util/u_pack_color.h
src/gallium/auxiliary/util/u_rect.c
src/gallium/auxiliary/util/u_rect.h
src/gallium/auxiliary/util/u_simple_shaders.c
src/gallium/auxiliary/util/u_split_prim.h
src/gallium/auxiliary/util/u_staging.c
src/gallium/auxiliary/util/u_staging.h
src/gallium/auxiliary/util/u_surface.c
src/gallium/auxiliary/util/u_surfaces.c
src/gallium/auxiliary/util/u_surfaces.h
src/gallium/auxiliary/util/u_tile.h
src/gallium/auxiliary/util/u_transfer.h
src/gallium/auxiliary/util/u_upload_mgr.h
src/gallium/docs/source/context.rst
src/gallium/docs/source/debugging.rst
src/gallium/docs/source/distro.rst
src/gallium/docs/source/index.rst
src/gallium/docs/source/resources.rst [new file with mode: 0644]
src/gallium/drivers/cell/ppu/cell_draw_arrays.c
src/gallium/drivers/cell/ppu/cell_state_vertex.c
src/gallium/drivers/galahad/glhd_context.c
src/gallium/drivers/galahad/glhd_screen.c
src/gallium/drivers/i915/i915_context.c
src/gallium/drivers/i915/i915_resource_texture.c
src/gallium/drivers/i915/i915_state.c
src/gallium/drivers/i965/brw_batchbuffer.c
src/gallium/drivers/i965/brw_resource_texture.c
src/gallium/drivers/i965/brw_wm_debug.c
src/gallium/drivers/llvmpipe/Makefile
src/gallium/drivers/llvmpipe/SConscript
src/gallium/drivers/llvmpipe/lp_context.c
src/gallium/drivers/llvmpipe/lp_context.h
src/gallium/drivers/llvmpipe/lp_debug.h
src/gallium/drivers/llvmpipe/lp_draw_arrays.c
src/gallium/drivers/llvmpipe/lp_fence.c
src/gallium/drivers/llvmpipe/lp_fence.h
src/gallium/drivers/llvmpipe/lp_flush.c
src/gallium/drivers/llvmpipe/lp_flush.h
src/gallium/drivers/llvmpipe/lp_perf.c
src/gallium/drivers/llvmpipe/lp_perf.h
src/gallium/drivers/llvmpipe/lp_query.c
src/gallium/drivers/llvmpipe/lp_rast.c
src/gallium/drivers/llvmpipe/lp_rast.h
src/gallium/drivers/llvmpipe/lp_rast_tri.c
src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h
src/gallium/drivers/llvmpipe/lp_scene.c
src/gallium/drivers/llvmpipe/lp_screen.c
src/gallium/drivers/llvmpipe/lp_setup.c
src/gallium/drivers/llvmpipe/lp_setup.h
src/gallium/drivers/llvmpipe/lp_setup_coef.c [new file with mode: 0644]
src/gallium/drivers/llvmpipe/lp_setup_coef.h [new file with mode: 0644]
src/gallium/drivers/llvmpipe/lp_setup_coef_intrin.c [new file with mode: 0644]
src/gallium/drivers/llvmpipe/lp_setup_context.h
src/gallium/drivers/llvmpipe/lp_setup_line.c
src/gallium/drivers/llvmpipe/lp_setup_point.c
src/gallium/drivers/llvmpipe/lp_setup_tri.c
src/gallium/drivers/llvmpipe/lp_state_derived.c
src/gallium/drivers/llvmpipe/lp_state_fs.c
src/gallium/drivers/llvmpipe/lp_state_fs.h
src/gallium/drivers/llvmpipe/lp_state_rasterizer.c
src/gallium/drivers/llvmpipe/lp_state_vertex.c
src/gallium/drivers/llvmpipe/lp_surface.c
src/gallium/drivers/llvmpipe/lp_texture.c
src/gallium/drivers/nouveau/nouveau_class.h
src/gallium/drivers/nouveau/nouveau_screen.c
src/gallium/drivers/nouveau/nouveau_util.h [deleted file]
src/gallium/drivers/nv50/nv50_miptree.c
src/gallium/drivers/nv50/nv50_push.c
src/gallium/drivers/nv50/nv50_tex.c
src/gallium/drivers/nvfx/Makefile
src/gallium/drivers/nvfx/SConscript
src/gallium/drivers/nvfx/nv04_2d.c [new file with mode: 0644]
src/gallium/drivers/nvfx/nv04_2d.h [new file with mode: 0644]
src/gallium/drivers/nvfx/nv04_2d_loops.h [new file with mode: 0644]
src/gallium/drivers/nvfx/nv04_surface_2d.c [deleted file]
src/gallium/drivers/nvfx/nv04_surface_2d.h [deleted file]
src/gallium/drivers/nvfx/nv30_fragtex.c
src/gallium/drivers/nvfx/nv30_vertprog.h
src/gallium/drivers/nvfx/nv40_fragtex.c
src/gallium/drivers/nvfx/nv40_vertprog.h
src/gallium/drivers/nvfx/nvfx_buffer.c
src/gallium/drivers/nvfx/nvfx_context.c
src/gallium/drivers/nvfx/nvfx_context.h
src/gallium/drivers/nvfx/nvfx_draw.c
src/gallium/drivers/nvfx/nvfx_fragprog.c
src/gallium/drivers/nvfx/nvfx_fragtex.c
src/gallium/drivers/nvfx/nvfx_miptree.c
src/gallium/drivers/nvfx/nvfx_push.c [new file with mode: 0644]
src/gallium/drivers/nvfx/nvfx_resource.c
src/gallium/drivers/nvfx/nvfx_resource.h
src/gallium/drivers/nvfx/nvfx_screen.c
src/gallium/drivers/nvfx/nvfx_screen.h
src/gallium/drivers/nvfx/nvfx_shader.h
src/gallium/drivers/nvfx/nvfx_state.c
src/gallium/drivers/nvfx/nvfx_state.h
src/gallium/drivers/nvfx/nvfx_state_emit.c
src/gallium/drivers/nvfx/nvfx_state_fb.c
src/gallium/drivers/nvfx/nvfx_state_stipple.c
src/gallium/drivers/nvfx/nvfx_surface.c
src/gallium/drivers/nvfx/nvfx_tex.h
src/gallium/drivers/nvfx/nvfx_transfer.c
src/gallium/drivers/nvfx/nvfx_transfer.h
src/gallium/drivers/nvfx/nvfx_vbo.c
src/gallium/drivers/nvfx/nvfx_vertprog.c
src/gallium/drivers/r300/r300_context.c
src/gallium/drivers/r300/r300_context.h
src/gallium/drivers/r300/r300_emit.c
src/gallium/drivers/r300/r300_flush.c
src/gallium/drivers/r300/r300_fs.c
src/gallium/drivers/r300/r300_hyperz.c
src/gallium/drivers/r300/r300_hyperz.h
src/gallium/drivers/r300/r300_reg.h
src/gallium/drivers/r300/r300_render.c
src/gallium/drivers/r300/r300_state.c
src/gallium/drivers/r300/r300_state_derived.c
src/gallium/drivers/r300/r300_texture.c
src/gallium/drivers/r300/r300_texture.h
src/gallium/drivers/r300/r300_texture_desc.c
src/gallium/drivers/r300/r300_texture_desc.h
src/gallium/drivers/r300/r300_tgsi_to_rc.c
src/gallium/drivers/r300/r300_vs.c
src/gallium/drivers/r300/r300_winsys.h
src/gallium/drivers/r600/r600_asm.c
src/gallium/drivers/r600/r600_asm.h
src/gallium/drivers/r600/r600_blit.c
src/gallium/drivers/r600/r600_context.c
src/gallium/drivers/r600/r600_context.h
src/gallium/drivers/r600/r600_draw.c
src/gallium/drivers/r600/r600_query.c
src/gallium/drivers/r600/r600_resource.h
src/gallium/drivers/r600/r600_screen.c
src/gallium/drivers/r600/r600_screen.h
src/gallium/drivers/r600/r600_shader.c
src/gallium/drivers/r600/r600_shader.h
src/gallium/drivers/r600/r600_sq.h
src/gallium/drivers/r600/r600_state.c
src/gallium/drivers/r600/r600_state_inlines.h
src/gallium/drivers/r600/r600_texture.c
src/gallium/drivers/r600/r600d.h
src/gallium/drivers/r600/radeon.h
src/gallium/drivers/softpipe/sp_draw_arrays.c
src/gallium/drivers/softpipe/sp_flush.c
src/gallium/drivers/softpipe/sp_screen.c
src/gallium/drivers/softpipe/sp_state_vertex.c
src/gallium/drivers/softpipe/sp_tex_sample.c
src/gallium/drivers/svga/svga_cmd.c
src/gallium/drivers/svga/svga_context.c
src/gallium/drivers/svga/svga_context.h
src/gallium/drivers/svga/svga_pipe_draw.c
src/gallium/drivers/svga/svga_resource_texture.c
src/gallium/drivers/svga/svga_state_framebuffer.c
src/gallium/drivers/svga/svga_state_tss.c
src/gallium/drivers/svga/svga_swtnl.h
src/gallium/drivers/svga/svga_swtnl_draw.c
src/gallium/drivers/svga/svga_tgsi_emit.h
src/gallium/drivers/svga/svga_tgsi_insn.c
src/gallium/drivers/trace/tr_context.c
src/gallium/include/pipe/p_compiler.h
src/gallium/include/pipe/p_context.h
src/gallium/include/pipe/p_defines.h
src/gallium/include/pipe/p_format.h
src/gallium/include/pipe/p_shader_tokens.h
src/gallium/include/pipe/p_state.h
src/gallium/include/state_tracker/graw.h
src/gallium/state_trackers/dri/common/dri_context.h
src/gallium/state_trackers/dri/common/dri_screen.c
src/gallium/state_trackers/dri/common/dri_screen.h
src/gallium/state_trackers/dri/drm/dri2.c
src/gallium/state_trackers/dri/sw/drisw.c
src/gallium/state_trackers/egl/Makefile
src/gallium/state_trackers/egl/SConscript
src/gallium/state_trackers/egl/common/egl_g3d.c
src/gallium/state_trackers/egl/common/egl_g3d.h
src/gallium/state_trackers/egl/common/egl_g3d_api.c
src/gallium/state_trackers/egl/common/egl_g3d_image.c
src/gallium/state_trackers/egl/common/egl_g3d_image.h
src/gallium/state_trackers/egl/common/egl_g3d_sync.c [new file with mode: 0644]
src/gallium/state_trackers/egl/common/egl_g3d_sync.h [new file with mode: 0644]
src/gallium/state_trackers/egl/kms/native_kms.c
src/gallium/state_trackers/glx/xlib/glx_api.c
src/gallium/state_trackers/glx/xlib/glx_usefont.c
src/gallium/state_trackers/glx/xlib/xm_api.c
src/gallium/state_trackers/glx/xlib/xm_api.h
src/gallium/state_trackers/glx/xlib/xm_st.c
src/gallium/state_trackers/wgl/stw_context.c
src/gallium/state_trackers/wgl/stw_device.c
src/gallium/state_trackers/wgl/stw_pixelformat.c
src/gallium/state_trackers/wgl/stw_pixelformat.h
src/gallium/targets/Makefile.dri
src/gallium/targets/SConscript
src/gallium/targets/dri-r300/Makefile [new file with mode: 0644]
src/gallium/targets/dri-r300/SConscript [new file with mode: 0644]
src/gallium/targets/dri-r300/target.c [new file with mode: 0644]
src/gallium/targets/dri-r600/Makefile
src/gallium/targets/dri-radeong/Makefile [deleted file]
src/gallium/targets/dri-radeong/SConscript [deleted file]
src/gallium/targets/dri-radeong/target.c [deleted file]
src/gallium/targets/egl-gdi/egl-static.c
src/gallium/targets/egl/Makefile
src/gallium/targets/egl/egl.c
src/gallium/targets/egl/pipe_r300.c [new file with mode: 0644]
src/gallium/targets/egl/pipe_r600.c [new file with mode: 0644]
src/gallium/targets/egl/pipe_radeon.c [deleted file]
src/gallium/targets/graw-xlib/graw_util.c
src/gallium/targets/graw-xlib/graw_xlib.c
src/gallium/targets/libgl-gdi/SConscript
src/gallium/targets/libgl-xlib/Makefile
src/gallium/targets/libgl-xlib/SConscript
src/gallium/targets/libgl-xlib/xlib.c
src/gallium/tests/python/tests/texture_blit.py
src/gallium/tools/addr2line.sh [new file with mode: 0755]
src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c
src/gallium/winsys/r600/drm/r600_state.c
src/gallium/winsys/r600/drm/r600_states.h
src/gallium/winsys/r600/drm/r600d.h
src/gallium/winsys/r600/drm/radeon.c
src/gallium/winsys/r600/drm/radeon_bo.c
src/gallium/winsys/r600/drm/radeon_ctx.c
src/gallium/winsys/r600/drm/radeon_draw.c
src/gallium/winsys/r600/drm/radeon_priv.h
src/gallium/winsys/r600/drm/radeon_state.c
src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c
src/glsl/.dir-locals.el [new file with mode: 0644]
src/glsl/.gitignore [new file with mode: 0644]
src/glsl/Makefile
src/glsl/Makefile.am [new file with mode: 0644]
src/glsl/README [new file with mode: 0644]
src/glsl/SConscript
src/glsl/TODO [new file with mode: 0644]
src/glsl/apps/.gitignore [deleted file]
src/glsl/apps/Makefile [deleted file]
src/glsl/apps/compile.c [deleted file]
src/glsl/apps/process.c [deleted file]
src/glsl/apps/purify.c [deleted file]
src/glsl/apps/tokenise.c [deleted file]
src/glsl/apps/version.c [deleted file]
src/glsl/ast.h [new file with mode: 0644]
src/glsl/ast_expr.cpp [new file with mode: 0644]
src/glsl/ast_function.cpp [new file with mode: 0644]
src/glsl/ast_to_hir.cpp [new file with mode: 0644]
src/glsl/ast_type.cpp [new file with mode: 0644]
src/glsl/autogen.sh [new file with mode: 0755]
src/glsl/builtin_function.cpp [new file with mode: 0644]
src/glsl/builtin_types.h [new file with mode: 0644]
src/glsl/builtin_variables.h [new file with mode: 0644]
src/glsl/builtins/ir/abs [new file with mode: 0644]
src/glsl/builtins/ir/acos [new file with mode: 0644]
src/glsl/builtins/ir/all [new file with mode: 0644]
src/glsl/builtins/ir/any [new file with mode: 0644]
src/glsl/builtins/ir/asin [new file with mode: 0644]
src/glsl/builtins/ir/atan [new file with mode: 0644]
src/glsl/builtins/ir/ceil [new file with mode: 0644]
src/glsl/builtins/ir/clamp [new file with mode: 0644]
src/glsl/builtins/ir/cos [new file with mode: 0644]
src/glsl/builtins/ir/cosh [new file with mode: 0644]
src/glsl/builtins/ir/cross [new file with mode: 0644]
src/glsl/builtins/ir/dFdx [new file with mode: 0644]
src/glsl/builtins/ir/dFdy [new file with mode: 0644]
src/glsl/builtins/ir/degrees [new file with mode: 0644]
src/glsl/builtins/ir/distance [new file with mode: 0644]
src/glsl/builtins/ir/dot [new file with mode: 0644]
src/glsl/builtins/ir/equal [new file with mode: 0644]
src/glsl/builtins/ir/exp [new file with mode: 0644]
src/glsl/builtins/ir/exp2 [new file with mode: 0644]
src/glsl/builtins/ir/faceforward [new file with mode: 0644]
src/glsl/builtins/ir/floor [new file with mode: 0644]
src/glsl/builtins/ir/fract [new file with mode: 0644]
src/glsl/builtins/ir/ftransform [new file with mode: 0644]
src/glsl/builtins/ir/fwidth [new file with mode: 0644]
src/glsl/builtins/ir/greaterThan [new file with mode: 0644]
src/glsl/builtins/ir/greaterThanEqual [new file with mode: 0644]
src/glsl/builtins/ir/inversesqrt [new file with mode: 0644]
src/glsl/builtins/ir/length [new file with mode: 0644]
src/glsl/builtins/ir/lessThan [new file with mode: 0644]
src/glsl/builtins/ir/lessThanEqual [new file with mode: 0644]
src/glsl/builtins/ir/log [new file with mode: 0644]
src/glsl/builtins/ir/log2 [new file with mode: 0644]
src/glsl/builtins/ir/matrixCompMult [new file with mode: 0644]
src/glsl/builtins/ir/max [new file with mode: 0644]
src/glsl/builtins/ir/min [new file with mode: 0644]
src/glsl/builtins/ir/mix [new file with mode: 0644]
src/glsl/builtins/ir/mod [new file with mode: 0644]
src/glsl/builtins/ir/noise1 [new file with mode: 0644]
src/glsl/builtins/ir/noise2 [new file with mode: 0644]
src/glsl/builtins/ir/noise3 [new file with mode: 0644]
src/glsl/builtins/ir/noise4 [new file with mode: 0644]
src/glsl/builtins/ir/normalize [new file with mode: 0644]
src/glsl/builtins/ir/not [new file with mode: 0644]
src/glsl/builtins/ir/notEqual [new file with mode: 0644]
src/glsl/builtins/ir/outerProduct [new file with mode: 0644]
src/glsl/builtins/ir/pow [new file with mode: 0644]
src/glsl/builtins/ir/radians [new file with mode: 0644]
src/glsl/builtins/ir/reflect [new file with mode: 0644]
src/glsl/builtins/ir/refract [new file with mode: 0644]
src/glsl/builtins/ir/sign [new file with mode: 0644]
src/glsl/builtins/ir/sin [new file with mode: 0644]
src/glsl/builtins/ir/sinh [new file with mode: 0644]
src/glsl/builtins/ir/smoothstep [new file with mode: 0644]
src/glsl/builtins/ir/sqrt [new file with mode: 0644]
src/glsl/builtins/ir/step [new file with mode: 0644]
src/glsl/builtins/ir/tan [new file with mode: 0644]
src/glsl/builtins/ir/tanh [new file with mode: 0644]
src/glsl/builtins/ir/transpose [new file with mode: 0644]
src/glsl/builtins/profiles/110.frag [new file with mode: 0644]
src/glsl/builtins/profiles/110.vert [new file with mode: 0644]
src/glsl/builtins/profiles/120.frag [new file with mode: 0644]
src/glsl/builtins/profiles/120.vert [new file with mode: 0644]
src/glsl/builtins/profiles/130.frag [new file with mode: 0644]
src/glsl/builtins/profiles/130.vert [new file with mode: 0644]
src/glsl/builtins/profiles/ARB_texture_rectangle.frag [new file with mode: 0644]
src/glsl/builtins/profiles/ARB_texture_rectangle.vert [new file with mode: 0644]
src/glsl/builtins/profiles/EXT_texture_array.frag [new file with mode: 0644]
src/glsl/builtins/profiles/EXT_texture_array.vert [new file with mode: 0644]
src/glsl/builtins/tools/builtin_function.cpp [new file with mode: 0644]
src/glsl/builtins/tools/generate_builtins.py [new file with mode: 0755]
src/glsl/builtins/tools/generate_matrixCompMultGLSL.py [new file with mode: 0755]
src/glsl/builtins/tools/generate_outerProductGLSL.py [new file with mode: 0755]
src/glsl/builtins/tools/generate_transposeGLSL.py [new file with mode: 0755]
src/glsl/builtins/tools/texture_builtins.py [new file with mode: 0755]
src/glsl/cl/Makefile [deleted file]
src/glsl/cl/sl_cl_parse.c [deleted file]
src/glsl/cl/sl_cl_parse.h [deleted file]
src/glsl/configure.ac [new file with mode: 0644]
src/glsl/glcpp/.gitignore [new file with mode: 0644]
src/glsl/glcpp/Makefile.am [new file with mode: 0644]
src/glsl/glcpp/README [new file with mode: 0644]
src/glsl/glcpp/glcpp-lex.c [new file with mode: 0644]
src/glsl/glcpp/glcpp-lex.l [new file with mode: 0644]
src/glsl/glcpp/glcpp-parse.c [new file with mode: 0644]
src/glsl/glcpp/glcpp-parse.h [new file with mode: 0644]
src/glsl/glcpp/glcpp-parse.y [new file with mode: 0644]
src/glsl/glcpp/glcpp.c [new file with mode: 0644]
src/glsl/glcpp/glcpp.h [new file with mode: 0644]
src/glsl/glcpp/pp.c [new file with mode: 0644]
src/glsl/glcpp/tests/000-content-with-spaces.c [new file with mode: 0644]
src/glsl/glcpp/tests/000-content-with-spaces.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/001-define.c [new file with mode: 0644]
src/glsl/glcpp/tests/001-define.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/002-define-chain.c [new file with mode: 0644]
src/glsl/glcpp/tests/002-define-chain.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/003-define-chain-reverse.c [new file with mode: 0644]
src/glsl/glcpp/tests/003-define-chain-reverse.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/004-define-recursive.c [new file with mode: 0644]
src/glsl/glcpp/tests/004-define-recursive.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/005-define-composite-chain.c [new file with mode: 0644]
src/glsl/glcpp/tests/005-define-composite-chain.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/006-define-composite-chain-reverse.c [new file with mode: 0644]
src/glsl/glcpp/tests/006-define-composite-chain-reverse.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/007-define-composite-recursive.c [new file with mode: 0644]
src/glsl/glcpp/tests/007-define-composite-recursive.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/008-define-empty.c [new file with mode: 0644]
src/glsl/glcpp/tests/008-define-empty.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/009-undef.c [new file with mode: 0644]
src/glsl/glcpp/tests/009-undef.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/010-undef-re-define.c [new file with mode: 0644]
src/glsl/glcpp/tests/010-undef-re-define.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/011-define-func-empty.c [new file with mode: 0644]
src/glsl/glcpp/tests/011-define-func-empty.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/012-define-func-no-args.c [new file with mode: 0644]
src/glsl/glcpp/tests/012-define-func-no-args.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/013-define-func-1-arg-unused.c [new file with mode: 0644]
src/glsl/glcpp/tests/013-define-func-1-arg-unused.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/014-define-func-2-arg-unused.c [new file with mode: 0644]
src/glsl/glcpp/tests/014-define-func-2-arg-unused.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/015-define-object-with-parens.c [new file with mode: 0644]
src/glsl/glcpp/tests/015-define-object-with-parens.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/016-define-func-1-arg.c [new file with mode: 0644]
src/glsl/glcpp/tests/016-define-func-1-arg.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/017-define-func-2-args.c [new file with mode: 0644]
src/glsl/glcpp/tests/017-define-func-2-args.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c [new file with mode: 0644]
src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/019-define-func-1-arg-multi.c [new file with mode: 0644]
src/glsl/glcpp/tests/019-define-func-1-arg-multi.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/020-define-func-2-arg-multi.c [new file with mode: 0644]
src/glsl/glcpp/tests/020-define-func-2-arg-multi.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/021-define-func-compose.c [new file with mode: 0644]
src/glsl/glcpp/tests/021-define-func-compose.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/022-define-func-arg-with-parens.c [new file with mode: 0644]
src/glsl/glcpp/tests/022-define-func-arg-with-parens.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/023-define-extra-whitespace.c [new file with mode: 0644]
src/glsl/glcpp/tests/023-define-extra-whitespace.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c [new file with mode: 0644]
src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/025-func-macro-as-non-macro.c [new file with mode: 0644]
src/glsl/glcpp/tests/025-func-macro-as-non-macro.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/026-define-func-extra-newlines.c [new file with mode: 0644]
src/glsl/glcpp/tests/026-define-func-extra-newlines.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/027-define-chain-obj-to-func.c [new file with mode: 0644]
src/glsl/glcpp/tests/027-define-chain-obj-to-func.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c [new file with mode: 0644]
src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c [new file with mode: 0644]
src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c [new file with mode: 0644]
src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c [new file with mode: 0644]
src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/032-define-func-self-recurse.c [new file with mode: 0644]
src/glsl/glcpp/tests/032-define-func-self-recurse.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/033-define-func-self-compose.c [new file with mode: 0644]
src/glsl/glcpp/tests/033-define-func-self-compose.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c [new file with mode: 0644]
src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c [new file with mode: 0644]
src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c [new file with mode: 0644]
src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c [new file with mode: 0644]
src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/038-func-arg-with-commas.c [new file with mode: 0644]
src/glsl/glcpp/tests/038-func-arg-with-commas.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c [new file with mode: 0644]
src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/040-token-pasting.c [new file with mode: 0644]
src/glsl/glcpp/tests/040-token-pasting.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/041-if-0.c [new file with mode: 0644]
src/glsl/glcpp/tests/041-if-0.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/042-if-1.c [new file with mode: 0644]
src/glsl/glcpp/tests/042-if-1.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/043-if-0-else.c [new file with mode: 0644]
src/glsl/glcpp/tests/043-if-0-else.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/044-if-1-else.c [new file with mode: 0644]
src/glsl/glcpp/tests/044-if-1-else.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/045-if-0-elif.c [new file with mode: 0644]
src/glsl/glcpp/tests/045-if-0-elif.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/046-if-1-elsif.c [new file with mode: 0644]
src/glsl/glcpp/tests/046-if-1-elsif.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/047-if-elif-else.c [new file with mode: 0644]
src/glsl/glcpp/tests/047-if-elif-else.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/048-if-nested.c [new file with mode: 0644]
src/glsl/glcpp/tests/048-if-nested.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/049-if-expression-precedence.c [new file with mode: 0644]
src/glsl/glcpp/tests/049-if-expression-precedence.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/050-if-defined.c [new file with mode: 0644]
src/glsl/glcpp/tests/050-if-defined.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/051-if-relational.c [new file with mode: 0644]
src/glsl/glcpp/tests/051-if-relational.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/052-if-bitwise.c [new file with mode: 0644]
src/glsl/glcpp/tests/052-if-bitwise.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/053-if-divide-and-shift.c [new file with mode: 0644]
src/glsl/glcpp/tests/053-if-divide-and-shift.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/054-if-with-macros.c [new file with mode: 0644]
src/glsl/glcpp/tests/054-if-with-macros.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c [new file with mode: 0644]
src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/056-macro-argument-with-comma.c [new file with mode: 0644]
src/glsl/glcpp/tests/056-macro-argument-with-comma.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/057-empty-arguments.c [new file with mode: 0644]
src/glsl/glcpp/tests/057-empty-arguments.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c [new file with mode: 0644]
src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/059-token-pasting-integer.c [new file with mode: 0644]
src/glsl/glcpp/tests/059-token-pasting-integer.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c [new file with mode: 0644]
src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c [new file with mode: 0644]
src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/062-if-0-skips-garbage.c [new file with mode: 0644]
src/glsl/glcpp/tests/062-if-0-skips-garbage.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/063-comments.c [new file with mode: 0644]
src/glsl/glcpp/tests/063-comments.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/064-version.c [new file with mode: 0644]
src/glsl/glcpp/tests/064-version.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/065-if-defined-parens.c [new file with mode: 0644]
src/glsl/glcpp/tests/065-if-defined-parens.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/066-if-nospace-expression.c [new file with mode: 0644]
src/glsl/glcpp/tests/066-if-nospace-expression.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c [new file with mode: 0644]
src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/068-accidental-pasting.c [new file with mode: 0644]
src/glsl/glcpp/tests/068-accidental-pasting.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/069-repeated-argument.c [new file with mode: 0644]
src/glsl/glcpp/tests/069-repeated-argument.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/070-undefined-macro-in-expression.c [new file with mode: 0644]
src/glsl/glcpp/tests/070-undefined-macro-in-expression.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/071-punctuator.c [new file with mode: 0644]
src/glsl/glcpp/tests/071-punctuator.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/072-token-pasting-same-line.c [new file with mode: 0644]
src/glsl/glcpp/tests/072-token-pasting-same-line.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/073-if-in-ifdef.c [new file with mode: 0644]
src/glsl/glcpp/tests/073-if-in-ifdef.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/074-elif-undef.c [new file with mode: 0644]
src/glsl/glcpp/tests/074-elif-undef.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/075-elif-elif-undef.c [new file with mode: 0644]
src/glsl/glcpp/tests/075-elif-elif-undef.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/076-elif-undef-nested.c [new file with mode: 0644]
src/glsl/glcpp/tests/076-elif-undef-nested.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/077-else-without-if.c [new file with mode: 0644]
src/glsl/glcpp/tests/077-else-without-if.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/078-elif-without-if.c [new file with mode: 0644]
src/glsl/glcpp/tests/078-elif-without-if.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/079-endif-without-if.c [new file with mode: 0644]
src/glsl/glcpp/tests/079-endif-without-if.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/080-if-without-expression.c [new file with mode: 0644]
src/glsl/glcpp/tests/080-if-without-expression.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/081-elif-without-expression.c [new file with mode: 0644]
src/glsl/glcpp/tests/081-elif-without-expression.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/082-invalid-paste.c [new file with mode: 0644]
src/glsl/glcpp/tests/082-invalid-paste.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/083-unterminated-if.c [new file with mode: 0644]
src/glsl/glcpp/tests/083-unterminated-if.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/084-unbalanced-parentheses.c [new file with mode: 0644]
src/glsl/glcpp/tests/085-incorrect-argument-count.c [new file with mode: 0644]
src/glsl/glcpp/tests/085-incorrect-argument-count.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/086-reserved-macro-names.c [new file with mode: 0644]
src/glsl/glcpp/tests/086-reserved-macro-names.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/087-if-comments.c [new file with mode: 0644]
src/glsl/glcpp/tests/087-if-comments.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/088-redefine-macro-legitimate.c [new file with mode: 0644]
src/glsl/glcpp/tests/088-redefine-macro-legitimate.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/089-redefine-macro-error.c [new file with mode: 0644]
src/glsl/glcpp/tests/089-redefine-macro-error.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/090-hash-error.c [new file with mode: 0644]
src/glsl/glcpp/tests/090-hash-error.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/091-hash-line.c [new file with mode: 0644]
src/glsl/glcpp/tests/091-hash-line.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/099-c99-example.c [new file with mode: 0644]
src/glsl/glcpp/tests/099-c99-example.c.expected [new file with mode: 0644]
src/glsl/glcpp/tests/glcpp-test [new file with mode: 0755]
src/glsl/glsl_lexer.cpp [new file with mode: 0644]
src/glsl/glsl_lexer.lpp [new file with mode: 0644]
src/glsl/glsl_parser.cpp [new file with mode: 0644]
src/glsl/glsl_parser.h [new file with mode: 0644]
src/glsl/glsl_parser.ypp [new file with mode: 0644]
src/glsl/glsl_parser_extras.cpp [new file with mode: 0644]
src/glsl/glsl_parser_extras.h [new file with mode: 0644]
src/glsl/glsl_symbol_table.cpp [new file with mode: 0644]
src/glsl/glsl_symbol_table.h [new file with mode: 0644]
src/glsl/glsl_types.cpp [new file with mode: 0644]
src/glsl/glsl_types.h [new file with mode: 0644]
src/glsl/hir_field_selection.cpp [new file with mode: 0644]
src/glsl/ir.cpp [new file with mode: 0644]
src/glsl/ir.h [new file with mode: 0644]
src/glsl/ir_algebraic.cpp [new file with mode: 0644]
src/glsl/ir_basic_block.cpp [new file with mode: 0644]
src/glsl/ir_basic_block.h [new file with mode: 0644]
src/glsl/ir_clone.cpp [new file with mode: 0644]
src/glsl/ir_constant_expression.cpp [new file with mode: 0644]
src/glsl/ir_constant_folding.cpp [new file with mode: 0644]
src/glsl/ir_constant_propagation.cpp [new file with mode: 0644]
src/glsl/ir_constant_variable.cpp [new file with mode: 0644]
src/glsl/ir_copy_propagation.cpp [new file with mode: 0644]
src/glsl/ir_dead_code.cpp [new file with mode: 0644]
src/glsl/ir_dead_code_local.cpp [new file with mode: 0644]
src/glsl/ir_dead_functions.cpp [new file with mode: 0644]
src/glsl/ir_div_to_mul_rcp.cpp [new file with mode: 0644]
src/glsl/ir_explog_to_explog2.cpp [new file with mode: 0644]
src/glsl/ir_expression_flattening.cpp [new file with mode: 0644]
src/glsl/ir_expression_flattening.h [new file with mode: 0644]
src/glsl/ir_function.cpp [new file with mode: 0644]
src/glsl/ir_function_can_inline.cpp [new file with mode: 0644]
src/glsl/ir_function_inlining.cpp [new file with mode: 0644]
src/glsl/ir_function_inlining.h [new file with mode: 0644]
src/glsl/ir_hierarchical_visitor.cpp [new file with mode: 0644]
src/glsl/ir_hierarchical_visitor.h [new file with mode: 0644]
src/glsl/ir_hv_accept.cpp [new file with mode: 0644]
src/glsl/ir_if_return.cpp [new file with mode: 0644]
src/glsl/ir_if_simplification.cpp [new file with mode: 0644]
src/glsl/ir_if_to_cond_assign.cpp [new file with mode: 0644]
src/glsl/ir_import_prototypes.cpp [new file with mode: 0644]
src/glsl/ir_mat_op_to_vec.cpp [new file with mode: 0644]
src/glsl/ir_mod_to_fract.cpp [new file with mode: 0644]
src/glsl/ir_noop_swizzle.cpp [new file with mode: 0644]
src/glsl/ir_optimization.h [new file with mode: 0644]
src/glsl/ir_print_visitor.cpp [new file with mode: 0644]
src/glsl/ir_print_visitor.h [new file with mode: 0644]
src/glsl/ir_reader.cpp [new file with mode: 0644]
src/glsl/ir_reader.h [new file with mode: 0644]
src/glsl/ir_rvalue_visitor.cpp [new file with mode: 0644]
src/glsl/ir_rvalue_visitor.h [new file with mode: 0644]
src/glsl/ir_set_program_inouts.cpp [new file with mode: 0644]
src/glsl/ir_structure_splitting.cpp [new file with mode: 0644]
src/glsl/ir_sub_to_add_neg.cpp [new file with mode: 0644]
src/glsl/ir_swizzle_swizzle.cpp [new file with mode: 0644]
src/glsl/ir_tree_grafting.cpp [new file with mode: 0644]
src/glsl/ir_validate.cpp [new file with mode: 0644]
src/glsl/ir_variable.cpp [new file with mode: 0644]
src/glsl/ir_variable_refcount.cpp [new file with mode: 0644]
src/glsl/ir_variable_refcount.h [new file with mode: 0644]
src/glsl/ir_vec_index_to_cond_assign.cpp [new file with mode: 0644]
src/glsl/ir_vec_index_to_swizzle.cpp [new file with mode: 0644]
src/glsl/ir_visitor.h [new file with mode: 0644]
src/glsl/link_functions.cpp [new file with mode: 0644]
src/glsl/linker.cpp [new file with mode: 0644]
src/glsl/linker.h [new file with mode: 0644]
src/glsl/list.h [new file with mode: 0644]
src/glsl/main.cpp [new file with mode: 0644]
src/glsl/pp/Makefile [deleted file]
src/glsl/pp/sl_pp_context.c [deleted file]
src/glsl/pp/sl_pp_context.h [deleted file]
src/glsl/pp/sl_pp_define.c [deleted file]
src/glsl/pp/sl_pp_dict.c [deleted file]
src/glsl/pp/sl_pp_dict.h [deleted file]
src/glsl/pp/sl_pp_error.c [deleted file]
src/glsl/pp/sl_pp_expression.c [deleted file]
src/glsl/pp/sl_pp_expression.h [deleted file]
src/glsl/pp/sl_pp_extension.c [deleted file]
src/glsl/pp/sl_pp_if.c [deleted file]
src/glsl/pp/sl_pp_line.c [deleted file]
src/glsl/pp/sl_pp_macro.c [deleted file]
src/glsl/pp/sl_pp_macro.h [deleted file]
src/glsl/pp/sl_pp_pragma.c [deleted file]
src/glsl/pp/sl_pp_process.c [deleted file]
src/glsl/pp/sl_pp_process.h [deleted file]
src/glsl/pp/sl_pp_public.h [deleted file]
src/glsl/pp/sl_pp_purify.c [deleted file]
src/glsl/pp/sl_pp_purify.h [deleted file]
src/glsl/pp/sl_pp_token.c [deleted file]
src/glsl/pp/sl_pp_token.h [deleted file]
src/glsl/pp/sl_pp_token_util.c [deleted file]
src/glsl/pp/sl_pp_token_util.h [deleted file]
src/glsl/pp/sl_pp_version.c [deleted file]
src/glsl/program.h [new file with mode: 0644]
src/glsl/s_expression.cpp [new file with mode: 0644]
src/glsl/s_expression.h [new file with mode: 0644]
src/glsl/tests/array-01.glsl [new file with mode: 0644]
src/glsl/tests/array-02.glsl [new file with mode: 0644]
src/glsl/tests/array-03.glsl [new file with mode: 0644]
src/glsl/tests/array-04.glsl [new file with mode: 0644]
src/glsl/tests/array-05.glsl [new file with mode: 0644]
src/glsl/tests/array-06.glsl [new file with mode: 0644]
src/glsl/tests/array-07.glsl [new file with mode: 0644]
src/glsl/tests/array-08.glsl [new file with mode: 0644]
src/glsl/tests/array-09.glsl [new file with mode: 0644]
src/glsl/tests/array-10.glsl [new file with mode: 0644]
src/glsl/tests/array-11.glsl [new file with mode: 0644]
src/glsl/tests/array-12.glsl [new file with mode: 0644]
src/glsl/tests/array-13.glsl [new file with mode: 0644]
src/glsl/tests/attribute-01.glsl [new file with mode: 0644]
src/glsl/tests/attribute-02.glsl [new file with mode: 0644]
src/glsl/tests/attribute-03.glsl [new file with mode: 0644]
src/glsl/tests/attribute-04.glsl [new file with mode: 0644]
src/glsl/tests/attribute-05.glsl [new file with mode: 0644]
src/glsl/tests/attribute-06.glsl [new file with mode: 0644]
src/glsl/tests/attribute-07.glsl [new file with mode: 0644]
src/glsl/tests/attribute-08.glsl [new file with mode: 0644]
src/glsl/tests/attribute-09.glsl [new file with mode: 0644]
src/glsl/tests/attribute-10.glsl [new file with mode: 0644]
src/glsl/tests/attribute-11.glsl [new file with mode: 0644]
src/glsl/tests/condition-01.glsl [new file with mode: 0644]
src/glsl/tests/condition-02.glsl [new file with mode: 0644]
src/glsl/tests/condition-03.glsl [new file with mode: 0644]
src/glsl/tests/condition-04.glsl [new file with mode: 0644]
src/glsl/tests/condition-05.glsl [new file with mode: 0644]
src/glsl/tests/constructor-01.glsl [new file with mode: 0644]
src/glsl/tests/constructor-02.glsl [new file with mode: 0644]
src/glsl/tests/constructor-03.glsl [new file with mode: 0644]
src/glsl/tests/constructor-04.glsl [new file with mode: 0644]
src/glsl/tests/constructor-05.glsl [new file with mode: 0644]
src/glsl/tests/constructor-06.glsl [new file with mode: 0644]
src/glsl/tests/constructor-07.glsl [new file with mode: 0644]
src/glsl/tests/constructor-08.glsl [new file with mode: 0644]
src/glsl/tests/constructor-09.glsl [new file with mode: 0644]
src/glsl/tests/function-01.glsl [new file with mode: 0644]
src/glsl/tests/function-02.glsl [new file with mode: 0644]
src/glsl/tests/function-03.glsl [new file with mode: 0644]
src/glsl/tests/function-04.glsl [new file with mode: 0644]
src/glsl/tests/function-05.glsl [new file with mode: 0644]
src/glsl/tests/if-01.glsl [new file with mode: 0644]
src/glsl/tests/if-02.glsl [new file with mode: 0644]
src/glsl/tests/if-03.glsl [new file with mode: 0644]
src/glsl/tests/if-04.glsl [new file with mode: 0644]
src/glsl/tests/matrix-01.glsl [new file with mode: 0644]
src/glsl/tests/matrix-02.glsl [new file with mode: 0644]
src/glsl/tests/matrix-03.glsl [new file with mode: 0644]
src/glsl/tests/matrix-04.glsl [new file with mode: 0644]
src/glsl/tests/matrix-05.glsl [new file with mode: 0644]
src/glsl/tests/matrix-06.glsl [new file with mode: 0644]
src/glsl/tests/matrix-07.glsl [new file with mode: 0644]
src/glsl/tests/matrix-08.glsl [new file with mode: 0644]
src/glsl/tests/matrix-09.glsl [new file with mode: 0644]
src/glsl/tests/matrix-10.glsl [new file with mode: 0644]
src/glsl/tests/parameters-01.glsl [new file with mode: 0644]
src/glsl/tests/parameters-02.glsl [new file with mode: 0644]
src/glsl/tests/parameters-03.glsl [new file with mode: 0644]
src/glsl/tests/qualifier-01.glsl [new file with mode: 0644]
src/glsl/tests/qualifier-02.glsl [new file with mode: 0644]
src/glsl/tests/qualifier-03.glsl [new file with mode: 0644]
src/glsl/tests/qualifier-04.glsl [new file with mode: 0644]
src/glsl/tests/qualifier-05.glsl [new file with mode: 0644]
src/glsl/tests/qualifier-06.glsl [new file with mode: 0644]
src/glsl/tests/qualifier-07.glsl [new file with mode: 0644]
src/glsl/tests/swiz-01.glsl [new file with mode: 0644]
src/glsl/tests/swiz-02.glsl [new file with mode: 0644]
src/glsl/tests/void-01.glsl [new file with mode: 0644]
src/glut/glx/glut_init.c
src/glx/Makefile
src/mapi/glapi/gen/glX_proto_send.py
src/mapi/glapi/glapi.h
src/mapi/glapi/glapi_dispatch.c
src/mapi/glapi/glapi_entrypoint.c
src/mapi/glapi/glapi_getproc.c
src/mapi/glapi/glapi_nop.c
src/mapi/glapi/glapi_priv.h
src/mapi/glapi/glthread.c
src/mapi/glapi/glthread.h
src/mapi/mapi/entry_x86-64_tls.h
src/mapi/mapi/entry_x86_tls.h
src/mapi/mapi/entry_x86_tsd.h
src/mapi/mapi/mapi.h
src/mapi/mapi/u_current.c
src/mapi/mapi/u_current.h
src/mapi/vgapi/SConscript
src/mesa/Makefile
src/mesa/SConscript
src/mesa/drivers/dri/Makefile.template
src/mesa/drivers/dri/common/dri_util.c
src/mesa/drivers/dri/common/dri_util.h
src/mesa/drivers/dri/i915/i830_context.c
src/mesa/drivers/dri/i915/i915_context.c
src/mesa/drivers/dri/i915/i915_fragprog.c
src/mesa/drivers/dri/i965/Makefile
src/mesa/drivers/dri/i965/brw_context.c
src/mesa/drivers/dri/i965/brw_context.h
src/mesa/drivers/dri/i965/brw_defines.h
src/mesa/drivers/dri/i965/brw_disasm.c
src/mesa/drivers/dri/i965/brw_draw_upload.c
src/mesa/drivers/dri/i965/brw_eu.c
src/mesa/drivers/dri/i965/brw_eu.h
src/mesa/drivers/dri/i965/brw_eu_emit.c
src/mesa/drivers/dri/i965/brw_fs.cpp [new file with mode: 0644]
src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp [new file with mode: 0644]
src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp [new file with mode: 0644]
src/mesa/drivers/dri/i965/brw_misc_state.c
src/mesa/drivers/dri/i965/brw_optimize.c
src/mesa/drivers/dri/i965/brw_program.c
src/mesa/drivers/dri/i965/brw_state.h
src/mesa/drivers/dri/i965/brw_state_upload.c
src/mesa/drivers/dri/i965/brw_structs.h
src/mesa/drivers/dri/i965/brw_vs.c
src/mesa/drivers/dri/i965/brw_vs_emit.c
src/mesa/drivers/dri/i965/brw_vtbl.c
src/mesa/drivers/dri/i965/brw_wm.c
src/mesa/drivers/dri/i965/brw_wm.h
src/mesa/drivers/dri/i965/brw_wm_debug.c
src/mesa/drivers/dri/i965/brw_wm_emit.c
src/mesa/drivers/dri/i965/brw_wm_fp.c
src/mesa/drivers/dri/i965/brw_wm_glsl.c
src/mesa/drivers/dri/i965/brw_wm_iz.c
src/mesa/drivers/dri/i965/brw_wm_pass0.c
src/mesa/drivers/dri/i965/brw_wm_pass1.c
src/mesa/drivers/dri/i965/brw_wm_pass2.c
src/mesa/drivers/dri/i965/brw_wm_state.c
src/mesa/drivers/dri/i965/gen6_cc.c
src/mesa/drivers/dri/i965/gen6_wm_state.c
src/mesa/drivers/dri/intel/intel_buffer_objects.c
src/mesa/drivers/dri/intel/intel_chipset.h
src/mesa/drivers/dri/intel/intel_context.c
src/mesa/drivers/dri/intel/intel_context.h
src/mesa/drivers/dri/intel/intel_extensions.c
src/mesa/drivers/dri/intel/intel_fbo.c
src/mesa/drivers/dri/intel/intel_mipmap_tree.c
src/mesa/drivers/dri/intel/intel_regions.c
src/mesa/drivers/dri/intel/intel_regions.h
src/mesa/drivers/dri/intel/intel_screen.c
src/mesa/drivers/dri/intel/intel_tex.h
src/mesa/drivers/dri/nouveau/nouveau_driver.c
src/mesa/drivers/dri/nouveau/nouveau_fbo.c
src/mesa/drivers/dri/r300/compiler/Makefile
src/mesa/drivers/dri/r300/compiler/SConscript
src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
src/mesa/drivers/dri/r300/compiler/radeon_code.h
src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c
src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c
src/mesa/drivers/dri/r300/compiler/radeon_opcodes.h
src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c
src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c
src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c
src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.c [new file with mode: 0644]
src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.h [new file with mode: 0644]
src/mesa/drivers/dri/r300/r300_fragprog_common.c
src/mesa/drivers/dri/r600/Makefile
src/mesa/drivers/dri/r600/evergreen_chip.c [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_chip.h [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_context.c [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_context.h [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_diff.h [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_fragprog.c [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_fragprog.h [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_ioctl.c [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_ioctl.h [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_off.h [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_oglprog.c [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_oglprog.h [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_render.c [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_sq.h [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_state.c [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_state.h [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_tex.c [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_tex.h [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_vertprog.c [new file with mode: 0644]
src/mesa/drivers/dri/r600/evergreen_vertprog.h [new file with mode: 0644]
src/mesa/drivers/dri/r600/r600_blit.c
src/mesa/drivers/dri/r600/r600_cmdbuf.c
src/mesa/drivers/dri/r600/r600_cmdbuf.h
src/mesa/drivers/dri/r600/r600_context.c
src/mesa/drivers/dri/r600/r600_context.h
src/mesa/drivers/dri/r600/r600_emit.c
src/mesa/drivers/dri/r600/r600_emit.h
src/mesa/drivers/dri/r600/r600_texstate.c
src/mesa/drivers/dri/r600/r700_assembler.c
src/mesa/drivers/dri/r600/r700_assembler.h
src/mesa/drivers/dri/r600/r700_chip.c
src/mesa/drivers/dri/r600/r700_chip.h
src/mesa/drivers/dri/r600/r700_fragprog.c
src/mesa/drivers/dri/r600/r700_fragprog.h
src/mesa/drivers/dri/r600/r700_oglprog.c
src/mesa/drivers/dri/r600/r700_render.c
src/mesa/drivers/dri/r600/r700_state.c
src/mesa/drivers/dri/r600/r700_vertprog.c
src/mesa/drivers/dri/r600/r700_vertprog.h
src/mesa/drivers/dri/radeon/radeon_chipset.h
src/mesa/drivers/dri/radeon/radeon_common_context.c
src/mesa/drivers/dri/radeon/radeon_common_context.h
src/mesa/drivers/dri/radeon/radeon_fbo.c
src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
src/mesa/drivers/dri/radeon/radeon_screen.c
src/mesa/drivers/glslcompiler/Makefile [deleted file]
src/mesa/drivers/glslcompiler/glslcompiler.c [deleted file]
src/mesa/drivers/osmesa/Makefile
src/mesa/drivers/x11/Makefile
src/mesa/main/accum.h
src/mesa/main/attrib.h
src/mesa/main/bufferobj.c
src/mesa/main/colortab.h
src/mesa/main/compiler.h
src/mesa/main/context.c
src/mesa/main/convolve.h
src/mesa/main/core.h [new file with mode: 0644]
src/mesa/main/dd.h
src/mesa/main/depthstencil.c
src/mesa/main/dlist.c
src/mesa/main/dlist.h
src/mesa/main/es_generator.py
src/mesa/main/extensions.c
src/mesa/main/fbobject.c
src/mesa/main/feedback.h
src/mesa/main/formats.c
src/mesa/main/formats.h
src/mesa/main/framebuffer.c
src/mesa/main/get.c
src/mesa/main/getstring.c
src/mesa/main/imports.h
src/mesa/main/mipmap.c
src/mesa/main/mtypes.h
src/mesa/main/querymatrix.c
src/mesa/main/shaderapi.c
src/mesa/main/shaderobj.c
src/mesa/main/shaderobj.h
src/mesa/main/shared.c
src/mesa/main/texcompress_s3tc.c
src/mesa/main/transformfeedback.c
src/mesa/main/uniforms.c
src/mesa/main/uniforms.h
src/mesa/program/hash_table.c
src/mesa/program/hash_table.h
src/mesa/program/ir_to_mesa.cpp [new file with mode: 0644]
src/mesa/program/ir_to_mesa.h [new file with mode: 0644]
src/mesa/program/prog_execute.c
src/mesa/program/prog_instruction.h
src/mesa/program/prog_optimize.c
src/mesa/program/prog_parameter.c
src/mesa/program/prog_parameter.h
src/mesa/program/prog_print.c
src/mesa/program/prog_print.h
src/mesa/program/prog_uniform.c
src/mesa/program/prog_uniform.h
src/mesa/program/symbol_table.c
src/mesa/program/symbol_table.h
src/mesa/slang/descrip.mms [deleted file]
src/mesa/slang/library/.gitignore [deleted file]
src/mesa/slang/library/Makefile [deleted file]
src/mesa/slang/library/SConscript [deleted file]
src/mesa/slang/library/slang_120_core.gc [deleted file]
src/mesa/slang/library/slang_builtin_120_common.gc [deleted file]
src/mesa/slang/library/slang_builtin_120_fragment.gc [deleted file]
src/mesa/slang/library/slang_common_builtin.gc [deleted file]
src/mesa/slang/library/slang_core.gc [deleted file]
src/mesa/slang/library/slang_fragment_builtin.gc [deleted file]
src/mesa/slang/library/slang_geometry_builtin.gc [deleted file]
src/mesa/slang/library/slang_vertex_builtin.gc [deleted file]
src/mesa/slang/slang_builtin.c [deleted file]
src/mesa/slang/slang_builtin.h [deleted file]
src/mesa/slang/slang_codegen.c [deleted file]
src/mesa/slang/slang_codegen.h [deleted file]
src/mesa/slang/slang_compile.c [deleted file]
src/mesa/slang/slang_compile.h [deleted file]
src/mesa/slang/slang_compile_function.c [deleted file]
src/mesa/slang/slang_compile_function.h [deleted file]
src/mesa/slang/slang_compile_operation.c [deleted file]
src/mesa/slang/slang_compile_operation.h [deleted file]
src/mesa/slang/slang_compile_struct.c [deleted file]
src/mesa/slang/slang_compile_struct.h [deleted file]
src/mesa/slang/slang_compile_variable.c [deleted file]
src/mesa/slang/slang_compile_variable.h [deleted file]
src/mesa/slang/slang_emit.c [deleted file]
src/mesa/slang/slang_emit.h [deleted file]
src/mesa/slang/slang_ir.c [deleted file]
src/mesa/slang/slang_ir.h [deleted file]
src/mesa/slang/slang_label.c [deleted file]
src/mesa/slang/slang_label.h [deleted file]
src/mesa/slang/slang_link.c [deleted file]
src/mesa/slang/slang_link.h [deleted file]
src/mesa/slang/slang_log.c [deleted file]
src/mesa/slang/slang_log.h [deleted file]
src/mesa/slang/slang_mem.c [deleted file]
src/mesa/slang/slang_mem.h [deleted file]
src/mesa/slang/slang_print.c [deleted file]
src/mesa/slang/slang_print.h [deleted file]
src/mesa/slang/slang_simplify.c [deleted file]
src/mesa/slang/slang_simplify.h [deleted file]
src/mesa/slang/slang_storage.c [deleted file]
src/mesa/slang/slang_storage.h [deleted file]
src/mesa/slang/slang_typeinfo.c [deleted file]
src/mesa/slang/slang_typeinfo.h [deleted file]
src/mesa/slang/slang_utility.c [deleted file]
src/mesa/slang/slang_utility.h [deleted file]
src/mesa/slang/slang_vartable.c [deleted file]
src/mesa/slang/slang_vartable.h [deleted file]
src/mesa/sources.mak
src/mesa/state_tracker/st_cb_accum.h
src/mesa/state_tracker/st_cb_bitmap.c
src/mesa/state_tracker/st_cb_blit.c
src/mesa/state_tracker/st_cb_drawpixels.c
src/mesa/state_tracker/st_cb_eglimage.c
src/mesa/state_tracker/st_cb_fbo.c
src/mesa/state_tracker/st_cb_fbo.h
src/mesa/state_tracker/st_cb_readpixels.c
src/mesa/state_tracker/st_cb_texture.c
src/mesa/state_tracker/st_context.c
src/mesa/state_tracker/st_context.h
src/mesa/state_tracker/st_draw.c
src/mesa/state_tracker/st_draw_feedback.c
src/mesa/state_tracker/st_extensions.c
src/mesa/state_tracker/st_format.c
src/mesa/state_tracker/st_manager.c
src/mesa/state_tracker/st_mesa_to_tgsi.c
src/mesa/state_tracker/st_program.c
src/mesa/state_tracker/st_texture.c
src/mesa/swrast/s_context.c
src/mesa/vbo/vbo_exec_array.c
src/mesa/x86/3dnow.h
src/mesa/x86/common_x86.c
src/mesa/x86/mmx.h
src/mesa/x86/sse.h
src/mesa/x86/x86_xform.c
src/talloc/SConscript [new file with mode: 0644]
src/talloc/gpl-3.0.txt [new file with mode: 0644]
src/talloc/lgpl-3.0.txt [new file with mode: 0644]
src/talloc/talloc.c [new file with mode: 0644]
src/talloc/talloc.def [new file with mode: 0644]
src/talloc/talloc.h [new file with mode: 0644]
src/talloc/talloc_guide.txt [new file with mode: 0644]

index ca465047158f874fc094f31728cd76641a05ce9d..2c146272fbcd4a1da9eced5c4df2ca0234bdc21c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -187,8 +187,6 @@ GLUT_NAME = MesaGLUT-$(VERSION)
 
 # This is part of MAIN_FILES
 MAIN_ES_FILES = \
-       $(DIRECTORY)/src/mesa/es/Makefile                               \
-       $(DIRECTORY)/src/mesa/es/sources.mak                            \
        $(DIRECTORY)/src/mesa/main/*.xml                                \
        $(DIRECTORY)/src/mesa/main/*.py                                 \
        $(DIRECTORY)/src/mesa/main/*.dtd
@@ -229,8 +227,10 @@ MAIN_FILES = \
        $(DIRECTORY)/src/glsl/Makefile                                  \
        $(DIRECTORY)/src/glsl/Makefile.template                         \
        $(DIRECTORY)/src/glsl/SConscript                                \
-       $(DIRECTORY)/src/glsl/*/Makefile                                \
-       $(DIRECTORY)/src/glsl/*/*.[ch]                                  \
+       $(DIRECTORY)/src/glsl/*.[ch]                                    \
+       $(DIRECTORY)/src/glsl/*.[cly]pp                                 \
+       $(DIRECTORY)/src/glsl/README                                    \
+       $(DIRECTORY)/src/glsl/glcpp/README                              \
        $(DIRECTORY)/src/Makefile                                       \
        $(DIRECTORY)/src/mesa/Makefile*                                 \
        $(DIRECTORY)/src/mesa/sources.mak                               \
@@ -246,10 +246,6 @@ MAIN_FILES = \
        $(DIRECTORY)/src/mesa/program/*.[chly]                          \
        $(DIRECTORY)/src/mesa/program/Makefile                          \
        $(DIRECTORY)/src/mesa/program/descrip.mms                       \
-       $(DIRECTORY)/src/mesa/slang/*.[ch]                              \
-       $(DIRECTORY)/src/mesa/slang/descrip.mms                         \
-       $(DIRECTORY)/src/mesa/slang/library/*.gc                        \
-       $(DIRECTORY)/src/mesa/slang/library/Makefile                    \
        $(DIRECTORY)/src/mesa/swrast/*.[ch]                             \
        $(DIRECTORY)/src/mesa/swrast/descrip.mms                        \
        $(DIRECTORY)/src/mesa/swrast_setup/*.[ch]                       \
@@ -278,8 +274,6 @@ MAIN_FILES = \
        $(DIRECTORY)/src/mesa/drivers/x11/Makefile                      \
        $(DIRECTORY)/src/mesa/drivers/x11/descrip.mms                   \
        $(DIRECTORY)/src/mesa/drivers/x11/*.[ch]                        \
-       $(DIRECTORY)/src/mesa/drivers/glslcompiler/Makefile             \
-       $(DIRECTORY)/src/mesa/drivers/glslcompiler/glslcompiler.c       \
        $(DIRECTORY)/src/mesa/ppc/*.[ch]                                \
        $(DIRECTORY)/src/mesa/sparc/*.[chS]                             \
        $(DIRECTORY)/src/mesa/x86/Makefile                              \
@@ -331,7 +325,6 @@ GALLIUM_FILES = \
        $(DIRECTORY)/src/gallium/Makefile.template                      \
        $(DIRECTORY)/src/gallium/SConscript                             \
        $(DIRECTORY)/src/gallium/targets/Makefile.dri                   \
-       $(DIRECTORY)/src/gallium/targets/Makefile.egl                   \
        $(DIRECTORY)/src/gallium/*/Makefile                             \
        $(DIRECTORY)/src/gallium/*/SConscript                           \
        $(DIRECTORY)/src/gallium/*/*/Makefile                           \
index a187d8d1b6faba6e4cf77bb0a3f87880c1e73714..bb03e5055eadf1d73407c8d539cf78aaa2f08fc3 100644 (file)
@@ -206,28 +206,6 @@ Export('env')
 # TODO: Build several variants at the same time?
 # http://www.scons.org/wiki/SimultaneousVariantBuilds
 
-if env['platform'] != common.default_platform:
-    # GLSL code has to be built twice -- one for the host OS, another for the target OS...
-
-    host_env = Environment(
-        # options are ignored
-        # default tool is used
-        tools = ['default', 'custom'],
-        toolpath = ['#scons'], 
-        ENV = os.environ,
-    )
-
-    host_env['platform'] = common.default_platform
-    host_env['machine'] = common.default_machine
-    host_env['debug'] = env['debug']
-
-    SConscript(
-        'src/glsl/SConscript',
-        variant_dir = os.path.join(env['build'], 'host'),
-        duplicate = 0, # http://www.scons.org/doc/0.97/HTML/scons-user/x2261.html
-        exports={'env':host_env},
-    )
-
 SConscript(
        'src/SConscript',
        variant_dir = env['build'],
index 130025829ba727210ab8eef55b15b8412eeb9879..094ec0c2b2af7f675db1f23e8efdffaf0e23de37 100755 (executable)
@@ -31,7 +31,7 @@ if [ $# -ge 2 ] ; then
 
        # Last cmd line arg is the dest dir
        for FILE in $@ ; do
-               DEST="$FILE"
+               DESTDIR="$FILE"
        done
 
        # Loop over args, moving them to DEST directory
@@ -42,6 +42,25 @@ if [ $# -ge 2 ] ; then
                        exit 0
                fi
 
+                DEST=$DESTDIR
+
+                # On CYGWIN, because DLLs are loaded by the native Win32 loader,
+                # they are installed in the executable path.  Stub libraries used
+                # only for linking are installed in the library path
+                case `uname` in
+                    CYGWIN*)
+                        case $FILE in
+                            *.dll)
+                                DEST="$DEST/../bin"
+                                ;;
+                            *)
+                                ;;
+                        esac
+                       ;;
+                    *)
+                        ;;
+                esac
+
                PWDSAVE=`pwd`
 
                # determine file's type
index c2760e5d892724b0c6a065695c1f3752605ab43f..2f9223ff3c1c94c6690baedc88e245b101acd03d 100755 (executable)
--- a/bin/mklib
+++ b/bin/mklib
@@ -930,6 +930,16 @@ case $ARCH in
 
      CYGWIN*)
        # GCC-based environment
+
+       if [ "x$LINK" = "x" ] ; then
+           # -linker was not specified so set default link command now
+            if [ $CPLUSPLUS = 1 ] ; then
+                LINK=g++
+            else
+                LINK=gcc
+            fi
+       fi
+
        if [ $NOPREFIX = 1 ] ; then
            # No "lib" or ".so" part
            echo "mklib: Making CYGWIN shared library: " ${LIBNAME}
@@ -938,7 +948,7 @@ case $ARCH in
                 OPTS=${ALTOPTS}
             fi
            rm -f ${LIBNAME}
-           ${LINK} ${OPTS} ${LDFLAGS} -o ${LIBNAME} ${OBJECTS} ${DEPS}
+           ${LINK} ${OPTS} ${LDFLAGS} -o ${LIBNAME} ${OBJECTS} ${DEPS} || exit $?
            FINAL_LIBS=${LIBNAME}
         else
        CYGNAME="cyg${LIBNAME}"     # prefix with "cyg"
@@ -946,7 +956,7 @@ case $ARCH in
 
         if [ $STATIC = 1 ] ; then
            LIBNAME=${LIBNAME}.a
-            echo "mklib: Making" $ARCH "static library: " ${LIBNAME}
+            echo "mklib: Making CYGWIN static library: " ${LIBNAME}
             OPTS="-ru"
             if [ "${ALTOPTS}" ] ; then
                 OPTS=${ALTOPTS}
@@ -964,13 +974,7 @@ case $ARCH in
             if [ "${ALTOPTS}" ] ; then
                 OPTS=${ALTOPTS}
             fi
-            echo "mklib: Making" $ARCH "shared library: " ${CYGNAME}-${MAJOR}.dll
-
-            if [ $CPLUSPLUS = 1 ] ; then
-                LINK="g++"
-            else
-                LINK="gcc"
-            fi
+            echo "mklib: Making CYGWIN shared library: " ${CYGNAME}-${MAJOR}.dll
 
             # rm any old libs
             rm -f ${CYGNAME}-${MAJOR}.dll
@@ -979,12 +983,7 @@ case $ARCH in
             rm -f ${LIBNAME}.a
 
             # make lib
-            ${LINK} ${OPTS} ${LDFLAGS} -o ${CYGNAME}-${MAJOR}.dll ${OBJECTS} ${DEPS}
-            # make build fail if link failed
-            es=$?
-            if [ "$es" -ne "0" ]; then
-                exit $es
-            fi
+            ${LINK} ${OPTS} ${LDFLAGS} -o ${CYGNAME}-${MAJOR}.dll ${OBJECTS} ${DEPS} || exit $?
             # make usual symlinks
             ln -s ${LIBNAME}-${MAJOR}.dll.a ${LIBNAME}.dll.a
             # finish up
@@ -1024,4 +1023,9 @@ if [ ${INSTALLDIR} != "." ] ; then
     echo "mklib: Installing" ${FINAL_LIBS} "in" ${INSTALLDIR}
     test -d ${INSTALLDIR} || mkdir -p ${INSTALLDIR}
     mv ${FINAL_LIBS} ${INSTALLDIR}/
+
+    if [ "x${FINAL_BINS}" != "x" ] ; then
+        echo "mklib: Installing" ${FINAL_BINS} "in" ${INSTALLDIR}
+        mv ${FINAL_BINS} ${INSTALLDIR}/
+    fi
 fi
index c7611a6f7812105a7fe5f3da43b1288aa2fef7c8..10d311fa4d3de6a080af2320500d25df96a04685 100644 (file)
@@ -34,6 +34,9 @@ LLVM_LIBS = @LLVM_LIBS@
 GLW_CFLAGS = @GLW_CFLAGS@
 GLUT_CFLAGS = @GLUT_CFLAGS@
 
+TALLOC_LIBS = @TALLOC_LIBS@
+TALLOC_CFLAGS = @TALLOC_CFLAGS@
+
 # dlopen
 DLOPEN_LIBS = @DLOPEN_LIBS@
 
index 8711a382cc0807f0b11745b6012e2ef4bec72bf8..7c9cdf18aee0d55f22e8fba9bb1a942eda97e0f6 100644 (file)
@@ -82,6 +82,9 @@ GLESv1_CM_LIB_GLOB = $(GLESv1_CM_LIB_NAME)*
 GLESv2_LIB_GLOB = $(GLESv2_LIB_NAME)*
 VG_LIB_GLOB = $(VG_LIB_NAME)*
 
+TALLOC_LIBS = `pkg-config --libs talloc`
+TALLOC_CFLAGS = `pkg-config --cflags talloc`
+
 # Optional assembly language optimization files for libGL
 MESA_ASM_SOURCES = 
 
@@ -116,7 +119,7 @@ EGL_CLIENT_APIS = $(GL_LIB)
 
 # Library dependencies
 #EXTRA_LIB_PATH ?=
-GL_LIB_DEPS     = $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread
+GL_LIB_DEPS     = $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread $(TALLOC_LIBS)
 EGL_LIB_DEPS    = $(EXTRA_LIB_PATH) -ldl -lpthread
 OSMESA_LIB_DEPS = $(EXTRA_LIB_PATH) -L$(TOP)/$(LIB_DIR) -l$(GL_LIB)
 GLU_LIB_DEPS    = $(EXTRA_LIB_PATH) -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) -lm
index de90f38cfe9192638333ac4e7c2d063b88eef26c..6f86277c4afa07afffce635f0f5e66df840501bc 100644 (file)
@@ -45,7 +45,7 @@ EXTRA_LIB_PATH=-L/usr/X11R6/lib
 
 LIBDRM_CFLAGS = $(shell pkg-config --cflags libdrm)
 LIBDRM_LIB = $(shell pkg-config --libs libdrm)
-DRI_LIB_DEPS  = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB)
+DRI_LIB_DEPS  = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl -ltalloc $(LIBDRM_LIB)
 GL_LIB_DEPS   = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \
                -lm -lpthread -ldl $(LIBDRM_LIB)
 
index 83d2fc371760751b6e7115974652e9ae5b097e56..6aa434032dc46368a9069d784bcf2ae1f3bdb222 100644 (file)
@@ -41,4 +41,4 @@ else
 endif
 
 LD = g++
-GL_LIB_DEPS = $(LLVM_LDFLAGS) $(LLVM_LIBS) $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread -lstdc++ -ludis86
+GL_LIB_DEPS = $(LLVM_LDFLAGS) $(LLVM_LIBS) $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread -ltalloc -lstdc++ -ludis86
index 9f3006230eb54ed213dabcfd12cd55233d02d5ca..d3d74ac265a7064567964f360853eaccca16eafa 100644 (file)
@@ -48,9 +48,23 @@ solaris*)
     ;;
 esac
 
+dnl clang is mostly GCC-compatible, but its version is much lower,
+dnl so we have to check for it.
+AC_MSG_CHECKING([if compiling with clang])
+
+AC_COMPILE_IFELSE(
+[AC_LANG_PROGRAM([], [[
+#ifndef __clang__
+       not clang
+#endif
+]])],
+[CLANG=yes], [CLANG=no])
+
+AC_MSG_RESULT([$CLANG])
+
 dnl If we're using GCC, make sure that it is at least version 3.3.0.  Older
 dnl versions are explictly not supported.
-if test "x$GCC" = xyes; then
+if test "x$GCC" = xyes -a "x$CLANG" = xno; then
     AC_MSG_CHECKING([whether gcc version is sufficient])
     major=0
     minor=0
@@ -123,7 +137,10 @@ esac
 
 dnl Add flags for gcc and g++
 if test "x$GCC" = xyes; then
-    CFLAGS="$CFLAGS -Wall -Wmissing-prototypes -std=c99 -ffast-math"
+    CFLAGS="$CFLAGS -Wall -Wmissing-prototypes -std=c99"
+    if test "x$CLANG" = "xno"; then
+       CFLAGS="$CFLAGS -ffast-math"
+    fi
 
     # Enable -fvisibility=hidden if using a gcc that supports it
     save_CFLAGS="$CFLAGS"
@@ -258,6 +275,8 @@ fi
 dnl
 dnl library names
 dnl
+LIB_PREFIX_GLOB='lib'
+LIB_VERSION_SEPARATOR='.'
 if test "$enable_static" = yes; then
     LIB_EXTENSION='a'
 else
@@ -265,7 +284,10 @@ else
     darwin* )
         LIB_EXTENSION='dylib' ;;
     cygwin* )
-        LIB_EXTENSION='dll.a' ;;
+        dnl prefix can be 'cyg' or 'lib'
+        LIB_PREFIX_GLOB='???'
+        LIB_VERSION_SEPARATOR='-'
+        LIB_EXTENSION='dll' ;;
     aix* )
         LIB_EXTENSION='a' ;;
     * )
@@ -283,15 +305,16 @@ GLESv1_CM_LIB_NAME='lib$(GLESv1_CM_LIB).'${LIB_EXTENSION}
 GLESv2_LIB_NAME='lib$(GLESv2_LIB).'${LIB_EXTENSION}
 VG_LIB_NAME='lib$(VG_LIB).'${LIB_EXTENSION}
 
-GL_LIB_GLOB='lib$(GL_LIB).*'${LIB_EXTENSION}'*'
-GLU_LIB_GLOB='lib$(GLU_LIB).*'${LIB_EXTENSION}'*'
-GLUT_LIB_GLOB='lib$(GLUT_LIB).*'${LIB_EXTENSION}'*'
-GLW_LIB_GLOB='lib$(GLW_LIB).*'${LIB_EXTENSION}'*'
-OSMESA_LIB_GLOB='lib$(OSMESA_LIB).*'${LIB_EXTENSION}'*'
-EGL_LIB_GLOB='lib$(EGL_LIB).*'${LIB_EXTENSION}'*'
-GLESv1_CM_LIB_GLOB='lib$(GLESv1_CM_LIB).*'${LIB_EXTENSION}'*'
-GLESv2_LIB_GLOB='lib$(GLESv2_LIB).*'${LIB_EXTENSION}'*'
-VG_LIB_GLOB='lib$(VG_LIB).*'${LIB_EXTENSION}'*'
+GL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
+GLU_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLU_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
+GLUT_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLUT_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
+GLW_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLW_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
+OSMESA_LIB_GLOB=${LIB_PREFIX_GLOB}'$(OSMESA_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
+EGL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(EGL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
+EGL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(EGL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
+GLESv1_CM_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLESv1_CM_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
+GLESv2_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLESv2_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
+VG_LIB_GLOB=${LIB_PREFIX_GLOB}'$(VG_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
 
 AC_SUBST([GL_LIB_NAME])
 AC_SUBST([GLU_LIB_NAME])
@@ -463,6 +486,10 @@ xxlib|xdri|xosmesa)
     ;;
 esac
 
+PKG_CHECK_MODULES([TALLOC], [talloc])
+AC_SUBST([TALLOC_LIBS])
+AC_SUBST([TALLOC_CFLAGS])
+
 dnl
 dnl Driver specific build directories
 dnl
@@ -574,8 +601,8 @@ xlib)
         GL_PC_LIB_PRIV="$GL_LIB_DEPS"
         GL_PC_CFLAGS="$X11_INCLUDES"
     fi
-    GL_LIB_DEPS="$GL_LIB_DEPS $SELINUX_LIBS -lm -lpthread"
-    GL_PC_LIB_PRIV="$GL_PC_LIB_PRIV $SELINUX_LIBS -lm -lpthread"
+    GL_LIB_DEPS="$GL_LIB_DEPS $SELINUX_LIBS -lm -lpthread $TALLOC_LIBS"
+    GL_PC_LIB_PRIV="$GL_PC_LIB_PRIV $SELINUX_LIBS -lm -lpthread $TALLOC_LIBS"
 
     # if static, move the external libraries to the programs
     # and empty the libraries for libGL
@@ -853,7 +880,7 @@ if test "$mesa_driver" = dri; then
         [AC_MSG_ERROR([Expat required for DRI.])])
 
     # put all the necessary libs together
-    DRI_LIB_DEPS="$SELINUX_LIBS $LIBDRM_LIBS $EXPAT_LIB -lm -lpthread $DLOPEN_LIBS"
+    DRI_LIB_DEPS="$SELINUX_LIBS $LIBDRM_LIBS $EXPAT_LIB -lm -lpthread $DLOPEN_LIBS $TALLOC_LIBS"
 fi
 AC_SUBST([DRI_DIRS])
 AC_SUBST([EXPAT_INCLUDES])
@@ -931,12 +958,12 @@ case "$DRIVER_DIRS" in
 *osmesa*)
     # only link libraries with osmesa if shared
     if test "$enable_static" = no; then
-        OSMESA_LIB_DEPS="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS"
+        OSMESA_LIB_DEPS="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS $TALLOC_LIBS"
     else
         OSMESA_LIB_DEPS=""
     fi
     OSMESA_MESA_DEPS=""
-    OSMESA_PC_LIB_PRIV="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS"
+    OSMESA_PC_LIB_PRIV="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS $TALLOC_LIBS"
     ;;
 esac
 AC_SUBST([OSMESA_LIB_DEPS])
@@ -1484,7 +1511,7 @@ AC_ARG_ENABLE([gallium-radeon],
     [enable_gallium_radeon=auto])
 if test "x$enable_gallium_radeon" = xyes; then
     GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300"
-    gallium_check_st "radeon/drm" "dri-radeong" "xorg-radeon"
+    gallium_check_st "radeon/drm" "dri-r300" "xorg-radeon"
 elif test "x$enable_gallium_radeon" = xauto; then
     GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300"
 fi
diff --git a/docs/MESA_drm_image.spec b/docs/MESA_drm_image.spec
new file mode 100644 (file)
index 0000000..118501c
--- /dev/null
@@ -0,0 +1,149 @@
+Name
+
+    MESA_drm_image
+
+Name Strings
+
+    EGL_MESA_drm_image
+
+Contact
+
+    Kristian Høgsberg <krh@bitplanet.net>
+
+Status
+
+    Proposal
+
+Version
+
+    Version 2, August 25, 2010
+
+Number
+
+    EGL Extension #not assigned
+
+Dependencies
+
+    Reguires EGL 1.4 or later.  This extension is written against the
+    wording of the EGL 1.4 specification.
+
+    EGL_KHR_base_image is required.
+
+Overview
+
+    This extension provides entry points for integrating EGLImage with the
+    Linux DRM mode setting and memory management drivers.  The extension
+    lets applications create EGLImages without a client API resource and
+    lets the application get the DRM buffer handles.
+
+IP Status
+
+    Open-source; freely implementable.
+
+New Procedures and Functions
+
+    EGLImageKHR eglCreateDRMImageMESA(EGLDisplay dpy,
+                                      const EGLint *attrib_list);
+
+    EGLBoolean eglExportDRMImageMESA(EGLDisplay dpy,
+                                     EGLImageKHR image,
+                                     EGLint *name,
+                                    EGLint *handle,
+                                    EGLint *stride);
+
+New Tokens
+
+    Accepted in the <attrib_list> parameter of eglCreateDRMImageMESA:
+
+        EGL_DRM_BUFFER_FORMAT_MESA             0x31D0
+        EGL_DRM_BUFFER_USE_MESA                        0x31D1
+
+    Accepted as values for the EGL_IMAGE_FORMAT_MESA attribute:
+
+        EGL_DRM_BUFFER_FORMAT_ARGB32_MESA      0x31D2
+
+    Bits accepted in EGL_DRM_BUFFER_USE_MESA:
+
+        EGL_DRM_BUFFER_USE_SCANOUT_MESA                0x0001
+        EGL_DRM_BUFFER_USE_SHARE_MESA          0x0002
+
+    Accepted in the <target> parameter of eglCreateImageKHR:
+
+        EGL_DRM_BUFFER_MESA                    0x31D3
+
+    Use when importing drm buffer:
+
+        EGL_DRM_BUFFER_STRIDE_MESA             0x31D4
+        EGL_DRM_BUFFER_FORMAT_MESA             0x31D0
+
+Additions to the EGL 1.4 Specification:
+
+    To create a DRM EGLImage, call
+
+        EGLImageKHR eglCreateDRMImageMESA(EGLDisplay dpy,
+                                          const EGLint *attrib_list);
+
+    In the attribute list, pass EGL_WIDTH, EGL_EIGHT and format and
+    use in the attrib list using EGL_DRM_BUFFER_FORMAT_MESA and
+    EGL_DRM_BUFFER_USE_MESA.  The only format specified by this
+    extension is EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, where each pixel
+    is a CPU-endian, 32-bit quantity, with alpha in the upper 8 bits,
+    then red, then green, then blue.  The bit values accepted by
+    EGL_DRM_BUFFER_USE_MESA are EGL_DRM_BUFFER_USE_SCANOUT_MESA and
+    EGL_DRM_BUFFER_USE_SHARE_MESA.  EGL_DRM_BUFFER_USE_SCANOUT_MESA
+    requests that the created EGLImage should be usable as a scanout
+    buffer with the DRM kernel modesetting API.  The
+    EGL_DRM_BUFFER_USE_SHARE_MESA bit requests that the EGLImage can
+    be shared with other processes by passing the underlying DRM
+    buffer name.
+
+    To create a process local handle or a global DRM name for a
+    buffer, call
+
+        EGLBoolean eglExportDRMImageMESA(EGLDisplay dpy,
+                                         EGLImageKHR image,
+                                         EGLint *name,
+                                         EGLint *handle,
+                                         EGLint *stride);
+
+    If <name> is non-NULL, a global name is assigned to the image and
+    written to <name>, the handle (local to the DRM file descriptor,
+    for use with DRM kernel modesetting API) is written to <handle> if
+    non-NULL and the stride (in bytes) is written to <stride>, if
+    non-NULL.
+
+    Import a shared buffer by calling eglCreateImageKHR with
+    EGL_DRM_BUFFER_MESA as the target, using EGL_WIDTH, EGL_HEIGHT,
+    EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_STRIDE_MESA
+    in the attrib list.
+
+Issues
+
+    1.  Why don't we use eglCreateImageKHR with a target that
+        indicates that we want to create an EGLImage from scratch?
+
+        RESOLVED: The eglCreateImageKHR entry point is reserved for
+        creating an EGLImage from an already existing client API
+        resource.  This is fine when we're creating the EGLImage from
+        an existing DRM buffer name, it doesn't seem right to overload
+        the function to also allocate the underlying resource.
+
+    2.  Why don't we use an eglQueryImageMESA type functions for
+        querying the DRM EGLImage attributes (name, handle, and stride)?
+
+        RESOLVED: The eglQueryImage function has been proposed often,
+        but it goes against the EGLImage design.  EGLImages are opaque
+        handles to a 2D array of pixels, which can be passed between
+        client APIs.  By referenceing an EGLImage in a client API, the
+        EGLImage target (a texture, a renderbuffer or such) can be
+        used to query the attributes of the EGLImage.  We don't have a
+        full client API for creating and querying DRM buffers, though,
+        so we use a new EGL extension entry point instead.
+
+Revision History
+
+    Version 1, June 3, 2010
+        Initial draft (Kristian Høgsberg)
+    Version 2, August 25, 2010
+        Flesh out the extension a bit, add final EGL tokens, capture
+        some of the original discussion in the issues section.
index cca20ecaae877805e6b3b3756ece26c3efd5e229..cf1661e4eac2e9d08273fcda83f954408d08ce8b 100644 (file)
@@ -69,7 +69,6 @@ a:visited {
 <li><a href="http://sourceforge.net/projects/mesa3d" target="_parent">SourceForge homepage</a>
 <li><a href="repository.html" target="MainFrame">Source Code Repository</a>
 <li><a href="sourcetree.html" target="MainFrame">Source Code Tree</a>
-<li><a href="memory.html" target="MainFrame">DRI Memory Management</a>
 <li><a href="glu.html" target="MainFrame">SGI's GLU</a>
 <li><a href="utilities.html" target="MainFrame">Utilities</a>
 <li><a href="helpwanted.html" target="MainFrame">Help Wanted</a>
index 410f1ac5e8e0a448b9cac658581bc0879e9eff47..8960e7cb48bd5d47a65a8f8c151ebda454dcf7af 100644 (file)
 Both professional and volunteer developers contribute to Mesa.
 </p>
 <p>
-<a href="http://www.tungstengraphics.com/" target="_parent">Tungsten Graphics</a>
+<a href="http://www.vmware.com/" target="_parent">VMware</a>
 employs several of the main Mesa developers including Brian Paul
 and Keith Whitwell.
-Much of the on-going work in Mesa is done through Tungsten Graphics engineering
-contracts.
-Prominent examples of this work includes:
+</p>
+
+<p>
+In the past, Tungsten Graphics contracts implemented many Mesa features
+including:
 </p>
 <ul>
 <li>DRI drivers for Intel i965, i945, i915 and other chips
@@ -29,23 +31,19 @@ Prominent examples of this work includes:
 <p>
 Other companies including
 <a href="http://www.intellinuxgraphics.org/index.html" target="_parent">Intel</a>
-and IBM also actively contribute to the project.
+and RedHat also actively contribute to the project.
+Intel has recently contributed the new GLSL compiler in Mesa 7.9.
 </p>
 
 <p>
-Volunteers have made significant contributions to all parts of Mesa, including
-complete device drivers.
+<a href="http://www.lunarg.com/" target="_parent">LunarG</a> can be contacted
+for custom Mesa / 3D graphics development.
 </p>
 
-
-<H1>Custom Development</H1>
 <p>
-Contact <a href="http://www.tungstengraphics.com/" target="_parent">
-Tungsten Graphics</a>
-for information about custom development in Mesa, OpenGL, X and other
-graphics technologies.
+Volunteers have made significant contributions to all parts of Mesa, including
+complete device drivers.
 </p>
 
-
 </body>
 </html>
index aae2e6e1928b2dde5302dc09752b6b81a63ea554..0806caf388e12a15041e502f8fd7d91669a641a0 100644 (file)
@@ -111,11 +111,9 @@ It implements the OpenGL 1.3 specification.
 
 
 <p>
-November 2001: I cofound <a href="http://www.tungstengraphics.com" target="_parent">
-Tungsten Graphics, Inc.</a> with Keith Whitwell, Jens Owen, David Dawes and
-Frank LaMonica.
-I continue to develop Mesa as part of my resposibilities with Tungsten
-Graphics and as a spare-time project.
+November 2001: I cofounded Tungsten Graphics, Inc. with Keith Whitwell,
+Jens Owen, David Dawes and Frank LaMonica.
+Tungsten Graphics was acquired by VMware in December 2008.
 </p>
 
 <p>
index b7731cdaf3fd3f541ba5991835f773a2a0cf01a3..09385ad35e147344420ae68da8f7e648173ef391 100644 (file)
 <H1>News</H1>
 
 
+<h2>June 16, 2010</h2>
+
+<p>
+<a href="relnotes-7.8.2.html">Mesa 7.8.2</a> is released.  This is a bug-fix
+release collecting fixes since the 7.8.1 release.
+</p>
+
+
 <h2>April 5, 2010</h2>
 
 <p>
@@ -157,9 +165,6 @@ Added a new page describing the <a href="cell.html">Mesa Cell driver</a>.
 <p>
 Gallium3D is the codename for the new Mesa device driver architecture
 which is currently under development.
-A <a href="http://wiki.freedesktop.org/wiki/Software/gallium"
-target="_parent"> summary</a> of the architecture can be found on the
-Tungsten Graphics website.
 </p>
 <p>
 Gallium3D development is taking place on the <em>gallium-0.1</em> branch
@@ -210,11 +215,8 @@ shading language and built-in functions.
 
 <h2>April 2007</h2>
 <p>
-Thomas Hellstr&ouml;m of
-<a href="http://www.tungstengraphics.com" target="_parent">
-Tungsten Graphics</a> has written a whitepaper describing the new
-<a href="http://www.tungstengraphics.com/mm.pdf">DRI memory management
-system</a>.
+Thomas Hellstr&ouml;m of Tungsten Graphics has written a whitepaper
+describing the new DRI memory management system</a>.
 </p>
 
 <h2>December 5, 2006</h2>
index 457dd8fd05d9ef864945ff2438984ee3782225a3..2cc7c4ec622361e949653b3e5cc6f2e2668d6526 100644 (file)
@@ -34,7 +34,11 @@ tbd
 
 <h2>New features</h2>
 <ul>
+<li>New, improved GLSL compiler written by Intel.
+    See the <a href="shading.html"> Shading Language</a> page for
+    more information.
 <li>GL_EXT_timer_query extension (i965 driver only)
+<li>GL_EXT_framebuffer_multisample extension (intel drivers, MAX_SAMPLES = 1)
 <li>GL_ARB_texture_swizzle extension (alias of GL_EXT_texture_swizzle)
 <li>GL_ARB_draw_elements_base_vertex, GL_ARB_fragment_program_shadow
     and GL_EXT_draw_buffers2 in Gallium drivers
index 750884cf36c448c8acfb7fd98edb0d0d70bfa5e7..c41d4a9be2b18e73bb6006774e5acc4d2e790782 100644 (file)
@@ -39,19 +39,19 @@ list of keywords to control some aspects of the GLSL compiler and shader
 execution.  These are generally used for debugging.
 </p>
 <ul>
-<li>dump - print GLSL shader code to stdout at link time
-<li>log - log all GLSL shaders to files.
+<li><b>dump</b> - print GLSL shader code to stdout at link time
+<li><b>log</b> - log all GLSL shaders to files.
     The filenames will be "shader_X.vert" or "shader_X.frag" where X
     the shader ID.
-<li>nopt - disable compiler optimizations
-<li>opt - force compiler optimizations
-<li>uniform - print message to stdout when glUniform is called
-<li>nopvert - force vertex shaders to be a simple shader that just transforms
+<li><b>nopt</b> - disable compiler optimizations
+<li><b>opt</b> - force compiler optimizations
+<li><b>uniform</b> - print message to stdout when glUniform is called
+<li><b>nopvert</b> - force vertex shaders to be a simple shader that just transforms
     the vertex position with ftransform() and passes through the color and
     texcoord[0] attributes.
-<li>nopfrag - force fragment shader to be a simple shader that passes
+<li><b>nopfrag</b> - force fragment shader to be a simple shader that passes
     through the color attribute.
-<li>useprog - log glUseProgram calls to stderr
+<li><b>useprog</b> - log glUseProgram calls to stderr
 </ul>
 <p>
 Example:  export MESA_GLSL=dump,nopt
@@ -59,30 +59,28 @@ Example:  export MESA_GLSL=dump,nopt
 
 
 <a name="120">
-<h2>GLSL 1.20 support</h2>
+<h2>GLSL Version</h2>
 
 <p>
-GLSL version 1.20 is supported in Mesa 7.3 and later.
-Among the features/differences of GLSL 1.20 are:
+The GLSL compiler currently supports version 1.20 of the shading language.
+</p>
+
+<p>
+Several GLSL extensions are also supported:
+</p>
 <ul>
-<li><code>mat2x3, mat2x4</code>, etc. types and functions
-<li><code>transpose(), outerProduct(), matrixCompMult()</code> functions
-(but untested)
-<li>precision qualifiers (lowp, mediump, highp)
-<li><code>invariant</code> qualifier
-<li><code>array.length()</code> method
-<li><code>float[5] a;</code> array syntax
-<li><code>centroid</code> qualifier
-<li>unsized array constructors
-<li>initializers for uniforms
-<li>const initializers calling built-in functions
+<li>GL_ARB_draw_buffers
+<li>GL_ARB_texture_rectangle
+<li>GL_ARB_fragment_coord_conventions
+<li>GL_EXT_texture_array
 </ul>
 
 
-
 <a name="unsup">
 <h2>Unsupported Features</h2>
 
+<p>XXX update this section</p>
+
 <p>
 The following features of the shading language are not yet fully supported
 in Mesa:
@@ -130,39 +128,6 @@ These issues will be addressed/resolved in the future.
 <h2>Programming Hints</h2>
 
 <ul>
-<li>Declare <em>in</em> function parameters as <em>const</em> whenever possible.
-    This improves the efficiency of function inlining.
-</li>
-<br>
-<li>To reduce register usage, declare variables within smaller scopes.
-    For example, the following code:
-<pre>
-    void main()
-    {
-       vec4 a1, a2, b1, b2;
-       gl_Position = expression using a1, a2.
-       gl_Color = expression using b1, b2;
-    }
-</pre>
-    Can be rewritten as follows to use half as many registers:
-<pre>
-    void main()
-    {
-       {
-          vec4 a1, a2;
-          gl_Position = expression using a1, a2.
-       }
-       {
-          vec4 b1, b2;
-          gl_Color = expression using b1, b2;
-       }
-    }
-</pre>
-    Alternately, rather than using several float variables, use
-    a vec4 instead.  Use swizzling and writemasks to access the
-    components of the vec4 as floats.
-</li>
-<br>
 <li>Use the built-in library functions whenever possible.
     For example, instead of writing this:
 <pre>
@@ -172,8 +137,6 @@ These issues will be addressed/resolved in the future.
 <pre>
         float x = inversesqrt(y);
 </pre>
-<li>
-   Use ++i when possible as it's more efficient than i++
 </li>
 </ul>
 
@@ -182,13 +145,8 @@ These issues will be addressed/resolved in the future.
 <h2>Stand-alone GLSL Compiler</h2>
 
 <p>
-A unique stand-alone GLSL compiler driver has been added to Mesa.
-<p>
-
-<p>
-The stand-alone compiler (like a conventional command-line compiler)
-is a tool that accepts Shading Language programs and emits low-level
-GPU programs.
+The stand-alone GLSL compiler program can be used to compile GLSL shaders
+into low-level GPU code.
 </p>
 
 <p>
@@ -201,59 +159,25 @@ This tool is useful for:
 </ul>
 
 <p>
-After building Mesa, the glslcompiler can be built by manually running:
+After building Mesa, the compiler can be found at src/glsl/glsl_compiler
 </p>
-<pre>
-    make realclean
-    make linux
-    cd src/mesa/drivers/glslcompiler
-    make
-</pre>
-
 
 <p>
 Here's an example of using the compiler to compile a vertex shader and
 emit GL_ARB_vertex_program-style instructions:
 </p>
 <pre>
-    bin/glslcompiler --debug --numbers --fs progs/glsl/CH06-brick.frag.txt
-</pre>
-<p>
-results in:
-</p>
-<pre>
-# Fragment Program/Shader
-  0: RCP TEMP[4].x, UNIFORM[2].xxxx;
-  1: RCP TEMP[4].y, UNIFORM[2].yyyy;
-  2: MUL TEMP[3].xy, VARYING[0], TEMP[4];
-  3: MOV TEMP[1], TEMP[3];
-  4: MUL TEMP[0].w, TEMP[1].yyyy, CONST[4].xxxx;
-  5: FRC TEMP[1].z, TEMP[0].wwww;
-  6: SGT.C TEMP[0].w, TEMP[1].zzzz, CONST[4].xxxx;
-  7: IF (NE.wwww); # (if false, goto 9);
-  8:    ADD TEMP[1].x, TEMP[1].xxxx, CONST[4].xxxx;
-  9: ENDIF;
- 10: FRC TEMP[1].xy, TEMP[1];
- 11: SGT TEMP[2].xy, UNIFORM[3], TEMP[1];
- 12: MUL TEMP[1].z, TEMP[2].xxxx, TEMP[2].yyyy;
- 13: LRP TEMP[0], TEMP[1].zzzz, UNIFORM[0], UNIFORM[1];
- 14: MUL TEMP[0].xyz, TEMP[0], VARYING[1].xxxx;
- 15: MOV OUTPUT[0].xyz, TEMP[0];
- 16: MOV OUTPUT[0].w, CONST[4].yyyy;
- 17: END
+    src/glsl/glslcompiler --dump-ast myshader.vert
 </pre>
 
-<p>
-Note that some shading language constructs (such as uniform and varying
-variables) aren't expressible in ARB or NV-style programs.
-Therefore, the resulting output is not always legal by definition of
-those program languages.
-</p>
-<p>
-Also note that this compiler driver is still under development.
-Over time, the correctness of the GPU programs, with respect to the ARB
-and NV languagues, should improve.
-</p>
+Options include
+<ul>
+<li><b>--dump-ast</b> - dump GPU code
+<li><b>--dump-hir</b> - dump high-level IR code
+<li><b>--dump-lir</b> - dump low-level IR code
+<li><b>--link</b> - ???
+</ul>
+
 
 
 
@@ -262,38 +186,12 @@ and NV languagues, should improve.
 
 <p>
 The source code for Mesa's shading language compiler is in the
-<code>src/mesa/shader/slang/</code> directory.
+<code>src/glsl/</code> directory.
 </p>
 
 <p>
-The compiler follows a fairly standard design and basically works as follows:
+XXX provide some info about the compiler....
 </p>
-<ul>
-<li>The input string is tokenized (see grammar.c) and parsed
-(see slang_compiler_*.c) to produce an Abstract Syntax Tree (AST).
-The nodes in this tree are slang_operation structures
-(see slang_compile_operation.h).
-The nodes are decorated with symbol table, scoping and datatype information.
-<li>The AST is converted into an Intermediate representation (IR) tree
-(see the slang_codegen.c file).
-The IR nodes represent basic GPU instructions, like add, dot product,
-move, etc. 
-The IR tree is mostly a binary tree, but a few nodes have three or four
-children.
-In principle, the IR tree could be executed by doing an in-order traversal.
-<li>The IR tree is traversed in-order to emit code (see slang_emit.c).
-This is also when registers are allocated to store variables and temps.
-<li>In the future, a pattern-matching code generator-generator may be
-used for code generation.
-Programs such as L-BURG (Bottom-Up Rewrite Generator) and Twig look for
-patterns in IR trees, compute weights for subtrees and use the weights
-to select the best instructions to represent the sub-tree.
-<li>The emitted GPU instructions (see prog_instruction.h) are stored in a
-gl_program object (see mtypes.h).
-<li>When a fragment shader and vertex shader are linked (see slang_link.c)
-the varying vars are matched up, uniforms are merged, and vertex
-attributes are resolved (rewriting instructions as needed).
-</ul>
 
 <p>
 The final vertex and fragment programs may be interpreted in software
@@ -351,20 +249,20 @@ Extra NOP instructions will also be inserted.
 <h2>Compiler Validation</h2>
 
 <p>
-A <a href="http://glean.sf.net" target="_parent">Glean</a> test has
-been create to exercise the GLSL compiler.
-</p>
-<p>
-The <em>glsl1</em> test runs over 170 sub-tests to check that the language
-features and built-in functions work properly.
-This test should be run frequently while working on the compiler to catch
+Developers working on the GLSL compiler should test frequently to avoid
 regressions.
 </p>
+
 <p>
-The test coverage is reasonably broad and complete but additional tests
-should be added.
+The <a href="http://people.freedesktop.org/~nh/piglit/">Piglit</a> project
+has many GLSL tests and the
+<a href="http://glean.sf.net" target="_parent">Glean</a> glsl1 test 
+tests GLSL features.
 </p>
 
+<p>
+The Mesa demos repository also has some good GLSL tests.
+</p>
 
 </BODY>
 </HTML>
index dac66a61bae3a4f4a891d3e20bf2f5052a4da48b..d576bb674400cf9d1718a5d5f170143ccc13c3e0 100644 (file)
@@ -16,8 +16,7 @@
 </h3>
 </center>
 </h2>
-<p> Copyright &copy; 2002-2003 by <a
- href="http://www.tungstengraphics.com/">Tungsten Graphics, Inc.</a>,
+<p> Copyright &copy; 2002-2003 by Tungsten Graphics, Inc.,
 Cedar Park, Texas. All Rights Reserved. <br>
 <br>
 Permission is granted to make and distribute verbatim copies of this
index 68591bdeb8c5adca5be59badadffd9d9cc24a155..04603931b3844a1fdb65fba824bfc4f9b034cbb9 100644 (file)
@@ -6,7 +6,7 @@ extern "C" {
 #endif
 
 /*
-** Copyright (c) 2007-2009 The Khronos Group Inc.
+** Copyright (c) 2007-2010 The Khronos Group Inc.
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a
 ** copy of this software and/or associated documentation files (the
@@ -34,8 +34,8 @@ extern "C" {
 
 /* Header file version number */
 /* Current version at http://www.khronos.org/registry/egl/ */
-/* $Revision: 10185 $ on $Date: 2010-01-22 11:38:01 -0800 (Fri, 22 Jan 2010) $ */
-#define EGL_EGLEXT_VERSION 5
+/* $Revision: 12124 $ on $Date: 2010-07-27 20:12:35 -0700 (Tue, 27 Jul 2010) $ */
+#define EGL_EGLEXT_VERSION 7
 
 #ifndef EGL_KHR_config_attribs
 #define EGL_KHR_config_attribs 1
@@ -120,6 +120,30 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGL
 #define EGL_GL_RENDERBUFFER_KHR                        0x30B9  /* eglCreateImageKHR target */
 #endif
 
+#ifndef EGL_MESA_drm_image
+#define EGL_MESA_drm_image 1
+#define EGL_DRM_BUFFER_FORMAT_MESA             0x31D0  /* eglCreateImageKHR attribute */
+#define EGL_DRM_BUFFER_USE_MESA                        0x31D1
+
+/* EGL_DRM_BUFFER_FORMAT_MESA tokens */
+#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA      0x31D2
+
+/* EGL_DRM_BUFFER_USE_MESA bits */
+#define EGL_DRM_BUFFER_USE_SCANOUT_MESA                0x0001
+#define EGL_DRM_BUFFER_USE_SHARE_MESA          0x0002
+
+#define EGL_DRM_BUFFER_MESA                    0x31D3  /* eglCreateImageKHR target */
+#define EGL_DRM_BUFFER_STRIDE_MESA             0x31D4  /* eglCreateImageKHR attribute */
+
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA(EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#endif
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESA) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESA) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#endif
+
+#if KHRONOS_SUPPORT_INT64   /* EGLTimeKHR requires 64-bit uint support */
 #ifndef EGL_KHR_reusable_sync
 #define EGL_KHR_reusable_sync 1
 
@@ -149,6 +173,7 @@ typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSy
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
 #endif
+#endif
 
 /* EGL_MESA_screen extension  >>> PRELIMINARY <<< */
 #ifndef EGL_MESA_screen_surface
@@ -238,6 +263,101 @@ typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETDRMDISPLAYMESA) (int fd);
 #define EGL_CONTEXT_PRIORITY_LOW_IMG           0x3103
 #endif
 
+#ifndef EGL_KHR_lock_surface2
+#define EGL_KHR_lock_surface2 1
+#define EGL_BITMAP_PIXEL_SIZE_KHR              0x3110
+#endif
+
+#ifndef EGL_NV_coverage_sample
+#define EGL_NV_coverage_sample 1
+#define EGL_COVERAGE_BUFFERS_NV 0x30E0
+#define EGL_COVERAGE_SAMPLES_NV 0x30E1
+#endif
+
+#ifndef EGL_NV_depth_nonlinear
+#define EGL_NV_depth_nonlinear 1
+#define EGL_DEPTH_ENCODING_NV 0x30E2
+#define EGL_DEPTH_ENCODING_NONE_NV 0
+#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3
+#endif
+
+#if KHRONOS_SUPPORT_INT64   /* EGLTimeNV requires 64-bit uint support */
+#ifndef EGL_NV_sync
+#define EGL_NV_sync 1
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV    0x30E6
+#define EGL_SYNC_STATUS_NV                     0x30E7
+#define EGL_SIGNALED_NV                                0x30E8
+#define EGL_UNSIGNALED_NV                      0x30E9
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV         0x0001
+#define EGL_FOREVER_NV                         0xFFFFFFFFFFFFFFFFull
+#define EGL_ALREADY_SIGNALED_NV                        0x30EA
+#define EGL_TIMEOUT_EXPIRED_NV                 0x30EB
+#define EGL_CONDITION_SATISFIED_NV             0x30EC
+#define EGL_SYNC_TYPE_NV                       0x30ED
+#define EGL_SYNC_CONDITION_NV                  0x30EE
+#define EGL_SYNC_FENCE_NV                      0x30EF
+#define EGL_NO_SYNC_NV                         ((EGLSyncNV)0)
+typedef void* EGLSyncNV;
+typedef khronos_utime_nanoseconds_t EGLTimeNV;
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLSyncNV eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+EGLBoolean eglDestroySyncNV (EGLSyncNV sync);
+EGLBoolean eglFenceNV (EGLSyncNV sync);
+EGLint eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+EGLBoolean eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
+EGLBoolean eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#endif
+#endif
+
+#if KHRONOS_SUPPORT_INT64   /* Dependent on EGL_KHR_reusable_sync which requires 64-bit uint support */
+#ifndef EGL_KHR_fence_sync
+#define EGL_KHR_fence_sync 1
+/* Reuses most tokens and entry points from EGL_KHR_reusable_sync */
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR   0x30F0
+#define EGL_SYNC_CONDITION_KHR                 0x30F8
+#define EGL_SYNC_FENCE_KHR                     0x30F9
+#endif
+#endif
+
+#ifndef EGL_HI_clientpixmap
+#define EGL_HI_clientpixmap 1
+
+/* Surface Attribute */
+#define EGL_CLIENT_PIXMAP_POINTER_HI           0x8F74
+/*
+ * Structure representing a client pixmap
+ * (pixmap's data is in client-space memory).
+ */
+struct EGLClientPixmapHI
+{
+       void*           pData;
+       EGLint          iWidth;
+       EGLint          iHeight;
+       EGLint          iStride;
+};
+
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI(EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap);
+#endif /* EGL_HI_clientpixmap */
+
+#ifndef EGL_HI_colorformats
+#define EGL_HI_colorformats 1
+/* Config Attribute */
+#define EGL_COLOR_FORMAT_HI                    0x8F70
+/* Color Formats */
+#define EGL_COLOR_RGB_HI                       0x8F71
+#define EGL_COLOR_RGBA_HI                      0x8F72
+#define EGL_COLOR_ARGB_HI                      0x8F73
+#endif /* EGL_HI_colorformats */
 
 #ifndef EGL_NOK_swap_region
 #define EGL_NOK_swap_region 1
index 2c8546499c5dc8847794b43c540963645246a473..ff83ff145e7550f3f4789f16aa5e404e651b5954 100644 (file)
@@ -789,6 +789,17 @@ struct __DRIdri2ExtensionRec {
 #define __DRI_IMAGE_FORMAT_XRGB8888     0x1002
 #define __DRI_IMAGE_FORMAT_ARGB8888     0x1003
 
+#define __DRI_IMAGE_USE_SHARE          0x0001
+#define __DRI_IMAGE_USE_SCANOUT                0x0002
+
+/**
+ * queryImage attributes
+ */
+
+#define __DRI_IMAGE_ATTRIB_STRIDE      0x2000
+#define __DRI_IMAGE_ATTRIB_HANDLE      0x2001
+#define __DRI_IMAGE_ATTRIB_NAME                0x2002
+
 typedef struct __DRIimageRec          __DRIimage;
 typedef struct __DRIimageExtensionRec __DRIimageExtension;
 struct __DRIimageExtensionRec {
@@ -804,8 +815,16 @@ struct __DRIimageExtensionRec {
                                               void *loaderPrivate);
 
     void (*destroyImage)(__DRIimage *image);
+
+    __DRIimage *(*createImage)(__DRIscreen *screen,
+                              int width, int height, int format,
+                              unsigned int use,
+                              void *loaderPrivate);
+
+   GLboolean (*queryImage)(__DRIimage *image, int attrib, int *value);
 };
 
+
 /**
  * This extension must be implemented by the loader and passed to the
  * driver at screen creation time.  The EGLImage entry points in the
diff --git a/include/c99/inttypes.h b/include/c99/inttypes.h
new file mode 100644 (file)
index 0000000..4b3828a
--- /dev/null
@@ -0,0 +1,305 @@
+// ISO C9x  compliant inttypes.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
+// 
+//  Copyright (c) 2006 Alexander Chemeris
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//   1. Redistributions of source code must retain the above copyright notice,
+//      this list of conditions and the following disclaimer.
+// 
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+// 
+//   3. The name of the author may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_INTTYPES_H_ // [
+#define _MSC_INTTYPES_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "stdint.h"
+
+// 7.8 Format conversion of integer types
+
+typedef struct {
+   intmax_t quot;
+   intmax_t rem;
+} imaxdiv_t;
+
+// 7.8.1 Macros for format specifiers
+
+#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [   See footnote 185 at page 198
+
+// The fprintf macros for signed integers are:
+#define PRId8       "d"
+#define PRIi8       "i"
+#define PRIdLEAST8  "d"
+#define PRIiLEAST8  "i"
+#define PRIdFAST8   "d"
+#define PRIiFAST8   "i"
+
+#define PRId16       "hd"
+#define PRIi16       "hi"
+#define PRIdLEAST16  "hd"
+#define PRIiLEAST16  "hi"
+#define PRIdFAST16   "hd"
+#define PRIiFAST16   "hi"
+
+#define PRId32       "I32d"
+#define PRIi32       "I32i"
+#define PRIdLEAST32  "I32d"
+#define PRIiLEAST32  "I32i"
+#define PRIdFAST32   "I32d"
+#define PRIiFAST32   "I32i"
+
+#define PRId64       "I64d"
+#define PRIi64       "I64i"
+#define PRIdLEAST64  "I64d"
+#define PRIiLEAST64  "I64i"
+#define PRIdFAST64   "I64d"
+#define PRIiFAST64   "I64i"
+
+#define PRIdMAX     "I64d"
+#define PRIiMAX     "I64i"
+
+#define PRIdPTR     "Id"
+#define PRIiPTR     "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8       "o"
+#define PRIu8       "u"
+#define PRIx8       "x"
+#define PRIX8       "X"
+#define PRIoLEAST8  "o"
+#define PRIuLEAST8  "u"
+#define PRIxLEAST8  "x"
+#define PRIXLEAST8  "X"
+#define PRIoFAST8   "o"
+#define PRIuFAST8   "u"
+#define PRIxFAST8   "x"
+#define PRIXFAST8   "X"
+
+#define PRIo16       "ho"
+#define PRIu16       "hu"
+#define PRIx16       "hx"
+#define PRIX16       "hX"
+#define PRIoLEAST16  "ho"
+#define PRIuLEAST16  "hu"
+#define PRIxLEAST16  "hx"
+#define PRIXLEAST16  "hX"
+#define PRIoFAST16   "ho"
+#define PRIuFAST16   "hu"
+#define PRIxFAST16   "hx"
+#define PRIXFAST16   "hX"
+
+#define PRIo32       "I32o"
+#define PRIu32       "I32u"
+#define PRIx32       "I32x"
+#define PRIX32       "I32X"
+#define PRIoLEAST32  "I32o"
+#define PRIuLEAST32  "I32u"
+#define PRIxLEAST32  "I32x"
+#define PRIXLEAST32  "I32X"
+#define PRIoFAST32   "I32o"
+#define PRIuFAST32   "I32u"
+#define PRIxFAST32   "I32x"
+#define PRIXFAST32   "I32X"
+
+#define PRIo64       "I64o"
+#define PRIu64       "I64u"
+#define PRIx64       "I64x"
+#define PRIX64       "I64X"
+#define PRIoLEAST64  "I64o"
+#define PRIuLEAST64  "I64u"
+#define PRIxLEAST64  "I64x"
+#define PRIXLEAST64  "I64X"
+#define PRIoFAST64   "I64o"
+#define PRIuFAST64   "I64u"
+#define PRIxFAST64   "I64x"
+#define PRIXFAST64   "I64X"
+
+#define PRIoMAX     "I64o"
+#define PRIuMAX     "I64u"
+#define PRIxMAX     "I64x"
+#define PRIXMAX     "I64X"
+
+#define PRIoPTR     "Io"
+#define PRIuPTR     "Iu"
+#define PRIxPTR     "Ix"
+#define PRIXPTR     "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd8       "d"
+#define SCNi8       "i"
+#define SCNdLEAST8  "d"
+#define SCNiLEAST8  "i"
+#define SCNdFAST8   "d"
+#define SCNiFAST8   "i"
+
+#define SCNd16       "hd"
+#define SCNi16       "hi"
+#define SCNdLEAST16  "hd"
+#define SCNiLEAST16  "hi"
+#define SCNdFAST16   "hd"
+#define SCNiFAST16   "hi"
+
+#define SCNd32       "ld"
+#define SCNi32       "li"
+#define SCNdLEAST32  "ld"
+#define SCNiLEAST32  "li"
+#define SCNdFAST32   "ld"
+#define SCNiFAST32   "li"
+
+#define SCNd64       "I64d"
+#define SCNi64       "I64i"
+#define SCNdLEAST64  "I64d"
+#define SCNiLEAST64  "I64i"
+#define SCNdFAST64   "I64d"
+#define SCNiFAST64   "I64i"
+
+#define SCNdMAX     "I64d"
+#define SCNiMAX     "I64i"
+
+#ifdef _WIN64 // [
+#  define SCNdPTR     "I64d"
+#  define SCNiPTR     "I64i"
+#else  // _WIN64 ][
+#  define SCNdPTR     "ld"
+#  define SCNiPTR     "li"
+#endif  // _WIN64 ]
+
+// The fscanf macros for unsigned integers are:
+#define SCNo8       "o"
+#define SCNu8       "u"
+#define SCNx8       "x"
+#define SCNX8       "X"
+#define SCNoLEAST8  "o"
+#define SCNuLEAST8  "u"
+#define SCNxLEAST8  "x"
+#define SCNXLEAST8  "X"
+#define SCNoFAST8   "o"
+#define SCNuFAST8   "u"
+#define SCNxFAST8   "x"
+#define SCNXFAST8   "X"
+
+#define SCNo16       "ho"
+#define SCNu16       "hu"
+#define SCNx16       "hx"
+#define SCNX16       "hX"
+#define SCNoLEAST16  "ho"
+#define SCNuLEAST16  "hu"
+#define SCNxLEAST16  "hx"
+#define SCNXLEAST16  "hX"
+#define SCNoFAST16   "ho"
+#define SCNuFAST16   "hu"
+#define SCNxFAST16   "hx"
+#define SCNXFAST16   "hX"
+
+#define SCNo32       "lo"
+#define SCNu32       "lu"
+#define SCNx32       "lx"
+#define SCNX32       "lX"
+#define SCNoLEAST32  "lo"
+#define SCNuLEAST32  "lu"
+#define SCNxLEAST32  "lx"
+#define SCNXLEAST32  "lX"
+#define SCNoFAST32   "lo"
+#define SCNuFAST32   "lu"
+#define SCNxFAST32   "lx"
+#define SCNXFAST32   "lX"
+
+#define SCNo64       "I64o"
+#define SCNu64       "I64u"
+#define SCNx64       "I64x"
+#define SCNX64       "I64X"
+#define SCNoLEAST64  "I64o"
+#define SCNuLEAST64  "I64u"
+#define SCNxLEAST64  "I64x"
+#define SCNXLEAST64  "I64X"
+#define SCNoFAST64   "I64o"
+#define SCNuFAST64   "I64u"
+#define SCNxFAST64   "I64x"
+#define SCNXFAST64   "I64X"
+
+#define SCNoMAX     "I64o"
+#define SCNuMAX     "I64u"
+#define SCNxMAX     "I64x"
+#define SCNXMAX     "I64X"
+
+#ifdef _WIN64 // [
+#  define SCNoPTR     "I64o"
+#  define SCNuPTR     "I64u"
+#  define SCNxPTR     "I64x"
+#  define SCNXPTR     "I64X"
+#else  // _WIN64 ][
+#  define SCNoPTR     "lo"
+#  define SCNuPTR     "lu"
+#  define SCNxPTR     "lx"
+#  define SCNXPTR     "lX"
+#endif  // _WIN64 ]
+
+#endif // __STDC_FORMAT_MACROS ]
+
+// 7.8.2 Functions for greatest-width integer types
+
+// 7.8.2.1 The imaxabs function
+#define imaxabs _abs64
+
+// 7.8.2.2 The imaxdiv function
+
+// This is modified version of div() function from Microsoft's div.c found
+// in %MSVC.NET%\crt\src\div.c
+#ifdef STATIC_IMAXDIV // [
+static
+#else // STATIC_IMAXDIV ][
+_inline
+#endif // STATIC_IMAXDIV ]
+imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
+{
+   imaxdiv_t result;
+
+   result.quot = numer / denom;
+   result.rem = numer % denom;
+
+   if (numer < 0 && result.rem > 0) {
+      // did division wrong; must fix up
+      ++result.quot;
+      result.rem -= denom;
+   }
+
+   return result;
+}
+
+// 7.8.2.3 The strtoimax and strtoumax functions
+#define strtoimax _strtoi64
+#define strtoumax _strtoui64
+
+// 7.8.2.4 The wcstoimax and wcstoumax functions
+#define wcstoimax _wcstoi64
+#define wcstoumax _wcstoui64
+
+
+#endif // _MSC_INTTYPES_H_ ]
index fc6459d03d2b4ac0de7b112862b4bf5856938665..d02608a5972642c7b7a13b987f21e2502a5af3ea 100644 (file)
-/**************************************************************************
- *
- * Copyright 2007-2010 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- **************************************************************************/
-
-/*
- * stdint.h --
- *
- *    Portable subset of C99's stdint.h.
- *
- *    At the moment it only supports MSVC, given all other mainstream compilers
- *    already support C99. If this is necessary for other compilers then it
- *    might be worth to replace this with
- *    http://www.azillionmonkeys.com/qed/pstdint.h.
- */
-
-#ifndef _STDINT_H_
-#define _STDINT_H_
-
-
-#ifndef INT8_MAX
-#define INT8_MAX           127
-#endif
-#ifndef INT8_MIN
-#define INT8_MIN           -128
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX          255
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX          32767
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN          -32768
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX         65535
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX          2147483647
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN          -2147483648
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX         4294967295U
-#endif
+// ISO C9x  compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
+// 
+//  Copyright (c) 2006-2008 Alexander Chemeris
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//   1. Redistributions of source code must retain the above copyright notice,
+//      this list of conditions and the following disclaimer.
+// 
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+// 
+//   3. The name of the author may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+///////////////////////////////////////////////////////////////////////////////
 
-#ifndef INT8_C
-#define INT8_C(__val)     __val
-#endif
-#ifndef UINT8_C
-#define UINT8_C(__val)    __val
-#endif
-#ifndef INT16_C
-#define INT16_C(__val)    __val
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
 #endif
-#ifndef UINT16_C
-#define UINT16_C(__val)   __val
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
+// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler give many errors like this:
+//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#ifdef __cplusplus
+extern "C" {
 #endif
-#ifndef INT32_C
-#define INT32_C(__val)    __val
+#  include <wchar.h>
+#ifdef __cplusplus
+}
 #endif
-#ifndef UINT32_C
-#define UINT32_C(__val)   __val##U
+
+// Define _W64 macros to mark types changing their size, like intptr_t.
+#ifndef _W64
+#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+#     define _W64 __w64
+#  else
+#     define _W64
+#  endif
 #endif
 
 
-#if defined(_MSC_VER)
+// 7.18.1 Integer types
 
-typedef __int8             int8_t;
-typedef unsigned __int8    uint8_t;
-typedef __int16            int16_t;
-typedef unsigned __int16   uint16_t;
-typedef __int32            int32_t;
-typedef unsigned __int32   uint32_t;
-typedef __int64            int64_t;
-typedef unsigned __int64   uint64_t;
+// 7.18.1.1 Exact-width integer types
 
-#if defined(_WIN64)
-typedef __int64            intptr_t;
-typedef unsigned __int64   uintptr_t;
+// Visual Studio 6 and Embedded Visual C++ 4 doesn't
+// realize that, e.g. char has the same size as __int8
+// so we give up on __intX for them.
+#if (_MSC_VER < 1300)
+   typedef signed char       int8_t;
+   typedef signed short      int16_t;
+   typedef signed int        int32_t;
+   typedef unsigned char     uint8_t;
+   typedef unsigned short    uint16_t;
+   typedef unsigned int      uint32_t;
 #else
-typedef __int32            intptr_t;
-typedef unsigned __int32   uintptr_t;
-#endif
+   typedef signed __int8     int8_t;
+   typedef signed __int16    int16_t;
+   typedef signed __int32    int32_t;
+   typedef unsigned __int8   uint8_t;
+   typedef unsigned __int16  uint16_t;
+   typedef unsigned __int32  uint32_t;
+#endif
+typedef signed __int64       int64_t;
+typedef unsigned __int64     uint64_t;
 
-#define INT64_C(__val)    __val##i64
-#define UINT64_C(__val)   __val##ui64
 
-#else
-#error "Unsupported compiler"
-#endif
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t    int_least8_t;
+typedef int16_t   int_least16_t;
+typedef int32_t   int_least32_t;
+typedef int64_t   int_least64_t;
+typedef uint8_t   uint_least8_t;
+typedef uint16_t  uint_least16_t;
+typedef uint32_t  uint_least32_t;
+typedef uint64_t  uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t    int_fast8_t;
+typedef int16_t   int_fast16_t;
+typedef int32_t   int_fast32_t;
+typedef int64_t   int_fast64_t;
+typedef uint8_t   uint_fast8_t;
+typedef uint16_t  uint_fast16_t;
+typedef uint32_t  uint_fast32_t;
+typedef uint64_t  uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+   typedef signed __int64    intptr_t;
+   typedef unsigned __int64  uintptr_t;
+#else // _WIN64 ][
+   typedef _W64 signed int   intptr_t;
+   typedef _W64 unsigned int uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t   intmax_t;
+typedef uint64_t  uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN     ((int8_t)_I8_MIN)
+#define INT8_MAX     _I8_MAX
+#define INT16_MIN    ((int16_t)_I16_MIN)
+#define INT16_MAX    _I16_MAX
+#define INT32_MIN    ((int32_t)_I32_MIN)
+#define INT32_MAX    _I32_MAX
+#define INT64_MIN    ((int64_t)_I64_MIN)
+#define INT64_MAX    _I64_MAX
+#define UINT8_MAX    _UI8_MAX
+#define UINT16_MAX   _UI16_MAX
+#define UINT32_MAX   _UI32_MAX
+#define UINT64_MAX   _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN    INT8_MIN
+#define INT_LEAST8_MAX    INT8_MAX
+#define INT_LEAST16_MIN   INT16_MIN
+#define INT_LEAST16_MAX   INT16_MAX
+#define INT_LEAST32_MIN   INT32_MIN
+#define INT_LEAST32_MAX   INT32_MAX
+#define INT_LEAST64_MIN   INT64_MIN
+#define INT_LEAST64_MAX   INT64_MAX
+#define UINT_LEAST8_MAX   UINT8_MAX
+#define UINT_LEAST16_MAX  UINT16_MAX
+#define UINT_LEAST32_MAX  UINT32_MAX
+#define UINT_LEAST64_MAX  UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN    INT8_MIN
+#define INT_FAST8_MAX    INT8_MAX
+#define INT_FAST16_MIN   INT16_MIN
+#define INT_FAST16_MAX   INT16_MAX
+#define INT_FAST32_MIN   INT32_MIN
+#define INT_FAST32_MAX   INT32_MAX
+#define INT_FAST64_MIN   INT64_MIN
+#define INT_FAST64_MAX   INT64_MAX
+#define UINT_FAST8_MAX   UINT8_MAX
+#define UINT_FAST16_MAX  UINT16_MAX
+#define UINT_FAST32_MAX  UINT32_MAX
+#define UINT_FAST64_MAX  UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+#  define INTPTR_MIN   INT64_MIN
+#  define INTPTR_MAX   INT64_MAX
+#  define UINTPTR_MAX  UINT64_MAX
+#else // _WIN64 ][
+#  define INTPTR_MIN   INT32_MIN
+#  define INTPTR_MAX   INT32_MAX
+#  define UINTPTR_MAX  UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN   INT64_MIN
+#define INTMAX_MAX   INT64_MAX
+#define UINTMAX_MAX  UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+#  define PTRDIFF_MIN  _I64_MIN
+#  define PTRDIFF_MAX  _I64_MAX
+#else  // _WIN64 ][
+#  define PTRDIFF_MIN  _I32_MIN
+#  define PTRDIFF_MAX  _I32_MAX
+#endif  // _WIN64 ]
+
+#define SIG_ATOMIC_MIN  INT_MIN
+#define SIG_ATOMIC_MAX  INT_MAX
+
+#ifndef SIZE_MAX // [
+#  ifdef _WIN64 // [
+#     define SIZE_MAX  _UI64_MAX
+#  else // _WIN64 ][
+#     define SIZE_MAX  _UI32_MAX
+#  endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+#  define WCHAR_MIN  0
+#endif  // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+#  define WCHAR_MAX  _UI16_MAX
+#endif  // WCHAR_MAX ]
+
+#define WINT_MIN  0
+#define WINT_MAX  _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val)  val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val)  val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+#define INTMAX_C   INT64_C
+#define UINTMAX_C  UINT64_C
+
+#endif // __STDC_CONSTANT_MACROS ]
+
 
-#endif /* _STDINT_H_ */
+#endif // _MSC_STDINT_H_ ]
index 03a4ef58815f1cf434ecaf9a40709f01fd93214c..d9a5fe0eeafc6d5e63163880f0aac83856b838ed 100644 (file)
@@ -291,6 +291,8 @@ def generate(env):
                 ]
         if env['machine'] == 'x86_64':
             ccflags += ['-m64']
+            if platform == 'darwin':
+                ccflags += ['-fno-common']
         # See also:
         # - http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
         ccflags += [
index 2b46186f986c6d8aaf5394b9205d483d011ddb24..c3e34be6f760f020ad2b797d6d937fcd98da21e4 100644 (file)
@@ -5,6 +5,9 @@ if 'egl' in env['statetrackers']:
     SConscript('egl/main/SConscript')
 
 if 'mesa' in env['statetrackers']:
+    if platform == 'windows':
+        SConscript('talloc/SConscript')
+
     SConscript('glsl/SConscript')
     SConscript('mapi/glapi/SConscript')
     SConscript('mesa/SConscript')
index 6beb4ce88e278eab8ce1f5ab906d705a9ee82755..698a2405781de4cfc338ef12c274bfe5cc34a9fd 100644 (file)
@@ -14,7 +14,7 @@ Contact
 
 Status
 
-    Preliminary - totally subject to change.
+    Obsolete.
 
 Version
 
index efb93bcf06b48d912dee116a1b5cb686342794ba..2b78bcc763dbc95ad8abb5cbdf4e3e32ad1ee501 100644 (file)
@@ -836,6 +836,7 @@ dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp,
         goto cleanup_configs;
    }
 
+   disp->Extensions.MESA_drm_image = EGL_TRUE;
    disp->Extensions.KHR_image_base = EGL_TRUE;
    disp->Extensions.KHR_image_pixmap = EGL_TRUE;
    disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
@@ -994,6 +995,7 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp,
    for (i = 0; dri2_dpy->driver_configs[i]; i++)
       dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, 0);
 
+   disp->Extensions.MESA_drm_image = EGL_TRUE;
    disp->Extensions.KHR_image_base = EGL_TRUE;
    disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
    disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
@@ -1620,6 +1622,96 @@ dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
    return &dri2_img->base;
 }
 
+static _EGLImage *
+dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
+                                 EGLClientBuffer buffer, const EGLint *attr_list)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
+   struct dri2_egl_image *dri2_img;
+   EGLint width, height, format, name, stride, pitch, i, err;
+
+   name = (EGLint) buffer;
+
+   err = EGL_SUCCESS;
+   width = 0;
+   height = 0;
+   format = 0;
+   stride = 0;
+
+   for (i = 0; attr_list[i] != EGL_NONE; i++) {
+      EGLint attr = attr_list[i++];
+      EGLint val = attr_list[i];
+
+      switch (attr) {
+      case EGL_WIDTH:
+        width = val;
+         break;
+      case EGL_HEIGHT:
+        height = val;
+         break;
+      case EGL_DRM_BUFFER_FORMAT_MESA:
+        format = val;
+         break;
+      case EGL_DRM_BUFFER_STRIDE_MESA:
+        stride = val;
+         break;
+      default:
+         err = EGL_BAD_ATTRIBUTE;
+         break;
+      }
+
+      if (err != EGL_SUCCESS) {
+         _eglLog(_EGL_WARNING, "bad image attribute 0x%04x", attr);
+        return NULL;
+      }
+   }
+
+   if (width <= 0 || height <= 0 || stride <= 0) {
+      _eglError(EGL_BAD_PARAMETER,
+               "bad width, height or stride");
+      return NULL;
+   }
+
+   switch (format) {
+   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
+      format = __DRI_IMAGE_FORMAT_ARGB8888;
+      pitch = stride;
+      break;
+   default:
+      _eglError(EGL_BAD_PARAMETER,
+               "dri2_create_image_khr: unsupported pixmap depth");
+      return NULL;
+   }
+
+   dri2_img = malloc(sizeof *dri2_img);
+   if (!dri2_img) {
+      _eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm");
+      return NULL;
+   }
+
+   if (!_eglInitImage(&dri2_img->base, disp, attr_list)) {
+      free(dri2_img);
+      return NULL;
+   }
+
+   dri2_img->dri_image =
+      dri2_dpy->image->createImageFromName(dri2_ctx->dri_context,
+                                          width,
+                                          height,
+                                          format,
+                                          name,
+                                          pitch,
+                                          dri2_img);
+   if (dri2_img->dri_image == NULL) {
+      free(dri2_img);
+      _eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm");
+      return NULL;
+   }
+
+   return &dri2_img->base;
+}
+
 static _EGLImage *
 dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
                      _EGLContext *ctx, EGLenum target,
@@ -1630,6 +1722,8 @@ dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
       return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
    case EGL_GL_RENDERBUFFER_KHR:
       return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
+   case EGL_DRM_BUFFER_MESA:
+      return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
    default:
       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
       return EGL_NO_IMAGE_KHR;
@@ -1648,6 +1742,133 @@ dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
    return EGL_TRUE;
 }
 
+static _EGLImage *
+dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
+                          const EGLint *attr_list)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_image *dri2_img;
+   int width, height, format, i;
+   unsigned int use, dri_use, valid_mask;
+   EGLint err = EGL_SUCCESS;
+
+   dri2_img = malloc(sizeof *dri2_img);
+   if (!dri2_img) {
+      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
+      return EGL_NO_IMAGE_KHR;
+   }
+
+   if (!attr_list) {
+      err = EGL_BAD_PARAMETER;
+      goto cleanup_img;
+   }
+
+   if (!_eglInitImage(&dri2_img->base, disp, attr_list)) {
+      err = EGL_BAD_PARAMETER;
+      goto cleanup_img;
+   }
+
+   width = 0;
+   height = 0;
+   format = 0;
+   use = 0;
+   for (i = 0; attr_list[i] != EGL_NONE; i++) {
+      EGLint attr = attr_list[i++];
+      EGLint val = attr_list[i];
+
+      switch (attr) {
+      case EGL_WIDTH:
+        width = val;
+         break;
+      case EGL_HEIGHT:
+        height = val;
+         break;
+      case EGL_DRM_BUFFER_FORMAT_MESA:
+        format = val;
+         break;
+      case EGL_DRM_BUFFER_USE_MESA:
+        use = val;
+         break;
+      default:
+         err = EGL_BAD_ATTRIBUTE;
+         break;
+      }
+
+      if (err != EGL_SUCCESS) {
+         _eglLog(_EGL_WARNING, "bad image attribute 0x%04x", attr);
+        goto cleanup_img;
+      }
+   }
+
+   if (width <= 0 || height <= 0) {
+      _eglLog(_EGL_WARNING, "bad width or height (%dx%d)", width, height);
+      goto cleanup_img;
+   }
+
+   switch (format) {
+   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
+      format = __DRI_IMAGE_FORMAT_ARGB8888;
+      break;
+   default:
+      _eglLog(_EGL_WARNING, "bad image format value 0x%04x", format);
+      goto cleanup_img;
+   }
+
+   valid_mask =
+      EGL_DRM_BUFFER_USE_SCANOUT_MESA |
+      EGL_DRM_BUFFER_USE_SHARE_MESA; 
+   if (use & ~valid_mask) {
+      _eglLog(_EGL_WARNING, "bad image use bit 0x%04x", use & ~valid_mask);
+      goto cleanup_img;
+   }
+
+   dri_use = 0;
+   if (use & EGL_DRM_BUFFER_USE_SHARE_MESA)
+      dri_use |= __DRI_IMAGE_USE_SHARE;
+   if (use & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
+      dri_use |= __DRI_IMAGE_USE_SCANOUT;
+
+   dri2_img->dri_image = 
+      dri2_dpy->image->createImage(dri2_dpy->dri_screen,
+                                  width, height, format, dri_use, dri2_img);
+   if (dri2_img->dri_image == NULL) {
+      err = EGL_BAD_ALLOC;
+      goto cleanup_img;
+   }
+
+   return &dri2_img->base;
+
+ cleanup_img:
+   free(dri2_img);
+   _eglError(err, "dri2_create_drm_image_mesa");
+
+   return EGL_NO_IMAGE_KHR;
+}
+
+static EGLBoolean
+dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
+                         EGLint *name, EGLint *handle, EGLint *stride)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
+
+   if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
+                                           __DRI_IMAGE_ATTRIB_NAME, name)) {
+      _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
+      return EGL_FALSE;
+   }
+
+   if (handle)
+      dri2_dpy->image->queryImage(dri2_img->dri_image,
+                                 __DRI_IMAGE_ATTRIB_HANDLE, handle);
+
+   if (stride)
+      dri2_dpy->image->queryImage(dri2_img->dri_image,
+                                 __DRI_IMAGE_ATTRIB_STRIDE, stride);
+
+   return EGL_TRUE;
+}
+
 /**
  * This is the main entrypoint into the driver, called by libEGL.
  * Create a new _EGLDriver object and init its dispatch table.
@@ -1681,6 +1902,8 @@ _eglMain(const char *args)
    dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr;
    dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
    dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
+   dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
+   dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
 
    dri2_drv->base.Name = "DRI2";
    dri2_drv->base.Unload = dri2_unload;
index 41d301fc14056b6b3a02f659b354308a1b0f060d..d92fbf6d9a7e854393b66e1bf1478b4523dbb3d8 100644 (file)
@@ -26,7 +26,8 @@ HEADERS = \
        eglmutex.h \
        eglscreen.h \
        eglstring.h \
-       eglsurface.h
+       eglsurface.h \
+       eglsync.h
 
 SOURCES = \
        eglapi.c \
@@ -44,7 +45,8 @@ SOURCES = \
        eglmode.c \
        eglscreen.c \
        eglstring.c \
-       eglsurface.c
+       eglsurface.c \
+       eglsync.c
 
 OBJECTS = $(SOURCES:.c=.o)
 
index 3d7ae3a8e4ebe8c355694538d5aa6cd25e205e8f..06846475baf6ddf082c9158854def68230359c18 100644 (file)
@@ -12,6 +12,7 @@ if env['platform'] != 'winddk':
                '_EGL_NATIVE_PLATFORM=_EGL_PLATFORM_WINDOWS',
                '_EGL_DRIVER_SEARCH_DIR=\\"\\"',
                '_EGL_OS_WINDOWS',
+               '_EGL_GET_CORE_ADDRESSES',
                'KHRONOS_DLL_EXPORTS',
        ])
 
@@ -36,11 +37,12 @@ if env['platform'] != 'winddk':
                'eglscreen.c',
                'eglstring.c',
                'eglsurface.c',
+               'eglsync.c',
        ]
 
        egl = env.SharedLibrary(
                target = 'libEGL',
-               source = egl_sources,
+               source = egl_sources + ['egl.def'],
        )
 
        env.InstallSharedLibrary(egl, version=(1, 4, 0))
diff --git a/src/egl/main/egl.def b/src/egl/main/egl.def
new file mode 100644 (file)
index 0000000..0cfe920
--- /dev/null
@@ -0,0 +1,35 @@
+EXPORTS
+   eglBindAPI
+   eglBindTexImage
+   eglChooseConfig
+   eglCopyBuffers
+   eglCreateContext
+   eglCreatePbufferFromClientBuffer
+   eglCreatePbufferSurface
+   eglCreatePixmapSurface
+   eglCreateWindowSurface
+   eglDestroyContext
+   eglDestroySurface
+   eglGetConfigAttrib
+   eglGetConfigs
+   eglGetCurrentContext
+   eglGetCurrentDisplay
+   eglGetCurrentSurface
+   eglGetDisplay
+   eglGetError
+   eglGetProcAddress
+   eglInitialize
+   eglMakeCurrent
+   eglQueryAPI
+   eglQueryContext
+   eglQueryString
+   eglQuerySurface
+   eglReleaseTexImage
+   eglReleaseThread
+   eglSurfaceAttrib
+   eglSwapBuffers
+   eglSwapInterval
+   eglTerminate
+   eglWaitClient
+   eglWaitGL
+   eglWaitNative
index 4dc8707cfbc66afaaf30bf0862748065823b3491..31c5419bbc3f7b34e0dc9956cd6cadf41781a20b 100644 (file)
@@ -68,6 +68,7 @@
 #include "eglscreen.h"
 #include "eglmode.h"
 #include "eglimage.h"
+#include "eglsync.h"
 
 
 /**
 #define _EGL_CHECK_MODE(disp, m, ret, drv) \
    _EGL_CHECK_OBJECT(disp, Mode, m, ret, drv)
 
+#define _EGL_CHECK_SYNC(disp, s, ret, drv) \
+   _EGL_CHECK_OBJECT(disp, Sync, s, ret, drv)
 
 
 static INLINE _EGLDriver *
@@ -185,6 +188,26 @@ _eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg)
 }
 
 
+#ifdef EGL_KHR_reusable_sync
+
+
+static INLINE _EGLDriver *
+_eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg)
+{
+   _EGLDriver *drv = _eglCheckDisplay(disp, msg);
+   if (!drv)
+      return NULL;
+   if (!s) {
+      _eglError(EGL_BAD_PARAMETER, msg);
+      return NULL;
+   }
+   return drv;
+}
+
+
+#endif /* EGL_KHR_reusable_sync */
+
+
 #ifdef EGL_MESA_screen_surface
 
 
@@ -809,7 +832,44 @@ eglGetProcAddress(const char *procname)
       const char *name;
       _EGLProc function;
    } egl_functions[] = {
-      /* extensions only */
+      /* core functions should not be queryable, but, well... */
+#ifdef _EGL_GET_CORE_ADDRESSES
+      /* alphabetical order */
+      { "eglBindAPI", (_EGLProc) eglBindAPI },
+      { "eglBindTexImage", (_EGLProc) eglBindTexImage },
+      { "eglChooseConfig", (_EGLProc) eglChooseConfig },
+      { "eglCopyBuffers", (_EGLProc) eglCopyBuffers },
+      { "eglCreateContext", (_EGLProc) eglCreateContext },
+      { "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer },
+      { "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface },
+      { "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface },
+      { "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface },
+      { "eglDestroyContext", (_EGLProc) eglDestroyContext },
+      { "eglDestroySurface", (_EGLProc) eglDestroySurface },
+      { "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib },
+      { "eglGetConfigs", (_EGLProc) eglGetConfigs },
+      { "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext },
+      { "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay },
+      { "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface },
+      { "eglGetDisplay", (_EGLProc) eglGetDisplay },
+      { "eglGetError", (_EGLProc) eglGetError },
+      { "eglGetProcAddress", (_EGLProc) eglGetProcAddress },
+      { "eglInitialize", (_EGLProc) eglInitialize },
+      { "eglMakeCurrent", (_EGLProc) eglMakeCurrent },
+      { "eglQueryAPI", (_EGLProc) eglQueryAPI },
+      { "eglQueryContext", (_EGLProc) eglQueryContext },
+      { "eglQueryString", (_EGLProc) eglQueryString },
+      { "eglQuerySurface", (_EGLProc) eglQuerySurface },
+      { "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage },
+      { "eglReleaseThread", (_EGLProc) eglReleaseThread },
+      { "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib },
+      { "eglSwapBuffers", (_EGLProc) eglSwapBuffers },
+      { "eglSwapInterval", (_EGLProc) eglSwapInterval },
+      { "eglTerminate", (_EGLProc) eglTerminate },
+      { "eglWaitClient", (_EGLProc) eglWaitClient },
+      { "eglWaitGL", (_EGLProc) eglWaitGL },
+      { "eglWaitNative", (_EGLProc) eglWaitNative },
+#endif /* _EGL_GET_CORE_ADDRESSES */
 #ifdef EGL_MESA_screen_surface
       { "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA },
       { "eglGetModesMESA", (_EGLProc) eglGetModesMESA },
@@ -833,6 +893,10 @@ eglGetProcAddress(const char *procname)
 #endif /* EGL_KHR_image_base */
 #ifdef EGL_NOK_swap_region
       { "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK },
+#endif
+#ifdef EGL_MESA_drm_image
+      { "eglCreateDRMImageMESA", (_EGLProc) eglCreateDRMImageMESA },
+      { "eglExportDRMImageMESA", (_EGLProc) eglExportDRMImageMESA },
 #endif
       { NULL, NULL }
    };
@@ -1245,6 +1309,90 @@ eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
 #endif /* EGL_KHR_image_base */
 
 
+#ifdef EGL_KHR_reusable_sync
+
+
+EGLSyncKHR EGLAPIENTRY
+eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLDriver *drv;
+   _EGLSync *sync;
+   EGLSyncKHR ret;
+
+   _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
+
+   sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
+   ret = (sync) ? _eglLinkSync(sync, disp) : EGL_NO_SYNC_KHR;
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+
+EGLBoolean EGLAPIENTRY
+eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSync *s = _eglLookupSync(sync, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
+   _eglUnlinkSync(s);
+   ret = drv->API.DestroySyncKHR(drv, disp, s);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+
+EGLint EGLAPIENTRY
+eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSync *s = _eglLookupSync(sync, disp);
+   _EGLDriver *drv;
+   EGLint ret;
+
+   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
+   ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+
+EGLBoolean EGLAPIENTRY
+eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSync *s = _eglLookupSync(sync, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
+   ret = drv->API.SignalSyncKHR(drv, disp, s, mode);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+
+EGLBoolean EGLAPIENTRY
+eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSync *s = _eglLookupSync(sync, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
+   ret = drv->API.GetSyncAttribKHR(drv, disp, s, attribute, value);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+
+#endif /* EGL_KHR_reusable_sync */
+
+
 #ifdef EGL_NOK_swap_region
 
 EGLBoolean EGLAPIENTRY
@@ -1272,3 +1420,42 @@ eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
 }
 
 #endif /* EGL_NOK_swap_region */
+
+
+#ifdef EGL_MESA_drm_image
+
+EGLImageKHR EGLAPIENTRY
+eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLDriver *drv;
+   _EGLImage *img;
+   EGLImageKHR ret;
+
+   _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
+
+   img = drv->API.CreateDRMImageMESA(drv, disp, attr_list);
+   ret = (img) ? _eglLinkImage(img, disp) : EGL_NO_IMAGE_KHR;
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+EGLBoolean EGLAPIENTRY
+eglExportDRMImageMESA(EGLDisplay dpy, EGLImageKHR image,
+                     EGLint *name, EGLint *handle, EGLint *stride)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLImage *img = _eglLookupImage(image, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
+   if (!img)
+      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
+
+   ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+#endif
index d8c8b49a49deef0be9cd7be2531700dd32d17fe0..127becc9acdccebdeb2d22befb907483e5c1f9c0 100644 (file)
@@ -76,10 +76,25 @@ typedef _EGLImage *(*CreateImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLCo
 typedef EGLBoolean (*DestroyImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
 #endif /* EGL_KHR_image_base */
 
+
+#ifdef EGL_KHR_reusable_sync
+typedef _EGLSync *(*CreateSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLenum type, const EGLint *attrib_list);
+typedef EGLBoolean (*DestroySyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync);
+typedef EGLint (*ClientWaitSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, EGLint flags, EGLTimeKHR timeout);
+typedef EGLBoolean (*SignalSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, EGLenum mode);
+typedef EGLBoolean (*GetSyncAttribKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, EGLint attribute, EGLint *value);
+#endif /* EGL_KHR_reusable_sync */
+
+
 #ifdef EGL_NOK_swap_region
 typedef EGLBoolean (*SwapBuffersRegionNOK_t)(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLint numRects, const EGLint *rects);
 #endif
 
+#ifdef EGL_MESA_drm_image
+typedef _EGLImage *(*CreateDRMImageMESA_t)(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attr_list);
+typedef EGLBoolean (*ExportDRMImageMESA_t)(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, EGLint *name, EGLint *handle, EGLint *stride);
+#endif
+
 /**
  * The API dispatcher jumps through these functions
  */
@@ -138,9 +153,22 @@ struct _egl_api
    DestroyImageKHR_t DestroyImageKHR;
 #endif /* EGL_KHR_image_base */
 
+#ifdef EGL_KHR_reusable_sync
+   CreateSyncKHR_t CreateSyncKHR;
+   DestroySyncKHR_t DestroySyncKHR;
+   ClientWaitSyncKHR_t ClientWaitSyncKHR;
+   SignalSyncKHR_t SignalSyncKHR;
+   GetSyncAttribKHR_t GetSyncAttribKHR;
+#endif /* EGL_KHR_reusable_sync */
+
 #ifdef EGL_NOK_swap_region
    SwapBuffersRegionNOK_t SwapBuffersRegionNOK;
 #endif
+
+#ifdef EGL_MESA_drm_image
+   CreateDRMImageMESA_t CreateDRMImageMESA;
+   ExportDRMImageMESA_t ExportDRMImageMESA;
+#endif
 };
 
 #endif /* EGLAPI_INCLUDED */
index ea8e47d02bbc4c105c299c275235bfa988301b4c..01e7144d40abd6c7a6701b578e1cbdb58aa408a2 100644 (file)
@@ -460,11 +460,14 @@ _eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria)
       }
 
       if (!matched) {
-#ifdef DEBUG
+#ifndef DEBUG
+         /* only print the common errors when DEBUG is not defined */
+         if (attr != EGL_RENDERABLE_TYPE)
+            break;
+#endif
          _eglLog(_EGL_DEBUG,
                "the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)",
                val, attr, cmp);
-#endif
          break;
       }
    }
index 9fc529613e587a13e67354400c0a56d3e9516cbe..e72664c23ccbf1b41d355141f5cc8e8f90535dcd 100644 (file)
@@ -83,15 +83,6 @@ _eglParseContextAttribList(_EGLContext *ctx, const EGLint *attrib_list)
       }
    }
 
-   if (err == EGL_SUCCESS && ctx->Config) {
-      EGLint renderable_type, api_bit;
-
-      renderable_type = GET_CONFIG_ATTRIB(ctx->Config, EGL_RENDERABLE_TYPE);
-      api_bit = _eglGetContextAPIBit(ctx);
-      if (!(renderable_type & api_bit))
-         err = EGL_BAD_CONFIG;
-   }
-
    return err;
 }
 
@@ -121,6 +112,17 @@ _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
    ctx->ClientVersion = 1; /* the default, per EGL spec */
 
    err = _eglParseContextAttribList(ctx, attrib_list);
+   if (err == EGL_SUCCESS && ctx->Config) {
+      EGLint renderable_type, api_bit;
+
+      renderable_type = GET_CONFIG_ATTRIB(ctx->Config, EGL_RENDERABLE_TYPE);
+      api_bit = _eglGetContextAPIBit(ctx);
+      if (!(renderable_type & api_bit)) {
+         _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
+               api_bit, renderable_type);
+         err = EGL_BAD_CONFIG;
+      }
+   }
    if (err != EGL_SUCCESS)
       return _eglError(err, "eglCreateContext");
 
index a2cee08bf6f76d07b1702b9abf0e84ab17e59b45..3863cce0108f99724a06040920d8b99491bbf5db 100644 (file)
@@ -24,6 +24,7 @@ enum _egl_resource_type {
    _EGL_RESOURCE_CONTEXT,
    _EGL_RESOURCE_SURFACE,
    _EGL_RESOURCE_IMAGE,
+   _EGL_RESOURCE_SYNC,
 
    _EGL_NUM_RESOURCES
 };
@@ -53,6 +54,8 @@ struct _egl_extensions
    EGLBoolean MESA_screen_surface;
    EGLBoolean MESA_copy_context;
    EGLBoolean MESA_drm_display;
+   EGLBoolean MESA_drm_image;
+
    EGLBoolean KHR_image_base;
    EGLBoolean KHR_image_pixmap;
    EGLBoolean KHR_vg_parent_image;
@@ -60,9 +63,14 @@ struct _egl_extensions
    EGLBoolean KHR_gl_texture_cubemap_image;
    EGLBoolean KHR_gl_texture_3D_image;
    EGLBoolean KHR_gl_renderbuffer_image;
+
+   EGLBoolean KHR_reusable_sync;
+   EGLBoolean KHR_fence_sync;
+
    EGLBoolean KHR_surfaceless_gles1;
    EGLBoolean KHR_surfaceless_gles2;
    EGLBoolean KHR_surfaceless_opengl;
+
    EGLBoolean NOK_swap_region;
    EGLBoolean NOK_texture_from_pixmap;
 
index 8fc9e792b061f533c0591967c2689103f7515e56..67f1d3dbaa4d3041559be59b4fc7b8756c60168d 100644 (file)
@@ -21,6 +21,7 @@
 #include "eglstring.h"
 #include "eglsurface.h"
 #include "eglimage.h"
+#include "eglsync.h"
 #include "eglmutex.h"
 
 #if defined(_EGL_OS_UNIX)
@@ -722,6 +723,14 @@ _eglInitDriverFallbacks(_EGLDriver *drv)
    drv->API.CreateImageKHR = _eglCreateImageKHR;
    drv->API.DestroyImageKHR = _eglDestroyImageKHR;
 #endif /* EGL_KHR_image_base */
+
+#ifdef EGL_KHR_reusable_sync
+   drv->API.CreateSyncKHR = _eglCreateSyncKHR;
+   drv->API.DestroySyncKHR = _eglDestroySyncKHR;
+   drv->API.ClientWaitSyncKHR = _eglClientWaitSyncKHR;
+   drv->API.SignalSyncKHR = _eglSignalSyncKHR;
+   drv->API.GetSyncAttribKHR = _eglGetSyncAttribKHR;
+#endif /* EGL_KHR_reusable_sync */
 }
 
 
index 985d1e0069d723f6d3571de77c930e34bbfb3427..eb3dde1fb485ad355809db98e83093eaec31b3e9 100644 (file)
@@ -85,6 +85,7 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
    _EGL_CHECK_EXTENSION(MESA_screen_surface);
    _EGL_CHECK_EXTENSION(MESA_copy_context);
    _EGL_CHECK_EXTENSION(MESA_drm_display);
+   _EGL_CHECK_EXTENSION(MESA_drm_image);
 
    _EGL_CHECK_EXTENSION(KHR_image_base);
    _EGL_CHECK_EXTENSION(KHR_image_pixmap);
@@ -97,6 +98,9 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
    _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image);
    _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
 
+   _EGL_CHECK_EXTENSION(KHR_reusable_sync);
+   _EGL_CHECK_EXTENSION(KHR_fence_sync);
+
    _EGL_CHECK_EXTENSION(KHR_surfaceless_gles1);
    _EGL_CHECK_EXTENSION(KHR_surfaceless_gles2);
    _EGL_CHECK_EXTENSION(KHR_surfaceless_opengl);
diff --git a/src/egl/main/eglsync.c b/src/egl/main/eglsync.c
new file mode 100644 (file)
index 0000000..b6c62d0
--- /dev/null
@@ -0,0 +1,128 @@
+#include <string.h>
+
+#include "eglsync.h"
+#include "eglcurrent.h"
+#include "egllog.h"
+
+
+#ifdef EGL_KHR_reusable_sync
+
+
+/**
+ * Parse the list of sync attributes and return the proper error code.
+ */
+static EGLint
+_eglParseSyncAttribList(_EGLSync *sync, const EGLint *attrib_list)
+{
+   EGLint i, err = EGL_SUCCESS;
+
+   if (!attrib_list)
+      return EGL_SUCCESS;
+
+   for (i = 0; attrib_list[i] != EGL_NONE; i++) {
+      EGLint attr = attrib_list[i++];
+      EGLint val = attrib_list[i];
+
+      switch (attr) {
+      default:
+         (void) val;
+         err = EGL_BAD_ATTRIBUTE;
+         break;
+      }
+
+      if (err != EGL_SUCCESS) {
+         _eglLog(_EGL_DEBUG, "bad sync attribute 0x%04x", attr);
+         break;
+      }
+   }
+
+   return err;
+}
+
+
+EGLBoolean
+_eglInitSync(_EGLSync *sync, _EGLDisplay *dpy, EGLenum type,
+             const EGLint *attrib_list)
+{
+   EGLint err;
+
+   if (!(type == EGL_SYNC_REUSABLE_KHR && dpy->Extensions.KHR_reusable_sync) &&
+       !(type == EGL_SYNC_FENCE_KHR && dpy->Extensions.KHR_fence_sync))
+      return _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
+
+   memset(sync, 0, sizeof(*sync));
+
+   sync->Resource.Display = dpy;
+
+   sync->Type = type;
+   sync->SyncStatus = EGL_UNSIGNALED_KHR;
+   sync->SyncCondition = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
+
+   err = _eglParseSyncAttribList(sync, attrib_list);
+   if (err != EGL_SUCCESS)
+      return _eglError(err, "eglCreateSyncKHR");
+
+   return EGL_TRUE;
+}
+
+
+_EGLSync *
+_eglCreateSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy,
+                  EGLenum type, const EGLint *attrib_list)
+{
+   return NULL;
+}
+
+
+EGLBoolean
+_eglDestroySyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync)
+{
+   return EGL_TRUE;
+}
+
+
+EGLint
+_eglClientWaitSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                      EGLint flags, EGLTimeKHR timeout)
+{
+   return EGL_FALSE;
+}
+
+
+EGLBoolean
+_eglSignalSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                  EGLenum mode)
+{
+   return EGL_FALSE;
+}
+
+
+EGLBoolean
+_eglGetSyncAttribKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                     EGLint attribute, EGLint *value)
+{
+   if (!value)
+      return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs");
+
+   switch (attribute) {
+   case EGL_SYNC_TYPE_KHR:
+      *value = sync->Type;
+      break;
+   case EGL_SYNC_STATUS_KHR:
+      *value = sync->SyncStatus;
+      break;
+   case EGL_SYNC_CONDITION_KHR:
+      if (sync->Type != EGL_SYNC_FENCE_KHR)
+         return _eglError(EGL_BAD_ATTRIBUTE, "eglGetSyncAttribKHR");
+      *value = sync->SyncCondition;
+      break;
+   default:
+      return _eglError(EGL_BAD_ATTRIBUTE, "eglGetSyncAttribKHR");
+      break;
+   }
+
+   return EGL_TRUE;
+}
+
+
+#endif /* EGL_KHR_reusable_sync */
diff --git a/src/egl/main/eglsync.h b/src/egl/main/eglsync.h
new file mode 100644 (file)
index 0000000..25c4671
--- /dev/null
@@ -0,0 +1,120 @@
+#ifndef EGLSYNC_INCLUDED
+#define EGLSYNC_INCLUDED
+
+
+#include "egltypedefs.h"
+#include "egldisplay.h"
+
+
+#ifdef EGL_KHR_reusable_sync
+
+
+/**
+ * "Base" class for device driver syncs.
+ */
+struct _egl_sync
+{
+   /* A sync is a display resource */
+   _EGLResource Resource;
+
+   EGLenum Type;
+   EGLenum SyncStatus;
+   EGLenum SyncCondition;
+};
+
+
+PUBLIC EGLBoolean
+_eglInitSync(_EGLSync *sync, _EGLDisplay *dpy, EGLenum type,
+             const EGLint *attrib_list);
+
+
+extern _EGLSync *
+_eglCreateSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy,
+                  EGLenum type, const EGLint *attrib_list);
+
+
+extern EGLBoolean
+_eglDestroySyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync);
+
+
+extern EGLint
+_eglClientWaitSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                      EGLint flags, EGLTimeKHR timeout);
+
+
+extern EGLBoolean
+_eglSignalSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                  EGLenum mode);
+
+
+extern EGLBoolean
+_eglGetSyncAttribKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                     EGLint attribute, EGLint *value);
+
+
+/**
+ * Link a sync to a display and return the handle of the link.
+ * The handle can be passed to client directly.
+ */
+static INLINE EGLSyncKHR
+_eglLinkSync(_EGLSync *sync, _EGLDisplay *dpy)
+{
+   _eglLinkResource(&sync->Resource, _EGL_RESOURCE_SYNC, dpy);
+   return (EGLSyncKHR) sync;
+}
+
+
+/**
+ * Unlink a linked sync from its display.
+ */
+static INLINE void
+_eglUnlinkSync(_EGLSync *sync)
+{
+   _eglUnlinkResource(&sync->Resource, _EGL_RESOURCE_SYNC);
+}
+
+
+/**
+ * Lookup a handle to find the linked sync.
+ * Return NULL if the handle has no corresponding linked sync.
+ */
+static INLINE _EGLSync *
+_eglLookupSync(EGLSyncKHR handle, _EGLDisplay *dpy)
+{
+   _EGLSync *sync = (_EGLSync *) handle;
+   if (!dpy || !_eglCheckResource((void *) sync, _EGL_RESOURCE_SYNC, dpy))
+      sync = NULL;
+   return sync;
+}
+
+
+/**
+ * Return the handle of a linked sync, or EGL_NO_SYNC_KHR.
+ */
+static INLINE EGLSyncKHR
+_eglGetSyncHandle(_EGLSync *sync)
+{
+   _EGLResource *res = (_EGLResource *) sync;
+   return (res && _eglIsResourceLinked(res)) ?
+      (EGLSyncKHR) sync : EGL_NO_SYNC_KHR;
+}
+
+
+/**
+ * Return true if the sync is linked to a display.
+ *
+ * The link is considered a reference to the sync (the display is owning the
+ * sync).  Drivers should not destroy a sync when it is linked.
+ */
+static INLINE EGLBoolean
+_eglIsSyncLinked(_EGLSync *sync)
+{
+   _EGLResource *res = (_EGLResource *) sync;
+   return (res && _eglIsResourceLinked(res));
+}
+
+
+#endif /* EGL_KHR_reusable_sync */
+
+
+#endif /* EGLSYNC_INCLUDED */
index 0e29e9aa47e9148a152a17228112cb99446d64ad..b65f3b72ae558205fb29b118ddecf9857393f13f 100644 (file)
@@ -32,6 +32,8 @@ typedef struct _egl_screen _EGLScreen;
 
 typedef struct _egl_surface _EGLSurface;
 
+typedef struct _egl_sync _EGLSync;
+
 typedef struct _egl_thread_info _EGLThreadInfo;
 
 #endif /* EGLTYPEDEFS_INCLUDED */
index 9544e90a965435b45def52a39691ba0fac753304..eb86d83d2a2c7cfeb34d907a8c890434e3554a51 100644 (file)
@@ -4,8 +4,8 @@ include $(TOP)/configs/current
 LIBNAME = gallium
 
 C_SOURCES = \
-       cso_cache/cso_context.c \
        cso_cache/cso_cache.c \
+       cso_cache/cso_context.c \
        cso_cache/cso_hash.c \
        draw/draw_context.c \
        draw/draw_gs.c \
@@ -26,7 +26,6 @@ C_SOURCES = \
        draw/draw_pipe_wide_line.c \
        draw/draw_pipe_wide_point.c \
        draw/draw_pt.c \
-       draw/draw_pt_elts.c \
        draw/draw_pt_emit.c \
        draw/draw_pt_fetch.c \
        draw/draw_pt_fetch_emit.c \
@@ -35,24 +34,24 @@ C_SOURCES = \
        draw/draw_pt_post_vs.c \
        draw/draw_pt_so_emit.c \
        draw/draw_pt_util.c \
-       draw/draw_pt_varray.c \
-       draw/draw_pt_vcache.c \
+       draw/draw_pt_vsplit.c \
        draw/draw_vertex.c \
        draw/draw_vs.c \
-       draw/draw_vs_varient.c \
        draw/draw_vs_aos.c \
        draw/draw_vs_aos_io.c \
        draw/draw_vs_aos_machine.c \
        draw/draw_vs_exec.c \
        draw/draw_vs_ppc.c \
        draw/draw_vs_sse.c \
+       draw/draw_vs_varient.c \
        indices/u_indices_gen.c \
        indices/u_unfilled_gen.c \
        os/os_misc.c \
+       os/os_stream.c \
        os/os_stream_log.c \
+       os/os_stream_null.c \
        os/os_stream_stdc.c \
        os/os_stream_str.c \
-       os/os_stream_null.c \
        os/os_time.c \
        pipebuffer/pb_buffer_fenced.c \
        pipebuffer/pb_buffer_malloc.c \
@@ -65,17 +64,16 @@ C_SOURCES = \
        pipebuffer/pb_bufmgr_slab.c \
        pipebuffer/pb_validate.c \
        rbug/rbug_connection.c \
+       rbug/rbug_context.c \
        rbug/rbug_core.c \
+       rbug/rbug_demarshal.c \
        rbug/rbug_texture.c \
-       rbug/rbug_context.c \
        rbug/rbug_shader.c \
-       rbug/rbug_demarshal.c \
        rtasm/rtasm_cpu.c \
        rtasm/rtasm_execmem.c \
-       rtasm/rtasm_x86sse.c \
        rtasm/rtasm_ppc.c \
        rtasm/rtasm_ppc_spe.c \
-       tgsi/tgsi_sanity.c \
+       rtasm/rtasm_x86sse.c \
        tgsi/tgsi_build.c \
        tgsi/tgsi_dump.c \
        tgsi/tgsi_exec.c \
@@ -83,19 +81,22 @@ C_SOURCES = \
        tgsi/tgsi_iterate.c \
        tgsi/tgsi_parse.c \
        tgsi/tgsi_ppc.c \
+       tgsi/tgsi_sanity.c \
        tgsi/tgsi_scan.c \
        tgsi/tgsi_sse2.c \
        tgsi/tgsi_text.c \
        tgsi/tgsi_transform.c \
        tgsi/tgsi_ureg.c \
        tgsi/tgsi_util.c \
-       translate/translate_generic.c \
-       translate/translate_sse.c \
        translate/translate.c \
        translate/translate_cache.c \
+       translate/translate_generic.c \
+       translate/translate_sse.c \
        util/u_debug.c \
-       util/u_debug_symbol.c \
+       util/u_debug_describe.c \
+       util/u_debug_refcnt.c \
        util/u_debug_stack.c \
+       util/u_debug_symbol.c \
        util/u_dump_defines.c \
        util/u_dump_state.c \
        util/u_bitmask.c \
@@ -118,10 +119,11 @@ C_SOURCES = \
        util/u_gen_mipmap.c \
        util/u_half.c \
        util/u_handle_table.c \
-       util/u_hash_table.c \
        util/u_hash.c \
+       util/u_hash_table.c \
        util/u_keymap.c \
        util/u_linear.c \
+       util/u_linkage.c \
        util/u_network.c \
        util/u_math.c \
        util/u_mempool.c \
@@ -172,10 +174,10 @@ GALLIVM_SOURCES = \
         gallivm/lp_bld_tgsi_soa.c \
         gallivm/lp_bld_type.c \
         draw/draw_llvm.c \
-        draw/draw_vs_llvm.c \
-        draw/draw_pt_fetch_shade_pipeline_llvm.c \
+        draw/draw_llvm_sample.c \
         draw/draw_llvm_translate.c \
-        draw/draw_llvm_sample.c
+        draw/draw_vs_llvm.c \
+        draw/draw_pt_fetch_shade_pipeline_llvm.c
 
 GALLIVM_CPP_SOURCES = \
     gallivm/lp_bld_misc.cpp
index 3124e20ce847a76f9ef6de4f03a0373756f0d0cc..6210ada990ed2bb75eae626fd344cc7303093dd6 100644 (file)
@@ -50,10 +50,11 @@ env.Depends('util/u_format_table.c', [
 ])
 
 source = [
-    'cso_cache/cso_context.c',
     'cso_cache/cso_cache.c',
+    'cso_cache/cso_context.c',
     'cso_cache/cso_hash.c',
     'draw/draw_context.c',
+    'draw/draw_gs.c',
     'draw/draw_pipe.c',
     'draw/draw_pipe_aaline.c',
     'draw/draw_pipe_aapoint.c',
@@ -71,7 +72,6 @@ source = [
     'draw/draw_pipe_wide_line.c',
     'draw/draw_pipe_wide_point.c',
     'draw/draw_pt.c',
-    'draw/draw_pt_elts.c',
     'draw/draw_pt_emit.c',
     'draw/draw_pt_fetch.c',
     'draw/draw_pt_fetch_emit.c',
@@ -80,8 +80,7 @@ source = [
     'draw/draw_pt_post_vs.c',
     'draw/draw_pt_so_emit.c',
     'draw/draw_pt_util.c',
-    'draw/draw_pt_varray.c',
-    'draw/draw_pt_vcache.c',
+    'draw/draw_pt_vsplit.c',
     'draw/draw_vertex.c',
     'draw/draw_vs.c',
     'draw/draw_vs_aos.c',
@@ -91,16 +90,16 @@ source = [
     'draw/draw_vs_ppc.c',
     'draw/draw_vs_sse.c',
     'draw/draw_vs_varient.c',
-    'draw/draw_gs.c',
     #'indices/u_indices.c',
     #'indices/u_unfilled_indices.c',
     'indices/u_indices_gen.c',
     'indices/u_unfilled_gen.c',
     'os/os_misc.c',
+    'os/os_stream.c',
     'os/os_stream_log.c',
+    'os/os_stream_null.c',
     'os/os_stream_stdc.c',
     'os/os_stream_str.c',
-    'os/os_stream_null.c',
     'os/os_time.c',
     'pipebuffer/pb_buffer_fenced.c',
     'pipebuffer/pb_buffer_malloc.c',
@@ -112,35 +111,35 @@ source = [
     'pipebuffer/pb_bufmgr_pool.c',
     'pipebuffer/pb_bufmgr_slab.c',
     'pipebuffer/pb_validate.c',
+    'rbug/rbug_connection.c',
+    'rbug/rbug_context.c',
     'rbug/rbug_core.c',
+    'rbug/rbug_demarshal.c',
     'rbug/rbug_shader.c',
-    'rbug/rbug_context.c',
     'rbug/rbug_texture.c',
-    'rbug/rbug_demarshal.c',
-    'rbug/rbug_connection.c',
     'rtasm/rtasm_cpu.c',
     'rtasm/rtasm_execmem.c',
-    'rtasm/rtasm_x86sse.c',
     'rtasm/rtasm_ppc.c',
     'rtasm/rtasm_ppc_spe.c',
+    'rtasm/rtasm_x86sse.c',
     'tgsi/tgsi_build.c',
     'tgsi/tgsi_dump.c',
     'tgsi/tgsi_exec.c',
     'tgsi/tgsi_info.c',
     'tgsi/tgsi_iterate.c',
     'tgsi/tgsi_parse.c',
+    'tgsi/tgsi_ppc.c',
     'tgsi/tgsi_sanity.c',
     'tgsi/tgsi_scan.c',
-    'tgsi/tgsi_ppc.c',
     'tgsi/tgsi_sse2.c',
     'tgsi/tgsi_text.c',
     'tgsi/tgsi_transform.c',
     'tgsi/tgsi_ureg.c',
     'tgsi/tgsi_util.c',
-    'translate/translate_generic.c',
-    'translate/translate_sse.c',
     'translate/translate.c',
     'translate/translate_cache.c',
+    'translate/translate_generic.c',
+    'translate/translate_sse.c',
     'util/u_bitmask.c',
     'util/u_blit.c',
     'util/u_blitter.c',
@@ -148,7 +147,9 @@ source = [
     'util/u_caps.c',
     'util/u_cpu_detect.c',
     'util/u_debug.c',
+    'util/u_debug_describe.c',
     'util/u_debug_memory.c',
+    'util/u_debug_refcnt.c',
     'util/u_debug_stack.c',
     'util/u_debug_symbol.c',
     'util/u_dump_defines.c',
@@ -170,6 +171,8 @@ source = [
     'util/u_hash.c',
     'util/u_hash_table.c',
     'util/u_keymap.c',
+    'util/u_linear.c',
+    'util/u_linkage.c',
     'util/u_network.c',
     'util/u_math.c',
     'util/u_mempool.c',
@@ -208,9 +211,9 @@ if env['llvm']:
     'gallivm/lp_bld_format_soa.c',
     'gallivm/lp_bld_format_yuv.c',
     'gallivm/lp_bld_gather.c',
+    'gallivm/lp_bld_init.c',
     'gallivm/lp_bld_intr.c',
     'gallivm/lp_bld_logic.c',
-    'gallivm/lp_bld_init.c',
     'gallivm/lp_bld_misc.cpp',
     'gallivm/lp_bld_pack.c',
     'gallivm/lp_bld_printf.c',
@@ -222,10 +225,10 @@ if env['llvm']:
     'gallivm/lp_bld_tgsi_soa.c',
     'gallivm/lp_bld_type.c',
     'draw/draw_llvm.c',
-    'draw/draw_pt_fetch_shade_pipeline_llvm.c',
+    'draw/draw_llvm_sample.c',
     'draw/draw_llvm_translate.c',
-    'draw/draw_vs_llvm.c',
-    'draw/draw_llvm_sample.c'
+    'draw/draw_pt_fetch_shade_pipeline_llvm.c',
+    'draw/draw_vs_llvm.c'
     ]
 
 gallium = env.ConvenienceLibrary(
diff --git a/src/gallium/auxiliary/draw/draw_cliptest_tmp.h b/src/gallium/auxiliary/draw/draw_cliptest_tmp.h
new file mode 100644 (file)
index 0000000..958ed20
--- /dev/null
@@ -0,0 +1,114 @@
+/**************************************************************************
+ * 
+ * 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.
+ * 
+ **************************************************************************/
+
+
+
+static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
+                                 struct draw_vertex_info *info )
+{
+   struct vertex_header *out = info->verts;
+   const float *scale = pvs->draw->viewport.scale;
+   const float *trans = pvs->draw->viewport.translate;
+   /* const */ float (*plane)[4] = pvs->draw->plane;
+   const unsigned pos = draw_current_shader_position_output(pvs->draw);
+   const unsigned ef = pvs->draw->vs.edgeflag_output;
+   const unsigned nr = pvs->draw->nr_planes;
+   const unsigned flags = (FLAGS);
+   unsigned need_pipeline = 0;
+   unsigned j;
+
+   for (j = 0; j < info->count; j++) {
+      float *position = out->data[pos];
+      unsigned mask = 0x0;
+  
+      initialize_vertex_header(out);
+
+      if (flags & (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_HALF_Z | DO_CLIP_USER)) {
+         out->clip[0] = position[0];
+         out->clip[1] = position[1];
+         out->clip[2] = position[2];
+         out->clip[3] = position[3];
+
+         /* Do the hardwired planes first:
+          */
+         if (flags & DO_CLIP_XY) {
+            if (-position[0] + position[3] < 0) mask |= (1<<0);
+            if ( position[0] + position[3] < 0) mask |= (1<<1);
+            if (-position[1] + position[3] < 0) mask |= (1<<2);
+            if ( position[1] + position[3] < 0) mask |= (1<<3);
+         }
+
+         /* Clip Z planes according to full cube, half cube or none.
+          */
+         if (flags & DO_CLIP_FULL_Z) {
+            if ( position[2] + position[3] < 0) mask |= (1<<4);
+            if (-position[2] + position[3] < 0) mask |= (1<<5);
+         }
+         else if (flags & DO_CLIP_HALF_Z) {
+            if ( position[2]               < 0) mask |= (1<<4);
+            if (-position[2] + position[3] < 0) mask |= (1<<5);
+         }
+
+         if (flags & DO_CLIP_USER) {
+            unsigned i;
+            for (i = 6; i < nr; i++) {
+               if (dot4(position, plane[i]) < 0) 
+                  mask |= (1<<i);
+            }
+         }
+
+         out->clipmask = mask;
+         need_pipeline |= out->clipmask;
+      }
+
+      if ((flags & DO_VIEWPORT) && mask == 0)
+      {
+        /* divide by w */
+        float w = 1.0f / position[3];
+
+        /* Viewport mapping */
+        position[0] = position[0] * w * scale[0] + trans[0];
+        position[1] = position[1] * w * scale[1] + trans[1];
+        position[2] = position[2] * w * scale[2] + trans[2];
+        position[3] = w;
+      }
+
+      if ((flags & DO_EDGEFLAG) && ef) {
+         const float *edgeflag = out->data[ef];
+         out->edgeflag = !(edgeflag[0] != 1.0f);
+         need_pipeline |= !out->edgeflag;
+      }
+
+      out = (struct vertex_header *)( (char *)out + info->stride );
+   }
+
+   return need_pipeline != 0;
+}
+
+
+#undef FLAGS
+#undef TAG
index 995b675b9a16b856be9f000499e48a267714074a..937b0934798ce48b7bf2d0853c53c324860f7fb3 100644 (file)
@@ -34,6 +34,7 @@
 #include "pipe/p_context.h"
 #include "util/u_memory.h"
 #include "util/u_math.h"
+#include "util/u_cpu_detect.h"
 #include "draw_context.h"
 #include "draw_vs.h"
 #include "draw_gs.h"
 #if HAVE_LLVM
 #include "gallivm/lp_bld_init.h"
 #include "draw_llvm.h"
+
+static boolean
+draw_get_option_use_llvm(void)
+{
+   static boolean first = TRUE;
+   static boolean value;
+   if (first) {
+      first = FALSE;
+      value = debug_get_bool_option("DRAW_USE_LLVM", TRUE);
+
+#ifdef PIPE_ARCH_X86
+      util_cpu_detect();
+      /* require SSE2 due to LLVM PR6960. */
+      if (!util_cpu_caps.has_sse2)
+         value = FALSE;
+#endif
+   }
+   return value;
+}
 #endif
 
 struct draw_context *draw_create( struct pipe_context *pipe )
@@ -50,10 +70,13 @@ struct draw_context *draw_create( struct pipe_context *pipe )
       goto fail;
 
 #if HAVE_LLVM
-   lp_build_init();
-   assert(lp_build_engine);
-   draw->engine = lp_build_engine;
-   draw->llvm = draw_llvm_create(draw);
+   if(draw_get_option_use_llvm())
+   {
+      lp_build_init();
+      assert(lp_build_engine);
+      draw->engine = lp_build_engine;
+      draw->llvm = draw_llvm_create(draw);
+   }
 #endif
 
    if (!draw_init(draw))
@@ -83,6 +106,8 @@ boolean draw_init(struct draw_context *draw)
    ASSIGN_4V( draw->plane[4],  0,  0,  1, 1 ); /* yes these are correct */
    ASSIGN_4V( draw->plane[5],  0,  0, -1, 1 ); /* mesa's a bit wonky */
    draw->nr_planes = 6;
+   draw->clip_xy = 1;
+   draw->clip_z = 1;
 
 
    draw->reduced_prim = ~0; /* != any of PIPE_PRIM_x */
@@ -135,7 +160,8 @@ void draw_destroy( struct draw_context *draw )
    draw_vs_destroy( draw );
    draw_gs_destroy( draw );
 #ifdef HAVE_LLVM
-   draw_llvm_destroy( draw->llvm );
+   if(draw->llvm)
+      draw_llvm_destroy( draw->llvm );
 #endif
 
    FREE( draw );
@@ -162,6 +188,14 @@ void draw_set_mrd(struct draw_context *draw, double mrd)
 }
 
 
+static void update_clip_flags( struct draw_context *draw )
+{
+   draw->clip_xy = !draw->driver.bypass_clip_xy;
+   draw->clip_z = (!draw->driver.bypass_clip_z &&
+                   !draw->depth_clamp);
+   draw->clip_user = (draw->nr_planes > 6);
+}
+
 /**
  * Register new primitive rasterization/rendering state.
  * This causes the drawing pipeline to be rebuilt.
@@ -176,18 +210,25 @@ void draw_set_rasterizer_state( struct draw_context *draw,
       draw->rasterizer = raster;
       draw->rast_handle = rast_handle;
 
-      draw->bypass_clipping = draw->driver.bypass_clipping;
-   }
+  }
 }
 
-
+/* With a little more work, llvmpipe will be able to turn this off and
+ * do its own x/y clipping.  
+ *
+ * Some hardware can turn off clipping altogether - in particular any
+ * hardware with a TNL unit can do its own clipping, even if it is
+ * relying on the draw module for some other reason.
+ */
 void draw_set_driver_clipping( struct draw_context *draw,
-                               boolean bypass_clipping )
+                               boolean bypass_clip_xy,
+                               boolean bypass_clip_z )
 {
    draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
 
-   draw->driver.bypass_clipping = bypass_clipping;
-   draw->bypass_clipping = draw->driver.bypass_clipping;
+   draw->driver.bypass_clip_xy = bypass_clip_xy;
+   draw->driver.bypass_clip_z = bypass_clip_z;
+   update_clip_flags(draw);
 }
 
 
@@ -217,6 +258,8 @@ void draw_set_clip_state( struct draw_context *draw,
    memcpy(&draw->plane[6], clip->ucp, clip->nr * sizeof(clip->ucp[0]));
    draw->nr_planes = 6 + clip->nr;
    draw->depth_clamp = clip->depth_clamp;
+
+   update_clip_flags(draw);
 }
 
 
@@ -472,47 +515,28 @@ void draw_set_render( struct draw_context *draw,
 }
 
 
-
-/**
- * Tell the drawing context about the index/element buffer to use
- * (ala glDrawElements)
- * If no element buffer is to be used (i.e. glDrawArrays) then this
- * should be called with eltSize=0 and elements=NULL.
- *
- * \param draw  the drawing context
- * \param eltSize  size of each element (1, 2 or 4 bytes)
- * \param elements  the element buffer ptr
- */
 void
-draw_set_mapped_element_buffer_range( struct draw_context *draw,
-                                      unsigned eltSize,
-                                      int eltBias,
-                                      unsigned min_index,
-                                      unsigned max_index,
-                                      const void *elements )
+draw_set_index_buffer(struct draw_context *draw,
+                      const struct pipe_index_buffer *ib)
 {
-   draw->pt.user.elts = elements;
-   draw->pt.user.eltSize = eltSize;
-   draw->pt.user.eltBias = eltBias;
-   draw->pt.user.min_index = min_index;
-   draw->pt.user.max_index = max_index;
+   if (ib)
+      memcpy(&draw->pt.index_buffer, ib, sizeof(draw->pt.index_buffer));
+   else
+      memset(&draw->pt.index_buffer, 0, sizeof(draw->pt.index_buffer));
 }
 
 
+/**
+ * Tell drawing context where to find mapped index/element buffer.
+ */
 void
-draw_set_mapped_element_buffer( struct draw_context *draw,
-                                unsigned eltSize,
-                                int eltBias,
-                                const void *elements )
+draw_set_mapped_index_buffer(struct draw_context *draw,
+                             const void *elements)
 {
-   draw->pt.user.elts = elements;
-   draw->pt.user.eltSize = eltSize;
-   draw->pt.user.eltBias = eltBias;
-   draw->pt.user.min_index = 0;
-   draw->pt.user.max_index = 0xffffffff;
+    draw->pt.user.elts = elements;
 }
 
+
 /* Revamp me please:
  */
 void draw_do_flush( struct draw_context *draw, unsigned flags )
@@ -659,7 +683,8 @@ draw_set_mapped_texture(struct draw_context *draw,
                         const void *data[DRAW_MAX_TEXTURE_LEVELS])
 {
 #ifdef HAVE_LLVM
-   draw_llvm_set_mapped_texture(draw,
+   if(draw->llvm)
+      draw_llvm_set_mapped_texture(draw,
                                 sampler_idx,
                                 width, height, depth, last_level,
                                 row_stride, img_stride, data);
index 116716af6f0aa65a07b8ba0ba7df6e9163d7bd32..4c780e4dcb4dc646e52966496ceefb87b8627c75 100644 (file)
@@ -160,18 +160,11 @@ void draw_set_vertex_elements(struct draw_context *draw,
                              unsigned count,
                               const struct pipe_vertex_element *elements);
 
-void
-draw_set_mapped_element_buffer_range( struct draw_context *draw,
-                                      unsigned eltSize,
-                                      int eltBias,
-                                      unsigned min_index,
-                                      unsigned max_index,
-                                      const void *elements );
-
-void draw_set_mapped_element_buffer( struct draw_context *draw,
-                                     unsigned eltSize, 
-                                     int eltBias,
-                                     const void *elements );
+void draw_set_index_buffer(struct draw_context *draw,
+                           const struct pipe_index_buffer *ib);
+
+void draw_set_mapped_index_buffer(struct draw_context *draw,
+                                  const void *elements);
 
 void draw_set_mapped_vertex_buffer(struct draw_context *draw,
                                    unsigned attr, const void *buffer);
@@ -196,6 +189,9 @@ draw_set_so_state(struct draw_context *draw,
  * draw_pt.c 
  */
 
+void draw_vbo(struct draw_context *draw,
+              const struct pipe_draw_info *info);
+
 void draw_arrays(struct draw_context *draw, unsigned prim,
                 unsigned start, unsigned count);
 
@@ -216,7 +212,8 @@ void draw_set_render( struct draw_context *draw,
                      struct vbuf_render *render );
 
 void draw_set_driver_clipping( struct draw_context *draw,
-                               boolean bypass_clipping );
+                               boolean bypass_clip_xy,
+                               boolean bypass_clip_z );
 
 void draw_set_force_passthrough( struct draw_context *draw, 
                                  boolean enable );
index a52d2b50588a1ad1b7def3120c4d23b5fd2a652a..a142563af97155baf6056cc8e883f5f80f35be96 100644 (file)
@@ -54,10 +54,10 @@ FUNC(FUNC_VARS)
 
    FUNC_ENTER;
 
-   /* prim, count, and last_vertex_last should have been defined */
+   /* prim, prim_flags, 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);
+      debug_printf("%s: prim 0x%x, prim_flags 0x%x, count %d, last_vertex_last %d\n",
+            __FUNCTION__, prim, prim_flags, count, last_vertex_last);
    }
 
    switch (prim) {
@@ -80,7 +80,7 @@ FUNC(FUNC_VARS)
    case PIPE_PRIM_LINE_LOOP:
    case PIPE_PRIM_LINE_STRIP:
       if (count >= 2) {
-         flags = DRAW_PIPE_RESET_STIPPLE;
+         flags = (prim_flags & DRAW_SPLIT_BEFORE) ? 0 : DRAW_PIPE_RESET_STIPPLE;
          idx[1] = GET_ELT(0);
          idx[2] = idx[1];
 
@@ -90,7 +90,7 @@ FUNC(FUNC_VARS)
             LINE(flags, idx[0], idx[1]);
          }
          /* close the loop */
-         if (prim == PIPE_PRIM_LINE_LOOP)
+         if (prim == PIPE_PRIM_LINE_LOOP && !prim_flags)
             LINE(flags, idx[1], idx[2]);
       }
       break;
@@ -255,17 +255,23 @@ FUNC(FUNC_VARS)
 
          if (last_vertex_last) {
             flags = (DRAW_PIPE_RESET_STIPPLE |
-                     DRAW_PIPE_EDGE_FLAG_2 |
                      DRAW_PIPE_EDGE_FLAG_0);
+            if (!(prim_flags & DRAW_SPLIT_BEFORE))
+               flags |= DRAW_PIPE_EDGE_FLAG_2;
+
             edge_next = DRAW_PIPE_EDGE_FLAG_0;
-            edge_finish = DRAW_PIPE_EDGE_FLAG_1;
+            edge_finish =
+               (prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_1;
          }
          else {
             flags = (DRAW_PIPE_RESET_STIPPLE |
-                     DRAW_PIPE_EDGE_FLAG_0 |
                      DRAW_PIPE_EDGE_FLAG_1);
+            if (!(prim_flags & DRAW_SPLIT_BEFORE))
+               flags |= DRAW_PIPE_EDGE_FLAG_0;
+
             edge_next = DRAW_PIPE_EDGE_FLAG_1;
-            edge_finish = DRAW_PIPE_EDGE_FLAG_2;
+            edge_finish =
+               (prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_2;
          }
 
          idx[0] = GET_ELT(0);
@@ -300,7 +306,7 @@ FUNC(FUNC_VARS)
 
    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
       if (count >= 4) {
-         flags = DRAW_PIPE_RESET_STIPPLE;
+         flags = (prim_flags & DRAW_SPLIT_BEFORE) ? 0 : DRAW_PIPE_RESET_STIPPLE;
          idx[1] = GET_ELT(0);
          idx[2] = GET_ELT(1);
          idx[3] = GET_ELT(2);
index 4a1013e79a5049e130a6fd68f8d260f41d181a65..50a03ac95a574a258a529ebe1212999874c245e5 100644 (file)
@@ -380,7 +380,7 @@ static void gs_tri_adj(struct draw_geometry_shader *shader,
 
 #define FUNC         gs_run_elts
 #define LOCAL_VARS   const ushort *elts = input_prims->elts;
-#define GET_ELT(idx) (elts[idx] & ~DRAW_PIPE_FLAG_MASK)
+#define GET_ELT(idx) (elts[idx])
 #include "draw_gs_tmp.h"
 
 
@@ -457,6 +457,7 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
    output_prims->start = 0;
    output_prims->count = shader->emitted_vertices;
    output_prims->prim = shader->output_primitive;
+   output_prims->flags = 0x0;
    output_prims->primitive_lengths = shader->primitive_lengths;
    output_prims->primitive_count = shader->emitted_primitives;
    output_verts->count = shader->emitted_vertices;
index 4a17af0dea34bf542110b655ec7955d9e9f3699e..de7b02655a5101c26bddaea4ed880623f9559538 100644 (file)
@@ -6,12 +6,10 @@
 
 #define FUNC_ENTER                                                \
    /* declare more local vars */                                  \
-   struct draw_context *draw = gs->draw;                          \
    const unsigned prim = input_prims->prim;                       \
+   const unsigned prim_flags = input_prims->flags;                \
    const unsigned count = input_prims->count;                     \
-   const boolean last_vertex_last =                               \
-      !(draw->rasterizer->flatshade &&                            \
-        draw->rasterizer->flatshade_first);                       \
+   const boolean last_vertex_last = TRUE;                         \
    do {                                                           \
       debug_assert(input_prims->primitive_count == 1);            \
       switch (prim) {                                             \
index 8d53601d195d6f28703de28e949d7076bc3851d0..8759c38cabbf840b496e8a149541a8bf26be44dc 100644 (file)
@@ -210,13 +210,6 @@ draw_llvm_create(struct draw_context *draw)
 {
    struct draw_llvm *llvm;
 
-#ifdef PIPE_ARCH_X86
-   util_cpu_detect();
-   /* require SSE2 due to LLVM PR6960. */
-   if (!util_cpu_caps.has_sse2)
-       return NULL;
-#endif
-
    llvm = CALLOC_STRUCT( draw_llvm );
    if (!llvm)
       return NULL;
@@ -292,15 +285,23 @@ draw_llvm_destroy(struct draw_llvm *llvm)
 }
 
 struct draw_llvm_variant *
-draw_llvm_create_variant(struct draw_llvm *llvm, int num_inputs)
+draw_llvm_create_variant(struct draw_llvm *llvm,
+                        unsigned num_inputs,
+                        const struct draw_llvm_variant_key *key)
 {
-   struct draw_llvm_variant *variant = MALLOC(sizeof(struct draw_llvm_variant));
+   struct draw_llvm_variant *variant;
    struct llvm_vertex_shader *shader =
       llvm_vertex_shader(llvm->draw->vs.vertex_shader);
 
+   variant = MALLOC(sizeof *variant +
+                   shader->variant_key_size -
+                   sizeof variant->key);
+   if (variant == NULL)
+      return NULL;
+
    variant->llvm = llvm;
 
-   draw_llvm_make_variant_key(llvm, &variant->key);
+   memcpy(&variant->key, key, shader->variant_key_size);
 
    llvm->vertex_header_ptr_type = create_vertex_header(llvm, num_inputs);
 
@@ -738,8 +739,9 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
    step = LLVMConstInt(LLVMInt32Type(), max_vertices, 0);
 
    /* code generated texture sampling */
-   sampler = draw_llvm_sampler_soa_create(variant->key.sampler,
-                                          context_ptr);
+   sampler = draw_llvm_sampler_soa_create(
+      draw_llvm_variant_key_samplers(&variant->key),
+      context_ptr);
 
 #if DEBUG_STORE
    lp_build_printf(builder, "start = %d, end = %d, step = %d\n",
@@ -901,8 +903,9 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
    step = LLVMConstInt(LLVMInt32Type(), max_vertices, 0);
 
    /* code generated texture sampling */
-   sampler = draw_llvm_sampler_soa_create(variant->key.sampler,
-                                          context_ptr);
+   sampler = draw_llvm_sampler_soa_create(
+      draw_llvm_variant_key_samplers(&variant->key),
+      context_ptr);
 
    fetch_max = LLVMBuildSub(builder, fetch_count,
                             LLVMConstInt(LLVMInt32Type(), 1, 0),
@@ -1002,35 +1005,42 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
    lp_func_delete_body(variant->function_elts);
 }
 
-void
-draw_llvm_make_variant_key(struct draw_llvm *llvm,
-                           struct draw_llvm_variant_key *key)
+
+struct draw_llvm_variant_key *
+draw_llvm_make_variant_key(struct draw_llvm *llvm, char *store)
 {
    unsigned i;
+   struct draw_llvm_variant_key *key;
+   struct lp_sampler_static_state *sampler;
 
-   memset(key, 0, sizeof(struct draw_llvm_variant_key));
+   key = (struct draw_llvm_variant_key *)store;
 
+   /* Presumably all variants of the shader should have the same
+    * number of vertex elements - ie the number of shader inputs.
+    */
    key->nr_vertex_elements = llvm->draw->pt.nr_vertex_elements;
 
+   /* All variants of this shader will have the same value for
+    * nr_samplers.  Not yet trying to compact away holes in the
+    * sampler array.
+    */
+   key->nr_samplers = llvm->draw->vs.vertex_shader->info.file_max[TGSI_FILE_SAMPLER] + 1;
+
+   sampler = draw_llvm_variant_key_samplers(key);
+
    memcpy(key->vertex_element,
           llvm->draw->pt.vertex_element,
           sizeof(struct pipe_vertex_element) * key->nr_vertex_elements);
+   
+   memset(sampler, 0, key->nr_samplers * sizeof *sampler);
 
-   memcpy(&key->vs,
-          &llvm->draw->vs.vertex_shader->state,
-          sizeof(struct pipe_shader_state));
-
-   /* if the driver implemented the sampling hooks then
-    * setup our sampling state */
-   if (llvm->draw->num_sampler_views && llvm->draw->num_samplers) {
-      for(i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; ++i) {
-         struct draw_vertex_shader *shader = llvm->draw->vs.vertex_shader;
-         if(shader->info.file_mask[TGSI_FILE_SAMPLER] & (1 << i))
-            lp_sampler_static_state(&key->sampler[i],
-                                    llvm->draw->sampler_views[i],
-                                    llvm->draw->samplers[i]);
-      }
+   for (i = 0 ; i < key->nr_samplers; i++) {
+      lp_sampler_static_state(&sampler[i],
+                             llvm->draw->sampler_views[i],
+                             llvm->draw->samplers[i]);
    }
+
+   return key;
 }
 
 void
index 4addb47d2d83c484336bf5784ab0f6144a8c19be..6196b2f983f0f4493fa517259b69eb0c584d68c4 100644 (file)
@@ -151,12 +151,43 @@ typedef void
 
 struct draw_llvm_variant_key
 {
-   struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
-   unsigned                   nr_vertex_elements;
-   struct pipe_shader_state   vs;
-   struct lp_sampler_static_state sampler[PIPE_MAX_VERTEX_SAMPLERS];
+   unsigned nr_vertex_elements:16;
+   unsigned nr_samplers:16;
+
+   /* Variable number of vertex elements:
+    */
+   struct pipe_vertex_element vertex_element[1];
+
+   /* Followed by variable number of samplers:
+    */
+/*   struct lp_sampler_static_state sampler; */
 };
 
+#define DRAW_LLVM_MAX_VARIANT_KEY_SIZE \
+   (sizeof(struct draw_llvm_variant_key) +     \
+    PIPE_MAX_VERTEX_SAMPLERS * sizeof(struct lp_sampler_static_state) +        \
+    (PIPE_MAX_ATTRIBS-1) * sizeof(struct pipe_vertex_element))
+
+
+static INLINE size_t
+draw_llvm_variant_key_size(unsigned nr_vertex_elements,
+                          unsigned nr_samplers)
+{
+   return (sizeof(struct draw_llvm_variant_key) +
+          nr_samplers * sizeof(struct lp_sampler_static_state) +
+          (nr_vertex_elements - 1) * sizeof(struct pipe_vertex_element));
+}
+
+
+static INLINE struct lp_sampler_static_state *
+draw_llvm_variant_key_samplers(struct draw_llvm_variant_key *key)
+{
+   return (struct lp_sampler_static_state *)
+      &key->vertex_element[key->nr_vertex_elements];
+}
+
+
+
 struct draw_llvm_variant_list_item
 {
    struct draw_llvm_variant *base;
@@ -165,7 +196,6 @@ struct draw_llvm_variant_list_item
 
 struct draw_llvm_variant
 {
-   struct draw_llvm_variant_key key;
    LLVMValueRef function;
    LLVMValueRef function_elts;
    draw_jit_vert_func jit_func;
@@ -176,11 +206,16 @@ struct draw_llvm_variant
    struct draw_llvm *llvm;
    struct draw_llvm_variant_list_item list_item_global;
    struct draw_llvm_variant_list_item list_item_local;
+
+   /* key is variable-sized, must be last */
+   struct draw_llvm_variant_key key;
+   /* key is variable-sized, must be last */
 };
 
 struct llvm_vertex_shader {
    struct draw_vertex_shader base;
 
+   unsigned variant_key_size;
    struct draw_llvm_variant_list_item variants;
    unsigned variants_created;
    unsigned variants_cached;
@@ -220,14 +255,15 @@ void
 draw_llvm_destroy(struct draw_llvm *llvm);
 
 struct draw_llvm_variant *
-draw_llvm_create_variant(struct draw_llvm *llvm, int num_inputs);
+draw_llvm_create_variant(struct draw_llvm *llvm,
+                        unsigned num_vertex_header_attribs,
+                        const struct draw_llvm_variant_key *key);
 
 void
 draw_llvm_destroy_variant(struct draw_llvm_variant *variant);
 
-void
-draw_llvm_make_variant_key(struct draw_llvm *llvm,
-                           struct draw_llvm_variant_key *key);
+struct draw_llvm_variant_key *
+draw_llvm_make_variant_key(struct draw_llvm *llvm, char *store);
 
 LLVMValueRef
 draw_llvm_translate_from(LLVMBuilderRef builder,
index 58995e07248f96e440722df2880f6dc36e72d5d1..6206197dae97645ef742a5bad301e698bd49eb89 100644 (file)
@@ -169,35 +169,27 @@ 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.
  */
 
 #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),  \
+                   flags,                                         \
+                   verts + stride * (i0),                         \
                    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),      \
+               flags,                                             \
+               verts + stride * (i0),                             \
                verts + stride * (i1) );                           \
    } while (0)
 
 #define POINT(i0)                               \
    do {                                         \
-      assert(!((i0) & DRAW_PIPE_FLAG_MASK));    \
       do_point( draw, verts + stride * (i0) );  \
    } while (0)
 
@@ -207,6 +199,7 @@ static void do_triangle( struct draw_context *draw,
 #define FUNC_VARS                               \
     struct draw_context *draw,                  \
     unsigned prim,                              \
+    unsigned prim_flags,                        \
     struct vertex_header *vertices,             \
     unsigned stride,                            \
     const ushort *elts,                         \
@@ -245,22 +238,27 @@ void draw_pipeline_run( struct draw_context *draw,
       const unsigned count = prim_info->primitive_lengths[i];
 
 #if DEBUG
-      /* make sure none of the element indexes go outside the vertex buffer */
+      /* Warn if one 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);
+            unsigned int index = prim_info->elts[start + i];
             if (index > max_index)
                max_index = index;
          }
-         assert(max_index <= vert_info->count);
+         if (max_index >= vert_info->count) {
+            debug_printf("%s: max_index (%u) outside vertex buffer (%u)\n",
+                         __FUNCTION__,
+                         max_index,
+                         vert_info->count);
+         }
       }
 #endif
 
       pipe_run_elts(draw,
                     prim_info->prim,
+                    prim_info->flags,
                     vert_info->verts,
                     vert_info->stride,
                     prim_info->elts + start,
@@ -298,6 +296,7 @@ void draw_pipeline_run( struct draw_context *draw,
 #define FUNC_VARS                      \
     struct draw_context *draw,         \
     unsigned prim,                     \
+    unsigned prim_flags,               \
     struct vertex_header *vertices,    \
     unsigned stride,                   \
     unsigned count
@@ -330,6 +329,7 @@ void draw_pipeline_run_linear( struct draw_context *draw,
 
       pipe_run_linear(draw,
                       prim_info->prim,
+                      prim_info->flags,
                       (struct vertex_header*)verts,
                       vert_info->stride,
                       count);
index eafa29276ffcd9bad39725a49e19a8a159db2684..8b92543987675efbde9f5dfc9bf4e5800d66d8b7 100644 (file)
@@ -265,7 +265,7 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage )
 
    /* Clip stage
     */
-   if (!draw->bypass_clipping)
+   if (draw->clip_xy || draw->clip_z || draw->clip_user)
    {
       draw->pipeline.clip->next = next;
       next = draw->pipeline.clip;
index 3c93c9014a605c08c1c29bcba7e2095bcf69d392..58c5858734a0504290f585ff004a019885d07cea 100644 (file)
@@ -353,9 +353,6 @@ vbuf_alloc_vertices( struct vbuf_stage *vbuf )
    /* Allocate a new vertex buffer */
    vbuf->max_vertices = vbuf->render->max_vertex_buffer_bytes / vbuf->vertex_size;
 
-   /* even number */
-   vbuf->max_vertices = vbuf->max_vertices & ~1;
-
    if(vbuf->max_vertices >= UNDEFINED_VERTEX_ID)
       vbuf->max_vertices = UNDEFINED_VERTEX_ID - 1;
 
index 397d4bf653c8d474e21453a7320171916ddc688b..362f563ba6a75ad8cf474db08353f35e8dee201c 100644 (file)
@@ -140,8 +140,7 @@ struct draw_context
       } middle;
 
       struct {
-         struct draw_pt_front_end *vcache;
-         struct draw_pt_front_end *varray;
+         struct draw_pt_front_end *vsplit;
       } front;
 
       struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
@@ -150,6 +149,8 @@ struct draw_context
       struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
       unsigned nr_vertex_elements;
 
+      struct pipe_index_buffer index_buffer;
+
       /* user-space vertex data, buffers */
       struct {
          /** vertex element/index buffer (ex: glDrawElements) */
@@ -175,13 +176,19 @@ struct draw_context
    } pt;
 
    struct {
-      boolean bypass_clipping;
-      boolean bypass_vs;
+      boolean bypass_clip_xy;
+      boolean bypass_clip_z;
    } driver;
 
    boolean flushing;         /**< debugging/sanity */
    boolean suspend_flushing; /**< internally set */
-   boolean bypass_clipping;  /**< set if either api or driver bypass_clipping true */
+
+   /* Flags set if API requires clipping in these planes and the
+    * driver doesn't indicate that it can do it for us.
+    */
+   boolean clip_xy;
+   boolean clip_z;
+   boolean clip_user;
 
    boolean force_passthrough; /**< never clip or shade */
 
@@ -296,6 +303,10 @@ struct draw_vertex_info {
    unsigned count;
 };
 
+/* these flags are set if the primitive is a segment of a larger one */
+#define DRAW_SPLIT_BEFORE 0x1
+#define DRAW_SPLIT_AFTER  0x2
+
 struct draw_prim_info {
    boolean linear;
    unsigned start;
@@ -304,6 +315,7 @@ struct draw_prim_info {
    unsigned count;
 
    unsigned prim;
+   unsigned flags;
    unsigned *primitive_lengths;
    unsigned primitive_count;
 };
@@ -369,21 +381,15 @@ void draw_pipeline_destroy( struct draw_context *draw );
 
 
 
-/* We use the top few bits in the elts[] parameter to convey a little
- * API information.  This limits the number of vertices we can address
- * to only 4096 -- if that becomes a problem, we can switch to 32-bit
- * draw indices.
- *
- * These flags expected at first vertex of lines & triangles when
- * unfilled and/or line stipple modes are operational.
+/*
+ * These flags are used by the pipeline when unfilled and/or line stipple modes
+ * are operational.
  */
-#define DRAW_PIPE_MAX_VERTICES  (0x1<<12)
-#define DRAW_PIPE_EDGE_FLAG_0   (0x1<<12)
-#define DRAW_PIPE_EDGE_FLAG_1   (0x2<<12)
-#define DRAW_PIPE_EDGE_FLAG_2   (0x4<<12)
-#define DRAW_PIPE_EDGE_FLAG_ALL (0x7<<12)
-#define DRAW_PIPE_RESET_STIPPLE (0x8<<12)
-#define DRAW_PIPE_FLAG_MASK     (0xf<<12)
+#define DRAW_PIPE_EDGE_FLAG_0   0x1
+#define DRAW_PIPE_EDGE_FLAG_1   0x2
+#define DRAW_PIPE_EDGE_FLAG_2   0x4
+#define DRAW_PIPE_EDGE_FLAG_ALL 0x7
+#define DRAW_PIPE_RESET_STIPPLE 0x8
 
 void draw_pipeline_run( struct draw_context *draw,
                         const struct draw_vertex_info *vert,
index 248927505da2d7d4d731be74bfeba7fa735b39d4..f44bf2507c6e0112e33cab5ceabd14b6d2fbc896 100644 (file)
 #include "util/u_math.h"
 #include "util/u_prim.h"
 #include "util/u_format.h"
+#include "util/u_draw.h"
 
 
 DEBUG_GET_ONCE_BOOL_OPTION(draw_fse, "DRAW_FSE", FALSE)
 DEBUG_GET_ONCE_BOOL_OPTION(draw_no_fse, "DRAW_NO_FSE", FALSE)
-#ifdef HAVE_LLVM
-DEBUG_GET_ONCE_BOOL_OPTION(draw_use_llvm, "DRAW_USE_LLVM", TRUE)
-#endif
-
-static unsigned trim( unsigned count, unsigned first, unsigned incr )
-{
-   if (count < first)
-      return 0;
-   return count - (count - first) % incr; 
-}
-
-
 
 /* Overall we split things into:
- *     - frontend -- prepare fetch_elts, draw_elts - eg vcache
+ *     - frontend -- prepare fetch_elts, draw_elts - eg vsplit
  *     - middle   -- fetch, shade, cliptest, viewport
  *     - pipeline -- the prim pipeline: clipping, wide lines, etc 
  *     - backend  -- the vbuf_render provided by the driver.
@@ -77,7 +66,7 @@ draw_pt_arrays(struct draw_context *draw,
    {
       unsigned first, incr;
       draw_pt_split_prim(prim, &first, &incr);
-      count = trim(count, first, incr);
+      count = draw_pt_trim_count(count, first, incr);
       if (count < first)
          return TRUE;
    }
@@ -97,7 +86,9 @@ draw_pt_arrays(struct draw_context *draw,
          opt |= PT_PIPELINE;
       }
 
-      if (!draw->bypass_clipping && !draw->pt.test_fse) {
+      if ((draw->clip_xy ||
+           draw->clip_z ||
+           draw->clip_user) && !draw->pt.test_fse) {
          opt |= PT_CLIPTEST;
       }
 
@@ -115,22 +106,11 @@ draw_pt_arrays(struct draw_context *draw,
          middle = draw->pt.middle.general;
    }
 
-
-   /* Pick the right frontend
-    */
-   if (draw->pt.user.elts || (opt & PT_PIPELINE)) {
-      frontend = draw->pt.front.vcache;
-   } else {
-      frontend = draw->pt.front.varray;
-   }
+   frontend = draw->pt.front.vsplit;
 
    frontend->prepare( frontend, prim, middle, opt );
 
-   frontend->run(frontend,
-                 draw_pt_elt_func(draw),
-                 draw_pt_elt_ptr(draw, start),
-                 draw->pt.user.eltBias,
-                 count);
+   frontend->run(frontend, start, count);
 
    frontend->finish( frontend );
 
@@ -143,12 +123,8 @@ boolean draw_pt_init( struct draw_context *draw )
    draw->pt.test_fse = debug_get_option_draw_fse();
    draw->pt.no_fse = debug_get_option_draw_no_fse();
 
-   draw->pt.front.vcache = draw_pt_vcache( draw );
-   if (!draw->pt.front.vcache)
-      return FALSE;
-
-   draw->pt.front.varray = draw_pt_varray(draw);
-   if (!draw->pt.front.varray)
+   draw->pt.front.vsplit = draw_pt_vsplit(draw);
+   if (!draw->pt.front.vsplit)
       return FALSE;
 
    draw->pt.middle.fetch_emit = draw_pt_fetch_emit( draw );
@@ -164,7 +140,7 @@ boolean draw_pt_init( struct draw_context *draw )
       return FALSE;
 
 #if HAVE_LLVM
-   if (debug_get_option_draw_use_llvm())
+   if (draw->llvm)
       draw->pt.middle.llvm = draw_pt_fetch_pipeline_or_emit_llvm( draw );
 #endif
 
@@ -194,14 +170,9 @@ void draw_pt_destroy( struct draw_context *draw )
       draw->pt.middle.fetch_shade_emit = NULL;
    }
 
-   if (draw->pt.front.vcache) {
-      draw->pt.front.vcache->destroy( draw->pt.front.vcache );
-      draw->pt.front.vcache = NULL;
-   }
-
-   if (draw->pt.front.varray) {
-      draw->pt.front.varray->destroy( draw->pt.front.varray );
-      draw->pt.front.varray = NULL;
+   if (draw->pt.front.vsplit) {
+      draw->pt.front.vsplit->destroy( draw->pt.front.vsplit );
+      draw->pt.front.vsplit = NULL;
    }
 }
 
@@ -221,24 +192,29 @@ draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
       uint ii = 0;
       uint j;
 
-      if (draw->pt.user.elts) {
+      if (draw->pt.user.eltSize) {
+         const char *elts;
+
          /* indexed arrays */
+         elts = (const char *) draw->pt.user.elts;
+         elts += draw->pt.index_buffer.offset;
+
          switch (draw->pt.user.eltSize) {
          case 1:
             {
-               const ubyte *elem = (const ubyte *) draw->pt.user.elts;
+               const ubyte *elem = (const ubyte *) elts;
                ii = elem[start + i];
             }
             break;
          case 2:
             {
-               const ushort *elem = (const ushort *) draw->pt.user.elts;
+               const ushort *elem = (const ushort *) elts;
                ii = elem[start + i];
             }
             break;
          case 4:
             {
-               const uint *elem = (const uint *) draw->pt.user.elts;
+               const uint *elem = (const uint *) elts;
                ii = elem[start + i];
             }
             break;
@@ -324,17 +300,8 @@ draw_arrays(struct draw_context *draw, unsigned prim,
 
 
 /**
- * Draw vertex arrays.
- * This is the main entrypoint into the drawing module.
- * If drawing an indexed primitive, the draw_set_mapped_element_buffer_range()
- * function should have already been called to specify the element/index buffer
- * information.
- *
- * \param prim  one of PIPE_PRIM_x
- * \param start  index of first vertex to draw
- * \param count  number of vertices to draw
- * \param startInstance  number for the first primitive instance (usually 0).
- * \param instanceCount  number of instances to draw (1=non-instanced)
+ * Instanced drawing.
+ * \sa draw_vbo
  */
 void
 draw_arrays_instanced(struct draw_context *draw,
@@ -344,10 +311,50 @@ draw_arrays_instanced(struct draw_context *draw,
                       unsigned startInstance,
                       unsigned instanceCount)
 {
-   unsigned reduced_prim = u_reduced_prim(mode);
+   struct pipe_draw_info info;
+
+   util_draw_init_info(&info);
+
+   info.mode = mode;
+   info.start = start;
+   info.count = count;
+   info.start_instance = startInstance;
+   info.instance_count = instanceCount;
+
+   info.indexed = (draw->pt.user.elts != NULL);
+   if (!info.indexed) {
+      info.min_index = start;
+      info.max_index = start + count - 1;
+   }
+
+   draw_vbo(draw, &info);
+}
+
+
+/**
+ * Draw vertex arrays.
+ * This is the main entrypoint into the drawing module.  If drawing an indexed
+ * primitive, the draw_set_index_buffer() and draw_set_mapped_index_buffer()
+ * functions should have already been called to specify the element/index
+ * buffer information.
+ */
+void
+draw_vbo(struct draw_context *draw,
+         const struct pipe_draw_info *info)
+{
+   unsigned reduced_prim = u_reduced_prim(info->mode);
    unsigned instance;
 
-   assert(instanceCount > 0);
+   assert(info->instance_count > 0);
+   if (info->indexed)
+      assert(draw->pt.user.elts);
+
+   draw->pt.user.eltSize =
+      (info->indexed) ? draw->pt.index_buffer.index_size : 0;
+
+   draw->pt.user.eltBias = info->index_bias;
+   draw->pt.user.min_index = info->min_index;
+   draw->pt.user.max_index = info->max_index;
 
    if (reduced_prim != draw->reduced_prim) {
       draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE);
@@ -355,8 +362,8 @@ draw_arrays_instanced(struct draw_context *draw,
    }
 
    if (0)
-      debug_printf("draw_arrays(mode=%u start=%u count=%u):\n",
-                   mode, start, count);
+      debug_printf("draw_vbo(mode=%u start=%u count=%u):\n",
+                   info->mode, info->start, info->count);
 
    if (0)
       tgsi_dump(draw->vs.vertex_shader->state.tokens, 0);
@@ -384,10 +391,10 @@ draw_arrays_instanced(struct draw_context *draw,
    }
 
    if (0)
-      draw_print_arrays(draw, mode, start, MIN2(count, 20));
+      draw_print_arrays(draw, info->mode, info->start, MIN2(info->count, 20));
 
-   for (instance = 0; instance < instanceCount; instance++) {
-      draw->instance_id = instance + startInstance;
-      draw_pt_arrays(draw, mode, start, count);
+   for (instance = 0; instance < info->instance_count; instance++) {
+      draw->instance_id = instance + info->start_instance;
+      draw_pt_arrays(draw, info->mode, info->start, info->count);
    }
 }
index 44356fba4c553f81f553da3bb007e8eeb2a887ae..5fbb424291572c2c522f95323e7984132c2851c5 100644 (file)
@@ -35,8 +35,6 @@
 
 #include "pipe/p_compiler.h"
 
-typedef unsigned (*pt_elt_func)( const void *elts, unsigned idx );
-
 struct draw_pt_middle_end;
 struct draw_context;
 struct draw_prim_info;
@@ -52,13 +50,18 @@ struct draw_vertex_info;
 /* The "front end" - prepare sets of fetch, draw elements for the
  * middle end.
  *
- * Currenly one version of this:
- *    - vcache - catchall implementation, decomposes to TRI/LINE/POINT prims
- * Later:
- *    - varray, varray_split
- *    - velement, velement_split
+ * The fetch elements are indices to the vertices.  The draw elements are
+ * indices to the fetched vertices.  When both arrays of elements are both
+ * linear, middle->run_linear is called;  When only the fetch elements are
+ * linear, middle->run_linear_elts is called;  Otherwise, middle->run is
+ * called.
+ *
+ * When the number of the draw elements exceeds max_vertex of the middle end,
+ * the draw elements (as well as the fetch elements) are splitted and the
+ * middle end is called multiple times.
  *
- * Currenly only using the vcache version.
+ * Currenly there is:
+ *    - vsplit - catchall implementation, splits big prims
  */
 struct draw_pt_front_end {
    void (*prepare)( struct draw_pt_front_end *,
@@ -67,9 +70,7 @@ struct draw_pt_front_end {
                    unsigned opt );
 
    void (*run)( struct draw_pt_front_end *,
-                pt_elt_func elt_func,
-                const void *elt_ptr,
-                int elt_bias,
+                unsigned start,
                 unsigned count );
 
    void (*finish)( struct draw_pt_front_end * );
@@ -80,6 +81,8 @@ struct draw_pt_front_end {
 /* The "middle end" - prepares actual hardware vertices for the
  * hardware backend.
  *
+ * prim_flags is as defined by pipe_draw_info::flags.
+ *
  * Currently two versions of this:
  *     - fetch, vertex shade, cliptest, prim-pipeline
  *     - fetch, emit (ie passthrough)
@@ -94,11 +97,13 @@ struct draw_pt_middle_end {
                 const unsigned *fetch_elts,
                 unsigned fetch_count,
                 const ushort *draw_elts,
-                unsigned draw_count );
+                unsigned draw_count,
+                unsigned prim_flags );
 
    void (*run_linear)(struct draw_pt_middle_end *,
                       unsigned start,
-                      unsigned count);
+                      unsigned count,
+                      unsigned prim_flags );
 
    /* Transform all vertices in a linear range and then draw them with
     * the supplied element list.  May fail and return FALSE.
@@ -107,7 +112,8 @@ struct draw_pt_middle_end {
                             unsigned fetch_start,
                             unsigned fetch_count,
                             const ushort *draw_elts,
-                            unsigned draw_count );
+                            unsigned draw_count,
+                            unsigned prim_flags );
 
    int (*get_max_vertex_count)( struct draw_pt_middle_end * );
 
@@ -122,19 +128,11 @@ struct vbuf_render;
 struct vertex_header;
 
 
-/* Helper functions.
- */
-pt_elt_func draw_pt_elt_func( struct draw_context *draw );
-const void *draw_pt_elt_ptr( struct draw_context *draw,
-                             unsigned start );
-
 /* Frontends: 
  *
- * Currently only the general-purpose vcache implementation, could add
- * a special case for tiny vertex buffers.
+ * Currently only the general-purpose vsplit implementation.
  */
-struct draw_pt_front_end *draw_pt_vcache( struct draw_context *draw );
-struct draw_pt_front_end *draw_pt_varray(struct draw_context *draw);
+struct draw_pt_front_end *draw_pt_vsplit(struct draw_context *draw);
 
 
 /* Middle-ends:
@@ -223,7 +221,9 @@ boolean draw_pt_post_vs_run( struct pt_post_vs *pvs,
                             struct draw_vertex_info *info );
 
 void draw_pt_post_vs_prepare( struct pt_post_vs *pvs,
-                             boolean bypass_clipping,
+                             boolean clip_xy,
+                             boolean clip_z,
+                             boolean clip_user,
                              boolean bypass_viewport,
                              boolean opengl,
                              boolean need_edgeflags );
@@ -237,6 +237,7 @@ void draw_pt_post_vs_destroy( struct pt_post_vs *pvs );
  * Utils: 
  */
 void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr);
+unsigned draw_pt_trim_count(unsigned count, unsigned first, unsigned incr);
 
 
 #endif
diff --git a/src/gallium/auxiliary/draw/draw_pt_elts.c b/src/gallium/auxiliary/draw/draw_pt_elts.c
deleted file mode 100644 (file)
index 88f4d9f..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2007 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.
- * 
- **************************************************************************/
-
- /*
-  * Authors:
-  *   Keith Whitwell <keith@tungstengraphics.com>
-  */
-
-#include "draw/draw_pt.h"
-#include "draw/draw_private.h"
-
-/* Neat get_elt func that also works for varrays drawing by encoding
- * the start value into a pointer.  
- */
-
-static unsigned elt_uint( const void *elts, unsigned idx )
-{
-   return *(((const uint *)elts) + idx);
-}
-
-static unsigned elt_ushort( const void *elts, unsigned idx )
-{
-   return *(((const ushort *)elts) + idx);
-}
-
-static unsigned elt_ubyte( const void *elts, unsigned idx )
-{
-   return *(((const ubyte *)elts) + idx);
-}
-
-static unsigned elt_vert( const void *elts, unsigned idx )
-{
-   /* unsigned index is packed in the pointer */
-   return (unsigned)(uintptr_t)elts + idx;
-}
-
-pt_elt_func draw_pt_elt_func( struct draw_context *draw )
-{
-   switch (draw->pt.user.eltSize) {
-   case 0: return &elt_vert;
-   case 1: return &elt_ubyte;
-   case 2: return &elt_ushort; 
-   case 4: return &elt_uint;
-   default: return NULL;
-   }
-}     
-
-const void *draw_pt_elt_ptr( struct draw_context *draw,
-                             unsigned start )
-{
-   const char *elts = draw->pt.user.elts;
-
-   switch (draw->pt.user.eltSize) {
-   case 0: 
-      return (const void *)(((const ubyte *)NULL) + start);
-   case 1: 
-      return (const void *)(((const ubyte *)elts) + start);
-   case 2: 
-      return (const void *)(((const ushort *)elts) + start);
-   case 4: 
-      return (const void *)(((const uint *)elts) + start);
-   default:
-      return NULL;
-   }
-}
index 5568fbb9f8809b26be475b7089c72a66587755d2..c8dfc16911e78ac409c6a329ddec8fcfd82dd281 100644 (file)
@@ -120,9 +120,6 @@ void draw_pt_emit_prepare( struct pt_emit *emit,
 
    *max_vertices = (draw->render->max_vertex_buffer_bytes / 
                     (vinfo->size * 4));
-
-   /* even number */
-   *max_vertices = *max_vertices & ~1;
 }
 
 
@@ -147,11 +144,6 @@ void draw_pt_emit( struct pt_emit *emit,
    if (vertex_count == 0)
       return;
 
-   if (vertex_count >= UNDEFINED_VERTEX_ID) {
-      assert(0);
-      return;
-   }
-
    /* XXX: and work out some way to coordinate the render primitive
     * between vbuf.c and here...
     */
@@ -226,9 +218,6 @@ void draw_pt_emit_linear(struct pt_emit *emit,
     */
    draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
-   if (count >= UNDEFINED_VERTEX_ID)
-      goto fail;
-
    /* XXX: and work out some way to coordinate the render primitive
     * between vbuf.c and here...
     */
index 5c8af17c8e36d6382a0b39e815ab22788fe33592..e706b7796f82249e451196a61a5494ae208d03f4 100644 (file)
@@ -191,15 +191,6 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
 
    *max_vertices = (draw->render->max_vertex_buffer_bytes / 
                     (vinfo->size * 4));
-
-   /* Return an even number of verts.
-    * This prevents "parity" errors when splitting long triangle strips which
-    * can lead to front/back culling mix-ups.
-    * Every other triangle in a strip has an alternate front/back orientation
-    * so splitting at an odd position can cause the orientation of subsequent
-    * triangles to get reversed.
-    */
-   *max_vertices = *max_vertices & ~1;
 }
 
 
@@ -210,7 +201,8 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle,
                             const unsigned *fetch_elts,
                             unsigned fetch_count,
                             const ushort *draw_elts,
-                            unsigned draw_count )
+                            unsigned draw_count,
+                            unsigned prim_flags )
 {
    struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
    struct draw_context *draw = feme->draw;
@@ -220,11 +212,6 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle,
     */
    draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
-   if (fetch_count >= UNDEFINED_VERTEX_ID) {
-      assert(0);
-      return;
-   }
-
    draw->render->allocate_vertices( draw->render,
                                     (ushort)feme->translate->key.output_stride,
                                     (ushort)fetch_count );
@@ -273,7 +260,8 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle,
 
 static void fetch_emit_run_linear( struct draw_pt_middle_end *middle,
                                    unsigned start,
-                                   unsigned count )
+                                   unsigned count,
+                                   unsigned prim_flags )
 {
    struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
    struct draw_context *draw = feme->draw;
@@ -283,9 +271,6 @@ static void fetch_emit_run_linear( struct draw_pt_middle_end *middle,
     */
    draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
-   if (count >= UNDEFINED_VERTEX_ID) 
-      goto fail;
-
    if (!draw->render->allocate_vertices( draw->render,
                                          (ushort)feme->translate->key.output_stride,
                                          (ushort)count )) 
@@ -334,7 +319,8 @@ static boolean fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle,
                                         unsigned start,
                                         unsigned count,
                                         const ushort *draw_elts,
-                                        unsigned draw_count )
+                                        unsigned draw_count,
+                                        unsigned prim_flags )
 {
    struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
    struct draw_context *draw = feme->draw;
@@ -344,9 +330,6 @@ static boolean fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle,
     */
    draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
-   if (count >= UNDEFINED_VERTEX_ID)
-      return FALSE;
-
    if (!draw->render->allocate_vertices( draw->render,
                                          (ushort)feme->translate->key.output_stride,
                                          (ushort)count ))
index b8270280b648175edb6055e2779312686cef2ff1..7c198c6026d955659cc0a84501d7591709799c22 100644 (file)
@@ -102,7 +102,7 @@ static void fse_prepare( struct draw_pt_middle_end *middle,
                                fse->key.nr_inputs);     /* inputs - fetch from api format */
 
    fse->key.viewport = !draw->identity_viewport;
-   fse->key.clip = !draw->bypass_clipping;
+   fse->key.clip = draw->clip_xy || draw->clip_z || draw->clip_user;
    fse->key.const_vbuffers = 0;
 
    memset(fse->key.element, 0, 
@@ -175,15 +175,6 @@ static void fse_prepare( struct draw_pt_middle_end *middle,
    *max_vertices = (draw->render->max_vertex_buffer_bytes / 
                     (vinfo->size * 4));
 
-   /* Return an even number of verts.
-    * This prevents "parity" errors when splitting long triangle strips which
-    * can lead to front/back culling mix-ups.
-    * Every other triangle in a strip has an alternate front/back orientation
-    * so splitting at an odd position can cause the orientation of subsequent
-    * triangles to get reversed.
-    */
-   *max_vertices = *max_vertices & ~1;
-
    /* Probably need to do this somewhere (or fix exec shader not to
     * need it):
     */
@@ -197,7 +188,8 @@ static void fse_prepare( struct draw_pt_middle_end *middle,
 
 static void fse_run_linear( struct draw_pt_middle_end *middle, 
                             unsigned start, 
-                            unsigned count )
+                            unsigned count,
+                            unsigned prim_flags )
 {
    struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
    struct draw_context *draw = fse->draw;
@@ -207,9 +199,6 @@ static void fse_run_linear( struct draw_pt_middle_end *middle,
     */
    draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
-   if (count >= UNDEFINED_VERTEX_ID) 
-      goto fail;
-
    if (!draw->render->allocate_vertices( draw->render,
                                          (ushort)fse->key.output_stride,
                                          (ushort)count ))
@@ -265,7 +254,8 @@ fse_run(struct draw_pt_middle_end *middle,
         const unsigned *fetch_elts,
         unsigned fetch_count,
         const ushort *draw_elts,
-        unsigned draw_count )
+        unsigned draw_count,
+        unsigned prim_flags )
 {
    struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
    struct draw_context *draw = fse->draw;
@@ -275,9 +265,6 @@ fse_run(struct draw_pt_middle_end *middle,
     */
    draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
-   if (fetch_count >= UNDEFINED_VERTEX_ID) 
-      goto fail;
-
    if (!draw->render->allocate_vertices( draw->render,
                                          (ushort)fse->key.output_stride,
                                          (ushort)fetch_count ))
@@ -327,7 +314,8 @@ static boolean fse_run_linear_elts( struct draw_pt_middle_end *middle,
                                  unsigned start, 
                                  unsigned count,
                                  const ushort *draw_elts,
-                                 unsigned draw_count )
+                                 unsigned draw_count,
+                                 unsigned prim_flags )
 {
    struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
    struct draw_context *draw = fse->draw;
@@ -337,9 +325,6 @@ static boolean fse_run_linear_elts( struct draw_pt_middle_end *middle,
     */
    draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
-   if (count >= UNDEFINED_VERTEX_ID)
-      return FALSE;
-
    if (!draw->render->allocate_vertices( draw->render,
                                          (ushort)fse->key.output_stride,
                                          (ushort)count ))
index 5b16c3788e508caea9f141fdbfe46c9c991c732c..b72fd612451d3da9b9840b6b3a894e5bebd04c75 100644 (file)
@@ -100,8 +100,10 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
     * but gl vs dx9 clip spaces.
     */
    draw_pt_post_vs_prepare( fpme->post_vs,
-                           (boolean)draw->bypass_clipping,
-                           (boolean)draw->identity_viewport,
+                           draw->clip_xy,
+                           draw->clip_z,
+                           draw->clip_user,
+                           draw->identity_viewport,
                            (boolean)draw->rasterizer->gl_rasterization_rules,
                            (draw->vs.edgeflag_output ? TRUE : FALSE) );
 
@@ -112,16 +114,13 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
                            gs_out_prim,
                             max_vertices );
 
-      *max_vertices = MAX2( *max_vertices,
-                            DRAW_PIPE_MAX_VERTICES );
+      *max_vertices = MAX2( *max_vertices, 4096 );
    }
    else {
-      *max_vertices = DRAW_PIPE_MAX_VERTICES; 
+      /* limit max fetches by limiting max_vertices */
+      *max_vertices = 4096;
    }
 
-   /* return even number */
-   *max_vertices = *max_vertices & ~1;
-
    /* No need to prepare the shader.
     */
    vs->prepare(vs, draw);
@@ -295,7 +294,8 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
                                 const unsigned *fetch_elts,
                                 unsigned fetch_count,
                                 const ushort *draw_elts,
-                                unsigned draw_count )
+                                unsigned draw_count,
+                                unsigned prim_flags )
 {
    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
    struct draw_fetch_info fetch_info;
@@ -311,6 +311,7 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
    prim_info.count = draw_count;
    prim_info.elts = draw_elts;
    prim_info.prim = fpme->input_prim;
+   prim_info.flags = prim_flags;
    prim_info.primitive_count = 1;
    prim_info.primitive_lengths = &draw_count;
 
@@ -320,7 +321,8 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
 
 static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
                                        unsigned start,
-                                       unsigned count)
+                                       unsigned count,
+                                       unsigned prim_flags)
 {
    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
    struct draw_fetch_info fetch_info;
@@ -336,6 +338,7 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
    prim_info.count = count;
    prim_info.elts = NULL;
    prim_info.prim = fpme->input_prim;
+   prim_info.flags = prim_flags;
    prim_info.primitive_count = 1;
    prim_info.primitive_lengths = &count;
 
@@ -348,7 +351,8 @@ static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle
                                                unsigned start,
                                                unsigned count,
                                                const ushort *draw_elts,
-                                               unsigned draw_count )
+                                               unsigned draw_count,
+                                               unsigned prim_flags )
 {
    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
    struct draw_fetch_info fetch_info;
@@ -364,6 +368,7 @@ static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle
    prim_info.count = draw_count;
    prim_info.elts = draw_elts;
    prim_info.prim = fpme->input_prim;
+   prim_info.flags = prim_flags;
    prim_info.primitive_count = 1;
    prim_info.primitive_lengths = &draw_count;
 
index 4b99bee86a0af2b3dbd37334f0705aff9c893c9c..77291e304e1803ef39f158859e5efb50bd954544 100644 (file)
@@ -66,7 +66,8 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
    struct draw_context *draw = fpme->draw;
    struct llvm_vertex_shader *shader =
       llvm_vertex_shader(draw->vs.vertex_shader);
-   struct draw_llvm_variant_key key;
+   char store[DRAW_LLVM_MAX_VARIANT_KEY_SIZE];
+   struct draw_llvm_variant_key *key;
    struct draw_llvm_variant *variant = NULL;
    struct draw_llvm_variant_list_item *li;
    unsigned i;
@@ -106,8 +107,10 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
     * but gl vs dx9 clip spaces.
     */
    draw_pt_post_vs_prepare( fpme->post_vs,
-                           (boolean)draw->bypass_clipping,
-                           (boolean)(draw->identity_viewport),
+                           draw->clip_xy,
+                           draw->clip_z,
+                           draw->clip_user,
+                           draw->identity_viewport,
                            (boolean)draw->rasterizer->gl_rasterization_rules,
                            (draw->vs.edgeflag_output ? TRUE : FALSE) );
 
@@ -118,21 +121,21 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
                            out_prim,
                             max_vertices );
 
-      *max_vertices = MAX2( *max_vertices,
-                            DRAW_PIPE_MAX_VERTICES );
+      *max_vertices = MAX2( *max_vertices, 4096 );
    }
    else {
-      *max_vertices = DRAW_PIPE_MAX_VERTICES;
+      /* limit max fetches by limiting max_vertices */
+      *max_vertices = 4096;
    }
 
    /* return even number */
    *max_vertices = *max_vertices & ~1;
-
-   draw_llvm_make_variant_key(fpme->llvm, &key);
+   
+   key = draw_llvm_make_variant_key(fpme->llvm, store);
 
    li = first_elem(&shader->variants);
    while(!at_end(&shader->variants, li)) {
-      if(memcmp(&li->base->key, &key, sizeof key) == 0) {
+      if(memcmp(&li->base->key, key, shader->variant_key_size) == 0) {
          variant = li->base;
          break;
       }
@@ -155,7 +158,7 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
          }
       }
 
-      variant = draw_llvm_create_variant(fpme->llvm, nr);
+      variant = draw_llvm_create_variant(fpme->llvm, nr, key);
 
       if (variant) {
          insert_at_head(&shader->variants, &variant->list_item_local);
@@ -294,7 +297,8 @@ static void llvm_middle_end_run( struct draw_pt_middle_end *middle,
                                  const unsigned *fetch_elts,
                                  unsigned fetch_count,
                                  const ushort *draw_elts,
-                                 unsigned draw_count )
+                                 unsigned draw_count,
+                                 unsigned prim_flags )
 {
    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
    struct draw_fetch_info fetch_info;
@@ -310,6 +314,7 @@ static void llvm_middle_end_run( struct draw_pt_middle_end *middle,
    prim_info.count = draw_count;
    prim_info.elts = draw_elts;
    prim_info.prim = fpme->input_prim;
+   prim_info.flags = prim_flags;
    prim_info.primitive_count = 1;
    prim_info.primitive_lengths = &draw_count;
 
@@ -319,7 +324,8 @@ static void llvm_middle_end_run( struct draw_pt_middle_end *middle,
 
 static void llvm_middle_end_linear_run( struct draw_pt_middle_end *middle,
                                        unsigned start,
-                                       unsigned count)
+                                       unsigned count,
+                                       unsigned prim_flags)
 {
    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
    struct draw_fetch_info fetch_info;
@@ -335,6 +341,7 @@ static void llvm_middle_end_linear_run( struct draw_pt_middle_end *middle,
    prim_info.count = count;
    prim_info.elts = NULL;
    prim_info.prim = fpme->input_prim;
+   prim_info.flags = prim_flags;
    prim_info.primitive_count = 1;
    prim_info.primitive_lengths = &count;
 
@@ -348,7 +355,8 @@ llvm_middle_end_linear_run_elts( struct draw_pt_middle_end *middle,
                                  unsigned start,
                                  unsigned count,
                                  const ushort *draw_elts,
-                                 unsigned draw_count )
+                                 unsigned draw_count,
+                                 unsigned prim_flags )
 {
    struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
    struct draw_fetch_info fetch_info;
@@ -364,6 +372,7 @@ llvm_middle_end_linear_run_elts( struct draw_pt_middle_end *middle,
    prim_info.count = draw_count;
    prim_info.elts = draw_elts;
    prim_info.prim = fpme->input_prim;
+   prim_info.flags = prim_flags;
    prim_info.primitive_count = 1;
    prim_info.primitive_lengths = &draw_count;
 
index 308f927b778652f0f55aca658d60dd139d101a20..769409cfd67d180855f33c153fa624e26dba8a5b 100644 (file)
  **************************************************************************/
 
 #include "util/u_memory.h"
+#include "util/u_math.h"
 #include "pipe/p_context.h"
 #include "draw/draw_context.h"
 #include "draw/draw_private.h"
 #include "draw/draw_pt.h"
 
+
+#define DO_CLIP_XY           0x1
+#define DO_CLIP_FULL_Z       0x2
+#define DO_CLIP_HALF_Z       0x4
+#define DO_CLIP_USER         0x8
+#define DO_VIEWPORT          0x10
+#define DO_EDGEFLAG          0x20
+
+
 struct pt_post_vs {
    struct draw_context *draw;
 
+   unsigned flags;
+
    boolean (*run)( struct pt_post_vs *pvs,
                    struct draw_vertex_info *info );
 };
@@ -56,186 +68,47 @@ dot4(const float *a, const float *b)
            a[3]*b[3]);
 }
 
-static INLINE unsigned
-compute_clipmask_gl(const float *clip, /*const*/ float plane[][4], unsigned nr,
-                    boolean clip_depth)
-{
-   unsigned mask = 0x0;
-   unsigned i;
+#define FLAGS (0)
+#define TAG(x) x##_none
+#include "draw_cliptest_tmp.h"
 
-#if 0
-   debug_printf("compute clipmask %f %f %f %f\n",
-                clip[0], clip[1], clip[2], clip[3]);
-   assert(clip[3] != 0.0);
-#endif
+#define FLAGS (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_VIEWPORT)
+#define TAG(x) x##_xy_fullz_viewport
+#include "draw_cliptest_tmp.h"
 
-   /* Do the hardwired planes first:
-    */
-   if (-clip[0] + clip[3] < 0) mask |= (1<<0);
-   if ( clip[0] + clip[3] < 0) mask |= (1<<1);
-   if (-clip[1] + clip[3] < 0) mask |= (1<<2);
-   if ( clip[1] + clip[3] < 0) mask |= (1<<3);
-   if (clip_depth) {
-      if ( clip[2] + clip[3] < 0) mask |= (1<<4); /* match mesa clipplane numbering - for now */
-      if (-clip[2] + clip[3] < 0) mask |= (1<<5); /* match mesa clipplane numbering - for now */
-   }
+#define FLAGS (DO_CLIP_XY | DO_CLIP_HALF_Z | DO_VIEWPORT)
+#define TAG(x) x##_xy_halfz_viewport
+#include "draw_cliptest_tmp.h"
 
-   /* Followed by any remaining ones:
-    */
-   for (i = 6; i < nr; i++) {
-      if (dot4(clip, plane[i]) < 0) 
-         mask |= (1<<i);
-   }
+#define FLAGS (DO_CLIP_FULL_Z | DO_VIEWPORT)
+#define TAG(x) x##_fullz_viewport
+#include "draw_cliptest_tmp.h"
 
-   return mask;
-}
+#define FLAGS (DO_CLIP_HALF_Z | DO_VIEWPORT)
+#define TAG(x) x##_halfz_viewport
+#include "draw_cliptest_tmp.h"
 
+#define FLAGS (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER | DO_VIEWPORT)
+#define TAG(x) x##_xy_fullz_user_viewport
+#include "draw_cliptest_tmp.h"
 
-/* The normal case - cliptest, rhw divide, viewport transform.
- *
- * Also handle identity viewport here at the expense of a few wasted
- * instructions
- */
-static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs,
-                                             struct draw_vertex_info *info )
-{
-   struct vertex_header *out = info->verts;
-   const float *scale = pvs->draw->viewport.scale;
-   const float *trans = pvs->draw->viewport.translate;
-   const unsigned pos = draw_current_shader_position_output(pvs->draw);
-   unsigned clipped = 0;
-   unsigned j;
-
-   if (0) debug_printf("%s count, %d\n", __FUNCTION__, info->count);
-
-   for (j = 0; j < info->count; j++) {
-      float *position = out->data[pos];
-
-      initialize_vertex_header(out);
-#if 0
-      debug_printf("%d) io = %p, data = %p = [%f, %f, %f, %f]\n",
-                   j, out, position, position[0], position[1], position[2], position[3]);
-#endif
-
-      out->clip[0] = position[0];
-      out->clip[1] = position[1];
-      out->clip[2] = position[2];
-      out->clip[3] = position[3];
-
-      out->vertex_id = 0xffff;
-      /* Disable depth clipping if depth clamping is enabled. */
-      out->clipmask = compute_clipmask_gl(out->clip, 
-                                         pvs->draw->plane,
-                                          pvs->draw->nr_planes,
-                                          !pvs->draw->depth_clamp);
-      clipped += out->clipmask;
-
-      if (out->clipmask == 0)
-      {
-        /* divide by w */
-        float w = 1.0f / position[3];
-
-        /* Viewport mapping */
-        position[0] = position[0] * w * scale[0] + trans[0];
-        position[1] = position[1] * w * scale[1] + trans[1];
-        position[2] = position[2] * w * scale[2] + trans[2];
-        position[3] = w;
-#if 0
-         debug_printf("post viewport: %f %f %f %f\n",
-                      position[0],
-                      position[1],
-                      position[2],
-                      position[3]);
-#endif
-      }
-
-      out = (struct vertex_header *)( (char *)out + info->stride );
-   }
-
-   return clipped != 0;
-}
+#define FLAGS (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER | DO_VIEWPORT | DO_EDGEFLAG)
+#define TAG(x) x##_xy_fullz_user_viewport_edgeflag
+#include "draw_cliptest_tmp.h"
 
 
 
-/* As above plus edgeflags
+/* Don't want to create 64 versions of this function, so catch the
+ * less common ones here.  This is looking like something which should
+ * be code-generated, perhaps appended to the end of the vertex
+ * shader.
  */
-static boolean
-post_vs_cliptest_viewport_gl_edgeflag(struct pt_post_vs *pvs,
-                                      struct draw_vertex_info *info)
-{
-   unsigned j;
-   boolean needpipe;
-
-   needpipe = post_vs_cliptest_viewport_gl(pvs, info);
-
-   /* If present, copy edgeflag VS output into vertex header.
-    * Otherwise, leave header as is.
-    */
-   if (pvs->draw->vs.edgeflag_output) {
-      struct vertex_header *out = info->verts;
-      int ef = pvs->draw->vs.edgeflag_output;
-
-      for (j = 0; j < info->count; j++) {
-         const float *edgeflag = out->data[ef];
-         out->edgeflag = !(edgeflag[0] != 1.0f);
-         needpipe |= !out->edgeflag;
-         out = (struct vertex_header *)( (char *)out + info->stride );
-      }
-   }
-   return needpipe;
-}
-
+#define FLAGS (pvs->flags)
+#define TAG(x) x##_generic
+#include "draw_cliptest_tmp.h"
 
 
 
-/* If bypass_clipping is set, skip cliptest and rhw divide.
- */
-static boolean post_vs_viewport( struct pt_post_vs *pvs,
-                                 struct draw_vertex_info *info )
-{
-   struct vertex_header *out = info->verts;
-   const float *scale = pvs->draw->viewport.scale;
-   const float *trans = pvs->draw->viewport.translate;
-   const unsigned pos = draw_current_shader_position_output(pvs->draw);
-   unsigned j;
-
-   if (0) debug_printf("%s\n", __FUNCTION__);
-   for (j = 0; j < info->count; j++) {
-      float *position = out->data[pos];
-
-      initialize_vertex_header(out);
-      /* Viewport mapping only, no cliptest/rhw divide
-       */
-      position[0] = position[0] * scale[0] + trans[0];
-      position[1] = position[1] * scale[1] + trans[1];
-      position[2] = position[2] * scale[2] + trans[2];
-
-      out = (struct vertex_header *)((char *)out + info->stride);
-   }
-
-   return FALSE;
-}
-
-
-/* If bypass_clipping is set and we have an identity viewport, nothing
- * to do.
- */
-static boolean post_vs_none( struct pt_post_vs *pvs,
-                            struct draw_vertex_info *info )
-{
-   struct vertex_header *out = info->verts;
-   unsigned j;
-
-   if (0) debug_printf("%s\n", __FUNCTION__);
-   /* just initialize the vertex_id in all headers */
-   for (j = 0; j < info->count; j++) {
-      initialize_vertex_header(out);
-
-      out = (struct vertex_header *)((char *)out + info->stride);
-   }
-   return FALSE;
-}
-
 boolean draw_pt_post_vs_run( struct pt_post_vs *pvs,
                             struct draw_vertex_info *info )
 {
@@ -244,31 +117,72 @@ boolean draw_pt_post_vs_run( struct pt_post_vs *pvs,
 
 
 void draw_pt_post_vs_prepare( struct pt_post_vs *pvs,
-                             boolean bypass_clipping,
+                             boolean clip_xy,
+                             boolean clip_z,
+                              boolean clip_user,
                              boolean bypass_viewport,
                              boolean opengl,
                              boolean need_edgeflags )
 {
-   if (!need_edgeflags) {
-      if (bypass_clipping) {
-         if (bypass_viewport)
-            pvs->run = post_vs_none;
-         else
-            pvs->run = post_vs_viewport;
-      }
-      else {
-         /* if (opengl) */
-         pvs->run = post_vs_cliptest_viewport_gl;
-      }
+   pvs->flags = 0;
+
+   if (clip_xy)
+      pvs->flags |= DO_CLIP_XY;
+   
+   if (clip_z && opengl) {
+      pvs->flags |= DO_CLIP_FULL_Z;
+      ASSIGN_4V( pvs->draw->plane[4],  0,  0,  1, 1 );
+   }
+
+   if (clip_z && !opengl) {
+      pvs->flags |= DO_CLIP_HALF_Z;
+      ASSIGN_4V( pvs->draw->plane[4],  0,  0,  1, 0 );
    }
-   else {
-      /* If we need to copy edgeflags to the vertex header, it should
-       * mean we're running the primitive pipeline.  Hence the bypass
-       * flags should be false.
-       */
-      assert(!bypass_clipping);
-      assert(!bypass_viewport);
-      pvs->run = post_vs_cliptest_viewport_gl_edgeflag;
+
+   if (clip_user)
+      pvs->flags |= DO_CLIP_USER;
+
+   if (!bypass_viewport)
+      pvs->flags |= DO_VIEWPORT;
+
+   if (need_edgeflags)
+      pvs->flags |= DO_EDGEFLAG;
+
+   /* Now select the relevant function:
+    */
+   switch (pvs->flags) {
+   case 0:
+      pvs->run = do_cliptest_none;
+      break;
+
+   case DO_CLIP_XY | DO_CLIP_FULL_Z | DO_VIEWPORT:
+      pvs->run = do_cliptest_xy_fullz_viewport;
+      break;
+
+   case DO_CLIP_XY | DO_CLIP_HALF_Z | DO_VIEWPORT:
+      pvs->run = do_cliptest_xy_halfz_viewport;
+      break;
+
+   case DO_CLIP_FULL_Z | DO_VIEWPORT:
+      pvs->run = do_cliptest_fullz_viewport;
+      break;
+
+   case DO_CLIP_HALF_Z | DO_VIEWPORT:
+      pvs->run = do_cliptest_halfz_viewport;
+      break;
+
+   case DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER | DO_VIEWPORT:
+      pvs->run = do_cliptest_xy_fullz_user_viewport;
+      break;
+
+   case (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER |
+         DO_VIEWPORT | DO_EDGEFLAG):
+      pvs->run = do_cliptest_xy_fullz_user_viewport_edgeflag;
+      break;
+      
+   default:
+      pvs->run = do_cliptest_generic;
+      break;
    }
 }
 
index f7f4f24d3544a41f2ac0527a63c27120ef11d97e..c86bdd99a33bfafe2534b23ef542967ea2e3ae95 100644 (file)
@@ -225,7 +225,7 @@ static void so_tri(struct pt_so_emit *so, int i0, int i1, int i2)
 
 #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)
+#define GET_ELT(idx) (elts[start + (idx)])
 #include "draw_so_emit_tmp.h"
 
 
index 182a597cca2302dbc9e884cfd9928e414261cbb0..513bbbed216780aee720c308d804b072fe49b6e3 100644 (file)
@@ -92,3 +92,10 @@ void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr)
       break;
    }
 }
+
+unsigned draw_pt_trim_count(unsigned count, unsigned first, unsigned incr)
+{
+   if (count < first)
+      return 0;
+   return count - (count - first) % incr;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_varray.c b/src/gallium/auxiliary/draw/draw_pt_varray.c
deleted file mode 100644 (file)
index cd7bb7b..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#include "util/u_math.h"
-#include "util/u_memory.h"
-
-#include "draw/draw_context.h"
-#include "draw/draw_private.h"
-#include "draw/draw_pt.h"
-
-#define FETCH_MAX 256
-#define DRAW_MAX (FETCH_MAX+8)
-
-struct varray_frontend {
-   struct draw_pt_front_end base;
-   struct draw_context *draw;
-
-   ushort draw_elts[DRAW_MAX];
-   unsigned fetch_elts[FETCH_MAX];
-
-   unsigned driver_fetch_max;
-   unsigned fetch_max;
-
-   struct draw_pt_middle_end *middle;
-
-   unsigned input_prim;
-   unsigned output_prim;
-};
-
-
-static void varray_flush_linear(struct varray_frontend *varray,
-                                unsigned start, unsigned count)
-{
-   if (count) {
-      assert(varray->middle->run_linear);
-      varray->middle->run_linear(varray->middle, start, count);
-   }
-}
-
-static void varray_line_loop_segment(struct varray_frontend *varray,
-                                     unsigned start,
-                                     unsigned segment_start,
-                                     unsigned segment_count,
-                                     boolean end )
-{
-   assert(segment_count < varray->fetch_max);
-   if (segment_count >= 1) {
-      unsigned nr = 0, i;
-
-      for (i = 0; i < segment_count; i++) 
-         varray->fetch_elts[nr++] = start + segment_start + i;
-
-      if (end) 
-         varray->fetch_elts[nr++] = start;
-
-      assert(nr <= FETCH_MAX);
-
-      varray->middle->run(varray->middle, 
-                          varray->fetch_elts,
-                          nr,
-                          varray->draw_elts, /* ie. linear */
-                          nr);
-   }
-}
-
-
-
-static void varray_fan_segment(struct varray_frontend *varray,
-                               unsigned start, 
-                               unsigned segment_start,
-                               unsigned segment_count )
-{
-   assert(segment_count < varray->fetch_max);
-   if (segment_count >= 2) {
-      unsigned nr = 0, i;
-
-      if (segment_start != 0)
-         varray->fetch_elts[nr++] = start;
-
-      for (i = 0 ; i < segment_count; i++) 
-         varray->fetch_elts[nr++] = start + segment_start + i;
-
-      assert(nr <= FETCH_MAX);
-
-      varray->middle->run(varray->middle, 
-                          varray->fetch_elts,
-                          nr,
-                          varray->draw_elts, /* ie. linear */
-                          nr);
-   }
-}
-
-
-
-
-#define FUNC varray_run
-#include "draw_pt_varray_tmp_linear.h"
-
-static unsigned decompose_prim[PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY + 1] = {
-   PIPE_PRIM_POINTS,
-   PIPE_PRIM_LINES,
-   PIPE_PRIM_LINE_STRIP,        /* decomposed LINELOOP */
-   PIPE_PRIM_LINE_STRIP,
-   PIPE_PRIM_TRIANGLES,
-   PIPE_PRIM_TRIANGLE_STRIP,
-   PIPE_PRIM_TRIANGLE_FAN,
-   PIPE_PRIM_QUADS,
-   PIPE_PRIM_QUAD_STRIP,
-   PIPE_PRIM_POLYGON,
-   PIPE_PRIM_LINES_ADJACENCY,
-   PIPE_PRIM_LINE_STRIP_ADJACENCY,
-   PIPE_PRIM_TRIANGLES_ADJACENCY,
-   PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY
-};
-
-
-
-static void varray_prepare(struct draw_pt_front_end *frontend,
-                           unsigned in_prim,
-                           struct draw_pt_middle_end *middle,
-                           unsigned opt)
-{
-   struct varray_frontend *varray = (struct varray_frontend *)frontend;
-
-   varray->base.run = varray_run;
-
-   varray->input_prim = in_prim;
-   assert(in_prim < Elements(decompose_prim));
-   varray->output_prim = decompose_prim[in_prim];
-
-   varray->middle = middle;
-   middle->prepare(middle,
-                   varray->output_prim,
-                   opt, &varray->driver_fetch_max );
-
-   /* check that the max is even */
-   assert((varray->driver_fetch_max & 1) == 0);
-
-   varray->fetch_max = MIN2(FETCH_MAX, varray->driver_fetch_max);
-}
-
-
-
-
-static void varray_finish(struct draw_pt_front_end *frontend)
-{
-   struct varray_frontend *varray = (struct varray_frontend *)frontend;
-   varray->middle->finish(varray->middle);
-   varray->middle = NULL;
-}
-
-static void varray_destroy(struct draw_pt_front_end *frontend)
-{
-   FREE(frontend);
-}
-
-
-struct draw_pt_front_end *draw_pt_varray(struct draw_context *draw)
-{
-   ushort i;
-   struct varray_frontend *varray = CALLOC_STRUCT(varray_frontend);
-   if (varray == NULL)
-      return NULL;
-
-   varray->base.prepare = varray_prepare;
-   varray->base.run     = NULL;
-   varray->base.finish  = varray_finish;
-   varray->base.destroy = varray_destroy;
-   varray->draw = draw;
-
-   for (i = 0; i < DRAW_MAX; i++) {
-      varray->draw_elts[i] = i;
-   }
-
-   return &varray->base;
-}
diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h
deleted file mode 100644 (file)
index 7c72245..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-
-static void FUNC(struct draw_pt_front_end *frontend,
-                 pt_elt_func get_elt,
-                 const void *elts,
-                 unsigned count)
-{
-   struct varray_frontend *varray = (struct varray_frontend *)frontend;
-   struct draw_context *draw = varray->draw;
-   unsigned start = (unsigned)elts;
-
-   boolean flatfirst = (draw->rasterizer->flatshade &&
-                        draw->rasterizer->flatshade_first);
-   unsigned i, j;
-   ushort flags;
-   unsigned first, incr;
-
-   varray->fetch_start = start;
-
-   draw_pt_split_prim(varray->input_prim, &first, &incr);
-
-#if 0
-   debug_printf("%s (%d) %d/%d\n", __FUNCTION__,
-                varray->input_prim,
-                start, count);
-#endif
-
-   switch (varray->input_prim) {
-   case PIPE_PRIM_POINTS:
-      for (j = 0; j + first <= count; j += i) {
-         unsigned end = MIN2(FETCH_MAX, count - j);
-         end -= (end % incr);
-         for (i = 0; i < end; i++) {
-            POINT(varray, i + 0);
-         }
-         i = end;
-         fetch_init(varray, end);
-         varray_flush(varray);
-      }
-      break;
-
-   case PIPE_PRIM_LINES:
-      for (j = 0; j + first <= count; j += i) {
-         unsigned end = MIN2(FETCH_MAX, count - j);
-         end -= (end % incr);
-         for (i = 0; i+1 < end; i += 2) {
-            LINE(varray, DRAW_PIPE_RESET_STIPPLE,
-                 i + 0, i + 1);
-         }
-         i = end;
-         fetch_init(varray, end);
-         varray_flush(varray);
-      }
-      break;
-
-   case PIPE_PRIM_LINE_LOOP:
-      if (count >= 2) {
-         flags = DRAW_PIPE_RESET_STIPPLE;
-
-         for (j = 0; j + first <= count; j += i) {
-            unsigned end = MIN2(FETCH_MAX, count - j);
-            end -= (end % incr);
-            for (i = 1; i < end; i++, flags = 0) {
-               LINE(varray, flags, i - 1, i);
-            }
-            LINE(varray, flags, i - 1, 0);
-            i = end;
-            fetch_init(varray, end);
-            varray_flush(varray);
-         }
-      }
-      break;
-
-   case PIPE_PRIM_LINE_STRIP:
-      flags = DRAW_PIPE_RESET_STIPPLE;
-      for (j = 0; j + first <= count; j += i) {
-         unsigned end = MIN2(FETCH_MAX, count - j);
-         end -= (end % incr);
-         for (i = 1; i < end; i++, flags = 0) {
-            LINE(varray, flags, i - 1, i);
-         }
-         i = end;
-         fetch_init(varray, end);
-         varray_flush(varray);
-      }
-      break;
-
-   case PIPE_PRIM_TRIANGLES:
-      for (j = 0; j + first <= count; j += i) {
-         unsigned end = MIN2(FETCH_MAX, count - j);
-         end -= (end % incr);
-         for (i = 0; i+2 < end; i += 3) {
-            TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
-                     i + 0, i + 1, i + 2);
-         }
-         i = end;
-         fetch_init(varray, end);
-         varray_flush(varray);
-      }
-      break;
-
-   case PIPE_PRIM_TRIANGLE_STRIP:
-      if (flatfirst) {
-         for (j = 0; j + first <= count; j += i) {
-            unsigned end = MIN2(FETCH_MAX, count - j);
-            end -= (end % incr);
-            for (i = 0; i+2 < end; i++) {
-               TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
-                        i + 0, i + 1 + (i&1), i + 2 - (i&1));
-            }
-            i = end;
-            fetch_init(varray, end);
-            varray_flush(varray);
-            if (j + first + i <= count) {
-               varray->fetch_start -= 2;
-               i -= 2;
-            }
-         }
-      }
-      else {
-         for (j = 0; j + first <= count; j += i) {
-            unsigned end = MIN2(FETCH_MAX, count - j);
-            end -= (end  % incr);
-            for (i = 0; i + 2 < end; i++) {
-               TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
-                        i + 0 + (i&1), i + 1 - (i&1), i + 2);
-            }
-            i = end;
-            fetch_init(varray, end);
-            varray_flush(varray);
-            if (j + first + i <= count) {
-               varray->fetch_start -= 2;
-               i -= 2;
-            }
-         }
-      }
-      break;
-
-   case PIPE_PRIM_TRIANGLE_FAN:
-      if (count >= 3) {
-         if (flatfirst) {
-            flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
-            for (j = 0; j + first <= count; j += i) {
-               unsigned end = MIN2(FETCH_MAX, count - j);
-               end -= (end % incr);
-               for (i = 0; i+2 < end; i++) {
-                  TRIANGLE(varray, flags, i + 1, i + 2, 0);
-               }
-               i = end;
-               fetch_init(varray, end);
-               varray_flush(varray);
-            }
-         }
-         else {
-            flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
-            for (j = 0; j + first <= count; j += i) {
-               unsigned end = MIN2(FETCH_MAX, count - j);
-               end -= (end % incr);
-               for (i = 0; i+2 < end; i++) {
-                  TRIANGLE(varray, flags, 0, i + 1, i + 2);
-               }
-               i = end;
-               fetch_init(varray, end);
-               varray_flush(varray);
-            }
-         }
-      }
-      break;
-
-   case PIPE_PRIM_QUADS:
-      for (j = 0; j + first <= count; j += i) {
-         unsigned end = MIN2(FETCH_MAX, count - j);
-         end -= (end % incr);
-         for (i = 0; i+3 < end; i += 4) {
-            QUAD(varray, i + 0, i + 1, i + 2, i + 3);
-         }
-         i = end;
-         fetch_init(varray, end);
-         varray_flush(varray);
-      }
-      break;
-
-   case PIPE_PRIM_QUAD_STRIP:
-      for (j = 0; j + first <= count; j += i) {
-         unsigned end = MIN2(FETCH_MAX, count - j);
-         end -= (end % incr);
-         for (i = 0; i+3 < end; i += 2) {
-            QUAD(varray, i + 2, i + 0, i + 1, i + 3);
-         }
-         i = end;
-         fetch_init(varray, end);
-         varray_flush(varray);
-         if (j + first + i <= count) {
-            varray->fetch_start -= 2;
-            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.
-       */
-      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 (j = 0; j + first <= count; j += i) {
-         unsigned end = MIN2(FETCH_MAX, count - j);
-         end -= (end % incr);
-         for (i = 0; i+2 < end; i++, flags = edge_middle) {
-
-            if (i + 3 == count)
-               flags |= edge_last;
-
-            TRIANGLE(varray, flags, i + 1, i + 2, 0);
-         }
-         i = end;
-         fetch_init(varray, end);
-         varray_flush(varray);
-      }
-   }
-   break;
-
-   default:
-      assert(0);
-      break;
-   }
-
-   varray_flush(varray);
-}
-
-#undef TRIANGLE
-#undef QUAD
-#undef POINT
-#undef LINE
-#undef FUNC
diff --git a/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h b/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h
deleted file mode 100644 (file)
index 55e43b2..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-static unsigned trim( unsigned count, unsigned first, unsigned 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,
-                 pt_elt_func get_elt,
-                 const void *elts,
-                 int elt_bias,
-                 unsigned count)
-{
-   struct varray_frontend *varray = (struct varray_frontend *)frontend;
-   unsigned start = (unsigned) ((char *) elts - (char *) NULL);
-
-   unsigned j;
-   unsigned first, incr;
-
-   assert(elt_bias == 0);
-
-   draw_pt_split_prim(varray->input_prim, &first, &incr);
-   
-   /* Sanitize primitive length:
-    */
-   count = trim(count, first, incr); 
-   if (count < first)
-      return;
-
-#if 0
-   debug_printf("%s (%d) %d/%d\n", __FUNCTION__,
-                varray->input_prim,
-                start, count);
-#endif
-
-   switch (varray->input_prim) {
-   case PIPE_PRIM_POINTS:
-   case PIPE_PRIM_LINES:
-   case PIPE_PRIM_TRIANGLES:
-   case PIPE_PRIM_LINE_STRIP:
-   case PIPE_PRIM_TRIANGLE_STRIP:
-   case PIPE_PRIM_QUADS:
-   case PIPE_PRIM_QUAD_STRIP:
-   case PIPE_PRIM_LINES_ADJACENCY:
-   case PIPE_PRIM_LINE_STRIP_ADJACENCY:
-   case PIPE_PRIM_TRIANGLES_ADJACENCY:
-   case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
-      for (j = 0; j < count;) {
-         unsigned remaining = count - j;
-         unsigned nr = trim( MIN2(varray->driver_fetch_max, remaining), first, incr );
-         varray_flush_linear(varray, start + j, nr);
-         j += nr;
-         if (nr != remaining) 
-            j -= (first - incr);
-      }
-      break;
-
-   case PIPE_PRIM_LINE_LOOP:
-      /* Always have to decompose as we've stated that this will be
-       * emitted as a line-strip.
-       */
-      for (j = 0; j < count;) {
-         unsigned remaining = count - j;
-         unsigned nr = trim( MIN2(varray->fetch_max-1, remaining), first, incr );
-         varray_line_loop_segment(varray, start, j, nr, nr == remaining);
-         j += nr;
-         if (nr != remaining) 
-            j -= (first - incr);
-      }
-      break;
-
-
-   case PIPE_PRIM_POLYGON:
-   case PIPE_PRIM_TRIANGLE_FAN: 
-      if (count < varray->driver_fetch_max) {
-         varray_flush_linear(varray, start, count);
-      }
-      else {
-         for ( j = 0; j < count;) {
-            unsigned remaining = count - j;
-            unsigned nr = trim( MIN2(varray->fetch_max-1, remaining), first, incr );
-            varray_fan_segment(varray, start, j, nr);
-            j += nr;
-            if (nr != remaining) 
-               j -= (first - incr);
-         }
-      }
-      break;
-
-   default:
-      assert(0);
-      break;
-   }
-}
-
-#undef TRIANGLE
-#undef QUAD
-#undef POINT
-#undef LINE
-#undef FUNC
diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c
deleted file mode 100644 (file)
index a848b54..0000000
+++ /dev/null
@@ -1,610 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2007 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.
- * 
- **************************************************************************/
-
- /*
-  * Authors:
-  *   Keith Whitwell <keith@tungstengraphics.com>
-  */
-
-#include "util/u_memory.h"
-#include "util/u_prim.h"
-#include "draw/draw_context.h"
-#include "draw/draw_private.h"
-#include "draw/draw_pt.h"
-
-
-#define CACHE_MAX 256
-#define FETCH_MAX 256
-#define DRAW_MAX (16*1024)
-
-
-struct vcache_frontend {
-   struct draw_pt_front_end base;
-   struct draw_context *draw;
-
-   unsigned in[CACHE_MAX];
-   ushort out[CACHE_MAX];
-
-   ushort draw_elts[DRAW_MAX];
-   unsigned fetch_elts[FETCH_MAX];
-
-   unsigned draw_count;
-   unsigned fetch_count;
-   unsigned fetch_max;
-
-   struct draw_pt_middle_end *middle;
-
-   unsigned input_prim;
-   unsigned output_prim;
-
-   unsigned middle_prim;
-   unsigned opt;
-};
-
-
-static INLINE void
-vcache_flush( struct vcache_frontend *vcache )
-{
-   if (vcache->middle_prim != vcache->output_prim) {
-      vcache->middle_prim = vcache->output_prim;
-      vcache->middle->prepare( vcache->middle,
-                               vcache->middle_prim,
-                               vcache->opt,
-                               &vcache->fetch_max );
-   }
-
-   if (vcache->draw_count) {
-      vcache->middle->run( vcache->middle,
-                           vcache->fetch_elts,
-                           vcache->fetch_count,
-                           vcache->draw_elts,
-                           vcache->draw_count );
-   }
-
-   memset(vcache->in, ~0, sizeof(vcache->in));
-   vcache->fetch_count = 0;
-   vcache->draw_count = 0;
-}
-
-
-static INLINE void 
-vcache_check_flush( struct vcache_frontend *vcache )
-{
-   if (vcache->draw_count + 6 >= DRAW_MAX ||
-       vcache->fetch_count + 6 >= FETCH_MAX) {
-      vcache_flush( vcache );
-   }
-}
-
-
-static INLINE void 
-vcache_elt( struct vcache_frontend *vcache,
-            unsigned felt,
-            ushort flags )
-{
-   unsigned idx = felt % CACHE_MAX;
-
-   if (vcache->in[idx] != felt) {
-      assert(vcache->fetch_count < FETCH_MAX);
-
-      vcache->in[idx] = felt;
-      vcache->out[idx] = (ushort)vcache->fetch_count;
-      vcache->fetch_elts[vcache->fetch_count++] = felt;
-   }
-
-   vcache->draw_elts[vcache->draw_count++] = vcache->out[idx] | flags;
-}
-
-
-                   
-static INLINE void 
-vcache_triangle( struct vcache_frontend *vcache,
-                 unsigned i0,
-                 unsigned i1,
-                 unsigned i2 )
-{
-   vcache_elt(vcache, i0, 0);
-   vcache_elt(vcache, i1, 0);
-   vcache_elt(vcache, i2, 0);
-   vcache_check_flush(vcache);
-}
-
-                         
-static INLINE void 
-vcache_triangle_flags( struct vcache_frontend *vcache,
-                       ushort flags,
-                       unsigned i0,
-                       unsigned i1,
-                       unsigned i2 )
-{
-   vcache_elt(vcache, i0, flags);
-   vcache_elt(vcache, i1, 0);
-   vcache_elt(vcache, i2, 0);
-   vcache_check_flush(vcache);
-}
-
-
-static INLINE void 
-vcache_line( struct vcache_frontend *vcache,
-             unsigned i0,
-             unsigned i1 )
-{
-   vcache_elt(vcache, i0, 0);
-   vcache_elt(vcache, i1, 0);
-   vcache_check_flush(vcache);
-}
-
-
-static INLINE void 
-vcache_line_flags( struct vcache_frontend *vcache,
-                   ushort flags,
-                   unsigned i0,
-                   unsigned i1 )
-{
-   vcache_elt(vcache, i0, flags);
-   vcache_elt(vcache, i1, 0);
-   vcache_check_flush(vcache);
-}
-
-
-static INLINE void 
-vcache_point( struct vcache_frontend *vcache,
-              unsigned i0 )
-{
-   vcache_elt(vcache, i0, 0);
-   vcache_check_flush(vcache);
-}
-
-
-static INLINE void
-vcache_line_adj_flags( struct vcache_frontend *vcache,
-                       unsigned flags,
-                       unsigned a0, unsigned i0, unsigned i1, unsigned a1 )
-{
-   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_line_adj( struct vcache_frontend *vcache,
-                 unsigned a0, unsigned i0, unsigned i1, unsigned a1 )
-{
-   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);
-}
-
-
-/* At least for now, we're back to using a template include file for
- * this.  The two paths aren't too different though - it may be
- * possible to reunify them.
- */
-#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(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"
-
-static INLINE void 
-rebase_uint_elts( const unsigned *src,
-                  unsigned count,
-                  int delta,
-                  ushort *dest )
-{
-   unsigned i;
-   for (i = 0; i < count; i++) 
-      dest[i] = (ushort)(src[i] + delta);
-}
-
-
-static INLINE void 
-rebase_ushort_elts( const ushort *src,
-                    unsigned count,
-                    int delta,
-                    ushort *dest )
-{
-   unsigned i;
-   for (i = 0; i < count; i++) 
-      dest[i] = (ushort)(src[i] + delta);
-}
-
-
-static INLINE void 
-rebase_ubyte_elts( const ubyte *src,
-                   unsigned count,
-                   int delta,
-                   ushort *dest )
-{
-   unsigned i;
-   for (i = 0; i < count; i++) 
-      dest[i] = (ushort)(src[i] + delta);
-}
-
-
-static INLINE void 
-translate_uint_elts( const unsigned *src,
-                     unsigned count,
-                     ushort *dest )
-{
-   unsigned i;
-   for (i = 0; i < count; i++) 
-      dest[i] = (ushort)(src[i]);
-}
-
-
-static INLINE void 
-translate_ushort_elts( const ushort *src,
-                       unsigned count,
-                       ushort *dest )
-{
-   unsigned i;
-   for (i = 0; i < count; i++) 
-      dest[i] = (ushort)(src[i]);
-}
-
-
-static INLINE void 
-translate_ubyte_elts( const ubyte *src,
-                      unsigned count,
-                      ushort *dest )
-{
-   unsigned i;
-   for (i = 0; i < count; i++) 
-      dest[i] = (ushort)(src[i]);
-}
-
-
-
-
-#if 0
-static INLINE enum pipe_format 
-format_from_get_elt( pt_elt_func get_elt )
-{
-   switch (draw->pt.user.eltSize) {
-   case 1: return PIPE_FORMAT_R8_UNORM;
-   case 2: return PIPE_FORMAT_R16_UNORM;
-   case 4: return PIPE_FORMAT_R32_UNORM;
-   default: return PIPE_FORMAT_NONE;
-   }
-}
-#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,
-                  const void *elts,
-                  int elt_bias,
-                  unsigned draw_count )
-{
-   struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; 
-   struct draw_context *draw = vcache->draw;
-   const unsigned min_index = draw->pt.user.min_index;
-   const unsigned max_index = draw->pt.user.max_index;
-   const unsigned index_size = draw->pt.user.eltSize;
-   unsigned fetch_count;
-   const ushort *transformed_elts;
-   ushort *storage = NULL;
-   boolean ok = FALSE;
-
-   /* debug: verify indexes are in range [min_index, max_index] */
-   if (0) {
-      unsigned i;
-      for (i = 0; i < draw_count; i++) {
-         if (index_size == 1) {
-            assert( ((const ubyte *) elts)[i] >= min_index);
-            assert( ((const ubyte *) elts)[i] <= max_index);
-         }
-         else if (index_size == 2) {
-            assert( ((const ushort *) elts)[i] >= min_index);
-            assert( ((const ushort *) elts)[i] <= max_index);
-         }
-         else {
-            assert(index_size == 4);
-            assert( ((const uint *) elts)[i] >= min_index);
-            assert( ((const uint *) elts)[i] <= max_index);
-         }
-      }
-   }
-
-   /* Note: max_index is frequently 0xffffffff so we have to be sure
-    * that any arithmetic involving max_index doesn't overflow!
-    */
-   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)
-      debug_printf("fetch_count %d fetch_max %d draw_count %d\n", fetch_count, 
-                   vcache->fetch_max,
-                   draw_count);
-
-   if (elt_bias + max_index >= DRAW_PIPE_MAX_VERTICES ||
-       fetch_count >= UNDEFINED_VERTEX_ID ||
-       fetch_count > draw_count) {
-      if (0) debug_printf("fail\n");
-      goto fail;
-   }
-
-   if (vcache->middle_prim != vcache->input_prim) {
-      vcache->middle_prim = vcache->input_prim;
-      vcache->middle->prepare( vcache->middle,
-                               vcache->middle_prim,
-                               vcache->opt,
-                               &vcache->fetch_max );
-   }
-
-   assert((elt_bias >= 0 && min_index + elt_bias >= min_index) ||
-          (elt_bias <  0 && min_index + elt_bias <  min_index));
-
-   if (min_index == 0 &&
-       index_size == 2) {
-      transformed_elts = (const ushort *)elts;
-   }
-   else {
-      storage = MALLOC( draw_count * sizeof(ushort) );
-      if (!storage)
-         goto fail;
-      
-      if (min_index == 0) {
-         switch(index_size) {
-         case 1:
-            translate_ubyte_elts( (const ubyte *)elts,
-                                  draw_count,
-                                  storage );
-            break;
-
-         case 2:
-            translate_ushort_elts( (const ushort *)elts,
-                                   draw_count,
-                                   storage );
-            break;
-
-         case 4:
-            translate_uint_elts( (const uint *)elts,
-                                 draw_count,
-                                 storage );
-            break;
-
-         default:
-            assert(0);
-            FREE(storage);
-            return;
-         }
-      }
-      else {
-         switch(index_size) {
-         case 1:
-            rebase_ubyte_elts( (const ubyte *)elts,
-                               draw_count,
-                               0 - (int)min_index,
-                               storage );
-            break;
-
-         case 2:
-            rebase_ushort_elts( (const ushort *)elts,
-                                draw_count,
-                                0 - (int)min_index,
-                                storage );
-            break;
-
-         case 4:
-            rebase_uint_elts( (const uint *)elts,
-                              draw_count,
-                              0 - (int)min_index,
-                              storage );
-            break;
-
-         default:
-            assert(0);
-            FREE(storage);
-            return;
-         }
-      }
-      transformed_elts = storage;
-   }
-
-   if (fetch_count < UNDEFINED_VERTEX_ID)
-      ok = vcache->middle->run_linear_elts( vcache->middle,
-                                            min_index + elt_bias, /* start */
-                                            fetch_count,
-                                            transformed_elts,
-                                            draw_count );
-   
-   FREE(storage);
-
-   if (ok)
-      return;
-
-   debug_printf("failed to execute atomic draw elts for %d/%d, splitting up\n",
-                fetch_count, draw_count);
-
-fail:
-   vcache_run( frontend, get_elt, elts, elt_bias, draw_count );
-}
-
-
-
-
-static void
-vcache_prepare( struct draw_pt_front_end *frontend,
-                unsigned in_prim,
-                struct draw_pt_middle_end *middle,
-                unsigned opt )
-{
-   struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
-
-   if (opt & PT_PIPELINE) {
-      vcache->base.run = vcache_run_extras;
-   }
-   else {
-      vcache->base.run = vcache_check_run;
-   }
-
-   /* VCache will always emit the reduced version of its input
-    * primitive, ie STRIP/FANS become TRIS, etc.
-    *
-    * This is not to be confused with what the GS might be up to,
-    * which is a separate issue.
-    */
-   vcache->input_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;
-
-   /* Have to run prepare here, but try and guess a good prim for
-    * doing so:
-    */
-   vcache->middle_prim = (opt & PT_PIPELINE)
-      ? vcache->output_prim : vcache->input_prim;
-
-   middle->prepare( middle,
-                    vcache->middle_prim,
-                    opt, &vcache->fetch_max );
-}
-
-
-static void 
-vcache_finish( struct draw_pt_front_end *frontend )
-{
-   struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
-   vcache->middle->finish( vcache->middle );
-   vcache->middle = NULL;
-}
-
-
-static void 
-vcache_destroy( struct draw_pt_front_end *frontend )
-{
-   FREE(frontend);
-}
-
-
-struct draw_pt_front_end *draw_pt_vcache( struct draw_context *draw )
-{
-   struct vcache_frontend *vcache = CALLOC_STRUCT( vcache_frontend );
-   if (vcache == NULL)
-      return NULL;
-   vcache->base.prepare = vcache_prepare;
-   vcache->base.run     = NULL;
-   vcache->base.finish  = vcache_finish;
-   vcache->base.destroy = vcache_destroy;
-   vcache->draw = draw;
-   
-   memset(vcache->in, ~0, sizeof(vcache->in));
-  
-   return &vcache->base;
-}
diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h b/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h
deleted file mode 100644 (file)
index 1a3748d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#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);
-
-#define GET_ELT(idx) (get_elt(elts, idx) + elt_bias)
-
-#define FUNC_EXIT do { vcache_flush(vcache); } while (0)
-
-#include "draw_decompose_tmp.h"
diff --git a/src/gallium/auxiliary/draw/draw_pt_vsplit.c b/src/gallium/auxiliary/draw/draw_pt_vsplit.c
new file mode 100644 (file)
index 0000000..a687525
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * Copyright 2007-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.
+ */
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_pt.h"
+
+#define SEGMENT_SIZE 1024
+#define MAP_SIZE     256
+
+struct vsplit_frontend {
+   struct draw_pt_front_end base;
+   struct draw_context *draw;
+
+   unsigned prim;
+
+   struct draw_pt_middle_end *middle;
+
+   unsigned max_vertices;
+   ushort segment_size;
+
+   /* buffers for splitting */
+   unsigned fetch_elts[SEGMENT_SIZE];
+   ushort draw_elts[SEGMENT_SIZE];
+   ushort identity_draw_elts[SEGMENT_SIZE];
+
+   struct {
+      /* map a fetch element to a draw element */
+      unsigned fetches[MAP_SIZE];
+      ushort draws[MAP_SIZE];
+      boolean has_max_fetch;
+
+      ushort num_fetch_elts;
+      ushort num_draw_elts;
+   } cache;
+};
+
+
+static void
+vsplit_clear_cache(struct vsplit_frontend *vsplit)
+{
+   memset(vsplit->cache.fetches, 0xff, sizeof(vsplit->cache.fetches));
+   vsplit->cache.has_max_fetch = FALSE;
+   vsplit->cache.num_fetch_elts = 0;
+   vsplit->cache.num_draw_elts = 0;
+}
+
+static void
+vsplit_flush_cache(struct vsplit_frontend *vsplit, unsigned flags)
+{
+   vsplit->middle->run(vsplit->middle,
+         vsplit->fetch_elts, vsplit->cache.num_fetch_elts,
+         vsplit->draw_elts, vsplit->cache.num_draw_elts, flags);
+}
+
+/**
+ * Add a fetch element and add it to the draw elements.
+ */
+static INLINE void
+vsplit_add_cache(struct vsplit_frontend *vsplit, unsigned fetch)
+{
+   unsigned hash = fetch % MAP_SIZE;
+
+   if (vsplit->cache.fetches[hash] != fetch) {
+      /* update cache */
+      vsplit->cache.fetches[hash] = fetch;
+      vsplit->cache.draws[hash] = vsplit->cache.num_fetch_elts;
+
+      /* add fetch */
+      assert(vsplit->cache.num_fetch_elts < vsplit->segment_size);
+      vsplit->fetch_elts[vsplit->cache.num_fetch_elts++] = fetch;
+   }
+
+   vsplit->draw_elts[vsplit->cache.num_draw_elts++] = vsplit->cache.draws[hash];
+}
+
+
+/**
+ * Add a fetch element and add it to the draw elements.  The fetch element is
+ * in full range (uint).
+ */
+static INLINE void
+vsplit_add_cache_uint(struct vsplit_frontend *vsplit, unsigned fetch)
+{
+   /* special care for 0xffffffff */
+   if (fetch == 0xffffffff && !vsplit->cache.has_max_fetch) {
+      unsigned hash = fetch % MAP_SIZE;
+      vsplit->cache.fetches[hash] = fetch - 1; /* force update */
+      vsplit->cache.has_max_fetch = TRUE;
+   }
+
+   vsplit_add_cache(vsplit, fetch);
+}
+
+
+#define FUNC vsplit_run_linear
+#include "draw_pt_vsplit_tmp.h"
+
+#define FUNC vsplit_run_ubyte
+#define ELT_TYPE ubyte
+#define ADD_CACHE(vsplit, fetch) vsplit_add_cache(vsplit, fetch)
+#include "draw_pt_vsplit_tmp.h"
+
+#define FUNC vsplit_run_ushort
+#define ELT_TYPE ushort
+#define ADD_CACHE(vsplit, fetch) vsplit_add_cache(vsplit, fetch)
+#include "draw_pt_vsplit_tmp.h"
+
+#define FUNC vsplit_run_uint
+#define ELT_TYPE uint
+#define ADD_CACHE(vsplit, fetch) vsplit_add_cache_uint(vsplit, fetch)
+#include "draw_pt_vsplit_tmp.h"
+
+
+static void vsplit_prepare(struct draw_pt_front_end *frontend,
+                           unsigned in_prim,
+                           struct draw_pt_middle_end *middle,
+                           unsigned opt)
+{
+   struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend;
+
+   switch (vsplit->draw->pt.user.eltSize) {
+   case 0:
+      vsplit->base.run = vsplit_run_linear;
+      break;
+   case 1:
+      vsplit->base.run = vsplit_run_ubyte;
+      break;
+   case 2:
+      vsplit->base.run = vsplit_run_ushort;
+      break;
+   case 4:
+      vsplit->base.run = vsplit_run_uint;
+      break;
+   default:
+      assert(0);
+      break;
+   }
+
+   /* split only */
+   vsplit->prim = in_prim;
+
+   vsplit->middle = middle;
+   middle->prepare(middle, vsplit->prim, opt, &vsplit->max_vertices);
+
+   vsplit->segment_size = MIN2(SEGMENT_SIZE, vsplit->max_vertices);
+}
+
+
+static void vsplit_finish(struct draw_pt_front_end *frontend)
+{
+   struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend;
+   vsplit->middle->finish(vsplit->middle);
+   vsplit->middle = NULL;
+}
+
+
+static void vsplit_destroy(struct draw_pt_front_end *frontend)
+{
+   FREE(frontend);
+}
+
+
+struct draw_pt_front_end *draw_pt_vsplit(struct draw_context *draw)
+{
+   struct vsplit_frontend *vsplit = CALLOC_STRUCT(vsplit_frontend);
+   ushort i;
+
+   if (!vsplit)
+      return NULL;
+
+   vsplit->base.prepare = vsplit_prepare;
+   vsplit->base.run     = NULL;
+   vsplit->base.finish  = vsplit_finish;
+   vsplit->base.destroy = vsplit_destroy;
+   vsplit->draw = draw;
+
+   for (i = 0; i < SEGMENT_SIZE; i++)
+      vsplit->identity_draw_elts[i] = i;
+
+   return &vsplit->base;
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h b/src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h
new file mode 100644 (file)
index 0000000..3f66f96
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * Copyright 2007-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.
+ */
+
+#define CONCAT2(name, elt_type) name ## elt_type
+#define CONCAT(name, elt_type) CONCAT2(name, elt_type)
+
+#ifdef ELT_TYPE
+
+/**
+ * Fetch all elements in [min_index, max_index] with bias, and use the
+ * (rebased) index buffer as the draw elements.
+ */
+static boolean
+CONCAT(vsplit_primitive_, ELT_TYPE)(struct vsplit_frontend *vsplit,
+                                    unsigned istart, unsigned icount)
+{
+   struct draw_context *draw = vsplit->draw;
+   const ELT_TYPE *ib = (const ELT_TYPE *)
+      ((const char *) draw->pt.user.elts + draw->pt.index_buffer.offset);
+   const unsigned min_index = draw->pt.user.min_index;
+   const unsigned max_index = draw->pt.user.max_index;
+   const int elt_bias = draw->pt.user.eltBias;
+   unsigned fetch_start, fetch_count;
+   const ushort *draw_elts = NULL;
+   unsigned i;
+
+   /* use the ib directly */
+   if (min_index == 0 && sizeof(ib[0]) == sizeof(draw_elts[0])) {
+      if (icount > vsplit->max_vertices)
+         return FALSE;
+
+      for (i = 0; i < icount; i++) {
+         ELT_TYPE idx = ib[istart + i];
+         assert(idx >= min_index && idx <= max_index);
+      }
+      draw_elts = (const ushort *) ib;
+   }
+   else {
+      /* have to go through vsplit->draw_elts */
+      if (icount > vsplit->segment_size)
+         return FALSE;
+   }
+
+   /* this is faster only when we fetch less elements than the normal path */
+   if (max_index - min_index > icount - 1)
+      return FALSE;
+
+   if (elt_bias < 0 && min_index < -elt_bias)
+      return FALSE;
+
+   /* why this check? */
+   for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
+      if (draw->pt.vertex_element[i].instance_divisor)
+         return FALSE;
+   }
+
+   fetch_start = min_index + elt_bias;
+   fetch_count = max_index - min_index + 1;
+
+   if (!draw_elts) {
+      if (min_index == 0) {
+         for (i = 0; i < icount; i++) {
+            ELT_TYPE idx = ib[istart + i];
+
+            assert(idx >= min_index && idx <= max_index);
+            vsplit->draw_elts[i] = (ushort) idx;
+         }
+      }
+      else {
+         for (i = 0; i < icount; i++) {
+            ELT_TYPE idx = ib[istart + i];
+
+            assert(idx >= min_index && idx <= max_index);
+            vsplit->draw_elts[i] = (ushort) (idx - min_index);
+         }
+      }
+
+      draw_elts = vsplit->draw_elts;
+   }
+
+   return vsplit->middle->run_linear_elts(vsplit->middle,
+                                          fetch_start, fetch_count,
+                                          draw_elts, icount, 0x0);
+}
+
+/**
+ * Use the cache to prepare the fetch and draw elements, and flush.
+ *
+ * When spoken is TRUE, ispoken replaces istart;  When close is TRUE, iclose is
+ * appended.
+ */
+static INLINE void
+CONCAT(vsplit_segment_cache_, ELT_TYPE)(struct vsplit_frontend *vsplit,
+                                        unsigned flags,
+                                        unsigned istart, unsigned icount,
+                                        boolean spoken, unsigned ispoken,
+                                        boolean close, unsigned iclose)
+{
+   struct draw_context *draw = vsplit->draw;
+   const ELT_TYPE *ib = (const ELT_TYPE *)
+      ((const char *) draw->pt.user.elts + draw->pt.index_buffer.offset);
+   const int ibias = draw->pt.user.eltBias;
+   unsigned i;
+
+   assert(icount + !!close <= vsplit->segment_size);
+
+   vsplit_clear_cache(vsplit);
+
+   spoken = !!spoken;
+   if (ibias == 0) {
+      if (spoken)
+         ADD_CACHE(vsplit, ib[ispoken]);
+
+      for (i = spoken; i < icount; i++)
+         ADD_CACHE(vsplit, ib[istart + i]);
+
+      if (close)
+         ADD_CACHE(vsplit, ib[iclose]);
+   }
+   else if (ibias > 0) {
+      if (spoken)
+         ADD_CACHE(vsplit, (uint) ib[ispoken] + ibias);
+
+      for (i = spoken; i < icount; i++)
+         ADD_CACHE(vsplit, (uint) ib[istart + i] + ibias);
+
+      if (close)
+         ADD_CACHE(vsplit, (uint) ib[iclose] + ibias);
+   }
+   else {
+      if (spoken) {
+         if (ib[ispoken] < -ibias)
+            return;
+         ADD_CACHE(vsplit, ib[ispoken] + ibias);
+      }
+
+      for (i = spoken; i < icount; i++) {
+         if (ib[istart + i] < -ibias)
+            return;
+         ADD_CACHE(vsplit, ib[istart + i] + ibias);
+      }
+
+      if (close) {
+         if (ib[iclose] < -ibias)
+            return;
+         ADD_CACHE(vsplit, ib[iclose] + ibias);
+      }
+   }
+
+   vsplit_flush_cache(vsplit, flags);
+}
+
+static void
+CONCAT(vsplit_segment_simple_, ELT_TYPE)(struct vsplit_frontend *vsplit,
+                                         unsigned flags,
+                                         unsigned istart,
+                                         unsigned icount)
+{
+   CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit,
+         flags, istart, icount, FALSE, 0, FALSE, 0);
+}
+
+static void
+CONCAT(vsplit_segment_loop_, ELT_TYPE)(struct vsplit_frontend *vsplit,
+                                       unsigned flags,
+                                       unsigned istart,
+                                       unsigned icount,
+                                       unsigned i0)
+{
+   const boolean close_loop = ((flags) == DRAW_SPLIT_BEFORE);
+
+   CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit,
+         flags, istart, icount, FALSE, 0, close_loop, i0);
+}
+
+static void
+CONCAT(vsplit_segment_fan_, ELT_TYPE)(struct vsplit_frontend *vsplit,
+                                      unsigned flags,
+                                      unsigned istart,
+                                      unsigned icount,
+                                      unsigned i0)
+{
+   const boolean use_spoken = (((flags) & DRAW_SPLIT_BEFORE) != 0);
+
+   CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit,
+         flags, istart, icount, use_spoken, i0, FALSE, 0);
+}
+
+#define LOCAL_VARS                                                         \
+   struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend;   \
+   const unsigned prim = vsplit->prim;                                     \
+   const unsigned max_count_simple = vsplit->segment_size;                 \
+   const unsigned max_count_loop = vsplit->segment_size - 1;               \
+   const unsigned max_count_fan = vsplit->segment_size;
+
+#define PRIMITIVE(istart, icount)   \
+   CONCAT(vsplit_primitive_, ELT_TYPE)(vsplit, istart, icount)
+
+#else /* ELT_TYPE */
+
+static void
+vsplit_segment_simple_linear(struct vsplit_frontend *vsplit, unsigned flags,
+                             unsigned istart, unsigned icount)
+{
+   assert(icount <= vsplit->max_vertices);
+   vsplit->middle->run_linear(vsplit->middle, istart, icount, flags);
+}
+
+static void
+vsplit_segment_loop_linear(struct vsplit_frontend *vsplit, unsigned flags,
+                           unsigned istart, unsigned icount, unsigned i0)
+{
+   boolean close_loop = (flags == DRAW_SPLIT_BEFORE);
+   unsigned nr;
+
+   assert(icount + !!close_loop <= vsplit->segment_size);
+
+   if (close_loop) {
+      for (nr = 0; nr < icount; nr++)
+         vsplit->fetch_elts[nr] = istart + nr;
+      vsplit->fetch_elts[nr++] = i0;
+
+      vsplit->middle->run(vsplit->middle, vsplit->fetch_elts, nr,
+            vsplit->identity_draw_elts, nr, flags);
+   }
+   else {
+      vsplit->middle->run_linear(vsplit->middle, istart, icount, flags);
+   }
+}
+
+static void
+vsplit_segment_fan_linear(struct vsplit_frontend *vsplit, unsigned flags,
+                          unsigned istart, unsigned icount, unsigned i0)
+{
+   boolean use_spoken = ((flags & DRAW_SPLIT_BEFORE) != 0);
+   unsigned nr = 0, i;
+
+   assert(icount + !!use_spoken <= vsplit->segment_size);
+
+   if (use_spoken) {
+      vsplit->fetch_elts[nr++] = i0;
+      for (i = 1 ; i < icount; i++)
+         vsplit->fetch_elts[nr++] = istart + i;
+
+      vsplit->middle->run(vsplit->middle, vsplit->fetch_elts, nr,
+            vsplit->identity_draw_elts, nr, flags);
+   }
+   else {
+      vsplit->middle->run_linear(vsplit->middle, istart, icount, flags);
+   }
+}
+
+#define LOCAL_VARS                                                         \
+   struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend;   \
+   const unsigned prim = vsplit->prim;                                     \
+   const unsigned max_count_simple = vsplit->max_vertices;                 \
+   const unsigned max_count_loop = vsplit->segment_size - 1;               \
+   const unsigned max_count_fan = vsplit->segment_size;
+
+#define PRIMITIVE(istart, icount) FALSE
+
+#define ELT_TYPE linear
+
+#endif /* ELT_TYPE */
+
+#define FUNC_VARS                      \
+   struct draw_pt_front_end *frontend, \
+   unsigned start,                     \
+   unsigned count
+
+#define SEGMENT_SIMPLE(flags, istart, icount)   \
+   CONCAT(vsplit_segment_simple_, ELT_TYPE)(vsplit, flags, istart, icount)
+
+#define SEGMENT_LOOP(flags, istart, icount, i0) \
+   CONCAT(vsplit_segment_loop_, ELT_TYPE)(vsplit, flags, istart, icount, i0)
+
+#define SEGMENT_FAN(flags, istart, icount, i0)  \
+   CONCAT(vsplit_segment_fan_, ELT_TYPE)(vsplit, flags, istart, icount, i0)
+
+#include "draw_split_tmp.h"
+
+#undef CONCAT2
+#undef CONCAT
+
+#undef ELT_TYPE
+#undef ADD_CACHE
index 6d8937a0b41b99c289a3fee55a9b2cd1e4a2d02c..7fafde9d5e6605d5a2c5c78e2c11ec61a3325671 100644 (file)
@@ -7,11 +7,9 @@
 
 #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);                       \
+   const unsigned prim_flags = input_prims->flags;                \
+   const boolean last_vertex_last = TRUE;                         \
    do {                                                           \
       debug_assert(input_prims->primitive_count == 1);            \
       switch (prim) {                                             \
diff --git a/src/gallium/auxiliary/draw/draw_split_tmp.h b/src/gallium/auxiliary/draw/draw_split_tmp.h
new file mode 100644 (file)
index 0000000..47defc6
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+static void
+FUNC(FUNC_VARS)
+{
+   unsigned first, incr;
+   LOCAL_VARS
+
+   /*
+    * prim, start, count, and max_count_{simple,loop,fan} should have been
+    * defined
+    */
+   if (0) {
+      debug_printf("%s: prim 0x%x, start %d, count %d, max_count_simple %d, "
+                   "max_count_loop %d, max_count_fan %d\n",
+                   __FUNCTION__, prim, start, count, max_count_simple,
+                   max_count_loop, max_count_fan);
+   }
+
+   draw_pt_split_prim(prim, &first, &incr);
+   /* sanitize primitive length */
+   count = draw_pt_trim_count(count, first, incr);
+   if (count < first)
+      return;
+
+   /* try flushing the entire primitive */
+   if (PRIMITIVE(start, count))
+      return;
+
+   /* must be able to at least flush two complete primitives */
+   assert(max_count_simple >= first + incr &&
+          max_count_loop >= first + incr &&
+          max_count_fan >= first + incr);
+
+   /* no splitting required */
+   if (count <= max_count_simple) {
+      SEGMENT_SIMPLE(0x0, start, count);
+   }
+   else {
+      const unsigned rollback = first - incr;
+      unsigned flags = DRAW_SPLIT_AFTER, seg_start = 0, seg_max;
+
+      /*
+       * Both count and seg_max below are explicitly trimmed.  Because
+       *
+       *   seg_start = N * (seg_max - rollback) = N' * incr,
+       *
+       * we have
+       *
+       *   remaining = count - seg_start = first + N'' * incr.
+       *
+       * That is, remaining is implicitly trimmed.
+       */
+      switch (prim) {
+      case PIPE_PRIM_POINTS:
+      case PIPE_PRIM_LINES:
+      case PIPE_PRIM_LINE_STRIP:
+      case PIPE_PRIM_TRIANGLES:
+      case PIPE_PRIM_TRIANGLE_STRIP:
+      case PIPE_PRIM_QUADS:
+      case PIPE_PRIM_QUAD_STRIP:
+      case PIPE_PRIM_LINES_ADJACENCY:
+      case PIPE_PRIM_LINE_STRIP_ADJACENCY:
+      case PIPE_PRIM_TRIANGLES_ADJACENCY:
+      case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
+         seg_max =
+            draw_pt_trim_count(MIN2(max_count_simple, count), first, incr);
+         if (prim == PIPE_PRIM_TRIANGLE_STRIP ||
+             prim == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY) {
+            /* make sure we flush even number of triangles at a time */
+            if (seg_max < count && !(((seg_max - first) / incr) & 1))
+               seg_max -= incr;
+         }
+
+         do {
+            const unsigned remaining = count - seg_start;
+
+            if (remaining > seg_max) {
+               SEGMENT_SIMPLE(flags, start + seg_start, seg_max);
+               seg_start += seg_max - rollback;
+
+               flags |= DRAW_SPLIT_BEFORE;
+            }
+            else {
+               flags &= ~DRAW_SPLIT_AFTER;
+
+               SEGMENT_SIMPLE(flags, start + seg_start, remaining);
+               seg_start += remaining;
+            }
+         } while (seg_start < count);
+         break;
+
+      case PIPE_PRIM_LINE_LOOP:
+         seg_max =
+            draw_pt_trim_count(MIN2(max_count_loop, count), first, incr);
+
+         do {
+            const unsigned remaining = count - seg_start;
+
+            if (remaining > seg_max) {
+               SEGMENT_LOOP(flags, start + seg_start, seg_max, start);
+               seg_start += seg_max - rollback;
+
+               flags |= DRAW_SPLIT_BEFORE;
+            }
+            else {
+               flags &= ~DRAW_SPLIT_AFTER;
+
+               SEGMENT_LOOP(flags, start + seg_start, remaining, start);
+               seg_start += remaining;
+            }
+         } while (seg_start < count);
+         break;
+
+      case PIPE_PRIM_TRIANGLE_FAN:
+      case PIPE_PRIM_POLYGON:
+         seg_max =
+            draw_pt_trim_count(MIN2(max_count_fan, count), first, incr);
+
+         do {
+            const unsigned remaining = count - seg_start;
+
+            if (remaining > seg_max) {
+               SEGMENT_FAN(flags, start + seg_start, seg_max, start);
+               seg_start += seg_max - rollback;
+
+               flags |= DRAW_SPLIT_BEFORE;
+            }
+            else {
+               flags &= ~DRAW_SPLIT_AFTER;
+
+               SEGMENT_FAN(flags, start + seg_start, remaining, start);
+               seg_start += remaining;
+            }
+         } while (seg_start < count);
+         break;
+
+      default:
+         assert(0);
+         break;
+      }
+   }
+}
+
+#undef FUNC
+#undef FUNC_VARS
+#undef LOCAL_VARS
+
+#undef PRIMITIVE
+#undef SEGMENT_SIMPLE
+#undef SEGMENT_LOOP
+#undef SEGMENT_FAN
index d13ad24fff0bf50d8485f55001ba2078a3003c1e..fa9992db78324f9ffd2f6f595cc95c6a878530d7 100644 (file)
@@ -28,6 +28,7 @@
 #include "util/u_math.h"
 #include "util/u_memory.h"
 #include "pipe/p_shader_tokens.h"
+#include "pipe/p_screen.h"
 
 #include "draw_private.h"
 #include "draw_context.h"
@@ -109,6 +110,11 @@ draw_create_vs_llvm(struct draw_context *draw,
 
    tgsi_scan_shader(state->tokens, &vs->base.info);
 
+   vs->variant_key_size = 
+      draw_llvm_variant_key_size(
+        vs->base.info.file_max[TGSI_FILE_INPUT]+1,
+        vs->base.info.file_max[TGSI_FILE_SAMPLER]+1);
+
    vs->base.draw = draw;
    vs->base.prepare = vs_llvm_prepare;
    vs->base.run_linear = vs_llvm_run_linear;
index 7b35dd4bb49cead48526a54f198c3404d9f0c248..e0d30be98d9749db0c57c49afe65242d52dfa931 100644 (file)
 #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
@@ -267,7 +259,7 @@ lp_build_add(struct lp_build_context *bld,
 }
 
 
-/** Return the sum of the elements of a */
+/** Return the scalar sum of the elements of a */
 LLVMValueRef
 lp_build_sum_vector(struct lp_build_context *bld,
                     LLVMValueRef a)
@@ -278,11 +270,9 @@ lp_build_sum_vector(struct lp_build_context *bld,
 
    assert(lp_check_value(type, a));
 
-   if (a == bld->zero)
-      return bld->zero;
-   if (a == bld->undef)
-      return bld->undef;
-   assert(type.length > 1);
+   if (type.length == 1) {
+      return a;
+   }
 
    assert(!bld->type.norm);
 
@@ -546,7 +536,7 @@ lp_build_mul_imm(struct lp_build_context *bld,
    if(b == 2 && bld->type.floating)
       return lp_build_add(bld, a, a);
 
-   if(util_is_pot(b)) {
+   if(util_is_power_of_two(b)) {
       unsigned shift = ffs(b) - 1;
 
       if(bld->type.floating) {
@@ -1266,6 +1256,11 @@ lp_build_sqrt(struct lp_build_context *bld,
  *
  *   x_{i+1} = x_i * (2 - a * x_i)
  *
+ * XXX: Unfortunately this won't give IEEE-754 conformant results for 0 or
+ * +/-Inf, giving NaN instead.  Certain applications rely on this behavior,
+ * such as Google Earth, which does RCP(RSQRT(0.0) when drawing the Earth's
+ * halo. It would be necessary to clamp the argument to prevent this.
+ *
  * See also:
  * - http://en.wikipedia.org/wiki/Division_(digital)#Newton.E2.80.93Raphson_division
  * - http://softwarecommunity.intel.com/articles/eng/1818.htm
@@ -1306,13 +1301,27 @@ lp_build_rcp(struct lp_build_context *bld,
    if(LLVMIsConstant(a))
       return LLVMConstFDiv(bld->one, a);
 
-   if(util_cpu_caps.has_sse && type.width == 32 && type.length == 4) {
+   /*
+    * We don't use RCPPS because:
+    * - it only has 10bits of precision
+    * - it doesn't even get the reciprocate of 1.0 exactly
+    * - doing Newton-Rapshon steps yields wrong (NaN) values for 0.0 or Inf
+    * - for recent processors the benefit over DIVPS is marginal, a case
+    *   depedent
+    *
+    * We could still use it on certain processors if benchmarks show that the
+    * RCPPS plus necessary workarounds are still preferrable to DIVPS; or for
+    * particular uses that require less workarounds.
+    */
+
+   if (FALSE && util_cpu_caps.has_sse && type.width == 32 && type.length == 4) {
+      const unsigned num_iterations = 0;
       LLVMValueRef res;
       unsigned i;
 
       res = lp_build_intrinsic_unary(bld->builder, "llvm.x86.sse.rcp.ps", bld->vec_type, a);
 
-      for (i = 0; i < RCP_NEWTON_STEPS; ++i) {
+      for (i = 0; i < num_iterations; ++i) {
          res = lp_build_rcp_refine(bld, a, res);
       }
 
@@ -1363,13 +1372,14 @@ lp_build_rsqrt(struct lp_build_context *bld,
 
    assert(type.floating);
 
-   if(util_cpu_caps.has_sse && type.width == 32 && type.length == 4) {
+   if (util_cpu_caps.has_sse && type.width == 32 && type.length == 4) {
+      const unsigned num_iterations = 0;
       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) {
+      for (i = 0; i < num_iterations; ++i) {
          res = lp_build_rsqrt_refine(bld, a, res);
       }
 
index 39dfc51e50331b6cabeaa2f076a2fc069f610b9f..d3a5afff8c23029bd7c45a4e63632d5252e37e30 100644 (file)
@@ -46,7 +46,7 @@
 boolean
 lp_check_alignment(const void *ptr, unsigned alignment)
 {
-   assert(util_is_pot(alignment));
+   assert(util_is_power_of_two(alignment));
    return ((uintptr_t)ptr & (alignment - 1)) == 0;
 }
 
index 247cb83ce6c4dcce96a29732d1b0dca30e063ca9..92123e09d3289c5d00a706749928c00d7fc24994 100644 (file)
@@ -388,7 +388,7 @@ lp_build_fetch_rgba_aos(LLVMBuilderRef builder,
 
    if (format_matches_type(format_desc, type) &&
        format_desc->block.bits <= type.width * 4 &&
-       util_is_pot(format_desc->block.bits)) {
+       util_is_power_of_two(format_desc->block.bits)) {
       LLVMValueRef packed;
 
       /*
@@ -416,7 +416,7 @@ lp_build_fetch_rgba_aos(LLVMBuilderRef builder,
         format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) &&
        format_desc->block.width == 1 &&
        format_desc->block.height == 1 &&
-       util_is_pot(format_desc->block.bits) &&
+       util_is_power_of_two(format_desc->block.bits) &&
        format_desc->block.bits <= 32 &&
        format_desc->is_bitmask &&
        !format_desc->is_mixed &&
index 6d5410d9701e9e1911ebb49a582844c1d07aa105..48baf7c425c8881cf44fa225aedd5197268ea04d 100644 (file)
@@ -40,6 +40,7 @@
 #include <llvm/ExecutionEngine/ExecutionEngine.h>
 #include <llvm/ExecutionEngine/JITEventListener.h>
 #include <llvm/Support/CommandLine.h>
+#include <llvm/Support/PrettyStackTrace.h>
 
 #include "pipe/p_config.h"
 #include "util/u_debug.h"
@@ -143,7 +144,6 @@ lp_set_target_options(void)
    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
@@ -152,10 +152,8 @@ lp_set_target_options(void)
     * 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;
+   static boolean first = TRUE;
    if (first) {
       static const char* options[] = {
          "prog",
@@ -164,7 +162,13 @@ lp_set_target_options(void)
       llvm::cl::ParseCommandLineOptions(2, const_cast<char**>(options));
       first = FALSE;
    }
-#endif
+
+   /*
+    * By default LLVM adds a signal handler to output a pretty stack trace.
+    * This signal handler is never removed, causing problems when unloading the
+    * shared object where the gallium driver resides.
+    */
+   llvm::DisablePrettyStackTrace = true;
 }
 
 
index e470082b97747ce9916af3c1b21a7d527d62e2a5..e947b90d1642a2e3a880eb6d0c67d4886b701dee 100644 (file)
@@ -37,6 +37,8 @@
 #define LP_BLD_PACK_H
 
 
+#include "pipe/p_compiler.h"
+
 #include "gallivm/lp_bld.h"
 
 
index 0fd014ab9b3632d6db2b061c35e6da52da59a9bd..259b1142e3cbbf5b93438db86c3ec735c1e35e97 100644 (file)
@@ -82,9 +82,9 @@ lp_sampler_static_state(struct lp_sampler_static_state *state,
    state->swizzle_a         = view->swizzle_a;
 
    state->target            = texture->target;
-   state->pot_width         = util_is_pot(texture->width0);
-   state->pot_height        = util_is_pot(texture->height0);
-   state->pot_depth         = util_is_pot(texture->depth0);
+   state->pot_width         = util_is_power_of_two(texture->width0);
+   state->pot_height        = util_is_power_of_two(texture->height0);
+   state->pot_depth         = util_is_power_of_two(texture->depth0);
 
    state->wrap_s            = sampler->wrap_s;
    state->wrap_t            = sampler->wrap_t;
@@ -123,6 +123,52 @@ lp_sampler_static_state(struct lp_sampler_static_state *state,
 }
 
 
+/**
+ * Compute the partial offset of a pixel block along an arbitrary axis.
+ *
+ * @param coord   coordinate in pixels
+ * @param stride  number of bytes between rows of successive pixel blocks
+ * @param block_length  number of pixels in a pixels block along the coordinate
+ *                      axis
+ * @param out_offset    resulting relative offset of the pixel block in bytes
+ * @param out_subcoord  resulting sub-block pixel coordinate
+ */
+void
+lp_build_sample_partial_offset(struct lp_build_context *bld,
+                               unsigned block_length,
+                               LLVMValueRef coord,
+                               LLVMValueRef stride,
+                               LLVMValueRef *out_offset,
+                               LLVMValueRef *out_subcoord)
+{
+   LLVMValueRef offset;
+   LLVMValueRef subcoord;
+
+   if (block_length == 1) {
+      subcoord = bld->zero;
+   }
+   else {
+      /*
+       * Pixel blocks have power of two dimensions. LLVM should convert the
+       * rem/div to bit arithmetic.
+       * TODO: Verify this.
+       */
+
+      LLVMValueRef block_width = lp_build_const_int_vec(bld->type, block_length);
+      subcoord = LLVMBuildURem(bld->builder, coord, block_width, "");
+      coord    = LLVMBuildUDiv(bld->builder, coord, block_width, "");
+   }
+
+   offset = lp_build_mul(bld, coord, stride);
+
+   assert(out_offset);
+   assert(out_subcoord);
+
+   *out_offset = offset;
+   *out_subcoord = subcoord;
+}
+
+
 /**
  * Compute the offset of a pixel block.
  *
@@ -144,48 +190,35 @@ lp_build_sample_offset(struct lp_build_context *bld,
 {
    LLVMValueRef x_stride;
    LLVMValueRef offset;
-   LLVMValueRef i;
-   LLVMValueRef j;
-
-   /*
-    * Describe the coordinates in terms of pixel blocks.
-    *
-    * TODO: pixel blocks are power of two. LLVM should convert rem/div to
-    * bit arithmetic. Verify this.
-    */
-
-   if (format_desc->block.width == 1) {
-      i = bld->zero;
-   }
-   else {
-      LLVMValueRef block_width = lp_build_const_int_vec(bld->type, format_desc->block.width);
-      i = LLVMBuildURem(bld->builder, x, block_width, "");
-      x = LLVMBuildUDiv(bld->builder, x, block_width, "");
-   }
-
-   if (format_desc->block.height == 1) {
-      j = bld->zero;
-   }
-   else {
-      LLVMValueRef block_height = lp_build_const_int_vec(bld->type, format_desc->block.height);
-      j = LLVMBuildURem(bld->builder, y, block_height, "");
-      y = LLVMBuildUDiv(bld->builder, y, block_height, "");
-   }
 
    x_stride = lp_build_const_vec(bld->type, format_desc->block.bits/8);
-   offset = lp_build_mul(bld, x, x_stride);
+
+   lp_build_sample_partial_offset(bld,
+                                  format_desc->block.width,
+                                  x, x_stride,
+                                  &offset, out_i);
 
    if (y && y_stride) {
-      LLVMValueRef y_offset = lp_build_mul(bld, y, y_stride);
+      LLVMValueRef y_offset;
+      lp_build_sample_partial_offset(bld,
+                                     format_desc->block.height,
+                                     y, y_stride,
+                                     &y_offset, out_j);
       offset = lp_build_add(bld, offset, y_offset);
    }
+   else {
+      *out_j = bld->zero;
+   }
 
    if (z && z_stride) {
-      LLVMValueRef z_offset = lp_build_mul(bld, z, z_stride);
+      LLVMValueRef z_offset;
+      LLVMValueRef k;
+      lp_build_sample_partial_offset(bld,
+                                     1, /* pixel blocks are always 2D */
+                                     z, z_stride,
+                                     &z_offset, &k);
       offset = lp_build_add(bld, offset, z_offset);
    }
 
    *out_offset = offset;
-   *out_i = i;
-   *out_j = j;
 }
index 5b8f478094b1aa95564c8894396e803d64de53b1..caafc4eca04f7919ee31c87bd2651a6c33d771a3 100644 (file)
@@ -36,6 +36,8 @@
 #define LP_BLD_SAMPLE_H
 
 
+#include "pipe/p_format.h"
+
 #include "gallivm/lp_bld.h"
 
 struct pipe_resource;
@@ -146,6 +148,15 @@ lp_sampler_static_state(struct lp_sampler_static_state *state,
                         const struct pipe_sampler_state *sampler);
 
 
+void
+lp_build_sample_partial_offset(struct lp_build_context *bld,
+                               unsigned block_length,
+                               LLVMValueRef coord,
+                               LLVMValueRef stride,
+                               LLVMValueRef *out_offset,
+                               LLVMValueRef *out_i);
+
+
 void
 lp_build_sample_offset(struct lp_build_context *bld,
                        const struct util_format_description *format_desc,
index 806c7d56a87529a1291d3a802298d2080671fc88..1f39d9c98b5cb3082eb03d7bebd51ee69572a9db 100644 (file)
@@ -176,6 +176,7 @@ texture_dims(enum pipe_texture_target tex)
    case PIPE_TEXTURE_1D:
       return 1;
    case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_RECT:
    case PIPE_TEXTURE_CUBE:
       return 2;
    case PIPE_TEXTURE_3D:
@@ -321,59 +322,6 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
 }
 
 
-/**
- * Fetch the texels as <4n x i8> in AoS form.
- */
-static LLVMValueRef
-lp_build_sample_packed(struct lp_build_sample_context *bld,
-                       LLVMValueRef x,
-                       LLVMValueRef y,
-                       LLVMValueRef y_stride,
-                       LLVMValueRef data_array)
-{
-   LLVMValueRef offset, i, j;
-   LLVMValueRef data_ptr;
-   LLVMValueRef res;
-
-   /* convert x,y,z coords to linear offset from start of texture, in bytes */
-   lp_build_sample_offset(&bld->uint_coord_bld,
-                          bld->format_desc,
-                          x, y, NULL, y_stride, NULL,
-                          &offset, &i, &j);
-
-   /* get pointer to mipmap level 0 data */
-   data_ptr = lp_build_get_const_mipmap_level(bld, data_array, 0);
-
-   if (util_format_is_rgba8_variant(bld->format_desc)) {
-      /* Just fetch the data directly without swizzling */
-      assert(bld->format_desc->block.width == 1);
-      assert(bld->format_desc->block.height == 1);
-      assert(bld->format_desc->block.bits <= bld->texel_type.width);
-
-      res = lp_build_gather(bld->builder,
-                            bld->texel_type.length,
-                            bld->format_desc->block.bits,
-                            bld->texel_type.width,
-                            data_ptr, offset);
-   }
-   else {
-      struct lp_type type;
-
-      assert(bld->texel_type.width == 32);
-
-      memset(&type, 0, sizeof type);
-      type.width = 8;
-      type.length = bld->texel_type.length*4;
-      type.norm = TRUE;
-
-      res = lp_build_fetch_rgba_aos(bld->builder, bld->format_desc, type,
-                                    data_ptr, offset, i, j);
-   }
-
-   return res;
-}
-
-
 /**
  * Helper to compute the mirror function for the PIPE_WRAP_MIRROR modes.
  */
@@ -408,7 +356,7 @@ lp_build_coord_mirror(struct lp_build_sample_context *bld,
 
 
 /**
- * We only support a few wrap modes in lp_build_sample_wrap_int() at this time.
+ * We only support a few wrap modes in lp_build_sample_wrap_linear_int() at this time.
  * Return whether the given mode is supported by that function.
  */
 static boolean
@@ -430,13 +378,18 @@ is_simple_wrap_mode(unsigned mode)
  * \param length  the texture size along one dimension
  * \param is_pot  if TRUE, length is a power of two
  * \param wrap_mode  one of PIPE_TEX_WRAP_x
+ * \param i0  resulting sub-block pixel coordinate for coord0
  */
-static LLVMValueRef
-lp_build_sample_wrap_int(struct lp_build_sample_context *bld,
-                         LLVMValueRef coord,
-                         LLVMValueRef length,
-                         boolean is_pot,
-                         unsigned wrap_mode)
+static void
+lp_build_sample_wrap_nearest_int(struct lp_build_sample_context *bld,
+                                 unsigned block_length,
+                                 LLVMValueRef coord,
+                                 LLVMValueRef length,
+                                 LLVMValueRef stride,
+                                 boolean is_pot,
+                                 unsigned wrap_mode,
+                                 LLVMValueRef *out_offset,
+                                 LLVMValueRef *out_i)
 {
    struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld;
    struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
@@ -469,7 +422,134 @@ lp_build_sample_wrap_int(struct lp_build_sample_context *bld,
       assert(0);
    }
 
-   return coord;
+   lp_build_sample_partial_offset(uint_coord_bld, block_length, coord, stride,
+                                  out_offset, out_i);
+}
+
+
+/**
+ * Build LLVM code for texture wrap mode, for scaled integer texcoords.
+ * \param coord0  the incoming texcoord (s,t,r or q) scaled to the texture size
+ * \param length  the texture size along one dimension
+ * \param stride  pixel stride along the coordinate axis
+ * \param block_length  is the length of the pixel block along the
+ *                      coordinate axis
+ * \param is_pot  if TRUE, length is a power of two
+ * \param wrap_mode  one of PIPE_TEX_WRAP_x
+ * \param offset0  resulting relative offset for coord0
+ * \param offset1  resulting relative offset for coord0 + 1
+ * \param i0  resulting sub-block pixel coordinate for coord0
+ * \param i1  resulting sub-block pixel coordinate for coord0 + 1
+ */
+static void
+lp_build_sample_wrap_linear_int(struct lp_build_sample_context *bld,
+                                unsigned block_length,
+                                LLVMValueRef coord0,
+                                LLVMValueRef length,
+                                LLVMValueRef stride,
+                                boolean is_pot,
+                                unsigned wrap_mode,
+                                LLVMValueRef *offset0,
+                                LLVMValueRef *offset1,
+                                LLVMValueRef *i0,
+                                LLVMValueRef *i1)
+{
+   struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld;
+   struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
+   LLVMValueRef length_minus_one;
+   LLVMValueRef lmask, umask, mask;
+
+   if (block_length != 1) {
+      /*
+       * If the pixel block covers more than one pixel then there is no easy
+       * way to calculate offset1 relative to offset0. Instead, compute them
+       * independently.
+       */
+
+      LLVMValueRef coord1;
+
+      lp_build_sample_wrap_nearest_int(bld,
+                                       block_length,
+                                       coord0,
+                                       length,
+                                       stride,
+                                       is_pot,
+                                       wrap_mode,
+                                       offset0, i0);
+
+      coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
+
+      lp_build_sample_wrap_nearest_int(bld,
+                                       block_length,
+                                       coord1,
+                                       length,
+                                       stride,
+                                       is_pot,
+                                       wrap_mode,
+                                       offset1, i1);
+
+      return;
+   }
+
+   /*
+    * Scalar pixels -- try to compute offset0 and offset1 with a single stride
+    * multiplication.
+    */
+
+   *i0 = uint_coord_bld->zero;
+   *i1 = uint_coord_bld->zero;
+
+   length_minus_one = lp_build_sub(int_coord_bld, length, int_coord_bld->one);
+
+   switch(wrap_mode) {
+   case PIPE_TEX_WRAP_REPEAT:
+      if (is_pot) {
+         coord0 = LLVMBuildAnd(bld->builder, coord0, length_minus_one, "");
+      }
+      else {
+         /* Signed remainder won't give the right results for negative
+          * dividends but unsigned remainder does.*/
+         coord0 = LLVMBuildURem(bld->builder, coord0, length, "");
+      }
+
+      mask = lp_build_compare(bld->builder, int_coord_bld->type,
+                              PIPE_FUNC_NOTEQUAL, coord0, length_minus_one);
+
+      *offset0 = lp_build_mul(uint_coord_bld, coord0, stride);
+      *offset1 = LLVMBuildAnd(bld->builder,
+                              lp_build_add(uint_coord_bld, *offset0, stride),
+                              mask, "");
+      break;
+
+   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+      lmask = lp_build_compare(int_coord_bld->builder, int_coord_bld->type,
+                               PIPE_FUNC_GEQUAL, coord0, int_coord_bld->zero);
+      umask = lp_build_compare(int_coord_bld->builder, int_coord_bld->type,
+                               PIPE_FUNC_LESS, coord0, length_minus_one);
+
+      coord0 = lp_build_select(int_coord_bld, lmask, coord0, int_coord_bld->zero);
+      coord0 = lp_build_select(int_coord_bld, umask, coord0, length_minus_one);
+
+      mask = LLVMBuildAnd(bld->builder, lmask, umask, "");
+
+      *offset0 = lp_build_mul(uint_coord_bld, coord0, stride);
+      *offset1 = lp_build_add(uint_coord_bld,
+                              *offset0,
+                              LLVMBuildAnd(bld->builder, stride, mask, ""));
+      break;
+
+   case PIPE_TEX_WRAP_CLAMP:
+   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+   case PIPE_TEX_WRAP_MIRROR_REPEAT:
+   case PIPE_TEX_WRAP_MIRROR_CLAMP:
+   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+   default:
+      assert(0);
+      *offset0 = uint_coord_bld->zero;
+      *offset1 = uint_coord_bld->zero;
+      break;
+   }
 }
 
 
@@ -1740,16 +1820,21 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
    LLVMValueRef i32_c8, i32_c128, i32_c255;
    LLVMValueRef s_ipart, s_fpart, s_fpart_lo, s_fpart_hi;
    LLVMValueRef t_ipart, t_fpart, t_fpart_lo, t_fpart_hi;
-   LLVMValueRef x0, x1;
-   LLVMValueRef y0, y1;
-   LLVMValueRef neighbors[2][2];
+   LLVMValueRef data_ptr;
+   LLVMValueRef x_stride, y_stride;
+   LLVMValueRef x_offset0, x_offset1;
+   LLVMValueRef y_offset0, y_offset1;
+   LLVMValueRef offset[2][2];
+   LLVMValueRef x_subcoord[2], y_subcoord[2];
    LLVMValueRef neighbors_lo[2][2];
    LLVMValueRef neighbors_hi[2][2];
    LLVMValueRef packed, packed_lo, packed_hi;
    LLVMValueRef unswizzled[4];
-   LLVMValueRef stride;
+   const unsigned level = 0;
+   unsigned i, j;
 
-   assert(bld->static_state->target == PIPE_TEXTURE_2D);
+   assert(bld->static_state->target == PIPE_TEXTURE_2D
+         || bld->static_state->target == PIPE_TEXTURE_RECT);
    assert(bld->static_state->min_img_filter == PIPE_TEX_FILTER_LINEAR);
    assert(bld->static_state->mag_img_filter == PIPE_TEX_FILTER_LINEAR);
    assert(bld->static_state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE);
@@ -1793,21 +1878,30 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
    s_fpart = LLVMBuildAnd(builder, s, i32_c255, "");
    t_fpart = LLVMBuildAnd(builder, t, i32_c255, "");
 
-   x0 = s_ipart;
-   y0 = t_ipart;
-
-   x1 = lp_build_add(&bld->int_coord_bld, x0, bld->int_coord_bld.one);
-   y1 = lp_build_add(&bld->int_coord_bld, y0, bld->int_coord_bld.one);
-
-   x0 = lp_build_sample_wrap_int(bld, x0, width,  bld->static_state->pot_width,
-                                 bld->static_state->wrap_s);
-   y0 = lp_build_sample_wrap_int(bld, y0, height, bld->static_state->pot_height,
-                                 bld->static_state->wrap_t);
-
-   x1 = lp_build_sample_wrap_int(bld, x1, width,  bld->static_state->pot_width,
-                                 bld->static_state->wrap_s);
-   y1 = lp_build_sample_wrap_int(bld, y1, height, bld->static_state->pot_height,
-                                 bld->static_state->wrap_t);
+   x_stride = lp_build_const_vec(bld->uint_coord_bld.type,
+                                 bld->format_desc->block.bits/8);
+
+   y_stride = lp_build_get_const_level_stride_vec(bld, stride_array, level);
+
+   lp_build_sample_wrap_linear_int(bld,
+                                   bld->format_desc->block.width,
+                                   s_ipart, width, x_stride,
+                                   bld->static_state->pot_width,
+                                   bld->static_state->wrap_s,
+                                   &x_offset0, &x_offset1,
+                                   &x_subcoord[0], &x_subcoord[1]);
+   lp_build_sample_wrap_linear_int(bld,
+                                   bld->format_desc->block.height,
+                                   t_ipart, height, y_stride,
+                                   bld->static_state->pot_height,
+                                   bld->static_state->wrap_t,
+                                   &y_offset0, &y_offset1,
+                                   &y_subcoord[0], &y_subcoord[1]);
+
+   offset[0][0] = lp_build_add(&bld->uint_coord_bld, x_offset0, y_offset0);
+   offset[0][1] = lp_build_add(&bld->uint_coord_bld, x_offset1, y_offset0);
+   offset[1][0] = lp_build_add(&bld->uint_coord_bld, x_offset0, y_offset1);
+   offset[1][1] = lp_build_add(&bld->uint_coord_bld, x_offset1, y_offset1);
 
    /*
     * Transform 4 x i32 in
@@ -1836,7 +1930,6 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
       LLVMValueRef shuffles_hi[LP_MAX_VECTOR_LENGTH];
       LLVMValueRef shuffle_lo;
       LLVMValueRef shuffle_hi;
-      unsigned i, j;
 
       for(j = 0; j < h16.type.length; j += 4) {
 #ifdef PIPE_ARCH_LITTLE_ENDIAN
@@ -1864,7 +1957,10 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
       t_fpart_hi = LLVMBuildShuffleVector(builder, t_fpart, h16.undef, shuffle_hi, "");
    }
 
-   stride = lp_build_get_const_level_stride_vec(bld, stride_array, 0);
+   /*
+    * get pointer to mipmap level 0 data
+    */
+   data_ptr = lp_build_get_const_mipmap_level(bld, data_array, level);
 
    /*
     * Fetch the pixels as 4 x 32bit (rgba order might differ):
@@ -1883,20 +1979,38 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
     * The higher 8 bits of the resulting elements will be zero.
     */
 
-   neighbors[0][0] = lp_build_sample_packed(bld, x0, y0, stride, data_array);
-   neighbors[0][1] = lp_build_sample_packed(bld, x1, y0, stride, data_array);
-   neighbors[1][0] = lp_build_sample_packed(bld, x0, y1, stride, data_array);
-   neighbors[1][1] = lp_build_sample_packed(bld, x1, y1, stride, data_array);
+   for (j = 0; j < 2; ++j) {
+      for (i = 0; i < 2; ++i) {
+         LLVMValueRef rgba8;
 
-   neighbors[0][0] = LLVMBuildBitCast(builder, neighbors[0][0], u8n_vec_type, "");
-   neighbors[0][1] = LLVMBuildBitCast(builder, neighbors[0][1], u8n_vec_type, "");
-   neighbors[1][0] = LLVMBuildBitCast(builder, neighbors[1][0], u8n_vec_type, "");
-   neighbors[1][1] = LLVMBuildBitCast(builder, neighbors[1][1], u8n_vec_type, "");
+         if (util_format_is_rgba8_variant(bld->format_desc)) {
+            /*
+             * Given the format is a rgba8, just read the pixels as is,
+             * without any swizzling. Swizzling will be done later.
+             */
+            rgba8 = lp_build_gather(bld->builder,
+                                    bld->texel_type.length,
+                                    bld->format_desc->block.bits,
+                                    bld->texel_type.width,
+                                    data_ptr, offset[j][i]);
 
-   lp_build_unpack2(builder, u8n.type, h16.type, neighbors[0][0], &neighbors_lo[0][0], &neighbors_hi[0][0]);
-   lp_build_unpack2(builder, u8n.type, h16.type, neighbors[0][1], &neighbors_lo[0][1], &neighbors_hi[0][1]);
-   lp_build_unpack2(builder, u8n.type, h16.type, neighbors[1][0], &neighbors_lo[1][0], &neighbors_hi[1][0]);
-   lp_build_unpack2(builder, u8n.type, h16.type, neighbors[1][1], &neighbors_lo[1][1], &neighbors_hi[1][1]);
+            rgba8 = LLVMBuildBitCast(builder, rgba8, u8n_vec_type, "");
+
+         }
+         else {
+            rgba8 = lp_build_fetch_rgba_aos(bld->builder,
+                                            bld->format_desc,
+                                            u8n.type,
+                                            data_ptr, offset[j][i],
+                                            x_subcoord[i],
+                                            y_subcoord[j]);
+         }
+
+         lp_build_unpack2(builder, u8n.type, h16.type,
+                          rgba8,
+                          &neighbors_lo[j][i], &neighbors_hi[j][i]);
+      }
+   }
 
    /*
     * Linear interpolate with 8.8 fixed point.
@@ -2077,7 +2191,8 @@ lp_build_sample_soa(LLVMBuilderRef builder,
    }
    else if (util_format_fits_8unorm(bld.format_desc) &&
             bld.format_desc->nr_channels > 1 &&
-            static_state->target == PIPE_TEXTURE_2D &&
+            (static_state->target == PIPE_TEXTURE_2D ||
+                  static_state->target == PIPE_TEXTURE_RECT) &&
             static_state->min_img_filter == PIPE_TEX_FILTER_LINEAR &&
             static_state->mag_img_filter == PIPE_TEX_FILTER_LINEAR &&
             static_state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE &&
index 0aa64affacc0346c400ed668ab9bb6256f9fe3fb..0e07f7f3f38e2666cb57592c4be6539f0b37b863 100644 (file)
@@ -200,8 +200,10 @@ static void lp_exec_mask_cond_push(struct lp_exec_mask *mask,
    }
    mask->cond_stack[mask->cond_stack_size++] = mask->cond_mask;
    assert(LLVMTypeOf(val) == mask->int_vec_type);
-   mask->cond_mask = val;
-
+   mask->cond_mask = LLVMBuildAnd(mask->bld->builder,
+                                  mask->cond_mask,
+                                  val,
+                                  "");
    lp_exec_mask_update(mask);
 }
 
@@ -802,7 +804,7 @@ emit_store(
 
    case TGSI_FILE_PREDICATE:
       lp_exec_mask_store(&bld->exec_mask, pred, value,
-                         bld->preds[index][chan_index]);
+                         bld->preds[reg->Register.Index][chan_index]);
       break;
 
    default:
index 3ffe916f8e42da9d807d24d066512305edb4057a..fec1d3dfbc637ba552234bd1fb8f08c045eff54a 100644 (file)
@@ -128,16 +128,16 @@ struct lp_build_context
     */
    struct lp_type type;
 
-   /** Same as lp_build_undef(type) */
+   /** Same as lp_build_elem_type(type) */
    LLVMTypeRef elem_type;
 
-   /** Same as lp_build_undef(type) */
+   /** Same as lp_build_vec_type(type) */
    LLVMTypeRef vec_type;
 
-   /** Same as lp_build_undef(type) */
+   /** Same as lp_build_int_elem_type(type) */
    LLVMTypeRef int_elem_type;
 
-   /** Same as lp_build_undef(type) */
+   /** Same as lp_build_int_vec_type(type) */
    LLVMTypeRef int_vec_type;
 
    /** Same as lp_build_undef(type) */
diff --git a/src/gallium/auxiliary/os/os_stream.c b/src/gallium/auxiliary/os/os_stream.c
new file mode 100644 (file)
index 0000000..3c55fc0
--- /dev/null
@@ -0,0 +1,58 @@
+/**************************************************************************
+ *
+ * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "pipe/p_config.h"
+
+#include "os_stream.h"
+#include "util/u_memory.h"
+#include "util/u_string.h"
+
+int
+os_default_stream_vprintf (struct os_stream* stream, const char *format, va_list ap)
+{
+   char buf[1024];
+   int retval;
+   va_list ap2;
+   va_copy(ap2, ap);
+   retval = util_vsnprintf(buf, sizeof(buf), format, ap2);
+   va_end(ap2);
+   if(retval <= 0)
+   {}
+   else if(retval < sizeof(buf))
+      stream->write(stream, buf, retval);
+   else
+   {
+      char* str = MALLOC(retval + 1);
+      if(!str)
+         return -1;
+      retval = util_vsnprintf(str, retval + 1, format, ap);
+      if(retval > 0)
+         stream->write(stream, str, retval);
+      FREE(str);
+   }
+
+   return retval;
+}
index 693a0621e2d374c215ee65026569723ef053c0a0..6c6050bb0284d5ae159c1f141a73f058697ab7c5 100644 (file)
@@ -50,6 +50,9 @@ struct os_stream
 
    void
    (*flush)(struct os_stream *stream);
+
+   int
+   (*vprintf)(struct os_stream *stream, const char* format, va_list ap);
 };
 
 
@@ -90,6 +93,27 @@ os_stream_flush(struct os_stream *stream)
    stream->flush(stream);
 }
 
+int
+os_default_stream_vprintf (struct os_stream* stream, const char *format, va_list ap);
+
+static INLINE int
+os_stream_vprintf (struct os_stream* stream, const char *format, va_list ap)
+{
+   return stream->vprintf(stream, format, ap);
+}
+
+static INLINE int
+os_stream_printf (struct os_stream* stream, const char *format, ...)
+{
+   int retval;
+   va_list args;
+
+   va_start (args, format);
+   retval = stream->vprintf(stream, format, args);
+   va_end (args);
+
+   return retval;
+}
 
 struct os_stream *
 os_file_stream_create(const char *filename);
@@ -118,5 +142,4 @@ os_str_stream_get_and_close(struct os_stream *stream);
 #define os_file_stream_create(_filename) os_null_stream_create()
 #endif
 
-
 #endif /* _OS_STREAM_H_ */
index 7cc2028a22cd643de05027d4b46ae2e6ee67de9f..b01377c346833af25febc3f99b518f161f8fbdd8 100644 (file)
@@ -73,7 +73,8 @@ static struct os_stream
 os_log_stream_struct = {
    &os_log_stream_close,
    &os_log_stream_write,
-   &os_log_stream_flush
+   &os_log_stream_flush,
+   &os_default_stream_vprintf,
 };
 
 
index 128c4e8f0e097159e4241c7cc25ed15c8133a228..a549a789e620638083ee7c754581ce5d8af8889b 100644 (file)
@@ -56,12 +56,18 @@ os_null_stream_flush(struct os_stream *stream)
    (void)stream;
 }
 
+static int
+os_null_stream_vprintf (struct os_stream* stream, const char *format, va_list ap)
+{
+   return 0;
+}
 
 static struct os_stream
 os_null_stream = {
    &os_null_stream_close,
    &os_null_stream_write,
-   &os_null_stream_flush
+   &os_null_stream_flush,
+   &os_null_stream_vprintf
 };
 
 
index 9e7ed7110763d9c9d039bf4ad30c86f0ede62679..37e7d063e2bf4c7f1e9d7d3204b262956a8e2aa0 100644 (file)
@@ -83,6 +83,14 @@ os_stdc_stream_flush(struct os_stream *_stream)
    fflush(stream->file);
 }
 
+static int
+os_stdc_stream_vprintf (struct os_stream* _stream, const char *format, va_list ap)
+{
+   struct os_stdc_stream *stream = os_stdc_stream(_stream);
+
+   return vfprintf(stream->file, format, ap);
+}
+
 
 struct os_stream *
 os_file_stream_create(const char *filename)
@@ -96,6 +104,7 @@ os_file_stream_create(const char *filename)
    stream->base.close = &os_stdc_stream_close;
    stream->base.write = &os_stdc_stream_write;
    stream->base.flush = &os_stdc_stream_flush;
+   stream->base.vprintf = &os_stdc_stream_vprintf;
 
    stream->file = fopen(filename, "w");
    if(!stream->file)
index b5c7270d2ae08b6439cd6dbb833b42866227de7a..be9478b2a170ba099fb112fbad6d05dcce201d11 100644 (file)
@@ -118,6 +118,7 @@ os_str_stream_create(size_t size)
    stream->base.close = &os_str_stream_close;
    stream->base.write = &os_str_stream_write;
    stream->base.flush = &os_str_stream_flush;
+   stream->base.vprintf = &os_default_stream_vprintf;
 
    stream->str = os_malloc(size);
    if(!stream->str)
index cec2524da2bdefc31bcc8612ab39002b5ae2383a..2ef02160f23ef606ce9b67dc7461678fa5b4398e 100644 (file)
@@ -50,8 +50,7 @@
 #define PB_BUFMGR_H_
 
 
-#include "pipe/p_compiler.h"
-#include "pipe/p_defines.h"
+#include "pb_buffer.h"
 
 
 #ifdef __cplusplus
index 2e15751e5086d80e5f3e36162f7176bd7edb610a..0461c815504800f183c9bb7f5ac919e7be9cc6d1 100644 (file)
@@ -30,7 +30,7 @@
 #include "rtasm_cpu.h"
 
 
-#if defined(PIPE_ARCH_X86)
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
 static boolean rtasm_sse_enabled(void)
 {
    static boolean firsttime = 1;
@@ -49,7 +49,7 @@ static boolean rtasm_sse_enabled(void)
 int rtasm_cpu_has_sse(void)
 {
    /* FIXME: actually detect this at run-time */
-#if defined(PIPE_ARCH_X86)
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
    return rtasm_sse_enabled();
 #else
    return 0;
@@ -59,7 +59,7 @@ int rtasm_cpu_has_sse(void)
 int rtasm_cpu_has_sse2(void) 
 {
    /* FIXME: actually detect this at run-time */
-#if defined(PIPE_ARCH_X86)
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
    return rtasm_sse_enabled();
 #else
    return 0;
index 9f70b73698aaa2735bf0fda24ae110d4b495605a..75b0f6a68ea555da2cd6ca39539e4621e826e454 100644 (file)
@@ -22,8 +22,9 @@
  **************************************************************************/
 
 #include "pipe/p_config.h"
+#include "util/u_cpu_detect.h"
 
-#if defined(PIPE_ARCH_X86)
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
 
 #include "pipe/p_compiler.h"
 #include "util/u_debug.h"
@@ -231,6 +232,10 @@ static void emit_modrm( struct x86_function *p,
    
    assert(reg.mod == mod_REG);
    
+   /* TODO: support extended x86-64 registers */
+   assert(reg.idx < 8);
+   assert(regmem.idx < 8);
+
    val |= regmem.mod << 6;             /* mod field */
    val |= reg.idx << 3;                /* reg field */
    val |= regmem.idx;          /* r/m field */
@@ -363,6 +368,12 @@ int x86_get_label( struct x86_function *p )
  */
 
 
+void x64_rexw(struct x86_function *p)
+{
+   if(x86_target(p) != X86_32)
+      emit_1ub(p, 0x48);
+}
+
 void x86_jcc( struct x86_function *p,
              enum x86_cc cc,
              int label )
@@ -449,6 +460,52 @@ void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm )
    emit_1i(p, imm);
 }
 
+void x86_mov_imm( struct x86_function *p, struct x86_reg dst, int imm )
+{
+   DUMP_RI( dst, imm );
+   if(dst.mod == mod_REG)
+      x86_mov_reg_imm(p, dst, imm);
+   else
+   {
+      emit_1ub(p, 0xc7);
+      emit_modrm_noreg(p, 0, dst);
+      emit_1i(p, imm);
+   }
+}
+
+void x86_mov16_imm( struct x86_function *p, struct x86_reg dst, uint16_t imm )
+{
+   DUMP_RI( dst, imm );
+   emit_1ub(p, 0x66);
+   if(dst.mod == mod_REG)
+   {
+      emit_1ub(p, 0xb8 + dst.idx);
+      emit_2ub(p, imm & 0xff, imm >> 8);
+   }
+   else
+   {
+      emit_1ub(p, 0xc7);
+      emit_modrm_noreg(p, 0, dst);
+      emit_2ub(p, imm & 0xff, imm >> 8);
+   }
+}
+
+void x86_mov8_imm( struct x86_function *p, struct x86_reg dst, uint8_t imm )
+{
+   DUMP_RI( dst, imm );
+   if(dst.mod == mod_REG)
+   {
+      emit_1ub(p, 0xb0 + dst.idx);
+      emit_1ub(p, imm);
+   }
+   else
+   {
+      emit_1ub(p, 0xc6);
+      emit_modrm_noreg(p, 0, dst);
+      emit_1ub(p, imm);
+   }
+}
+
 /**
  * Immediate group 1 instructions.
  */
@@ -520,7 +577,7 @@ void x86_push( struct x86_function *p,
    }
 
 
-   p->stack_offset += 4;
+   p->stack_offset += sizeof(void*);
 }
 
 void x86_push_imm32( struct x86_function *p,
@@ -530,7 +587,7 @@ void x86_push_imm32( struct x86_function *p,
    emit_1ub(p, 0x68);
    emit_1i(p,  imm32);
 
-   p->stack_offset += 4;
+   p->stack_offset += sizeof(void*);
 }
 
 
@@ -540,23 +597,33 @@ void x86_pop( struct x86_function *p,
    DUMP_R( reg );
    assert(reg.mod == mod_REG);
    emit_1ub(p, 0x58 + reg.idx);
-   p->stack_offset -= 4;
+   p->stack_offset -= sizeof(void*);
 }
 
 void x86_inc( struct x86_function *p,
              struct x86_reg reg )
 {
    DUMP_R( reg );
-   assert(reg.mod == mod_REG);
-   emit_1ub(p, 0x40 + reg.idx);
+   if(x86_target(p) == X86_32 && reg.mod == mod_REG)
+   {
+      emit_1ub(p, 0x40 + reg.idx);
+      return;
+   }
+   emit_1ub(p, 0xff);
+   emit_modrm_noreg(p, 0, reg);
 }
 
 void x86_dec( struct x86_function *p,
              struct x86_reg reg )
 {
    DUMP_R( reg );
-   assert(reg.mod == mod_REG);
-   emit_1ub(p, 0x48 + reg.idx);
+   if(x86_target(p) == X86_32 && reg.mod == mod_REG)
+   {
+      emit_1ub(p, 0x48 + reg.idx);
+      return;
+   }
+   emit_1ub(p, 0xff);
+   emit_modrm_noreg(p, 1, reg);
 }
 
 void x86_ret( struct x86_function *p )
@@ -583,9 +650,82 @@ void x86_mov( struct x86_function *p,
              struct x86_reg src )
 {
    DUMP_RR( dst, src );
+   /* special hack for reading arguments until we support x86-64 registers everywhere */
+   if(src.mod == mod_REG && dst.mod == mod_REG && (src.idx >= 8 || dst.idx >= 8))
+   {
+      uint8_t rex = 0x40;
+      if(dst.idx >= 8)
+      {
+         rex |= 4;
+         dst.idx -= 8;
+      }
+      if(src.idx >= 8)
+      {
+         rex |= 1;
+         src.idx -= 8;
+      }
+      emit_1ub(p, rex);
+   }
+   emit_op_modrm( p, 0x8b, 0x89, dst, src );
+}
+
+void x86_mov16( struct x86_function *p,
+             struct x86_reg dst,
+             struct x86_reg src )
+{
+   DUMP_RR( dst, src );
+   emit_1ub(p, 0x66);
+   emit_op_modrm( p, 0x8b, 0x89, dst, src );
+}
+
+void x86_mov8( struct x86_function *p,
+             struct x86_reg dst,
+             struct x86_reg src )
+{
+   DUMP_RR( dst, src );
+   emit_op_modrm( p, 0x8a, 0x88, dst, src );
+}
+
+void x64_mov64( struct x86_function *p,
+             struct x86_reg dst,
+             struct x86_reg src )
+{
+   uint8_t rex = 0x48;
+   DUMP_RR( dst, src );
+   assert(x86_target(p) != X86_32);
+
+   /* special hack for reading arguments until we support x86-64 registers everywhere */
+   if(src.mod == mod_REG && dst.mod == mod_REG && (src.idx >= 8 || dst.idx >= 8))
+   {
+      if(dst.idx >= 8)
+      {
+         rex |= 4;
+         dst.idx -= 8;
+      }
+      if(src.idx >= 8)
+      {
+         rex |= 1;
+         src.idx -= 8;
+      }
+   }
+   emit_1ub(p, rex);
    emit_op_modrm( p, 0x8b, 0x89, dst, src );
 }
 
+void x86_movzx8(struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+   DUMP_RR( dst, src );
+   emit_2ub(p, 0x0f, 0xb6);
+   emit_modrm(p, dst, src);
+}
+
+void x86_movzx16(struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+   DUMP_RR( dst, src );
+   emit_2ub(p, 0x0f, 0xb7);
+   emit_modrm(p, dst, src);
+}
+
 void x86_xor( struct x86_function *p,
              struct x86_reg dst,
              struct x86_reg src )
@@ -680,6 +820,61 @@ void x86_div( struct x86_function *p,
    emit_op_modrm(p, 0xf7, 0, x86_make_reg(file_REG32, 6), src);
 }
 
+void x86_bswap( struct x86_function *p, struct x86_reg reg )
+{
+   DUMP_R(reg);
+   assert(reg.file == file_REG32);
+   assert(reg.mod == mod_REG);
+   emit_2ub(p, 0x0f, 0xc8 + reg.idx);
+}
+
+void x86_shr_imm( struct x86_function *p, struct x86_reg reg, unsigned imm )
+{
+   DUMP_RI(reg, imm);
+   if(imm == 1)
+   {
+      emit_1ub(p, 0xd1);
+      emit_modrm_noreg(p, 5, reg);
+   }
+   else
+   {
+      emit_1ub(p, 0xc1);
+      emit_modrm_noreg(p, 5, reg);
+      emit_1ub(p, imm);
+   }
+}
+
+void x86_sar_imm( struct x86_function *p, struct x86_reg reg, unsigned imm )
+{
+   DUMP_RI(reg, imm);
+   if(imm == 1)
+   {
+      emit_1ub(p, 0xd1);
+      emit_modrm_noreg(p, 7, reg);
+   }
+   else
+   {
+      emit_1ub(p, 0xc1);
+      emit_modrm_noreg(p, 7, reg);
+      emit_1ub(p, imm);
+   }
+}
+
+void x86_shl_imm( struct x86_function *p, struct x86_reg reg, unsigned imm  )
+{
+   DUMP_RI(reg, imm);
+   if(imm == 1)
+   {
+      emit_1ub(p, 0xd1);
+      emit_modrm_noreg(p, 4, reg);
+   }
+   else
+   {
+      emit_1ub(p, 0xc1);
+      emit_modrm_noreg(p, 4, reg);
+      emit_1ub(p, imm);
+   }
+}
 
 
 /***********************************************************************
@@ -1013,6 +1208,77 @@ void sse_movmskps( struct x86_function *p,
  * SSE2 instructions
  */
 
+void sse2_movd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+   DUMP_RR(dst, src);
+   emit_2ub(p, 0x66, 0x0f);
+   if(dst.mod == mod_REG && dst.file == file_REG32)
+   {
+      emit_1ub(p, 0x7e);
+      emit_modrm(p, src, dst);
+   }
+   else
+   {
+      emit_op_modrm(p, 0x6e, 0x7e, dst, src);
+   }
+}
+
+void sse2_movq( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+   DUMP_RR(dst, src);
+   switch (dst.mod) {
+   case mod_REG:
+      emit_3ub(p, 0xf3, 0x0f, 0x7e);
+      emit_modrm(p, dst, src);
+      break;
+   case mod_INDIRECT:
+   case mod_DISP32:
+   case mod_DISP8:
+      assert(src.mod == mod_REG);
+      emit_3ub(p, 0x66, 0x0f, 0xd6);
+      emit_modrm(p, src, dst);
+      break;
+   default:
+      assert(0);
+      break;
+   }
+}
+
+void sse2_movdqu( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+   DUMP_RR(dst, src);
+   emit_2ub(p, 0xf3, 0x0f);
+   emit_op_modrm(p, 0x6f, 0x7f, dst, src);
+}
+
+void sse2_movdqa( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+   DUMP_RR(dst, src);
+   emit_2ub(p, 0x66, 0x0f);
+   emit_op_modrm(p, 0x6f, 0x7f, dst, src);
+}
+
+void sse2_movsd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+   DUMP_RR(dst, src);
+   emit_2ub(p, 0xf2, 0x0f);
+   emit_op_modrm(p, 0x10, 0x11, dst, src);
+}
+
+void sse2_movupd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+   DUMP_RR(dst, src);
+   emit_2ub(p, 0x66, 0x0f);
+   emit_op_modrm(p, 0x10, 0x11, dst, src);
+}
+
+void sse2_movapd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+   DUMP_RR(dst, src);
+   emit_2ub(p, 0x66, 0x0f);
+   emit_op_modrm(p, 0x28, 0x29, dst, src);
+}
+
 /**
  * Perform a reduced swizzle:
  */
@@ -1027,6 +1293,28 @@ void sse2_pshufd( struct x86_function *p,
    emit_1ub(p, shuf); 
 }
 
+void sse2_pshuflw( struct x86_function *p,
+                  struct x86_reg dst,
+                  struct x86_reg src,
+                  unsigned char shuf)
+{
+   DUMP_RRI( dst, src, shuf );
+   emit_3ub(p, 0xf2, X86_TWOB, 0x70);
+   emit_modrm(p, dst, src);
+   emit_1ub(p, shuf);
+}
+
+void sse2_pshufhw( struct x86_function *p,
+                  struct x86_reg dst,
+                  struct x86_reg src,
+                  unsigned char shuf)
+{
+   DUMP_RRI( dst, src, shuf );
+   emit_3ub(p, 0xf3, X86_TWOB, 0x70);
+   emit_modrm(p, dst, src);
+   emit_1ub(p, shuf);
+}
+
 void sse2_cvttps2dq( struct x86_function *p,
                      struct x86_reg dst,
                      struct x86_reg src )
@@ -1045,6 +1333,24 @@ void sse2_cvtps2dq( struct x86_function *p,
    emit_modrm( p, dst, src );
 }
 
+void sse2_cvtsd2ss( struct x86_function *p,
+                    struct x86_reg dst,
+                    struct x86_reg src )
+{
+   DUMP_RR( dst, src );
+   emit_3ub(p, 0xf2, 0x0f, 0x5a);
+   emit_modrm( p, dst, src );
+}
+
+void sse2_cvtpd2ps( struct x86_function *p,
+                    struct x86_reg dst,
+                    struct x86_reg src )
+{
+   DUMP_RR( dst, src );
+   emit_3ub(p, 0x66, 0x0f, 0x5a);
+   emit_modrm( p, dst, src );
+}
+
 void sse2_packssdw( struct x86_function *p,
                    struct x86_reg dst,
                    struct x86_reg src )
@@ -1081,6 +1387,97 @@ void sse2_punpcklbw( struct x86_function *p,
    emit_modrm( p, dst, src );
 }
 
+void sse2_punpcklwd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+   DUMP_RR( dst, src );
+   emit_3ub(p, 0x66, 0x0f, 0x61);
+   emit_modrm( p, dst, src );
+}
+
+void sse2_punpckldq( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+   DUMP_RR( dst, src );
+   emit_3ub(p, 0x66, 0x0f, 0x62);
+   emit_modrm( p, dst, src );
+}
+
+void sse2_punpcklqdq( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+   DUMP_RR( dst, src );
+   emit_3ub(p, 0x66, 0x0f, 0x6c);
+   emit_modrm( p, dst, src );
+}
+
+void sse2_psllw_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
+{
+   DUMP_RI(dst, imm);
+   emit_3ub(p, 0x66, 0x0f, 0x71);
+   emit_modrm_noreg(p, 6, dst);
+   emit_1ub(p, imm);
+}
+
+void sse2_pslld_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
+{
+   DUMP_RI(dst, imm);
+   emit_3ub(p, 0x66, 0x0f, 0x72);
+   emit_modrm_noreg(p, 6, dst);
+   emit_1ub(p, imm);
+}
+
+void sse2_psllq_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
+{
+   DUMP_RI(dst, imm);
+   emit_3ub(p, 0x66, 0x0f, 0x73);
+   emit_modrm_noreg(p, 6, dst);
+   emit_1ub(p, imm);
+}
+
+void sse2_psrlw_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
+{
+   DUMP_RI(dst, imm);
+   emit_3ub(p, 0x66, 0x0f, 0x71);
+   emit_modrm_noreg(p, 2, dst);
+   emit_1ub(p, imm);
+}
+
+void sse2_psrld_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
+{
+   DUMP_RI(dst, imm);
+   emit_3ub(p, 0x66, 0x0f, 0x72);
+   emit_modrm_noreg(p, 2, dst);
+   emit_1ub(p, imm);
+}
+
+void sse2_psrlq_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
+{
+   DUMP_RI(dst, imm);
+   emit_3ub(p, 0x66, 0x0f, 0x73);
+   emit_modrm_noreg(p, 2, dst);
+   emit_1ub(p, imm);
+}
+
+void sse2_psraw_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
+{
+   DUMP_RI(dst, imm);
+   emit_3ub(p, 0x66, 0x0f, 0x71);
+   emit_modrm_noreg(p, 4, dst);
+   emit_1ub(p, imm);
+}
+
+void sse2_psrad_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
+{
+   DUMP_RI(dst, imm);
+   emit_3ub(p, 0x66, 0x0f, 0x72);
+   emit_modrm_noreg(p, 4, dst);
+   emit_1ub(p, imm);
+}
+
+void sse2_por( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
+{
+   DUMP_RR(dst, src);
+   emit_3ub(p, 0x66, 0x0f, 0xeb);
+   emit_modrm(p, dst, src);
+}
 
 void sse2_rcpps( struct x86_function *p,
                  struct x86_reg dst,
@@ -1100,18 +1497,6 @@ void sse2_rcpss( struct x86_function *p,
    emit_modrm( p, dst, src );
 }
 
-void sse2_movd( struct x86_function *p,
-               struct x86_reg dst,
-               struct x86_reg src )
-{
-   DUMP_RR( dst, src );
-   emit_2ub(p, 0x66, X86_TWOB);
-   emit_op_modrm( p, 0x6e, 0x7e, dst, src );
-}
-
-
-
-
 /***********************************************************************
  * x87 instructions
  */
@@ -1702,23 +2087,80 @@ void x86_cdecl_caller_pop_regs( struct x86_function *p )
 }
 
 
-/* Retreive a reference to one of the function arguments, taking into
- * account any push/pop activity:
- */
 struct x86_reg x86_fn_arg( struct x86_function *p,
-                          unsigned arg )
+                           unsigned arg )
 {
-   return x86_make_disp(x86_make_reg(file_REG32, reg_SP), 
+   switch(x86_target(p))
+   {
+   case X86_64_WIN64_ABI:
+      /* Microsoft uses a different calling convention than the rest of the world */
+      switch(arg)
+      {
+      case 1:
+         return x86_make_reg(file_REG32, reg_CX);
+      case 2:
+         return x86_make_reg(file_REG32, reg_DX);
+      case 3:
+         return x86_make_reg(file_REG32, reg_R8);
+      case 4:
+         return x86_make_reg(file_REG32, reg_R9);
+      default:
+        /* Win64 allocates stack slots as if it pushed the first 4 arguments too */
+         return x86_make_disp(x86_make_reg(file_REG32, reg_SP),
+               p->stack_offset + arg * 8);
+      }
+   case X86_64_STD_ABI:
+      switch(arg)
+      {
+      case 1:
+         return x86_make_reg(file_REG32, reg_DI);
+      case 2:
+         return x86_make_reg(file_REG32, reg_SI);
+      case 3:
+         return x86_make_reg(file_REG32, reg_DX);
+      case 4:
+         return x86_make_reg(file_REG32, reg_CX);
+      case 5:
+         return x86_make_reg(file_REG32, reg_R8);
+      case 6:
+         return x86_make_reg(file_REG32, reg_R9);
+      default:
+         return x86_make_disp(x86_make_reg(file_REG32, reg_SP),
+               p->stack_offset + (arg - 6) * 8);     /* ??? */
+      }
+   case X86_32:
+      return x86_make_disp(x86_make_reg(file_REG32, reg_SP),
                        p->stack_offset + arg * 4);     /* ??? */
+   default:
+      abort();
+   }
 }
 
+static void x86_init_func_common( struct x86_function *p )
+{
+   util_cpu_detect();
+   p->caps = 0;
+   if(util_cpu_caps.has_mmx)
+      p->caps |= X86_MMX;
+   if(util_cpu_caps.has_mmx2)
+      p->caps |= X86_MMX2;
+   if(util_cpu_caps.has_sse)
+      p->caps |= X86_SSE;
+   if(util_cpu_caps.has_sse2)
+      p->caps |= X86_SSE2;
+   if(util_cpu_caps.has_sse3)
+      p->caps |= X86_SSE3;
+   if(util_cpu_caps.has_sse4_1)
+      p->caps |= X86_SSE4_1;
+   p->csr = p->store;
+   DUMP_START();
+}
 
 void x86_init_func( struct x86_function *p )
 {
    p->size = 0;
    p->store = NULL;
-   p->csr = p->store;
-   DUMP_START();
+   x86_init_func_common(p);
 }
 
 void x86_init_func_size( struct x86_function *p, unsigned code_size )
@@ -1728,8 +2170,7 @@ void x86_init_func_size( struct x86_function *p, unsigned code_size )
    if (p->store == NULL) {
       p->store = p->error_overflow;
    }
-   p->csr = p->store;
-   DUMP_START();
+   x86_init_func_common(p);
 }
 
 void x86_release_func( struct x86_function *p )
index 6208e8f707f26a89f593d54d5f8ea530ae0f9eda..2b9678b17657764622d59d927437f0dc5da33254 100644 (file)
 #ifndef _RTASM_X86SSE_H_
 #define _RTASM_X86SSE_H_
 
+#include "pipe/p_compiler.h"
 #include "pipe/p_config.h"
 
-#if defined(PIPE_ARCH_X86)
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
 
 /* It is up to the caller to ensure that instructions issued are
  * suitable for the host cpu.  There are no checks made in this module
  * for mmx/sse/sse2 support on the cpu.
  */
 struct x86_reg {
-   unsigned file:3;
-   unsigned idx:3;
+   unsigned file:2;
+   unsigned idx:4;
    unsigned mod:2;             /* mod_REG if this is just a register */
    int      disp:24;           /* only +/- 23bits of offset - should be enough... */
 };
 
+#define X86_MMX 1
+#define X86_MMX2 2
+#define X86_SSE 4
+#define X86_SSE2 8
+#define X86_SSE3 0x10
+#define X86_SSE4_1 0x20
+
 struct x86_function {
+   unsigned caps;
    unsigned size;
    unsigned char *store;
    unsigned char *csr;
@@ -75,7 +84,15 @@ enum x86_reg_name {
    reg_SP,
    reg_BP,
    reg_SI,
-   reg_DI
+   reg_DI,
+   reg_R8,
+   reg_R9,
+   reg_R10,
+   reg_R11,
+   reg_R12,
+   reg_R13,
+   reg_R14,
+   reg_R15
 };
 
 
@@ -110,6 +127,29 @@ typedef void (*x86_func)(void);
 /* Begin/end/retrieve function creation:
  */
 
+enum x86_target
+{
+   X86_32,
+   X86_64_STD_ABI,
+   X86_64_WIN64_ABI
+};
+
+/* make this read a member of x86_function if target != host is desired */
+static INLINE enum x86_target x86_target( struct x86_function* p )
+{
+#ifdef PIPE_ARCH_X86
+   return X86_32;
+#elif defined(_WIN64)
+   return X86_64_WIN64_ABI;
+#elif defined(PIPE_ARCH_X86_64)
+   return X86_64_STD_ABI;
+#endif
+}
+
+static INLINE unsigned x86_target_caps( struct x86_function* p )
+{
+   return p->caps;
+}
 
 void x86_init_func( struct x86_function *p );
 void x86_init_func_size( struct x86_function *p, unsigned code_size );
@@ -138,6 +178,8 @@ struct x86_reg x86_get_base_reg( struct x86_reg reg );
  */
 int x86_get_label( struct x86_function *p );
 
+void x64_rexw(struct x86_function *p);
+
 void x86_jcc( struct x86_function *p,
              enum x86_cc cc,
              int label );
@@ -178,18 +220,54 @@ void mmx_movq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void mmx_packssdw( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void mmx_packuswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 
+void sse2_movd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_movq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_movdqu( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_movdqa( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_movsd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_movupd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_movapd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+
 void sse2_cvtps2dq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void sse2_cvttps2dq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void sse2_cvtdq2ps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_cvtsd2ss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_cvtpd2ps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+
 void sse2_movd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void sse2_packssdw( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void sse2_packsswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void sse2_packuswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void sse2_pshufd( struct x86_function *p, struct x86_reg dest, struct x86_reg arg0,
                   unsigned char shuf );
+void sse2_pshuflw( struct x86_function *p, struct x86_reg dest, struct x86_reg arg0,
+                  unsigned char shuf );
+void sse2_pshufhw( struct x86_function *p, struct x86_reg dest, struct x86_reg arg0,
+                  unsigned char shuf );
 void sse2_rcpps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void sse2_rcpss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 
+void sse2_punpcklbw( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_punpcklwd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_punpckldq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void sse2_punpcklqdq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+
+void sse2_psllw_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
+void sse2_pslld_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
+void sse2_psllq_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
+
+void sse2_psrlw_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
+void sse2_psrld_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
+void sse2_psrlq_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
+
+void sse2_psraw_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
+void sse2_psrad_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
+
+void sse2_por( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+
+void sse2_pshuflw( struct x86_function *p, struct x86_reg dst, struct x86_reg src, uint8_t imm );
+void sse2_pshufhw( struct x86_function *p, struct x86_reg dst, struct x86_reg src, uint8_t imm );
+void sse2_pshufd( struct x86_function *p, struct x86_reg dst, struct x86_reg src, uint8_t imm );
 
 void sse_prefetchnta( struct x86_function *p, struct x86_reg ptr);
 void sse_prefetch0( struct x86_function *p, struct x86_reg ptr);
@@ -227,7 +305,6 @@ void sse_shufps( struct x86_function *p, struct x86_reg dest, struct x86_reg arg
 void sse_unpckhps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void sse_unpcklps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void sse_pmovmskb( struct x86_function *p, struct x86_reg dest, struct x86_reg src );
-void sse2_punpcklbw( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void sse_movmskps( struct x86_function *p, struct x86_reg dst, struct x86_reg src);
 
 void x86_add( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
@@ -237,6 +314,14 @@ void x86_dec( struct x86_function *p, struct x86_reg reg );
 void x86_inc( struct x86_function *p, struct x86_reg reg );
 void x86_lea( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void x86_mov( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x64_mov64( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x86_mov8( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x86_mov16( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x86_movzx8(struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x86_movzx16(struct x86_function *p, struct x86_reg dst, struct x86_reg src );
+void x86_mov_imm(struct x86_function *p, struct x86_reg dst, int imm );
+void x86_mov8_imm(struct x86_function *p, struct x86_reg dst, uint8_t imm );
+void x86_mov16_imm(struct x86_function *p, struct x86_reg dst, uint16_t imm );
 void x86_mul( struct x86_function *p, struct x86_reg src );
 void x86_imul( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void x86_or( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
@@ -250,7 +335,10 @@ void x86_test( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void x86_xor( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
 void x86_sahf( struct x86_function *p );
 void x86_div( struct x86_function *p, struct x86_reg src );
-
+void x86_bswap( struct x86_function *p, struct x86_reg src );
+void x86_shr_imm( struct x86_function *p, struct x86_reg reg, unsigned imm );
+void x86_sar_imm( struct x86_function *p, struct x86_reg reg, unsigned imm );
+void x86_shl_imm( struct x86_function *p, struct x86_reg reg, unsigned imm  );
 
 void x86_cdecl_caller_push_regs( struct x86_function *p );
 void x86_cdecl_caller_pop_regs( struct x86_function *p );
index 4cd27317b36792b5d60e53c8efca3ee5dc51b054..dd78b361007001b50236aaf093f1565801c9b6e9 100644 (file)
@@ -28,6 +28,7 @@
 #ifndef TGSI_DUMP_H
 #define TGSI_DUMP_H
 
+#include "pipe/p_compiler.h"
 #include "pipe/p_shader_tokens.h"
 
 #if defined __cplusplus
index 298f3d0a8bb1807d375c21b1140181128bbc88da..0757f05dfabb7e528002e5dffb73cb36ddb65a16 100644 (file)
@@ -3239,6 +3239,8 @@ exec_instruction(
 
          if (mach->CallStackTop == 0) {
             /* returning from main() */
+            mach->CondStackTop = 0;
+            mach->LoopStackTop = 0;
             *pc = -1;
             return;
          }
@@ -3767,6 +3769,9 @@ tgsi_exec_machine_run( struct tgsi_exec_machine *mach )
    }
 #endif
 
+   /* Strictly speaking, these assertions aren't really needed but they
+    * can potentially catch some bugs in the control flow code.
+    */
    assert(mach->CondStackTop == 0);
    assert(mach->LoopStackTop == 0);
    assert(mach->ContStackTop == 0);
index 50248884fd0d67d4cde3c84ae147467f3e2fce3a..1992d11bbe847659436d2a966683fbf4dcdc028c 100644 (file)
@@ -28,6 +28,7 @@
 #ifndef TGSI_INFO_H
 #define TGSI_INFO_H
 
+#include "pipe/p_compiler.h"
 #include "pipe/p_shader_tokens.h"
 
 #if defined __cplusplus
index db9a3422203732cef76109b052b8e71397fef10b..1891203abe17acc2ce39151b52e15e4ac885abdd 100644 (file)
@@ -282,17 +282,6 @@ tgsi_parse_token(
 }
 
 
-unsigned
-tgsi_num_tokens(const struct tgsi_token *tokens)
-{
-   struct tgsi_parse_context ctx;
-   if (tgsi_parse_init(&ctx, tokens) == TGSI_PARSE_OK) {
-      unsigned len = (ctx.FullHeader.Header.HeaderSize +
-                      ctx.FullHeader.Header.BodySize);
-      return len;
-   }
-   return 0;
-}
 
 
 /**
@@ -319,3 +308,19 @@ tgsi_alloc_tokens(unsigned num_tokens)
    unsigned bytes = num_tokens * sizeof(struct tgsi_token);
    return (struct tgsi_token *) MALLOC(bytes);
 }
+
+
+void
+tgsi_dump_tokens(const struct tgsi_token *tokens)
+{
+   const unsigned *dwords = (const unsigned *)tokens;
+   int nr = tgsi_num_tokens(tokens);
+   int i;
+   
+   assert(sizeof(*tokens) == sizeof(unsigned));
+
+   debug_printf("const unsigned tokens[%d] = {\n", nr);
+   for (i = 0; i < nr; i++)
+      debug_printf("0x%08x,\n", dwords[i]);
+   debug_printf("};\n");
+}
index 36de8807b443a460f377dcd58326bfc64399aeb0..d4df5851764e91664e02747ad1c6635ab934767a 100644 (file)
@@ -28,6 +28,7 @@
 #ifndef TGSI_PARSE_H
 #define TGSI_PARSE_H
 
+#include "pipe/p_compiler.h"
 #include "pipe/p_shader_tokens.h"
 
 #if defined __cplusplus
@@ -132,8 +133,15 @@ void
 tgsi_parse_token(
    struct tgsi_parse_context *ctx );
 
-unsigned
-tgsi_num_tokens(const struct tgsi_token *tokens);
+static INLINE unsigned
+tgsi_num_tokens(const struct tgsi_token *tokens)
+{
+   struct tgsi_header header = *(const struct tgsi_header *) tokens;
+   return header.HeaderSize + header.BodySize;
+}
+
+void
+tgsi_dump_tokens(const struct tgsi_token *tokens);
 
 struct tgsi_token *
 tgsi_dup_tokens(const struct tgsi_token *tokens);
index d81ee3d00ec90e6f0faffb1ee924ea9353fb27fc..00aa8b84fe94707dd1e9479c51354cd1c684a5f2 100644 (file)
 extern "C" {
 #endif
 
+#include "pipe/p_compiler.h"
+
+struct tgsi_exec_machine;
+struct tgsi_interp_coef;
 struct tgsi_token;
 struct x86_function;
-struct tgsi_interp_coef;
 
 unsigned
 tgsi_emit_sse2(
index fe638e211fac95500b7c15284f0179a04fa70adf..73287b667db77b04cfb4a7dacb3587074ccd655c 100644 (file)
@@ -38,7 +38,7 @@ struct translate *translate_create( const struct translate_key *key )
 {
    struct translate *translate = NULL;
 
-#if defined(PIPE_ARCH_X86)
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
    translate = translate_sse2_create( key );
    if (translate)
       return translate;
index eb6f2cc4862b0793dbaa4e3902438db6edf19692..a75380228b1dd21f116843e35d4b9c07a750ae91 100644 (file)
@@ -85,6 +85,18 @@ struct translate {
                                 unsigned instance_id,
                                 void *output_buffer);
 
+   void (PIPE_CDECL *run_elts16)( struct translate *,
+                                const uint16_t *elts,
+                                unsigned count,
+                                unsigned instance_id,
+                                void *output_buffer);
+
+   void (PIPE_CDECL *run_elts8)( struct translate *,
+                                const uint8_t *elts,
+                                unsigned count,
+                                unsigned instance_id,
+                                void *output_buffer);
+
    void (PIPE_CDECL *run)( struct translate *,
                            unsigned start,
                            unsigned count,
index 42cfd763e9ca08a6eb19f39aef572d0f83fb172b..ad809db720d4b485d7c1b9ee55edb4ca678f31cf 100644 (file)
@@ -64,6 +64,14 @@ struct translate_generic {
       unsigned input_stride;
       unsigned max_index;
 
+      /* this value is set to -1 if this is a normal element with output_format != input_format:
+       * in this case, u_format is used to do a full conversion
+       *
+       * this value is set to the format size in bytes if output_format == input_format or for 32-bit instance ids:
+       * in this case, memcpy is used to copy this amount of bytes
+       */
+      int copy_size;
+
    } attrib[PIPE_MAX_ATTRIBS];
 
    unsigned nr_attrib;
@@ -354,7 +362,65 @@ static emit_func get_emit_func( enum pipe_format format )
    }
 }
 
+static ALWAYS_INLINE void PIPE_CDECL generic_run_one( struct translate_generic *tg,
+                                         unsigned elt,
+                                         unsigned instance_id,
+                                         void *vert )
+{
+   unsigned nr_attrs = tg->nr_attrib;
+   unsigned attr;
+
+   for (attr = 0; attr < nr_attrs; attr++) {
+      float data[4];
+      uint8_t *dst = (uint8_t *)vert + tg->attrib[attr].output_offset;
+
+      if (tg->attrib[attr].type == TRANSLATE_ELEMENT_NORMAL) {
+         const uint8_t *src;
+         unsigned index;
+         int copy_size;
+
+         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 +
+               tg->attrib[attr].input_stride * index;
+
+         copy_size = tg->attrib[attr].copy_size;
+         if(likely(copy_size >= 0))
+            memcpy(dst, src, copy_size);
+         else
+         {
+            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]);
+
+            tg->attrib[attr].emit( data, dst );
+         }
+      } else {
+         if(likely(tg->attrib[attr].copy_size >= 0))
+            memcpy(data, &instance_id, 4);
+         else
+         {
+            data[0] = (float)instance_id;
+            tg->attrib[attr].emit( data, dst );
+         }
+      }
+   }
+}
 
 /**
  * Fetch vertex attributes for 'count' vertices.
@@ -367,62 +433,45 @@ static void PIPE_CDECL generic_run_elts( struct translate *translate,
 {
    struct translate_generic *tg = translate_generic(translate);
    char *vert = output_buffer;
-   unsigned nr_attrs = tg->nr_attrib;
-   unsigned attr;
    unsigned i;
 
-   /* loop over vertex attributes (vertex shader inputs)
-    */
    for (i = 0; i < count; i++) {
-      const unsigned elt = *elts++;
-
-      for (attr = 0; attr < nr_attrs; attr++) {
-        float data[4];
-        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 +
-                  tg->attrib[attr].input_stride * index;
-
-            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;
-         }
+      generic_run_one(tg, *elts++, instance_id, vert);
+      vert += tg->translate.key.output_stride;
+   }
+}
 
-         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]);
+static void PIPE_CDECL generic_run_elts16( struct translate *translate,
+                                         const uint16_t *elts,
+                                         unsigned count,
+                                         unsigned instance_id,
+                                         void *output_buffer )
+{
+   struct translate_generic *tg = translate_generic(translate);
+   char *vert = output_buffer;
+   unsigned i;
 
-        tg->attrib[attr].emit( data, dst );
-      }
+   for (i = 0; i < count; i++) {
+      generic_run_one(tg, *elts++, instance_id, vert);
       vert += tg->translate.key.output_stride;
    }
 }
 
+static void PIPE_CDECL generic_run_elts8( struct translate *translate,
+                                         const uint8_t *elts,
+                                         unsigned count,
+                                         unsigned instance_id,
+                                         void *output_buffer )
+{
+   struct translate_generic *tg = translate_generic(translate);
+   char *vert = output_buffer;
+   unsigned i;
 
+   for (i = 0; i < count; i++) {
+      generic_run_one(tg, *elts++, instance_id, vert);
+      vert += tg->translate.key.output_stride;
+   }
+}
 
 static void PIPE_CDECL generic_run( struct translate *translate,
                                     unsigned start,
@@ -432,57 +481,10 @@ static void PIPE_CDECL generic_run( struct translate *translate,
 {
    struct translate_generic *tg = translate_generic(translate);
    char *vert = output_buffer;
-   unsigned nr_attrs = tg->nr_attrib;
-   unsigned attr;
    unsigned i;
 
-   /* loop over vertex attributes (vertex shader inputs)
-    */
    for (i = 0; i < count; i++) {
-      unsigned elt = start + i;
-
-      for (attr = 0; attr < nr_attrs; attr++) {
-        float data[4];
-        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 +
-                  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]);
-
-        tg->attrib[attr].emit( data, dst );
-      }
-      
+      generic_run_one(tg, start + i, instance_id, vert);
       vert += tg->translate.key.output_stride;
    }
 }
@@ -528,6 +530,8 @@ struct translate *translate_generic_create( const struct translate_key *key )
    tg->translate.release = generic_release;
    tg->translate.set_buffer = generic_set_buffer;
    tg->translate.run_elts = generic_run_elts;
+   tg->translate.run_elts16 = generic_run_elts16;
+   tg->translate.run_elts8 = generic_run_elts8;
    tg->translate.run = generic_run;
 
    for (i = 0; i < key->nr_elements; i++) {
@@ -544,9 +548,28 @@ struct translate *translate_generic_create( const struct translate_key *key )
       tg->attrib[i].input_offset = key->element[i].input_offset;
       tg->attrib[i].instance_divisor = key->element[i].instance_divisor;
 
-      tg->attrib[i].emit = get_emit_func(key->element[i].output_format);
       tg->attrib[i].output_offset = key->element[i].output_offset;
 
+      tg->attrib[i].copy_size = -1;
+      if (tg->attrib[i].type == TRANSLATE_ELEMENT_INSTANCE_ID)
+      {
+            if(key->element[i].output_format == PIPE_FORMAT_R32_USCALED
+                  || key->element[i].output_format == PIPE_FORMAT_R32_SSCALED)
+               tg->attrib[i].copy_size = 4;
+      }
+      else
+      {
+         if(key->element[i].input_format == key->element[i].output_format
+               && format_desc->block.width == 1
+               && format_desc->block.height == 1
+               && !(format_desc->block.bits & 7))
+            tg->attrib[i].copy_size = format_desc->block.bits >> 3;
+      }
+
+      if(tg->attrib[i].copy_size < 0)
+             tg->attrib[i].emit = get_emit_func(key->element[i].output_format);
+      else
+             tg->attrib[i].emit  = NULL;
    }
 
    tg->nr_attrib = key->nr_elements;
index ef3aa674a341eee4c80a572e476bae0ce969691b..f8bf5b46692762931c4e0391da738830d342acf0 100644 (file)
 #include "pipe/p_compiler.h"
 #include "util/u_memory.h"
 #include "util/u_math.h"
+#include "util/u_format.h"
 
 #include "translate.h"
 
 
-#if defined(PIPE_ARCH_X86)
+#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
 
 #include "rtasm/rtasm_cpu.h"
 #include "rtasm/rtasm_x86sse.h"
 #define W    3
 
 
-typedef void (PIPE_CDECL *run_func)( struct translate *translate,
-                                     unsigned start,
-                                     unsigned count,
-                                     unsigned instance_id,
-                                     void *output_buffer);
-
-typedef void (PIPE_CDECL *run_elts_func)( struct translate *translate,
-                                          const unsigned *elts,
-                                          unsigned count,
-                                          unsigned instance_id,
-                                          void *output_buffer);
-
 struct translate_buffer {
    const void *base_ptr;
-   unsigned stride;
+   uintptr_t stride;
    unsigned max_index;
 };
 
@@ -73,21 +62,43 @@ struct translate_buffer_varient {
 
 #define ELEMENT_BUFFER_INSTANCE_ID  1001
 
+#define NUM_CONSTS 7
+
+enum
+{
+   CONST_IDENTITY,
+   CONST_INV_127,
+   CONST_INV_255,
+   CONST_INV_32767,
+   CONST_INV_65535,
+   CONST_INV_2147483647,
+   CONST_255
+};
+
+#define C(v) {(float)(v), (float)(v), (float)(v), (float)(v)}
+static float consts[NUM_CONSTS][4] = {
+      {0, 0, 0, 1},
+      C(1.0 / 127.0),
+      C(1.0 / 255.0),
+      C(1.0 / 32767.0),
+      C(1.0 / 65535.0),
+      C(1.0 / 2147483647.0),
+      C(255.0)
+};
+#undef C
 
 struct translate_sse {
    struct translate translate;
 
    struct x86_function linear_func;
    struct x86_function elt_func;
+   struct x86_function elt16_func;
+   struct x86_function elt8_func;
    struct x86_function *func;
 
-   boolean loaded_identity;
-   boolean loaded_255;
-   boolean loaded_inv_255;
-
-   float identity[4];
-   float float_255[4];
-   float inv_255[4];
+   PIPE_ALIGN_VAR(16) float consts[NUM_CONSTS][4];
+   int8_t reg_to_const[16];
+   int8_t const_to_reg[NUM_CONSTS];
 
    struct translate_buffer buffer[PIPE_MAX_ATTRIBS];
    unsigned nr_buffers;
@@ -102,17 +113,16 @@ struct translate_sse {
    boolean use_instancing;
    unsigned instance_id;
 
-   run_func      gen_run;
-   run_elts_func gen_run_elts;
-
    /* these are actually known values, but putting them in a struct
     * like this is helpful to keep them in sync across the file.
     */
    struct x86_reg tmp_EAX;
-   struct x86_reg idx_EBX;     /* either start+i or &elt[i] */
-   struct x86_reg outbuf_ECX;
-   struct x86_reg machine_EDX;
-   struct x86_reg count_ESI;    /* decrements to zero */
+   struct x86_reg tmp2_EDX;
+   struct x86_reg src_ECX;
+   struct x86_reg idx_ESI;     /* either start+i or &elt[i] */
+   struct x86_reg machine_EDI;
+   struct x86_reg outbuf_EBX;
+   struct x86_reg count_EBP;    /* decrements to zero */
 };
 
 static int get_offset( const void *a, const void *b )
@@ -120,281 +130,950 @@ static int get_offset( const void *a, const void *b )
    return (const char *)b - (const char *)a;
 }
 
+static struct x86_reg get_const( struct translate_sse *p, unsigned id)
+{
+   struct x86_reg reg;
+   unsigned i;
 
+   if(p->const_to_reg[id] >= 0)
+      return x86_make_reg(file_XMM, p->const_to_reg[id]);
 
-static struct x86_reg get_identity( struct translate_sse *p )
-{
-   struct x86_reg reg = x86_make_reg(file_XMM, 6);
-
-   if (!p->loaded_identity) {
-      p->loaded_identity = TRUE;
-      p->identity[0] = 0;
-      p->identity[1] = 0;
-      p->identity[2] = 0;
-      p->identity[3] = 1;
-
-      sse_movups(p->func, reg, 
-                x86_make_disp(p->machine_EDX, 
-                              get_offset(p, &p->identity[0])));
+   for(i = 2; i < 8; ++i)
+   {
+      if(p->reg_to_const[i] < 0)
+         break;
    }
 
+   /* TODO: be smarter here */
+   if(i == 8)
+      --i;
+
+   reg = x86_make_reg(file_XMM, i);
+
+   if(p->reg_to_const[i] >= 0)
+      p->const_to_reg[p->reg_to_const[i]] = -1;
+
+   p->reg_to_const[i] = id;
+   p->const_to_reg[id] = i;
+
+   /* TODO: this should happen outside the loop, if possible */
+   sse_movaps(p->func, reg,
+         x86_make_disp(p->machine_EDI,
+               get_offset(p, &p->consts[id][0])));
+
    return reg;
 }
 
-static struct x86_reg get_255( struct translate_sse *p )
+/* load the data in a SSE2 register, padding with zeros */
+static boolean emit_load_sse2( struct translate_sse *p,
+                                      struct x86_reg data,
+                                      struct x86_reg src,
+                                      unsigned size)
 {
-   struct x86_reg reg = x86_make_reg(file_XMM, 7);
-
-   if (!p->loaded_255) {
-      p->loaded_255 = TRUE;
-      p->float_255[0] =
-        p->float_255[1] =
-        p->float_255[2] =
-        p->float_255[3] = 255.0f;
-
-      sse_movups(p->func, reg, 
-                x86_make_disp(p->machine_EDX, 
-                              get_offset(p, &p->float_255[0])));
+   struct x86_reg tmpXMM = x86_make_reg(file_XMM, 1);
+   struct x86_reg tmp = p->tmp_EAX;
+   switch(size)
+   {
+   case 1:
+      x86_movzx8(p->func, tmp, src);
+      sse2_movd(p->func, data, tmp);
+      break;
+   case 2:
+      x86_movzx16(p->func, tmp, src);
+      sse2_movd(p->func, data, tmp);
+      break;
+   case 3:
+      x86_movzx8(p->func, tmp, x86_make_disp(src, 2));
+      x86_shl_imm(p->func, tmp, 16);
+      x86_mov16(p->func, tmp, src);
+      sse2_movd(p->func, data, tmp);
+      break;
+   case 4:
+      sse2_movd(p->func, data, src);
+      break;
+   case 6:
+      sse2_movd(p->func, data, src);
+      x86_movzx16(p->func, tmp, x86_make_disp(src, 4));
+      sse2_movd(p->func, tmpXMM, tmp);
+      sse2_punpckldq(p->func, data, tmpXMM);
+      break;
+   case 8:
+      sse2_movq(p->func, data, src);
+      break;
+   case 12:
+      sse2_movq(p->func, data, src);
+      sse2_movd(p->func, tmpXMM, x86_make_disp(src, 8));
+      sse2_punpcklqdq(p->func, data, tmpXMM);
+      break;
+   case 16:
+      sse2_movdqu(p->func, data, src);
+      break;
+   default:
+      return FALSE;
    }
-
-   return reg;
+   return TRUE;
 }
 
-static struct x86_reg get_inv_255( struct translate_sse *p )
+/* this value can be passed for the out_chans argument */
+#define CHANNELS_0001 5
+
+/* this function will load #chans float values, and will
+ * pad the register with zeroes at least up to out_chans.
+ *
+ * If out_chans is set to CHANNELS_0001, then the fourth
+ * value will be padded with 1. Only pass this value if
+ * chans < 4 or results are undefined.
+ */
+static void emit_load_float32( struct translate_sse *p,
+                                       struct x86_reg data,
+                                       struct x86_reg arg0,
+                                       unsigned out_chans,
+                                       unsigned chans)
 {
-   struct x86_reg reg = x86_make_reg(file_XMM, 5);
-
-   if (!p->loaded_inv_255) {
-      p->loaded_inv_255 = TRUE;
-      p->inv_255[0] =
-        p->inv_255[1] =
-        p->inv_255[2] =
-        p->inv_255[3] = 1.0f / 255.0f;
-
-      sse_movups(p->func, reg, 
-                x86_make_disp(p->machine_EDX, 
-                              get_offset(p, &p->inv_255[0])));
+   switch(chans)
+   {
+   case 1:
+      /* a 0 0 0
+       * a 0 0 1
+       */
+      sse_movss(p->func, data, arg0);
+      if(out_chans == CHANNELS_0001)
+         sse_orps(p->func, data, get_const(p, CONST_IDENTITY) );
+      break;
+   case 2:
+      /* 0 0 0 1
+       * a b 0 1
+       */
+      if(out_chans == CHANNELS_0001)
+         sse_shufps(p->func, data, get_const(p, CONST_IDENTITY), SHUF(X, Y, Z, W) );
+      else if(out_chans > 2)
+         sse_movlhps(p->func, data, get_const(p, CONST_IDENTITY) );
+      sse_movlps(p->func, data, arg0);
+      break;
+   case 3:
+      /* Have to jump through some hoops:
+       *
+       * c 0 0 0
+       * c 0 0 1 if out_chans == CHANNELS_0001
+       * 0 0 c 0/1
+       * a b c 0/1
+       */
+      sse_movss(p->func, data, x86_make_disp(arg0, 8));
+      if(out_chans == CHANNELS_0001)
+         sse_shufps(p->func, data, get_const(p, CONST_IDENTITY), SHUF(X,Y,Z,W) );
+      sse_shufps(p->func, data, data, SHUF(Y,Z,X,W) );
+      sse_movlps(p->func, data, arg0);
+      break;
+   case 4:
+      sse_movups(p->func, data, arg0);
+      break;
    }
-
-   return reg;
 }
 
+/* this function behaves like emit_load_float32, but loads
+   64-bit floating point numbers, converting them to 32-bit
+  ones */
+static void emit_load_float64to32( struct translate_sse *p,
+                                       struct x86_reg data,
+                                       struct x86_reg arg0,
+                                       unsigned out_chans,
+                                       unsigned chans)
+{
+   struct x86_reg tmpXMM = x86_make_reg(file_XMM, 1);
+   switch(chans)
+   {
+   case 1:
+      sse2_movsd(p->func, data, arg0);
+      if(out_chans > 1)
+         sse2_cvtpd2ps(p->func, data, data);
+      else
+         sse2_cvtsd2ss(p->func, data, data);
+      if(out_chans == CHANNELS_0001)
+         sse_shufps(p->func, data, get_const(p, CONST_IDENTITY), SHUF(X, Y, Z, W)  );
+      break;
+   case 2:
+      sse2_movupd(p->func, data, arg0);
+      sse2_cvtpd2ps(p->func, data, data);
+      if(out_chans == CHANNELS_0001)
+         sse_shufps(p->func, data, get_const(p, CONST_IDENTITY), SHUF(X, Y, Z, W) );
+      else if(out_chans > 2)
+         sse_movlhps(p->func, data, get_const(p, CONST_IDENTITY) );
+       break;
+   case 3:
+      sse2_movupd(p->func, data, arg0);
+      sse2_cvtpd2ps(p->func, data, data);
+      sse2_movsd(p->func, tmpXMM, x86_make_disp(arg0, 16));
+      if(out_chans > 3)
+         sse2_cvtpd2ps(p->func, tmpXMM, tmpXMM);
+      else
+         sse2_cvtsd2ss(p->func, tmpXMM, tmpXMM);
+      sse_movlhps(p->func, data, tmpXMM);
+      if(out_chans == CHANNELS_0001)
+         sse_orps(p->func, data, get_const(p, CONST_IDENTITY) );
+      break;
+   case 4:
+      sse2_movupd(p->func, data, arg0);
+      sse2_cvtpd2ps(p->func, data, data);
+      sse2_movupd(p->func, tmpXMM, x86_make_disp(arg0, 16));
+      sse2_cvtpd2ps(p->func, tmpXMM, tmpXMM);
+      sse_movlhps(p->func, data, tmpXMM);
+      break;
+   }
+}
 
-static void emit_load_R32G32B32A32( struct translate_sse *p,                      
-                                   struct x86_reg data,
-                                   struct x86_reg arg0 )
+static void emit_mov64(struct translate_sse *p, struct x86_reg dst_gpr, struct x86_reg dst_xmm, struct x86_reg src_gpr,  struct x86_reg src_xmm)
 {
-   sse_movups(p->func, data, arg0);
+   if(x86_target(p->func) != X86_32)
+      x64_mov64(p->func, dst_gpr, src_gpr);
+   else
+   {
+      /* TODO: when/on which CPUs is SSE2 actually better than SSE? */
+      if(x86_target_caps(p->func) & X86_SSE2)
+         sse2_movq(p->func, dst_xmm, src_xmm);
+      else
+         sse_movlps(p->func, dst_xmm, src_xmm);
+   }
 }
 
-static void emit_load_R32G32B32( struct translate_sse *p,                         
-                                struct x86_reg data,
-                                struct x86_reg arg0 )
+static void emit_load64(struct translate_sse *p, struct x86_reg dst_gpr, struct x86_reg dst_xmm, struct x86_reg src)
 {
-   /* Have to jump through some hoops:
-    *
-    * c 0 0 0
-    * c 0 0 1
-    * 0 0 c 1
-    * a b c 1
-    */
-   sse_movss(p->func, data, x86_make_disp(arg0, 8));
-   sse_shufps(p->func, data, get_identity(p), SHUF(X,Y,Z,W) );
-   sse_shufps(p->func, data, data, SHUF(Y,Z,X,W) );
-   sse_movlps(p->func, data, arg0);
+   emit_mov64(p, dst_gpr, dst_xmm, src, src);
 }
 
-static void emit_load_R32G32( struct translate_sse *p, 
-                          struct x86_reg data,
-                          struct x86_reg arg0 )
+static void emit_store64(struct translate_sse *p, struct x86_reg dst, struct x86_reg src_gpr, struct x86_reg src_xmm)
 {
-   /* 0 0 0 1
-    * a b 0 1
-    */
-   sse_movups(p->func, data, get_identity(p) );
-   sse_movlps(p->func, data, arg0);
+   emit_mov64(p, dst, dst, src_gpr, src_xmm);
 }
 
+static void emit_mov128(struct translate_sse *p, struct x86_reg dst, struct x86_reg src)
+{
+   if(x86_target_caps(p->func) & X86_SSE2)
+      sse2_movdqu(p->func, dst, src);
+   else
+      sse_movups(p->func, dst, src);
+}
 
-static void emit_load_R32( struct translate_sse *p, 
-                          struct x86_reg data,
-                          struct x86_reg arg0 )
+/* TODO: this uses unaligned accesses liberally, which is great on Nehalem,
+ * but may or may not be good on older processors
+ * TODO: may perhaps want to use non-temporal stores here if possible
+ */
+static void emit_memcpy(struct translate_sse *p, struct x86_reg dst, struct x86_reg src, unsigned size)
 {
-   /* a 0 0 0
-    * a 0 0 1
-    */
-   sse_movss(p->func, data, arg0);
-   sse_orps(p->func, data, get_identity(p) );
+   struct x86_reg dataXMM = x86_make_reg(file_XMM, 0);
+   struct x86_reg dataXMM2 = x86_make_reg(file_XMM, 1);
+   struct x86_reg dataGPR = p->tmp_EAX;
+   struct x86_reg dataGPR2 = p->tmp2_EDX;
+
+   if(size < 8)
+   {
+      switch (size)
+      {
+      case 1:
+         x86_mov8(p->func, dataGPR, src);
+         x86_mov8(p->func, dst, dataGPR);
+         break;
+      case 2:
+         x86_mov16(p->func, dataGPR, src);
+         x86_mov16(p->func, dst, dataGPR);
+         break;
+      case 3:
+         x86_mov16(p->func, dataGPR, src);
+         x86_mov8(p->func, dataGPR2, x86_make_disp(src, 2));
+         x86_mov16(p->func, dst, dataGPR);
+         x86_mov8(p->func, x86_make_disp(dst, 2), dataGPR2);
+         break;
+      case 4:
+         x86_mov(p->func, dataGPR, src);
+         x86_mov(p->func, dst, dataGPR);
+         break;
+      case 6:
+         x86_mov(p->func, dataGPR, src);
+         x86_mov16(p->func, dataGPR2, x86_make_disp(src, 4));
+         x86_mov(p->func, dst, dataGPR);
+         x86_mov16(p->func, x86_make_disp(dst, 4), dataGPR2);
+         break;
+      }
+   }
+   else if(!(x86_target_caps(p->func) & X86_SSE))
+   {
+      unsigned i = 0;
+      assert((size & 3) == 0);
+      for(i = 0; i < size; i += 4)
+      {
+         x86_mov(p->func, dataGPR, x86_make_disp(src, i));
+         x86_mov(p->func, x86_make_disp(dst, i), dataGPR);
+      }
+   }
+   else
+   {
+      switch(size)
+      {
+      case 8:
+         emit_load64(p, dataGPR, dataXMM, src);
+         emit_store64(p, dst, dataGPR, dataXMM);
+         break;
+      case 12:
+         emit_load64(p, dataGPR2, dataXMM, src);
+         x86_mov(p->func, dataGPR, x86_make_disp(src, 8));
+         emit_store64(p, dst, dataGPR2, dataXMM);
+         x86_mov(p->func, x86_make_disp(dst, 8), dataGPR);
+         break;
+      case 16:
+         emit_mov128(p, dataXMM, src);
+         emit_mov128(p, dst, dataXMM);
+         break;
+      case 24:
+         emit_mov128(p, dataXMM, src);
+         emit_load64(p, dataGPR, dataXMM2, x86_make_disp(src, 16));
+         emit_mov128(p, dst, dataXMM);
+         emit_store64(p, x86_make_disp(dst, 16), dataGPR, dataXMM2);
+         break;
+      case 32:
+         emit_mov128(p, dataXMM, src);
+         emit_mov128(p, dataXMM2, x86_make_disp(src, 16));
+         emit_mov128(p, dst, dataXMM);
+         emit_mov128(p, x86_make_disp(dst, 16), dataXMM2);
+         break;
+      default:
+         assert(0);
+      }
+   }
 }
 
+static boolean translate_attr_convert( struct translate_sse *p,
+                               const struct translate_element *a,
+                               struct x86_reg src,
+                               struct x86_reg dst)
 
-static void emit_load_R8G8B8A8_UNORM( struct translate_sse *p,
-                                      struct x86_reg data,
-                                      struct x86_reg src )
 {
+   const struct util_format_description* input_desc = util_format_description(a->input_format);
+   const struct util_format_description* output_desc = util_format_description(a->output_format);
+   unsigned i;
+   boolean id_swizzle = TRUE;
+   unsigned swizzle[4] = {UTIL_FORMAT_SWIZZLE_NONE, UTIL_FORMAT_SWIZZLE_NONE, UTIL_FORMAT_SWIZZLE_NONE, UTIL_FORMAT_SWIZZLE_NONE};
+   unsigned needed_chans = 0;
+   unsigned imms[2] = {0, 0x3f800000};
 
-   /* Load and unpack twice:
-    */
-   sse_movss(p->func, data, src);
-   sse2_punpcklbw(p->func, data, get_identity(p));
-   sse2_punpcklbw(p->func, data, get_identity(p));
+   if(a->output_format == PIPE_FORMAT_NONE || a->input_format == PIPE_FORMAT_NONE)
+      return FALSE;
 
-   /* Convert to float:
-    */
-   sse2_cvtdq2ps(p->func, data, data);
+   if(input_desc->channel[0].size & 7)
+      return FALSE;
 
+   if(input_desc->colorspace != output_desc->colorspace)
+      return FALSE;
 
-   /* Scale by 1/255.0
-    */
-   sse_mulps(p->func, data, get_inv_255(p));
-}
+   for(i = 1; i < input_desc->nr_channels; ++i)
+   {
+      if(memcmp(&input_desc->channel[i], &input_desc->channel[0], sizeof(input_desc->channel[0])))
+         return FALSE;
+   }
 
+   for(i = 1; i < output_desc->nr_channels; ++i)
+   {
+      if(memcmp(&output_desc->channel[i], &output_desc->channel[0], sizeof(output_desc->channel[0])))
+         return FALSE;
+   }
 
+   for(i = 0; i < output_desc->nr_channels; ++i)
+   {
+      if(output_desc->swizzle[i] < 4)
+         swizzle[output_desc->swizzle[i]] = input_desc->swizzle[i];
+   }
 
+   if((x86_target_caps(p->func) & X86_SSE) && (0
+         || a->output_format == PIPE_FORMAT_R32_FLOAT
+         || a->output_format == PIPE_FORMAT_R32G32_FLOAT
+         || a->output_format == PIPE_FORMAT_R32G32B32_FLOAT
+         || a->output_format == PIPE_FORMAT_R32G32B32A32_FLOAT))
+   {
+      struct x86_reg dataXMM = x86_make_reg(file_XMM, 0);
 
-static void emit_store_R32G32B32A32( struct translate_sse *p,                     
-                                    struct x86_reg dest,
-                                    struct x86_reg dataXMM )
-{
-   sse_movups(p->func, dest, dataXMM);
-}
+      for(i = 0; i < output_desc->nr_channels; ++i)
+      {
+         if(swizzle[i] == UTIL_FORMAT_SWIZZLE_0 && i >= input_desc->nr_channels)
+            swizzle[i] = i;
+      }
 
-static void emit_store_R32G32B32( struct translate_sse *p, 
-                                 struct x86_reg dest,
-                                 struct x86_reg dataXMM )
-{
-   /* Emit two, shuffle, emit one.
-    */
-   sse_movlps(p->func, dest, dataXMM);
-   sse_shufps(p->func, dataXMM, dataXMM, SHUF(Z,Z,Z,Z) ); /* NOTE! destructive */
-   sse_movss(p->func, x86_make_disp(dest,8), dataXMM);
-}
+      for(i = 0; i < output_desc->nr_channels; ++i)
+      {
+         if(swizzle[i] < 4)
+            needed_chans = MAX2(needed_chans, swizzle[i] + 1);
+         if(swizzle[i] < UTIL_FORMAT_SWIZZLE_0 && swizzle[i] != i)
+            id_swizzle = FALSE;
+      }
 
-static void emit_store_R32G32( struct translate_sse *p, 
-                              struct x86_reg dest,
-                              struct x86_reg dataXMM )
-{
-   sse_movlps(p->func, dest, dataXMM);
-}
+      if(needed_chans > 0)
+      {
+         switch(input_desc->channel[0].type)
+         {
+         case UTIL_FORMAT_TYPE_UNSIGNED:
+            if(!(x86_target_caps(p->func) & X86_SSE2))
+               return FALSE;
+            emit_load_sse2(p, dataXMM, src, input_desc->channel[0].size * input_desc->nr_channels >> 3);
+
+            /* TODO: add support for SSE4.1 pmovzx */
+            switch(input_desc->channel[0].size)
+            {
+            case 8:
+               /* TODO: this may be inefficient due to get_identity() being used both as a float and integer register */
+               sse2_punpcklbw(p->func, dataXMM, get_const(p, CONST_IDENTITY));
+               sse2_punpcklbw(p->func, dataXMM, get_const(p, CONST_IDENTITY));
+               break;
+            case 16:
+               sse2_punpcklwd(p->func, dataXMM, get_const(p, CONST_IDENTITY));
+               break;
+            case 32: /* we lose precision here */
+               sse2_psrld_imm(p->func, dataXMM, 1);
+               break;
+            default:
+               return FALSE;
+            }
+            sse2_cvtdq2ps(p->func, dataXMM, dataXMM);
+            if(input_desc->channel[0].normalized)
+            {
+               struct x86_reg factor;
+               switch(input_desc->channel[0].size)
+               {
+               case 8:
+                  factor = get_const(p, CONST_INV_255);
+                  break;
+               case 16:
+                  factor = get_const(p, CONST_INV_65535);
+                  break;
+               case 32:
+                  factor = get_const(p, CONST_INV_2147483647);
+                  break;
+               default:
+                  assert(0);
+                  factor.disp = 0;
+                  factor.file = 0;
+                  factor.idx = 0;
+                  factor.mod = 0;
+                  break;
+               }
+               sse_mulps(p->func, dataXMM, factor);
+            }
+            else if(input_desc->channel[0].size == 32)
+               sse_addps(p->func, dataXMM, dataXMM); /* compensate for the bit we threw away to fit u32 into s32 */
+            break;
+         case UTIL_FORMAT_TYPE_SIGNED:
+            if(!(x86_target_caps(p->func) & X86_SSE2))
+               return FALSE;
+            emit_load_sse2(p, dataXMM, src, input_desc->channel[0].size * input_desc->nr_channels >> 3);
+
+            /* TODO: add support for SSE4.1 pmovsx */
+            switch(input_desc->channel[0].size)
+            {
+            case 8:
+               sse2_punpcklbw(p->func, dataXMM, dataXMM);
+               sse2_punpcklbw(p->func, dataXMM, dataXMM);
+               sse2_psrad_imm(p->func, dataXMM, 24);
+               break;
+            case 16:
+               sse2_punpcklwd(p->func, dataXMM, dataXMM);
+               sse2_psrad_imm(p->func, dataXMM, 16);
+               break;
+            case 32: /* we lose precision here */
+               break;
+            default:
+               return FALSE;
+            }
+            sse2_cvtdq2ps(p->func, dataXMM, dataXMM);
+            if(input_desc->channel[0].normalized)
+            {
+               struct x86_reg factor;
+               switch(input_desc->channel[0].size)
+               {
+               case 8:
+                  factor = get_const(p, CONST_INV_127);
+                  break;
+               case 16:
+                  factor = get_const(p, CONST_INV_32767);
+                  break;
+               case 32:
+                  factor = get_const(p, CONST_INV_2147483647);
+                  break;
+               default:
+                  assert(0);
+                  factor.disp = 0;
+                  factor.file = 0;
+                  factor.idx = 0;
+                  factor.mod = 0;
+                  break;
+               }
+               sse_mulps(p->func, dataXMM, factor);
+            }
+            break;
+
+            break;
+         case UTIL_FORMAT_TYPE_FLOAT:
+            if(input_desc->channel[0].size != 32 && input_desc->channel[0].size != 64)
+               return FALSE;
+            if(swizzle[3] == UTIL_FORMAT_SWIZZLE_1 && input_desc->nr_channels <= 3)
+            {
+               swizzle[3] = UTIL_FORMAT_SWIZZLE_W;
+               needed_chans = CHANNELS_0001;
+            }
+            switch(input_desc->channel[0].size)
+            {
+            case 32:
+               emit_load_float32(p, dataXMM, src, needed_chans, input_desc->nr_channels);
+               break;
+            case 64: /* we lose precision here */
+               if(!(x86_target_caps(p->func) & X86_SSE2))
+                  return FALSE;
+               emit_load_float64to32(p, dataXMM, src, needed_chans, input_desc->nr_channels);
+               break;
+            default:
+               return FALSE;
+            }
+            break;
+         default:
+            return FALSE;
+         }
 
-static void emit_store_R32( struct translate_sse *p, 
-                           struct x86_reg dest,
-                           struct x86_reg dataXMM )
-{
-   sse_movss(p->func, dest, dataXMM);
-}
+         if(!id_swizzle)
+            sse_shufps(p->func, dataXMM, dataXMM, SHUF(swizzle[0], swizzle[1], swizzle[2], swizzle[3]) );
+      }
 
+      if(output_desc->nr_channels >= 4
+            && swizzle[0] < UTIL_FORMAT_SWIZZLE_0
+            && swizzle[1] < UTIL_FORMAT_SWIZZLE_0
+            && swizzle[2] < UTIL_FORMAT_SWIZZLE_0
+            && swizzle[3] < UTIL_FORMAT_SWIZZLE_0
+            )
+         sse_movups(p->func, dst, dataXMM);
+      else
+      {
+         if(output_desc->nr_channels >= 2
+               && swizzle[0] < UTIL_FORMAT_SWIZZLE_0
+               && swizzle[1] < UTIL_FORMAT_SWIZZLE_0)
+            sse_movlps(p->func, dst, dataXMM);
+         else
+         {
+            if(swizzle[0] < UTIL_FORMAT_SWIZZLE_0)
+               sse_movss(p->func, dst, dataXMM);
+            else
+               x86_mov_imm(p->func, dst, imms[swizzle[0] - UTIL_FORMAT_SWIZZLE_0]);
+
+            if(output_desc->nr_channels >= 2)
+            {
+               if(swizzle[1] < UTIL_FORMAT_SWIZZLE_0)
+               {
+                  sse_shufps(p->func, dataXMM, dataXMM, SHUF(1, 1, 2, 3));
+                  sse_movss(p->func, x86_make_disp(dst, 4), dataXMM);
+               }
+               else
+                  x86_mov_imm(p->func, x86_make_disp(dst, 4), imms[swizzle[1] - UTIL_FORMAT_SWIZZLE_0]);
+            }
+         }
 
+         if(output_desc->nr_channels >= 3)
+         {
+            if(output_desc->nr_channels >= 4
+                  && swizzle[2] < UTIL_FORMAT_SWIZZLE_0
+                  && swizzle[3] < UTIL_FORMAT_SWIZZLE_0)
+               sse_movhps(p->func, x86_make_disp(dst, 8), dataXMM);
+            else
+            {
+               if(swizzle[2] < UTIL_FORMAT_SWIZZLE_0)
+               {
+                  sse_shufps(p->func, dataXMM, dataXMM, SHUF(2, 2, 2, 3));
+                  sse_movss(p->func, x86_make_disp(dst, 8), dataXMM);
+               }
+               else
+                  x86_mov_imm(p->func, x86_make_disp(dst, 8), imms[swizzle[2] - UTIL_FORMAT_SWIZZLE_0]);
+
+               if(output_desc->nr_channels >= 4)
+               {
+                  if(swizzle[3] < UTIL_FORMAT_SWIZZLE_0)
+                  {
+                     sse_shufps(p->func, dataXMM, dataXMM, SHUF(3, 3, 3, 3));
+                     sse_movss(p->func, x86_make_disp(dst, 12), dataXMM);
+                  }
+                  else
+                     x86_mov_imm(p->func, x86_make_disp(dst, 12), imms[swizzle[3] - UTIL_FORMAT_SWIZZLE_0]);
+               }
+            }
+         }
+      }
+      return TRUE;
+   }
+   else if((x86_target_caps(p->func) & X86_SSE2) && input_desc->channel[0].size == 8 && output_desc->channel[0].size == 16
+         && output_desc->channel[0].normalized == input_desc->channel[0].normalized
+         && (0
+               || (input_desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED && output_desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED)
+               || (input_desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED && output_desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED)
+               || (input_desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED && output_desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED)
+               ))
+   {
+      struct x86_reg dataXMM = x86_make_reg(file_XMM, 0);
+      struct x86_reg tmpXMM = x86_make_reg(file_XMM, 1);
+      struct x86_reg tmp = p->tmp_EAX;
+      unsigned imms[2] = {0, 1};
+
+      for(i = 0; i < output_desc->nr_channels; ++i)
+      {
+         if(swizzle[i] == UTIL_FORMAT_SWIZZLE_0 && i >= input_desc->nr_channels)
+            swizzle[i] = i;
+      }
 
-static void emit_store_R8G8B8A8_UNORM( struct translate_sse *p,
-                                      struct x86_reg dest,
-                                      struct x86_reg dataXMM )
-{
-   /* Scale by 255.0
-    */
-   sse_mulps(p->func, dataXMM, get_255(p));
+      for(i = 0; i < output_desc->nr_channels; ++i)
+      {
+         if(swizzle[i] < 4)
+            needed_chans = MAX2(needed_chans, swizzle[i] + 1);
+         if(swizzle[i] < UTIL_FORMAT_SWIZZLE_0 && swizzle[i] != i)
+            id_swizzle = FALSE;
+      }
 
-   /* Pack and emit:
-    */
-   sse2_cvtps2dq(p->func, dataXMM, dataXMM);
-   sse2_packssdw(p->func, dataXMM, dataXMM);
-   sse2_packuswb(p->func, dataXMM, dataXMM);
-   sse_movss(p->func, dest, dataXMM);
-}
+      if(needed_chans > 0)
+      {
+         emit_load_sse2(p, dataXMM, src, input_desc->channel[0].size * input_desc->nr_channels >> 3);
+
+         switch(input_desc->channel[0].type)
+         {
+         case UTIL_FORMAT_TYPE_UNSIGNED:
+            if(input_desc->channel[0].normalized)
+            {
+               sse2_punpcklbw(p->func, dataXMM, dataXMM);
+               if(output_desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED)
+                      sse2_psrlw_imm(p->func, dataXMM, 1);
+            }
+            else
+               sse2_punpcklbw(p->func, dataXMM, get_const(p, CONST_IDENTITY));
+            break;
+         case UTIL_FORMAT_TYPE_SIGNED:
+            if(input_desc->channel[0].normalized)
+            {
+               sse2_movq(p->func, tmpXMM, get_const(p, CONST_IDENTITY));
+               sse2_punpcklbw(p->func, tmpXMM, dataXMM);
+               sse2_psllw_imm(p->func, dataXMM, 9);
+               sse2_psrlw_imm(p->func, dataXMM, 8);
+               sse2_por(p->func, tmpXMM, dataXMM);
+               sse2_psrlw_imm(p->func, dataXMM, 7);
+               sse2_por(p->func, tmpXMM, dataXMM);
+               {
+                  struct x86_reg t = dataXMM;
+                  dataXMM = tmpXMM;
+                  tmpXMM = t;
+               }
+            }
+            else
+            {
+               sse2_punpcklbw(p->func, dataXMM, dataXMM);
+               sse2_psraw_imm(p->func, dataXMM, 8);
+            }
+            break;
+         default:
+            assert(0);
+         }
 
+         if(output_desc->channel[0].normalized)
+            imms[1] = (output_desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED) ? 0xffff : 0x7ffff;
 
+         if(!id_swizzle)
+            sse2_pshuflw(p->func, dataXMM, dataXMM, (swizzle[0] & 3) | ((swizzle[1] & 3) << 2) | ((swizzle[2] & 3) << 4) | ((swizzle[3] & 3) << 6));
+      }
 
+      if(output_desc->nr_channels >= 4
+            && swizzle[0] < UTIL_FORMAT_SWIZZLE_0
+            && swizzle[1] < UTIL_FORMAT_SWIZZLE_0
+            && swizzle[2] < UTIL_FORMAT_SWIZZLE_0
+            && swizzle[3] < UTIL_FORMAT_SWIZZLE_0
+            )
+         sse2_movq(p->func, dst, dataXMM);
+      else
+      {
+         if(swizzle[0] < UTIL_FORMAT_SWIZZLE_0)
+         {
+            if(output_desc->nr_channels >= 2 && swizzle[1] < UTIL_FORMAT_SWIZZLE_0)
+               sse2_movd(p->func, dst, dataXMM);
+            else
+            {
+               sse2_movd(p->func, tmp, dataXMM);
+               x86_mov16(p->func, dst, tmp);
+               if(output_desc->nr_channels >= 2)
+                  x86_mov16_imm(p->func, x86_make_disp(dst, 2), imms[swizzle[1] - UTIL_FORMAT_SWIZZLE_0]);
+            }
+         }
+         else
+         {
+            if(output_desc->nr_channels >= 2 && swizzle[1] >= UTIL_FORMAT_SWIZZLE_0)
+               x86_mov_imm(p->func, dst, (imms[swizzle[1] - UTIL_FORMAT_SWIZZLE_0] << 16) | imms[swizzle[0] - UTIL_FORMAT_SWIZZLE_0]);
+            else
+            {
+               x86_mov16_imm(p->func, dst, imms[swizzle[0] - UTIL_FORMAT_SWIZZLE_0]);
+               if(output_desc->nr_channels >= 2)
+               {
+                  sse2_movd(p->func, tmp, dataXMM);
+                  x86_shr_imm(p->func, tmp, 16);
+                  x86_mov16(p->func, x86_make_disp(dst, 2), tmp);
+               }
+            }
+         }
 
+         if(output_desc->nr_channels >= 3)
+         {
+            if(swizzle[2] < UTIL_FORMAT_SWIZZLE_0)
+            {
+               if(output_desc->nr_channels >= 4 && swizzle[3] < UTIL_FORMAT_SWIZZLE_0)
+               {
+                  sse2_psrlq_imm(p->func, dataXMM, 32);
+                  sse2_movd(p->func, x86_make_disp(dst, 4), dataXMM);
+               }
+               else
+               {
+                  sse2_psrlq_imm(p->func, dataXMM, 32);
+                  sse2_movd(p->func, tmp, dataXMM);
+                  x86_mov16(p->func, x86_make_disp(dst, 4), tmp);
+                  if(output_desc->nr_channels >= 4)
+                  {
+                     x86_mov16_imm(p->func, x86_make_disp(dst, 6), imms[swizzle[3] - UTIL_FORMAT_SWIZZLE_0]);
+                  }
+               }
+            }
+            else
+            {
+               if(output_desc->nr_channels >= 4 && swizzle[3] >= UTIL_FORMAT_SWIZZLE_0)
+                  x86_mov_imm(p->func, x86_make_disp(dst, 4), (imms[swizzle[3] - UTIL_FORMAT_SWIZZLE_0] << 16) | imms[swizzle[2] - UTIL_FORMAT_SWIZZLE_0]);
+               else
+               {
+                  x86_mov16_imm(p->func, x86_make_disp(dst, 4), imms[swizzle[2] - UTIL_FORMAT_SWIZZLE_0]);
+
+                  if(output_desc->nr_channels >= 4)
+                  {
+                     sse2_psrlq_imm(p->func, dataXMM, 48);
+                     sse2_movd(p->func, tmp, dataXMM);
+                     x86_mov16(p->func, x86_make_disp(dst, 6), tmp);
+                  }
+               }
+            }
+         }
+      }
+      return TRUE;
+   }
+   else if(!memcmp(&output_desc->channel[0], &input_desc->channel[0], sizeof(output_desc->channel[0])))
+   {
+      struct x86_reg tmp = p->tmp_EAX;
+      unsigned i;
+      if(input_desc->channel[0].size == 8 && input_desc->nr_channels == 4 && output_desc->nr_channels == 4
+                     && swizzle[0] == UTIL_FORMAT_SWIZZLE_W
+                     && swizzle[1] == UTIL_FORMAT_SWIZZLE_Z
+                     && swizzle[2] == UTIL_FORMAT_SWIZZLE_Y
+                     && swizzle[3] == UTIL_FORMAT_SWIZZLE_X)
+      {
+         /* TODO: support movbe */
+         x86_mov(p->func, tmp, src);
+         x86_bswap(p->func, tmp);
+         x86_mov(p->func, dst, tmp);
+         return TRUE;
+      }
 
-/* Extended swizzles?  Maybe later.
- */  
-static void emit_swizzle( struct translate_sse *p,
-                         struct x86_reg dest,
-                         struct x86_reg src,
-                         unsigned char shuffle )
-{
-   sse_shufps(p->func, dest, src, shuffle);
-}
+      for(i = 0; i < output_desc->nr_channels; ++i)
+      {
+         switch(output_desc->channel[0].size)
+         {
+         case 8:
+            if(swizzle[i] >= UTIL_FORMAT_SWIZZLE_0)
+            {
+               unsigned v = 0;
+               if(swizzle[i] == UTIL_FORMAT_SWIZZLE_1)
+               {
+                  switch(output_desc->channel[0].type)
+                  {
+                  case UTIL_FORMAT_TYPE_UNSIGNED:
+                     v = output_desc->channel[0].normalized ? 0xff : 1;
+                     break;
+                  case UTIL_FORMAT_TYPE_SIGNED:
+                     v = output_desc->channel[0].normalized ? 0x7f : 1;
+                     break;
+                  default:
+                     return FALSE;
+                  }
+               }
+               x86_mov8_imm(p->func, x86_make_disp(dst, i * 1), v);
+            }
+            else
+            {
+               x86_mov8(p->func, tmp, x86_make_disp(src, swizzle[i] * 1));
+               x86_mov8(p->func, x86_make_disp(dst, i * 1), tmp);
+            }
+            break;
+         case 16:
+            if(swizzle[i] >= UTIL_FORMAT_SWIZZLE_0)
+            {
+               unsigned v = 0;
+               if(swizzle[i] == UTIL_FORMAT_SWIZZLE_1)
+               {
+                  switch(output_desc->channel[1].type)
+                  {
+                  case UTIL_FORMAT_TYPE_UNSIGNED:
+                     v = output_desc->channel[1].normalized ? 0xffff : 1;
+                     break;
+                  case UTIL_FORMAT_TYPE_SIGNED:
+                     v = output_desc->channel[1].normalized ? 0x7fff : 1;
+                     break;
+                  case UTIL_FORMAT_TYPE_FLOAT:
+                     v = 0x3c00;
+                     break;
+                  default:
+                     return FALSE;
+                  }
+               }
+               x86_mov16_imm(p->func, x86_make_disp(dst, i * 2), v);
+            }
+            else if(swizzle[i] == UTIL_FORMAT_SWIZZLE_0)
+               x86_mov16_imm(p->func, x86_make_disp(dst, i * 2), 0);
+            else
+            {
+               x86_mov16(p->func, tmp, x86_make_disp(src, swizzle[i] * 2));
+               x86_mov16(p->func, x86_make_disp(dst, i * 2), tmp);
+            }
+            break;
+         case 32:
+            if(swizzle[i] >= UTIL_FORMAT_SWIZZLE_0)
+            {
+               unsigned v = 0;
+               if(swizzle[i] == UTIL_FORMAT_SWIZZLE_1)
+               {
+                  switch(output_desc->channel[1].type)
+                  {
+                  case UTIL_FORMAT_TYPE_UNSIGNED:
+                     v = output_desc->channel[1].normalized ? 0xffffffff : 1;
+                     break;
+                  case UTIL_FORMAT_TYPE_SIGNED:
+                     v = output_desc->channel[1].normalized ? 0x7fffffff : 1;
+                     break;
+                  case UTIL_FORMAT_TYPE_FLOAT:
+                     v = 0x3f800000;
+                     break;
+                  default:
+                     return FALSE;
+                  }
+               }
+               x86_mov_imm(p->func, x86_make_disp(dst, i * 4), v);
+            }
+            else
+            {
+               x86_mov(p->func, tmp, x86_make_disp(src, swizzle[i] * 4));
+               x86_mov(p->func, x86_make_disp(dst, i * 4), tmp);
+            }
+            break;
+         case 64:
+            if(swizzle[i] >= UTIL_FORMAT_SWIZZLE_0)
+            {
+               unsigned l = 0;
+               unsigned h = 0;
+               if(swizzle[i] == UTIL_FORMAT_SWIZZLE_1)
+               {
+                  switch(output_desc->channel[1].type)
+                  {
+                  case UTIL_FORMAT_TYPE_UNSIGNED:
+                     h = output_desc->channel[1].normalized ? 0xffffffff : 0;
+                     l = output_desc->channel[1].normalized ? 0xffffffff : 1;
+                     break;
+                  case UTIL_FORMAT_TYPE_SIGNED:
+                     h = output_desc->channel[1].normalized ? 0x7fffffff : 0;
+                     l = output_desc->channel[1].normalized ? 0xffffffff : 1;
+                     break;
+                  case UTIL_FORMAT_TYPE_FLOAT:
+                     h = 0x3ff00000;
+                     l = 0;
+                     break;
+                  default:
+                     return FALSE;
+                  }
+               }
+               x86_mov_imm(p->func, x86_make_disp(dst, i * 8), l);
+               x86_mov_imm(p->func, x86_make_disp(dst, i * 8 + 4), h);
+            }
+            else
+            {
+               if(x86_target_caps(p->func) & X86_SSE)
+               {
+                  struct x86_reg tmpXMM = x86_make_reg(file_XMM, 0);
+                  emit_load64(p, tmp, tmpXMM, x86_make_disp(src, swizzle[i] * 8));
+                  emit_store64(p, x86_make_disp(dst, i * 8), tmp, tmpXMM);
+               }
+               else
+               {
+                  x86_mov(p->func, tmp, x86_make_disp(src, swizzle[i] * 8));
+                  x86_mov(p->func, x86_make_disp(dst, i * 8), tmp);
+                  x86_mov(p->func, tmp, x86_make_disp(src, swizzle[i] * 8 + 4));
+                  x86_mov(p->func, x86_make_disp(dst, i * 8 + 4), tmp);
+               }
+            }
+            break;
+         default:
+            return FALSE;
+         }
+      }
+      return TRUE;
+   }
+   /* special case for draw's EMIT_4UB (RGBA) and EMIT_4UB_BGRA */
+   else if((x86_target_caps(p->func) & X86_SSE2) &&
+         a->input_format == PIPE_FORMAT_R32G32B32A32_FLOAT && (0
+               || a->output_format == PIPE_FORMAT_B8G8R8A8_UNORM
+               || a->output_format == PIPE_FORMAT_R8G8B8A8_UNORM
+         ))
+   {
+      struct x86_reg dataXMM = x86_make_reg(file_XMM, 0);
 
+      /* load */
+      sse_movups(p->func, dataXMM, src);
 
-static boolean translate_attr( struct translate_sse *p,
-                              const struct translate_element *a,
-                              struct x86_reg srcECX,
-                              struct x86_reg dstEAX)
-{
-   struct x86_reg dataXMM = x86_make_reg(file_XMM, 0);
+      if (a->output_format == PIPE_FORMAT_B8G8R8A8_UNORM)
+         sse_shufps(p->func, dataXMM, dataXMM, SHUF(2,1,0,3));
 
-   switch (a->input_format) {
-   case PIPE_FORMAT_R32_FLOAT:
-      emit_load_R32(p, dataXMM, srcECX);
-      break;
-   case PIPE_FORMAT_R32G32_FLOAT:
-      emit_load_R32G32(p, dataXMM, srcECX);
-      break;
-   case PIPE_FORMAT_R32G32B32_FLOAT:
-      emit_load_R32G32B32(p, dataXMM, srcECX);
-      break;
-   case PIPE_FORMAT_R32G32B32A32_FLOAT:
-      emit_load_R32G32B32A32(p, dataXMM, srcECX);
-      break;
-   case PIPE_FORMAT_B8G8R8A8_UNORM:
-      emit_load_R8G8B8A8_UNORM(p, dataXMM, srcECX);
-      emit_swizzle(p, dataXMM, dataXMM, SHUF(Z,Y,X,W));
-      break;
-   case PIPE_FORMAT_R8G8B8A8_UNORM:
-      emit_load_R8G8B8A8_UNORM(p, dataXMM, srcECX);
-      break;
-   default:
-      return FALSE;
-   }
+      /* scale by 255.0 */
+      sse_mulps(p->func, dataXMM, get_const(p, CONST_255));
 
-   switch (a->output_format) {
-   case PIPE_FORMAT_R32_FLOAT:
-      emit_store_R32(p, dstEAX, dataXMM);
-      break;
-   case PIPE_FORMAT_R32G32_FLOAT:
-      emit_store_R32G32(p, dstEAX, dataXMM);
-      break;
-   case PIPE_FORMAT_R32G32B32_FLOAT:
-      emit_store_R32G32B32(p, dstEAX, dataXMM);
-      break;
-   case PIPE_FORMAT_R32G32B32A32_FLOAT:
-      emit_store_R32G32B32A32(p, dstEAX, dataXMM);
-      break;
-   case PIPE_FORMAT_B8G8R8A8_UNORM:
-      emit_swizzle(p, dataXMM, dataXMM, SHUF(Z,Y,X,W));
-      emit_store_R8G8B8A8_UNORM(p, dstEAX, dataXMM);
-      break;
-   case PIPE_FORMAT_R8G8B8A8_UNORM:
-      emit_store_R8G8B8A8_UNORM(p, dstEAX, dataXMM);
-      break;
-   default:
-      return FALSE;
+      /* pack and emit */
+      sse2_cvtps2dq(p->func, dataXMM, dataXMM);
+      sse2_packssdw(p->func, dataXMM, dataXMM);
+      sse2_packuswb(p->func, dataXMM, dataXMM);
+      sse2_movd(p->func, dst, dataXMM);
+
+      return TRUE;
    }
 
-   return TRUE;
+   return FALSE;
 }
 
+static boolean translate_attr( struct translate_sse *p,
+                              const struct translate_element *a,
+                              struct x86_reg src,
+                              struct x86_reg dst)
+{
+   if(a->input_format == a->output_format)
+   {
+      emit_memcpy(p, dst, src, util_format_get_stride(a->input_format, 1));
+      return TRUE;
+   }
+
+   return translate_attr_convert(p, a, src, dst);
+}
 
 static boolean init_inputs( struct translate_sse *p,
-                            boolean linear )
+                            unsigned index_size )
 {
    unsigned i;
-   struct x86_reg instance_id = x86_make_disp(p->machine_EDX,
+   struct x86_reg instance_id = x86_make_disp(p->machine_EDI,
                                               get_offset(p, &p->instance_id));
 
    for (i = 0; i < p->nr_buffer_varients; i++) {
       struct translate_buffer_varient *varient = &p->buffer_varient[i];
       struct translate_buffer *buffer = &p->buffer[varient->buffer_index];
 
-      if (linear || varient->instance_divisor) {
-         struct x86_reg buf_stride   = x86_make_disp(p->machine_EDX,
+      if (!index_size || varient->instance_divisor) {
+         struct x86_reg buf_stride   = x86_make_disp(p->machine_EDI,
                                                      get_offset(p, &buffer->stride));
-         struct x86_reg buf_ptr      = x86_make_disp(p->machine_EDX,
+         struct x86_reg buf_ptr      = x86_make_disp(p->machine_EDI,
                                                      get_offset(p, &varient->ptr));
-         struct x86_reg buf_base_ptr = x86_make_disp(p->machine_EDX,
+         struct x86_reg buf_base_ptr = x86_make_disp(p->machine_EDI,
                                                      get_offset(p, &buffer->base_ptr));
-         struct x86_reg elt = p->idx_EBX;
+         struct x86_reg elt = p->idx_ESI;
          struct x86_reg tmp_EAX = p->tmp_EAX;
 
          /* Calculate pointer to first attrib:
@@ -406,20 +1085,16 @@ static boolean init_inputs( struct translate_sse *p,
             x86_mov(p->func, tmp_EAX, instance_id);
 
             if (varient->instance_divisor != 1) {
-               struct x86_reg tmp_EDX = p->machine_EDX;
-               struct x86_reg tmp_ECX = p->outbuf_ECX;
+               struct x86_reg tmp_EDX = p->tmp2_EDX;
+               struct x86_reg tmp_ECX = p->src_ECX;
 
                /* TODO: Add x86_shr() to rtasm and use it whenever
                 *       instance divisor is power of two.
                 */
 
-               x86_push(p->func, tmp_EDX);
-               x86_push(p->func, tmp_ECX);
                x86_xor(p->func, tmp_EDX, tmp_EDX);
                x86_mov_reg_imm(p->func, tmp_ECX, varient->instance_divisor);
                x86_div(p->func, tmp_ECX);    /* EAX = EDX:EAX / ECX */
-               x86_pop(p->func, tmp_ECX);
-               x86_pop(p->func, tmp_EDX);
             }
          } else {
             x86_mov(p->func, tmp_EAX, elt);
@@ -430,16 +1105,23 @@ static boolean init_inputs( struct translate_sse *p,
           */
 
          x86_imul(p->func, tmp_EAX, buf_stride);
+         x64_rexw(p->func);
          x86_add(p->func, tmp_EAX, buf_base_ptr);
 
 
          /* In the linear case, keep the buffer pointer instead of the
           * index number.
           */
-         if (linear && p->nr_buffer_varients == 1)
+         if (!index_size && p->nr_buffer_varients == 1)
+         {
+            x64_rexw(p->func);
             x86_mov(p->func, elt, tmp_EAX);
+         }
          else
+         {
+            x64_rexw(p->func);
             x86_mov(p->func, buf_ptr, tmp_EAX);
+         }
       }
    }
 
@@ -448,44 +1130,57 @@ static boolean init_inputs( struct translate_sse *p,
 
 
 static struct x86_reg get_buffer_ptr( struct translate_sse *p,
-                                      boolean linear,
+                                      unsigned index_size,
                                       unsigned var_idx,
                                       struct x86_reg elt )
 {
    if (var_idx == ELEMENT_BUFFER_INSTANCE_ID) {
-      return x86_make_disp(p->machine_EDX,
+      return x86_make_disp(p->machine_EDI,
                            get_offset(p, &p->instance_id));
    }
-   if (linear && p->nr_buffer_varients == 1) {
-      return p->idx_EBX;
+   if (!index_size && p->nr_buffer_varients == 1) {
+      return p->idx_ESI;
    }
-   else if (linear || p->buffer_varient[var_idx].instance_divisor) {
-      struct x86_reg ptr = p->tmp_EAX;
+   else if (!index_size || p->buffer_varient[var_idx].instance_divisor) {
+      struct x86_reg ptr = p->src_ECX;
       struct x86_reg buf_ptr = 
-         x86_make_disp(p->machine_EDX, 
+         x86_make_disp(p->machine_EDI,
                        get_offset(p, &p->buffer_varient[var_idx].ptr));
       
+      x64_rexw(p->func);
       x86_mov(p->func, ptr, buf_ptr);
       return ptr;
    }
    else {
-      struct x86_reg ptr = p->tmp_EAX;
+      struct x86_reg ptr = p->src_ECX;
       const struct translate_buffer_varient *varient = &p->buffer_varient[var_idx];
 
       struct x86_reg buf_stride = 
-         x86_make_disp(p->machine_EDX, 
+         x86_make_disp(p->machine_EDI,
                        get_offset(p, &p->buffer[varient->buffer_index].stride));
 
       struct x86_reg buf_base_ptr = 
-         x86_make_disp(p->machine_EDX, 
+         x86_make_disp(p->machine_EDI,
                        get_offset(p, &p->buffer[varient->buffer_index].base_ptr));
 
 
 
       /* Calculate pointer to current attrib:
        */
-      x86_mov(p->func, ptr, buf_stride);
-      x86_imul(p->func, ptr, elt);
+      switch(index_size)
+      {
+      case 1:
+         x86_movzx8(p->func, ptr, elt);
+         break;
+      case 2:
+         x86_movzx16(p->func, ptr, elt);
+         break;
+      case 4:
+         x86_mov(p->func, ptr, elt);
+         break;
+      }
+      x86_imul(p->func, ptr, buf_stride);
+      x64_rexw(p->func);
       x86_add(p->func, ptr, buf_base_ptr);
       return ptr;
    }
@@ -494,39 +1189,43 @@ static struct x86_reg get_buffer_ptr( struct translate_sse *p,
 
 
 static boolean incr_inputs( struct translate_sse *p, 
-                            boolean linear )
+                            unsigned index_size )
 {
-   if (linear && p->nr_buffer_varients == 1) {
-      struct x86_reg stride = x86_make_disp(p->machine_EDX,
+   if (!index_size && p->nr_buffer_varients == 1) {
+      struct x86_reg stride = x86_make_disp(p->machine_EDI,
                                             get_offset(p, &p->buffer[0].stride));
 
       if (p->buffer_varient[0].instance_divisor == 0) {
-         x86_add(p->func, p->idx_EBX, stride);
-         sse_prefetchnta(p->func, x86_make_disp(p->idx_EBX, 192));
+         x64_rexw(p->func);
+         x86_add(p->func, p->idx_ESI, stride);
+         sse_prefetchnta(p->func, x86_make_disp(p->idx_ESI, 192));
       }
    }
-   else if (linear) {
+   else if (!index_size) {
       unsigned i;
 
       /* Is this worthwhile??
        */
       for (i = 0; i < p->nr_buffer_varients; i++) {
          struct translate_buffer_varient *varient = &p->buffer_varient[i];
-         struct x86_reg buf_ptr = x86_make_disp(p->machine_EDX,
+         struct x86_reg buf_ptr = x86_make_disp(p->machine_EDI,
                                                 get_offset(p, &varient->ptr));
-         struct x86_reg buf_stride = x86_make_disp(p->machine_EDX,
+         struct x86_reg buf_stride = x86_make_disp(p->machine_EDI,
                                                    get_offset(p, &p->buffer[varient->buffer_index].stride));
 
          if (varient->instance_divisor == 0) {
-            x86_mov(p->func, p->tmp_EAX, buf_ptr);
-            x86_add(p->func, p->tmp_EAX, buf_stride);
+            x86_mov(p->func, p->tmp_EAX, buf_stride);
+            x64_rexw(p->func);
+            x86_add(p->func, p->tmp_EAX, buf_ptr);
             if (i == 0) sse_prefetchnta(p->func, x86_make_disp(p->tmp_EAX, 192));
+            x64_rexw(p->func);
             x86_mov(p->func, buf_ptr, p->tmp_EAX);
          }
       }
    } 
    else {
-      x86_lea(p->func, p->idx_EBX, x86_make_disp(p->idx_EBX, 4));
+      x64_rexw(p->func);
+      x86_lea(p->func, p->idx_ESI, x86_make_disp(p->idx_ESI, index_size));
    }
    
    return TRUE;
@@ -551,35 +1250,52 @@ static boolean incr_inputs( struct translate_sse *p,
  */
 static boolean build_vertex_emit( struct translate_sse *p,
                                  struct x86_function *func,
-                                 boolean linear )
+                                 unsigned index_size )
 {
    int fixup, label;
    unsigned j;
 
+   memset(p->reg_to_const, 0xff, sizeof(p->reg_to_const));
+   memset(p->const_to_reg, 0xff, sizeof(p->const_to_reg));
+
    p->tmp_EAX       = x86_make_reg(file_REG32, reg_AX);
-   p->idx_EBX       = x86_make_reg(file_REG32, reg_BX);
-   p->outbuf_ECX    = x86_make_reg(file_REG32, reg_CX);
-   p->machine_EDX   = x86_make_reg(file_REG32, reg_DX);
-   p->count_ESI     = x86_make_reg(file_REG32, reg_SI);
+   p->idx_ESI       = x86_make_reg(file_REG32, reg_SI);
+   p->outbuf_EBX    = x86_make_reg(file_REG32, reg_BX);
+   p->machine_EDI   = x86_make_reg(file_REG32, reg_DI);
+   p->count_EBP     = x86_make_reg(file_REG32, reg_BP);
+   p->tmp2_EDX     = x86_make_reg(file_REG32, reg_DX);
+   p->src_ECX     = x86_make_reg(file_REG32, reg_CX);
 
    p->func = func;
-   p->loaded_inv_255 = FALSE;
-   p->loaded_255 = FALSE;
-   p->loaded_identity = FALSE;
 
    x86_init_func(p->func);
 
-   /* Push a few regs?
-    */
-   x86_push(p->func, p->idx_EBX);
-   x86_push(p->func, p->count_ESI);
+   if(x86_target(p->func) == X86_64_WIN64_ABI)
+   {
+          /* the ABI guarantees a 16-byte aligned 32-byte "shadow space" above the return address */
+          sse2_movdqa(p->func, x86_make_disp(x86_make_reg(file_REG32, reg_SP), 8), x86_make_reg(file_XMM, 6));
+          sse2_movdqa(p->func, x86_make_disp(x86_make_reg(file_REG32, reg_SP), 24), x86_make_reg(file_XMM, 7));
+   }
 
-   /* Load arguments into regs:
-    */
-   x86_mov(p->func, p->machine_EDX, x86_fn_arg(p->func, 1));
-   x86_mov(p->func, p->idx_EBX, x86_fn_arg(p->func, 2));
-   x86_mov(p->func, p->count_ESI, x86_fn_arg(p->func, 3));
-   x86_mov(p->func, p->outbuf_ECX, x86_fn_arg(p->func, 5));
+   x86_push(p->func, p->outbuf_EBX);
+   x86_push(p->func, p->count_EBP);
+
+/* on non-Win64 x86-64, these are already in the right registers */
+   if(x86_target(p->func) != X86_64_STD_ABI)
+   {
+      x86_push(p->func, p->machine_EDI);
+      x86_push(p->func, p->idx_ESI);
+
+      x86_mov(p->func, p->machine_EDI, x86_fn_arg(p->func, 1));
+      x86_mov(p->func, p->idx_ESI, x86_fn_arg(p->func, 2));
+   }
+
+   x86_mov(p->func, p->count_EBP, x86_fn_arg(p->func, 3));
+
+   if(x86_target(p->func) != X86_32)
+      x64_mov64(p->func, p->outbuf_EBX, x86_fn_arg(p->func, 5));
+   else
+      x86_mov(p->func, p->outbuf_EBX, x86_fn_arg(p->func, 5));
 
    /* Load instance ID.
     */
@@ -588,25 +1304,25 @@ static boolean build_vertex_emit( struct translate_sse *p,
               p->tmp_EAX,
               x86_fn_arg(p->func, 4));
       x86_mov(p->func,
-              x86_make_disp(p->machine_EDX, get_offset(p, &p->instance_id)),
+              x86_make_disp(p->machine_EDI, get_offset(p, &p->instance_id)),
               p->tmp_EAX);
    }
 
    /* Get vertex count, compare to zero
     */
    x86_xor(p->func, p->tmp_EAX, p->tmp_EAX);
-   x86_cmp(p->func, p->count_ESI, p->tmp_EAX);
+   x86_cmp(p->func, p->count_EBP, p->tmp_EAX);
    fixup = x86_jcc_forward(p->func, cc_E);
 
    /* always load, needed or not:
     */
-   init_inputs(p, linear);
+   init_inputs(p, index_size);
 
    /* Note address for loop jump
     */
    label = x86_get_label(p->func);
    {
-      struct x86_reg elt = linear ? p->idx_EBX : x86_deref(p->idx_EBX);
+      struct x86_reg elt = !index_size ? p->idx_ESI : x86_deref(p->idx_ESI);
       int last_varient = -1;
       struct x86_reg vb;
 
@@ -618,30 +1334,31 @@ static boolean build_vertex_emit( struct translate_sse *p,
           */
          if (varient != last_varient) {
             last_varient = varient;
-            vb = get_buffer_ptr(p, linear, varient, elt);
+            vb = get_buffer_ptr(p, index_size, varient, elt);
          }
          
          if (!translate_attr( p, a, 
                               x86_make_disp(vb, a->input_offset), 
-                              x86_make_disp(p->outbuf_ECX, a->output_offset)))
+                              x86_make_disp(p->outbuf_EBX, a->output_offset)))
             return FALSE;
       }
 
       /* Next output vertex:
        */
+      x64_rexw(p->func);
       x86_lea(p->func, 
-              p->outbuf_ECX, 
-              x86_make_disp(p->outbuf_ECX, 
+              p->outbuf_EBX,
+              x86_make_disp(p->outbuf_EBX,
                             p->translate.key.output_stride));
 
       /* Incr index
        */ 
-      incr_inputs( p, linear );
+      incr_inputs( p, index_size );
    }
 
    /* decr count, loop if not zero
     */
-   x86_dec(p->func, p->count_ESI);
+   x86_dec(p->func, p->count_EBP);
    x86_jcc(p->func, cc_NZ, label);
 
    /* Exit mmx state?
@@ -656,8 +1373,20 @@ static boolean build_vertex_emit( struct translate_sse *p,
    /* Pop regs and return
     */
    
-   x86_pop(p->func, p->count_ESI);
-   x86_pop(p->func, p->idx_EBX);
+   if(x86_target(p->func) != X86_64_STD_ABI)
+   {
+      x86_pop(p->func, p->idx_ESI);
+      x86_pop(p->func, p->machine_EDI);
+   }
+
+   x86_pop(p->func, p->count_EBP);
+   x86_pop(p->func, p->outbuf_EBX);
+
+   if(x86_target(p->func) == X86_64_WIN64_ABI)
+   {
+          sse2_movdqa(p->func, x86_make_reg(file_XMM, 6), x86_make_disp(x86_make_reg(file_REG32, reg_SP), 8));
+          sse2_movdqa(p->func, x86_make_reg(file_XMM, 7), x86_make_disp(x86_make_reg(file_REG32, reg_SP), 24));
+   }
    x86_ret(p->func);
 
    return TRUE;
@@ -697,37 +1426,7 @@ static void translate_sse_release( struct translate *translate )
    x86_release_func( &p->linear_func );
    x86_release_func( &p->elt_func );
 
-   FREE(p);
-}
-
-static void PIPE_CDECL translate_sse_run_elts( struct translate *translate,
-                             const unsigned *elts,
-                             unsigned count,
-                              unsigned instance_id,
-                             void *output_buffer )
-{
-   struct translate_sse *p = (struct translate_sse *)translate;
-
-   p->gen_run_elts( translate,
-                   elts,
-                   count,
-                    instance_id,
-                    output_buffer);
-}
-
-static void PIPE_CDECL translate_sse_run( struct translate *translate,
-                        unsigned start,
-                        unsigned count,
-                         unsigned instance_id,
-                        void *output_buffer )
-{
-   struct translate_sse *p = (struct translate_sse *)translate;
-
-   p->gen_run( translate,
-              start,
-              count,
-               instance_id,
-               output_buffer);
+   os_free_aligned(p);
 }
 
 
@@ -736,18 +1435,19 @@ struct translate *translate_sse2_create( const struct translate_key *key )
    struct translate_sse *p = NULL;
    unsigned i;
 
-   if (!rtasm_cpu_has_sse() || !rtasm_cpu_has_sse2())
+   /* this is misnamed, it actually refers to whether rtasm is enabled or not */
+   if (!rtasm_cpu_has_sse())
       goto fail;
 
-   p = CALLOC_STRUCT( translate_sse );
+   p = os_malloc_aligned(sizeof(struct translate_sse), 16);
    if (p == NULL) 
       goto fail;
+   memset(p, 0, sizeof(*p));
+   memcpy(p->consts, consts, sizeof(consts));
 
    p->translate.key = *key;
    p->translate.release = translate_sse_release;
    p->translate.set_buffer = translate_sse_set_buffer;
-   p->translate.run_elts = translate_sse_run_elts;
-   p->translate.run = translate_sse_run;
 
    for (i = 0; i < key->nr_elements; i++) {
       if (key->element[i].type == TRANSLATE_ELEMENT_NORMAL) {
@@ -783,18 +1483,32 @@ struct translate *translate_sse2_create( const struct translate_key *key )
 
    if (0) debug_printf("nr_buffers: %d\n", p->nr_buffers);
 
-   if (!build_vertex_emit(p, &p->linear_func, TRUE))
+   if (!build_vertex_emit(p, &p->linear_func, 0))
+      goto fail;
+
+   if (!build_vertex_emit(p, &p->elt_func, 4))
+      goto fail;
+
+   if (!build_vertex_emit(p, &p->elt16_func, 2))
+      goto fail;
+
+   if (!build_vertex_emit(p, &p->elt8_func, 1))
+      goto fail;
+
+   p->translate.run = (void*)x86_get_func(&p->linear_func);
+   if (p->translate.run == NULL)
       goto fail;
 
-   if (!build_vertex_emit(p, &p->elt_func, FALSE))
+   p->translate.run_elts = (void*)x86_get_func(&p->elt_func);
+   if (p->translate.run_elts == NULL)
       goto fail;
 
-   p->gen_run = (run_func)x86_get_func(&p->linear_func);
-   if (p->gen_run == NULL)
+   p->translate.run_elts16 = (void*)x86_get_func(&p->elt16_func);
+   if (p->translate.run_elts16 == NULL)
       goto fail;
 
-   p->gen_run_elts = (run_elts_func)x86_get_func(&p->elt_func);
-   if (p->gen_run_elts == NULL)
+   p->translate.run_elts8 = (void*)x86_get_func(&p->elt8_func);
+   if (p->translate.run_elts8 == NULL)
       goto fail;
 
    return &p->translate;
index 87f1110296af17aae6cd980414e8f98a13d388c2..98b85ddecd510be014f7ad080276870d41e80756 100644 (file)
@@ -36,6 +36,9 @@
 #define U_HANDLE_BITMASK_H_
 
 
+#include "pipe/p_compiler.h"
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
index 97fa99ec65d2e52ba3d49193ee20ada3cb297449..dfb142b9e1cc92b8074b99b1fc36a5ff18c29ca6 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "util/u_blit.h"
 #include "util/u_draw_quad.h"
+#include "util/u_format.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 #include "util/u_sampler.h"
@@ -56,15 +57,18 @@ struct blit_state
    struct cso_context *cso;
 
    struct pipe_blend_state blend;
-   struct pipe_depth_stencil_alpha_state depthstencil;
+   struct pipe_depth_stencil_alpha_state depthstencil_keep;
+   struct pipe_depth_stencil_alpha_state depthstencil_write;
    struct pipe_rasterizer_state rasterizer;
    struct pipe_sampler_state sampler;
    struct pipe_viewport_state viewport;
    struct pipe_clip_state clip;
    struct pipe_vertex_element velem[2];
+   enum pipe_texture_target internal_target;
 
    void *vs;
    void *fs[TGSI_WRITEMASK_XYZW + 1];
+   void *fs_depth;
 
    struct pipe_resource *vbuf;  /**< quad vertices */
    unsigned vbuf_slot;
@@ -95,7 +99,11 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
    ctx->blend.rt[0].colormask = PIPE_MASK_RGBA;
 
    /* no-op depth/stencil/alpha */
-   memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
+   memset(&ctx->depthstencil_keep, 0, sizeof(ctx->depthstencil_keep));
+   memset(&ctx->depthstencil_write, 0, sizeof(ctx->depthstencil_write));
+   ctx->depthstencil_write.depth.enabled = 1;
+   ctx->depthstencil_write.depth.writemask = 1;
+   ctx->depthstencil_write.depth.func = PIPE_FUNC_ALWAYS;
 
    /* rasterizer */
    memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
@@ -110,7 +118,6 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
    ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
    ctx->sampler.min_img_filter = 0; /* set later */
    ctx->sampler.mag_img_filter = 0; /* set later */
-   ctx->sampler.normalized_coords = 1;
 
    /* vertex elements state */
    memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2);
@@ -145,6 +152,11 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
       ctx->vertices[i][1][3] = 1.0f; /* q */
    }
 
+   if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES))
+      ctx->internal_target = PIPE_TEXTURE_2D;
+   else
+      ctx->internal_target = PIPE_TEXTURE_RECT;
+
    return ctx;
 }
 
@@ -164,6 +176,9 @@ util_destroy_blit(struct blit_state *ctx)
       if (ctx->fs[i])
          pipe->delete_fs_state(pipe, ctx->fs[i]);
 
+   if (ctx->fs_depth)
+      pipe->delete_fs_state(pipe, ctx->fs_depth);
+
    pipe_resource_reference(&ctx->vbuf, NULL);
 
    FREE(ctx);
@@ -271,7 +286,7 @@ regions_overlap(int srcX0, int srcY0,
  * \param writemask  controls which channels in the dest surface are sourced
  *                   from the src surface.  Disabled channels are sourced
  *                   from (0,0,0,1).
- * XXX need some control over blitting Z and/or stencil.
+ * XXX need some control over blitting stencil.
  */
 void
 util_blit_pixels_writemask(struct blit_state *ctx,
@@ -294,8 +309,9 @@ util_blit_pixels_writemask(struct blit_state *ctx,
    const int srcW = abs(srcX1 - srcX0);
    const int srcH = abs(srcY1 - srcY0);
    unsigned offset;
-   boolean overlap;
+   boolean overlap, dst_is_depth;
    float s0, t0, s1, t1;
+   boolean normalized;
 
    assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
           filter == PIPE_TEX_MIPFILTER_LINEAR);
@@ -335,7 +351,6 @@ util_blit_pixels_writemask(struct blit_state *ctx,
       return;
    }
 
-
    /* Create a temporary texture when src and dest alias or when src
     * is anything other than a 2d texture.
     * XXX should just use appropriate shader to access 1d / 3d slice / cube face,
@@ -347,7 +362,8 @@ util_blit_pixels_writemask(struct blit_state *ctx,
        dst->face == srcsub.face &&
        dst->level == srcsub.level &&
        dst->zslice == srcZ0) ||
-       src_tex->target != PIPE_TEXTURE_2D)
+       (src_tex->target != PIPE_TEXTURE_2D &&
+       src_tex->target != PIPE_TEXTURE_RECT))
    {
       struct pipe_resource texTemp;
       struct pipe_resource *tex;
@@ -372,7 +388,7 @@ util_blit_pixels_writemask(struct blit_state *ctx,
 
       /* create temp texture */
       memset(&texTemp, 0, sizeof(texTemp));
-      texTemp.target = PIPE_TEXTURE_2D;
+      texTemp.target = ctx->internal_target;
       texTemp.format = src_tex->format;
       texTemp.last_level = 0;
       texTemp.width0 = srcW;
@@ -392,10 +408,19 @@ util_blit_pixels_writemask(struct blit_state *ctx,
                                  src_tex, srcsub, srcLeft, srcTop, srcZ0, /* src */
                                  srcW, srcH);     /* size */
 
-      s0 = 0.0f; 
-      s1 = 1.0f;
-      t0 = 0.0f;
-      t1 = 1.0f;
+      normalized = tex->target != PIPE_TEXTURE_RECT;
+      if(normalized) {
+         s0 = 0.0f;
+         s1 = 1.0f;
+         t0 = 0.0f;
+         t1 = 1.0f;
+      }
+      else {
+         s0 = 0;
+         s1 = srcW;
+         t0 = 0;
+         t1 = srcH;
+      }
 
       u_sampler_view_default_template(&sv_templ, tex, tex->format);
       sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ);
@@ -415,20 +440,29 @@ util_blit_pixels_writemask(struct blit_state *ctx,
          return;
       }
 
-      s0 = srcX0 / (float)(u_minify(sampler_view->texture->width0, srcsub.level));
-      s1 = srcX1 / (float)(u_minify(sampler_view->texture->width0, srcsub.level));
-      t0 = srcY0 / (float)(u_minify(sampler_view->texture->height0, srcsub.level));
-      t1 = srcY1 / (float)(u_minify(sampler_view->texture->height0, srcsub.level));
+      s0 = srcX0;
+      s1 = srcX1;
+      t0 = srcY0;
+      t1 = srcY1;
+      normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT;
+      if(normalized)
+      {
+         s0 /= (float)(u_minify(sampler_view->texture->width0, srcsub.level));
+         s1 /= (float)(u_minify(sampler_view->texture->width0, srcsub.level));
+         t0 /= (float)(u_minify(sampler_view->texture->height0, srcsub.level));
+         t1 /= (float)(u_minify(sampler_view->texture->height0, srcsub.level));
+      }
    }
 
+   dst_is_depth = util_format_is_depth_or_stencil(dst->format);
 
-   assert(screen->is_format_supported(screen, sampler_view->format, PIPE_TEXTURE_2D,
+   assert(screen->is_format_supported(screen, sampler_view->format, ctx->internal_target,
                                       sampler_view->texture->nr_samples,
                                       PIPE_BIND_SAMPLER_VIEW, 0));
-   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
+   assert(screen->is_format_supported(screen, dst->format, ctx->internal_target,
                                       dst->texture->nr_samples,
-                                      PIPE_BIND_RENDER_TARGET, 0));
-
+                                      dst_is_depth ? PIPE_BIND_DEPTH_STENCIL :
+                                                     PIPE_BIND_RENDER_TARGET, 0));
    /* save state (restored below) */
    cso_save_blend(ctx->cso);
    cso_save_depth_stencil_alpha(ctx->cso);
@@ -444,12 +478,15 @@ util_blit_pixels_writemask(struct blit_state *ctx,
 
    /* set misc state we care about */
    cso_set_blend(ctx->cso, &ctx->blend);
-   cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
+   cso_set_depth_stencil_alpha(ctx->cso,
+                               dst_is_depth ? &ctx->depthstencil_write :
+                                              &ctx->depthstencil_keep);
    cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
    cso_set_clip(ctx->cso, &ctx->clip);
    cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
 
    /* sampler */
+   ctx->sampler.normalized_coords = normalized;
    ctx->sampler.min_img_filter = filter;
    ctx->sampler.mag_img_filter = filter;
    /* we've limited this already with the sampler view but you never know... */
@@ -472,22 +509,35 @@ util_blit_pixels_writemask(struct blit_state *ctx,
    /* texture */
    cso_set_fragment_sampler_views(ctx->cso, 1, &sampler_view);
 
-   if (ctx->fs[writemask] == NULL)
-      ctx->fs[writemask] =
-         util_make_fragment_tex_shader_writemask(pipe, TGSI_TEXTURE_2D,
-                                                 TGSI_INTERPOLATE_LINEAR,
-                                                 writemask);
-
    /* shaders */
-   cso_set_fragment_shader_handle(ctx->cso, ctx->fs[writemask]);
+   if (dst_is_depth) {
+      if (ctx->fs_depth == NULL)
+         ctx->fs_depth =
+            util_make_fragment_tex_shader_writedepth(pipe, TGSI_TEXTURE_2D,
+                                                     TGSI_INTERPOLATE_LINEAR);
+
+      cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth);
+   } else {
+      if (ctx->fs[writemask] == NULL)
+         ctx->fs[writemask] =
+            util_make_fragment_tex_shader_writemask(pipe, TGSI_TEXTURE_2D,
+                                                    TGSI_INTERPOLATE_LINEAR,
+                                                    writemask);
+
+      cso_set_fragment_shader_handle(ctx->cso, ctx->fs[writemask]);
+   }
    cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
 
    /* drawing dest */
    memset(&fb, 0, sizeof(fb));
    fb.width = dst->width;
    fb.height = dst->height;
-   fb.nr_cbufs = 1;
-   fb.cbufs[0] = dst;
+   if (dst_is_depth) {
+      fb.zsbuf = dst;
+   } else {
+      fb.nr_cbufs = 1;
+      fb.cbufs[0] = dst;
+   }
    cso_set_framebuffer(ctx->cso, &fb);
 
    /* draw quad */
@@ -574,6 +624,7 @@ util_blit_pixels_tex(struct blit_state *ctx,
                      int dstX1, int dstY1,
                      float z, uint filter)
 {
+   boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT;
    struct pipe_framebuffer_state fb;
    float s0, t0, s1, t1;
    unsigned offset;
@@ -586,10 +637,18 @@ util_blit_pixels_tex(struct blit_state *ctx,
    assert(tex->width0 != 0);
    assert(tex->height0 != 0);
 
-   s0 = srcX0 / (float)tex->width0;
-   s1 = srcX1 / (float)tex->width0;
-   t0 = srcY0 / (float)tex->height0;
-   t1 = srcY1 / (float)tex->height0;
+   s0 = srcX0;
+   s1 = srcX1;
+   t0 = srcY0;
+   t1 = srcY1;
+
+   if(normalized)
+   {
+      s0 /= (float)tex->width0;
+      s1 /= (float)tex->width0;
+      t0 /= (float)tex->height0;
+      t1 /= (float)tex->height0;
+   }
 
    assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
                                                  PIPE_TEXTURE_2D,
@@ -611,12 +670,13 @@ util_blit_pixels_tex(struct blit_state *ctx,
 
    /* set misc state we care about */
    cso_set_blend(ctx->cso, &ctx->blend);
-   cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
+   cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil_keep);
    cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
    cso_set_clip(ctx->cso, &ctx->clip);
    cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
 
    /* sampler */
+   ctx->sampler.normalized_coords = normalized;
    ctx->sampler.min_img_filter = filter;
    ctx->sampler.mag_img_filter = filter;
    cso_single_sampler(ctx->cso, 0, &ctx->sampler);
index ef95134f3248ad570bfed407cb75360175af78ae..b8a0dfce13f443b5c4634f9d256897cf86053698 100644 (file)
 #define U_BLIT_H
 
 
+#include "pipe/p_compiler.h"
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
    
+struct cso_context;
 struct pipe_context;
-struct pipe_surface;
 struct pipe_resource;
-struct cso_context;
-
-
-struct blit_state;
+struct pipe_sampler_view;
+struct pipe_subresource;
+struct pipe_surface;
 
 
 extern struct blit_state *
index b5b86b7214258788a066d1b2ac295c630e8a181b..f93ef26ae73c182a7f2918b358be26906a377dfa 100644 (file)
@@ -92,7 +92,7 @@ struct blitter_context_priv
    void *velem_state;
 
    /* Sampler state for clamping to a miplevel. */
-   void *sampler_state[PIPE_MAX_TEXTURE_LEVELS];
+   void *sampler_state[PIPE_MAX_TEXTURE_LEVELS * 2];
 
    /* Rasterizer state. */
    void *rs_state;
@@ -254,6 +254,7 @@ void util_blitter_destroy(struct blitter_context *blitter)
                                           ctx->dsa_write_depth_keep_stencil);
    pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
    pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
+   pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_flush_depth_stencil);
 
    pipe->delete_rasterizer_state(pipe, ctx->rs_state);
    pipe->delete_vs_state(pipe, ctx->vs_col);
@@ -271,7 +272,7 @@ void util_blitter_destroy(struct blitter_context *blitter)
       if (ctx->fs_col[i])
          pipe->delete_fs_state(pipe, ctx->fs_col[i]);
 
-   for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++)
+   for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS * 2; i++)
       if (ctx->sampler_state[i])
          pipe->delete_sampler_state(pipe, ctx->sampler_state[i]);
 
@@ -319,7 +320,7 @@ static void blitter_restore_CSOs(struct blitter_context_priv *ctx)
     */
    if (ctx->base.saved_fb_state.nr_cbufs != ~0) {
       pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state);
-      util_assign_framebuffer_state(&ctx->base.saved_fb_state, NULL);
+      util_unreference_framebuffer_state(&ctx->base.saved_fb_state);
       ctx->base.saved_fb_state.nr_cbufs = ~0;
    }
 
@@ -417,16 +418,26 @@ static void blitter_set_clear_color(struct blitter_context_priv *ctx,
    }
 }
 
-static void get_normalized_texcoords(struct pipe_resource *src,
+static void get_texcoords(struct pipe_resource *src,
                                      struct pipe_subresource subsrc,
                                      unsigned x1, unsigned y1,
                                      unsigned x2, unsigned y2,
-                                     float out[4])
+                                     boolean normalized, float out[4])
 {
-   out[0] = x1 / (float)u_minify(src->width0,  subsrc.level);
-   out[1] = y1 / (float)u_minify(src->height0, subsrc.level);
-   out[2] = x2 / (float)u_minify(src->width0,  subsrc.level);
-   out[3] = y2 / (float)u_minify(src->height0, subsrc.level);
+   if(normalized)
+   {
+      out[0] = x1 / (float)u_minify(src->width0,  subsrc.level);
+      out[1] = y1 / (float)u_minify(src->height0, subsrc.level);
+      out[2] = x2 / (float)u_minify(src->width0,  subsrc.level);
+      out[3] = y2 / (float)u_minify(src->height0, subsrc.level);
+   }
+   else
+   {
+      out[0] = x1;
+      out[1] = y1;
+      out[2] = x2;
+      out[3] = y2;
+   }
 }
 
 static void set_texcoords_in_vertices(const float coord[4],
@@ -454,7 +465,7 @@ static void blitter_set_texcoords_2d(struct blitter_context_priv *ctx,
    unsigned i;
    float coord[4];
 
-   get_normalized_texcoords(src, subsrc, x1, y1, x2, y2, coord);
+   get_texcoords(src, subsrc, x1, y1, x2, y2, TRUE, coord);
    set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8);
 
    for (i = 0; i < 4; i++) {
@@ -489,7 +500,7 @@ static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx,
    float coord[4];
    float st[4][2];
 
-   get_normalized_texcoords(src, subsrc, x1, y1, x2, y2, coord);
+   get_texcoords(src, subsrc, x1, y1, x2, y2, TRUE, coord);
    set_texcoords_in_vertices(coord, &st[0][0], 2);
 
    util_map_texcoords2d_onto_cubemap(subsrc.face,
@@ -523,7 +534,7 @@ static void blitter_draw_quad(struct blitter_context_priv *ctx)
 
 static INLINE
 void **blitter_get_sampler_state(struct blitter_context_priv *ctx,
-                                 int miplevel)
+                                 int miplevel, boolean normalized)
 {
    struct pipe_context *pipe = ctx->base.pipe;
    struct pipe_sampler_state *sampler_state = &ctx->template_sampler_state;
@@ -531,18 +542,19 @@ void **blitter_get_sampler_state(struct blitter_context_priv *ctx,
    assert(miplevel < PIPE_MAX_TEXTURE_LEVELS);
 
    /* Create the sampler state on-demand. */
-   if (!ctx->sampler_state[miplevel]) {
+   if (!ctx->sampler_state[miplevel * 2 + normalized]) {
       sampler_state->lod_bias = miplevel;
       sampler_state->min_lod = miplevel;
       sampler_state->max_lod = miplevel;
+      sampler_state->normalized_coords = normalized;
 
-      ctx->sampler_state[miplevel] = pipe->create_sampler_state(pipe,
+      ctx->sampler_state[miplevel * 2 + normalized] = pipe->create_sampler_state(pipe,
                                                                 sampler_state);
    }
 
    /* Return void** so that it can be passed to bind_fragment_sampler_states
     * directly. */
-   return &ctx->sampler_state[miplevel];
+   return &ctx->sampler_state[miplevel * 2 + normalized];
 }
 
 static INLINE
@@ -568,6 +580,8 @@ pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target)
       return TGSI_TEXTURE_1D;
    case PIPE_TEXTURE_2D:
       return TGSI_TEXTURE_2D;
+   case PIPE_TEXTURE_RECT:
+      return TGSI_TEXTURE_RECT;
    case PIPE_TEXTURE_3D:
       return TGSI_TEXTURE_3D;
    case PIPE_TEXTURE_CUBE:
@@ -716,6 +730,7 @@ void util_blitter_copy_region(struct blitter_context *blitter,
    struct pipe_sampler_view viewTempl, *view;
    unsigned bind;
    boolean is_stencil, is_depth;
+   boolean normalized;
 
    /* Give up if textures are not set. */
    assert(dst && src);
@@ -787,6 +802,8 @@ void util_blitter_copy_region(struct blitter_context *blitter,
       fb_state.zsbuf = 0;
    }
 
+   normalized = src->target != PIPE_TEXTURE_RECT;
+
    /* Initialize sampler view. */
    u_sampler_view_default_template(&viewTempl, src, src->format);
    view = pipe->create_sampler_view(pipe, src, &viewTempl);
@@ -795,7 +812,7 @@ void util_blitter_copy_region(struct blitter_context *blitter,
    pipe->bind_rasterizer_state(pipe, ctx->rs_state);
    pipe->bind_vs_state(pipe, ctx->vs_tex);
    pipe->bind_fragment_sampler_states(pipe, 1,
-                                      blitter_get_sampler_state(ctx, subsrc.level));
+                                      blitter_get_sampler_state(ctx, subsrc.level, normalized));
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
    pipe->set_fragment_sampler_views(pipe, 1, &view);
    pipe->set_framebuffer_state(pipe, &fb_state);
@@ -806,11 +823,12 @@ void util_blitter_copy_region(struct blitter_context *blitter,
       /* Draw the quad with the draw_rectangle callback. */
       case PIPE_TEXTURE_1D:
       case PIPE_TEXTURE_2D:
+      case PIPE_TEXTURE_RECT:
          {
             /* Set texture coordinates. */
             float coord[4];
-            get_normalized_texcoords(src, subsrc, srcx, srcy,
-                                     srcx+width, srcy+height, coord);
+            get_texcoords(src, subsrc, srcx, srcy,
+                                     srcx+width, srcy+height, normalized, coord);
 
             /* Draw. */
             blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
index f316587dea02c19f8e1d868bc38af8ef319d143d..e33d2e283f8072606fb3c61df816b6569e523ee4 100644 (file)
@@ -27,6 +27,7 @@
 #ifndef U_BLITTER_H
 #define U_BLITTER_H
 
+#include "util/u_framebuffer.h"
 #include "util/u_inlines.h"
 #include "util/u_memory.h"
 
@@ -258,45 +259,12 @@ void util_blitter_save_vertex_shader(struct blitter_context *blitter,
    blitter->saved_vs = vs;
 }
 
-/* XXX This should probably be moved elsewhere. */
-static INLINE
-void util_assign_framebuffer_state(struct pipe_framebuffer_state *dst,
-                                   const struct pipe_framebuffer_state *src)
-{
-   unsigned i;
-
-   if (src) {
-      /* Reference all surfaces. */
-      for (i = 0; i < src->nr_cbufs; i++) {
-         pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]);
-      }
-      for (; i < dst->nr_cbufs; i++) {
-         pipe_surface_reference(&dst->cbufs[i], NULL);
-      }
-
-      pipe_surface_reference(&dst->zsbuf, src->zsbuf);
-
-      dst->nr_cbufs = src->nr_cbufs;
-      dst->width = src->width;
-      dst->height = src->height;
-   } else {
-      /* Set all surfaces to NULL. */
-      for (i = 0; i < dst->nr_cbufs; i++) {
-         pipe_surface_reference(&dst->cbufs[i], NULL);
-      }
-
-      pipe_surface_reference(&dst->zsbuf, NULL);
-
-      dst->nr_cbufs = 0;
-   }
-}
-
 static INLINE
 void util_blitter_save_framebuffer(struct blitter_context *blitter,
                                    const struct pipe_framebuffer_state *state)
 {
    blitter->saved_fb_state.nr_cbufs = 0; /* It's ~0 now, meaning it's unsaved. */
-   util_assign_framebuffer_state(&blitter->saved_fb_state, state);
+   util_copy_framebuffer_state(&blitter->saved_fb_state, state);
 }
 
 static INLINE
index 5056351307295d99adac3eaaedb8d0b3209af05c..32519b148b6467fad3cb8bd8891d590d54521243 100644 (file)
@@ -73,7 +73,9 @@
 #endif
 
 
+#ifdef DEBUG
 DEBUG_GET_ONCE_BOOL_OPTION(dump_cpu, "GALLIUM_DUMP_CPU", FALSE)
+#endif
 
 
 struct util_cpu_caps util_cpu_caps;
@@ -83,61 +85,6 @@ static int has_cpuid(void);
 #endif
 
 
-#if defined(PIPE_ARCH_X86)
-
-/* The sigill handlers */
-#if defined(PIPE_OS_LINUX) /*&& defined(_POSIX_SOURCE) && defined(X86_FXSR_MAGIC)*/
-static void
-sigill_handler_sse(int signal, struct sigcontext sc)
-{
-   /* Both the "xorps %%xmm0,%%xmm0" and "divps %xmm0,%%xmm1"
-    * instructions are 3 bytes long.  We must increment the instruction
-    * pointer manually to avoid repeated execution of the offending
-    * instruction.
-    *
-    * If the SIGILL is caused by a divide-by-zero when unmasked
-    * exceptions aren't supported, the SIMD FPU status and control
-    * word will be restored at the end of the test, so we don't need
-    * to worry about doing it here.  Besides, we may not be able to...
-    */
-   sc.eip += 3;
-
-   util_cpu_caps.has_sse=0;
-}
-
-static void
-sigfpe_handler_sse(int signal, struct sigcontext sc)
-{
-   if (sc.fpstate->magic != 0xffff) {
-      /* Our signal context has the extended FPU state, so reset the
-       * divide-by-zero exception mask and clear the divide-by-zero
-       * exception bit.
-       */
-      sc.fpstate->mxcsr |= 0x00000200;
-      sc.fpstate->mxcsr &= 0xfffffffb;
-   } else {
-      /* If we ever get here, we're completely hosed.
-      */
-   }
-}
-#endif /* PIPE_OS_LINUX && _POSIX_SOURCE && X86_FXSR_MAGIC */
-
-#if defined(PIPE_OS_WINDOWS)
-static LONG CALLBACK
-win32_sig_handler_sse(EXCEPTION_POINTERS* ep)
-{
-   if(ep->ExceptionRecord->ExceptionCode==EXCEPTION_ILLEGAL_INSTRUCTION){
-      ep->ContextRecord->Eip +=3;
-      util_cpu_caps.has_sse=0;
-      return EXCEPTION_CONTINUE_EXECUTION;
-   }
-   return EXCEPTION_CONTINUE_SEARCH;
-}
-#endif /* PIPE_OS_WINDOWS */
-
-#endif /* PIPE_ARCH_X86 */
-
-
 #if defined(PIPE_ARCH_PPC) && !defined(PIPE_OS_APPLE)
 static jmp_buf  __lv_powerpc_jmpbuf;
 static volatile sig_atomic_t __lv_powerpc_canjump = 0;
@@ -194,123 +141,8 @@ check_os_altivec_support(void)
 }
 #endif /* PIPE_ARCH_PPC */
 
-/* If we're running on a processor that can do SSE, let's see if we
- * are allowed to or not.  This will catch 2.4.0 or later kernels that
- * haven't been configured for a Pentium III but are running on one,
- * and RedHat patched 2.2 kernels that have broken exception handling
- * support for user space apps that do SSE.
- */
-#if defined(PIPE_ARCH_X86) || defined (PIPE_ARCH_X86_64)
-static void
-check_os_katmai_support(void)
-{
-#if defined(PIPE_ARCH_X86)
-#if defined(PIPE_OS_FREEBSD)
-   int has_sse=0, ret;
-   int len = sizeof (has_sse);
-
-   ret = sysctlbyname("hw.instruction_sse", &has_sse, &len, NULL, 0);
-   if (ret || !has_sse)
-      util_cpu_caps.has_sse=0;
-
-#elif defined(PIPE_OS_NETBSD) || defined(PIPE_OS_OPENBSD)
-   int has_sse, has_sse2, ret, mib[2];
-   int varlen;
-
-   mib[0] = CTL_MACHDEP;
-   mib[1] = CPU_SSE;
-   varlen = sizeof (has_sse);
-
-   ret = sysctl(mib, 2, &has_sse, &varlen, NULL, 0);
-   if (ret < 0 || !has_sse) {
-      util_cpu_caps.has_sse = 0;
-   } else {
-      util_cpu_caps.has_sse = 1;
-   }
-
-   mib[1] = CPU_SSE2;
-   varlen = sizeof (has_sse2);
-   ret = sysctl(mib, 2, &has_sse2, &varlen, NULL, 0);
-   if (ret < 0 || !has_sse2) {
-      util_cpu_caps.has_sse2 = 0;
-   } else {
-      util_cpu_caps.has_sse2 = 1;
-   }
-   util_cpu_caps.has_sse = 0; /* FIXME ?!?!? */
-
-#elif defined(PIPE_OS_WINDOWS)
-   LPTOP_LEVEL_EXCEPTION_FILTER exc_fil;
-   if (util_cpu_caps.has_sse) {
-      exc_fil = SetUnhandledExceptionFilter(win32_sig_handler_sse);
-#if defined(PIPE_CC_GCC)
-      __asm __volatile ("xorps %xmm0, %xmm0");
-#elif defined(PIPE_CC_MSVC)
-      __asm {
-          xorps xmm0, xmm0        /* executing SSE instruction */
-      }
-#else
-#error Unsupported compiler
-#endif
-      SetUnhandledExceptionFilter(exc_fil);
-   }
-#elif defined(PIPE_OS_LINUX)
-   struct sigaction saved_sigill;
-   struct sigaction saved_sigfpe;
-
-   /* Save the original signal handlers.
-   */
-   sigaction(SIGILL, NULL, &saved_sigill);
-   sigaction(SIGFPE, NULL, &saved_sigfpe);
-
-   signal(SIGILL, (void (*)(int))sigill_handler_sse);
-   signal(SIGFPE, (void (*)(int))sigfpe_handler_sse);
-
-   /* Emulate test for OSFXSR in CR4.  The OS will set this bit if it
-    * supports the extended FPU save and restore required for SSE.  If
-    * we execute an SSE instruction on a PIII and get a SIGILL, the OS
-    * doesn't support Streaming SIMD Exceptions, even if the processor
-    * does.
-    */
-   if (util_cpu_caps.has_sse) {
-      __asm __volatile ("xorps %xmm1, %xmm0");
-   }
-
-   /* Emulate test for OSXMMEXCPT in CR4.  The OS will set this bit if
-    * it supports unmasked SIMD FPU exceptions.  If we unmask the
-    * exceptions, do a SIMD divide-by-zero and get a SIGILL, the OS
-    * doesn't support unmasked SIMD FPU exceptions.  If we get a SIGFPE
-    * as expected, we're okay but we need to clean up after it.
-    *
-    * Are we being too stringent in our requirement that the OS support
-    * unmasked exceptions?  Certain RedHat 2.2 kernels enable SSE by
-    * setting CR4.OSFXSR but don't support unmasked exceptions.  Win98
-    * doesn't even support them.  We at least know the user-space SSE
-    * support is good in kernels that do support unmasked exceptions,
-    * and therefore to be safe I'm going to leave this test in here.
-    */
-   if (util_cpu_caps.has_sse) {
-      /* test_os_katmai_exception_support(); */
-   }
-
-   /* Restore the original signal handlers.
-   */
-   sigaction(SIGILL, &saved_sigill, NULL);
-   sigaction(SIGFPE, &saved_sigfpe, NULL);
-
-#else
-   /* We can't use POSIX signal handling to test the availability of
-    * SSE, so we disable it by default.
-    */
-   util_cpu_caps.has_sse = 0;
-#endif /* __linux__ */
-#endif
-
-#if defined(PIPE_ARCH_X86_64)
-   util_cpu_caps.has_sse = 1;
-#endif
-}
-
 
+#if defined(PIPE_ARCH_X86) || defined (PIPE_ARCH_X86_64)
 static int has_cpuid(void)
 {
 #if defined(PIPE_ARCH_X86)
@@ -469,9 +301,6 @@ util_cpu_detect(void)
          util_cpu_caps.cacheline = regs2[2] & 0xFF;
       }
 
-      if (util_cpu_caps.has_sse)
-         check_os_katmai_support();
-
       if (!util_cpu_caps.has_sse) {
          util_cpu_caps.has_sse2 = 0;
          util_cpu_caps.has_sse3 = 0;
diff --git a/src/gallium/auxiliary/util/u_debug_describe.c b/src/gallium/auxiliary/util/u_debug_describe.c
new file mode 100644 (file)
index 0000000..1c90ff3
--- /dev/null
@@ -0,0 +1,81 @@
+/**************************************************************************
+ *
+ * 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <pipe/p_state.h>
+#include <util/u_format.h>
+#include <util/u_debug_describe.h>
+#include <util/u_string.h>
+
+void
+debug_describe_reference(char* buf, const struct pipe_reference*ptr)
+{
+   strcpy(buf, "pipe_object");
+}
+
+void
+debug_describe_resource(char* buf, const struct pipe_resource *ptr)
+{
+   switch(ptr->target)
+   {
+   case PIPE_BUFFER:
+      util_sprintf(buf, "pipe_buffer<%u>", (unsigned)util_format_get_stride(ptr->format, ptr->width0));
+      break;
+   case PIPE_TEXTURE_1D:
+      util_sprintf(buf, "pipe_texture1d<%u,%s,%u>", ptr->width0, util_format_short_name(ptr->format), ptr->last_level);
+      break;
+   case PIPE_TEXTURE_2D:
+      util_sprintf(buf, "pipe_texture2d<%u,%u,%s,%u>", ptr->width0, ptr->height0, util_format_short_name(ptr->format), ptr->last_level);
+      break;
+   case PIPE_TEXTURE_RECT:
+      util_sprintf(buf, "pipe_texture_rect<%u,%u,%s>", ptr->width0, ptr->height0, util_format_short_name(ptr->format));
+      break;
+   case PIPE_TEXTURE_CUBE:
+      util_sprintf(buf, "pipe_texture_cube<%u,%u,%s,%u>", ptr->width0, ptr->height0, util_format_short_name(ptr->format), ptr->last_level);
+      break;
+   case PIPE_TEXTURE_3D:
+      util_sprintf(buf, "pipe_texture3d<%u,%u,%u,%s,%u>", ptr->width0, ptr->height0, ptr->depth0, util_format_short_name(ptr->format), ptr->last_level);
+      break;
+   default:
+      util_sprintf(buf, "pipe_martian_resource<%u>", ptr->target);
+      break;
+   }
+}
+
+void
+debug_describe_surface(char* buf, const struct pipe_surface *ptr)
+{
+   char res[128];
+   debug_describe_resource(res, ptr->texture);
+   util_sprintf(buf, "pipe_surface<%s,%u,%u,%u>", res, ptr->face, ptr->level, ptr->zslice);
+}
+
+void
+debug_describe_sampler_view(char* buf, const struct pipe_sampler_view *ptr)
+{
+   char res[128];
+   debug_describe_resource(res, ptr->texture);
+   util_sprintf(buf, "pipe_sampler_view<%s,%s>", res, util_format_short_name(ptr->format));
+}
diff --git a/src/gallium/auxiliary/util/u_debug_describe.h b/src/gallium/auxiliary/util/u_debug_describe.h
new file mode 100644 (file)
index 0000000..26d1f80
--- /dev/null
@@ -0,0 +1,49 @@
+/**************************************************************************
+ *
+ * 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 COPYRIGHT OWNER(S) 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_DEBUG_DESCRIBE_H_
+#define U_DEBUG_DESCRIBE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct pipe_reference;
+struct pipe_resource;
+struct pipe_surface;
+struct pipe_sampler_view;
+
+/* a 256-byte buffer is necessary and sufficient */
+void debug_describe_reference(char* buf, const struct pipe_reference*ptr);
+void debug_describe_resource(char* buf, const struct pipe_resource *ptr);
+void debug_describe_surface(char* buf, const struct pipe_surface *ptr);
+void debug_describe_sampler_view(char* buf, const struct pipe_sampler_view *ptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_DEBUG_DESCRIBE_H_ */
diff --git a/src/gallium/auxiliary/util/u_debug_refcnt.c b/src/gallium/auxiliary/util/u_debug_refcnt.c
new file mode 100644 (file)
index 0000000..40a26c9
--- /dev/null
@@ -0,0 +1,181 @@
+/**************************************************************************
+ *
+ * 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 COPYRIGHT OWNER(S) 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.
+ *
+ **************************************************************************/
+
+#if defined(DEBUG) && (!defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_WINDOWS_USER))
+
+/* see http://www.mozilla.org/performance/refcnt-balancer.html for what do with the output
+ * on Linux, use tools/addr2line.sh to postprocess it before anything else
+ **/
+#include <util/u_debug.h>
+#include <util/u_debug_refcnt.h>
+#include <util/u_debug_stack.h>
+#include <util/u_debug_symbol.h>
+#include <util/u_string.h>
+#include <util/u_hash_table.h>
+#include <os/os_thread.h>
+#include <os/os_stream.h>
+
+int debug_refcnt_state;
+
+struct os_stream* stream;
+
+/* TODO: maybe move this serial machinery to a stand-alone module and expose it? */
+static pipe_mutex serials_mutex;
+static struct util_hash_table* serials_hash;
+static unsigned serials_last;
+
+static unsigned hash_ptr(void* p)
+{
+   return (unsigned)(uintptr_t)p;
+}
+
+static int compare_ptr(void* a, void* b)
+{
+   if(a == b)
+      return 0;
+   else if(a < b)
+      return -1;
+   else
+      return 1;
+}
+
+static boolean debug_serial(void* p, unsigned* pserial)
+{
+   unsigned serial;
+   boolean found = TRUE;
+   pipe_mutex_lock(serials_mutex);
+   if(!serials_hash)
+      serials_hash = util_hash_table_create(hash_ptr, compare_ptr);
+   serial = (unsigned)(uintptr_t)util_hash_table_get(serials_hash, p);
+   if(!serial)
+   {
+      /* time to stop logging... (you'll have a 100 GB logfile at least at this point)
+       * TODO: avoid this
+       */
+      serial = ++serials_last;
+      if(!serial)
+      {
+         debug_error("More than 2^32 objects detected, aborting.\n");
+         os_abort();
+      }
+
+      util_hash_table_set(serials_hash, p, (void*)(uintptr_t)serial);
+      found = FALSE;
+   }
+   pipe_mutex_unlock(serials_mutex);
+   *pserial = serial;
+   return found;
+}
+
+static void debug_serial_delete(void* p)
+{
+   pipe_mutex_lock(serials_mutex);
+   util_hash_table_remove(serials_hash, p);
+   pipe_mutex_unlock(serials_mutex);
+}
+
+#define STACK_LEN 64
+
+static void dump_stack(const char* symbols[STACK_LEN])
+{
+   unsigned i;
+   for(i = 0; i < STACK_LEN; ++i)
+   {
+      if(symbols[i])
+         os_stream_printf(stream, "%s\n", symbols[i]);
+   }
+   os_stream_write(stream, "\n", 1);
+}
+
+void debug_reference_slowpath(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change)
+{
+   if(debug_refcnt_state < 0)
+      return;
+
+   if(!debug_refcnt_state)
+   {
+      const char* filename = debug_get_option("GALLIUM_REFCNT_LOG", NULL);
+      if(filename && filename[0])
+         stream = os_file_stream_create(filename);
+
+      if(stream)
+         debug_refcnt_state = 1;
+      else
+         debug_refcnt_state = -1;
+   }
+
+   if(debug_refcnt_state > 0)
+   {
+      struct debug_stack_frame frames[STACK_LEN];
+      const char* symbols[STACK_LEN];
+      char buf[1024];
+
+      unsigned i;
+      unsigned refcnt = p->count;
+      unsigned serial;
+      boolean existing = debug_serial((void*)p, &serial);
+
+      debug_backtrace_capture(frames, 1, STACK_LEN);
+      for(i = 0; i < STACK_LEN; ++i)
+      {
+         if(frames[i].function)
+            symbols[i] = debug_symbol_name_cached(frames[i].function);
+         else
+            symbols[i] = 0;
+      }
+
+      get_desc(buf, p);
+
+      if(!existing)
+      {
+         os_stream_printf(stream, "<%s> %p %u Create\n", buf, p, serial);
+         dump_stack(symbols);
+
+         /* this is there to provide a gradual change even if we don't see the initialization */
+         for(i = 1; i <= refcnt - change; ++i)
+         {
+            os_stream_printf(stream, "<%s> %p %u AddRef %u\n", buf, p, serial, i);
+            dump_stack(symbols);
+         }
+      }
+
+      if(change)
+      {
+         os_stream_printf(stream, "<%s> %p %u %s %u\n", buf, p, serial, change > 0 ? "AddRef" : "Release", refcnt);
+         dump_stack(symbols);
+      }
+
+      if(!refcnt)
+      {
+         debug_serial_delete((void*)p);
+         os_stream_printf(stream, "<%s> %p %u Destroy\n", buf, p, serial);
+         dump_stack(symbols);
+      }
+
+      os_stream_flush(stream);
+   }
+}
+#endif
diff --git a/src/gallium/auxiliary/util/u_debug_refcnt.h b/src/gallium/auxiliary/util/u_debug_refcnt.h
new file mode 100644 (file)
index 0000000..bea2d1c
--- /dev/null
@@ -0,0 +1,63 @@
+/**************************************************************************
+ *
+ * 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 COPYRIGHT OWNER(S) 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_DEBUG_REFCNT_H_
+#define U_DEBUG_REFCNT_H_
+
+#include <pipe/p_config.h>
+#include <pipe/p_state.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*debug_reference_descriptor)(char*, const struct pipe_reference*);
+
+#if defined(DEBUG) && (!defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_WINDOWS_USER))
+
+extern int debug_refcnt_state;
+
+void debug_reference_slowpath(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change);
+
+static INLINE void debug_reference(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change)
+{
+   if (debug_refcnt_state >= 0)
+      debug_reference_slowpath(p, get_desc, change);
+}
+
+#else
+
+static INLINE void debug_reference(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change)
+{
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_DEBUG_REFCNT_H_ */
index 6e250575d66756592a7cfc03aca502724e1685a6..332952af88b85c4036a0f7866e3c93cb70775138 100644 (file)
  */
 
 #include "pipe/p_compiler.h"
+#include "os/os_thread.h"
+#include "u_string.h"
 
 #include "u_debug.h"
 #include "u_debug_symbol.h"
+#include "u_hash_table.h"
 
 #if defined(PIPE_SUBSYSTEM_WINDOWS_USER) && defined(PIPE_ARCH_X86)
    
@@ -113,8 +116,8 @@ BOOL WINAPI j_SymGetSymFromAddr(HANDLE hProcess, DWORD Address, PDWORD Displacem
 }
 
 
-static INLINE boolean
-debug_symbol_print_imagehlp(const void *addr)
+static INLINE void
+debug_symbol_name_imagehlp(const void *addr, char* buf, unsigned size)
 {
    HANDLE hProcess;
    BYTE symbolBuffer[1024];
@@ -131,25 +134,95 @@ debug_symbol_print_imagehlp(const void *addr)
       if(j_SymInitialize(hProcess, NULL, TRUE))
          bSymInitialized = TRUE;
    }
-      
+
    if(!j_SymGetSymFromAddr(hProcess, (DWORD)addr, &dwDisplacement, pSymbol))
-      return FALSE;
+      buf[0] = 0;
+   else
+   {
+      strncpy(buf, pSymbol->Name, size);
+      buf[size - 1] = 0;
+   }
+}
+#endif
 
-   debug_printf("\t%s\n", pSymbol->Name);
+#ifdef __GLIBC__
+#include <execinfo.h>
 
-   return TRUE;
-   
+/* This can only provide dynamic symbols, or binary offsets into a file.
+ *
+ * To fix this, post-process the output with tools/addr2line.sh
+ */
+static INLINE void
+debug_symbol_name_glibc(const void *addr, char* buf, unsigned size)
+{
+   char** syms = backtrace_symbols((void**)&addr, 1);
+   strncpy(buf, syms[0], size);
+   buf[size - 1] = 0;
+   free(syms);
 }
 #endif
 
-
 void
-debug_symbol_print(const void *addr)
+debug_symbol_name(const void *addr, char* buf, unsigned size)
 {
 #if defined(PIPE_SUBSYSTEM_WINDOWS_USER) && defined(PIPE_ARCH_X86)
-   if(debug_symbol_print_imagehlp(addr))
+   debug_symbol_name_imagehlp(addr, buf, size);
+   if(buf[0])
       return;
 #endif
-   
-   debug_printf("\t%p\n", addr);
+
+#ifdef __GLIBC__
+   debug_symbol_name_glibc(addr, buf, size);
+   if(buf[0])
+      return;
+#endif
+
+   util_snprintf(buf, size, "%p", addr);
+   buf[size - 1] = 0;
+}
+
+void
+debug_symbol_print(const void *addr)
+{
+   char buf[1024];
+   debug_symbol_name(addr, buf, sizeof(buf));
+   debug_printf("\t%s\n", buf);
+}
+
+struct util_hash_table* symbols_hash;
+pipe_mutex symbols_mutex;
+
+static unsigned hash_ptr(void* p)
+{
+   return (unsigned)(uintptr_t)p;
+}
+
+static int compare_ptr(void* a, void* b)
+{
+   if(a == b)
+      return 0;
+   else if(a < b)
+      return -1;
+   else
+      return 1;
+}
+
+const char*
+debug_symbol_name_cached(const void *addr)
+{
+   const char* name;
+   pipe_mutex_lock(symbols_mutex);
+   if(!symbols_hash)
+      symbols_hash = util_hash_table_create(hash_ptr, compare_ptr);
+   name = util_hash_table_get(symbols_hash, (void*)addr);
+   if(!name)
+   {
+      char buf[1024];
+      debug_symbol_name(addr, buf, sizeof(buf));
+      name = strdup(buf);
+
+      util_hash_table_set(symbols_hash, (void*)addr, (void*)name);
+   }
+   pipe_mutex_unlock(symbols_mutex);
+   return name;
 }
index 021586987b6d52504dfdc84d178541302f2ed642..b247706c2a0642e0cc331610e37249f84ed5a4ea 100644 (file)
@@ -43,8 +43,13 @@ extern "C" {
 
 
 void
-debug_symbol_print(const void *addr);
+debug_symbol_name(const void *addr, char* buf, unsigned size);
+
+const char*
+debug_symbol_name_cached(const void *addr);
 
+void
+debug_symbol_print(const void *addr);
 
 #ifdef __cplusplus
 }
index 99f260bf9671d48795415ded396dcc3cc5383ce7..fd1bbe5ffdf3d48c935872924c44f639b3b47247 100644 (file)
@@ -1,9 +1,39 @@
+/**************************************************************************
+ *
+ * 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 COPYRIGHT OWNER(S) 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_DIRTY_SURFACES_H_
 #define U_DIRTY_SURFACES_H_
 
+#include "pipe/p_state.h"
+
 #include "util/u_double_list.h"
 #include "util/u_math.h"
 
+struct pipe_context;
+
 typedef void (*util_dirty_surface_flush_t) (struct pipe_context *, struct pipe_surface *);
 
 struct util_dirty_surfaces
index 2a91ea0f9ae5c2dddbfa05bd77b5c0926bc75073..f06d09ef91d8049459564494b5202c64973990c9 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "pipe/p_compiler.h"
 #include "pipe/p_context.h"
+#include "pipe/p_state.h"
 
 
 static INLINE void
index 9d1c1713a7c47646362a003617b9af9e0bb54013..980cadf22d1b1e5eb7320dadce0dde5021ba7f9e 100644 (file)
@@ -106,6 +106,9 @@ util_dynarray_trim(struct util_dynarray *buf)
 #define util_dynarray_pop_ptr(buf, type) (type*)((char*)(buf)->data + ((buf)->size -= sizeof(type)))
 #define util_dynarray_pop(buf, type) *util_dynarray_pop_ptr(buf, type)
 #define util_dynarray_contains(buf, type) ((buf)->size >= sizeof(type))
+#define util_dynarray_element(buf, type, idx) ((type*)(buf)->data + (idx))
+#define util_dynarray_begin(buf) ((buf)->data)
+#define util_dynarray_end(buf) ((void*)util_dynarray_element((buf), char, (buf)->size))
 
 #endif /* U_DYNARRAY_H */
 
index b7fe2d3003a1483ba012857adca6a8dc663bd20d..6a931a95819cdd690b074870212dab49986cbf55 100644 (file)
@@ -1255,6 +1255,7 @@ fallback_gen_mipmap(struct gen_mipmap_state *ctx,
       make_1d_mipmap(ctx, pt, face, baseLevel, lastLevel);
       break;
    case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_RECT:
    case PIPE_TEXTURE_CUBE:
       make_2d_mipmap(ctx, pt, face, baseLevel, lastLevel);
       break;
index 540305c1465765a90c3fd141ca484520e5a0a285..78473bf35ac0d690182c984d3160a55e43f9dfae 100644 (file)
@@ -33,6 +33,8 @@
 #include "pipe/p_state.h"
 #include "pipe/p_screen.h"
 #include "util/u_debug.h"
+#include "util/u_debug_describe.h"
+#include "util/u_debug_refcnt.h"
 #include "util/u_atomic.h"
 #include "util/u_box.h"
 #include "util/u_math.h"
@@ -67,7 +69,9 @@ pipe_is_referenced(struct pipe_reference *reference)
  * \return TRUE if the object's refcount hits zero and should be destroyed.
  */
 static INLINE boolean
-pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
+pipe_reference_described(struct pipe_reference *ptr, 
+                         struct pipe_reference *reference, 
+                         debug_reference_descriptor get_desc)
 {
    boolean destroy = FALSE;
 
@@ -76,6 +80,7 @@ pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
       if (reference) {
          assert(pipe_is_referenced(reference));
          p_atomic_inc(&reference->count);
+         debug_reference(reference, get_desc, 1);
       }
 
       if (ptr) {
@@ -83,41 +88,49 @@ pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
          if (p_atomic_dec_zero(&ptr->count)) {
             destroy = TRUE;
          }
+         debug_reference(ptr, get_desc, -1);
       }
    }
 
    return destroy;
 }
 
+static INLINE boolean
+pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
+{
+   return pipe_reference_described(ptr, reference, 
+                                   (debug_reference_descriptor)debug_describe_reference);
+}
 
 static INLINE void
 pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf)
 {
    struct pipe_surface *old_surf = *ptr;
 
-   if (pipe_reference(&(*ptr)->reference, &surf->reference))
+   if (pipe_reference_described(&(*ptr)->reference, &surf->reference, 
+                                (debug_reference_descriptor)debug_describe_surface))
       old_surf->texture->screen->tex_surface_destroy(old_surf);
    *ptr = surf;
 }
 
-
 static INLINE void
 pipe_resource_reference(struct pipe_resource **ptr, struct pipe_resource *tex)
 {
    struct pipe_resource *old_tex = *ptr;
 
-   if (pipe_reference(&(*ptr)->reference, &tex->reference))
+   if (pipe_reference_described(&(*ptr)->reference, &tex->reference, 
+                                (debug_reference_descriptor)debug_describe_resource))
       old_tex->screen->resource_destroy(old_tex->screen, old_tex);
    *ptr = tex;
 }
 
-
 static INLINE void
 pipe_sampler_view_reference(struct pipe_sampler_view **ptr, struct pipe_sampler_view *view)
 {
    struct pipe_sampler_view *old_view = *ptr;
 
-   if (pipe_reference(&(*ptr)->reference, &view->reference))
+   if (pipe_reference_described(&(*ptr)->reference, &view->reference,
+                                (debug_reference_descriptor)debug_describe_sampler_view))
       old_view->context->sampler_view_destroy(old_view->context, old_view);
    *ptr = view;
 }
diff --git a/src/gallium/auxiliary/util/u_linkage.c b/src/gallium/auxiliary/util/u_linkage.c
new file mode 100644 (file)
index 0000000..2f6f41b
--- /dev/null
@@ -0,0 +1,149 @@
+/**************************************************************************
+ *
+ * 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 COPYRIGHT OWNER(S) 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 "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_scan.h"
+#include "util/u_linkage.h"
+
+/* we must only record the registers that are actually used, not just declared */
+static INLINE boolean
+util_semantic_set_test_and_set(struct util_semantic_set *set, unsigned value)
+{
+   unsigned mask = 1 << (value % (sizeof(long) * 8));
+   unsigned long *p = &set->masks[value / (sizeof(long) * 8)];
+   unsigned long v = *p & mask;
+   *p |= mask;
+   return !!v;
+}
+
+unsigned
+util_semantic_set_from_program_file(struct util_semantic_set *set, const struct tgsi_token *tokens, enum tgsi_file_type file)
+{
+   struct tgsi_shader_info info;
+   struct tgsi_parse_context parse;
+   unsigned count = 0;
+   ubyte *semantic_name;
+   ubyte *semantic_index;
+
+   tgsi_scan_shader(tokens, &info);
+
+   if(file == TGSI_FILE_INPUT)
+   {
+      semantic_name = info.input_semantic_name;
+      semantic_index = info.input_semantic_index;
+   }
+   else if(file == TGSI_FILE_OUTPUT)
+   {
+      semantic_name = info.output_semantic_name;
+      semantic_index = info.output_semantic_index;
+   }
+   else
+   {
+      assert(0);
+      semantic_name = NULL;
+      semantic_index = NULL;
+   }
+
+   tgsi_parse_init(&parse, tokens);
+
+   memset(set->masks, 0, sizeof(set->masks));
+   while(!tgsi_parse_end_of_tokens(&parse))
+   {
+      tgsi_parse_token(&parse);
+
+      if(parse.FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION)
+      {
+        const struct tgsi_full_instruction *finst = &parse.FullToken.FullInstruction;
+        unsigned i;
+        for(i = 0; i < finst->Instruction.NumDstRegs; ++i)
+        {
+           if(finst->Dst[i].Register.File == file)
+           {
+              unsigned idx = finst->Dst[i].Register.Index;
+              if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC)
+              {
+                 if(!util_semantic_set_test_and_set(set, semantic_index[idx]))
+                    ++count;
+              }
+           }
+        }
+
+        for(i = 0; i < finst->Instruction.NumSrcRegs; ++i)
+        {
+           if(finst->Src[i].Register.File == file)
+           {
+              unsigned idx = finst->Src[i].Register.Index;
+              if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC)
+              {
+                 if(!util_semantic_set_test_and_set(set, semantic_index[idx]))
+                    ++count;
+              }
+           }
+        }
+      }
+   }
+   tgsi_parse_free(&parse);
+
+   return count;
+}
+
+#define UTIL_SEMANTIC_SET_FOR_EACH(i, set) for(i = 0; i < 256; ++i) if(set->masks[i / (sizeof(long) * 8)] & (1 << (i % (sizeof(long) * 8))))
+
+void
+util_semantic_layout_from_set(unsigned char *layout, const struct util_semantic_set *set, unsigned efficient_slots, unsigned num_slots)
+{
+   int first = -1;
+   int last = -1;
+   unsigned i;
+
+   memset(layout, 0xff, num_slots);
+
+   UTIL_SEMANTIC_SET_FOR_EACH(i, set)
+   {
+      if(first < 0)
+        first = i;
+      last = i;
+   }
+
+   if(last < efficient_slots)
+   {
+      UTIL_SEMANTIC_SET_FOR_EACH(i, set)
+         layout[i] = i;
+   }
+   else if((last - first) < efficient_slots)
+   {
+      UTIL_SEMANTIC_SET_FOR_EACH(i, set)
+         layout[i - first] = i;
+   }
+   else
+   {
+      unsigned idx = 0;
+      UTIL_SEMANTIC_SET_FOR_EACH(i, set)
+         layout[idx++] = i;
+   }
+}
diff --git a/src/gallium/auxiliary/util/u_linkage.h b/src/gallium/auxiliary/util/u_linkage.h
new file mode 100644 (file)
index 0000000..4720e0e
--- /dev/null
@@ -0,0 +1,66 @@
+/**************************************************************************
+ *
+ * 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 COPYRIGHT OWNER(S) 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_LINKAGE_H_
+#define U_LINKAGE_H_
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_shader_tokens.h"
+
+struct util_semantic_set
+{
+   unsigned long masks[256 / 8 / sizeof(unsigned long)];
+};
+
+static INLINE bool
+util_semantic_set_contains(struct util_semantic_set *set, unsigned char value)
+{
+   return !!(set->masks[value / (sizeof(long) * 8)] & (1 << (value / (sizeof(long) * 8))));
+}
+
+unsigned util_semantic_set_from_program_file(struct util_semantic_set *set, const struct tgsi_token *tokens, enum tgsi_file_type file);
+
+/* efficient_slots is the number of slots such that hardware performance is
+ * the same for using that amount, with holes, or less slots but with less
+ * holes.
+ *
+ * num_slots is the size of the layout array and hardware limit instead.
+ *
+ * efficient_slots == 0 or efficient_solts == num_slots are typical settings.
+ */
+void util_semantic_layout_from_set(unsigned char *layout, const struct util_semantic_set *set, unsigned efficient_slots, unsigned num_slots);
+
+static INLINE void
+util_semantic_table_from_layout(unsigned char *table, unsigned char *layout, unsigned char first_slot_value, unsigned char num_slots)
+{
+   int i;
+   memset(table, 0xff, sizeof(table));
+
+   for(i = 0; i < num_slots; ++i)
+      table[layout[i]] = first_slot_value + i;
+}
+
+#endif /* U_LINKAGE_H_ */
index fe19466436a089ef1fb04ef2ef6e819ad78dfe38..69a76814945d206eadf396a36384b6a7ab5bd76f 100644 (file)
@@ -360,16 +360,6 @@ util_is_inf_or_nan(float x)
 }
 
 
-/**
- * Test whether x is a power of two.
- */
-static INLINE boolean
-util_is_pot(unsigned x)
-{
-   return (x & (x - 1)) == 0;
-}
-
-
 /**
  * Find first bit set in word.  Least significant bit is 1.
  * Return 0 if no bits set.
@@ -566,6 +556,9 @@ util_bswap16(uint16_t n)
 #define MIN3( A, B, C ) MIN2( MIN2( A, B ), C )
 #define MAX3( A, B, C ) MAX2( MAX2( A, B ), C )
 
+#define MIN4( A, B, C, D ) MIN2( MIN2( A, B ), MIN2(C, D) )
+#define MAX4( A, B, C, D ) MAX2( MAX2( A, B ), MAX2(C, D) )
+
 
 /**
  * Align a value, only works pot alignemnts.
index 5f113f742b113060701f150074a86a94b1a79c87..aae8b8bdf189d4af35851cf67c6520bf207e2313 100644 (file)
 #include "util/u_math.h"
 
 
-
+/**
+ * Helper union for packing pixel values.
+ * Will often contain values in formats which are too complex to be described
+ * in simple terms, hence might just effectively contain a number of bytes.
+ * Must be big enough to hold data for all formats (currently 256 bits).
+ */
 union util_color {
    ubyte ub;
    ushort us;
    uint ui;
    float f[4];
+   double d[4];
 };
 
 /**
index 9bbcf1c8c49ae1d636b46facb9534ff6993f67c3..56fcfac069368fc5d487068b46ec077c5b856ad4 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "util/u_format.h"
 #include "util/u_rect.h"
+#include "util/u_pack_color.h"
 
 
 /**
@@ -94,7 +95,7 @@ util_fill_rect(ubyte * dst,
                unsigned dst_y,
                unsigned width,
                unsigned height,
-               uint32_t value)
+               union util_color *uc)
 {
    unsigned i, j;
    unsigned width_size;
@@ -110,40 +111,54 @@ util_fill_rect(ubyte * dst,
    dst_y /= blockheight;
    width = (width + blockwidth - 1)/blockwidth;
    height = (height + blockheight - 1)/blockheight;
-   
+
    dst += dst_x * blocksize;
    dst += dst_y * dst_stride;
    width_size = width * blocksize;
-   
+
    switch (blocksize) {
    case 1:
       if(dst_stride == width_size)
-        memset(dst, (ubyte) value, height * width_size);
+         memset(dst, uc->ub, height * width_size);
       else {
-        for (i = 0; i < height; i++) {
-           memset(dst, (ubyte) value, width_size);
-           dst += dst_stride;
-        }
+         for (i = 0; i < height; i++) {
+            memset(dst, uc->ub, width_size);
+            dst += dst_stride;
+         }
       }
       break;
    case 2:
       for (i = 0; i < height; i++) {
-        uint16_t *row = (uint16_t *)dst;
-        for (j = 0; j < width; j++)
-           *row++ = (uint16_t) value;
-        dst += dst_stride;
+         uint16_t *row = (uint16_t *)dst;
+         for (j = 0; j < width; j++)
+            *row++ = uc->us;
+         dst += dst_stride;
       }
       break;
    case 4:
       for (i = 0; i < height; i++) {
-        uint32_t *row = (uint32_t *)dst;
-        for (j = 0; j < width; j++)
-           *row++ = value;
-        dst += dst_stride;
+         uint32_t *row = (uint32_t *)dst;
+         for (j = 0; j < width; j++)
+            *row++ = uc->ui;
+         dst += dst_stride;
+      }
+      break;
+   case 8:
+   case 12:
+   case 16:
+   case 24:
+   case 32:
+      for (i = 0; i < height; i++) {
+         ubyte *row = dst;
+         for (j = 0; j < width; j++) {
+            memcpy(row, uc, blocksize);
+            row += blocksize;
+         }
+         dst += dst_stride;
       }
       break;
    default:
-        assert(0);
-        break;
+      assert(0);
+      break;
    }
 }
index 40d57e662d7e3ec1a7ebe96e2e1981ec7e31b899..4cb90d3c3162374857c8a8907a6cc71b931d822d 100644 (file)
  **************************************************************************/
 
 
-/**
- * Pipe copy/fill rect helpers.
+#ifndef U_RECT_H
+#define U_RECT_H
+
+#include "pipe/p_compiler.h"
+
+struct u_rect {
+   int x0, x1;
+   int y0, y1;
+};
+
+/* Do two rectangles intersect?
  */
+static INLINE boolean
+u_rect_test_intersection(const struct u_rect *a,
+                         const struct u_rect *b)
+{
+   return (!(a->x1 < b->x0 ||
+             b->x1 < a->x0 ||
+             a->y1 < b->y0 ||
+             b->y1 < a->y0));
+}
 
+/* Find the intersection of two rectangles known to intersect.
+ */
+static INLINE void
+u_rect_find_intersection(const struct u_rect *a,
+                         struct u_rect *b)
+{
+   /* Caller should verify intersection exists before calling.
+    */
+   if (b->x0 < a->x0) b->x0 = a->x0;
+   if (b->x1 > a->x1) b->x1 = a->x1;
+   if (b->y0 < a->y0) b->y0 = a->y0;
+   if (b->y1 > a->y1) b->y1 = a->y1;
+}
 
-#ifndef U_RECT_H
-#define U_RECT_H
 
+static INLINE void
+u_rect_possible_intersection(const struct u_rect *a,
+                             struct u_rect *b)
+{
+   if (u_rect_test_intersection(a,b)) {
+      u_rect_find_intersection(a,b);
+   }
+   else {
+      b->x0 = b->x1 = b->y0 = b->y1 = 0;
+   }
+}
 
 #include "pipe/p_format.h"
+#include "util/u_pack_color.h"
+
+
+
+/**********************************************************************
+ * Pipe copy/fill rect helpers.
+ */
 
+/* These really should move to a different file:
+ */
+#include "pipe/p_format.h"
 
 extern void
 util_copy_rect(ubyte * dst, enum pipe_format format,
@@ -47,7 +97,7 @@ util_copy_rect(ubyte * dst, enum pipe_format format,
 extern void
 util_fill_rect(ubyte * dst, enum pipe_format format,
                unsigned dst_stride, unsigned dst_x, unsigned dst_y,
-               unsigned width, unsigned height, uint32_t value);
+               unsigned width, unsigned height, union util_color *uc);
 
 
 #endif /* U_RECT_H */
index 5b682f496cb70657ae2e5d1b91bd609cbe11189f..58ef68377fcea467509125842e854c72cdf205ef 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "pipe/p_context.h"
 #include "pipe/p_shader_tokens.h"
+#include "pipe/p_state.h"
 #include "util/u_simple_shaders.h"
 #include "util/u_debug.h"
 #include "tgsi/tgsi_ureg.h"
index 206e1ec3118c233da2ffbdd878d2f272304bfb13..7f80fc127009067a8ea05d9a50451b69bbf0f52e 100644 (file)
@@ -1,5 +1,12 @@
 /* Originally written by Ben Skeggs for the nv50 driver*/
-#include <pipe/p_defines.h>
+
+#ifndef U_SPLIT_PRIM_H
+#define U_SPLIT_PRIM_H
+
+#include "pipe/p_defines.h"
+#include "pipe/p_compiler.h"
+
+#include "util/u_debug.h"
 
 struct util_split_prim {
    void *priv;
@@ -48,7 +55,7 @@ util_split_prim_next(struct util_split_prim *s, unsigned max_verts)
       }
    }
 
-   if (s->p_start + s->close_first + max_verts >= s->p_end) {
+   if ((s->p_end - s->p_start) + s->close_first <= max_verts) {
       s->emit(s->priv, s->p_start, s->p_end - s->p_start);
       if (s->close_first)
          s->emit(s->priv, s->start, 1);
@@ -103,3 +110,5 @@ util_split_prim_next(struct util_split_prim *s, unsigned max_verts)
    s->p_start += (max_verts - repeat);
    return FALSE;
 }
+
+#endif /* U_SPLIT_PRIM_H */
index 607c31f5ee779130dcdab45a39e7323745ccd52c..c5d68f8df8674aac26cbe8adc90194fa5438aae7 100644 (file)
@@ -1,3 +1,29 @@
+/**************************************************************************
+ *
+ * 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 COPYRIGHT OWNER(S) 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_staging.h"
 #include "pipe/p_context.h"
 #include "util/u_memory.h"
@@ -8,7 +34,7 @@ util_staging_resource_template(struct pipe_resource *pt, unsigned width, unsigne
 {
    memset(template, 0, sizeof(struct pipe_resource));
    if(pt->target != PIPE_BUFFER && depth <= 1)
-      template->target = PIPE_TEXTURE_2D;
+      template->target = PIPE_TEXTURE_RECT;
    else
       template->target = pt->target;
    template->format = pt->format;
@@ -23,20 +49,16 @@ util_staging_resource_template(struct pipe_resource *pt, unsigned width, unsigne
 }
 
 struct util_staging_transfer *
-util_staging_transfer_new(struct pipe_context *pipe,
+util_staging_transfer_init(struct pipe_context *pipe,
            struct pipe_resource *pt,
            struct pipe_subresource sr,
            unsigned usage,
            const struct pipe_box *box,
-           bool direct)
+           bool direct, struct util_staging_transfer *tx)
 {
    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;
+   struct pipe_resource staging_resource_template;
 
    pipe_resource_reference(&tx->base.resource, pt);
    tx->base.sr = sr;
index 602faa2971df6e3bbfc21df356538804f1e44770..1aab78cc88173fd47a0eb339e657be972bab73b1 100644 (file)
@@ -1,3 +1,29 @@
+/**************************************************************************
+ *
+ * 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 COPYRIGHT OWNER(S) 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.
+ *
+ **************************************************************************/
+
 /* 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.
@@ -21,15 +47,15 @@ struct util_staging_transfer {
 };
 
 /* 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 */
+/* pt->usage == PIPE_USAGE_DYNAMIC || pt->usage == PIPE_USAGE_STAGING should be a good value to pass for direct */
+/* staging resource is currently created with PIPE_USAGE_STAGING */
 struct util_staging_transfer *
-util_staging_transfer_new(struct pipe_context *pipe,
+util_staging_transfer_init(struct pipe_context *pipe,
            struct pipe_resource *pt,
            struct pipe_subresource sr,
            unsigned usage,
            const struct pipe_box *box,
-           bool direct);
+           bool direct, struct util_staging_transfer *tx);
 
 void
 util_staging_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *ptx);
index cab7691c705a77d5a4da1a86aacaa3e6bfd6afac..af99163b2ed2b780cddb0d698a1ab60e21545eb4 100644 (file)
@@ -216,7 +216,7 @@ util_clear_render_target(struct pipe_context *pipe,
    assert(dst->texture);
    if (!dst->texture)
       return;
-   util_pack_color(rgba, dst->texture->format, &uc);
+
    dst_trans = pipe_get_transfer(pipe,
                                 dst->texture,
                                 dst->face,
@@ -232,46 +232,10 @@ util_clear_render_target(struct pipe_context *pipe,
    if (dst_map) {
       assert(dst_trans->stride > 0);
 
-      switch (util_format_get_blocksize(dst->texture->format)) {
-      case 1:
-      case 2:
-      case 4:
-         util_pack_color(rgba, dst->texture->format, &uc);
-         util_fill_rect(dst_map, dst->texture->format,
-                        dst_trans->stride,
-                        0, 0, width, height, uc.ui);
-         break;
-      case 8:
-      {
-        /* expand the 4-byte clear value to an 8-byte value */
-        /* should probably not convert back from ubyte but not
-           sure what this code really achieved since it doesn't even
-           check for format type... */
-        ushort *row = (ushort *) dst_map;
-        ushort val0 = UBYTE_TO_USHORT((uc.ui >>  0) & 0xff);
-        ushort val1 = UBYTE_TO_USHORT((uc.ui >>  8) & 0xff);
-        ushort val2 = UBYTE_TO_USHORT((uc.ui >> 16) & 0xff);
-        ushort val3 = UBYTE_TO_USHORT((uc.ui >> 24) & 0xff);
-        unsigned i, j;
-        val0 = (val0 << 8) | val0;
-        val1 = (val1 << 8) | val1;
-        val2 = (val2 << 8) | val2;
-        val3 = (val3 << 8) | val3;
-        for (i = 0; i < height; i++) {
-           for (j = 0; j < width; j++) {
-              row[j*4+0] = val0;
-              row[j*4+1] = val1;
-              row[j*4+2] = val2;
-              row[j*4+3] = val3;
-           }
-           row += dst_trans->stride/2;
-        }
-      }
-      break;
-      default:
-         assert(0);
-         break;
-      }
+      util_pack_color(rgba, dst->texture->format, &uc);
+      util_fill_rect(dst_map, dst->texture->format,
+                     dst_trans->stride,
+                     0, 0, width, height, &uc);
    }
 
    pipe->transfer_unmap(pipe, dst_trans);
index 7733ad24d0d68bbde6d8350b503bfb4d81186986..404e12199525681076c521076753d1bd2d117a12 100644 (file)
@@ -1,3 +1,29 @@
+/**************************************************************************
+ *
+ * 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 COPYRIGHT OWNER(S) 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 "u_surfaces.h"
 #include "util/u_hash_table.h"
 #include "util/u_inlines.h"
index af978c705793453ba0dd0f229267de52385178ce..17d8a5d3a5b6fc3e9908ae9b3a0be8ac5f7d38cf 100644 (file)
@@ -1,3 +1,29 @@
+/**************************************************************************
+ *
+ * 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 COPYRIGHT OWNER(S) 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_SURFACES_H_
 #define U_SURFACES_H_
 
@@ -22,7 +48,7 @@ struct pipe_surface *util_surfaces_do_get(struct util_surfaces *us, unsigned sur
 static INLINE struct pipe_surface *
 util_surfaces_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)
 {
-   if(likely(pt->target == PIPE_TEXTURE_2D && us->u.array))
+   if(likely((pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT) && us->u.array))
    {
       struct pipe_surface *ps = us->u.array[level];
       if(ps)
@@ -52,7 +78,7 @@ void util_surfaces_do_detach(struct util_surfaces *us, struct pipe_surface *ps);
 static INLINE void
 util_surfaces_detach(struct util_surfaces *us, struct pipe_surface *ps)
 {
-   if(likely(ps->texture->target == PIPE_TEXTURE_2D))
+   if(likely(ps->texture->target == PIPE_TEXTURE_2D || ps->texture->target == PIPE_TEXTURE_RECT))
    {
       us->u.array[ps->level] = 0;
       return;
index 986eee07435b5c7d3ccd1a9abb74724d4ac63163..558351d0ce5866a150d5cb711cbb0bd9cc0ed723 100644 (file)
 #define P_TILE_H
 
 #include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+#include "pipe/p_state.h"
 
+struct pipe_context;
 struct pipe_transfer;
 
 /**
index eb07945d15f9a9ee53b021b12358058efd3af8ad..e3a38730f214aea837b80e5a4fbd180cc76973c7 100644 (file)
@@ -8,6 +8,7 @@
 #include "pipe/p_state.h"
 
 struct pipe_context;
+struct winsys_handle;
 
 boolean u_default_resource_get_handle(struct pipe_screen *screen,
                                      struct pipe_resource *resource,
index a124924fc80f113acd6db40c40ad42dcdc372d33..de016df02e02f826c8456b5bdd4ebb7960d0b072 100644 (file)
 #ifndef U_UPLOAD_MGR_H
 #define U_UPLOAD_MGR_H
 
-#include "pipe/p_defines.h"
-
-struct pipe_screen;
+struct pipe_context;
 struct pipe_resource;
-struct u_upload_mgr;
 
 
 struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
index f241411a0024ec7f017ea1220fc79d65be8508ec..8250c30f2abe5e1c2fead3b9f90dd5e14b3b7d9f 100644 (file)
@@ -63,7 +63,9 @@ objects. They all follow simple, one-method binding calls, e.g.
 * ``set_scissor_state`` sets the bounds for the scissor test, which culls
   pixels before blending to render targets. If the :ref:`Rasterizer` does
   not have the scissor test enabled, then the scissor bounds never need to
-  be set since they will not be used.
+  be set since they will not be used.  Note that scissor xmin and ymin are
+  inclusive, but  xmax and ymax are exclusive.  The inclusive ranges in x
+  and y would be [xmin..xmax-1] and [ymin..ymax-1].
 * ``set_viewport_state``
 
 
index 42bda5aee93a1d1bf07bd40c2b993b39cc6f7db1..e081cbf74e1d435c112bff064730b8fdba61a2f6 100644 (file)
@@ -21,6 +21,10 @@ 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_GALAHAD <bool> (false)
+
+Controls if the :ref:`galahad` sanity checker module should be used.
+
 .. envvar:: GALLIUM_RBUG <bool> (false)
 
 Controls if the :ref:`rbug` should be used.
index 70d75b51e658bc071a3870cb53d097e1c698c119..08c8eab890a15cb93c089665eae4cf506d5a9b4f 100644 (file)
@@ -79,6 +79,15 @@ Rbug
 
 Wrapper driver. :ref:`rbug` driver used with stand alone rbug-gui.
 
+.. _galahad:
+
+Galahad
+^^^^^^^
+
+Wrapper driver. Sanity checker for the internal gallium state. Normally
+a driver should n't have to sanity check the input it gets from a state
+tracker. Any wrong state received should be perceived as a state tracker bug.
+
 State Trackers
 --------------
 
index 6c19842dac414e2133ab18e68103831de7f074b4..2a73e3ab59d4a9a55de6fc70cc9aae502523bd7b 100644 (file)
@@ -15,6 +15,7 @@ Contents:
    debugging
    tgsi
    screen
+   resources
    context
    cso
    distro
diff --git a/src/gallium/docs/source/resources.rst b/src/gallium/docs/source/resources.rst
new file mode 100644 (file)
index 0000000..c8a5766
--- /dev/null
@@ -0,0 +1,195 @@
+Resources and derived objects
+=============================
+
+Resources represent objects that hold data: textures and buffers.
+
+They are mostly modelled after the resources in Direct3D 10/11, but with a
+different transfer/update mechanism, and more features for OpenGL support.
+
+Resources can be used in several ways, and it is required to specify all planned uses through an appropriate set of bind flags.
+
+TODO: write much more on resources
+
+Transfers
+---------
+
+Transfers are the mechanism used to access resources with the CPU.
+
+OpenGL: OpenGL supports mapping buffers and has inline transfer functions for both buffers and textures
+
+D3D11: D3D11 lacks transfers, but has special resource types that are mappable to the CPU address space
+
+TODO: write much more on transfers
+
+Resource targets
+----------------
+
+Resource targets determine the type of a resource.
+
+Note that drivers may not actually have the restrictions listed regarding
+coordinate normalization and wrap modes, and in fact efficient OpenCL
+support will probably require drivers that don't have any of them, which
+will probably be advertised with an appropriate cap.
+
+TODO: document all targets. Note that both 3D and cube have restrictions
+that depend on the hardware generation.
+
+TODO: can buffers have a non-R8 format?
+
+PIPE_BUFFER
+^^^^^^^^^^^
+
+Buffer resource: can be used as a vertex, index, constant buffer (appropriate bind flags must be requested).
+
+They can be bound to stream output if supported.
+TODO: what about the restrictions lifted by the several later GL transform feedback extensions? How does one advertise that in Gallium?
+
+They can be also be bound to a shader stage as usual.
+TODO: are all drivers supposed to support this? how does this work exactly? are there size limits?
+
+They can be also be bound to the framebuffer as usual.
+TODO: are all drivers supposed to support this? how does this work exactly? are there size limits?
+TODO: is there any chance of supporting GL pixel buffer object acceleration with this?
+
+- depth0 must be 1
+- last_level must be 0
+- TODO: what about normalization?
+- TODO: wrap modes/other sampling state?
+- TODO: are arbitrary formats supported? in which cases?
+
+OpenGL: vertex buffers in GL 1.5 or GL_ARB_vertex_buffer_object
+
+- Binding to stream out requires GL 3.0 or GL_NV_transform_feedback
+- Binding as constant buffers requires GL 3.1 or GL_ARB_uniform_buffer_object
+- Binding to a sampling stage requires GL 3.1 or GL_ARB_texture_buffer_object
+- TODO: can they be bound to an FBO?
+
+D3D11: buffer resources
+- Binding to a render target requires D3D_FEATURE_LEVEL_10_0
+
+PIPE_TEXTURE_1D
+^^^^^^^^^^^^^^^
+1D surface accessed with normalized coordinates.
+
+UNIMPLEMENTED: 1D texture arrays not supported
+
+- If PIPE_CAP_NPOT_TEXTURES is not supported,
+      width must be a power of two
+- height0 must be 1
+- depth0 must be 1
+- Mipmaps can be used
+- Must use normalized coordinates
+
+OpenGL: GL_TEXTURE_1D in GL 1.0
+
+- PIPE_CAP_NPOT_TEXTURES is equivalent to GL 2.0 or GL_ARB_texture_non_power_of_two
+
+D3D11: 1D textures in D3D_FEATURE_LEVEL_10_0
+
+PIPE_TEXTURE_RECT
+^^^^^^^^^^^^^^^^^
+2D surface with OpenGL GL_TEXTURE_RECTANGLE semantics.
+
+- depth0 must be 1
+- last_level must be 0
+- Must use unnormalized coordinates
+- Must use a clamp wrap mode
+
+OpenGL: GL_TEXTURE_RECTANGLE in GL 3.1 or GL_ARB_texture_rectangle or GL_NV_texture_rectangle
+
+OpenCL: can create OpenCL images based on this, that can then be sampled arbitrarily
+
+D3D11: not supported (only PIPE_TEXTURE_2D with normalized coordinates is supported)
+
+PIPE_TEXTURE_2D
+^^^^^^^^^^^^^^^
+2D surface accessed with normalized coordinates.
+
+UNIMPLEMENTED: 2D texture arrays not supported
+
+- If PIPE_CAP_NPOT_TEXTURES is not supported,
+      width and height must be powers of two
+- depth0 must be 1
+- Mipmaps can be used
+- Must use normalized coordinates
+- No special restrictions on wrap modes
+
+OpenGL: GL_TEXTURE_2D in GL 1.0
+
+- PIPE_CAP_NPOT_TEXTURES is equivalent to GL 2.0 or GL_ARB_texture_non_power_of_two
+
+OpenCL: can create OpenCL images based on this, that can then be sampled arbitrarily
+
+D3D11: 2D textures
+
+- PIPE_CAP_NPOT_TEXTURES is equivalent to D3D_FEATURE_LEVEL_9_3
+
+PIPE_TEXTURE_3D
+^^^^^^^^^^^^^^^
+
+3-dimensional array of texels.
+Mipmap dimensions are reduced in all 3 coordinates.
+
+- If PIPE_CAP_NPOT_TEXTURES is not supported,
+      width, height and depth must be powers of two
+- Must use normalized coordinates
+
+OpenGL: GL_TEXTURE_3D in GL 1.2 or GL_EXT_texture3D
+
+- PIPE_CAP_NPOT_TEXTURES is equivalent to GL 2.0 or GL_ARB_texture_non_power_of_two
+
+D3D11: 3D textures
+
+- PIPE_CAP_NPOT_TEXTURES is equivalent to D3D_FEATURE_LEVEL_10_0
+
+PIPE_TEXTURE_CUBE
+^^^^^^^^^^^^^^^^^
+
+Cube maps consist of 6 2D faces.
+The 6 surfaces form an imaginary cube, and sampling happens by mapping an
+input 3-vector to the point of the cube surface in that direction.
+
+Sampling may be optionally seamless, resulting in filtering taking samples
+from multiple surfaces near to the edge.
+UNIMPLEMENTED: seamless cube map sampling not supported
+
+UNIMPLEMENTED: cube map arrays not supported
+
+- Width and height must be equal
+- If PIPE_CAP_NPOT_TEXTURES is not supported,
+      width and height must be powers of two
+- Must use normalized coordinates
+
+OpenGL: GL_TEXTURE_CUBE_MAP in GL 1.3 or EXT_texture_cube_map
+
+- PIPE_CAP_NPOT_TEXTURES is equivalent to GL 2.0 or GL_ARB_texture_non_power_of_two
+- Seamless cube maps require GL 3.2 or GL_ARB_seamless_cube_map or GL_AMD_seamless_cubemap_per_texture
+- Cube map arrays require GL 4.0 or GL_ARB_texture_cube_map_array
+
+D3D11: 2D array textures with the D3D11_RESOURCE_MISC_TEXTURECUBE flag
+
+- PIPE_CAP_NPOT_TEXTURES is equivalent to D3D_FEATURE_LEVEL_10_0
+- Cube map arrays require D3D_FEATURE_LEVEL_10_1
+- TODO: are (non)seamless cube maps supported in D3D11? how?
+
+Surfaces
+--------
+
+Surfaces are views of a resource that can be bound as a framebuffer to serve as the render target or depth buffer.
+
+TODO: write much more on surfaces
+
+OpenGL: FBOs are collections of surfaces in GL 3.0 or GL_ARB_framebuffer_object
+
+D3D11: render target views and depth/stencil views
+
+Sampler views
+-------------
+
+Sampler views are views of a resource that can be bound to a pipeline stage to be sampled from shaders.
+
+TODO: write much more on sampler views
+
+OpenGL: texture objects are actually sampler view and resource in a single unit
+
+D3D11: shader resource views
index 4adef5b8c074fcb206250f7851592dcbbbdf2be5..a367fa3fe157b2395962c95fb0a02e35aa9a709d 100644 (file)
@@ -78,20 +78,13 @@ cell_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
       draw_set_mapped_vertex_buffer(draw, i, buf);
    }
    /* Map index buffer, if present */
-   if (info->indexed && cell->index_buffer.buffer) {
+   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_set_mapped_index_buffer(draw, mapped_indices);
 
    /* draw! */
-   draw_arrays(draw, info->mode, info->start, info->count);
+   draw_vbo(draw, info);
 
    /*
     * unmap vertex/index buffers - will cause draw module to flush
@@ -100,7 +93,7 @@ cell_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
       draw_set_mapped_vertex_buffer(draw, i, NULL);
    }
    if (mapped_indices) {
-      draw_set_mapped_element_buffer(draw, 0, 0, NULL);
+      draw_set_mapped_index_buffer(draw, NULL);
    }
 
    /*
index 4e3701cd0acb85ce75f154b1b3abc453da4379aa..a065d68b5a63ba297d9c20cc3c5e18c23bef0aa8 100644 (file)
@@ -102,7 +102,7 @@ cell_set_index_buffer(struct pipe_context *pipe,
    else
       memset(&cell->index_buffer, 0, sizeof(cell->index_buffer));
 
-   /* TODO make this more like a state */
+   draw_set_index_buffer(cell->draw, ib);
 }
 
 
index fe14a287efbb2c37080f77a8a98bd4947fd090e1..383c448926160195584a1616142a7697427de14a 100644 (file)
@@ -185,6 +185,12 @@ galahad_bind_fragment_sampler_states(struct pipe_context *_pipe,
    struct galahad_context *glhd_pipe = galahad_context(_pipe);
    struct pipe_context *pipe = glhd_pipe->pipe;
 
+   if (num_samplers > PIPE_MAX_SAMPLERS) {
+      glhd_error("%u fragment samplers requested, "
+         "but only %u are permitted by API",
+         num_samplers, PIPE_MAX_SAMPLERS);
+   }
+
    pipe->bind_fragment_sampler_states(pipe,
                                       num_samplers,
                                       samplers);
@@ -198,6 +204,12 @@ galahad_bind_vertex_sampler_states(struct pipe_context *_pipe,
    struct galahad_context *glhd_pipe = galahad_context(_pipe);
    struct pipe_context *pipe = glhd_pipe->pipe;
 
+   if (num_samplers > PIPE_MAX_VERTEX_SAMPLERS) {
+      glhd_error("%u vertex samplers requested, "
+         "but only %u are permitted by API",
+         num_samplers, PIPE_MAX_VERTEX_SAMPLERS);
+   }
+
    pipe->bind_vertex_sampler_states(pipe,
                                     num_samplers,
                                     samplers);
@@ -447,6 +459,19 @@ galahad_set_constant_buffer(struct pipe_context *_pipe,
    struct pipe_resource *unwrapped_resource;
    struct pipe_resource *resource = NULL;
 
+   if (shader >= PIPE_SHADER_TYPES) {
+      glhd_error("Unknown shader type %u", shader);
+   }
+
+   if (index &&
+      index >=
+         pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_CONST_BUFFERS)) {
+      glhd_error("Access to constant buffer %u requested, "
+         "but only %d are supported",
+         index,
+         pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_CONST_BUFFERS));
+   }
+
    /* XXX hmm? unwrap the input state */
    if (_resource) {
       unwrapped_resource = galahad_resource_unwrap(_resource);
@@ -972,5 +997,7 @@ galahad_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
 
    glhd_pipe->pipe = pipe;
 
+   glhd_warn("Created context %p", glhd_pipe);
+
    return &glhd_pipe->base;
 }
index 4117485702efdcfe9462eecd734e9494810b8e02..75e4c2d82e91ddd7eae42ca9ffdbf73b28ee87af 100644 (file)
@@ -30,6 +30,7 @@
 #include "pipe/p_screen.h"
 #include "pipe/p_state.h"
 #include "util/u_memory.h"
+#include "util/u_math.h"
 
 #include "glhd_public.h"
 #include "glhd_screen.h"
@@ -134,6 +135,33 @@ galahad_screen_resource_create(struct pipe_screen *_screen,
    struct pipe_screen *screen = glhd_screen->screen;
    struct pipe_resource *result;
 
+   if (templat->target >= PIPE_MAX_TEXTURE_TYPES)
+      glhd_warn("Received bogus resource target %d", templat->target);
+
+   if(templat->target != PIPE_TEXTURE_RECT && templat->target != PIPE_BUFFER && !screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES))
+   {
+      if(!util_is_power_of_two(templat->width0) || !util_is_power_of_two(templat->height0))
+         glhd_warn("Requested NPOT (%ux%u) non-rectangle texture without NPOT support", templat->width0, templat->height0);
+   }
+
+   if(templat->target == PIPE_TEXTURE_RECT && templat->last_level)
+      glhd_warn("Rectangle textures cannot have mipmaps, but last_level = %u", templat->last_level);
+
+   if(templat->target == PIPE_BUFFER && templat->last_level)
+      glhd_warn("Buffers cannot have mipmaps, but last_level = %u", templat->last_level);
+
+   if(templat->target != PIPE_TEXTURE_3D && templat->depth0 != 1)
+      glhd_warn("Only 3D textures can have depth != 1, but received target %u and depth %u", templat->target, templat->depth0);
+
+   if(templat->target == PIPE_TEXTURE_1D && templat->height0 != 1)
+     glhd_warn("1D textures must have height 1 but got asked for height %u", templat->height0);
+
+   if(templat->target == PIPE_BUFFER && templat->height0 != 1)
+     glhd_warn("Buffers must have height 1 but got asked for height %u", templat->height0);
+
+   if(templat->target == PIPE_TEXTURE_CUBE && templat->width0 != templat->height0)
+      glhd_warn("Cube maps must be square, but got asked for %ux%u", templat->width0, templat->height0);
+
    result = screen->resource_create(screen,
                                     templat);
 
@@ -330,5 +358,7 @@ galahad_screen_create(struct pipe_screen *screen)
 
    glhd_screen->screen = screen;
 
+   glhd_warn("Created screen %p", glhd_screen);
+
    return &glhd_screen->base;
 }
index 2beb9e3091f145d09b92b59c127d05a77b6cd1f8..847dd6dd47e697792f42a8514a23d5174daeecbb 100644 (file)
@@ -66,18 +66,9 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
    /*
     * Map index buffer, if present
     */
-   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);
-
+   if (info->indexed && i915->index_buffer.buffer)
+      mapped_indices = i915_buffer(i915->index_buffer.buffer)->data;
+   draw_set_mapped_index_buffer(draw, mapped_indices);
 
    draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0,
                                    i915->current.constants[PIPE_SHADER_VERTEX],
@@ -87,7 +78,7 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
    /*
     * Do the drawing
     */
-   draw_arrays(i915->draw, info->mode, info->start, info->count);
+   draw_vbo(i915->draw, info);
 
    /*
     * unmap vertex/index buffers
@@ -96,9 +87,8 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
       draw_set_mapped_vertex_buffer(draw, i, NULL);
    }
 
-   if (mapped_indices) {
-      draw_set_mapped_element_buffer(draw, 0, 0, NULL);
-   }
+   if (mapped_indices)
+      draw_set_mapped_index_buffer(draw, NULL);
 }
 
 
index 752ddaae7b1571719a2e788ab238867ff7cb6548..c5c6179b169e5bd3138b94bd62f1ef26e545c5f3 100644 (file)
@@ -360,6 +360,7 @@ i915_texture_layout(struct i915_texture * tex)
    switch (pt->target) {
    case PIPE_TEXTURE_1D:
    case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_RECT:
       if (!i9x5_special_layout(tex))
          i915_texture_layout_2d(tex);
       break;
@@ -605,6 +606,7 @@ i945_texture_layout(struct i915_texture * tex)
    switch (pt->target) {
    case PIPE_TEXTURE_1D:
    case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_RECT:
       if (!i9x5_special_layout(tex))
          i945_texture_layout_2d(tex);
       break;
@@ -829,7 +831,8 @@ i915_texture_from_handle(struct pipe_screen * screen,
    buffer = iws->buffer_from_handle(iws, whandle, &stride);
 
    /* Only supports one type */
-   if (template->target != PIPE_TEXTURE_2D ||
+   if ((template->target != PIPE_TEXTURE_2D &&
+       template->target != PIPE_TEXTURE_RECT) ||
        template->last_level != 0 ||
        template->depth0 != 1) {
       return NULL;
index 385c3b2d2d3ff91c5fb99427f0c707a1a3411e70..bbfcff6bc4d04396872b40c7813cd44af520a13b 100644 (file)
@@ -294,8 +294,6 @@ static void i915_bind_sampler_states(struct pipe_context *pipe,
    struct i915_context *i915 = i915_context(pipe);
    unsigned i;
 
-   assert(num <= PIPE_MAX_SAMPLERS);
-
    /* Check for no-op */
    if (num == i915->num_samplers &&
        !memcmp(i915->sampler, sampler, num * sizeof(void *)))
@@ -529,9 +527,6 @@ static void i915_set_constant_buffer(struct pipe_context *pipe,
    struct i915_context *i915 = i915_context(pipe);
    draw_flush(i915->draw);
 
-   assert(shader < PIPE_SHADER_TYPES);
-   assert(index == 0);
-
    /* Make a copy of shader constants.
     * During fragment program translation we may add additional
     * constants to the array.
@@ -822,7 +817,8 @@ static void i915_set_index_buffer(struct pipe_context *pipe,
    else
       memset(&i915->index_buffer, 0, sizeof(i915->index_buffer));
 
-   /* TODO make this more like a state */
+   /* pass-through to draw module */
+   draw_set_index_buffer(i915->draw, ib);
 }
 
 static void
index 8b3f46f2c1632cf4b288d0e2ca4f6a1994464c8d..e80067f3b191830d72bc67335688a5f33c61cb82 100644 (file)
@@ -162,7 +162,7 @@ brw_batchbuffer_emit_reloc(struct brw_batchbuffer *batch,
 
    if (batch->ptr - batch->map > batch->buf->size) {
       debug_printf("bad relocation ptr %p map %p offset %li size %i\n",
-                  batch->ptr, batch->map, batch->ptr - batch->map, batch->buf->size);
+                  batch->ptr, batch->map, (long) (batch->ptr - batch->map), batch->buf->size);
 
       return PIPE_ERROR_OUT_OF_MEMORY;
    }
index ffd0f38672c7e7b32121fea8796d1571c4b72262..3860d18a7a2f10190d25f26efda9a20b9133bcc8 100644 (file)
@@ -66,6 +66,7 @@ static GLuint translate_tex_target( unsigned target )
       return BRW_SURFACE_1D;
 
    case PIPE_TEXTURE_2D: 
+   case PIPE_TEXTURE_RECT:
       return BRW_SURFACE_2D;
 
    case PIPE_TEXTURE_3D: 
@@ -498,7 +499,8 @@ brw_texture_from_handle(struct pipe_screen *screen,
    unsigned pitch;
    GLuint format;
 
-   if (template->target != PIPE_TEXTURE_2D ||
+   if ((template->target != PIPE_TEXTURE_2D
+         && template->target != PIPE_TEXTURE_RECT)  ||
        template->last_level != 0 ||
        template->depth0 != 1)
       return NULL;
index e2767264e7e286bc50f876b9fcb0ce52a5402e95..1b2aa93befc7a5424c63d93a15899083729f141a 100644 (file)
@@ -101,16 +101,16 @@ void brw_wm_print_value( struct brw_wm_compile *c,
       debug_printf("undef");
    else if( value - c->vreg >= 0 &&
            value - c->vreg < BRW_WM_MAX_VREG)
-      debug_printf("r%d", value - c->vreg);
+      debug_printf("r%ld", (long) (value - c->vreg));
    else if (value - c->creg >= 0 &&
            value - c->creg < BRW_WM_MAX_PARAM)
-      debug_printf("c%d", value - c->creg);
+      debug_printf("c%ld", (long) (value - c->creg));
    else if (value - c->payload.input_interp >= 0 &&
            value - c->payload.input_interp < PIPE_MAX_SHADER_INPUTS)
-      debug_printf("i%d", value - c->payload.input_interp);
+      debug_printf("i%ld", (long) (value - c->payload.input_interp));
    else if (value - c->payload.depth >= 0 &&
            value - c->payload.depth < PIPE_MAX_SHADER_INPUTS)
-      debug_printf("d%d", value - c->payload.depth);
+      debug_printf("d%ld", (long) (value - c->payload.depth));
    else 
       debug_printf("?");
 }
index 2892b62920e80b18c009bdce54506586f442a57e..dec874623e5897ac60c50f2f4938c51071351275 100644 (file)
@@ -27,6 +27,8 @@ C_SOURCES = \
        lp_scene_queue.c \
        lp_screen.c \
        lp_setup.c \
+       lp_setup_coef.c \
+       lp_setup_coef_intrin.c \
        lp_setup_line.c \
        lp_setup_point.c \
        lp_setup_tri.c \
index 5583fca38e6b43562bdf9a183d19c67c7e965a54..8d57db72cfb1174456bd9602a4d79542451ffacd 100644 (file)
@@ -63,6 +63,8 @@ llvmpipe = env.ConvenienceLibrary(
                'lp_setup_line.c',
                'lp_setup_point.c',
                'lp_setup_tri.c',
+               'lp_setup_coef.c',
+               'lp_setup_coef_intrin.c',
                'lp_setup_vbuf.c',
                'lp_state_blend.c',
                'lp_state_clip.c',
index 7543bd7b2b0d27489496e871bd7e0f5361ab0fac..39f2c6085ef0665fa0db47c233f1ee3058bac18a 100644 (file)
@@ -85,6 +85,14 @@ static void llvmpipe_destroy( struct pipe_context *pipe )
    align_free( llvmpipe );
 }
 
+static void
+do_flush( struct pipe_context *pipe,
+          unsigned flags,
+          struct pipe_fence_handle **fence)
+{
+   llvmpipe_flush(pipe, flags, fence, __FUNCTION__);
+}
+
 
 struct pipe_context *
 llvmpipe_create_context( struct pipe_screen *screen, void *priv )
@@ -109,7 +117,7 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv )
    llvmpipe->pipe.destroy = llvmpipe_destroy;
    llvmpipe->pipe.set_framebuffer_state = llvmpipe_set_framebuffer_state;
    llvmpipe->pipe.clear = llvmpipe_clear;
-   llvmpipe->pipe.flush = llvmpipe_flush;
+   llvmpipe->pipe.flush = do_flush;
 
    llvmpipe_init_blend_funcs(llvmpipe);
    llvmpipe_init_clip_funcs(llvmpipe);
@@ -147,9 +155,13 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv )
    draw_install_aapoint_stage(llvmpipe->draw, &llvmpipe->pipe);
    draw_install_pstipple_stage(llvmpipe->draw, &llvmpipe->pipe);
 
-   /* convert points and lines into triangles: */
-   draw_wide_point_threshold(llvmpipe->draw, 0.0);
-   draw_wide_line_threshold(llvmpipe->draw, 0.0);
+   /* convert points and lines into triangles: 
+    * (otherwise, draw points and lines natively)
+    */
+   draw_wide_point_sprites(llvmpipe->draw, FALSE);
+   draw_enable_point_sprites(llvmpipe->draw, FALSE);
+   draw_wide_point_threshold(llvmpipe->draw, 10000.0);
+   draw_wide_line_threshold(llvmpipe->draw, 10000.0);
 
 #if USE_DRAW_STAGE_PSTIPPLE
    /* Do polygon stipple w/ texture map + frag prog? */
index 50f9091c3ca743e0a27b9e3399b1f2756588f265..34fa20e204a6e1d22e21ce2d0dcf75b6b935dfbb 100644 (file)
@@ -101,6 +101,9 @@ struct llvmpipe_context {
    
    /** Vertex format */
    struct vertex_info vertex_info;
+   
+   /** Which vertex shader output slot contains point size */
+   int psize_slot;
 
    /** Fragment shader input interpolation info */
    unsigned num_inputs;
index 92fb2b3ee5b530477999e211c19aac21a59998a9..a928ee38becaefffaff25f9d8ec28de15ba79fb6 100644 (file)
@@ -46,6 +46,8 @@ st_print_current(void);
 #define DEBUG_SHOW_TILES    0x200
 #define DEBUG_SHOW_SUBTILES 0x400
 #define DEBUG_COUNTERS      0x800
+#define DEBUG_SCENE         0x1000
+#define DEBUG_FENCE         0x2000
 
 
 #ifdef DEBUG
index e73b431cb4d5af5da930b7204b5aaf2b12eba6c4..3af5c8d5c55e2bc213959b1177095ffb85e6fcd8 100644 (file)
@@ -68,25 +68,17 @@ llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
    }
 
    /* Map index buffer, if present */
-   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);
-   }
+   if (info->indexed && lp->index_buffer.buffer)
+      mapped_indices = llvmpipe_resource_data(lp->index_buffer.buffer);
 
-   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_set_mapped_index_buffer(draw, mapped_indices);
 
    llvmpipe_prepare_vertex_sampling(lp,
                                     lp->num_vertex_sampler_views,
                                     lp->vertex_sampler_views);
 
    /* draw! */
-   draw_arrays_instanced(draw, info->mode, info->start, info->count,
-         info->start_instance, info->instance_count);
+   draw_vbo(draw, info);
 
    /*
     * unmap vertex/index buffers
@@ -95,7 +87,7 @@ llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
       draw_set_mapped_vertex_buffer(draw, i, NULL);
    }
    if (mapped_indices) {
-      draw_set_mapped_element_buffer(draw, 0, 0, NULL);
+      draw_set_mapped_index_buffer(draw, NULL);
    }
    llvmpipe_cleanup_vertex_sampling(lp);
 
index f9805e5d6881fa1ac347f59306a9be55e694f2f2..3a55e76bc3558e6df028bf368e036f14404edd10 100644 (file)
@@ -44,6 +44,7 @@
 struct lp_fence *
 lp_fence_create(unsigned rank)
 {
+   static int fence_id;
    struct lp_fence *fence = CALLOC_STRUCT(lp_fence);
 
    pipe_reference_init(&fence->reference, 1);
@@ -51,8 +52,12 @@ lp_fence_create(unsigned rank)
    pipe_mutex_init(fence->mutex);
    pipe_condvar_init(fence->signalled);
 
+   fence->id = fence_id++;
    fence->rank = rank;
 
+   if (LP_DEBUG & DEBUG_FENCE)
+      debug_printf("%s %d\n", __FUNCTION__, fence->id);
+
    return fence;
 }
 
@@ -61,64 +66,15 @@ lp_fence_create(unsigned rank)
 void
 lp_fence_destroy(struct lp_fence *fence)
 {
+   if (LP_DEBUG & DEBUG_FENCE)
+      debug_printf("%s %d\n", __FUNCTION__, fence->id);
+
    pipe_mutex_destroy(fence->mutex);
    pipe_condvar_destroy(fence->signalled);
    FREE(fence);
 }
 
 
-/**
- * For reference counting.
- * This is a Gallium API function.
- */
-static void
-llvmpipe_fence_reference(struct pipe_screen *screen,
-                         struct pipe_fence_handle **ptr,
-                         struct pipe_fence_handle *fence)
-{
-   struct lp_fence **old = (struct lp_fence **) ptr;
-   struct lp_fence *f = (struct lp_fence *) fence;
-
-   lp_fence_reference(old, f);
-}
-
-
-/**
- * Has the fence been executed/finished?
- * This is a Gallium API function.
- */
-static int
-llvmpipe_fence_signalled(struct pipe_screen *screen,
-                         struct pipe_fence_handle *fence,
-                         unsigned flag)
-{
-   struct lp_fence *f = (struct lp_fence *) fence;
-
-   return f->count == f->rank;
-}
-
-
-/**
- * Wait for the fence to finish.
- * This is a Gallium API function.
- */
-static int
-llvmpipe_fence_finish(struct pipe_screen *screen,
-                      struct pipe_fence_handle *fence_handle,
-                      unsigned flag)
-{
-   struct lp_fence *fence = (struct lp_fence *) fence_handle;
-
-   pipe_mutex_lock(fence->mutex);
-   while (fence->count < fence->rank) {
-      pipe_condvar_wait(fence->signalled, fence->mutex);
-   }
-   pipe_mutex_unlock(fence->mutex);
-
-   return 0;
-}
-
-
 /**
  * Called by the rendering threads to increment the fence counter.
  * When the counter == the rank, the fence is finished.
@@ -126,24 +82,43 @@ llvmpipe_fence_finish(struct pipe_screen *screen,
 void
 lp_fence_signal(struct lp_fence *fence)
 {
+   if (LP_DEBUG & DEBUG_FENCE)
+      debug_printf("%s %d\n", __FUNCTION__, fence->id);
+
    pipe_mutex_lock(fence->mutex);
 
    fence->count++;
    assert(fence->count <= fence->rank);
 
-   LP_DBG(DEBUG_RAST, "%s count=%u rank=%u\n", __FUNCTION__,
-          fence->count, fence->rank);
+   if (LP_DEBUG & DEBUG_FENCE)
+      debug_printf("%s count=%u rank=%u\n", __FUNCTION__,
+                   fence->count, fence->rank);
 
-   pipe_condvar_signal(fence->signalled);
+   /* Wakeup all threads waiting on the mutex:
+    */
+   pipe_condvar_broadcast(fence->signalled);
 
    pipe_mutex_unlock(fence->mutex);
 }
 
+boolean
+lp_fence_signalled(struct lp_fence *f)
+{
+   return f->count == f->rank;
+}
 
 void
-llvmpipe_init_screen_fence_funcs(struct pipe_screen *screen)
+lp_fence_wait(struct lp_fence *f)
 {
-   screen->fence_reference = llvmpipe_fence_reference;
-   screen->fence_signalled = llvmpipe_fence_signalled;
-   screen->fence_finish = llvmpipe_fence_finish;
+   if (LP_DEBUG & DEBUG_FENCE)
+      debug_printf("%s %d\n", __FUNCTION__, f->id);
+
+   pipe_mutex_lock(f->mutex);
+   assert(f->issued);
+   while (f->count < f->rank) {
+      pipe_condvar_wait(f->signalled, f->mutex);
+   }
+   pipe_mutex_unlock(f->mutex);
 }
+
+
index 13358fb99f2a89ddd3007706ab2fc4708691af23..3c591187801fc54514fd89923812578d63816d1d 100644 (file)
@@ -41,10 +41,12 @@ struct pipe_screen;
 struct lp_fence
 {
    struct pipe_reference reference;
+   unsigned id;
 
    pipe_mutex mutex;
    pipe_condvar signalled;
 
+   boolean issued;
    unsigned rank;
    unsigned count;
 };
@@ -57,6 +59,11 @@ lp_fence_create(unsigned rank);
 void
 lp_fence_signal(struct lp_fence *fence);
 
+boolean
+lp_fence_signalled(struct lp_fence *fence);
+
+void
+lp_fence_wait(struct lp_fence *fence);
 
 void
 llvmpipe_init_screen_fence_funcs(struct pipe_screen *screen);
@@ -78,5 +85,11 @@ lp_fence_reference(struct lp_fence **ptr,
    *ptr = f;
 }
 
+static INLINE boolean
+lp_fence_issued(const struct lp_fence *fence)
+{
+   return fence->issued;
+}
+
 
 #endif /* LP_FENCE_H */
index 845292f4ab206f4c21e290d7bba91e253cf626db..e2c723b7a873ad64936b66c95ad42ef271777d61 100644 (file)
@@ -31,6 +31,7 @@
 
 
 #include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
 #include "util/u_string.h"
 #include "draw/draw_context.h"
 #include "lp_flush.h"
 void
 llvmpipe_flush( struct pipe_context *pipe,
                 unsigned flags,
-                struct pipe_fence_handle **fence )
+                struct pipe_fence_handle **fence,
+                const char *reason)
 {
    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
 
    draw_flush(llvmpipe->draw);
 
    /* ask the setup module to flush */
-   lp_setup_flush(llvmpipe->setup, flags, fence);
+   lp_setup_flush(llvmpipe->setup, flags, fence, reason);
 
    /* Enable to dump BMPs of the color/depth buffers each frame */
    if (0) {
@@ -76,6 +78,17 @@ llvmpipe_flush( struct pipe_context *pipe,
    }
 }
 
+void
+llvmpipe_finish( struct pipe_context *pipe,
+                 const char *reason )
+{
+   struct pipe_fence_handle *fence = NULL;
+   llvmpipe_flush(pipe, 0, &fence, reason);
+   if (fence) {
+      pipe->screen->fence_finish(pipe->screen, fence, 0);
+      pipe->screen->fence_reference(pipe->screen, &fence, NULL);
+   }
+}
 
 /**
  * Flush context if necessary.
@@ -93,7 +106,8 @@ llvmpipe_flush_resource(struct pipe_context *pipe,
                         unsigned flush_flags,
                         boolean read_only,
                         boolean cpu_access,
-                        boolean do_not_block)
+                        boolean do_not_block,
+                        const char *reason)
 {
    unsigned referenced;
 
@@ -106,31 +120,16 @@ llvmpipe_flush_resource(struct pipe_context *pipe,
          /*
           * Flush and wait.
           */
-
-         struct pipe_fence_handle *fence = NULL;
-
          if (do_not_block)
             return FALSE;
 
-         /*
-          * Do the unswizzling in parallel.
-          *
-          * XXX: Don't abuse the PIPE_FLUSH_FRAME flag for this.
-          */
-         flush_flags |= PIPE_FLUSH_FRAME;
-
-         llvmpipe_flush(pipe, flush_flags, &fence);
-
-         if (fence) {
-            pipe->screen->fence_finish(pipe->screen, fence, 0);
-            pipe->screen->fence_reference(pipe->screen, &fence, NULL);
-         }
+         llvmpipe_finish(pipe, reason);
       } else {
          /*
           * Just flush.
           */
 
-         llvmpipe_flush(pipe, flush_flags, NULL);
+         llvmpipe_flush(pipe, flush_flags, NULL, reason);
       }
    }
 
index 7b605681a935e51cc06bfab3cf69c45bcda5b10b..bb538b2bd83d70fa01f4f76d3df98e3c04d5f676 100644 (file)
@@ -34,8 +34,14 @@ struct pipe_context;
 struct pipe_fence_handle;
 
 void
-llvmpipe_flush(struct pipe_context *pipe, unsigned flags,
-               struct pipe_fence_handle **fence);
+llvmpipe_flush(struct pipe_context *pipe,
+               unsigned flags,
+               struct pipe_fence_handle **fence,
+               const char *reason);
+
+void
+llvmpipe_finish( struct pipe_context *pipe,
+                 const char *reason );
 
 boolean
 llvmpipe_flush_resource(struct pipe_context *pipe,
@@ -45,6 +51,7 @@ llvmpipe_flush_resource(struct pipe_context *pipe,
                         unsigned flush_flags,
                         boolean read_only,
                         boolean cpu_access,
-                        boolean do_not_block);
+                        boolean do_not_block,
+                        const char *reason);
 
 #endif
index 083e7e30a5b27bb4e152be4e2396b3a90397a8d8..e22532f25c10593e5185a94133c26246563f4ac6 100644 (file)
@@ -46,7 +46,7 @@ lp_print_counters(void)
 {
    if (LP_DEBUG & DEBUG_COUNTERS) {
       unsigned total_64, total_16, total_4;
-      float p1, p2, p3, p4;
+      float p1, p2, p3, p5, p6;
 
       debug_printf("llvmpipe: nr_triangles:                 %9u\n", lp_count.nr_tris);
       debug_printf("llvmpipe: nr_culled_triangles:          %9u\n", lp_count.nr_culled_tris);
@@ -58,11 +58,15 @@ lp_print_counters(void)
       p1 = 100.0 * (float) lp_count.nr_empty_64 / (float) total_64;
       p2 = 100.0 * (float) lp_count.nr_fully_covered_64 / (float) total_64;
       p3 = 100.0 * (float) lp_count.nr_partially_covered_64 / (float) total_64;
-      p4 = 100.0 * (float) lp_count.nr_shade_opaque_64 / (float) total_64;
+      p5 = 100.0 * (float) lp_count.nr_shade_opaque_64 / (float) total_64;
+      p6 = 100.0 * (float) lp_count.nr_shade_64 / (float) total_64;
 
       debug_printf("llvmpipe: nr_64x64:                     %9u\n", total_64);
       debug_printf("llvmpipe:   nr_fully_covered_64x64:     %9u (%3.0f%% of %u)\n", lp_count.nr_fully_covered_64, p2, total_64);
-      debug_printf("llvmpipe:     nr_shade_opaque_64x64:    %9u (%3.0f%% of %u)\n", lp_count.nr_shade_opaque_64, p4, total_64);
+      debug_printf("llvmpipe:     nr_shade_opaque_64x64:    %9u (%3.0f%% of %u)\n", lp_count.nr_shade_opaque_64, p5, total_64);
+      debug_printf("llvmpipe:        nr_pure_shade_opaque:  %9u (%3.0f%% of %u)\n", lp_count.nr_pure_shade_opaque_64, 0.0, lp_count.nr_shade_opaque_64);
+      debug_printf("llvmpipe:     nr_shade_64x64:           %9u (%3.0f%% of %u)\n", lp_count.nr_shade_64, p6, total_64);
+      debug_printf("llvmpipe:        nr_pure_shade:         %9u (%3.0f%% of %u)\n", lp_count.nr_pure_shade_64, 0.0, lp_count.nr_shade_64);
       debug_printf("llvmpipe:   nr_partially_covered_64x64: %9u (%3.0f%% of %u)\n", lp_count.nr_partially_covered_64, p3, total_64);
       debug_printf("llvmpipe:   nr_empty_64x64:             %9u (%3.0f%% of %u)\n", lp_count.nr_empty_64, p1, total_64);
 
@@ -79,12 +83,17 @@ lp_print_counters(void)
       debug_printf("llvmpipe:   nr_partially_covered_16x16: %9u (%3.0f%% of %u)\n", lp_count.nr_partially_covered_16, p3, total_16);
       debug_printf("llvmpipe:   nr_empty_16x16:             %9u (%3.0f%% of %u)\n", lp_count.nr_empty_16, p1, total_16);
 
-      total_4 = (lp_count.nr_empty_4 + lp_count.nr_non_empty_4);
+      total_4 = (lp_count.nr_empty_4 +
+                 lp_count.nr_fully_covered_4 +
+                 lp_count.nr_partially_covered_4);
 
       p1 = 100.0 * (float) lp_count.nr_empty_4 / (float) total_4;
-      p2 = 100.0 * (float) lp_count.nr_non_empty_4 / (float) total_4;
+      p2 = 100.0 * (float) lp_count.nr_fully_covered_4 / (float) total_4;
+      p3 = 100.0 * (float) lp_count.nr_partially_covered_4 / (float) total_4;
 
-      debug_printf("llvmpipe: nr_4x4:                       %9u\n", total_4);
+      debug_printf("llvmpipe: nr_tri_4x4:                   %9u\n", total_4);
+      debug_printf("llvmpipe:   nr_fully_covered_4x4:       %9u (%3.0f%% of %u)\n", lp_count.nr_fully_covered_4, p2, total_4);
+      debug_printf("llvmpipe:   nr_partially_covered_4x4:   %9u (%3.0f%% of %u)\n", lp_count.nr_partially_covered_4, p3, total_4);
       debug_printf("llvmpipe:   nr_empty_4x4:               %9u (%3.0f%% of %u)\n", lp_count.nr_empty_4, p1, total_4);
       debug_printf("llvmpipe:   nr_non_empty_4x4:           %9u (%3.0f%% of %u)\n", lp_count.nr_non_empty_4, p2, total_4);
 
index 4774f645508742dc1d7cd6c0167481e7fa6fa6b6..c28652fc3052a91ff4e2ba58a0ae96d5d482feb6 100644 (file)
@@ -44,11 +44,16 @@ struct lp_counters
    unsigned nr_empty_64;
    unsigned nr_fully_covered_64;
    unsigned nr_partially_covered_64;
+   unsigned nr_pure_shade_opaque_64;
+   unsigned nr_pure_shade_64;
+   unsigned nr_shade_64;
    unsigned nr_shade_opaque_64;
    unsigned nr_empty_16;
    unsigned nr_fully_covered_16;
    unsigned nr_partially_covered_16;
    unsigned nr_empty_4;
+   unsigned nr_fully_covered_4;
+   unsigned nr_partially_covered_4;
    unsigned nr_non_empty_4;
    unsigned nr_llvm_compiles;
    int64_t llvm_compile_time;  /**< total, in microseconds */
@@ -66,9 +71,11 @@ extern struct lp_counters lp_count;
 #ifdef DEBUG
 #define LP_COUNT(counter) lp_count.counter++
 #define LP_COUNT_ADD(counter, incr)  lp_count.counter += (incr)
+#define LP_COUNT_GET(counter) (lp_count.counter)
 #else
 #define LP_COUNT(counter)
 #define LP_COUNT_ADD(counter, incr) (void) incr
+#define LP_COUNT_GET(counter) 0
 #endif
 
 
index 02eeaf64871d5344aab458785f201939654a6331..67fd797af228526827b2a001176008caf978587f 100644 (file)
@@ -35,9 +35,8 @@
 #include "util/u_memory.h"
 #include "lp_context.h"
 #include "lp_flush.h"
+#include "lp_fence.h"
 #include "lp_query.h"
-#include "lp_rast.h"
-#include "lp_rast_priv.h"
 #include "lp_state.h"
 
 
@@ -69,12 +68,7 @@ llvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
    struct llvmpipe_query *pq = llvmpipe_query(q);
    /* query might still be in process if we never waited for the result */
    if (!pq->done) {
-     struct pipe_fence_handle *fence = NULL;
-     llvmpipe_flush(pipe, 0, &fence);
-     if (fence) {
-         pipe->screen->fence_finish(pipe->screen, fence, 0);
-         pipe->screen->fence_reference(pipe->screen, &fence, NULL);
-      }
+      llvmpipe_finish(pipe, __FUNCTION__);
    }
 
    pipe_mutex_destroy(pq->mutex);
@@ -93,16 +87,11 @@ llvmpipe_get_query_result(struct pipe_context *pipe,
 
    if (!pq->done) {
       if (wait) {
-         struct pipe_fence_handle *fence = NULL;
-         llvmpipe_flush(pipe, 0, &fence);
-         if (fence) {
-            pipe->screen->fence_finish(pipe->screen, fence, 0);
-            pipe->screen->fence_reference(pipe->screen, &fence, NULL);
-         }
+         llvmpipe_finish(pipe, __FUNCTION__);
       }
       /* this is a bit inconsequent but should be ok */
       else {
-         llvmpipe_flush(pipe, 0, NULL);
+         llvmpipe_flush(pipe, 0, NULL, __FUNCTION__);
       }
    }
 
@@ -125,12 +114,7 @@ llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
     * frame of rendering.
     */
    if (pq->binned) {
-      struct pipe_fence_handle *fence;
-      llvmpipe_flush(pipe, 0, &fence);
-      if (fence) {
-         pipe->screen->fence_finish(pipe->screen, fence, 0);
-         pipe->screen->fence_reference(pipe->screen, &fence, NULL);
-      }
+      llvmpipe_finish(pipe, __FUNCTION__);
    }
 
    lp_setup_begin_query(llvmpipe->setup, pq);
index 3215d0f65255b9ba9160934e94f4fc2adf5fc487..b1c306bbe948d6a6c3e64b32b7be7f8f64f0e091 100644 (file)
@@ -316,43 +316,6 @@ lp_rast_clear_zstencil(struct lp_rasterizer_task *task,
 }
 
 
-/**
- * Load tile color from the framebuffer surface.
- * This is a bin command called during bin processing.
- */
-#if 0
-void
-lp_rast_load_color(struct lp_rasterizer_task *task,
-                   const union lp_rast_cmd_arg arg)
-{
-   struct lp_rasterizer *rast = task->rast;
-   unsigned buf;
-   enum lp_texture_usage usage;
-
-   LP_DBG(DEBUG_RAST, "%s at %u, %u\n", __FUNCTION__, x, y);
-
-   if (scene->has_color_clear)
-      usage = LP_TEX_USAGE_WRITE_ALL;
-   else
-      usage = LP_TEX_USAGE_READ_WRITE;
-
-   /* Get pointers to color tile(s).
-    * This will convert linear data to tiled if needed.
-    */
-   for (buf = 0; buf < rast->state.nr_cbufs; buf++) {
-      struct pipe_surface *cbuf = rast->curr_scene->fb.cbufs[buf];
-      struct llvmpipe_texture *lpt;
-      assert(cbuf);
-      lpt = llvmpipe_texture(cbuf->texture);
-      task->color_tiles[buf] = llvmpipe_get_texture_tile(lpt,
-                                                         cbuf->face + cbuf->zslice,
-                                                         cbuf->level,
-                                                         usage,
-                                                         task->x, task->y);
-      assert(task->color_tiles[buf]);
-   }
-}
-#endif
 
 
 /**
index 44319a0ad6fc498d503588ac7c66c324c2dca54c..b4564ef33bdf97ae75d48df0e848eb8b494481e9 100644 (file)
@@ -120,7 +120,7 @@ struct lp_rast_triangle {
    float v[3][2];
 #endif
 
-   struct lp_rast_plane plane[7]; /* NOTE: may allocate fewer planes */
+   struct lp_rast_plane plane[8]; /* NOTE: may allocate fewer planes */
 };
 
 
@@ -236,6 +236,8 @@ void lp_rast_triangle_6( struct lp_rasterizer_task *,
                          const union lp_rast_cmd_arg );
 void lp_rast_triangle_7( struct lp_rasterizer_task *, 
                          const union lp_rast_cmd_arg );
+void lp_rast_triangle_8( struct lp_rasterizer_task *, 
+                         const union lp_rast_cmd_arg );
 
 void lp_rast_shade_tile( struct lp_rasterizer_task *,
                          const union lp_rast_cmd_arg );
@@ -256,5 +258,9 @@ void lp_rast_begin_query(struct lp_rasterizer_task *,
 void lp_rast_end_query(struct lp_rasterizer_task *,
                        const union lp_rast_cmd_arg );
 
+void
+lp_rast_triangle_3_16(struct lp_rasterizer_task *task,
+                      const union lp_rast_cmd_arg arg);
+
 
 #endif
index 980c18c0240e3fe8fd1628d895c71dfe9055530b..dbaa8e023a4a70702147bb189706404397cb7400 100644 (file)
@@ -67,7 +67,7 @@ block_full_16(struct lp_rasterizer_task *task,
         block_full_4(task, tri, x + ix, y + iy);
 }
 
-
+#if !defined(PIPE_ARCH_SSE)
 static INLINE unsigned
 build_mask(int c, int dcdx, int dcdy)
 {
@@ -98,6 +98,7 @@ build_mask(int c, int dcdx, int dcdy)
    return mask;
 }
 
+
 static INLINE unsigned
 build_mask_linear(int c, int dcdx, int dcdy)
 {
@@ -129,6 +130,137 @@ build_mask_linear(int c, int dcdx, int dcdy)
 }
 
 
+static INLINE void
+build_masks(int c, 
+           int cdiff,
+           int dcdx,
+           int dcdy,
+           unsigned *outmask,
+           unsigned *partmask)
+{
+   *outmask |= build_mask_linear(c, dcdx, dcdy);
+   *partmask |= build_mask_linear(c + cdiff, dcdx, dcdy);
+}
+
+#else
+#include <emmintrin.h>
+#include "util/u_sse.h"
+
+
+static INLINE void
+build_masks(int c, 
+           int cdiff,
+           int dcdx,
+           int dcdy,
+           unsigned *outmask,
+           unsigned *partmask)
+{
+   __m128i cstep0 = _mm_setr_epi32(c, c+dcdx, c+dcdx*2, c+dcdx*3);
+   __m128i xdcdy = _mm_set1_epi32(dcdy);
+
+   /* Get values across the quad
+    */
+   __m128i cstep1 = _mm_add_epi32(cstep0, xdcdy);
+   __m128i cstep2 = _mm_add_epi32(cstep1, xdcdy);
+   __m128i cstep3 = _mm_add_epi32(cstep2, xdcdy);
+
+   {
+      __m128i cstep01, cstep23, result;
+
+      cstep01 = _mm_packs_epi32(cstep0, cstep1);
+      cstep23 = _mm_packs_epi32(cstep2, cstep3);
+      result = _mm_packs_epi16(cstep01, cstep23);
+
+      *outmask |= _mm_movemask_epi8(result);
+   }
+
+
+   {
+      __m128i cio4 = _mm_set1_epi32(cdiff);
+      __m128i cstep01, cstep23, result;
+
+      cstep0 = _mm_add_epi32(cstep0, cio4);
+      cstep1 = _mm_add_epi32(cstep1, cio4);
+      cstep2 = _mm_add_epi32(cstep2, cio4);
+      cstep3 = _mm_add_epi32(cstep3, cio4);
+
+      cstep01 = _mm_packs_epi32(cstep0, cstep1);
+      cstep23 = _mm_packs_epi32(cstep2, cstep3);
+      result = _mm_packs_epi16(cstep01, cstep23);
+
+      *partmask |= _mm_movemask_epi8(result);
+   }
+}
+
+
+static INLINE unsigned
+build_mask_linear(int c, int dcdx, int dcdy)
+{
+   __m128i cstep0 = _mm_setr_epi32(c, c+dcdx, c+dcdx*2, c+dcdx*3);
+   __m128i xdcdy = _mm_set1_epi32(dcdy);
+
+   /* Get values across the quad
+    */
+   __m128i cstep1 = _mm_add_epi32(cstep0, xdcdy);
+   __m128i cstep2 = _mm_add_epi32(cstep1, xdcdy);
+   __m128i cstep3 = _mm_add_epi32(cstep2, xdcdy);
+
+   /* pack pairs of results into epi16
+    */
+   __m128i cstep01 = _mm_packs_epi32(cstep0, cstep1);
+   __m128i cstep23 = _mm_packs_epi32(cstep2, cstep3);
+
+   /* pack into epi8, preserving sign bits
+    */
+   __m128i result = _mm_packs_epi16(cstep01, cstep23);
+
+   /* extract sign bits to create mask
+    */
+   return _mm_movemask_epi8(result);
+}
+
+static INLINE unsigned
+build_mask(int c, int dcdx, int dcdy)
+{
+   __m128i step = _mm_setr_epi32(0, dcdx, dcdy, dcdx + dcdy);
+   __m128i c0 = _mm_set1_epi32(c);
+
+   /* Get values across the quad
+    */
+   __m128i cstep0 = _mm_add_epi32(c0, step);
+
+   /* Scale up step for moving between quads.
+    */
+   __m128i step4 = _mm_add_epi32(step, step);
+
+   /* Get values for the remaining quads:
+    */
+   __m128i cstep1 = _mm_add_epi32(cstep0, 
+                                 _mm_shuffle_epi32(step4, _MM_SHUFFLE(1,1,1,1)));
+   __m128i cstep2 = _mm_add_epi32(cstep0,
+                                 _mm_shuffle_epi32(step4, _MM_SHUFFLE(2,2,2,2)));
+   __m128i cstep3 = _mm_add_epi32(cstep2,
+                                 _mm_shuffle_epi32(step4, _MM_SHUFFLE(1,1,1,1)));
+
+   /* pack pairs of results into epi16
+    */
+   __m128i cstep01 = _mm_packs_epi32(cstep0, cstep1);
+   __m128i cstep23 = _mm_packs_epi32(cstep2, cstep3);
+
+   /* pack into epi8, preserving sign bits
+    */
+   __m128i result = _mm_packs_epi16(cstep01, cstep23);
+
+   /* extract sign bits to create mask
+    */
+   return _mm_movemask_epi8(result);
+}
+
+#endif
+
+
+
+
 #define TAG(x) x##_1
 #define NR_PLANES 1
 #include "lp_rast_tri_tmp.h"
@@ -157,3 +289,92 @@ build_mask_linear(int c, int dcdx, int dcdy)
 #define NR_PLANES 7
 #include "lp_rast_tri_tmp.h"
 
+#define TAG(x) x##_8
+#define NR_PLANES 8
+#include "lp_rast_tri_tmp.h"
+
+
+/* Special case for 3 plane triangle which is contained entirely
+ * within a 16x16 block.
+ */
+void
+lp_rast_triangle_3_16(struct lp_rasterizer_task *task,
+                      const union lp_rast_cmd_arg arg)
+{
+   const struct lp_rast_triangle *tri = arg.triangle.tri;
+   const struct lp_rast_plane *plane = tri->plane;
+   unsigned mask = arg.triangle.plane_mask;
+   const int x = task->x + (mask & 0xf) * 16;
+   const int y = task->y + (mask >> 4) * 16;
+   unsigned outmask, inmask, partmask, partial_mask;
+   unsigned j;
+   int c[3];
+
+   outmask = 0;                 /* outside one or more trivial reject planes */
+   partmask = 0;                /* outside one or more trivial accept planes */
+
+   for (j = 0; j < 3; j++) {
+      c[j] = plane[j].c + plane[j].dcdy * y - plane[j].dcdx * x;
+
+      {
+        const int dcdx = -plane[j].dcdx * 4;
+        const int dcdy = plane[j].dcdy * 4;
+        const int cox = plane[j].eo * 4;
+        const int cio = plane[j].ei * 4 - 1;
+
+        build_masks(c[j] + cox,
+                    cio - cox,
+                    dcdx, dcdy, 
+                    &outmask,   /* sign bits from c[i][0..15] + cox */
+                    &partmask); /* sign bits from c[i][0..15] + cio */
+      }
+   }
+
+   if (outmask == 0xffff)
+      return;
+
+   /* Mask of sub-blocks which are inside all trivial accept planes:
+    */
+   inmask = ~partmask & 0xffff;
+
+   /* Mask of sub-blocks which are inside all trivial reject planes,
+    * but outside at least one trivial accept plane:
+    */
+   partial_mask = partmask & ~outmask;
+
+   assert((partial_mask & inmask) == 0);
+
+   /* Iterate over partials:
+    */
+   while (partial_mask) {
+      int i = ffs(partial_mask) - 1;
+      int ix = (i & 3) * 4;
+      int iy = (i >> 2) * 4;
+      int px = x + ix;
+      int py = y + iy; 
+      int cx[3];
+
+      partial_mask &= ~(1 << i);
+
+      for (j = 0; j < 3; j++)
+         cx[j] = (c[j] 
+                 - plane[j].dcdx * ix
+                 + plane[j].dcdy * iy);
+
+      do_block_4_3(task, tri, plane, px, py, cx);
+   }
+
+   /* Iterate over fulls: 
+    */
+   while (inmask) {
+      int i = ffs(inmask) - 1;
+      int ix = (i & 3) * 4;
+      int iy = (i >> 2) * 4;
+      int px = x + ix;
+      int py = y + iy; 
+
+      inmask &= ~(1 << i);
+
+      block_full_4(task, tri, px, py);
+   }
+}
index 43f72d8ca8f6b19a6e1d9eec096ce9b152262dd7..99a0bae45dba417bc7d0e6219a476eae5c3da966 100644 (file)
@@ -32,7 +32,7 @@
 
 
 /**
- * Prototype for a 7 plane rasterizer function.  Will codegenerate
+ * Prototype for a 8 plane rasterizer function.  Will codegenerate
  * several of these.
  *
  * XXX: Varients for more/fewer planes.
@@ -81,11 +81,14 @@ TAG(do_block_16)(struct lp_rasterizer_task *task,
    for (j = 0; j < NR_PLANES; j++) {
       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);
+      const int cox = plane[j].eo * 4;
+      const int cio = plane[j].ei * 4 - 1;
+
+      build_masks(c[j] + cox,
+                 cio - cox,
+                 dcdx, dcdy, 
+                 &outmask,   /* sign bits from c[i][0..15] + cox */
+                 &partmask); /* sign bits from c[i][0..15] + cio */
    }
 
    if (outmask == 0xffff)
@@ -102,6 +105,8 @@ TAG(do_block_16)(struct lp_rasterizer_task *task,
 
    assert((partial_mask & inmask) == 0);
 
+   LP_COUNT_ADD(nr_empty_4, util_bitcount(0xffff & ~(partial_mask | inmask)));
+
    /* Iterate over partials:
     */
    while (partial_mask) {
@@ -114,6 +119,8 @@ TAG(do_block_16)(struct lp_rasterizer_task *task,
 
       partial_mask &= ~(1 << i);
 
+      LP_COUNT(nr_partially_covered_4);
+
       for (j = 0; j < NR_PLANES; j++)
          cx[j] = (c[j] 
                  - plane[j].dcdx * ix
@@ -133,6 +140,7 @@ TAG(do_block_16)(struct lp_rasterizer_task *task,
 
       inmask &= ~(1 << i);
 
+      LP_COUNT(nr_fully_covered_4);
       block_full_4(task, tri, px, py);
    }
 }
@@ -166,11 +174,14 @@ TAG(lp_rast_triangle)(struct lp_rasterizer_task *task,
       {
         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;
-
-        outmask |= build_mask_linear(cox, dcdx, dcdy);
-        partmask |= build_mask_linear(cio, dcdx, dcdy);
+        const int cox = plane[j].eo * 16;
+        const int cio = plane[j].ei * 16 - 1;
+
+        build_masks(c[j] + cox,
+                    cio - cox,
+                    dcdx, dcdy, 
+                    &outmask,   /* sign bits from c[i][0..15] + cox */
+                    &partmask); /* sign bits from c[i][0..15] + cio */
       }
 
       j++;
@@ -190,6 +201,8 @@ TAG(lp_rast_triangle)(struct lp_rasterizer_task *task,
 
    assert((partial_mask & inmask) == 0);
 
+   LP_COUNT_ADD(nr_empty_16, util_bitcount(0xffff & ~(partial_mask | inmask)));
+
    /* Iterate over partials:
     */
    while (partial_mask) {
index f88a759fe703bf03bb4eafe21eac4c52f4869dff..15a09b71006e923972ae3e37f5659988e852f405 100644 (file)
@@ -163,12 +163,15 @@ lp_scene_reset(struct lp_scene *scene )
 
    /* Free all but last binner command lists:
     */
-   for (i = 0; i < TILES_X; i++) {
-      for (j = 0; j < TILES_Y; j++) {
+   for (i = 0; i < scene->tiles_x; i++) {
+      for (j = 0; j < scene->tiles_y; j++) {
          lp_scene_bin_reset(scene, i, j);
       }
    }
 
+   /* If there are any bins which weren't cleared by the loop above,
+    * they will be caught (on debug builds at least) by this assert:
+    */
    assert(lp_scene_is_empty(scene));
 
    /* Free all but last binned data block:
index 167cb2ee2e05cde6710f0754582715038f7e90fb..1e65a91fc67e35ba2a60db3648ebaa98c7d4ea14 100644 (file)
@@ -61,6 +61,8 @@ static const struct debug_named_value lp_debug_flags[] = {
    { "show_tiles",    DEBUG_SHOW_TILES, NULL },
    { "show_subtiles", DEBUG_SHOW_SUBTILES, NULL },
    { "counters", DEBUG_COUNTERS, NULL },
+   { "scene", DEBUG_SCENE, NULL },
+   { "fence", DEBUG_FENCE, NULL },
    DEBUG_NAMED_VALUE_END
 };
 #endif
@@ -87,7 +89,14 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
       return PIPE_MAX_SAMPLERS;
    case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
-      return PIPE_MAX_VERTEX_SAMPLERS;
+      /* At this time, the draw module and llvmpipe driver only
+       * support vertex shader texture lookups when LLVM is enabled in
+       * the draw module.
+       */
+      if (debug_get_bool_option("DRAW_USE_LLVM", TRUE))
+         return PIPE_MAX_VERTEX_SAMPLERS;
+      else
+         return 0;
    case PIPE_CAP_MAX_COMBINED_SAMPLERS:
       return PIPE_MAX_SAMPLERS + PIPE_MAX_VERTEX_SAMPLERS;
    case PIPE_CAP_NPOT_TEXTURES:
@@ -230,6 +239,7 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen,
    assert(target == PIPE_BUFFER ||
           target == PIPE_TEXTURE_1D ||
           target == PIPE_TEXTURE_2D ||
+          target == PIPE_TEXTURE_RECT ||
           target == PIPE_TEXTURE_3D ||
           target == PIPE_TEXTURE_CUBE);
 
@@ -314,6 +324,51 @@ llvmpipe_destroy_screen( struct pipe_screen *_screen )
 
 
 
+
+/**
+ * Fence reference counting.
+ */
+static void
+llvmpipe_fence_reference(struct pipe_screen *screen,
+                         struct pipe_fence_handle **ptr,
+                         struct pipe_fence_handle *fence)
+{
+   struct lp_fence **old = (struct lp_fence **) ptr;
+   struct lp_fence *f = (struct lp_fence *) fence;
+
+   lp_fence_reference(old, f);
+}
+
+
+/**
+ * Has the fence been executed/finished?
+ */
+static int
+llvmpipe_fence_signalled(struct pipe_screen *screen,
+                         struct pipe_fence_handle *fence,
+                         unsigned flag)
+{
+   struct lp_fence *f = (struct lp_fence *) fence;
+   return lp_fence_signalled(f);
+}
+
+
+/**
+ * Wait for the fence to finish.
+ */
+static int
+llvmpipe_fence_finish(struct pipe_screen *screen,
+                      struct pipe_fence_handle *fence_handle,
+                      unsigned flag)
+{
+   struct lp_fence *f = (struct lp_fence *) fence_handle;
+
+   lp_fence_wait(f);
+   return 0;
+}
+
+
+
 /**
  * Create a new pipe_screen object
  * Note: we're not presently subclassing pipe_screen (no llvmpipe_screen).
@@ -351,9 +406,11 @@ llvmpipe_create_screen(struct sw_winsys *winsys)
 
    screen->base.context_create = llvmpipe_create_context;
    screen->base.flush_frontbuffer = llvmpipe_flush_frontbuffer;
+   screen->base.fence_reference = llvmpipe_fence_reference;
+   screen->base.fence_signalled = llvmpipe_fence_signalled;
+   screen->base.fence_finish = llvmpipe_fence_finish;
 
    llvmpipe_init_screen_resource_funcs(&screen->base);
-   llvmpipe_init_screen_fence_funcs(&screen->base);
 
    lp_jit_screen_init(screen);
 
index 556e571585dc948268415dccf01fea6a5d95c6e4..3da9097154ef630a918087e6ac8cc882cf398c57 100644 (file)
@@ -275,9 +275,10 @@ set_scene_state( struct lp_setup_context *setup,
 void
 lp_setup_flush( struct lp_setup_context *setup,
                 unsigned flags,
-                struct pipe_fence_handle **fence)
+                struct pipe_fence_handle **fence,
+                const char *reason)
 {
-   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
+   LP_DBG(DEBUG_SETUP, "%s %s\n", __FUNCTION__, reason);
 
    if (setup->scene) {
       if (fence) {
@@ -287,6 +288,8 @@ lp_setup_flush( struct lp_setup_context *setup,
          *fence = lp_setup_fence( setup );
       }
 
+      if (setup->scene->fence)
+         setup->scene->fence->issued = TRUE;
    }
 
    set_scene_state( setup, SETUP_FLUSHED );
@@ -312,6 +315,11 @@ lp_setup_bind_framebuffer( struct lp_setup_context *setup,
     * scene.
     */
    util_copy_framebuffer_state(&setup->fb, fb);
+   setup->framebuffer.x0 = 0;
+   setup->framebuffer.y0 = 0;
+   setup->framebuffer.x1 = fb->width-1;
+   setup->framebuffer.y1 = fb->height-1;
+   setup->dirty |= LP_SETUP_NEW_SCISSOR;
 }
 
 
@@ -469,11 +477,35 @@ lp_setup_set_triangle_state( struct lp_setup_context *setup,
    setup->ccw_is_frontface = ccw_is_frontface;
    setup->cullmode = cull_mode;
    setup->triangle = first_triangle;
-   setup->scissor_test = scissor;
    setup->pixel_offset = gl_rasterization_rules ? 0.5f : 0.0f;
+
+   if (setup->scissor_test != scissor) {
+      setup->dirty |= LP_SETUP_NEW_SCISSOR;
+      setup->scissor_test = scissor;
+   }
 }
 
+void 
+lp_setup_set_line_state( struct lp_setup_context *setup,
+                        float line_width)
+{
+   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
 
+   setup->line_width = line_width;
+}
+
+void 
+lp_setup_set_point_state( struct lp_setup_context *setup,
+                          float point_size,                          
+                          boolean point_size_per_vertex,
+                          uint sprite)
+{
+   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
+
+   setup->point_size = point_size;
+   setup->sprite = sprite;
+   setup->point_size_per_vertex = point_size_per_vertex;
+}
 
 void
 lp_setup_set_fs_inputs( struct lp_setup_context *setup,
@@ -559,10 +591,11 @@ lp_setup_set_scissor( struct lp_setup_context *setup,
 
    assert(scissor);
 
-   if (memcmp(&setup->scissor.current, scissor, sizeof(*scissor)) != 0) {
-      setup->scissor.current = *scissor; /* struct copy */
-      setup->dirty |= LP_SETUP_NEW_SCISSOR;
-   }
+   setup->scissor.x0 = scissor->minx;
+   setup->scissor.x1 = scissor->maxx-1;
+   setup->scissor.y0 = scissor->miny;
+   setup->scissor.y1 = scissor->maxy-1;
+   setup->dirty |= LP_SETUP_NEW_SCISSOR;
 }
 
 
@@ -713,6 +746,12 @@ lp_setup_update_state( struct lp_setup_context *setup )
     */
    {
       struct llvmpipe_context *lp = llvmpipe_context(scene->pipe);
+
+      /* Will probably need to move this somewhere else, just need  
+       * to know about vertex shader point size attribute.
+       */
+      setup->psize = lp->psize_slot;
+
       if (lp->dirty) {
          llvmpipe_update_derived(lp);
       }
@@ -806,6 +845,14 @@ lp_setup_update_state( struct lp_setup_context *setup )
       }
    }
 
+   if (setup->dirty & LP_SETUP_NEW_SCISSOR) {
+      setup->draw_region = setup->framebuffer;
+      if (setup->scissor_test) {
+         u_rect_possible_intersection(&setup->scissor,
+                                      &setup->draw_region);
+      }
+   }
+                                      
    setup->dirty = 0;
 
    assert(setup->fs.stored);
index 73b1c85325a4ec5eb883f84dfe8daf094827b683..821ebb1087dcd70f4a33942facfcce9963ee06ae 100644 (file)
@@ -85,7 +85,8 @@ lp_setup_fence( struct lp_setup_context *setup );
 void
 lp_setup_flush( struct lp_setup_context *setup,
                 unsigned flags,
-                struct pipe_fence_handle **fence);
+                struct pipe_fence_handle **fence,
+                const char *reason);
 
 
 void
@@ -99,6 +100,16 @@ lp_setup_set_triangle_state( struct lp_setup_context *setup,
                              boolean scissor,
                              boolean gl_rasterization_rules );
 
+void 
+lp_setup_set_line_state( struct lp_setup_context *setup,
+                         float line_width);
+
+void 
+lp_setup_set_point_state( struct lp_setup_context *setup,
+                          float point_size,                          
+                          boolean point_size_per_vertex,
+                          uint sprite);
+
 void
 lp_setup_set_fs_inputs( struct lp_setup_context *setup,
                         const struct lp_shader_input *interp,
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_coef.c b/src/gallium/drivers/llvmpipe/lp_setup_coef.c
new file mode 100644 (file)
index 0000000..95e3e8f
--- /dev/null
@@ -0,0 +1,258 @@
+/**************************************************************************
+ *
+ * Copyright 2010, VMware.
+ * 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.
+ *
+ **************************************************************************/
+
+/*
+ * Binning code for triangles
+ */
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "lp_perf.h"
+#include "lp_setup_context.h"
+#include "lp_setup_coef.h"
+#include "lp_rast.h"
+#include "lp_state_fs.h"
+
+#if !defined(PIPE_ARCH_SSE)
+
+/**
+ * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
+ */
+static void constant_coef( struct lp_rast_shader_inputs *inputs,
+                           unsigned slot,
+                          const float value,
+                           unsigned i )
+{
+   inputs->a0[slot][i] = value;
+   inputs->dadx[slot][i] = 0.0f;
+   inputs->dady[slot][i] = 0.0f;
+}
+
+
+
+static void linear_coef( struct lp_rast_shader_inputs *inputs,
+                         const struct lp_tri_info *info,
+                         unsigned slot,
+                         unsigned vert_attr,
+                         unsigned i)
+{
+   float a0 = info->v0[vert_attr][i];
+   float a1 = info->v1[vert_attr][i];
+   float a2 = info->v2[vert_attr][i];
+
+   float da01 = a0 - a1;
+   float da20 = a2 - a0;
+   float dadx = (da01 * info->dy20_ooa - info->dy01_ooa * da20);
+   float dady = (da20 * info->dx01_ooa - info->dx20_ooa * da01);
+
+   inputs->dadx[slot][i] = dadx;
+   inputs->dady[slot][i] = dady;
+
+   /* calculate a0 as the value which would be sampled for the
+    * fragment at (0,0), taking into account that we want to sample at
+    * pixel centers, in other words (0.5, 0.5).
+    *
+    * this is neat but unfortunately not a good way to do things for
+    * triangles with very large values of dadx or dady as it will
+    * result in the subtraction and re-addition from a0 of a very
+    * large number, which means we'll end up loosing a lot of the
+    * fractional bits and precision from a0.  the way to fix this is
+    * to define a0 as the sample at a pixel center somewhere near vmin
+    * instead - i'll switch to this later.
+    */
+   inputs->a0[slot][i] = a0 - (dadx * info->x0_center +
+                                  dady * info->y0_center);
+}
+
+
+/**
+ * Compute a0, dadx and dady for a perspective-corrected interpolant,
+ * for a triangle.
+ * We basically multiply the vertex value by 1/w before computing
+ * the plane coefficients (a0, dadx, dady).
+ * Later, when we compute the value at a particular fragment position we'll
+ * divide the interpolated value by the interpolated W at that fragment.
+ */
+static void perspective_coef( struct lp_rast_shader_inputs *inputs,
+                              const struct lp_tri_info *info,
+                              unsigned slot,
+                             unsigned vert_attr,
+                              unsigned i)
+{
+   /* premultiply by 1/w  (v[0][3] is always 1/w):
+    */
+   float a0 = info->v0[vert_attr][i] * info->v0[0][3];
+   float a1 = info->v1[vert_attr][i] * info->v1[0][3];
+   float a2 = info->v2[vert_attr][i] * info->v2[0][3];
+   float da01 = a0 - a1;
+   float da20 = a2 - a0;
+   float dadx = da01 * info->dy20_ooa - info->dy01_ooa * da20;
+   float dady = da20 * info->dx01_ooa - info->dx20_ooa * da01;
+
+   inputs->dadx[slot][i] = dadx;
+   inputs->dady[slot][i] = dady;
+   inputs->a0[slot][i] = a0 - (dadx * info->x0_center +
+                                  dady * info->y0_center);
+}
+
+
+/**
+ * Special coefficient setup for gl_FragCoord.
+ * X and Y are trivial
+ * Z and W are copied from position_coef which should have already been computed.
+ * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
+ */
+static void
+setup_fragcoord_coef(struct lp_rast_shader_inputs *inputs,
+                     const struct lp_tri_info *info,
+                     unsigned slot,
+                     unsigned usage_mask)
+{
+   /*X*/
+   if (usage_mask & TGSI_WRITEMASK_X) {
+      inputs->a0[slot][0] = 0.0;
+      inputs->dadx[slot][0] = 1.0;
+      inputs->dady[slot][0] = 0.0;
+   }
+
+   /*Y*/
+   if (usage_mask & TGSI_WRITEMASK_Y) {
+      inputs->a0[slot][1] = 0.0;
+      inputs->dadx[slot][1] = 0.0;
+      inputs->dady[slot][1] = 1.0;
+   }
+
+   /*Z*/
+   if (usage_mask & TGSI_WRITEMASK_Z) {
+      linear_coef(inputs, info, slot, 0, 2);
+   }
+
+   /*W*/
+   if (usage_mask & TGSI_WRITEMASK_W) {
+      linear_coef(inputs, info, slot, 0, 3);
+   }
+}
+
+
+/**
+ * Setup the fragment input attribute with the front-facing value.
+ * \param frontface  is the triangle front facing?
+ */
+static void setup_facing_coef( struct lp_rast_shader_inputs *inputs,
+                               unsigned slot,
+                               boolean frontface,
+                               unsigned usage_mask)
+{
+   /* convert TRUE to 1.0 and FALSE to -1.0 */
+   if (usage_mask & TGSI_WRITEMASK_X)
+      constant_coef( inputs, slot, 2.0f * frontface - 1.0f, 0 );
+
+   if (usage_mask & TGSI_WRITEMASK_Y)
+      constant_coef( inputs, slot, 0.0f, 1 ); /* wasted */
+
+   if (usage_mask & TGSI_WRITEMASK_Z)
+      constant_coef( inputs, slot, 0.0f, 2 ); /* wasted */
+
+   if (usage_mask & TGSI_WRITEMASK_W)
+      constant_coef( inputs, slot, 0.0f, 3 ); /* wasted */
+}
+
+
+/**
+ * Compute the tri->coef[] array dadx, dady, a0 values.
+ */
+void lp_setup_tri_coef( struct lp_setup_context *setup,
+                       struct lp_rast_shader_inputs *inputs,
+                       const struct lp_tri_info *info)
+{
+   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;
+
+      switch (setup->fs.input[slot].interp) {
+      case LP_INTERP_CONSTANT:
+         if (setup->flatshade_first) {
+            for (i = 0; i < NUM_CHANNELS; i++)
+               if (usage_mask & (1 << i))
+                  constant_coef(inputs, slot+1, info->v0[vert_attr][i], i);
+         }
+         else {
+            for (i = 0; i < NUM_CHANNELS; i++)
+               if (usage_mask & (1 << i))
+                  constant_coef(inputs, slot+1, info->v2[vert_attr][i], i);
+         }
+         break;
+
+      case LP_INTERP_LINEAR:
+         for (i = 0; i < NUM_CHANNELS; i++)
+            if (usage_mask & (1 << i))
+               linear_coef(inputs, info, slot+1, vert_attr, i);
+         break;
+
+      case LP_INTERP_PERSPECTIVE:
+         for (i = 0; i < NUM_CHANNELS; i++)
+            if (usage_mask & (1 << i))
+               perspective_coef(inputs, info, slot+1, vert_attr, i);
+         fragcoord_usage_mask |= TGSI_WRITEMASK_W;
+         break;
+
+      case LP_INTERP_POSITION:
+         /*
+          * The generated pixel interpolators will pick up the coeffs from
+          * slot 0, so all need to ensure that the usage mask is covers all
+          * usages.
+          */
+         fragcoord_usage_mask |= usage_mask;
+         break;
+
+      case LP_INTERP_FACING:
+         setup_facing_coef(inputs, slot+1, info->frontfacing, usage_mask);
+         break;
+
+      default:
+         assert(0);
+      }
+   }
+
+   /* The internal position input is in slot zero:
+    */
+   setup_fragcoord_coef(inputs, info, 0, fragcoord_usage_mask);
+}
+
+#else
+extern void lp_setup_coef_dummy(void);
+void lp_setup_coef_dummy(void)
+{
+}
+
+#endif
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_coef.h b/src/gallium/drivers/llvmpipe/lp_setup_coef.h
new file mode 100644 (file)
index 0000000..d68b39c
--- /dev/null
@@ -0,0 +1,61 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+/**
+ * The setup code is concerned with point/line/triangle setup and
+ * putting commands/data into the bins.
+ */
+
+
+#ifndef LP_SETUP_COEF_H
+#define LP_SETUP_COEF_H
+
+
+struct lp_tri_info {
+
+   float x0_center;
+   float y0_center;
+
+   /* turn these into an aligned float[4] */
+   float dy01_ooa;
+   float dy20_ooa;
+   float dx01_ooa;
+   float dx20_ooa;
+
+   const float (*v0)[4];
+   const float (*v1)[4];
+   const float (*v2)[4];
+
+   boolean frontfacing;                /* remove eventually */
+};
+
+void lp_setup_tri_coef( struct lp_setup_context *setup,
+                       struct lp_rast_shader_inputs *inputs,
+                       const struct lp_tri_info *info);
+
+#endif
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_coef_intrin.c b/src/gallium/drivers/llvmpipe/lp_setup_coef_intrin.c
new file mode 100644 (file)
index 0000000..73fb705
--- /dev/null
@@ -0,0 +1,207 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware.
+ * 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.
+ *
+ **************************************************************************/
+
+/*
+ * Binning code for triangles
+ */
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "lp_perf.h"
+#include "lp_setup_context.h"
+#include "lp_setup_coef.h"
+#include "lp_rast.h"
+
+#if defined(PIPE_ARCH_SSE)
+#include <emmintrin.h>
+
+
+static void constant_coef4( struct lp_rast_shader_inputs *inputs,
+                           const struct lp_tri_info *info,
+                           unsigned slot,
+                           const float *attr)
+{
+   *(__m128 *)inputs->a0[slot]   = *(__m128 *)attr;
+   *(__m128 *)inputs->dadx[slot] = _mm_set1_ps(0.0);
+   *(__m128 *)inputs->dady[slot] = _mm_set1_ps(0.0);
+}
+
+
+
+/**
+ * Setup the fragment input attribute with the front-facing value.
+ * \param frontface  is the triangle front facing?
+ */
+static void setup_facing_coef( struct lp_rast_shader_inputs *inputs,
+                              const struct lp_tri_info *info,
+                              unsigned slot )
+{
+   /* XXX: just pass frontface directly to the shader, don't bother
+    * treating it as an input.
+    */
+   __m128 a0 = _mm_setr_ps(info->frontfacing ? 1.0 : -1.0,
+                          0, 0, 0);
+
+   *(__m128 *)inputs->a0[slot]   = a0;
+   *(__m128 *)inputs->dadx[slot] = _mm_set1_ps(0.0);
+   *(__m128 *)inputs->dady[slot] = _mm_set1_ps(0.0);
+}
+
+
+
+static void calc_coef4( struct lp_rast_shader_inputs *inputs,
+                       const struct lp_tri_info *info,
+                       unsigned slot,
+                       __m128 a0,
+                       __m128 a1,
+                       __m128 a2)
+{
+   __m128 da01          = _mm_sub_ps(a0, a1);
+   __m128 da20          = _mm_sub_ps(a2, a0);
+
+   __m128 da01_dy20_ooa = _mm_mul_ps(da01, _mm_set1_ps(info->dy20_ooa));
+   __m128 da20_dy01_ooa = _mm_mul_ps(da20, _mm_set1_ps(info->dy01_ooa));   
+   __m128 dadx          = _mm_sub_ps(da01_dy20_ooa, da20_dy01_ooa);
+
+   __m128 da01_dx20_ooa = _mm_mul_ps(da01, _mm_set1_ps(info->dx20_ooa));
+   __m128 da20_dx01_ooa = _mm_mul_ps(da20, _mm_set1_ps(info->dx01_ooa));
+   __m128 dady          = _mm_sub_ps(da20_dx01_ooa, da01_dx20_ooa);
+
+   __m128 dadx_x0       = _mm_mul_ps(dadx, _mm_set1_ps(info->x0_center));
+   __m128 dady_y0       = _mm_mul_ps(dady, _mm_set1_ps(info->y0_center));
+   __m128 attr_v0       = _mm_add_ps(dadx_x0, dady_y0);
+   __m128 attr_0        = _mm_sub_ps(a0, attr_v0);
+
+   *(__m128 *)inputs->a0[slot]   = attr_0;
+   *(__m128 *)inputs->dadx[slot] = dadx;
+   *(__m128 *)inputs->dady[slot] = dady;
+}
+
+
+static void linear_coef( struct lp_rast_shader_inputs *inputs,
+                         const struct lp_tri_info *info,
+                         unsigned slot,
+                         unsigned vert_attr)
+{
+   __m128 a0 = *(const __m128 *)info->v0[vert_attr];
+   __m128 a1 = *(const __m128 *)info->v1[vert_attr];
+   __m128 a2 = *(const __m128 *)info->v2[vert_attr];
+
+   calc_coef4(inputs, info, slot, a0, a1, a2);
+}
+
+
+
+/**
+ * Compute a0, dadx and dady for a perspective-corrected interpolant,
+ * for a triangle.
+ * We basically multiply the vertex value by 1/w before computing
+ * the plane coefficients (a0, dadx, dady).
+ * Later, when we compute the value at a particular fragment position we'll
+ * divide the interpolated value by the interpolated W at that fragment.
+ */
+static void perspective_coef( struct lp_rast_shader_inputs *inputs,
+                              const struct lp_tri_info *info,
+                              unsigned slot,
+                             unsigned vert_attr)
+{
+   /* premultiply by 1/w  (v[0][3] is always 1/w):
+    */
+   __m128 a0 = *(const __m128 *)info->v0[vert_attr];
+   __m128 a1 = *(const __m128 *)info->v1[vert_attr];
+   __m128 a2 = *(const __m128 *)info->v2[vert_attr];
+
+   __m128 a0_oow = _mm_mul_ps(a0, _mm_set1_ps(info->v0[0][3]));
+   __m128 a1_oow = _mm_mul_ps(a1, _mm_set1_ps(info->v1[0][3]));
+   __m128 a2_oow = _mm_mul_ps(a2, _mm_set1_ps(info->v2[0][3]));
+
+   calc_coef4(inputs, info, slot, a0_oow, a1_oow, a2_oow);
+}
+
+
+
+
+
+/**
+ * Compute the inputs-> dadx, dady, a0 values.
+ */
+void lp_setup_tri_coef( struct lp_setup_context *setup,
+                       struct lp_rast_shader_inputs *inputs,
+                       const struct lp_tri_info *info)
+{
+   unsigned slot;
+
+   /* The internal position input is in slot zero:
+    */
+   linear_coef(inputs, info, 0, 0);
+
+   /* 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;
+
+      switch (setup->fs.input[slot].interp) {
+      case LP_INTERP_CONSTANT:
+         if (setup->flatshade_first) {
+           constant_coef4(inputs, info, slot+1, info->v0[vert_attr]);
+         }
+         else {
+           constant_coef4(inputs, info, slot+1, info->v2[vert_attr]);
+         }
+         break;
+
+      case LP_INTERP_LINEAR:
+        linear_coef(inputs, info, slot+1, vert_attr);
+         break;
+
+      case LP_INTERP_PERSPECTIVE:
+        perspective_coef(inputs, info, slot+1, vert_attr);
+         break;
+
+      case LP_INTERP_POSITION:
+         /*
+          * The generated pixel interpolators will pick up the coeffs from
+          * slot 0.
+          */
+         break;
+
+      case LP_INTERP_FACING:
+         setup_facing_coef(inputs, info, slot+1);
+         break;
+
+      default:
+         assert(0);
+      }
+   }
+}
+
+#else
+extern void lp_setup_coef_dummy(void);
+void lp_setup_coef_dummy(void)
+{
+}
+#endif
index a0606f503408e882db84b176b457f1c450cb5825..877a492c6d8e30190541816a37fb6f4718dc687a 100644 (file)
@@ -41,6 +41,7 @@
 #include "lp_scene.h"
 
 #include "draw/draw_vbuf.h"
+#include "util/u_rect.h"
 
 #define LP_SETUP_NEW_FS          0x01
 #define LP_SETUP_NEW_CONSTANTS   0x02
@@ -73,6 +74,7 @@ struct lp_setup_context
    uint prim;
    uint vertex_size;
    uint nr_vertices;
+   uint sprite;
    uint vertex_buffer_size;
    void *vertex_buffer;
 
@@ -88,10 +90,17 @@ struct lp_setup_context
    boolean flatshade_first;
    boolean ccw_is_frontface;
    boolean scissor_test;
+   boolean point_size_per_vertex;
    unsigned cullmode;
    float pixel_offset;
+   float line_width;
+   float point_size;
+   float psize;
 
    struct pipe_framebuffer_state fb;
+   struct u_rect framebuffer;
+   struct u_rect scissor;
+   struct u_rect draw_region;   /* intersection of fb & scissor */
 
    struct {
       unsigned flags;
@@ -127,9 +136,6 @@ struct lp_setup_context
       uint8_t *stored;
    } blend_color;
 
-   struct {
-      struct pipe_scissor_state current;
-   } scissor;
 
    unsigned dirty;   /**< bitmask of LP_SETUP_NEW_x bits */
 
@@ -158,4 +164,29 @@ void lp_setup_update_state( struct lp_setup_context *setup );
 
 void lp_setup_destroy( struct lp_setup_context *setup );
 
+void
+lp_setup_print_triangle(struct lp_setup_context *setup,
+                        const float (*v0)[4],
+                        const float (*v1)[4],
+                        const float (*v2)[4]);
+
+void
+lp_setup_print_vertex(struct lp_setup_context *setup,
+                      const char *name,
+                      const float (*v)[4]);
+
+
+struct lp_rast_triangle *
+lp_setup_alloc_triangle(struct lp_scene *scene,
+                        unsigned nr_inputs,
+                        unsigned nr_planes,
+                        unsigned *tri_size);
+
+void
+lp_setup_bin_triangle( struct lp_setup_context *setup,
+                       struct lp_rast_triangle *tri,
+                       const struct u_rect *bbox,
+                       int nr_planes );
+
 #endif
+
index be41c44e6f5d51444aa7a286199137fb4b1e8732..ce2da55cf49d32177a3ce03d092cdf74ac078313 100644 (file)
  * Binning code for lines
  */
 
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "lp_perf.h"
 #include "lp_setup_context.h"
+#include "lp_rast.h"
+#include "lp_state_fs.h"
 
-static void line_nop( struct lp_setup_context *setup,
-                      const float (*v0)[4],
-                      const float (*v1)[4] )
+#define NUM_CHANNELS 4
+
+struct lp_line_info {
+
+   float dx;
+   float dy;
+   float oneoverarea;
+
+   const float (*v1)[4];
+   const float (*v2)[4];
+};
+
+
+/**
+ * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
+ */
+static void constant_coef( struct lp_setup_context *setup,
+                           struct lp_rast_triangle *tri,
+                           unsigned slot,
+                           const float value,
+                           unsigned i )
+{
+   tri->inputs.a0[slot][i] = value;
+   tri->inputs.dadx[slot][i] = 0.0f;
+   tri->inputs.dady[slot][i] = 0.0f;
+}
+
+
+/**
+ * Compute a0, dadx and dady for a linearly interpolated coefficient,
+ * for a triangle.
+ */
+static void linear_coef( struct lp_setup_context *setup,
+                         struct lp_rast_triangle *tri,
+                         struct lp_line_info *info,
+                         unsigned slot,
+                         unsigned vert_attr,
+                         unsigned i)
+{
+   float a1 = info->v1[vert_attr][i]; 
+   float a2 = info->v2[vert_attr][i];
+      
+   float da21 = a1 - a2;   
+   float dadx = da21 * info->dx * info->oneoverarea;
+   float dady = da21 * info->dy * info->oneoverarea;
+
+   tri->inputs.dadx[slot][i] = dadx;
+   tri->inputs.dady[slot][i] = dady;  
+   
+   tri->inputs.a0[slot][i] = (a1 -
+                              (dadx * (info->v1[0][0] - setup->pixel_offset) +
+                               dady * (info->v1[0][1] - setup->pixel_offset)));
+}
+
+
+/**
+ * Compute a0, dadx and dady for a perspective-corrected interpolant,
+ * for a triangle.
+ * We basically multiply the vertex value by 1/w before computing
+ * the plane coefficients (a0, dadx, dady).
+ * Later, when we compute the value at a particular fragment position we'll
+ * divide the interpolated value by the interpolated W at that fragment.
+ */
+static void perspective_coef( struct lp_setup_context *setup,
+                              struct lp_rast_triangle *tri,
+                              struct lp_line_info *info,
+                              unsigned slot,
+                              unsigned vert_attr,
+                              unsigned i)
+{
+   /* premultiply by 1/w  (v[0][3] is always 1/w):
+    */
+   float a1 = info->v1[vert_attr][i] * info->v1[0][3];
+   float a2 = info->v2[vert_attr][i] * info->v2[0][3];
+
+   float da21 = a1 - a2;   
+   float dadx = da21 * info->dx * info->oneoverarea;
+   float dady = da21 * info->dy * info->oneoverarea;
+
+   tri->inputs.dadx[slot][i] = dadx;
+   tri->inputs.dady[slot][i] = dady;
+   
+   tri->inputs.a0[slot][i] = (a1 -
+                              (dadx * (info->v1[0][0] - setup->pixel_offset) +
+                               dady * (info->v1[0][1] - setup->pixel_offset)));
+}
+
+static void
+setup_fragcoord_coef( struct lp_setup_context *setup,
+                      struct lp_rast_triangle *tri,
+                      struct lp_line_info *info,
+                      unsigned slot,
+                      unsigned usage_mask)
+{
+   /*X*/
+   if (usage_mask & TGSI_WRITEMASK_X) {
+      tri->inputs.a0[slot][0] = 0.0;
+      tri->inputs.dadx[slot][0] = 1.0;
+      tri->inputs.dady[slot][0] = 0.0;
+   }
+
+   /*Y*/
+   if (usage_mask & TGSI_WRITEMASK_Y) {
+      tri->inputs.a0[slot][1] = 0.0;
+      tri->inputs.dadx[slot][1] = 0.0;
+      tri->inputs.dady[slot][1] = 1.0;
+   }
+
+   /*Z*/
+   if (usage_mask & TGSI_WRITEMASK_Z) {
+      linear_coef(setup, tri, info, slot, 0, 2);
+   }
+
+   /*W*/
+   if (usage_mask & TGSI_WRITEMASK_W) {
+      linear_coef(setup, tri, info, slot, 0, 3);
+   }
+}
+
+/**
+ * Compute the tri->coef[] array dadx, dady, a0 values.
+ */
+static void setup_line_coefficients( struct lp_setup_context *setup,
+                                     struct lp_rast_triangle *tri,
+                                     struct lp_line_info *info)
+{
+   unsigned fragcoord_usage_mask = TGSI_WRITEMASK_XYZ;
+   unsigned slot;
+
+   /* 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:
+         if (setup->flatshade_first) {
+            for (i = 0; i < NUM_CHANNELS; i++)
+               if (usage_mask & (1 << i))
+                  constant_coef(setup, tri, slot+1, info->v1[vert_attr][i], i);
+         }
+         else {
+            for (i = 0; i < NUM_CHANNELS; i++)
+               if (usage_mask & (1 << i))
+                  constant_coef(setup, tri, slot+1, info->v2[vert_attr][i], i);
+         }
+         break;
+
+      case LP_INTERP_LINEAR:
+         for (i = 0; i < NUM_CHANNELS; i++)
+            if (usage_mask & (1 << i))
+               linear_coef(setup, tri, info, slot+1, vert_attr, i);
+         break;
+
+      case LP_INTERP_PERSPECTIVE:
+         for (i = 0; i < NUM_CHANNELS; i++)
+            if (usage_mask & (1 << i))
+               perspective_coef(setup, tri, info, slot+1, vert_attr, i);
+         fragcoord_usage_mask |= TGSI_WRITEMASK_W;
+         break;
+
+      case LP_INTERP_POSITION:
+         /*
+          * The generated pixel interpolators will pick up the coeffs from
+          * slot 0, so all need to ensure that the usage mask is covers all
+          * usages.
+          */
+         fragcoord_usage_mask |= usage_mask;
+         break;
+
+      default:
+         assert(0);
+      }
+   }
+
+   /* The internal position input is in slot zero:
+    */
+   setup_fragcoord_coef(setup, tri, info, 0,
+                        fragcoord_usage_mask);
+}
+
+
+
+static INLINE int subpixel_snap( float a )
+{
+   return util_iround(FIXED_ONE * a);
+}
+
+
+/**
+ * Print line vertex attribs (for debug).
+ */
+static void
+print_line(struct lp_setup_context *setup,
+           const float (*v1)[4],
+           const float (*v2)[4])
+{
+   uint i;
+
+   debug_printf("llvmpipe line\n");
+   for (i = 0; i < 1 + setup->fs.nr_inputs; i++) {
+      debug_printf("  v1[%d]:  %f %f %f %f\n", i,
+                   v1[i][0], v1[i][1], v1[i][2], v1[i][3]);
+   }
+   for (i = 0; i < 1 + setup->fs.nr_inputs; i++) {
+      debug_printf("  v2[%d]:  %f %f %f %f\n", i,
+                   v2[i][0], v2[i][1], v2[i][2], v2[i][3]);
+   }
+}
+
+
+static INLINE boolean sign(float x){
+   return x >= 0;  
+}  
+
+
+/* Used on positive floats only:
+ */
+static INLINE float fracf(float f)
 {
+   return f - floorf(f);
 }
 
 
-void 
-lp_setup_choose_line( struct lp_setup_context *setup )
+
+static void
+lp_setup_line( struct lp_setup_context *setup,
+               const float (*v1)[4],
+               const float (*v2)[4])
 {
-   setup->line = line_nop;
+   struct lp_scene *scene = lp_setup_get_current_scene(setup);
+   struct lp_rast_triangle *line;
+   struct lp_line_info info;
+   float width = MAX2(1.0, setup->line_width);
+   struct u_rect bbox;
+   unsigned tri_bytes;
+   int x[4]; 
+   int y[4];
+   int i;
+   int nr_planes = 4;
+   
+   /* linewidth should be interpreted as integer */
+   int fixed_width = util_iround(width) * FIXED_ONE;
+
+   float x_offset=0;
+   float y_offset=0;
+   float x_offset_end=0;
+   float y_offset_end=0;
+      
+   float x1diff;
+   float y1diff;
+   float x2diff;
+   float y2diff;
+   float dx, dy;
+
+   boolean draw_start;
+   boolean draw_end;
+   boolean will_draw_start;
+   boolean will_draw_end;
+
+   if (0)
+      print_line(setup, v1, v2);
+
+   if (setup->scissor_test) {
+      nr_planes = 8;
+   }
+   else {
+      nr_planes = 4;
+   }
+
+
+   dx = v1[0][0] - v2[0][0];
+   dy = v1[0][1] - v2[0][1];
+  
+   /* X-MAJOR LINE */
+   if (fabsf(dx) >= fabsf(dy)) {
+      float dydx = dy / dx;
+
+      x1diff = v1[0][0] - (float) floor(v1[0][0]) - 0.5;
+      y1diff = v1[0][1] - (float) floor(v1[0][1]) - 0.5;
+      x2diff = v2[0][0] - (float) floor(v2[0][0]) - 0.5;
+      y2diff = v2[0][1] - (float) floor(v2[0][1]) - 0.5;
+
+      if (y2diff==-0.5 && dy<0){
+         y2diff = 0.5;
+      }
+      
+      /* 
+       * Diamond exit rule test for starting point 
+       */    
+      if (fabsf(x1diff) + fabsf(y1diff) < 0.5) {
+         draw_start = TRUE;
+      }
+      else if (sign(x1diff) == sign(-dx)) {
+         draw_start = FALSE;
+      }
+      else if (sign(-y1diff) != sign(dy)) {
+         draw_start = TRUE;
+      }
+      else {
+         /* do intersection test */
+         float yintersect = fracf(v1[0][1]) + x1diff * dydx;
+         draw_start = (yintersect < 1.0 && yintersect > 0.0);
+      }
+
+
+      /* 
+       * Diamond exit rule test for ending point 
+       */    
+      if (fabsf(x2diff) + fabsf(y2diff) < 0.5) {
+         draw_end = FALSE;
+      }
+      else if (sign(x2diff) != sign(-dx)) {
+         draw_end = FALSE;
+      }
+      else if (sign(-y2diff) == sign(dy)) {
+         draw_end = TRUE;
+      }
+      else {
+         /* do intersection test */
+         float yintersect = fracf(v2[0][1]) + x2diff * dydx;
+         draw_end = (yintersect < 1.0 && yintersect > 0.0);
+      }
+
+      /* Are we already drawing start/end?
+       */
+      will_draw_start = sign(-x1diff) != sign(dx);
+      will_draw_end = (sign(x2diff) == sign(-dx)) || x2diff==0;
+
+      if (dx < 0) {
+         /* if v2 is to the right of v1, swap pointers */
+         const float (*temp)[4] = v1;
+         v1 = v2;
+         v2 = temp;
+         dx = -dx;
+         dy = -dy;
+         /* Otherwise shift planes appropriately */
+         if (will_draw_start != draw_start) {
+            x_offset_end = - x1diff - 0.5;
+            y_offset_end = x_offset_end * dydx;
+
+         }
+         if (will_draw_end != draw_end) {
+            x_offset = - x2diff - 0.5;
+            y_offset = x_offset * dydx;
+         }
+
+      }
+      else{
+         /* Otherwise shift planes appropriately */
+         if (will_draw_start != draw_start) {
+            x_offset = - x1diff + 0.5;
+            y_offset = x_offset * dydx;
+         }
+         if (will_draw_end != draw_end) {
+            x_offset_end = - x2diff + 0.5;
+            y_offset_end = x_offset_end * dydx;
+         }
+      }
+  
+      /* x/y positions in fixed point */
+      x[0] = subpixel_snap(v1[0][0] + x_offset     - setup->pixel_offset);
+      x[1] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset);
+      x[2] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset);
+      x[3] = subpixel_snap(v1[0][0] + x_offset     - setup->pixel_offset);
+      
+      y[0] = subpixel_snap(v1[0][1] + y_offset     - setup->pixel_offset) - fixed_width/2;
+      y[1] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset) - fixed_width/2;
+      y[2] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset) + fixed_width/2;
+      y[3] = subpixel_snap(v1[0][1] + y_offset     - setup->pixel_offset) + fixed_width/2;
+      
+   }
+   else {
+      const float dxdy = dx / dy;
+
+      /* Y-MAJOR LINE */      
+      x1diff = v1[0][0] - (float) floor(v1[0][0]) - 0.5;
+      y1diff = v1[0][1] - (float) floor(v1[0][1]) - 0.5;
+      x2diff = v2[0][0] - (float) floor(v2[0][0]) - 0.5;
+      y2diff = v2[0][1] - (float) floor(v2[0][1]) - 0.5;
+
+      if (x2diff==-0.5 && dx<0) {
+         x2diff = 0.5;
+      }
+
+      /* 
+       * Diamond exit rule test for starting point 
+       */    
+      if (fabsf(x1diff) + fabsf(y1diff) < 0.5) {
+         draw_start = TRUE;
+      }
+      else if (sign(-y1diff) == sign(dy)) {
+         draw_start = FALSE;
+      }
+      else if (sign(x1diff) != sign(-dx)) {
+         draw_start = TRUE;
+      }
+      else {
+         /* do intersection test */
+         float xintersect = fracf(v1[0][0]) + y1diff * dxdy;
+         draw_start = (xintersect < 1.0 && xintersect > 0.0);
+      }
+
+      /* 
+       * Diamond exit rule test for ending point 
+       */    
+      if (fabsf(x2diff) + fabsf(y2diff) < 0.5) {
+         draw_end = FALSE;
+      }
+      else if (sign(-y2diff) != sign(dy) ) {
+         draw_end = FALSE;
+      }
+      else if (sign(x2diff) == sign(-dx) ) {
+         draw_end = TRUE;
+      }
+      else {
+         /* do intersection test */
+         float xintersect = fracf(v2[0][0]) + y2diff * dxdy;
+         draw_end = (xintersect < 1.0 && xintersect > 0.0);
+      }
+
+      /* Are we already drawing start/end?
+       */
+      will_draw_start = sign(y1diff) == sign(dy);
+      will_draw_end = (sign(-y2diff) == sign(dy)) || y2diff==0;
+
+      if (dy > 0) {
+         /* if v2 is on top of v1, swap pointers */
+         const float (*temp)[4] = v1;
+         v1 = v2;
+         v2 = temp; 
+         dx = -dx;
+         dy = -dy;
+
+         /* Otherwise shift planes appropriately */
+         if (will_draw_start != draw_start) {
+            y_offset_end = - y1diff + 0.5;
+            x_offset_end = y_offset_end * dxdy;
+         }
+         if (will_draw_end != draw_end) {
+            y_offset = - y2diff + 0.5;
+            x_offset = y_offset * dxdy;
+         }
+      }
+      else {
+         /* Otherwise shift planes appropriately */
+         if (will_draw_start != draw_start) {
+            y_offset = - y1diff - 0.5;
+            x_offset = y_offset * dxdy;
+                     
+         }
+         if (will_draw_end != draw_end) {
+            y_offset_end = - y2diff - 0.5;
+            x_offset_end = y_offset_end * dxdy;
+         }
+      }
+      /* x/y positions in fixed point */
+      x[0] = subpixel_snap(v1[0][0] + x_offset     - setup->pixel_offset) - fixed_width/2;
+      x[1] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset) - fixed_width/2;
+      x[2] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset) + fixed_width/2;
+      x[3] = subpixel_snap(v1[0][0] + x_offset     - setup->pixel_offset) + fixed_width/2;
+     
+      y[0] = subpixel_snap(v1[0][1] + y_offset     - setup->pixel_offset); 
+      y[1] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset);
+      y[2] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset);
+      y[3] = subpixel_snap(v1[0][1] + y_offset     - setup->pixel_offset);
+   }
+
+
+
+   LP_COUNT(nr_tris);
+
+   /* Bounding rectangle (in pixels) */
+   {
+      /* Yes this is necessary to accurately calculate bounding boxes
+       * with the two fill-conventions we support.  GL (normally) ends
+       * up needing a bottom-left fill convention, which requires
+       * slightly different rounding.
+       */
+      int adj = (setup->pixel_offset != 0) ? 1 : 0;
+
+      bbox.x0 = (MIN4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER;
+      bbox.x1 = (MAX4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER;
+      bbox.y0 = (MIN4(y[0], y[1], y[2], y[3]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
+      bbox.y1 = (MAX4(y[0], y[1], y[2], y[3]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
+
+      /* Inclusive coordinates:
+       */
+      bbox.x1--;
+      bbox.y1--;
+   }
+
+   if (bbox.x1 < bbox.x0 ||
+       bbox.y1 < bbox.y0) {
+      if (0) debug_printf("empty bounding box\n");
+      LP_COUNT(nr_culled_tris);
+      return;
+   }
+
+   if (!u_rect_test_intersection(&setup->draw_region, &bbox)) {
+      if (0) debug_printf("offscreen\n");
+      LP_COUNT(nr_culled_tris);
+      return;
+   }
+
+   u_rect_find_intersection(&setup->draw_region, &bbox);
+
+   line = lp_setup_alloc_triangle(scene,
+                                  setup->fs.nr_inputs,
+                                  nr_planes,
+                                  &tri_bytes);
+   if (!line)
+      return;
+
+#ifdef DEBUG
+   line->v[0][0] = v1[0][0];
+   line->v[1][0] = v2[0][0];   
+   line->v[0][1] = v1[0][1];
+   line->v[1][1] = v2[0][1];
+#endif
+
+   /* calculate the deltas */
+   line->plane[0].dcdy = x[0] - x[1];
+   line->plane[1].dcdy = x[1] - x[2];
+   line->plane[2].dcdy = x[2] - x[3];
+   line->plane[3].dcdy = x[3] - x[0];
+
+   line->plane[0].dcdx = y[0] - y[1];
+   line->plane[1].dcdx = y[1] - y[2];
+   line->plane[2].dcdx = y[2] - y[3];
+   line->plane[3].dcdx = y[3] - y[0];
+
+
+   info.oneoverarea = 1.0f / (dx * dx  + dy * dy);    
+   info.dx = dx;
+   info.dy = dy;
+   info.v1 = v1;
+   info.v2 = v2;
+
+   /* Setup parameter interpolants:
+    */
+   setup_line_coefficients( setup, line, &info); 
+
+   line->inputs.facing = 1.0F;
+   line->inputs.state = setup->fs.stored;
+
+   for (i = 0; i < 4; i++) {
+      struct lp_rast_plane *plane = &line->plane[i];
+
+      /* half-edge constants, will be interated over the whole render
+       * target.
+       */
+      plane->c = plane->dcdx * x[i] - plane->dcdy * y[i];
+
+      
+      /* correct for top-left vs. bottom-left fill convention.  
+       *
+       * note that we're overloading gl_rasterization_rules to mean
+       * both (0.5,0.5) pixel centers *and* bottom-left filling
+       * convention.
+       *
+       * GL actually has a top-left filling convention, but GL's
+       * notion of "top" differs from gallium's...
+       *
+       * Also, sometimes (in FBO cases) GL will render upside down
+       * to its usual method, in which case it will probably want
+       * to use the opposite, top-left convention.
+       */         
+      if (plane->dcdx < 0) {
+         /* both fill conventions want this - adjust for left edges */
+         plane->c++;            
+      }
+      else if (plane->dcdx == 0) {
+         if (setup->pixel_offset == 0) {
+            /* correct for top-left fill convention:
+             */
+            if (plane->dcdy > 0) plane->c++;
+         }
+         else {
+            /* correct for bottom-left fill convention:
+             */
+            if (plane->dcdy < 0) plane->c++;
+         }
+      }
+
+      plane->dcdx *= FIXED_ONE;
+      plane->dcdy *= FIXED_ONE;
+
+      /* find trivial reject offsets for each edge for a single-pixel
+       * sized block.  These will be scaled up at each recursive level to
+       * match the active blocksize.  Scaling in this way works best if
+       * the blocks are square.
+       */
+      plane->eo = 0;
+      if (plane->dcdx < 0) plane->eo -= plane->dcdx;
+      if (plane->dcdy > 0) plane->eo += plane->dcdy;
+
+      /* Calculate trivial accept offsets from the above.
+       */
+      plane->ei = plane->dcdy - plane->dcdx - plane->eo;
+   }
+
+
+   /* 
+    * When rasterizing scissored tris, use the intersection of the
+    * triangle bounding box and the scissor rect to generate the
+    * scissor planes.
+    *
+    * This permits us to cut off the triangle "tails" that are present
+    * in the intermediate recursive levels caused when two of the
+    * triangles edges don't diverge quickly enough to trivially reject
+    * exterior blocks from the triangle.
+    *
+    * It's not really clear if it's worth worrying about these tails,
+    * but since we generate the planes for each scissored tri, it's
+    * free to trim them in this case.
+    * 
+    * Note that otherwise, the scissor planes only vary in 'C' value,
+    * and even then only on state-changes.  Could alternatively store
+    * these planes elsewhere.
+    */
+   if (nr_planes == 8) {
+      line->plane[4].dcdx = -1;
+      line->plane[4].dcdy = 0;
+      line->plane[4].c = 1-bbox.x0;
+      line->plane[4].ei = 0;
+      line->plane[4].eo = 1;
+
+      line->plane[5].dcdx = 1;
+      line->plane[5].dcdy = 0;
+      line->plane[5].c = bbox.x1+1;
+      line->plane[5].ei = -1;
+      line->plane[5].eo = 0;
+
+      line->plane[6].dcdx = 0;
+      line->plane[6].dcdy = 1;
+      line->plane[6].c = 1-bbox.y0;
+      line->plane[6].ei = 0;
+      line->plane[6].eo = 1;
+
+      line->plane[7].dcdx = 0;
+      line->plane[7].dcdy = -1;
+      line->plane[7].c = bbox.y1+1;
+      line->plane[7].ei = -1;
+      line->plane[7].eo = 0;
+   }
+
+   lp_setup_bin_triangle(setup, line, &bbox, nr_planes);
+}
+   
+
+void lp_setup_choose_line( struct lp_setup_context *setup ) 
+{ 
+   setup->line = lp_setup_line;
 }
 
 
index 9f69e6c5ce2d83d56229e60277a8adb743c1d9ba..6ae318d328df425b62b067b2f71874fafe7d7b95 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  *
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2010, VMware Inc.
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -18,7 +18,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL 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 "lp_setup_context.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "lp_perf.h"
+#include "lp_setup_context.h"
+#include "lp_rast.h"
+#include "lp_state_fs.h"
+#include "tgsi/tgsi_scan.h"
+
+#define NUM_CHANNELS 4
+
+struct point_info {
+   /* x,y deltas */
+   int dy01, dy12;
+   int dx01, dx12;
+
+   const float (*v0)[4];
+};   
+
+
+/**
+ * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
+ */
+static void constant_coef( struct lp_setup_context *setup,
+                           struct lp_rast_triangle *point,
+                           unsigned slot,
+                           const float value,
+                           unsigned i )
+{
+   point->inputs.a0[slot][i] = value;
+   point->inputs.dadx[slot][i] = 0.0f;
+   point->inputs.dady[slot][i] = 0.0f;
+}
+
+static void perspective_coef( struct lp_setup_context *setup,
+                              struct lp_rast_triangle *point,
+                              const struct point_info *info,
+                              unsigned slot,
+                              unsigned vert_attr,
+                              unsigned i)
+{
+   if (i == 0) {   
+      float dadx = FIXED_ONE / (float)info->dx12;  
+      float dady =  0.0f;
+      point->inputs.dadx[slot][i] = dadx;
+      point->inputs.dady[slot][i] = dady;
+      point->inputs.a0[slot][i] = (0.5 -
+                                  (dadx * ((float)info->v0[0][0] - setup->pixel_offset) +
+                                   dady * ((float)info->v0[0][1] - setup->pixel_offset)));
+   }
+
+   else if (i == 1) {
+      float dadx =  0.0f; 
+      float dady =  FIXED_ONE / (float)info->dx12;
+   
+      point->inputs.dadx[slot][i] = dadx;
+      point->inputs.dady[slot][i] = dady;
+      point->inputs.a0[slot][i] = (0.5 -
+                                  (dadx * ((float)info->v0[0][0] - setup->pixel_offset) +
+                                   dady * ((float)info->v0[0][1] - setup->pixel_offset)));
+   }
+
+   else if (i == 2) {
+      point->inputs.a0[slot][i] = 0.0f;
+      point->inputs.dadx[slot][i] = 0.0f;
+      point->inputs.dady[slot][i] = 0.0f;
+   }
+      
+   else if (i == 3) {
+      point->inputs.a0[slot][i] = 1.0f;
+      point->inputs.dadx[slot][i] = 0.0f;
+      point->inputs.dady[slot][i] = 0.0f;
+   }
+
+}
+
+
+/**
+ * Special coefficient setup for gl_FragCoord.
+ * X and Y are trivial
+ * Z and W are copied from position_coef which should have already been computed.
+ * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
+ */
+static void
+setup_point_fragcoord_coef(struct lp_setup_context *setup,
+                           struct lp_rast_triangle *point,
+                           const struct point_info *info,
+                           unsigned slot,
+                           unsigned usage_mask)
+{
+   /*X*/
+   if (usage_mask & TGSI_WRITEMASK_X) {
+      point->inputs.a0[slot][0] = 0.0;
+      point->inputs.dadx[slot][0] = 1.0;
+      point->inputs.dady[slot][0] = 0.0;
+   }
+
+   /*Y*/
+   if (usage_mask & TGSI_WRITEMASK_Y) {
+      point->inputs.a0[slot][1] = 0.0;
+      point->inputs.dadx[slot][1] = 0.0;
+      point->inputs.dady[slot][1] = 1.0;
+   }
+
+   /*Z*/
+   if (usage_mask & TGSI_WRITEMASK_Z) {
+      constant_coef(setup, point, slot, info->v0[0][2], 2);
+   }
+
+   /*W*/
+   if (usage_mask & TGSI_WRITEMASK_W) {
+      constant_coef(setup, point, slot, info->v0[0][3], 3);
+   }
+}
+
+/**
+ * Compute the point->coef[] array dadx, dady, a0 values.
+ */
+static void   
+setup_point_coefficients( struct lp_setup_context *setup,
+                          struct lp_rast_triangle *point,
+                          const struct point_info *info)
+{
+   unsigned fragcoord_usage_mask = TGSI_WRITEMASK_XYZ;
+   unsigned slot;
+
+   /* 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_POSITION:
+         /*
+          * The generated pixel interpolators will pick up the coeffs from
+          * slot 0, so all need to ensure that the usage mask is covers all
+          * usages.
+          */
+         fragcoord_usage_mask |= usage_mask;
+         break;
+
+      case LP_INTERP_PERSPECTIVE:
+         /* For point sprite textures */        
+         if (setup->fs.current.variant->shader->info.input_semantic_name[slot] 
+             == TGSI_SEMANTIC_GENERIC) 
+         {
+            int index = setup->fs.current.variant->shader->info.input_semantic_index[slot];
+            
+            if (setup->sprite & (1 << index)) {
+               for (i = 0; i < NUM_CHANNELS; i++)
+                  if (usage_mask & (1 << i))
+                     perspective_coef(setup, point, info, slot+1, vert_attr, i);
+               fragcoord_usage_mask |= TGSI_WRITEMASK_W;
+               break;                     
+            }
+         }
+
+         /* Otherwise fallthrough */
+      default:
+         for (i = 0; i < NUM_CHANNELS; i++) {
+            if (usage_mask & (1 << i))
+               constant_coef(setup, point, slot+1, info->v0[vert_attr][i], i);
+         }
+      }
+   }
 
-static void point_nop( struct lp_setup_context *setup,
-                       const float (*v0)[4] )
+   /* The internal position input is in slot zero:
+    */
+   setup_point_fragcoord_coef(setup, point, info, 0,
+                              fragcoord_usage_mask);
+}
+
+static INLINE int
+subpixel_snap(float a)
 {
+   return util_iround(FIXED_ONE * a);
+}
+
+
+static void lp_setup_point( struct lp_setup_context *setup,
+                            const float (*v0)[4] )
+{
+   /* x/y positions in fixed point */
+   const int sizeAttr = setup->psize;
+   const float size
+      = (setup->point_size_per_vertex && sizeAttr > 0) ? v0[sizeAttr][0]
+      : setup->point_size;
+   
+   /* Point size as fixed point integer, remove rounding errors 
+    * and gives minimum width for very small points
+    */
+   int fixed_width = MAX2(FIXED_ONE,
+                          (subpixel_snap(size) + FIXED_ONE/2 - 1) & ~(FIXED_ONE-1));
+
+   const int x0 = subpixel_snap(v0[0][0] - setup->pixel_offset) - fixed_width/2;
+   const int y0 = subpixel_snap(v0[0][1] - setup->pixel_offset) - fixed_width/2;
+     
+   struct lp_scene *scene = lp_setup_get_current_scene(setup);
+   struct lp_rast_triangle *point;
+   unsigned bytes;
+   struct u_rect bbox;
+   unsigned nr_planes = 4;
+   struct point_info info;
+
+
+   /* Bounding rectangle (in pixels) */
+   {
+      /* Yes this is necessary to accurately calculate bounding boxes
+       * with the two fill-conventions we support.  GL (normally) ends
+       * up needing a bottom-left fill convention, which requires
+       * slightly different rounding.
+       */
+      int adj = (setup->pixel_offset != 0) ? 1 : 0;
+
+      bbox.x0 = (x0 + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
+      bbox.x1 = (x0 + fixed_width + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
+      bbox.y0 = (y0 + (FIXED_ONE-1)) >> FIXED_ORDER;
+      bbox.y1 = (y0 + fixed_width + (FIXED_ONE-1)) >> FIXED_ORDER;
+
+      /* Inclusive coordinates:
+       */
+      bbox.x1--;
+      bbox.y1--;
+   }
+   
+   if (!u_rect_test_intersection(&setup->draw_region, &bbox)) {
+      if (0) debug_printf("offscreen\n");
+      LP_COUNT(nr_culled_tris);
+      return;
+   }
+
+   u_rect_find_intersection(&setup->draw_region, &bbox);
+
+   point = lp_setup_alloc_triangle(scene,
+                                   setup->fs.nr_inputs,
+                                   nr_planes,
+                                   &bytes);
+   if (!point)
+      return;
+
+#ifdef DEBUG
+   point->v[0][0] = v0[0][0];
+   point->v[0][1] = v0[0][1];
+#endif
+
+   info.v0 = v0;
+   info.dx01 = 0;
+   info.dx12 = fixed_width;
+   info.dy01 = fixed_width;
+   info.dy12 = 0;
+   
+   /* Setup parameter interpolants:
+    */
+   setup_point_coefficients(setup, point, &info);
+
+   point->inputs.facing = 1.0F;
+   point->inputs.state = setup->fs.stored;
+
+   {
+      point->plane[0].dcdx = -1;
+      point->plane[0].dcdy = 0;
+      point->plane[0].c = 1-bbox.x0;
+      point->plane[0].ei = 0;
+      point->plane[0].eo = 1;
+
+      point->plane[1].dcdx = 1;
+      point->plane[1].dcdy = 0;
+      point->plane[1].c = bbox.x1+1;
+      point->plane[1].ei = -1;
+      point->plane[1].eo = 0;
+
+      point->plane[2].dcdx = 0;
+      point->plane[2].dcdy = 1;
+      point->plane[2].c = 1-bbox.y0;
+      point->plane[2].ei = 0;
+      point->plane[2].eo = 1;
+
+      point->plane[3].dcdx = 0;
+      point->plane[3].dcdy = -1;
+      point->plane[3].c = bbox.y1+1;
+      point->plane[3].ei = -1;
+      point->plane[3].eo = 0;
+   }
+
+   lp_setup_bin_triangle(setup, point, &bbox, nr_planes);
 }
 
 
 void 
 lp_setup_choose_point( struct lp_setup_context *setup )
 {
-   setup->point = point_nop;
+   setup->point = lp_setup_point;
 }
 
 
index 393533ebee47306ab940b2620faed289316651f5..0180d95090fc3dcfb2a56d0455a7a236b783c404 100644 (file)
 
 #include "util/u_math.h"
 #include "util/u_memory.h"
+#include "util/u_rect.h"
 #include "lp_perf.h"
 #include "lp_setup_context.h"
+#include "lp_setup_coef.h"
 #include "lp_rast.h"
 #include "lp_state_fs.h"
 
 #define NUM_CHANNELS 4
 
-struct tri_info {
-
-   float pixel_offset;
-
-   /* fixed point vertex coordinates */
-   int x[3];
-   int y[3];
-
-   /* float x,y deltas - all from the original coordinates
-    */
-   float dy01, dy20;
-   float dx01, dx20;
-   float oneoverarea;
-
-   const float (*v0)[4];
-   const float (*v1)[4];
-   const float (*v2)[4];
-
-   boolean frontfacing;
-};
-
-
 
    
 static INLINE int
@@ -76,247 +56,6 @@ fixed_to_float(int a)
 
 
 
-/**
- * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
- */
-static void constant_coef( struct lp_rast_triangle *tri,
-                           unsigned slot,
-                          const float value,
-                           unsigned i )
-{
-   tri->inputs.a0[slot][i] = value;
-   tri->inputs.dadx[slot][i] = 0.0f;
-   tri->inputs.dady[slot][i] = 0.0f;
-}
-
-
-
-static void linear_coef( struct lp_rast_triangle *tri,
-                         const struct tri_info *info,
-                         unsigned slot,
-                         unsigned vert_attr,
-                         unsigned i)
-{
-   float a0 = info->v0[vert_attr][i];
-   float a1 = info->v1[vert_attr][i];
-   float a2 = info->v2[vert_attr][i];
-
-   float da01 = a0 - a1;
-   float da20 = a2 - a0;
-   float dadx = (da01 * info->dy20 - info->dy01 * da20) * info->oneoverarea;
-   float dady = (da20 * info->dx01 - info->dx20 * da01) * info->oneoverarea;
-
-   tri->inputs.dadx[slot][i] = dadx;
-   tri->inputs.dady[slot][i] = dady;
-
-   /* calculate a0 as the value which would be sampled for the
-    * fragment at (0,0), taking into account that we want to sample at
-    * pixel centers, in other words (0.5, 0.5).
-    *
-    * this is neat but unfortunately not a good way to do things for
-    * triangles with very large values of dadx or dady as it will
-    * result in the subtraction and re-addition from a0 of a very
-    * large number, which means we'll end up loosing a lot of the
-    * fractional bits and precision from a0.  the way to fix this is
-    * to define a0 as the sample at a pixel center somewhere near vmin
-    * instead - i'll switch to this later.
-    */
-   tri->inputs.a0[slot][i] = (a0 -
-                              (dadx * (info->v0[0][0] - info->pixel_offset) +
-                               dady * (info->v0[0][1] - info->pixel_offset)));
-}
-
-
-/**
- * Compute a0, dadx and dady for a perspective-corrected interpolant,
- * for a triangle.
- * We basically multiply the vertex value by 1/w before computing
- * the plane coefficients (a0, dadx, dady).
- * Later, when we compute the value at a particular fragment position we'll
- * divide the interpolated value by the interpolated W at that fragment.
- */
-static void perspective_coef( struct lp_rast_triangle *tri,
-                              const struct tri_info *info,
-                              unsigned slot,
-                             unsigned vert_attr,
-                              unsigned i)
-{
-   /* premultiply by 1/w  (v[0][3] is always 1/w):
-    */
-   float a0 = info->v0[vert_attr][i] * info->v0[0][3];
-   float a1 = info->v1[vert_attr][i] * info->v1[0][3];
-   float a2 = info->v2[vert_attr][i] * info->v2[0][3];
-   float da01 = a0 - a1;
-   float da20 = a2 - a0;
-   float dadx = (da01 * info->dy20 - info->dy01 * da20) * info->oneoverarea;
-   float dady = (da20 * info->dx01 - info->dx20 * da01) * info->oneoverarea;
-
-   tri->inputs.dadx[slot][i] = dadx;
-   tri->inputs.dady[slot][i] = dady;
-   tri->inputs.a0[slot][i] = (a0 -
-                              (dadx * (info->v0[0][0] - info->pixel_offset) +
-                               dady * (info->v0[0][1] - info->pixel_offset)));
-}
-
-
-/**
- * Special coefficient setup for gl_FragCoord.
- * X and Y are trivial
- * Z and W are copied from position_coef which should have already been computed.
- * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
- */
-static void
-setup_fragcoord_coef(struct lp_rast_triangle *tri,
-                     const struct tri_info *info,
-                     unsigned slot,
-                     unsigned usage_mask)
-{
-   /*X*/
-   if (usage_mask & TGSI_WRITEMASK_X) {
-      tri->inputs.a0[slot][0] = 0.0;
-      tri->inputs.dadx[slot][0] = 1.0;
-      tri->inputs.dady[slot][0] = 0.0;
-   }
-
-   /*Y*/
-   if (usage_mask & TGSI_WRITEMASK_Y) {
-      tri->inputs.a0[slot][1] = 0.0;
-      tri->inputs.dadx[slot][1] = 0.0;
-      tri->inputs.dady[slot][1] = 1.0;
-   }
-
-   /*Z*/
-   if (usage_mask & TGSI_WRITEMASK_Z) {
-      linear_coef(tri, info, slot, 0, 2);
-   }
-
-   /*W*/
-   if (usage_mask & TGSI_WRITEMASK_W) {
-      linear_coef(tri, info, slot, 0, 3);
-   }
-}
-
-
-/**
- * Setup the fragment input attribute with the front-facing value.
- * \param frontface  is the triangle front facing?
- */
-static void setup_facing_coef( struct lp_rast_triangle *tri,
-                               unsigned slot,
-                               boolean frontface,
-                               unsigned usage_mask)
-{
-   /* convert TRUE to 1.0 and FALSE to -1.0 */
-   if (usage_mask & TGSI_WRITEMASK_X)
-      constant_coef( tri, slot, 2.0f * frontface - 1.0f, 0 );
-
-   if (usage_mask & TGSI_WRITEMASK_Y)
-      constant_coef( tri, slot, 0.0f, 1 ); /* wasted */
-
-   if (usage_mask & TGSI_WRITEMASK_Z)
-      constant_coef( tri, slot, 0.0f, 2 ); /* wasted */
-
-   if (usage_mask & TGSI_WRITEMASK_W)
-      constant_coef( tri, slot, 0.0f, 3 ); /* wasted */
-}
-
-
-/**
- * Compute the tri->coef[] array dadx, dady, a0 values.
- */
-static void setup_tri_coefficients( struct lp_setup_context *setup,
-                                   struct lp_rast_triangle *tri,
-                                    const struct tri_info *info)
-{
-   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;
-
-      switch (setup->fs.input[slot].interp) {
-      case LP_INTERP_CONSTANT:
-         if (setup->flatshade_first) {
-            for (i = 0; i < NUM_CHANNELS; i++)
-               if (usage_mask & (1 << i))
-                  constant_coef(tri, slot+1, info->v0[vert_attr][i], i);
-         }
-         else {
-            for (i = 0; i < NUM_CHANNELS; i++)
-               if (usage_mask & (1 << i))
-                  constant_coef(tri, slot+1, info->v2[vert_attr][i], i);
-         }
-         break;
-
-      case LP_INTERP_LINEAR:
-         for (i = 0; i < NUM_CHANNELS; i++)
-            if (usage_mask & (1 << i))
-               linear_coef(tri, info, slot+1, vert_attr, i);
-         break;
-
-      case LP_INTERP_PERSPECTIVE:
-         for (i = 0; i < NUM_CHANNELS; i++)
-            if (usage_mask & (1 << i))
-               perspective_coef(tri, info, slot+1, vert_attr, i);
-         fragcoord_usage_mask |= TGSI_WRITEMASK_W;
-         break;
-
-      case LP_INTERP_POSITION:
-         /*
-          * The generated pixel interpolators will pick up the coeffs from
-          * slot 0, so all need to ensure that the usage mask is covers all
-          * usages.
-          */
-         fragcoord_usage_mask |= usage_mask;
-         break;
-
-      case LP_INTERP_FACING:
-         setup_facing_coef(tri, slot+1, info->frontfacing, usage_mask);
-         break;
-
-      default:
-         assert(0);
-      }
-   }
-
-   /* 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);
-            }
-         }
-      }
-   }
-}
-
-
 
 
 
@@ -329,11 +68,11 @@ static void setup_tri_coefficients( struct lp_setup_context *setup,
  * \param nr_inputs  number of fragment shader inputs
  * \return pointer to triangle space
  */
-static INLINE struct lp_rast_triangle *
-alloc_triangle(struct lp_scene *scene,
-               unsigned nr_inputs,
-               unsigned nr_planes,
-               unsigned *tri_size)
+struct lp_rast_triangle *
+lp_setup_alloc_triangle(struct lp_scene *scene,
+                        unsigned nr_inputs,
+                        unsigned nr_planes,
+                        unsigned *tri_size)
 {
    unsigned input_array_sz = NUM_CHANNELS * (nr_inputs + 1) * sizeof(float);
    struct lp_rast_triangle *tri;
@@ -357,35 +96,71 @@ alloc_triangle(struct lp_scene *scene,
    return tri;
 }
 
+void
+lp_setup_print_vertex(struct lp_setup_context *setup,
+                      const char *name,
+                      const float (*v)[4])
+{
+   int i, j;
+
+   debug_printf("   wpos (%s[0]) xyzw %f %f %f %f\n",
+                name,
+                v[0][0], v[0][1], v[0][2], v[0][3]);
+
+   for (i = 0; i < setup->fs.nr_inputs; i++) {
+      const float *in = v[setup->fs.input[i].src_index];
+
+      debug_printf("  in[%d] (%s[%d]) %s%s%s%s ",
+                   i, 
+                   name, setup->fs.input[i].src_index,
+                   (setup->fs.input[i].usage_mask & 0x1) ? "x" : " ",
+                   (setup->fs.input[i].usage_mask & 0x2) ? "y" : " ",
+                   (setup->fs.input[i].usage_mask & 0x4) ? "z" : " ",
+                   (setup->fs.input[i].usage_mask & 0x8) ? "w" : " ");
+
+      for (j = 0; j < 4; j++)
+         if (setup->fs.input[i].usage_mask & (1<<j))
+            debug_printf("%.5f ", in[j]);
+
+      debug_printf("\n");
+   }
+}
+
 
 /**
  * Print triangle vertex attribs (for debug).
  */
-static void
-print_triangle(struct lp_setup_context *setup,
-               const float (*v1)[4],
-               const float (*v2)[4],
-               const float (*v3)[4])
+void
+lp_setup_print_triangle(struct lp_setup_context *setup,
+                        const float (*v0)[4],
+                        const float (*v1)[4],
+                        const float (*v2)[4])
 {
-   uint i;
+   debug_printf("triangle\n");
 
-   debug_printf("llvmpipe triangle\n");
-   for (i = 0; i < 1 + setup->fs.nr_inputs; i++) {
-      debug_printf("  v1[%d]:  %f %f %f %f\n", i,
-                   v1[i][0], v1[i][1], v1[i][2], v1[i][3]);
-   }
-   for (i = 0; i < 1 + setup->fs.nr_inputs; i++) {
-      debug_printf("  v2[%d]:  %f %f %f %f\n", i,
-                   v2[i][0], v2[i][1], v2[i][2], v2[i][3]);
-   }
-   for (i = 0; i < 1 + setup->fs.nr_inputs; i++) {
-      debug_printf("  v3[%d]:  %f %f %f %f\n", i,
-                   v3[i][0], v3[i][1], v3[i][2], v3[i][3]);
+   {
+      const float ex = v0[0][0] - v2[0][0];
+      const float ey = v0[0][1] - v2[0][1];
+      const float fx = v1[0][0] - v2[0][0];
+      const float fy = v1[0][1] - v2[0][1];
+
+      /* det = cross(e,f).z */
+      const float det = ex * fy - ey * fx;
+      if (det < 0.0f) 
+         debug_printf("   - ccw\n");
+      else if (det > 0.0f)
+         debug_printf("   - cw\n");
+      else
+         debug_printf("   - zero area\n");
    }
+
+   lp_setup_print_vertex(setup, "v0", v0);
+   lp_setup_print_vertex(setup, "v1", v1);
+   lp_setup_print_vertex(setup, "v2", v2);
 }
 
 
-lp_rast_cmd lp_rast_tri_tab[8] = {
+lp_rast_cmd lp_rast_tri_tab[9] = {
    NULL,               /* should be impossible */
    lp_rast_triangle_1,
    lp_rast_triangle_2,
@@ -393,7 +168,8 @@ lp_rast_cmd lp_rast_tri_tab[8] = {
    lp_rast_triangle_4,
    lp_rast_triangle_5,
    lp_rast_triangle_6,
-   lp_rast_triangle_7
+   lp_rast_triangle_7,
+   lp_rast_triangle_8
 };
 
 /**
@@ -403,25 +179,27 @@ lp_rast_cmd lp_rast_tri_tab[8] = {
  */
 static void
 do_triangle_ccw(struct lp_setup_context *setup,
+               const float (*v0)[4],
                const float (*v1)[4],
                const float (*v2)[4],
-               const float (*v3)[4],
                boolean frontfacing )
 {
-
    struct lp_scene *scene = lp_setup_get_current_scene(setup);
-   struct lp_fragment_shader_variant *variant = setup->fs.current.variant;
    struct lp_rast_triangle *tri;
-   struct tri_info info;
+   int x[3];
+   int y[3];
+   float dy01, dy20;
+   float dx01, dx20;
+   float oneoverarea;
+   struct lp_tri_info info;
    int area;
-   int minx, maxx, miny, maxy;
-   int ix0, ix1, iy0, iy1;
+   struct u_rect bbox;
    unsigned tri_bytes;
    int i;
    int nr_planes = 3;
       
    if (0)
-      print_triangle(setup, v1, v2, v3);
+      lp_setup_print_triangle(setup, v0, v1, v2);
 
    if (setup->scissor_test) {
       nr_planes = 7;
@@ -430,38 +208,73 @@ do_triangle_ccw(struct lp_setup_context *setup,
       nr_planes = 3;
    }
 
+   /* x/y positions in fixed point */
+   x[0] = subpixel_snap(v0[0][0] - setup->pixel_offset);
+   x[1] = subpixel_snap(v1[0][0] - setup->pixel_offset);
+   x[2] = subpixel_snap(v2[0][0] - setup->pixel_offset);
+   y[0] = subpixel_snap(v0[0][1] - setup->pixel_offset);
+   y[1] = subpixel_snap(v1[0][1] - setup->pixel_offset);
+   y[2] = subpixel_snap(v2[0][1] - setup->pixel_offset);
+
+
+   /* Bounding rectangle (in pixels) */
+   {
+      /* Yes this is necessary to accurately calculate bounding boxes
+       * with the two fill-conventions we support.  GL (normally) ends
+       * up needing a bottom-left fill convention, which requires
+       * slightly different rounding.
+       */
+      int adj = (setup->pixel_offset != 0) ? 1 : 0;
+
+      bbox.x0 = (MIN3(x[0], x[1], x[2]) + (FIXED_ONE-1)) >> FIXED_ORDER;
+      bbox.x1 = (MAX3(x[0], x[1], x[2]) + (FIXED_ONE-1)) >> FIXED_ORDER;
+      bbox.y0 = (MIN3(y[0], y[1], y[2]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
+      bbox.y1 = (MAX3(y[0], y[1], y[2]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
+
+      /* Inclusive coordinates:
+       */
+      bbox.x1--;
+      bbox.y1--;
+   }
+
+   if (bbox.x1 < bbox.x0 ||
+       bbox.y1 < bbox.y0) {
+      if (0) debug_printf("empty bounding box\n");
+      LP_COUNT(nr_culled_tris);
+      return;
+   }
+
+   if (!u_rect_test_intersection(&setup->draw_region, &bbox)) {
+      if (0) debug_printf("offscreen\n");
+      LP_COUNT(nr_culled_tris);
+      return;
+   }
+
+   u_rect_find_intersection(&setup->draw_region, &bbox);
 
-   tri = alloc_triangle(scene,
-                        setup->fs.nr_inputs,
-                        nr_planes,
-                        &tri_bytes);
+   tri = lp_setup_alloc_triangle(scene,
+                                 setup->fs.nr_inputs,
+                                 nr_planes,
+                                 &tri_bytes);
    if (!tri)
       return;
 
 #ifdef DEBUG
-   tri->v[0][0] = v1[0][0];
-   tri->v[1][0] = v2[0][0];
-   tri->v[2][0] = v3[0][0];
-   tri->v[0][1] = v1[0][1];
-   tri->v[1][1] = v2[0][1];
-   tri->v[2][1] = v3[0][1];
+   tri->v[0][0] = v0[0][0];
+   tri->v[1][0] = v1[0][0];
+   tri->v[2][0] = v2[0][0];
+   tri->v[0][1] = v0[0][1];
+   tri->v[1][1] = v1[0][1];
+   tri->v[2][1] = v2[0][1];
 #endif
 
-   /* x/y positions in fixed point */
-   info.x[0] = subpixel_snap(v1[0][0] - setup->pixel_offset);
-   info.x[1] = subpixel_snap(v2[0][0] - setup->pixel_offset);
-   info.x[2] = subpixel_snap(v3[0][0] - setup->pixel_offset);
-   info.y[0] = subpixel_snap(v1[0][1] - setup->pixel_offset);
-   info.y[1] = subpixel_snap(v2[0][1] - setup->pixel_offset);
-   info.y[2] = subpixel_snap(v3[0][1] - setup->pixel_offset);
-
-   tri->plane[0].dcdy = info.x[0] - info.x[1];
-   tri->plane[1].dcdy = info.x[1] - info.x[2];
-   tri->plane[2].dcdy = info.x[2] - info.x[0];
+   tri->plane[0].dcdy = x[0] - x[1];
+   tri->plane[1].dcdy = x[1] - x[2];
+   tri->plane[2].dcdy = x[2] - x[0];
 
-   tri->plane[0].dcdx = info.y[0] - info.y[1];
-   tri->plane[1].dcdx = info.y[1] - info.y[2];
-   tri->plane[2].dcdx = info.y[2] - info.y[0];
+   tri->plane[0].dcdx = y[0] - y[1];
+   tri->plane[1].dcdx = y[1] - y[2];
+   tri->plane[2].dcdx = y[2] - y[0];
 
    area = (tri->plane[0].dcdy * tri->plane[2].dcdx -
            tri->plane[2].dcdy * tri->plane[0].dcdx);
@@ -478,57 +291,29 @@ do_triangle_ccw(struct lp_setup_context *setup,
       return;
    }
 
-   /* Bounding rectangle (in pixels) */
-   {
-      /* Yes this is necessary to accurately calculate bounding boxes
-       * with the two fill-conventions we support.  GL (normally) ends
-       * up needing a bottom-left fill convention, which requires
-       * slightly different rounding.
-       */
-      int adj = (setup->pixel_offset != 0) ? 1 : 0;
-
-      minx = (MIN3(info.x[0], info.x[1], info.x[2]) + (FIXED_ONE-1)) >> FIXED_ORDER;
-      maxx = (MAX3(info.x[0], info.x[1], info.x[2]) + (FIXED_ONE-1)) >> FIXED_ORDER;
-      miny = (MIN3(info.y[0], info.y[1], info.y[2]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
-      maxy = (MAX3(info.y[0], info.y[1], info.y[2]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
-   }
-
-   if (setup->scissor_test) {
-      minx = MAX2(minx, setup->scissor.current.minx);
-      maxx = MIN2(maxx, setup->scissor.current.maxx);
-      miny = MAX2(miny, setup->scissor.current.miny);
-      maxy = MIN2(maxy, setup->scissor.current.maxy);
-   }
-   else {
-      minx = MAX2(minx, 0);
-      miny = MAX2(miny, 0);
-      maxx = MIN2(maxx, scene->fb.width);
-      maxy = MIN2(maxy, scene->fb.height);
-   }
-
-
-   if (miny >= maxy || minx >= maxx) {
-      lp_scene_putback_data( scene, tri_bytes );
-      LP_COUNT(nr_culled_tris);
-      return;
-   }
 
    /* 
     */
-   info.pixel_offset = setup->pixel_offset;
-   info.v0 = v1;
-   info.v1 = v2;
-   info.v2 = v3;
-   info.dx01 = info.v0[0][0] - info.v1[0][0];
-   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.0f / (info.dx01 * info.dy20 - info.dx20 * info.dy01);
+   dx01 = v0[0][0] - v1[0][0];
+   dy01 = v0[0][1] - v1[0][1];
+   dx20 = v2[0][0] - v0[0][0];
+   dy20 = v2[0][1] - v0[0][1];
+   oneoverarea = 1.0f / (dx01 * dy20 - dx20 * dy01);
+
+   info.v0 = v0;
+   info.v1 = v1;
+   info.v2 = v2;
    info.frontfacing = frontfacing;
+   info.x0_center = v0[0][0] - setup->pixel_offset;
+   info.y0_center = v0[0][1] - setup->pixel_offset;
+   info.dx01_ooa  = dx01 * oneoverarea;
+   info.dx20_ooa  = dx20 * oneoverarea;
+   info.dy01_ooa  = dy01 * oneoverarea;
+   info.dy20_ooa  = dy20 * oneoverarea;
 
    /* Setup parameter interpolants:
     */
-   setup_tri_coefficients( setup, tri, &info );
+   lp_setup_tri_coef( setup, &tri->inputs, &info );
 
    tri->inputs.facing = frontfacing ? 1.0F : -1.0F;
    tri->inputs.state = setup->fs.stored;
@@ -541,7 +326,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
       /* half-edge constants, will be interated over the whole render
        * target.
        */
-      plane->c = plane->dcdx * info.x[i] - plane->dcdy * info.y[i];
+      plane->c = plane->dcdx * x[i] - plane->dcdy * y[i];
 
       /* correct for top-left vs. bottom-left fill convention.  
        *
@@ -612,29 +397,43 @@ do_triangle_ccw(struct lp_setup_context *setup,
    if (nr_planes == 7) {
       tri->plane[3].dcdx = -1;
       tri->plane[3].dcdy = 0;
-      tri->plane[3].c = 1-minx;
+      tri->plane[3].c = 1-bbox.x0;
       tri->plane[3].ei = 0;
       tri->plane[3].eo = 1;
 
       tri->plane[4].dcdx = 1;
       tri->plane[4].dcdy = 0;
-      tri->plane[4].c = maxx;
+      tri->plane[4].c = bbox.x1+1;
       tri->plane[4].ei = -1;
       tri->plane[4].eo = 0;
 
       tri->plane[5].dcdx = 0;
       tri->plane[5].dcdy = 1;
-      tri->plane[5].c = 1-miny;
+      tri->plane[5].c = 1-bbox.y0;
       tri->plane[5].ei = 0;
       tri->plane[5].eo = 1;
 
       tri->plane[6].dcdx = 0;
       tri->plane[6].dcdy = -1;
-      tri->plane[6].c = maxy;
+      tri->plane[6].c = bbox.y1+1;
       tri->plane[6].ei = -1;
       tri->plane[6].eo = 0;
    }
 
+   lp_setup_bin_triangle( setup, tri, &bbox, nr_planes );
+}
+
+
+void
+lp_setup_bin_triangle( struct lp_setup_context *setup,
+                       struct lp_rast_triangle *tri,
+                       const struct u_rect *bbox,
+                       int nr_planes )
+{
+   struct lp_scene *scene = setup->scene;
+   struct lp_fragment_shader_variant *variant = setup->fs.current.variant;
+   int ix0, ix1, iy0, iy1;
+   int i;
 
    /*
     * All fields of 'tri' are now set.  The remaining code here is
@@ -643,10 +442,30 @@ do_triangle_ccw(struct lp_setup_context *setup,
 
    /* Convert to tile coordinates, and inclusive ranges:
     */
-   ix0 = minx / TILE_SIZE;
-   iy0 = miny / TILE_SIZE;
-   ix1 = (maxx-1) / TILE_SIZE;
-   iy1 = (maxy-1) / TILE_SIZE;
+   if (nr_planes == 3) {
+      int ix0 = bbox->x0 / 16;
+      int iy0 = bbox->y0 / 16;
+      int ix1 = bbox->x1 / 16;
+      int iy1 = bbox->y1 / 16;
+      
+      if (iy0 == iy1 && ix0 == ix1)
+      {
+
+        /* Triangle is contained in a single 16x16 block:
+         */
+        int mask = (ix0 & 3) | ((iy0 & 3) << 4);
+
+        lp_scene_bin_command( scene, ix0/4, iy0/4,
+                              lp_rast_triangle_3_16,
+                              lp_rast_arg_triangle(tri, mask) );
+        return;
+      }
+   }
+
+   ix0 = bbox->x0 / TILE_SIZE;
+   iy0 = bbox->y0 / TILE_SIZE;
+   ix1 = bbox->x1 / TILE_SIZE;
+   iy1 = bbox->y1 / TILE_SIZE;
 
    /*
     * Clamp to framebuffer size
@@ -799,9 +618,10 @@ static void triangle_both( struct lp_setup_context *setup,
    const float fy = v1[0][1] - v2[0][1];
 
    /* det = cross(e,f).z */
-   if (ex * fy - ey * fx < 0.0f) 
+   const float det = ex * fy - ey * fx;
+   if (det < 0.0f) 
       triangle_ccw( setup, v0, v1, v2 );
-   else
+   else if (det > 0.0f)
       triangle_cw( setup, v0, v1, v2 );
 }
 
index 77bec4640bb5517b4e83465df84119e0daf633b3..edd723f65f28700bad18f187bb340efa1d3a708b 100644 (file)
@@ -74,6 +74,15 @@ compute_vertex_info(struct llvmpipe_context *llvmpipe)
       vs_index = draw_find_shader_output(llvmpipe->draw,
                                          lpfs->info.input_semantic_name[i],
                                          lpfs->info.input_semantic_index[i]);
+      if (vs_index < 0) {
+         /*
+          * This can happen with sprite coordinates - the vertex
+          * shader doesn't need to provide an output as we generate
+          * them internally.  However, lets keep pretending that there
+          * is something there to not confuse other code.
+          */
+         vs_index = 0;
+      }
 
       /* This can be pre-computed, except for flatshade:
        */
@@ -125,6 +134,17 @@ compute_vertex_info(struct llvmpipe_context *llvmpipe)
       inputs[i].src_index = vinfo->num_attribs;
       draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index);
    }
+
+   /* Figure out if we need pointsize as well.
+    */
+   vs_index = draw_find_shader_output(llvmpipe->draw,
+                                      TGSI_SEMANTIC_PSIZE, 0);
+
+   if (vs_index > 0) {
+      llvmpipe->psize_slot = vinfo->num_attribs;
+      draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
+   }
+
    llvmpipe->num_inputs = lpfs->info.num_inputs;
 
    draw_compute_vertex_size(vinfo);
index dbca49a2efac8ffe66884f37bb57a2eee331395e..33c1a49efec66f7c4ac9747af18686e9e60cd556 100644 (file)
@@ -808,7 +808,7 @@ generate_variant(struct llvmpipe_context *lp,
    variant->list_item_local.base = variant;
    variant->no = shader->variants_created++;
 
-   memcpy(&variant->key, key, sizeof *key);
+   memcpy(&variant->key, key, shader->variant_key_size);
 
    if (gallivm_debug & GALLIVM_DEBUG_IR) {
       debug_printf("llvmpipe: Creating fragment shader #%u variant #%u:\n", 
@@ -840,6 +840,7 @@ llvmpipe_create_fs_state(struct pipe_context *pipe,
                          const struct pipe_shader_state *templ)
 {
    struct lp_fragment_shader *shader;
+   int nr_samplers;
 
    shader = CALLOC_STRUCT(lp_fragment_shader);
    if (!shader)
@@ -854,6 +855,11 @@ llvmpipe_create_fs_state(struct pipe_context *pipe,
    /* we need to keep a local copy of the tokens */
    shader->base.tokens = tgsi_dup_tokens(templ->tokens);
 
+   nr_samplers = shader->info.file_max[TGSI_FILE_SAMPLER] + 1;
+
+   shader->variant_key_size = Offset(struct lp_fragment_shader_variant_key,
+                                    sampler[nr_samplers]);
+
    if (LP_DEBUG & DEBUG_TGSI) {
       unsigned attrib;
       debug_printf("llvmpipe: Create fragment shader #%u %p:\n", shader->no, (void *) shader);
@@ -921,7 +927,6 @@ static void
 llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
 {
    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
-   struct pipe_fence_handle *fence = NULL;
    struct lp_fragment_shader *shader = fs;
    struct lp_fs_variant_list_item *li;
 
@@ -934,12 +939,7 @@ llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
     * Flushing alone might not sufficient we need to wait on it too.
     */
 
-   llvmpipe_flush(pipe, 0, &fence);
-
-   if (fence) {
-      pipe->screen->fence_finish(pipe->screen, fence, 0);
-      pipe->screen->fence_reference(pipe->screen, &fence, NULL);
-   }
+   llvmpipe_finish(pipe, __FUNCTION__);
 
    li = first_elem(&shader->variants);
    while(!at_end(&shader->variants, li)) {
@@ -1027,7 +1027,7 @@ make_variant_key(struct llvmpipe_context *lp,
 {
    unsigned i;
 
-   memset(key, 0, sizeof *key);
+   memset(key, 0, shader->variant_key_size);
 
    if (lp->framebuffer.zsbuf) {
       if (lp->depth_stencil->depth.enabled) {
@@ -1097,9 +1097,17 @@ make_variant_key(struct llvmpipe_context *lp,
       }
    }
 
-   for(i = 0; i < PIPE_MAX_SAMPLERS; ++i)
-      if(shader->info.file_mask[TGSI_FILE_SAMPLER] & (1 << i))
-         lp_sampler_static_state(&key->sampler[i], lp->fragment_sampler_views[i], lp->sampler[i]);
+   /* This value will be the same for all the variants of a given shader:
+    */
+   key->nr_samplers = shader->info.file_max[TGSI_FILE_SAMPLER] + 1;
+
+   for(i = 0; i < key->nr_samplers; ++i) {
+      if(shader->info.file_mask[TGSI_FILE_SAMPLER] & (1 << i)) {
+         lp_sampler_static_state(&key->sampler[i],
+                                lp->fragment_sampler_views[i],
+                                lp->sampler[i]);
+      }
+   }
 }
 
 /**
@@ -1118,7 +1126,7 @@ llvmpipe_update_fs(struct llvmpipe_context *lp)
 
    li = first_elem(&shader->variants);
    while(!at_end(&shader->variants, li)) {
-      if(memcmp(&li->base->key, &key, sizeof key) == 0) {
+      if(memcmp(&li->base->key, &key, shader->variant_key_size) == 0) {
          variant = li->base;
          break;
       }
@@ -1134,19 +1142,14 @@ llvmpipe_update_fs(struct llvmpipe_context *lp)
       unsigned i;
       if (lp->nr_fs_variants >= LP_MAX_SHADER_VARIANTS) {
          struct pipe_context *pipe = &lp->pipe;
-         struct pipe_fence_handle *fence = NULL;
 
          /*
           * XXX: we need to flush the context until we have some sort of reference
           * counting in fragment shaders as they may still be binned
           * Flushing alone might not be sufficient we need to wait on it too.
           */
-         llvmpipe_flush(pipe, 0, &fence);
+         llvmpipe_finish(pipe, __FUNCTION__);
 
-         if (fence) {
-            pipe->screen->fence_finish(pipe->screen, fence, 0);
-            pipe->screen->fence_reference(pipe->screen, &fence, NULL);
-         }
          for (i = 0; i < LP_MAX_SHADER_VARIANTS / 4; i++) {
             struct lp_fs_variant_list_item *item = last_elem(&lp->fs_variants_list);
             remove_shader_variant(lp, item->base);
index 37900fc54432297487c2848e3d7335c0439263a7..33c480010dd2422c37ca29160d96d6b0a6fcd779 100644 (file)
@@ -53,13 +53,10 @@ struct lp_fragment_shader_variant_key
    struct pipe_blend_state blend;
    enum pipe_format zsbuf_format;
    unsigned nr_cbufs:8;
+   unsigned nr_samplers:8;     /* actually derivable from just the shader */
    unsigned flatshade:1;
    unsigned occlusion_count:1;
 
-   struct {
-      ubyte colormask;
-   } cbuf_blend[PIPE_MAX_COLOR_BUFS];
-
    struct lp_sampler_static_state sampler[PIPE_MAX_SAMPLERS];
 };
 
@@ -97,6 +94,7 @@ struct lp_fragment_shader
    struct lp_fs_variant_list_item variants;
 
    /* For debugging/profiling purposes */
+   unsigned variant_key_size;
    unsigned no;
    unsigned variants_created;
    unsigned variants_cached;
index afd3e0b21c912c043a7672b41de020f3077e4c2d..0bad7320f3ef30699357849e54f26b8d57d24c1e 100644 (file)
@@ -73,7 +73,13 @@ llvmpipe_bind_rasterizer_state(struct pipe_context *pipe, void *handle)
                    llvmpipe->rasterizer->gl_rasterization_rules);
       lp_setup_set_flatshade_first( llvmpipe->setup,
                    llvmpipe->rasterizer->flatshade_first);
-   }
+      lp_setup_set_line_state( llvmpipe->setup,
+                   llvmpipe->rasterizer->line_width);
+      lp_setup_set_point_state( llvmpipe->setup,
+                   llvmpipe->rasterizer->point_size,
+                   llvmpipe->rasterizer->point_size_per_vertex,
+                   llvmpipe->rasterizer->sprite_coord_enable);
+       }
 
    llvmpipe->dirty |= LP_NEW_RASTERIZER;
 }
index d86e66b4fb87c579d1691667bec17907d03f7a91..fb29423dd3562e2559503a8d3c74764df5133cd2 100644 (file)
@@ -100,7 +100,7 @@ llvmpipe_set_index_buffer(struct pipe_context *pipe,
    else
       memset(&llvmpipe->index_buffer, 0, sizeof(llvmpipe->index_buffer));
 
-   /* TODO make this more like a state */
+   draw_set_index_buffer(llvmpipe->draw, ib);
 }
 
 void
index f761e8285000b2adea39f26bdfe5b658791ef4ab..63ddc669c2cc644a45df9c9922ae2360bf165785 100644 (file)
@@ -68,14 +68,16 @@ lp_resource_copy(struct pipe_context *pipe,
                            0, /* flush_flags */
                            FALSE, /* read_only */
                            TRUE, /* cpu_access */
-                           FALSE); /* do_not_block */
+                           FALSE,
+                           "blit dst"); /* do_not_block */
 
    llvmpipe_flush_resource(pipe,
                            src, subsrc.face, subsrc.level,
                            0, /* flush_flags */
                            TRUE, /* read_only */
                            TRUE, /* cpu_access */
-                           FALSE); /* do_not_block */
+                           FALSE,
+                           "blit src"); /* do_not_block */
 
    /*
    printf("surface copy from %u to %u: %u,%u to %u,%u %u x %u\n",
index 25112c10a662868c8393275a1ee798e3fda04f1d..5832ea274452af6cb4eabebe96aaf89e5990f7c6 100644 (file)
@@ -67,6 +67,7 @@ resource_is_texture(const struct pipe_resource *resource)
       return FALSE;
    case PIPE_TEXTURE_1D:
    case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_RECT:
    case PIPE_TEXTURE_3D:
    case PIPE_TEXTURE_CUBE:
       return TRUE;
@@ -583,7 +584,8 @@ llvmpipe_get_transfer(struct pipe_context *pipe,
                                    0, /* flush_flags */
                                    read_only,
                                    TRUE, /* cpu_access */
-                                   do_not_block)) {
+                                   do_not_block,
+                                   "transfer dest")) {
          /*
           * It would have blocked, but state tracker requested no to.
           */
index f44979e562c1aa57379cad901f853c77bc03d153..d9f35b4c4b9683813c5e228d02bae4702f786d7d 100644 (file)
@@ -6189,6 +6189,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define   NV34TCL_FP_REG_CONTROL_UNK1_MASK                                             0xffff0000
 #define   NV34TCL_FP_REG_CONTROL_UNK0_SHIFT                                            0
 #define   NV34TCL_FP_REG_CONTROL_UNK0_MASK                                             0x0000ffff
+#define  NV34TCL_FLATSHADE_FIRST                                                       0x00001454
+#define  NV34TCL_EDGEFLAG_ENABLE                                                       0x0000145c
 #define  NV34TCL_VP_CLIP_PLANES_ENABLE                                                 0x00001478
 #define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0                                         (1 <<  1)
 #define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1                                         (1 <<  5)
@@ -6222,10 +6224,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define  NV34TCL_VTXFMT__SIZE                                                          0x00000010
 #define   NV34TCL_VTXFMT_TYPE_SHIFT                                                    0
 #define   NV34TCL_VTXFMT_TYPE_MASK                                                     0x0000000f
-#define    NV34TCL_VTXFMT_TYPE_FLOAT                                                   0x00000002
-#define    NV34TCL_VTXFMT_TYPE_HALF                                                    0x00000003
-#define    NV34TCL_VTXFMT_TYPE_UBYTE                                                   0x00000004
-#define    NV34TCL_VTXFMT_TYPE_USHORT                                                  0x00000005
+#define    NV34TCL_VTXFMT_TYPE_16_SNORM                                                        0x00000001
+#define    NV34TCL_VTXFMT_TYPE_32_FLOAT                                                        0x00000002
+#define    NV34TCL_VTXFMT_TYPE_16_FLOAT                                                        0x00000003
+#define    NV34TCL_VTXFMT_TYPE_8_UNORM                                                 0x00000004
+#define    NV34TCL_VTXFMT_TYPE_16_SSCALED                                                      0x00000005
+#define    NV34TCL_VTXFMT_TYPE_11_11_10_SNORM                                                  0x00000006
+#define    NV34TCL_VTXFMT_TYPE_8_USCALED                                                       0x00000007
 #define   NV34TCL_VTXFMT_SIZE_SHIFT                                                    4
 #define   NV34TCL_VTXFMT_SIZE_MASK                                                     0x000000f0
 #define   NV34TCL_VTXFMT_STRIDE_SHIFT                                                  8
@@ -6368,6 +6373,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define    NV34TCL_TX_FORMAT_FORMAT_R8G8B8_RECT                                                0x00001e00
 #define    NV34TCL_TX_FORMAT_FORMAT_A8L8_RECT                                          0x00002000
 #define    NV34TCL_TX_FORMAT_FORMAT_DSDT8                                              0x00002800
+#define    NV34TCL_TX_FORMAT_FORMAT_Z24                                                        0x2a00
+#define    NV34TCL_TX_FORMAT_FORMAT_Z24_RECT                                           0x2b00 /* XXX: guess! */
+#define    NV34TCL_TX_FORMAT_FORMAT_Z16                                                        0x2c00
+#define    NV34TCL_TX_FORMAT_FORMAT_Z16_RECT                                           0x2d00 /* XXX: guess! */
 #define    NV34TCL_TX_FORMAT_FORMAT_HILO16                                             0x00003300
 #define    NV34TCL_TX_FORMAT_FORMAT_HILO16_RECT                                                0x00003600
 #define    NV34TCL_TX_FORMAT_FORMAT_HILO8                                              0x00004400
index 513e5e02bc05ab834b0f0c48d05532d978b752b0..ebb21a6e5a37d53b5c817c86cb24f38001453e12 100644 (file)
@@ -258,6 +258,7 @@ nouveau_screen_fini(struct nouveau_screen *screen)
 {
        struct pipe_winsys *ws = screen->base.winsys;
        nouveau_channel_free(&screen->channel);
-       ws->destroy(ws);
+       if (ws)
+               ws->destroy(ws);
 }
 
diff --git a/src/gallium/drivers/nouveau/nouveau_util.h b/src/gallium/drivers/nouveau/nouveau_util.h
deleted file mode 100644 (file)
index b165f7a..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-#ifndef __NOUVEAU_UTIL_H__
-#define __NOUVEAU_UTIL_H__
-
-/* Determine how many vertices can be pushed into the command stream.
- * Where the remaining space isn't large enough to represent all verices,
- * split the buffer at primitive boundaries.
- *
- * Returns a count of vertices that can be rendered, and an index to
- * restart drawing at after a flush.
- */
-static INLINE unsigned
-nouveau_vbuf_split(unsigned remaining, unsigned overhead, unsigned vpp,
-                  unsigned mode, unsigned start, unsigned count,
-                  unsigned *restart)
-{
-       int max, adj = 0;
-
-       max  = remaining - overhead;
-       if (max < 0)
-               return 0;
-
-       max *= vpp;
-       if (max >= count)
-               return count;
-
-       switch (mode) {
-       case PIPE_PRIM_POINTS:
-               break;
-       case PIPE_PRIM_LINES:
-               max = max & 1;
-               break;
-       case PIPE_PRIM_TRIANGLES:
-               max = max - (max % 3);
-               break;
-       case PIPE_PRIM_QUADS:
-               max = max & ~3;
-               break;
-       case PIPE_PRIM_LINE_LOOP:
-       case PIPE_PRIM_LINE_STRIP:
-               if (max < 2)
-                       max = 0;
-               adj = 1;
-               break;
-       case PIPE_PRIM_POLYGON:
-       case PIPE_PRIM_TRIANGLE_STRIP:
-       case PIPE_PRIM_TRIANGLE_FAN:
-               if (max < 3)
-                       max = 0;
-               adj = 2;
-               break;
-       case PIPE_PRIM_QUAD_STRIP:
-               if (max < 4)
-                       max = 0;
-               adj = 3;
-               break;
-       default:
-               assert(0);
-       }
-
-       *restart = start + max - adj;
-       return max;
-}
-
-/* Integer base-2 logarithm, rounded towards zero. */
-static INLINE unsigned log2i(unsigned i)
-{
-       unsigned r = 0;
-
-       if (i & 0xffff0000) {
-               i >>= 16;
-               r += 16;
-       }
-       if (i & 0x0000ff00) {
-               i >>= 8;
-               r += 8;
-       }
-       if (i & 0x000000f0) {
-               i >>= 4;
-               r += 4;
-       }
-       if (i & 0x0000000c) {
-               i >>= 2;
-               r += 2;
-       }
-       if (i & 0x00000002) {
-               r += 1;
-       }
-       return r;
-}
-
-#endif
index 12b5ad106caaf4136574e1fdd0a73c5d72533552..dd0e8fd41b1b4a238853bc1ab804770397106602 100644 (file)
@@ -238,7 +238,8 @@ nv50_miptree_from_handle(struct pipe_screen *pscreen,
        unsigned stride;
 
        /* Only supports 2D, non-mipmapped textures for the moment */
-       if (template->target != PIPE_TEXTURE_2D ||
+       if ((template->target != PIPE_TEXTURE_2D &&
+             template->target != PIPE_TEXTURE_RECT) ||
            template->last_level != 0 ||
            template->depth0 != 1)
                return NULL;
index 0091927a9822c842b14b88133bdbf6012b81e343..380f69406a27d8925d3be34e4fdda4bd89ac06b0 100644 (file)
@@ -108,8 +108,9 @@ emit_vertex(struct push_context *ctx, unsigned n)
    int i;
 
    if (ctx->edgeflag_attr < 16) {
-      float *edgeflag = (uint8_t *)ctx->attr[ctx->edgeflag_attr].map +
-                        ctx->attr[ctx->edgeflag_attr].stride * n;
+      float *edgeflag = (float *)
+         ((uint8_t *)ctx->attr[ctx->edgeflag_attr].map +
+          ctx->attr[ctx->edgeflag_attr].stride * n);
 
       if (*edgeflag != ctx->edgeflag) {
          BEGIN_RING(chan, tesla, NV50TCL_EDGEFLAG_ENABLE, 1);
index 55358183703583c33da22c4f8ce157083e6d7cd6..658324ec5bebc1aba6c266c860b3b1971946e24b 100644 (file)
@@ -83,6 +83,9 @@ nv50_tex_construct(struct nv50_sampler_view *view)
        case PIPE_TEXTURE_2D:
                tic[2] |= NV50TIC_0_2_TARGET_2D;
                break;
+       case PIPE_TEXTURE_RECT:
+               tic[2] |= NV50TIC_0_2_TARGET_RECT;
+               break;
        case PIPE_TEXTURE_3D:
                tic[2] |= NV50TIC_0_2_TARGET_3D;
                break;
index c1d57ca3969b10a27ea0d4c1e47ffe03a3fdc90d..6cbbad699eb5eb728a74fcffd300bf00302b2fab 100644 (file)
@@ -4,7 +4,7 @@ include $(TOP)/configs/current
 LIBNAME = nvfx
 
 C_SOURCES = \
-       nv04_surface_2d.c \
+       nv04_2d.c \
        nvfx_buffer.c \
        nvfx_context.c \
        nvfx_clear.c \
@@ -14,6 +14,7 @@ C_SOURCES = \
        nv30_fragtex.c \
        nv40_fragtex.c \
        nvfx_miptree.c \
+       nvfx_push.c \
        nvfx_query.c \
        nvfx_resource.c \
        nvfx_screen.c \
index 02d931b10e855cac9ed11cdc0db4f4f7ea211113..80e3ef2257f8d0e9bd837fba17f4e305d8d4de9b 100644 (file)
@@ -9,7 +9,7 @@ env.PrependUnique(delete_existing=1, CPPPATH = [
 nvfx = env.ConvenienceLibrary(
     target = 'nvfx',
     source = [
-        'nv04_surface_2d.c',
+        'nv04_2d.c',
         'nvfx_buffer.c',
         'nvfx_context.c',
         'nvfx_clear.c',
@@ -19,6 +19,7 @@ nvfx = env.ConvenienceLibrary(
         'nv30_fragtex.c',
         'nv40_fragtex.c',
         'nvfx_miptree.c',
+        'nvfx_push.c',
         'nvfx_query.c',
         'nvfx_resource.c',
         'nvfx_screen.c',
diff --git a/src/gallium/drivers/nvfx/nv04_2d.c b/src/gallium/drivers/nvfx/nv04_2d.c
new file mode 100644 (file)
index 0000000..c053122
--- /dev/null
@@ -0,0 +1,1341 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Ben Skeggs
+ * Copyright 2009 Younes Manton
+ * Copyright 2010 Luca Barbieri
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
+ * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ **************************************************************************/
+
+/* this code has no Mesa or Gallium dependency and can be reused in the classic Mesa driver or DDX */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <nouveau/nouveau_class.h>
+#include <nouveau/nouveau_device.h>
+#include <nouveau/nouveau_pushbuf.h>
+#include <nouveau/nouveau_channel.h>
+#include <nouveau/nouveau_bo.h>
+#include <nouveau/nouveau_notifier.h>
+#include <nouveau/nouveau_grobj.h>
+#include "nv04_2d.h"
+
+/* avoid depending on Mesa/Gallium */
+#ifdef __GNUC__
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#else
+#define likely(x) !!(x)
+#define unlikely(x) !!(x)
+#endif
+
+#define MIN2( A, B )   ( (A)<(B) ? (A) : (B) )
+#define MAX2( A, B )   ( (A)>(B) ? (A) : (B) )
+
+struct nv04_2d_context
+{
+       struct nouveau_notifier *ntfy;
+       struct nouveau_grobj *surf2d;
+       struct nouveau_grobj *swzsurf;
+       struct nouveau_grobj *m2mf;
+       struct nouveau_grobj *rect;
+       struct nouveau_grobj *sifm;
+       struct nouveau_grobj *blit;
+};
+
+static inline int
+align(int value, int alignment)
+{
+   return (value + alignment - 1) & ~(alignment - 1);
+}
+
+static inline int
+util_is_pot(unsigned x)
+{
+   return (x & (x - 1)) == 0;
+}
+
+/* Integer base-2 logarithm, rounded towards zero. */
+static inline unsigned log2i(unsigned i)
+{
+       unsigned r = 0;
+
+       if (i & 0xffff0000) {
+               i >>= 16;
+               r += 16;
+       }
+       if (i & 0x0000ff00) {
+               i >>= 8;
+               r += 8;
+       }
+       if (i & 0x000000f0) {
+               i >>= 4;
+               r += 4;
+       }
+       if (i & 0x0000000c) {
+               i >>= 2;
+               r += 2;
+       }
+       if (i & 0x00000002) {
+               r += 1;
+       }
+       return r;
+}
+
+//#define NV04_REGION_DEBUG
+
+// Yes, we really want to inline everything, since all the functions are used only once
+#if defined(__GNUC__) && defined(DEBUG)
+#define inline __attribute__((always_inline)) inline
+#endif
+
+static inline unsigned
+nv04_swizzle_bits_square(unsigned x, unsigned y)
+{
+       unsigned u = (x & 0x001) << 0 |
+                    (x & 0x002) << 1 |
+                    (x & 0x004) << 2 |
+                    (x & 0x008) << 3 |
+                    (x & 0x010) << 4 |
+                    (x & 0x020) << 5 |
+                    (x & 0x040) << 6 |
+                    (x & 0x080) << 7 |
+                    (x & 0x100) << 8 |
+                    (x & 0x200) << 9 |
+                    (x & 0x400) << 10 |
+                    (x & 0x800) << 11;
+
+       unsigned v = (y & 0x001) << 1 |
+                    (y & 0x002) << 2 |
+                    (y & 0x004) << 3 |
+                    (y & 0x008) << 4 |
+                    (y & 0x010) << 5 |
+                    (y & 0x020) << 6 |
+                    (y & 0x040) << 7 |
+                    (y & 0x080) << 8 |
+                    (y & 0x100) << 9 |
+                    (y & 0x200) << 10 |
+                    (y & 0x400) << 11 |
+                    (y & 0x800) << 12;
+       return v | u;
+}
+
+/* rectangular swizzled textures are linear concatenations of swizzled square tiles */
+static inline unsigned
+nv04_swizzle_bits_2d(unsigned x, unsigned y, unsigned w, unsigned h)
+{
+       if(h <= 1)
+               return x;
+       else
+       {
+               unsigned s = MIN2(w, h);
+               unsigned m = s - 1;
+               return (((x | y) & ~m) * s) | nv04_swizzle_bits_square(x & m, y & m);
+       }
+}
+
+// general 3D texture case
+static inline unsigned
+nv04_swizzle_bits(unsigned x, unsigned y, unsigned z, unsigned w, unsigned h, unsigned d)
+{
+       if(d <= 1)
+               return nv04_swizzle_bits_2d(x, y, w, h);
+       else
+       {
+               // TODO: autogenerate code for all possible texture sizes (13 * 13 * 13 with dims <= 4096) and do a single indirect call
+               unsigned v = 0;
+               w >>= 1;
+               h >>= 1;
+               d >>= 1;
+               for(int i = 0;;)
+               {
+                       int oldi = i;
+                       if(likely(w))
+                       {
+                               v |= (x & 1) << i;
+                               x >>= 1;
+                               w >>= 1;
+                               ++i;
+                       }
+
+                       if(likely(h))
+                       {
+                               v |= (y & 1) << i;
+                               y >>= 1;
+                               h >>= 1;
+                               ++i;
+                       }
+
+                       if(likely(d))
+                       {
+                               v |= (z & 1) << i;
+                               z >>= 1;
+                               d >>= 1;
+                               ++i;
+                       }
+
+                       if(i == oldi)
+                               break;
+               }
+               return v;
+       }
+}
+
+unsigned
+nv04_region_begin(struct nv04_region* rgn, unsigned w, unsigned h)
+{
+       if(rgn->pitch)
+               return rgn->pitch * rgn->y + (rgn->x << rgn->bpps);
+       else
+               return nv04_swizzle_bits(rgn->x, rgn->y, rgn->z, rgn->w, rgn->h, rgn->d) << rgn->bpps;
+}
+
+unsigned
+nv04_region_end(struct nv04_region* rgn, unsigned w, unsigned h)
+{
+       if(rgn->pitch)
+               return rgn->pitch * (rgn->y + h - 1) + ((rgn->x + w) << rgn->bpps);
+       else
+               return (nv04_swizzle_bits(rgn->x + w - 1, rgn->y + h - 1, rgn->z, rgn->w, rgn->h, rgn->d) + 1) << rgn->bpps;
+}
+
+// *pitch = -1 -> use 3D swizzling for (x, y), *pitch = 0 -> use 2D swizzling, other *pitch -> use linear calculations
+// returns 2 if pixel order is 3D-swizzled and 1 if subrect is 2D-swizzled
+/* *pitch == -1 ret = 0 -> 3D swizzled subrect
+ * *pitch == 0 ret = 0 -> 2D swizzled subrect
+ * *pitch > 0 ret = 0 -> linear subrect
+ * *pitch > 0 ret = 1 -> linear subrect, but with swizzled 3D data inside
+ */
+
+static inline void
+nv04_region_print(struct nv04_region* rgn)
+{
+       fprintf(stderr, "<%i[%i]> ", rgn->bo->handle, rgn->offset);
+       if(rgn->pitch)
+               fprintf(stderr, "lin %i", rgn->pitch);
+       else
+               fprintf(stderr, "swz %ix%ix%i", rgn->w, rgn->h, rgn->d);
+       fprintf(stderr, " (%i, %i, %i)", rgn->x, rgn->y, rgn->z);
+}
+
+static inline void
+nv04_region_assert(struct nv04_region* rgn, unsigned w, unsigned h)
+{
+       unsigned end = rgn->offset + nv04_region_end(rgn, w, h);
+
+       assert(rgn->offset <= (int)rgn->bo->size);
+       assert(end <= rgn->bo->size);
+       (void) end;
+       if(!rgn->pitch) {
+               assert(util_is_pot(rgn->w));
+               assert(util_is_pot(rgn->h));
+       }
+}
+
+/* determine if region can be linearized or fake-linearized */
+static inline int
+nv04_region_is_contiguous(struct nv04_region* rgn, int w, int h)
+{
+       int surf_min;
+       int rect_min;
+
+       if(rgn->pitch)
+               return rgn->pitch == w << rgn->bpps;
+
+       // redundant, but this is the fast path for the common case
+       if(w == rgn->w && h == rgn->h && rgn->d <= 1)
+               return 1;
+
+       // must be POT
+       if((w & (w - 1)) || (h & (h - 1)))
+               return 0;
+
+       // must be aligned
+       if((rgn->x & (w - 1)) || (rgn->y & (h - 1)))
+               return 0;
+
+       if(rgn->d > 1)
+               return 0;
+
+       surf_min = MIN2(rgn->w, rgn->h);
+       rect_min = MIN2(w, h);
+
+       if((rect_min == surf_min) || (w == h) || (w == 2 * h))
+               return 1;
+
+       return 0;
+}
+
+// double the pitch until it is larger than the alignment, or the height becomes odd or 1
+static inline void
+nv04_region_contiguous_shape(struct nv04_region* rgn, int* w, int* h, int align)
+{
+       while(!(*h & 1) && (*w << rgn->bpps) < (1 << align))
+       {
+               *w <<= 1;
+               *h >>= 1;
+       }
+
+       while((*w << rgn->bpps) > 16384 && !(*w & 1))
+       {
+               *w >>= 1;
+               *h <<= 1;
+       }
+
+#ifdef NV04_REGION_DEBUG
+       fprintf(stderr, "\tCONTIGUOUS %ix%i\n", *w, *h);
+#endif
+}
+
+static inline void
+nv04_region_linearize_contiguous(struct nv04_region* rgn, unsigned w, unsigned h)
+{
+       int pos;
+       if(rgn->pitch)
+       {
+               rgn->offset += rgn->y * rgn->pitch + (rgn->x << rgn->bpps);
+               rgn->x = 0;
+               rgn->y = 0;
+       }
+       else
+       {
+               rgn->offset += (rgn->w * rgn->h * rgn->z) << rgn->bpps;
+               pos = nv04_swizzle_bits(rgn->x, rgn->y, rgn->z, rgn->w, rgn->h, rgn->d);
+               rgn->x = pos & (w - 1);
+               rgn->y = pos / w;
+       }
+       rgn->pitch = w << rgn->bpps;
+
+#ifdef NV04_REGION_DEBUG
+       fprintf(stderr, "\tLINEARIZE ");
+       nv04_region_print(rgn);
+       fprintf(stderr, "\n");
+#endif
+}
+
+       /* preserve the offset! */
+       /*
+       rgn->pitch = util_format_get_stride(rgn->format, w);
+       int pos = nv04_swizzle_bits(rgn->x, rgn->y, rgn->z, rgn->w, rgn->h, rgn->d);
+       rgn->x = pos & (w - 1);
+       rgn->y = pos & ~(w - 1);
+       */
+
+       /*
+       rgn->offset +=
+       rgn->pitch = util_format_get_stride(rgn->format, w);
+       rgn->x = 0;
+       rgn->y = 0;
+       */
+
+/* This code will get used for, and always succeed on:
+ * - 4x2 1bpp swizzled texture mipmap levels
+ * - linear regions created by linearization
+ *
+ * This code will get used for, and MAY work for:
+ * - misaligned texture blanket
+ * - linear surfaces created without wide_pitch (in this case, it will only work if we are lucky)
+ *
+ * The general case requires splitting the region in 2.
+ */
+static inline int
+nv04_region_do_align_offset(struct nv04_region* rgn, unsigned w, unsigned h, int shift)
+{
+       if(rgn->pitch > 0)
+       {
+               int delta;
+
+               assert(!(rgn->offset & ((1 << rgn->bpps) - 1))); // fatal!
+               delta = rgn->offset & ((1 << shift) - 1);
+
+               if(h <= 1)
+               {
+                       rgn->x += delta >> rgn->bpps;
+                       rgn->offset -= delta;
+                       rgn->pitch = align((rgn->x + w) << rgn->bpps, 1 << shift);
+               }
+               else
+               {
+                       int newxo = (rgn->x << rgn->bpps) + delta;
+                       int dy = newxo / rgn->pitch;
+                       newxo -= dy * rgn->pitch;
+                       if((newxo + (w << rgn->bpps)) > rgn->pitch)
+                       {
+                               // TODO: split the region into two rectangles (!) if *really* necessary, unless the hardware actually supports "wrapping" rectangles
+                               // this does not happen if the surface is pitch-aligned, which it should always be
+                               assert(0);
+                               return -1;
+                       }
+                       rgn->x = newxo >> rgn->bpps;
+                       rgn->y += dy;
+               }
+       }
+       else
+       {
+               int size;
+               int min;
+               int v;
+
+               // we don't care about the alignment of 3D surfaces since the 2D engine can't use them
+               if(rgn->d < 0)
+                       return -1;
+
+               min = MIN2(rgn->w, rgn->h);
+               size = min * min << rgn->bpps;
+
+               // this is unfixable, and should not be happening
+               if(rgn->offset & (size - 1))
+                       return -1;
+
+               v = (rgn->offset & ((1 << shift) - 1)) / size;
+               rgn->offset -= v * size;
+
+               if(rgn->h == min)
+               {
+                       unsigned w;
+                       rgn->x += rgn->h * v;
+                       w = rgn->w + rgn->h * v;
+
+                       while(rgn->w < w)
+                               rgn->w += rgn->w;
+               }
+               else
+               {
+                       unsigned h;
+                       rgn->y += rgn->w * v;
+                       h = rgn->h + rgn->w * v;
+
+                       while(rgn->h < h)
+                               rgn->h += rgn->h;
+               }
+       }
+
+#ifdef NV04_REGION_DEBUG
+       fprintf(stderr, "\tALIGNED ");
+       nv04_region_print(rgn);
+       fprintf(stderr, "\n");
+#endif
+       return 0;
+}
+
+// both pitch and shift
+// will leave the region unchanged if it fails
+static inline int
+nv04_region_align(struct nv04_region* rgn, unsigned w, unsigned h, int shift)
+{
+       if(rgn->pitch & ((1 << shift) - 1))
+       {
+               if(h == 1)
+                       goto do_align; /* this will fix pitch too in this case */
+               else
+                       return -1;
+       }
+
+       if(rgn->offset & ((1 << shift) - 1))
+       {
+               do_align:
+               if(nv04_region_do_align_offset(rgn, w, h, shift))
+                       return -1;
+       }
+       return 0;
+}
+
+/* this contains 22 different copy loops after preprocessing. unfortunately, it's necessary */
+void
+nv04_region_copy_cpu(struct nv04_region* dst, struct nv04_region* src, int w, int h)
+{
+       uint8_t* mdst;
+       uint8_t* msrc;
+       int size;
+
+       if(dst->bo != src->bo)
+       {
+               nouveau_bo_map(dst->bo, NOUVEAU_BO_WR);
+               nouveau_bo_map(src->bo, NOUVEAU_BO_RD);
+       }
+       else
+               nouveau_bo_map(dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_RD);
+
+       mdst = (uint8_t*)dst->bo->map + dst->offset;
+       msrc = (uint8_t*)src->bo->map + src->offset;
+
+       size = w << dst->bpps;
+
+       nv04_region_assert(dst, w, h);
+       nv04_region_assert(src, w, h);
+
+#ifdef NV04_REGION_DEBUG
+       fprintf(stderr, "\tRGN_COPY_CPU [%i, %i: %i] ", w, h, dst->bpps);
+       for(int i = 0; i < 2; ++i)
+       {
+               nv04_region_print(i ? src : dst);
+               fprintf(stderr, i ? "\n" : " <- ");
+       }
+
+//     for(int i = 0; i < 16; ++i)
+//             fprintf(stderr, "%02x ", msrc[i]);
+//     fprintf(stderr, "\n");
+#endif
+
+       // TODO: support overlapping copies!
+       if(src->pitch && dst->pitch)
+       {
+               mdst += dst->y * dst->pitch + (dst->x << dst->bpps);
+               msrc += src->y * src->pitch + (src->x << src->bpps);
+               if(dst->bo != src->bo)
+                       goto simple;
+               else if(mdst < msrc)
+               {
+                       if(mdst + size <= msrc)
+                       {
+simple:
+                               for(int iy = 0; iy < h; ++iy)
+                               {
+                                       assert(mdst + size <= (uint8_t*)dst->bo->map + dst->bo->size);
+                                       assert(msrc + size <= (uint8_t*)src->bo->map + src->bo->size);
+                                       memcpy(mdst, msrc, size);
+                                       msrc += src->pitch; mdst += dst->pitch;
+                               }
+                       }
+                       else
+                       {
+                               for(int iy = 0; iy < h; ++iy)
+                               {
+                                       assert(mdst + size <= (uint8_t*)dst->bo->map + dst->bo->size);
+                                       assert(msrc + size <= (uint8_t*)src->bo->map + src->bo->size);
+                                       memmove(mdst, msrc, size);
+                                       msrc += src->pitch; mdst += dst->pitch;
+                               }
+                       }
+               }
+               else
+               {
+                       /* copy backwards so we don't destroy data we have to read yet */
+                       if(msrc + size <= mdst)
+                       {
+                               for(int iy = h - 1; iy >= 0; --iy)
+                               {
+                                       assert(mdst + size <= (uint8_t*)dst->bo->map + dst->bo->size);
+                                       assert(msrc + size <= (uint8_t*)src->bo->map + src->bo->size);
+                                       memcpy(mdst, msrc, size);
+                                       msrc += src->pitch; mdst += dst->pitch;
+                               }
+                       }
+                       else
+                       {
+                               for(int iy = h - 1; iy >= 0; --iy)
+                               {
+                                       assert(mdst + size <= (uint8_t*)dst->bo->map + dst->bo->size);
+                                       assert(msrc + size <= (uint8_t*)src->bo->map + src->bo->size);
+                                       memmove(mdst, msrc, size);
+                                       msrc += src->pitch; mdst += dst->pitch;
+                               }
+                       }
+               }
+       }
+       else
+       {
+               int* dswx = NULL;
+               int* dswy = NULL;
+               int* sswx = NULL;
+               int* sswy = NULL;
+               int dir;
+
+               if(!dst->pitch)
+               {
+                       dswx = alloca(w * sizeof(int));
+                       for(int ix = 0; ix < w; ++ix) // we are adding, so z cannot be contributed by both
+                               dswx[ix] = nv04_swizzle_bits(dst->x + ix, 0, 0, dst->w, dst->h, dst->d);
+                       dswy = alloca(h * sizeof(int));
+                       for(int iy = 0; iy < h; ++iy)
+                               dswy[iy] = nv04_swizzle_bits(0, dst->y + iy, dst->z, dst->w, dst->h, dst->d);
+               }
+
+               if(!src->pitch)
+               {
+                       sswx = alloca(w * sizeof(int));
+                       for(int ix = 0; ix < w; ++ix)
+                               sswx[ix] = nv04_swizzle_bits(src->x + ix, 0, 0, src->w, src->h, src->d);
+                       sswy = alloca(h * sizeof(int));
+                       for(int iy = 0; iy < h; ++iy)
+                               sswy[iy] = nv04_swizzle_bits(0, src->y + iy, src->z, src->w, src->h, src->d);
+               }
+
+               dir = 1;
+               /* do backwards copies for overlapping swizzled surfaces */
+               if(dst->pitch == src->pitch && dst->offset == src->offset)
+               {
+                       if(dst->y > src->y || (dst->y == src->y && dst->x > src->x))
+                               dir = -1;
+               }
+
+#define SWIZZLED_COPY_LOOPS
+               if(dir == 1)
+               {
+                       int dir = 1;
+#define LOOP_Y for(int iy = 0; iy < h; ++iy)
+#define LOOP_X for(int ix = 0; ix < w; ++ix)
+#include "nv04_2d_loops.h"
+#undef LOOP_X
+#undef LOOP_Y
+               }
+               else
+               {
+                       int dir = -1;
+#define LOOP_Y for(int iy = h - 1; iy >= 0; --iy)
+#define LOOP_X for(int ix = w - 1; ix >= 0; --ix)
+#include "nv04_2d_loops.h"
+#undef LOOP_X
+#undef LOOP_Y
+               }
+#undef SWIZZLED_COPY_LOOP
+       }
+
+       if(src->bo != dst->bo)
+               nouveau_bo_unmap(src->bo);
+       nouveau_bo_unmap(dst->bo);
+}
+
+/* TODO: if the destination is swizzled, we are doing random writes, which causes write combining to fail
+ * the alternative is to read, modify and copy back, which may or may not be faster
+ * loading 3D textures is a common case that hits this and could probably benefit from the temporary
+ */
+void
+nv04_region_fill_cpu(struct nv04_region* dst, int w, int h, unsigned value)
+{
+       uint8_t* mdst = (nouveau_bo_map(dst->bo, NOUVEAU_BO_WR), (uint8_t*)dst->bo->map + dst->offset);
+
+#ifdef NV04_REGION_DEBUG
+       fprintf(stderr, "\tRGN_FILL_CPU ");
+       nv04_region_print(dst);
+       fprintf(stderr, "\n");
+#endif
+
+       nv04_region_assert(dst, w, h);
+
+       if(dst->pitch)
+       {
+               unsigned size = w << dst->bpps;
+
+#define FILL(T) do { \
+                       for(int iy = 0; iy < h; ++iy) \
+                       { \
+                               assert((char*)((T*)mdst + w) <= (char*)dst->bo->map + dst->bo->size); \
+                               for(int ix = 0; ix < w; ++ix) \
+                                       ((T*)mdst)[ix] = (T)value; \
+                               mdst += dst->pitch; \
+                       } \
+               } while(0)
+
+               mdst += dst->y * dst->pitch + (dst->x << dst->bpps);
+
+               if(dst->bpps == 0)
+               {
+ms:
+                       assert(mdst + size * h <= (uint8_t*)dst->bo->map + dst->bo->size);
+                       if(size == dst->pitch)
+                               memset(mdst, (uint8_t)value, size * h);
+                       else
+                       {
+                               for(int iy = 0; iy < h; ++iy)
+                               {
+                                       assert(mdst + size <= (uint8_t*)dst->bo->map + dst->bo->size);
+                                       memset(mdst, (uint8_t)value, size);
+                                       mdst += dst->pitch;
+                               }
+                       }
+               }
+               else if(dst->bpps == 1)
+               {
+                       if(!((uint8_t)value ^ (uint8_t)(value >> 8)))
+                               goto ms;
+
+                       FILL(uint16_t);
+               }
+               else if(dst->bpps == 2)
+               {
+                       if(value == (uint8_t)value * 0x1010101)
+                               goto ms;
+                       FILL(uint32_t);
+               }
+               else
+                       assert(0);
+#undef FILL
+       }
+       else
+       {
+               int* dswx;
+               int* dswy;
+
+               dswx = alloca(w * sizeof(int));
+               for(int ix = 0; ix < w; ++ix)
+                       dswx[ix] = nv04_swizzle_bits(dst->x + ix, 0, dst->z, dst->w, dst->h, dst->d);
+               dswy = alloca(h * sizeof(int));
+               for(int iy = 0; iy < h; ++iy)
+                       dswy[iy] = nv04_swizzle_bits(0, dst->y + iy, dst->z, dst->w, dst->h, dst->d);
+
+#define FILL(T) do { \
+                       T tvalue = (T)value; \
+                       for(int iy = 0; iy < h; ++iy) \
+                       { \
+                               T* pdst = (T*)mdst + dswy[iy]; \
+                               for(int ix = 0; ix < w; ++ix) \
+                               { \
+                                       assert((uint8_t*)&pdst[dswx[ix] + 1] <= (uint8_t*)dst->bo->map + dst->bo->size); \
+                                       pdst[dswx[ix]] = tvalue; \
+                               } \
+                       } \
+               } while(0)
+
+               if(dst->bpps == 0)
+                       FILL(uint8_t);
+               else if(dst->bpps == 1)
+                       FILL(uint16_t);
+               else if(dst->bpps == 2)
+                       FILL(uint32_t);
+               else
+                       assert(0 && "unhandled bpp");
+#undef FILL
+       }
+
+       nouveau_bo_unmap(dst->bo);
+}
+
+static void
+nv04_region_copy_swizzle(struct nv04_2d_context *ctx,
+                         struct nv04_region* dst,
+                         struct nv04_region* src,
+                         int w, int h, int cs2d_format, int sifm_format)
+{
+       struct nouveau_channel *chan = ctx->swzsurf->channel;
+       struct nouveau_grobj *swzsurf = ctx->swzsurf;
+       struct nouveau_grobj *sifm = ctx->sifm;
+       /* Max width & height may not be the same on all HW, but must be POT */
+       unsigned max_shift = 10;
+       unsigned cw = 1 << max_shift;
+       unsigned ch = 1 << max_shift;
+       unsigned sx = dst->x >> max_shift;
+       unsigned sy = dst->y >> max_shift;
+       unsigned ex = (dst->x + w - 1) >> max_shift;
+       unsigned ey = (dst->y + h - 1) >> max_shift;
+       unsigned chunks = (ex - sx + 1) * (ey - sy + 1);
+       unsigned chunk_size;
+       if(dst->w < cw)
+               cw = dst->w;
+       if(dst->h < ch)
+               ch = dst->h;
+       chunk_size = cw * ch << dst->bpps;
+
+#ifdef NV04_REGION_DEBUG
+       fprintf(stderr, "\tRGN_COPY_SWIZZLE [%i, %i: %i] ", w, h, dst->bpps);
+       for(int i = 0; i < 2; ++i)
+       {
+               nv04_region_print(i ? src : dst);
+               fprintf(stderr, i ? "\n" : " <- ");
+       }
+#endif
+
+       nv04_region_assert(dst, w, h);
+       nv04_region_assert(src, w, h);
+
+       MARK_RING (chan, 8 + chunks * 17, 2 + chunks * 2);
+
+       BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE, 1);
+       OUT_RELOCo(chan, dst->bo,
+                       NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+       BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_FORMAT, 1);
+       OUT_RING  (chan, cs2d_format |
+                        log2i(cw) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT |
+                        log2i(ch) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT);
+
+       BEGIN_RING(chan, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
+       OUT_RELOCo(chan, src->bo,
+                        NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+       BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1);
+       OUT_RING  (chan, swzsurf->handle);
+
+       assert(!(dst->offset & 63));
+
+       for (int cy = sy; cy <= ey; ++cy) {
+         int ry = MAX2(0, (int)(dst->y - ch * cy));
+         int rh = MIN2((int)ch, (int)(dst->y - ch * cy + h)) - ry;
+         for (int cx = sx; cx <= ex; ++cx) {
+           int rx = MAX2(0, (int)(dst->x - cw * cx));
+           int rw = MIN2((int)cw, (int)(dst->x - cw * cx + w)) - rx;
+           unsigned dst_offset;
+           unsigned src_offset;
+
+           BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_OFFSET, 1);
+
+           dst_offset = dst->offset + (nv04_swizzle_bits_2d(cx * cw, cy * ch, dst->w, dst->h) << dst->bpps);
+           assert(dst_offset <= dst->bo->size);
+           assert(dst_offset + chunk_size <= dst->bo->size);
+           OUT_RELOCl(chan, dst->bo, dst_offset,
+                           NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+           BEGIN_RING(chan, sifm, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9);
+           OUT_RING  (chan, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
+           OUT_RING  (chan, sifm_format);
+           OUT_RING  (chan, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
+           OUT_RING  (chan, rx | (ry << NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y_SHIFT));
+           OUT_RING  (chan, rh << NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H_SHIFT | rw);
+           OUT_RING  (chan, rx | (ry << NV03_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_Y_SHIFT));
+           OUT_RING  (chan, rh << NV03_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_H_SHIFT | rw);
+           OUT_RING  (chan, 1 << 20);
+           OUT_RING  (chan, 1 << 20);
+
+           BEGIN_RING(chan, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
+           OUT_RING  (chan, rh << NV03_SCALED_IMAGE_FROM_MEMORY_SIZE_H_SHIFT | align(rw, 8));
+           OUT_RING  (chan, src->pitch |
+                            NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
+                            NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
+           src_offset = src->offset + (cy * ch + ry + src->y - dst->y) * src->pitch + ((cx * cw + rx + src->x - dst->x) << src->bpps);
+           assert(src_offset <= src->bo->size);
+           assert(src_offset + (src->pitch * (rh - 1)) + (rw << src->bpps) <= src->bo->size);
+           OUT_RELOCl(chan, src->bo, src_offset,
+                            NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+           OUT_RING  (chan, 0);
+         }
+       }
+}
+
+static inline void
+nv04_copy_m2mf_begin(struct nv04_2d_context *ctx, struct nouveau_bo* dstbo, struct nouveau_bo* srcbo, unsigned commands)
+{
+       struct nouveau_channel *chan = ctx->m2mf->channel;
+       struct nouveau_grobj *m2mf = ctx->m2mf;
+       MARK_RING (chan, 3 + commands * 9, 2 + commands * 2);
+       BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
+       OUT_RELOCo(chan, srcbo,
+                  NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+       OUT_RELOCo(chan, dstbo,
+                  NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+}
+
+static inline void
+nv04_copy_m2mf_body(struct nv04_2d_context *ctx, struct nouveau_bo* dstbo, int* pdstoff, unsigned dstpitch, struct nouveau_bo* srcbo, int* psrcoff, unsigned srcpitch, unsigned size, unsigned lines)
+{
+       struct nouveau_channel *chan = ctx->m2mf->channel;
+       struct nouveau_grobj *m2mf = ctx->m2mf;
+
+#ifdef NV04_REGION_DEBUG
+       fprintf(stderr, "\t\t\tCOPY_M2MF_BODY [%i, %i] <%i[%u]> lin %u <- <%i[%u]> lin %u\n", size, lines, dstbo->handle, *pdstoff, dstpitch, srcbo->handle, *psrcoff, srcpitch);
+#endif
+
+       BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+       OUT_RELOCl(chan, srcbo, *psrcoff,
+                  NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+       OUT_RELOCl(chan, dstbo, *pdstoff,
+                  NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR);
+       OUT_RING  (chan, srcpitch);
+       OUT_RING  (chan, dstpitch);
+       OUT_RING  (chan, size);
+       OUT_RING  (chan, lines);
+       OUT_RING  (chan, 0x0101);
+       OUT_RING  (chan, 0);
+
+       *psrcoff += srcpitch * lines;
+       *pdstoff += dstpitch * lines;
+}
+
+static void
+nv04_copy_m2mf(struct nv04_2d_context *ctx,
+               struct nouveau_bo* dstbo, int dstoff, unsigned dstpitch,
+               struct nouveau_bo* srcbo, int srcoff, unsigned srcpitch,
+               unsigned size, unsigned h)
+{
+       unsigned max_pitch = 32767;
+       unsigned max_lines = 2047;
+
+#ifdef NV04_REGION_DEBUG
+       fprintf(stderr, "\t\tCOPY_M2MF [%i, %i] <%i[%i]> lin %u <- <%i[%i]> lin %u\n", size, h, dstbo->handle, dstoff, dstpitch, srcbo->handle, srcoff, srcpitch);
+#endif
+
+       if(srcpitch <= max_pitch && dstpitch <= max_pitch)
+       {
+               unsigned full_pages = h / max_lines;
+               unsigned leftover_lines = h - full_pages * max_lines;
+
+               nv04_copy_m2mf_begin(ctx, dstbo, srcbo, full_pages + !!leftover_lines);
+
+               for(unsigned i = 0; i < full_pages; ++i)
+                       nv04_copy_m2mf_body(ctx, dstbo, &dstoff, dstpitch, srcbo, &srcoff, srcpitch, size, max_lines);
+
+               if(leftover_lines)
+                       nv04_copy_m2mf_body(ctx, dstbo, &dstoff, dstpitch, srcbo, &srcoff, srcpitch, size, leftover_lines);
+       }
+       else
+       {
+               unsigned lines = size / max_pitch;
+               unsigned leftover = size - lines * max_pitch;
+               unsigned full_pages = lines / max_lines;
+               unsigned leftover_lines = lines - full_pages * max_lines;
+               unsigned srcgap = srcpitch - size;
+               unsigned dstgap = dstpitch - size;
+
+               nv04_copy_m2mf_begin(ctx, dstbo, srcbo, h * (full_pages + !!leftover_lines + !!leftover));
+
+               for(unsigned i = 0; i < h; ++i)
+               {
+                       for(unsigned j = 0; j < full_pages; ++j)
+                               nv04_copy_m2mf_body(ctx, dstbo, &dstoff, max_pitch, srcbo, &srcoff, max_pitch, max_pitch, max_lines);
+
+                       if(leftover_lines)
+                               nv04_copy_m2mf_body(ctx, dstbo, &dstoff, max_pitch, srcbo, &srcoff, max_pitch, max_pitch, leftover_lines);
+
+                       if(leftover)
+                               nv04_copy_m2mf_body(ctx, dstbo, &dstoff, leftover, srcbo, &srcoff, leftover, leftover, 1);
+
+                       srcoff += srcgap;
+                       dstoff += dstgap;
+               }
+       }
+}
+
+void
+nv04_memcpy(struct nv04_2d_context *ctx, struct nouveau_bo* dstbo, int dstoff, struct nouveau_bo* srcbo, int srcoff, unsigned size)
+{
+#ifdef NV04_REGION_DEBUG
+       fprintf(stderr, "\tMEMCPY [%i] <%i[%i]> <- <%i[%i]>\n", size, dstbo->handle, dstoff, srcbo->handle, srcoff);
+#endif
+
+       nv04_copy_m2mf(ctx, dstbo, dstoff, size, srcbo, srcoff, size, size, 1);
+}
+
+static void
+nv04_region_copy_m2mf(struct nv04_2d_context *ctx, struct nv04_region *dst, struct nv04_region *src, int w, int h)
+{
+#ifdef NV04_REGION_DEBUG
+       fprintf(stderr, "\tRGN_COPY_M2MF [%i, %i: %i] ", w, h, dst->bpps);
+       for(int i = 0; i < 2; ++i)
+       {
+               nv04_region_print(i ? src : dst);
+               fprintf(stderr, i ? "\n" : " <- ");
+       }
+#endif
+
+       nv04_region_assert(dst, w, h);
+       nv04_region_assert(src, w, h);
+       assert(src->pitch);
+       assert(dst->pitch);
+
+       nv04_copy_m2mf(ctx,
+                       dst->bo, dst->offset + dst->y * dst->pitch + (dst->x << dst->bpps), dst->pitch,
+                       src->bo, src->offset + src->y * src->pitch + (src->x << src->bpps), src->pitch,
+                       w << src->bpps, h);
+}
+
+static inline void
+nv04_region_copy_blit(struct nv04_2d_context *ctx, struct nv04_region* dst, struct nv04_region* src, int w, int h, int format)
+{
+       struct nouveau_channel *chan = ctx->surf2d->channel;
+       struct nouveau_grobj *surf2d = ctx->surf2d;
+       struct nouveau_grobj *blit = ctx->blit;
+
+#ifdef NV04_REGION_DEBUG
+       fprintf(stderr, "\tRGN_COPY_BLIT [%i, %i: %i] ", w, h, dst->bpps);
+       for(int i = 0; i < 2; ++i)
+       {
+               nv04_region_print(i ? src : dst);
+               fprintf(stderr, i ? "\n" : " <- ");
+       }
+#endif
+
+       assert(!(src->pitch & 63) && src->pitch);
+       assert(!(dst->pitch & 63) && dst->pitch);
+       nv04_region_assert(dst, w, h);
+       nv04_region_assert(src, w, h);
+
+       MARK_RING (chan, 12, 4);
+       BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
+       OUT_RELOCo(chan, src->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+       OUT_RELOCo(chan, dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+       BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
+       OUT_RING  (chan, format);
+       OUT_RING  (chan, (dst->pitch << 16) | src->pitch);
+       OUT_RELOCl(chan, src->bo, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+       OUT_RELOCl(chan, dst->bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+       BEGIN_RING(chan, blit, 0x0300, 3);
+       OUT_RING  (chan, (src->y << 16) | src->x);
+       OUT_RING  (chan, (dst->y << 16) | dst->x);
+       OUT_RING  (chan, ( h << 16) |  w);
+}
+
+/* THEOREM: a non-linearizable swizzled destination is always 64 byte aligned, except for 4x2 mipmap levels of swizzled 1bpp surfaces
+ * HYPOTESIS:
+ * 1. The first mipmap level is 64-byte-aligned
+ * PROOF:
+ * 1. Thus, all mipmaps level with a parent which is 64-byte or more in size are.
+ * 2. At 1bpp, the smallest levels with a <= 32-byte parent are either Nx1 or 1xN or size <=8, thus 4x2, 2x2 or 2x4
+ * 3. Nx1, 1xN, 2x4, 2x2 have all subrects linearizable. 4x2 does not.
+ * 4. At 2/4bpp or more, the smallest levels with a 32-byte parent are 1xN, Nx1 or 2x2
+ *
+ * However, nv04_region_align handles that.
+ */
+
+// 0 -> done, 1 -> do with 3D engine or CPU, -1 -> do with CPU
+// dst and src may be modified, and the possibly modified version should be passed to nv04_region_cpu if necessary
+int
+nv04_region_copy_2d(struct nv04_2d_context *ctx, struct nv04_region* dst, struct nv04_region* src,
+               int w, int h, int cs2d_format, int sifm_format, int dst_to_gpu, int src_on_gpu)
+{
+       assert(src->bpps == dst->bpps);
+
+#ifdef NV04_REGION_DEBUG
+       fprintf(stderr, "RGN_COPY%s [%i, %i: %i] ", (cs2d_format >= 0) ? "_2D" : "_NO2D", w, h, dst->bpps);
+       for(int i = 0; i < 2; ++i)
+       {
+               int gpu = i ? src_on_gpu : dst_to_gpu;
+               nv04_region_print(i ? src : dst);
+               fprintf(stderr, " %s", gpu ? "gpu" : "cpu");
+               fprintf(stderr, i ? "\n" : " <- ");
+       }
+#endif
+
+       // if they are contiguous and either both swizzled or both linear, reshape
+       if(!dst->pitch == !src->pitch
+               && nv04_region_is_contiguous(dst, w, h)
+               && nv04_region_is_contiguous(src, w, h))
+       {
+               nv04_region_contiguous_shape(dst, &w, &h, 6);
+               nv04_region_linearize_contiguous(dst, w, h);
+               nv04_region_linearize_contiguous(src, w, h);
+       }
+
+#ifdef NV04_REGION_DEBUG
+       fprintf(stderr, "\tOPT ");
+       for(int i = 0; i < 2; ++i)
+       {
+               nv04_region_print(i ? src : dst);
+               fprintf(stderr, i ? "\n" : " <- ");
+       }
+#endif
+
+       /* if the destination is not for GPU _and_ source is on CPU, use CPU */
+       /* if the destination is not for GPU _or_ source is on CPU, use CPU only if we think it's faster than the GPU */
+       /* TODO: benchmark to find out in which cases exactly we should prefer the CPU */
+        if((!dst_to_gpu && !src_on_gpu)
+               || (!dst->pitch && dst->d > 1)
+               /* 3D swizzled destination are unwritable by the GPU, and 2D swizzled ones are readable only by the 3D engine */
+        )
+                return -1;
+       /* there is no known way to read 2D/3D-swizzled surfaces with the 2D engine
+        * ask the caller to use the 3D engine
+        * If a format cannot be sampled from the 3D engine there is no point in making it swizzled, so we must not do so
+        */
+        else if(!src->pitch)
+        {
+#ifdef NV04_REGION_DEBUG
+               fprintf(stderr, "\tCOPY_ENG3D\n");
+#endif
+                return 1;
+        }
+       /* Setup transfer to swizzle the texture to vram if needed */
+       else
+       {
+               if (!dst->pitch)
+               {
+                       if(cs2d_format < 0 || sifm_format < 0 || !dst_to_gpu)
+                       {
+#ifdef NV04_REGION_DEBUG
+                               fprintf(stderr, "\tCOPY_ENG3D\n");
+#endif
+                               return 1;
+                       }
+                       else
+                       {
+                               assert(!nv04_region_align(dst, w, h, 6));
+
+                               nv04_region_copy_swizzle(ctx, dst, src, w, h, cs2d_format, sifm_format);
+                               return 0;
+                       }
+               }
+               else
+               {
+                       /* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
+                        * to NV_MEMORY_TO_MEMORY_FORMAT in this case.
+                        * TODO: is this also true for the source? possibly not
+                        */
+
+                       if ((cs2d_format < 0)
+                               || !dst_to_gpu
+                               || nv04_region_align(src, w, h, 6)
+                               || nv04_region_align(dst, w, h, 6)
+                               )
+                               nv04_region_copy_m2mf(ctx, dst, src, w, h);
+                       else
+                               nv04_region_copy_blit(ctx, dst, src, w, h, cs2d_format);
+
+                       return 0;
+               }
+       }
+}
+
+static inline void
+nv04_region_fill_gdirect(struct nv04_2d_context *ctx, struct nv04_region* dst, int w, int h, unsigned value)
+{
+       struct nouveau_channel *chan = ctx->surf2d->channel;
+       struct nouveau_grobj *surf2d = ctx->surf2d;
+       struct nouveau_grobj *rect = ctx->rect;
+       int cs2d_format, gdirect_format;
+
+#ifdef NV04_REGION_DEBUG
+       fprintf(stderr, "\tFILL_GDIRECT\n");
+#endif
+
+       assert(!(dst->pitch & 63) && dst->pitch);
+       nv04_region_assert(dst, w, h);
+
+       if(dst->bpps == 0)
+       {
+               gdirect_format = NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
+               cs2d_format = NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
+       }
+       else if(dst->bpps == 1)
+       {
+               gdirect_format = NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
+               cs2d_format = NV04_CONTEXT_SURFACES_2D_FORMAT_Y16;
+       }
+       else if(dst->bpps == 2)
+       {
+               gdirect_format = NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
+               cs2d_format = NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
+       }
+       else
+       {
+               assert(0);
+               gdirect_format = 0;
+               cs2d_format = 0;
+       }
+
+       MARK_RING (chan, 15, 4);
+       BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
+       OUT_RELOCo(chan, dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+       OUT_RELOCo(chan, dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+       BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
+       OUT_RING  (chan, cs2d_format);
+       OUT_RING  (chan, (dst->pitch << 16) | dst->pitch);
+       OUT_RELOCl(chan, dst->bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+       OUT_RELOCl(chan, dst->bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+       BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
+       OUT_RING  (chan, gdirect_format);
+       BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
+       OUT_RING  (chan, value);
+       BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
+       OUT_RING  (chan, (dst->x << 16) | dst->y);
+       OUT_RING  (chan, ( w << 16) |  h);
+}
+
+int
+nv04_region_fill_2d(struct nv04_2d_context *ctx, struct nv04_region *dst,
+                 int w, int h, unsigned value)
+{
+       if(!w || !h)
+               return 0;
+
+#ifdef NV04_REGION_DEBUG
+       fprintf(stderr, "FILL [%i, %i: %i] ", w, h, dst->bpps);
+       nv04_region_print(dst);
+       fprintf(stderr, " <- 0x%x\n", value);
+#endif
+
+       if(nv04_region_is_contiguous(dst, w, h))
+       {
+               nv04_region_contiguous_shape(dst, &w, &h, 6);
+               nv04_region_linearize_contiguous(dst, w, h);
+       }
+
+       // TODO: maybe do intermediate copies for some cases instead of using the 3D engine/CPU
+       /* GdiRect doesn't work together with swzsurf, so the 3D engine, or an intermediate copy, is the only option here */
+       if(!dst->pitch)
+       {
+#ifdef NV04_REGION_DEBUG
+               fprintf(stderr, "\tFILL_ENG3D\n");
+#endif
+               return 1;
+       }
+       else if(!nv04_region_align(dst, w, h, 6))
+       {
+               nv04_region_fill_gdirect(ctx, dst, w, h, value);
+               return 0;
+       }
+       else
+               return -1;
+}
+
+
+void
+nv04_2d_context_takedown(struct nv04_2d_context *ctx)
+{
+       nouveau_notifier_free(&ctx->ntfy);
+       nouveau_grobj_free(&ctx->m2mf);
+       nouveau_grobj_free(&ctx->surf2d);
+       nouveau_grobj_free(&ctx->swzsurf);
+       nouveau_grobj_free(&ctx->rect);
+       nouveau_grobj_free(&ctx->blit);
+       nouveau_grobj_free(&ctx->sifm);
+
+       free(ctx);
+}
+
+struct nv04_2d_context *
+nv04_2d_context_init(struct nouveau_channel* chan)
+{
+       struct nv04_2d_context *ctx = calloc(1, sizeof(struct nv04_2d_context));
+       unsigned handle = 0x88000000, class;
+       int ret;
+
+       if (!ctx)
+               return NULL;
+
+       ret = nouveau_notifier_alloc(chan, handle++, 1, &ctx->ntfy);
+       if (ret) {
+               nv04_2d_context_takedown(ctx);
+               return NULL;
+       }
+
+       ret = nouveau_grobj_alloc(chan, handle++, 0x0039, &ctx->m2mf);
+       if (ret) {
+               nv04_2d_context_takedown(ctx);
+               return NULL;
+       }
+
+       BEGIN_RING(chan, ctx->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
+       OUT_RING  (chan, ctx->ntfy->handle);
+
+       if (chan->device->chipset < 0x10)
+               class = NV04_CONTEXT_SURFACES_2D;
+       else
+               class = NV10_CONTEXT_SURFACES_2D;
+
+       ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->surf2d);
+       if (ret) {
+               nv04_2d_context_takedown(ctx);
+               return NULL;
+       }
+
+       BEGIN_RING(chan, ctx->surf2d,
+                        NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
+       OUT_RING  (chan, chan->vram->handle);
+       OUT_RING  (chan, chan->vram->handle);
+
+       if (chan->device->chipset < 0x10)
+               class = NV04_IMAGE_BLIT;
+       else
+               class = NV12_IMAGE_BLIT;
+
+       ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->blit);
+       if (ret) {
+               nv04_2d_context_takedown(ctx);
+               return NULL;
+       }
+
+       BEGIN_RING(chan, ctx->blit, NV01_IMAGE_BLIT_DMA_NOTIFY, 1);
+       OUT_RING  (chan, ctx->ntfy->handle);
+       BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_SURFACE, 1);
+       OUT_RING  (chan, ctx->surf2d->handle);
+       BEGIN_RING(chan, ctx->blit, NV01_IMAGE_BLIT_OPERATION, 1);
+       OUT_RING  (chan, NV01_IMAGE_BLIT_OPERATION_SRCCOPY);
+
+       ret = nouveau_grobj_alloc(chan, handle++, NV04_GDI_RECTANGLE_TEXT,
+                                 &ctx->rect);
+       if (ret) {
+               nv04_2d_context_takedown(ctx);
+               return NULL;
+       }
+
+       BEGIN_RING(chan, ctx->rect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
+       OUT_RING  (chan, ctx->ntfy->handle);
+       BEGIN_RING(chan, ctx->rect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
+       OUT_RING  (chan, ctx->surf2d->handle);
+       BEGIN_RING(chan, ctx->rect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
+       OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY);
+       BEGIN_RING(chan, ctx->rect,
+                        NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
+       OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
+
+       switch (chan->device->chipset & 0xf0) {
+       case 0x00:
+       case 0x10:
+               class = NV04_SWIZZLED_SURFACE;
+               break;
+       case 0x20:
+               class = NV20_SWIZZLED_SURFACE;
+               break;
+       case 0x30:
+               class = NV30_SWIZZLED_SURFACE;
+               break;
+       case 0x40:
+       case 0x60:
+               class = NV40_SWIZZLED_SURFACE;
+               break;
+       default:
+               /* Famous last words: this really can't happen.. */
+               assert(0);
+               break;
+       }
+
+       ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->swzsurf);
+       if (ret) {
+               nv04_2d_context_takedown(ctx);
+               return NULL;
+       }
+
+       /* all the Gallium MARK_RING calculations assume no autobinding, so do that now */
+       if(ctx->swzsurf->bound == NOUVEAU_GROBJ_UNBOUND)
+               nouveau_grobj_autobind(ctx->swzsurf);
+
+       switch (chan->device->chipset & 0xf0) {
+       case 0x10:
+       case 0x20:
+               class = NV10_SCALED_IMAGE_FROM_MEMORY;
+               break;
+       case 0x30:
+               class = NV30_SCALED_IMAGE_FROM_MEMORY;
+               break;
+       case 0x40:
+       case 0x60:
+               class = NV40_SCALED_IMAGE_FROM_MEMORY;
+               break;
+       default:
+               class = NV04_SCALED_IMAGE_FROM_MEMORY;
+               break;
+       }
+
+       ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->sifm);
+       if (ret) {
+               nv04_2d_context_takedown(ctx);
+               return NULL;
+       }
+
+       /* all the Gallium MARK_RING calculations assume no autobinding, so do that now */
+       if(ctx->sifm->bound == NOUVEAU_GROBJ_UNBOUND)
+               nouveau_grobj_autobind(ctx->sifm);
+
+       return ctx;
+}
diff --git a/src/gallium/drivers/nvfx/nv04_2d.h b/src/gallium/drivers/nvfx/nv04_2d.h
new file mode 100644 (file)
index 0000000..e638b8c
--- /dev/null
@@ -0,0 +1,87 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Ben Skeggs
+ * Copyright 2009 Younes Manton
+ * Copyright 2010 Luca Barbieri
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
+ * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ **************************************************************************/
+
+/* this code has no Mesa or Gallium dependency and can be reused in the classic Mesa driver or DDX */
+
+#ifndef __NV04_2D_H__
+#define __NV04_2D_H__
+
+struct nv04_2d_context;
+struct nouveau_channel;
+struct nouveau_bo;
+
+// NOTE: all functions taking this as a parameter will CLOBBER it (except for ->bo)
+struct nv04_region {
+       struct nouveau_bo* bo;
+       int offset;
+       unsigned pitch; // 0 -> swizzled
+       unsigned bpps; // bpp shift (0, 1, 2; 3, 4 for fp/compressed)
+       unsigned x, y, z;
+       unsigned w, h, d;
+};
+
+void
+nv04_memcpy(struct nv04_2d_context *ctx,
+               struct nouveau_bo* dstbo, int dstoff,
+               struct nouveau_bo* srcbo, int srcoff,
+               unsigned size);
+
+unsigned
+nv04_region_begin(struct nv04_region* rgn, unsigned w, unsigned h);
+
+unsigned
+nv04_region_end(struct nv04_region* rgn, unsigned w, unsigned h);
+
+void
+nv04_2d_context_takedown(struct nv04_2d_context *pctx);
+
+struct nv04_2d_context *
+nv04_2d_context_init(struct nouveau_channel* chan);
+
+void
+nv04_region_copy_cpu(struct nv04_region* dst, struct nv04_region* src, int w, int h);
+
+void
+nv04_region_fill_cpu(struct nv04_region* dst, int w, int h, unsigned value);
+
+int
+nv04_region_copy_2d(struct nv04_2d_context *ctx,
+               struct nv04_region* dst, struct nv04_region* src,
+               int w, int h,
+               int cs2d_format, int sifm_format,
+               int dst_to_gpu, int src_on_gpu);
+
+int
+nv04_region_fill_2d(struct nv04_2d_context *ctx,
+               struct nv04_region *dst,
+                int w, int h,
+                unsigned value);
+
+#endif
diff --git a/src/gallium/drivers/nvfx/nv04_2d_loops.h b/src/gallium/drivers/nvfx/nv04_2d_loops.h
new file mode 100644 (file)
index 0000000..3a6787c
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef T
+{
+       if(dst->bpps == 0)
+#define T uint8_t
+#include "nv04_2d_loops.h"
+#undef T
+       else if(dst->bpps == 1)
+#define T uint16_t
+#include "nv04_2d_loops.h"
+#undef T
+       else if(dst->bpps == 2)
+#define T uint32_t
+#include "nv04_2d_loops.h"
+#undef T
+       else
+               assert(0);
+}
+#else
+#ifdef SWIZZLED_COPY_LOOPS
+{
+       if(!dst->pitch)
+       {
+               if(!src->pitch)
+               {
+                       LOOP_Y
+                       {
+                               T* pdst = (T*)mdst + dswy[iy];
+                               T* psrc = (T*)msrc + sswy[iy];
+                               LOOP_X
+                               {
+                                       assert((char*)&psrc[sswx[ix] + 1] <= ((char*)src->bo->map + src->bo->size));
+                                       assert((char*)&pdst[dswx[ix] + 1] <= ((char*)dst->bo->map + dst->bo->size));
+                                       pdst[dswx[ix]] = psrc[sswx[ix]];
+                               }
+                       }
+               }
+               else
+               {
+                       T* psrc = (T*)(msrc + ((dir > 0) ? src->y : (src->y + h - 1)) * src->pitch) + src->x;
+                       LOOP_Y
+                       {
+                               T* pdst = (T*)mdst + dswy[iy];
+                               LOOP_X
+                               {
+                                       assert((char*)&psrc[ix + 1] <= ((char*)src->bo->map + src->bo->size));
+                                       assert((char*)&pdst[dswx[ix] + 1] <= ((char*)dst->bo->map + dst->bo->size));
+                                       pdst[dswx[ix]] = psrc[ix];
+                               }
+                               psrc = (T*)((char*)psrc + dir * src->pitch);
+                       }
+               }
+       }
+       else
+       {
+               T* pdst = (T*)(mdst + ((dir > 0) ? dst->y : (dst->y + h - 1)) * dst->pitch) + dst->x;
+               LOOP_Y
+               {
+                       T* psrc = (T*)msrc + sswy[iy];
+                       LOOP_X
+                       {
+                               assert((char*)&psrc[sswx[ix] + 1] <= ((char*)src->bo->map + src->bo->size));
+                               assert((char*)&pdst[ix + 1] <= ((char*)dst->bo->map + dst->bo->size));
+                               pdst[ix] = psrc[sswx[ix]];
+                       }
+                       pdst = (T*)((char*)pdst + dir * dst->pitch);
+               }
+       }
+}
+#endif
+#endif
diff --git a/src/gallium/drivers/nvfx/nv04_surface_2d.c b/src/gallium/drivers/nvfx/nv04_surface_2d.c
deleted file mode 100644 (file)
index 7acbb50..0000000
+++ /dev/null
@@ -1,532 +0,0 @@
-#include "pipe/p_context.h"
-#include "pipe/p_format.h"
-#include "util/u_format.h"
-#include "util/u_math.h"
-#include "util/u_memory.h"
-
-#include "nouveau/nouveau_winsys.h"
-#include "nouveau/nouveau_util.h"
-#include "nouveau/nouveau_screen.h"
-#include "nv04_surface_2d.h"
-
-static INLINE int
-nv04_surface_format(enum pipe_format format)
-{
-       switch (format) {
-       case PIPE_FORMAT_A8_UNORM:
-       case PIPE_FORMAT_L8_UNORM:
-       case PIPE_FORMAT_I8_UNORM:
-               return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
-       case PIPE_FORMAT_R16_SNORM:
-       case PIPE_FORMAT_B5G6R5_UNORM:
-       case PIPE_FORMAT_Z16_UNORM:
-       case PIPE_FORMAT_L8A8_UNORM:
-               return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
-       case PIPE_FORMAT_B8G8R8X8_UNORM:
-       case PIPE_FORMAT_B8G8R8A8_UNORM:
-               return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
-       case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
-       case PIPE_FORMAT_X8Z24_UNORM:
-               return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
-       default:
-               return -1;
-       }
-}
-
-static INLINE int
-nv04_rect_format(enum pipe_format format)
-{
-       switch (format) {
-       case PIPE_FORMAT_A8_UNORM:
-               return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
-       case PIPE_FORMAT_B5G6R5_UNORM:
-       case PIPE_FORMAT_L8A8_UNORM:
-       case PIPE_FORMAT_Z16_UNORM:
-               return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
-       case PIPE_FORMAT_B8G8R8X8_UNORM:
-       case PIPE_FORMAT_B8G8R8A8_UNORM:
-       case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
-       case PIPE_FORMAT_X8Z24_UNORM:
-               return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
-       default:
-               return -1;
-       }
-}
-
-static INLINE int
-nv04_scaled_image_format(enum pipe_format format)
-{
-       switch (format) {
-       case PIPE_FORMAT_A8_UNORM:
-       case PIPE_FORMAT_L8_UNORM:
-       case PIPE_FORMAT_I8_UNORM:
-               return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8;
-       case PIPE_FORMAT_B5G5R5A1_UNORM:
-               return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5;
-       case PIPE_FORMAT_B8G8R8A8_UNORM:
-               return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
-       case PIPE_FORMAT_B8G8R8X8_UNORM:
-               return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
-       case PIPE_FORMAT_B5G6R5_UNORM:
-       case PIPE_FORMAT_R16_SNORM:
-       case PIPE_FORMAT_L8A8_UNORM:
-               return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
-       default:
-               return -1;
-       }
-}
-
-static INLINE unsigned
-nv04_swizzle_bits_square(unsigned x, unsigned y)
-{
-       unsigned u = (x & 0x001) << 0 |
-                    (x & 0x002) << 1 |
-                    (x & 0x004) << 2 |
-                    (x & 0x008) << 3 |
-                    (x & 0x010) << 4 |
-                    (x & 0x020) << 5 |
-                    (x & 0x040) << 6 |
-                    (x & 0x080) << 7 |
-                    (x & 0x100) << 8 |
-                    (x & 0x200) << 9 |
-                    (x & 0x400) << 10 |
-                    (x & 0x800) << 11;
-
-       unsigned v = (y & 0x001) << 1 |
-                    (y & 0x002) << 2 |
-                    (y & 0x004) << 3 |
-                    (y & 0x008) << 4 |
-                    (y & 0x010) << 5 |
-                    (y & 0x020) << 6 |
-                    (y & 0x040) << 7 |
-                    (y & 0x080) << 8 |
-                    (y & 0x100) << 9 |
-                    (y & 0x200) << 10 |
-                    (y & 0x400) << 11 |
-                    (y & 0x800) << 12;
-       return v | u;
-}
-
-/* rectangular swizzled textures are linear concatenations of swizzled square tiles */
-static INLINE unsigned
-nv04_swizzle_bits(unsigned x, unsigned y, unsigned w, unsigned h)
-{
-       unsigned s = MIN2(w, h);
-       unsigned m = s - 1;
-       return (((x | y) & ~m) * s) | nv04_swizzle_bits_square(x & m, y & m);
-}
-
-static int
-nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx,
-                         struct pipe_surface *dst, int dx, int dy,
-                         struct pipe_surface *src, int sx, int sy,
-                         int w, int h)
-{
-       struct nouveau_channel *chan = ctx->swzsurf->channel;
-       struct nouveau_grobj *swzsurf = ctx->swzsurf;
-       struct nouveau_grobj *sifm = ctx->sifm;
-       struct nouveau_bo *src_bo = ctx->buf(src);
-       struct nouveau_bo *dst_bo = ctx->buf(dst);
-       const unsigned src_pitch = ((struct nv04_surface *)src)->pitch;
-        /* Max width & height may not be the same on all HW, but must be POT */
-       const unsigned max_w = 1024;
-       const unsigned max_h = 1024;
-       unsigned sub_w = w > max_w ? max_w : w;
-       unsigned sub_h = h > max_h ? max_h : h;
-       unsigned x;
-       unsigned y;
-
-        /* Swizzled surfaces must be POT  */
-       assert(util_is_pot(dst->width) && util_is_pot(dst->height));
-
-        /* If area is too large to copy in one shot we must copy it in POT chunks to meet alignment requirements */
-       assert(sub_w == w || util_is_pot(sub_w));
-       assert(sub_h == h || util_is_pot(sub_h));
-
-       MARK_RING (chan, 8 + ((w+sub_w)/sub_w)*((h+sub_h)/sub_h)*17, 2 +
-                        ((w+sub_w)/sub_w)*((h+sub_h)/sub_h)*2);
-
-       BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE, 1);
-       OUT_RELOCo(chan, dst_bo,
-                        NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-
-       BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_FORMAT, 1);
-       OUT_RING  (chan, nv04_surface_format(dst->format) |
-                        log2i(dst->width) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT |
-                        log2i(dst->height) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT);
-
-       BEGIN_RING(chan, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
-       OUT_RELOCo(chan, src_bo,
-                        NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
-       BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1);
-       OUT_RING  (chan, swzsurf->handle);
-
-       for (y = 0; y < h; y += sub_h) {
-         sub_h = MIN2(sub_h, h - y);
-
-         for (x = 0; x < w; x += sub_w) {
-           sub_w = MIN2(sub_w, w - x);
-
-           assert(!(dst->offset & 63));
-
-           BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_OFFSET, 1);
-           OUT_RELOCl(chan, dst_bo, dst->offset,
-                             NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-
-           BEGIN_RING(chan, sifm, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9);
-           OUT_RING  (chan, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
-           OUT_RING  (chan, nv04_scaled_image_format(src->format));
-           OUT_RING  (chan, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
-           OUT_RING  (chan, (x + dx) | ((y + dy) << NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y_SHIFT));
-           OUT_RING  (chan, sub_h << NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H_SHIFT | sub_w);
-           OUT_RING  (chan, (x + dx) | ((y + dy) << NV03_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_Y_SHIFT));
-           OUT_RING  (chan, sub_h << NV03_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_H_SHIFT | sub_w);
-           OUT_RING  (chan, 1 << 20);
-           OUT_RING  (chan, 1 << 20);
-
-           BEGIN_RING(chan, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
-           OUT_RING  (chan, sub_h << NV03_SCALED_IMAGE_FROM_MEMORY_SIZE_H_SHIFT | sub_w);
-           OUT_RING  (chan, src_pitch |
-                            NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
-                            NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
-           OUT_RELOCl(chan, src_bo, src->offset + (sy+y) * src_pitch + (sx+x) * util_format_get_blocksize(src->texture->format),
-                             NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
-           OUT_RING  (chan, 0);
-         }
-       }
-
-       return 0;
-}
-
-static int
-nv04_surface_copy_m2mf(struct nv04_surface_2d *ctx,
-                      struct pipe_surface *dst, int dx, int dy,
-                      struct pipe_surface *src, int sx, int sy, int w, int h)
-{
-       struct nouveau_channel *chan = ctx->m2mf->channel;
-       struct nouveau_grobj *m2mf = ctx->m2mf;
-       struct nouveau_bo *src_bo = ctx->buf(src);
-       struct nouveau_bo *dst_bo = ctx->buf(dst);
-       unsigned src_pitch = ((struct nv04_surface *)src)->pitch;
-       unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch;
-       unsigned dst_offset = dst->offset + dy * dst_pitch +
-                             dx * util_format_get_blocksize(dst->texture->format);
-       unsigned src_offset = src->offset + sy * src_pitch +
-                             sx * util_format_get_blocksize(src->texture->format);
-
-       MARK_RING (chan, 3 + ((h / 2047) + 1) * 9, 2 + ((h / 2047) + 1) * 2);
-       BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
-       OUT_RELOCo(chan, src_bo,
-                  NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
-       OUT_RELOCo(chan, dst_bo,
-                  NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-
-       while (h) {
-               int count = (h > 2047) ? 2047 : h;
-
-               BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
-               OUT_RELOCl(chan, src_bo, src_offset,
-                          NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
-               OUT_RELOCl(chan, dst_bo, dst_offset,
-                          NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR);
-               OUT_RING  (chan, src_pitch);
-               OUT_RING  (chan, dst_pitch);
-               OUT_RING  (chan, w * util_format_get_blocksize(src->texture->format));
-               OUT_RING  (chan, count);
-               OUT_RING  (chan, 0x0101);
-               OUT_RING  (chan, 0);
-
-               h -= count;
-               src_offset += src_pitch * count;
-               dst_offset += dst_pitch * count;
-       }
-
-       return 0;
-}
-
-static int
-nv04_surface_copy_blit(struct nv04_surface_2d *ctx, struct pipe_surface *dst,
-                      int dx, int dy, struct pipe_surface *src, int sx, int sy,
-                      int w, int h)
-{
-       struct nouveau_channel *chan = ctx->surf2d->channel;
-       struct nouveau_grobj *surf2d = ctx->surf2d;
-       struct nouveau_grobj *blit = ctx->blit;
-       struct nouveau_bo *src_bo = ctx->buf(src);
-       struct nouveau_bo *dst_bo = ctx->buf(dst);
-       unsigned src_pitch = ((struct nv04_surface *)src)->pitch;
-       unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch;
-       int format;
-
-       format = nv04_surface_format(dst->format);
-       if (format < 0)
-               return 1;
-
-       MARK_RING (chan, 12, 4);
-       BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
-       OUT_RELOCo(chan, src_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
-       OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-       BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
-       OUT_RING  (chan, format);
-       OUT_RING  (chan, (dst_pitch << 16) | src_pitch);
-       OUT_RELOCl(chan, src_bo, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
-       OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-
-       BEGIN_RING(chan, blit, 0x0300, 3);
-       OUT_RING  (chan, (sy << 16) | sx);
-       OUT_RING  (chan, (dy << 16) | dx);
-       OUT_RING  (chan, ( h << 16) |  w);
-
-       return 0;
-}
-
-static void
-nv04_surface_copy(struct nv04_surface_2d *ctx, struct pipe_surface *dst,
-                 int dx, int dy, struct pipe_surface *src, int sx, int sy,
-                 int w, int h)
-{
-       int src_linear = src->texture->flags & NVFX_RESOURCE_FLAG_LINEAR;
-       int dst_linear = dst->texture->flags & NVFX_RESOURCE_FLAG_LINEAR;
-
-       assert(src->format == dst->format);
-
-       /* Setup transfer to swizzle the texture to vram if needed */
-        if (src_linear && !dst_linear && w > 1 && h > 1) {
-           nv04_surface_copy_swizzle(ctx, dst, dx, dy, src, sx, sy, w, h);
-           return;
-        }
-
-        /* Use M2MF instead of the blitter since it always works
-         * Any possible performance drop is likely to be not very significant
-         * and dwarfed anyway by the current buffer management problems
-         */
-        nv04_surface_copy_m2mf(ctx, dst, dx, dy, src, sx, sy, w, h);
-}
-
-static void
-nv04_surface_fill(struct nv04_surface_2d *ctx, struct pipe_surface *dst,
-                 int dx, int dy, int w, int h, unsigned value)
-{
-       struct nouveau_channel *chan = ctx->surf2d->channel;
-       struct nouveau_grobj *surf2d = ctx->surf2d;
-       struct nouveau_grobj *rect = ctx->rect;
-       struct nouveau_bo *dst_bo = ctx->buf(dst);
-       unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch;
-       int cs2d_format, gdirect_format;
-
-       cs2d_format = nv04_surface_format(dst->format);
-       assert(cs2d_format >= 0);
-
-       gdirect_format = nv04_rect_format(dst->format);
-       assert(gdirect_format >= 0);
-
-       MARK_RING (chan, 16, 4);
-       BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
-       OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-       OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-       BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
-       OUT_RING  (chan, cs2d_format);
-       OUT_RING  (chan, (dst_pitch << 16) | dst_pitch);
-       OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-       OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-
-       BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
-       OUT_RING  (chan, gdirect_format);
-       BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
-       OUT_RING  (chan, value);
-       BEGIN_RING(chan, rect,
-                  NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
-       OUT_RING  (chan, (dx << 16) | dy);
-       OUT_RING  (chan, ( w << 16) |  h);
-}
-
-void
-nv04_surface_2d_takedown(struct nv04_surface_2d **pctx)
-{
-       struct nv04_surface_2d *ctx;
-
-       if (!pctx || !*pctx)
-               return;
-       ctx = *pctx;
-       *pctx = NULL;
-
-       nouveau_notifier_free(&ctx->ntfy);
-       nouveau_grobj_free(&ctx->m2mf);
-       nouveau_grobj_free(&ctx->surf2d);
-       nouveau_grobj_free(&ctx->swzsurf);
-       nouveau_grobj_free(&ctx->rect);
-       nouveau_grobj_free(&ctx->blit);
-       nouveau_grobj_free(&ctx->sifm);
-
-       FREE(ctx);
-}
-
-struct nv04_surface_2d *
-nv04_surface_2d_init(struct nouveau_screen *screen)
-{
-       struct nv04_surface_2d *ctx = CALLOC_STRUCT(nv04_surface_2d);
-       struct nouveau_channel *chan = screen->channel;
-       unsigned handle = 0x88000000, class;
-       int ret;
-
-       if (!ctx)
-               return NULL;
-
-       ret = nouveau_notifier_alloc(chan, handle++, 1, &ctx->ntfy);
-       if (ret) {
-               nv04_surface_2d_takedown(&ctx);
-               return NULL;
-       }
-
-       ret = nouveau_grobj_alloc(chan, handle++, 0x0039, &ctx->m2mf);
-       if (ret) {
-               nv04_surface_2d_takedown(&ctx);
-               return NULL;
-       }
-
-       BEGIN_RING(chan, ctx->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
-       OUT_RING  (chan, ctx->ntfy->handle);
-
-       if (chan->device->chipset < 0x10)
-               class = NV04_CONTEXT_SURFACES_2D;
-       else
-               class = NV10_CONTEXT_SURFACES_2D;
-
-       ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->surf2d);
-       if (ret) {
-               nv04_surface_2d_takedown(&ctx);
-               return NULL;
-       }
-
-       BEGIN_RING(chan, ctx->surf2d,
-                        NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
-       OUT_RING  (chan, chan->vram->handle);
-       OUT_RING  (chan, chan->vram->handle);
-
-       if (chan->device->chipset < 0x10)
-               class = NV04_IMAGE_BLIT;
-       else
-               class = NV12_IMAGE_BLIT;
-
-       ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->blit);
-       if (ret) {
-               nv04_surface_2d_takedown(&ctx);
-               return NULL;
-       }
-
-       BEGIN_RING(chan, ctx->blit, NV01_IMAGE_BLIT_DMA_NOTIFY, 1);
-       OUT_RING  (chan, ctx->ntfy->handle);
-       BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_SURFACE, 1);
-       OUT_RING  (chan, ctx->surf2d->handle);
-       BEGIN_RING(chan, ctx->blit, NV01_IMAGE_BLIT_OPERATION, 1);
-       OUT_RING  (chan, NV01_IMAGE_BLIT_OPERATION_SRCCOPY);
-
-       ret = nouveau_grobj_alloc(chan, handle++, NV04_GDI_RECTANGLE_TEXT,
-                                 &ctx->rect);
-       if (ret) {
-               nv04_surface_2d_takedown(&ctx);
-               return NULL;
-       }
-
-       BEGIN_RING(chan, ctx->rect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
-       OUT_RING  (chan, ctx->ntfy->handle);
-       BEGIN_RING(chan, ctx->rect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
-       OUT_RING  (chan, ctx->surf2d->handle);
-       BEGIN_RING(chan, ctx->rect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
-       OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY);
-       BEGIN_RING(chan, ctx->rect,
-                        NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
-       OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
-
-       switch (chan->device->chipset & 0xf0) {
-       case 0x00:
-       case 0x10:
-               class = NV04_SWIZZLED_SURFACE;
-               break;
-       case 0x20:
-               class = NV20_SWIZZLED_SURFACE;
-               break;
-       case 0x30:
-               class = NV30_SWIZZLED_SURFACE;
-               break;
-       case 0x40:
-       case 0x60:
-               class = NV40_SWIZZLED_SURFACE;
-               break;
-       default:
-               /* Famous last words: this really can't happen.. */
-               assert(0);
-               break;
-       }
-
-       ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->swzsurf);
-       if (ret) {
-               nv04_surface_2d_takedown(&ctx);
-               return NULL;
-       }
-
-       switch (chan->device->chipset & 0xf0) {
-       case 0x10:
-       case 0x20:
-               class = NV10_SCALED_IMAGE_FROM_MEMORY;
-               break;
-       case 0x30:
-               class = NV30_SCALED_IMAGE_FROM_MEMORY;
-               break;
-       case 0x40:
-       case 0x60:
-               class = NV40_SCALED_IMAGE_FROM_MEMORY;
-               break;
-       default:
-               class = NV04_SCALED_IMAGE_FROM_MEMORY;
-               break;
-       }
-
-       ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->sifm);
-       if (ret) {
-               nv04_surface_2d_takedown(&ctx);
-               return NULL;
-       }
-
-       ctx->copy = nv04_surface_copy;
-       ctx->fill = nv04_surface_fill;
-       return ctx;
-}
-
-struct nv04_surface*
-nv04_surface_wrap_for_render(struct pipe_screen *pscreen,
-                            struct nv04_surface_2d* eng2d, struct nv04_surface* ns)
-{
-       struct pipe_resource templ;
-       struct pipe_resource* temp_tex;
-       struct nv04_surface* temp_ns;
-       int temp_flags;
-
-       temp_flags = ns->base.usage;
-
-       ns->base.usage = 0;
-
-       memset(&templ, 0, sizeof(templ));
-       templ.format = ns->base.texture->format;
-       templ.target = PIPE_TEXTURE_2D;
-       templ.width0 = ns->base.width;
-       templ.height0 = ns->base.height;
-       templ.depth0 = 1;
-       templ.last_level = 0;
-
-       // TODO: this is probably wrong and we should specifically handle multisampling somehow once it is implemented
-       templ.nr_samples = ns->base.texture->nr_samples;
-
-       templ.bind = ns->base.texture->bind | PIPE_BIND_RENDER_TARGET;
-
-       temp_tex = pscreen->resource_create(pscreen, &templ);
-       temp_ns = (struct nv04_surface*)pscreen->get_tex_surface(pscreen, temp_tex, 0, 0, 0, temp_flags);
-       temp_ns->backing = ns;
-
-       if(1) /* hmm */
-               eng2d->copy(eng2d, &temp_ns->backing->base,
-                           0, 0, &ns->base,
-                           0, 0, ns->base.width, ns->base.height);
-
-       return temp_ns;
-}
diff --git a/src/gallium/drivers/nvfx/nv04_surface_2d.h b/src/gallium/drivers/nvfx/nv04_surface_2d.h
deleted file mode 100644 (file)
index 2123c3e..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef __NV04_SURFACE_2D_H__
-#define __NV04_SURFACE_2D_H__
-
-#include "pipe/p_state.h"
-
-struct nouveau_screen;
-
-struct nv04_surface {
-       struct pipe_surface base;
-       unsigned pitch;
-       struct nv04_surface* backing;
-};
-
-struct nv04_surface_2d {
-       struct nouveau_notifier *ntfy;
-       struct nouveau_grobj *surf2d;
-       struct nouveau_grobj *swzsurf;
-       struct nouveau_grobj *m2mf;
-       struct nouveau_grobj *rect;
-       struct nouveau_grobj *blit;
-       struct nouveau_grobj *sifm;
-
-       struct nouveau_bo *(*buf)(struct pipe_surface *);
-
-       void (*copy)(struct nv04_surface_2d *, struct pipe_surface *dst,
-                    int dx, int dy, struct pipe_surface *src, int sx, int sy,
-                    int w, int h);
-       void (*fill)(struct nv04_surface_2d *, struct pipe_surface *dst,
-                    int dx, int dy, int w, int h, unsigned value);
-};
-
-struct nv04_surface_2d *
-nv04_surface_2d_init(struct nouveau_screen *screen);
-
-void
-nv04_surface_2d_takedown(struct nv04_surface_2d **);
-
-struct nv04_surface*
-nv04_surface_wrap_for_render(struct pipe_screen *pscreen, struct nv04_surface_2d* eng2d, struct nv04_surface* ns);
-
-#define NVFX_RESOURCE_FLAG_LINEAR (PIPE_RESOURCE_FLAG_DRV_PRIV << 0)
-
-#endif
index dec073ac9003622bee6f6a627cd021f0fb0bf447..0c3d43fd57345a54b67a66b10302f702de9bc0ad 100644 (file)
@@ -1,7 +1,6 @@
 #include "util/u_format.h"
 
 #include "nvfx_context.h"
-#include "nouveau/nouveau_util.h"
 #include "nvfx_tex.h"
 #include "nvfx_resource.h"
 
@@ -10,138 +9,109 @@ nv30_sampler_state_init(struct pipe_context *pipe,
                          struct nvfx_sampler_state *ps,
                          const struct pipe_sampler_state *cso)
 {
-       if (cso->max_anisotropy >= 8) {
-               ps->en |= NV34TCL_TX_ENABLE_ANISO_8X;
-       } else
-       if (cso->max_anisotropy >= 4) {
-               ps->en |= NV34TCL_TX_ENABLE_ANISO_4X;
-       } else
-       if (cso->max_anisotropy >= 2) {
-               ps->en |= NV34TCL_TX_ENABLE_ANISO_2X;
-       }
+       float limit;
 
+       if (cso->max_anisotropy >= 2)
        {
-               float limit;
+               if (cso->max_anisotropy >= 8)
+                       ps->en |= NV34TCL_TX_ENABLE_ANISO_8X;
+               else if (cso->max_anisotropy >= 4)
+                       ps->en |= NV34TCL_TX_ENABLE_ANISO_4X;
+               else if (cso->max_anisotropy >= 2)
+                       ps->en |= NV34TCL_TX_ENABLE_ANISO_2X;
+       }
 
-               limit = CLAMP(cso->lod_bias, -16.0, 15.0);
-               ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
+       limit = CLAMP(cso->lod_bias, -16.0, 15.0 + (255.0 / 256.0));
+       ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
 
-               limit = CLAMP(cso->max_lod, 0.0, 15.0);
-               ps->en |= (int)(limit) << 14 /*NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_SHIFT*/;
+       ps->max_lod = (int)CLAMP(cso->max_lod, 0.0, 15.0);
+       ps->min_lod = (int)CLAMP(cso->min_lod, 0.0, 15.0);
 
-               limit = CLAMP(cso->min_lod, 0.0, 15.0);
-               ps->en |= (int)(limit) << 26 /*NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_SHIFT*/;
-       }
+       ps->en |= NV34TCL_TX_ENABLE_ENABLE;
 }
 
-#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w)                        \
-{                                                                              \
-  TRUE,                                                                        \
-  PIPE_FORMAT_##m,                                                             \
-  NV34TCL_TX_FORMAT_FORMAT_##tf,                                               \
-  (NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y |           \
-   NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w |           \
-   NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y |           \
-   NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w)            \
-}
-
-struct nv30_texture_format {
-       boolean defined;
-       uint    pipe;
-       int     format;
-       int     swizzle;
-};
-
-static struct nv30_texture_format
-nv30_texture_formats[] = {
-       _(B8G8R8X8_UNORM, A8R8G8B8,   S1,   S1,   S1,  ONE, X, Y, Z, W),
-       _(B8G8R8A8_UNORM, A8R8G8B8,   S1,   S1,   S1,   S1, X, Y, Z, W),
-       _(B5G5R5A1_UNORM, A1R5G5B5,   S1,   S1,   S1,   S1, X, Y, Z, W),
-       _(B4G4R4A4_UNORM, A4R4G4B4,   S1,   S1,   S1,   S1, X, Y, Z, W),
-       _(B5G6R5_UNORM  , R5G6B5  ,   S1,   S1,   S1,  ONE, X, Y, Z, W),
-       _(L8_UNORM      , L8      ,   S1,   S1,   S1,  ONE, X, X, X, X),
-       _(A8_UNORM      , L8      , ZERO, ZERO, ZERO,   S1, X, X, X, X),
-       _(I8_UNORM      , L8      ,   S1,   S1,   S1,   S1, X, X, X, X),
-       _(L8A8_UNORM    , A8L8    ,   S1,   S1,   S1,   S1, X, X, X, Y),
-       _(Z16_UNORM     , R5G6B5  ,   S1,   S1,   S1,  ONE, X, X, X, X),
-       _(S8_USCALED_Z24_UNORM   , A8R8G8B8,   S1,   S1,   S1,  ONE, X, X, X, X),
-       _(DXT1_RGB      , DXT1    ,   S1,   S1,   S1,  ONE, X, Y, Z, W),
-       _(DXT1_RGBA     , DXT1    ,   S1,   S1,   S1,   S1, X, Y, Z, W),
-       _(DXT3_RGBA     , DXT3    ,   S1,   S1,   S1,   S1, X, Y, Z, W),
-       _(DXT5_RGBA     , DXT5    ,   S1,   S1,   S1,   S1, X, Y, Z, W),
-       {},
-};
-
-static struct nv30_texture_format *
-nv30_fragtex_format(uint pipe_format)
+void
+nv30_sampler_view_init(struct pipe_context *pipe,
+                         struct nvfx_sampler_view *sv)
 {
-       struct nv30_texture_format *tf = nv30_texture_formats;
-
-       while (tf->defined) {
-               if (tf->pipe == pipe_format)
-                       return tf;
-               tf++;
-       }
-
-       NOUVEAU_ERR("unknown texture format %s\n", util_format_name(pipe_format));
-       return NULL;
+       struct pipe_resource* pt = sv->base.texture;
+       struct nvfx_texture_format *tf = &nvfx_texture_formats[sv->base.format];
+       unsigned txf;
+       unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.first_level;
+
+       assert(tf->fmt[0] >= 0);
+
+       txf = sv->u.init_fmt;
+       txf |= (level != sv->base.last_level ? NV34TCL_TX_FORMAT_MIPMAP : 0);
+       txf |= util_logbase2(u_minify(pt->width0, level)) << NV34TCL_TX_FORMAT_BASE_SIZE_U_SHIFT;
+       txf |= util_logbase2(u_minify(pt->height0, level)) << NV34TCL_TX_FORMAT_BASE_SIZE_V_SHIFT;
+       txf |= util_logbase2(u_minify(pt->depth0, level)) << NV34TCL_TX_FORMAT_BASE_SIZE_W_SHIFT;
+       txf |=  0x10000;
+
+       sv->u.nv30.fmt[0] = tf->fmt[0] | txf;
+       sv->u.nv30.fmt[1] = tf->fmt[1] | txf;
+       sv->u.nv30.fmt[2] = tf->fmt[2] | txf;
+       sv->u.nv30.fmt[3] = tf->fmt[3] | txf;
+
+       sv->swizzle  |= (nvfx_subresource_pitch(pt, 0) << NV34TCL_TX_SWIZZLE_RECT_PITCH_SHIFT);
+
+       if(pt->height0 <= 1 || util_format_is_compressed(sv->base.format))
+               sv->u.nv30.rect = -1;
+       else
+               sv->u.nv30.rect = !!(pt->flags & NVFX_RESOURCE_FLAG_LINEAR);
+
+       sv->lod_offset = sv->base.first_level - level;
+       sv->max_lod_limit = sv->base.last_level - level;
 }
 
-
 void
 nv30_fragtex_set(struct nvfx_context *nvfx, int unit)
 {
        struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit];
-       struct nvfx_miptree *nv30mt = (struct nvfx_miptree *)nvfx->fragment_sampler_views[unit]->texture;
-       struct pipe_resource *pt = &nv30mt->base.base;
-       struct nouveau_bo *bo = nv30mt->base.bo;
-       struct nv30_texture_format *tf;
+       struct nvfx_sampler_view* sv = (struct nvfx_sampler_view*)nvfx->fragment_sampler_views[unit];
+       struct nouveau_bo *bo = ((struct nvfx_miptree *)sv->base.texture)->base.bo;
        struct nouveau_channel* chan = nvfx->screen->base.channel;
-       uint32_t txf, txs;
+       unsigned txf;
        unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
+       unsigned use_rect;
+       unsigned max_lod = MIN2(ps->max_lod + sv->lod_offset, sv->max_lod_limit);
+       unsigned min_lod = MIN2(ps->min_lod + sv->lod_offset, max_lod) ;
 
-       tf = nv30_fragtex_format(pt->format);
-       if (!tf)
-               return;
-
-       txf  = tf->format;
-       txf |= ((pt->last_level>0) ? NV34TCL_TX_FORMAT_MIPMAP : 0);
-       txf |= log2i(pt->width0) << NV34TCL_TX_FORMAT_BASE_SIZE_U_SHIFT;
-       txf |= log2i(pt->height0) << NV34TCL_TX_FORMAT_BASE_SIZE_V_SHIFT;
-       txf |= log2i(pt->depth0) << NV34TCL_TX_FORMAT_BASE_SIZE_W_SHIFT;
-       txf |= NV34TCL_TX_FORMAT_NO_BORDER | 0x10000;
-
-       switch (pt->target) {
-       case PIPE_TEXTURE_CUBE:
-               txf |= NV34TCL_TX_FORMAT_CUBIC;
-               /* fall-through */
-       case PIPE_TEXTURE_2D:
-               txf |= NV34TCL_TX_FORMAT_DIMS_2D;
-               break;
-       case PIPE_TEXTURE_3D:
-               txf |= NV34TCL_TX_FORMAT_DIMS_3D;
-               break;
-       case PIPE_TEXTURE_1D:
-               txf |= NV34TCL_TX_FORMAT_DIMS_1D;
-               break;
-       default:
-               NOUVEAU_ERR("Unknown target %d\n", pt->target);
-               return;
+       if(sv->u.nv30.rect < 0)
+       {
+               /* in the case of compressed or 1D textures, we can get away with this,
+                * since the layout is the same
+                */
+               use_rect = ps->fmt;
+       }
+       else
+       {
+               static boolean warned = FALSE;
+               if( !!ps->fmt != sv->u.nv30.rect && !warned) {
+                       warned = TRUE;
+                       fprintf(stderr,
+                                       "Unimplemented: coordinate normalization mismatch. Possible reasons:\n"
+                                       "1. ARB_texture_non_power_of_two is being used despite the fact it isn't supported\n"
+                                       "2. The state tracker is not using the appropriate coordinate normalization\n"
+                                       "3. The state tracker is not supported\n");
+               }
+
+               use_rect  = sv->u.nv30.rect;
        }
 
-       txs = tf->swizzle;
+       txf = sv->u.nv30.fmt[ps->compare + (use_rect ? 2 : 0)];
 
        MARK_RING(chan, 9, 2);
        OUT_RING(chan, RING_3D(NV34TCL_TX_OFFSET(unit), 8));
-       OUT_RELOC(chan, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0);
-       OUT_RELOC(chan, bo, txf, tex_flags | NOUVEAU_BO_OR,
-                     NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
-       OUT_RING(chan, ps->wrap);
-       OUT_RING(chan, NV34TCL_TX_ENABLE_ENABLE | ps->en);
-       OUT_RING(chan, txs);
-       OUT_RING(chan, ps->filt | 0x2000 /*voodoo*/);
-       OUT_RING(chan, (pt->width0 << NV34TCL_TX_NPOT_SIZE_W_SHIFT) |
-                      pt->height0);
+       OUT_RELOC(chan, bo, sv->offset, tex_flags | NOUVEAU_BO_LOW, 0, 0);
+       OUT_RELOC(chan, bo, txf,
+               tex_flags | NOUVEAU_BO_OR,
+               NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
+       OUT_RING(chan, (ps->wrap & sv->wrap_mask) | sv->wrap);
+       OUT_RING(chan, ps->en | (min_lod << NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_SHIFT) | (max_lod << NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_SHIFT));
+       OUT_RING(chan, sv->swizzle);
+       OUT_RING(chan, ps->filt | sv->filt);
+       OUT_RING(chan, sv->npot_size);
        OUT_RING(chan, ps->bcol);
 
        nvfx->hw_txf[unit] = txf;
index ec0444c07f864a52b864eb62a617adf8542ad721..9a68f5c1fb06c106951b1c6ad29648bd9e45ffd7 100644 (file)
@@ -68,7 +68,7 @@
 #define NV30_VP_INST_DEST_TEMP_ID_SHIFT        16
 #define NV30_VP_INST_DEST_TEMP_ID_MASK        (0x0F << 16)
 #define NV30_VP_INST_COND_UPDATE_ENABLE        (1<<15)
-#define NV30_VP_INST_VEC_DEST_TEMP_MASK      (0xF << 16)
+#define NV30_VP_INST_VEC_DEST_TEMP_MASK      (0x1F << 16)
 #define NV30_VP_INST_COND_TEST_ENABLE        (1<<14)
 #define NV30_VP_INST_COND_SHIFT          11
 #define NV30_VP_INST_COND_MASK          (0x07 << 11)
 #define NV30_VP_INST_SRC2H_SHIFT        0    /*NV20*/
 #define NV30_VP_INST_SRC2H_MASK          (0x7FF << 0)  /* NV30_VP_SRC2_HIGH_MASK >> 4*/
 #define NV30_VP_INST_IADDR_SHIFT        2
-#define NV30_VP_INST_IADDR_MASK          (0xF <<  28)   /* NV30_VP_SRC2_LOW_MASK << 28 */
+#define NV30_VP_INST_IADDR_MASK          (0x1FF <<  2)   /* NV30_VP_SRC2_LOW_MASK << 28 */
 
 /* DWORD 3 */
 #define NV30_VP_INST_SRC2L_SHIFT        28    /*NV20*/
 #define NV30_VP_INST_VDEST_WRITEMASK_SHIFT      12    /*NV20*/
 #define NV30_VP_INST_VDEST_WRITEMASK_MASK      (0x0F << 12)  /*NV20*/
 #define NV30_VP_INST_DEST_SHIFT        2
-#define NV30_VP_INST_DEST_MASK        (0x0F <<  2)
+#define NV30_VP_INST_DEST_MASK        (0x1F <<  2)
 #  define NV30_VP_INST_DEST_POS  0
 #  define NV30_VP_INST_DEST_BFC0  1
 #  define NV30_VP_INST_DEST_BFC1  2
 #  define NV30_VP_INST_DEST_COL1  4
 #  define NV30_VP_INST_DEST_FOGC  5
 #  define NV30_VP_INST_DEST_PSZ   6
-#  define NV30_VP_INST_DEST_TC(n)  (8+n)
+#  define NV30_VP_INST_DEST_TC(n)  (8+(n))
+#  define NV30_VP_INST_DEST_CLP(n) (17 + (n))
 
 /* Useful to split the source selection regs into their pieces */
 #define NV30_VP_SRC0_HIGH_SHIFT                                                6
index 0068b1ba54ac044884bb9416ddca619051c9a960..106ce71a079b5ef28f6ef8e8172802a79c290025 100644 (file)
@@ -8,168 +8,97 @@ nv40_sampler_state_init(struct pipe_context *pipe,
                          struct nvfx_sampler_state *ps,
                          const struct pipe_sampler_state *cso)
 {
+       float limit;
        if (cso->max_anisotropy >= 2) {
                /* no idea, binary driver sets it, works without it.. meh.. */
                ps->wrap |= (1 << 5);
 
-               if (cso->max_anisotropy >= 16) {
+               if (cso->max_anisotropy >= 16)
                        ps->en |= NV40TCL_TEX_ENABLE_ANISO_16X;
-               } else
-               if (cso->max_anisotropy >= 12) {
+               else if (cso->max_anisotropy >= 12)
                        ps->en |= NV40TCL_TEX_ENABLE_ANISO_12X;
-               } else
-               if (cso->max_anisotropy >= 10) {
+               else if (cso->max_anisotropy >= 10)
                        ps->en |= NV40TCL_TEX_ENABLE_ANISO_10X;
-               } else
-               if (cso->max_anisotropy >= 8) {
+               else if (cso->max_anisotropy >= 8)
                        ps->en |= NV40TCL_TEX_ENABLE_ANISO_8X;
-               } else
-               if (cso->max_anisotropy >= 6) {
+               else if (cso->max_anisotropy >= 6)
                        ps->en |= NV40TCL_TEX_ENABLE_ANISO_6X;
-               } else
-               if (cso->max_anisotropy >= 4) {
+               else if (cso->max_anisotropy >= 4)
                        ps->en |= NV40TCL_TEX_ENABLE_ANISO_4X;
-               } else {
+               else
                        ps->en |= NV40TCL_TEX_ENABLE_ANISO_2X;
-               }
        }
 
-       {
-               float limit;
+       limit = CLAMP(cso->lod_bias, -16.0, 15.0 + (255.0 / 256.0));
+       ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
 
-               limit = CLAMP(cso->lod_bias, -16.0, 15.0);
-               ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
+       ps->max_lod = (int)(CLAMP(cso->max_lod, 0.0, 15.0 + (255.0 / 256.0)) * 256.0);
+       ps->min_lod = (int)(CLAMP(cso->min_lod, 0.0, 15.0 + (255.0 / 256.0)) * 256.0);
 
-               limit = CLAMP(cso->max_lod, 0.0, 15.0);
-               ps->en |= (int)(limit * 256.0) << 7;
-
-               limit = CLAMP(cso->min_lod, 0.0, 15.0);
-               ps->en |= (int)(limit * 256.0) << 19;
-       }
-}
-
-#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sx,sy,sz,sw)            \
-{                                                                              \
-  TRUE,                                                                        \
-  PIPE_FORMAT_##m,                                                             \
-  NV40TCL_TEX_FORMAT_FORMAT_##tf,                                              \
-  (NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y |         \
-   NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w |         \
-   NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y |         \
-   NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w),         \
-  ((NV34TCL_TX_FILTER_SIGNED_RED*sx) | (NV34TCL_TX_FILTER_SIGNED_GREEN*sy) |       \
-   (NV34TCL_TX_FILTER_SIGNED_BLUE*sz) | (NV34TCL_TX_FILTER_SIGNED_ALPHA*sw))       \
+       ps->en |= NV40TCL_TEX_ENABLE_ENABLE;
 }
 
-struct nv40_texture_format {
-       boolean defined;
-       uint    pipe;
-       int     format;
-       int     swizzle;
-       int     sign;
-};
-
-static struct nv40_texture_format
-nv40_texture_formats[] = {
-       _(B8G8R8X8_UNORM, A8R8G8B8,   S1,   S1,   S1,  ONE, X, Y, Z, W, 0, 0, 0, 0),
-       _(B8G8R8A8_UNORM, A8R8G8B8,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0),
-       _(B5G5R5A1_UNORM, A1R5G5B5,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0),
-       _(B4G4R4A4_UNORM, A4R4G4B4,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0),
-       _(B5G6R5_UNORM  , R5G6B5  ,   S1,   S1,   S1,  ONE, X, Y, Z, W, 0, 0, 0, 0),
-       _(L8_UNORM      , L8      ,   S1,   S1,   S1,  ONE, X, X, X, X, 0, 0, 0, 0),
-       _(A8_UNORM      , L8      , ZERO, ZERO, ZERO,   S1, X, X, X, X, 0, 0, 0, 0),
-       _(R16_SNORM     , A16     , ZERO, ZERO,   S1,  ONE, X, X, X, Y, 1, 1, 1, 1),
-       _(I8_UNORM      , L8      ,   S1,   S1,   S1,   S1, X, X, X, X, 0, 0, 0, 0),
-       _(L8A8_UNORM    , A8L8    ,   S1,   S1,   S1,   S1, X, X, X, Y, 0, 0, 0, 0),
-       _(Z16_UNORM     , Z16     ,   S1,   S1,   S1,  ONE, X, X, X, X, 0, 0, 0, 0),
-       _(S8_USCALED_Z24_UNORM   , Z24     ,   S1,   S1,   S1,  ONE, X, X, X, X, 0, 0, 0, 0),
-       _(DXT1_RGB      , DXT1    ,   S1,   S1,   S1,  ONE, X, Y, Z, W, 0, 0, 0, 0),
-       _(DXT1_RGBA     , DXT1    ,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0),
-       _(DXT3_RGBA     , DXT3    ,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0),
-       _(DXT5_RGBA     , DXT5    ,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0),
-       {},
-};
-
-static struct nv40_texture_format *
-nv40_fragtex_format(uint pipe_format)
+void
+nv40_sampler_view_init(struct pipe_context *pipe,
+                         struct nvfx_sampler_view *sv)
 {
-       struct nv40_texture_format *tf = nv40_texture_formats;
-
-       while (tf->defined) {
-               if (tf->pipe == pipe_format)
-                       return tf;
-               tf++;
+       struct pipe_resource* pt = sv->base.texture;
+       struct nvfx_miptree* mt = (struct nvfx_miptree*)pt;
+       struct nvfx_texture_format *tf = &nvfx_texture_formats[sv->base.format];
+       unsigned txf;
+       unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.first_level;
+       assert(tf->fmt[4] >= 0);
+
+       txf = sv->u.init_fmt;
+       txf |= 0x8000;
+       if(pt->target == PIPE_TEXTURE_CUBE)
+               txf |= ((pt->last_level + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT);
+       else
+               txf |= (((sv->base.last_level - sv->base.first_level) + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT);
+
+       if (!mt->linear_pitch)
+               sv->u.nv40.npot_size2 = 0;
+       else {
+               sv->u.nv40.npot_size2  = mt->linear_pitch;
+               txf |= NV40TCL_TEX_FORMAT_LINEAR;
        }
 
-       NOUVEAU_ERR("unknown texture format %s\n", util_format_name(pipe_format));
-       return NULL;
-}
+       sv->u.nv40.fmt[0] = tf->fmt[4] | txf;
+       sv->u.nv40.fmt[1] = tf->fmt[5] | txf;
 
+       sv->u.nv40.npot_size2 |= (u_minify(pt->depth0, level) << NV40TCL_TEX_SIZE1_DEPTH_SHIFT);
+
+       sv->lod_offset = (sv->base.first_level - level) * 256;
+       sv->max_lod_limit = (sv->base.last_level - level) * 256;
+}
 
 void
 nv40_fragtex_set(struct nvfx_context *nvfx, int unit)
 {
        struct nouveau_channel* chan = nvfx->screen->base.channel;
        struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit];
-       struct nvfx_miptree *nv40mt = (struct nvfx_miptree *)nvfx->fragment_sampler_views[unit]->texture;
-       struct nouveau_bo *bo = nv40mt->base.bo;
-       struct pipe_resource *pt = &nv40mt->base.base;
-       struct nv40_texture_format *tf;
-
-       uint32_t txf, txs, txp;
+       struct nvfx_sampler_view* sv = (struct nvfx_sampler_view*)nvfx->fragment_sampler_views[unit];
+       struct nouveau_bo *bo = ((struct nvfx_miptree *)sv->base.texture)->base.bo;
        unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
+       unsigned txf;
+       unsigned max_lod = MIN2(ps->max_lod + sv->lod_offset, sv->max_lod_limit);
+       unsigned min_lod = MIN2(ps->min_lod + sv->lod_offset, max_lod);
 
-       tf = nv40_fragtex_format(pt->format);
-       if (!tf)
-               assert(0);
-
-       txf  = ps->fmt;
-       txf |= tf->format | 0x8000;
-       txf |= ((pt->last_level + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT);
-
-       if (1) /* XXX */
-               txf |= NV34TCL_TX_FORMAT_NO_BORDER;
-
-       switch (pt->target) {
-       case PIPE_TEXTURE_CUBE:
-               txf |= NV34TCL_TX_FORMAT_CUBIC;
-               /* fall-through */
-       case PIPE_TEXTURE_2D:
-               txf |= NV34TCL_TX_FORMAT_DIMS_2D;
-               break;
-       case PIPE_TEXTURE_3D:
-               txf |= NV34TCL_TX_FORMAT_DIMS_3D;
-               break;
-       case PIPE_TEXTURE_1D:
-               txf |= NV34TCL_TX_FORMAT_DIMS_1D;
-               break;
-       default:
-               NOUVEAU_ERR("Unknown target %d\n", pt->target);
-               return;
-       }
-
-       if (!(pt->flags & NVFX_RESOURCE_FLAG_LINEAR)) {
-               txp = 0;
-       } else {
-               txp  = nv40mt->level[0].pitch;
-               txf |= NV40TCL_TEX_FORMAT_LINEAR;
-       }
-
-       txs = tf->swizzle;
+       txf = sv->u.nv40.fmt[ps->compare] | ps->fmt;
 
-       MARK_RING(chan, 11 + 2 * !unit, 2);
+       MARK_RING(chan, 11, 2);
        OUT_RING(chan, RING_3D(NV34TCL_TX_OFFSET(unit), 8));
-       OUT_RELOC(chan, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0);
+       OUT_RELOC(chan, bo, sv->offset, tex_flags | NOUVEAU_BO_LOW, 0, 0);
        OUT_RELOC(chan, bo, txf, tex_flags | NOUVEAU_BO_OR,
                        NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
-       OUT_RING(chan, ps->wrap);
-       OUT_RING(chan, NV40TCL_TEX_ENABLE_ENABLE | ps->en);
-       OUT_RING(chan, txs);
-       OUT_RING(chan, ps->filt | tf->sign | 0x2000 /*voodoo*/);
-       OUT_RING(chan, (pt->width0 << NV34TCL_TX_NPOT_SIZE_W_SHIFT) | pt->height0);
+       OUT_RING(chan, (ps->wrap & sv->wrap_mask) | sv->wrap);
+       OUT_RING(chan, ps->en | (min_lod << 19) | (max_lod << 7));
+       OUT_RING(chan, sv->swizzle);
+       OUT_RING(chan, ps->filt | sv->filt);
+       OUT_RING(chan, sv->npot_size);
        OUT_RING(chan, ps->bcol);
        OUT_RING(chan, RING_3D(NV40TCL_TEX_SIZE1(unit), 1));
-       OUT_RING(chan, (pt->depth0 << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) | txp);
+       OUT_RING(chan, sv->u.nv40.npot_size2);
 
        nvfx->hw_txf[unit] = txf;
        nvfx->hw_samplers |= (1 << unit);
index 7337293babc522d8a103433728ab075c00f3091a..3d0a1fe3d1010d7f9b8132eba3a9237fdb8106a1 100644 (file)
@@ -44,7 +44,7 @@
 #define NV40_VP_INST_SRC1_ABS                                          (1 << 22)
 #define NV40_VP_INST_SRC0_ABS                                          (1 << 21)
 #define NV40_VP_INST_VEC_DEST_TEMP_SHIFT                                      15
-#define NV40_VP_INST_VEC_DEST_TEMP_MASK                             (0x1F << 15)
+#define NV40_VP_INST_VEC_DEST_TEMP_MASK                             (0x3F << 15)
 #define NV40_VP_INST_COND_TEST_ENABLE                                  (1 << 13)
 #define NV40_VP_INST_COND_SHIFT                                               10
 #define NV40_VP_INST_COND_MASK                                       (0x7 << 10)
 #define NV40_VP_INST_SRC2H_SHIFT                                               0
 #define NV40_VP_INST_SRC2H_MASK                                      (0x3F << 0)
 #define NV40_VP_INST_IADDRH_SHIFT                                              0
-#define NV40_VP_INST_IADDRH_MASK                                     (0x1F << 0)
+#define NV40_VP_INST_IADDRH_MASK                                     (0x3F << 0)
 
 /* ---- OPCODE BITS 31:0 / data DWORD 3 --- */
 #define NV40_VP_INST_IADDRL_SHIFT                                             29
index 05b824b8f74f57b9e1fab2220b4962743c883f42..041099e0e568ca953464fc4aa09468077f8409be 100644 (file)
 #include "nouveau/nouveau_screen.h"
 #include "nouveau/nouveau_winsys.h"
 #include "nvfx_resource.h"
+#include "nvfx_screen.h"
 
-
-/* Currently using separate implementations for buffers and textures,
- * even though gallium has a unified abstraction of these objects.
- * Eventually these should be combined, and mechanisms like transfers
- * be adapted to work for both buffer and texture uploads.
- */
-static void nvfx_buffer_destroy(struct pipe_screen *pscreen,
+void nvfx_buffer_destroy(struct pipe_screen *pscreen,
                                struct pipe_resource *presource)
 {
-       struct nvfx_resource *buffer = nvfx_resource(presource);
+       struct nvfx_buffer *buffer = nvfx_buffer(presource);
 
-       nouveau_screen_bo_release(pscreen, buffer->bo);
+       if(!(buffer->base.base.flags & NVFX_RESOURCE_FLAG_USER))
+               align_free(buffer->data);
+       nouveau_screen_bo_release(pscreen, buffer->base.bo);
        FREE(buffer);
 }
 
-
-
-
-/* Utility functions for transfer create/destroy are hooked in and
- * just record the arguments to those functions.
- */
-static void *
-nvfx_buffer_transfer_map( struct pipe_context *pipe,
-                         struct pipe_transfer *transfer )
-{
-       struct nvfx_resource *buffer = nvfx_resource(transfer->resource);
-       uint8_t *map;
-
-       map = nouveau_screen_bo_map_range( pipe->screen,
-                                          buffer->bo,
-                                          transfer->box.x,
-                                          transfer->box.width,
-                                          nouveau_screen_transfer_flags(transfer->usage) );
-       if (map == NULL)
-               return NULL;
-       
-       return map + transfer->box.x;
-}
-
-
-
-static void nvfx_buffer_transfer_flush_region( struct pipe_context *pipe,
-                                              struct pipe_transfer *transfer,
-                                              const struct pipe_box *box)
-{
-       struct nvfx_resource *buffer = nvfx_resource(transfer->resource);
-
-       nouveau_screen_bo_map_flush_range(pipe->screen,
-                                         buffer->bo,
-                                         transfer->box.x + box->x,
-                                         box->width);
-}
-
-static void nvfx_buffer_transfer_unmap( struct pipe_context *pipe,
-                                       struct pipe_transfer *transfer )
-{
-       struct nvfx_resource *buffer = nvfx_resource(transfer->resource);
-
-       nouveau_screen_bo_unmap(pipe->screen, buffer->bo);
-}
-
-
-
-
-struct u_resource_vtbl nvfx_buffer_vtbl = 
-{
-       u_default_resource_get_handle,      /* get_handle */
-       nvfx_buffer_destroy,                 /* resource_destroy */
-       NULL,                       /* is_resource_referenced */
-       u_default_get_transfer,      /* get_transfer */
-       u_default_transfer_destroy,          /* transfer_destroy */
-       nvfx_buffer_transfer_map,            /* transfer_map */
-       nvfx_buffer_transfer_flush_region,  /* transfer_flush_region */
-       nvfx_buffer_transfer_unmap,          /* transfer_unmap */
-       u_default_transfer_inline_write   /* transfer_inline_write */
-};
-
-
-
 struct pipe_resource *
 nvfx_buffer_create(struct pipe_screen *pscreen,
                   const struct pipe_resource *template)
 {
-       struct nvfx_resource *buffer;
+       struct nvfx_screen* screen = nvfx_screen(pscreen);
+       struct nvfx_buffer* buffer;
 
-       buffer = CALLOC_STRUCT(nvfx_resource);
+       buffer = CALLOC_STRUCT(nvfx_buffer);
        if (!buffer)
                return NULL;
 
-       buffer->base = *template;
-       buffer->vtbl = &nvfx_buffer_vtbl;
-       pipe_reference_init(&buffer->base.reference, 1);
-       buffer->base.screen = pscreen;
-
-       buffer->bo = nouveau_screen_bo_new(pscreen,
-                                          16,
-                                          buffer->base.usage,
-                                          buffer->base.bind,
-                                          buffer->base.width0);
-
-       if (buffer->bo == NULL)
-               goto fail;
-
-       return &buffer->base;
+       buffer->base.base = *template;
+       buffer->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
+       pipe_reference_init(&buffer->base.base.reference, 1);
+       buffer->base.base.screen = pscreen;
+       buffer->size = util_format_get_stride(template->format, template->width0);
+       buffer->bytes_to_draw_until_static = buffer->size * screen->static_reuse_threshold;
+       buffer->data = align_malloc(buffer->size, 16);
 
-fail:
-       FREE(buffer);
-       return NULL;
+       return &buffer->base.base;
 }
 
 
@@ -124,30 +48,49 @@ nvfx_user_buffer_create(struct pipe_screen *pscreen,
                        unsigned bytes,
                        unsigned usage)
 {
-       struct nvfx_resource *buffer;
+       struct nvfx_screen* screen = nvfx_screen(pscreen);
+       struct nvfx_buffer* buffer;
 
-       buffer = CALLOC_STRUCT(nvfx_resource);
+       buffer = CALLOC_STRUCT(nvfx_buffer);
        if (!buffer)
                return NULL;
 
-       pipe_reference_init(&buffer->base.reference, 1);
-       buffer->vtbl = &nvfx_buffer_vtbl;
-       buffer->base.screen = pscreen;
-       buffer->base.format = PIPE_FORMAT_R8_UNORM;
-       buffer->base.usage = PIPE_USAGE_IMMUTABLE;
-       buffer->base.bind = usage;
-       buffer->base.width0 = bytes;
-       buffer->base.height0 = 1;
-       buffer->base.depth0 = 1;
-
-       buffer->bo = nouveau_screen_bo_user(pscreen, ptr, bytes);
-       if (!buffer->bo)
-               goto fail;
-       
-       return &buffer->base;
-
-fail:
-       FREE(buffer);
-       return NULL;
+       pipe_reference_init(&buffer->base.base.reference, 1);
+       buffer->base.base.flags = NVFX_RESOURCE_FLAG_LINEAR | NVFX_RESOURCE_FLAG_USER;
+       buffer->base.base.screen = pscreen;
+       buffer->base.base.format = PIPE_FORMAT_R8_UNORM;
+       buffer->base.base.usage = PIPE_USAGE_IMMUTABLE;
+       buffer->base.base.bind = usage;
+       buffer->base.base.width0 = bytes;
+       buffer->base.base.height0 = 1;
+       buffer->base.base.depth0 = 1;
+       buffer->data = ptr;
+       buffer->size = bytes;
+       buffer->bytes_to_draw_until_static = bytes * screen->static_reuse_threshold;
+       buffer->dirty_end = bytes;
+
+       return &buffer->base.base;
 }
 
+void nvfx_buffer_upload(struct nvfx_buffer* buffer)
+{
+       unsigned dirty = buffer->dirty_end - buffer->dirty_begin;
+       if(!buffer->base.bo)
+       {
+               buffer->base.bo = nouveau_screen_bo_new(buffer->base.base.screen,
+                                          16,
+                                          buffer->base.base.usage,
+                                          buffer->base.base.bind,
+                                          buffer->base.base.width0);
+       }
+
+       if(dirty)
+       {
+               // TODO: may want to use a temporary in some cases
+               nouveau_bo_map(buffer->base.bo, NOUVEAU_BO_WR
+                               | (buffer->dirty_unsynchronized ? NOUVEAU_BO_NOSYNC : 0));
+               memcpy((uint8_t*)buffer->base.bo->map + buffer->dirty_begin, buffer->data + buffer->dirty_begin, dirty);
+               nouveau_bo_unmap(buffer->base.bo);
+               buffer->dirty_begin = buffer->dirty_end = 0;
+       }
+}
index 7218abff22ddf8f1da5381899bba5e03db3dde75..5a2fa14c887b773070ae1de4c8af2840b2f39d88 100644 (file)
@@ -1,5 +1,6 @@
 #include "draw/draw_context.h"
 #include "pipe/p_defines.h"
+#include "util/u_framebuffer.h"
 
 #include "nvfx_context.h"
 #include "nvfx_screen.h"
@@ -14,6 +15,7 @@ nvfx_flush(struct pipe_context *pipe, unsigned flags,
        struct nouveau_channel *chan = screen->base.channel;
        struct nouveau_grobj *eng3d = screen->eng3d;
 
+       /* XXX: we need to actually be intelligent here */
        if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
                BEGIN_RING(chan, eng3d, 0x1fd8, 1);
                OUT_RING  (chan, 2);
@@ -31,8 +33,22 @@ nvfx_destroy(struct pipe_context *pipe)
 {
        struct nvfx_context *nvfx = nvfx_context(pipe);
 
+       if(nvfx->dummy_fs)
+               pipe->delete_fs_state(pipe, nvfx->dummy_fs);
+
+       for(unsigned i = 0; i < nvfx->vtxbuf_nr; ++i)
+               pipe_resource_reference(&nvfx->vtxbuf[i].buffer, 0);
+       pipe_resource_reference(&nvfx->idxbuf.buffer, 0);
+       util_unreference_framebuffer_state(&nvfx->framebuffer);
+       for(unsigned i = 0; i < PIPE_MAX_SAMPLERS; ++i)
+               pipe_sampler_view_reference(&nvfx->fragment_sampler_views[i], 0);
+
        if (nvfx->draw)
                draw_destroy(nvfx->draw);
+
+       if(nvfx->screen->cur_ctx == nvfx)
+               nvfx->screen->cur_ctx = NULL;
+
        FREE(nvfx);
 }
 
@@ -59,14 +75,21 @@ nvfx_create(struct pipe_screen *pscreen, void *priv)
        nvfx->pipe.clear = nvfx_clear;
        nvfx->pipe.flush = nvfx_flush;
 
-       screen->base.channel->user_private = nvfx;
-
        nvfx->is_nv4x = screen->is_nv4x;
+       /* TODO: it seems that nv30 might have fixed function clipping usable with vertex programs
+        * However, my code for that doesn't work, so use vp clipping for all cards, which works.
+        */
+       nvfx->use_vp_clipping = TRUE;
 
        nvfx_init_query_functions(nvfx);
        nvfx_init_surface_functions(nvfx);
        nvfx_init_state_functions(nvfx);
+       nvfx_init_sampling_functions(nvfx);
+       nvfx_init_vbo_functions(nvfx);
+       nvfx_init_fragprog_functions(nvfx);
+       nvfx_init_vertprog_functions(nvfx);
        nvfx_init_resource_functions(&nvfx->pipe);
+       nvfx_init_transfer_functions(&nvfx->pipe);
 
        /* Create, configure, and install fallback swtnl path */
        nvfx->draw = draw_create(&nvfx->pipe);
@@ -78,6 +101,12 @@ nvfx_create(struct pipe_screen *pscreen, void *priv)
 
        /* set these to that we init them on first validation */
        nvfx->state.scissor_enabled = ~0;
-       nvfx->state.stipple_enabled = ~0;
+       nvfx->hw_pointsprite_control = -1;
+       nvfx->hw_vp_output = -1;
+       nvfx->use_vertex_buffers = -1;
+       nvfx->relocs_needed = NVFX_RELOCATE_ALL;
+
+       LIST_INITHEAD(&nvfx->render_cache);
+
        return &nvfx->pipe;
 }
index 89f94c10bd13b560ca8ae9083e0ea520be8c0d8a..4c654bfa8bab1ca4af6b104f21e0c6c24a7b38ec 100644 (file)
 #include "util/u_memory.h"
 #include "util/u_math.h"
 #include "util/u_inlines.h"
+#include "util/u_double_list.h"
 
 #include "draw/draw_vertex.h"
+#include "util/u_blitter.h"
 
 #include "nouveau/nouveau_winsys.h"
 #include "nouveau/nouveau_gldefs.h"
 #define NVFX_NEW_SR            (1 << 13)
 #define NVFX_NEW_VERTCONST     (1 << 14)
 #define NVFX_NEW_FRAGCONST     (1 << 15)
+#define NVFX_NEW_INDEX (1 << 16)
+#define NVFX_NEW_SPRITE  (1 << 17)
+
+#define NVFX_RELOCATE_FRAMEBUFFER (1 << 0)
+#define NVFX_RELOCATE_FRAGTEX (1 << 1)
+#define NVFX_RELOCATE_FRAGPROG (1 << 2)
+#define NVFX_RELOCATE_VTXBUF (1 << 3)
+#define NVFX_RELOCATE_IDXBUF (1 << 4)
+#define NVFX_RELOCATE_ALL 0x1f
 
 struct nvfx_rasterizer_state {
        struct pipe_rasterizer_state pipe;
        unsigned sb_len;
-       uint32_t sb[32];
+       uint32_t sb[34];
 };
 
 struct nvfx_zsa_state {
        struct pipe_depth_stencil_alpha_state pipe;
        unsigned sb_len;
-       uint32_t sb[26];
+       uint32_t sb[24];
 };
 
 struct nvfx_blend_state {
@@ -64,13 +75,57 @@ struct nvfx_blend_state {
 
 struct nvfx_state {
        unsigned scissor_enabled;
-       unsigned stipple_enabled;
        unsigned fp_samplers;
+       unsigned render_temps;
+};
+
+struct nvfx_per_vertex_element {
+       unsigned idx;
+        unsigned vertex_buffer_index;
+        unsigned src_offset;
+};
+
+struct nvfx_low_frequency_element {
+       unsigned idx;
+       unsigned vertex_buffer_index;
+       unsigned src_offset;
+        void (*fetch_rgba_float)(float *dst, const uint8_t *src, unsigned i, unsigned j);
+        unsigned ncomp;
+};
+
+struct nvfx_per_instance_element {
+       struct nvfx_low_frequency_element base;
+       unsigned instance_divisor;
+};
+
+struct nvfx_per_vertex_buffer_info
+{
+       unsigned vertex_buffer_index;
+       unsigned per_vertex_size;
 };
 
 struct nvfx_vtxelt_state {
        struct pipe_vertex_element pipe[16];
        unsigned num_elements;
+       unsigned vtxfmt[16];
+
+       unsigned num_per_vertex_buffer_infos;
+       struct nvfx_per_vertex_buffer_info per_vertex_buffer_info[16];
+
+       unsigned num_per_vertex;
+       struct nvfx_per_vertex_element per_vertex[16];
+
+       unsigned num_per_instance;
+       struct nvfx_per_instance_element per_instance[16];
+
+       unsigned num_constant;
+       struct nvfx_low_frequency_element constant[16];
+
+       boolean needs_translate;
+       struct translate* translate;
+
+       unsigned vertex_length;
+       unsigned max_vertices_per_packet;
 };
 
 struct nvfx_render_target {
@@ -86,8 +141,11 @@ struct nvfx_context {
        struct nvfx_screen *screen;
 
        unsigned is_nv4x; /* either 0 or ~0 */
+       boolean use_vp_clipping;
 
        struct draw_context *draw;
+       struct blitter_context* blitter;
+       struct list_head render_cache;
 
        /* HW state derived from pipe states */
        struct nvfx_state state;
@@ -111,7 +169,7 @@ struct nvfx_context {
        unsigned stipple[32];
        struct pipe_clip_state clip;
        struct nvfx_vertex_program *vertprog;
-       struct nvfx_fragment_program *fragprog;
+       struct nvfx_pipe_fragment_program *fragprog;
        struct pipe_resource *constbuf[PIPE_SHADER_TYPES];
        unsigned constbuf_nr[PIPE_SHADER_TYPES];
        struct nvfx_rasterizer_state *rasterizer;
@@ -122,23 +180,34 @@ struct nvfx_context {
        struct pipe_viewport_state viewport;
        struct pipe_framebuffer_state framebuffer;
        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];
+       struct nvfx_pipe_fragment_program* dummy_fs;
+
        unsigned nr_samplers;
        unsigned nr_textures;
        unsigned dirty_samplers;
        struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
        unsigned vtxbuf_nr;
        struct nvfx_vtxelt_state *vtxelt;
+       int base_vertex;
+       boolean use_index_buffer;
+       /* -1 = hardware input setup is outdated
+        * 0 = hardware input setup is for inline vertices
+        * 1 = hardware input setup is for hardware vertices
+        */
+       int use_vertex_buffers;
 
-       unsigned vbo_bo;
        unsigned hw_vtxelt_nr;
        uint8_t hw_samplers;
        uint32_t hw_txf[8];
        struct nvfx_render_target hw_rt[4];
        struct nvfx_render_target hw_zeta;
+       int hw_pointsprite_control;
+       int hw_vp_output;
+       struct nvfx_fragment_program* hw_fragprog;
+
+       unsigned relocs_needed;
 };
 
 static INLINE struct nvfx_context *
@@ -175,15 +244,12 @@ extern void nvfx_clear(struct pipe_context *pipe, unsigned buffers,
 
 /* nvfx_draw.c */
 extern struct draw_stage *nvfx_draw_render_stage(struct nvfx_context *nvfx);
-extern void nvfx_draw_elements_swtnl(struct pipe_context *pipe,
-                                     struct pipe_resource *idxbuf,
-                                     unsigned ib_size, int ib_bias,
-                                     unsigned mode,
-                                     unsigned start, unsigned count);
+extern void nvfx_draw_vbo_swtnl(struct pipe_context *pipe, const struct pipe_draw_info* info);
 extern void nvfx_vtxfmt_validate(struct nvfx_context *nvfx);
 
 /* nvfx_fb.c */
-extern void nvfx_state_framebuffer_validate(struct nvfx_context *nvfx);
+extern int nvfx_framebuffer_prepare(struct nvfx_context *nvfx);
+extern void nvfx_framebuffer_validate(struct nvfx_context *nvfx, unsigned prepare_result);
 void
 nvfx_framebuffer_relocate(struct nvfx_context *nvfx);
 
@@ -191,19 +257,24 @@ nvfx_framebuffer_relocate(struct nvfx_context *nvfx);
 extern void nvfx_fragprog_destroy(struct nvfx_context *,
                                    struct nvfx_fragment_program *);
 extern void nvfx_fragprog_validate(struct nvfx_context *nvfx);
-extern void
-nvfx_fragprog_relocate(struct nvfx_context *nvfx);
+extern void nvfx_fragprog_relocate(struct nvfx_context *nvfx);
+extern void nvfx_init_fragprog_functions(struct nvfx_context *nvfx);
 
 /* nvfx_fragtex.c */
+extern void nvfx_init_sampling_functions(struct nvfx_context *nvfx);
 extern void nvfx_fragtex_validate(struct nvfx_context *nvfx);
-extern void
-nvfx_fragtex_relocate(struct nvfx_context *nvfx);
+extern void nvfx_fragtex_relocate(struct nvfx_context *nvfx);
+
+struct nvfx_sampler_view;
 
 /* nv30_fragtex.c */
 extern void
 nv30_sampler_state_init(struct pipe_context *pipe,
                          struct nvfx_sampler_state *ps,
                          const struct pipe_sampler_state *cso);
+extern void
+nv30_sampler_view_init(struct pipe_context *pipe,
+                         struct nvfx_sampler_view *sv);
 extern void nv30_fragtex_set(struct nvfx_context *nvfx, int unit);
 
 /* nv40_fragtex.c */
@@ -211,6 +282,9 @@ extern void
 nv40_sampler_state_init(struct pipe_context *pipe,
                          struct nvfx_sampler_state *ps,
                          const struct pipe_sampler_state *cso);
+extern void
+nv40_sampler_view_init(struct pipe_context *pipe,
+                         struct nvfx_sampler_view *sv);
 extern void nv40_fragtex_set(struct nvfx_context *nvfx, int unit);
 
 /* nvfx_state.c */
@@ -225,23 +299,75 @@ extern void nvfx_state_sr_validate(struct nvfx_context *nvfx);
 extern void nvfx_state_zsa_validate(struct nvfx_context *nvfx);
 
 /* nvfx_state_emit.c */
-extern void nvfx_state_relocate(struct nvfx_context *nvfx);
+extern void nvfx_state_relocate(struct nvfx_context *nvfx, unsigned relocs);
 extern boolean nvfx_state_validate(struct nvfx_context *nvfx);
 extern boolean nvfx_state_validate_swtnl(struct nvfx_context *nvfx);
-extern void nvfx_state_emit(struct nvfx_context *nvfx);
+
+static inline void
+nvfx_state_emit(struct nvfx_context *nvfx)
+{
+        unsigned relocs = NVFX_RELOCATE_FRAMEBUFFER | NVFX_RELOCATE_FRAGTEX | NVFX_RELOCATE_FRAGPROG;
+        if (nvfx->render_mode == HW)
+        {
+                relocs |= NVFX_RELOCATE_VTXBUF;
+                if(nvfx->use_index_buffer)
+                        relocs |= NVFX_RELOCATE_IDXBUF;
+        }
+
+        relocs &= nvfx->relocs_needed;
+        if(relocs)
+                nvfx_state_relocate(nvfx, relocs);
+}
 
 /* nvfx_transfer.c */
-extern void nvfx_init_transfer_functions(struct nvfx_context *nvfx);
+extern void nvfx_init_transfer_functions(struct pipe_context *pipe);
 
 /* nvfx_vbo.c */
 extern boolean nvfx_vbo_validate(struct nvfx_context *nvfx);
 extern void nvfx_vbo_relocate(struct nvfx_context *nvfx);
+extern void nvfx_idxbuf_validate(struct nvfx_context* nvfx);
+extern void nvfx_idxbuf_relocate(struct nvfx_context* nvfx);
 extern void nvfx_draw_vbo(struct pipe_context *pipe,
                           const struct pipe_draw_info *info);
+extern void nvfx_init_vbo_functions(struct nvfx_context *nvfx);
+extern unsigned nvfx_vertex_formats[];
 
 /* nvfx_vertprog.c */
 extern boolean nvfx_vertprog_validate(struct nvfx_context *nvfx);
 extern void nvfx_vertprog_destroy(struct nvfx_context *,
                                  struct nvfx_vertex_program *);
+extern void nvfx_init_vertprog_functions(struct nvfx_context *nvfx);
+
+/* nvfx_push.c */
+extern void nvfx_push_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info);
+
+/* must WAIT_RING(chan, ncomp + 1) or equivalent beforehand! */
+static inline void nvfx_emit_vtx_attr(struct nouveau_channel* chan, unsigned attrib, const float* v, unsigned ncomp)
+{
+       switch (ncomp) {
+       case 4:
+               OUT_RING(chan, RING_3D(NV34TCL_VTX_ATTR_4F_X(attrib), 4));
+               OUT_RING(chan, fui(v[0]));
+               OUT_RING(chan, fui(v[1]));
+               OUT_RING(chan,  fui(v[2]));
+               OUT_RING(chan,  fui(v[3]));
+               break;
+       case 3:
+               OUT_RING(chan, RING_3D(NV34TCL_VTX_ATTR_3F_X(attrib), 3));
+               OUT_RING(chan,  fui(v[0]));
+               OUT_RING(chan,  fui(v[1]));
+               OUT_RING(chan,  fui(v[2]));
+               break;
+       case 2:
+               OUT_RING(chan, RING_3D(NV34TCL_VTX_ATTR_2F_X(attrib), 2));
+               OUT_RING(chan,  fui(v[0]));
+               OUT_RING(chan,  fui(v[1]));
+               break;
+       case 1:
+               OUT_RING(chan, RING_3D(NV34TCL_VTX_ATTR_1F(attrib), 1));
+               OUT_RING(chan,  fui(v[0]));
+               break;
+       }
+}
 
 #endif
index 22cff370b77e44a3851a64704a68a6e04f9f19a3..2601d5b8e2ecc7edcd97a0bb83cded1cd432111e 100644 (file)
@@ -9,6 +9,7 @@
 #include "draw/draw_pipe.h"
 
 #include "nvfx_context.h"
+#include "nvfx_resource.h"
 
 /* Simple, but crappy, swtnl path, hopefully we wont need to hit this very
  * often at all.  Uses "quadro style" vertex submission + a fixed vertex
@@ -39,30 +40,21 @@ nvfx_render_vertex(struct nvfx_context *nvfx, const struct vertex_header *v)
                unsigned idx = nvfx->swtnl.draw[i];
                unsigned hw = nvfx->swtnl.hw[i];
 
+               WAIT_RING(chan, 5);
                switch (nvfx->swtnl.emit[i]) {
                case EMIT_OMIT:
                        break;
                case EMIT_1F:
-                       BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_1F(hw), 1);
-                       OUT_RING  (chan, fui(v->data[idx][0]));
+                       nvfx_emit_vtx_attr(chan, hw, v->data[idx], 1);
                        break;
                case EMIT_2F:
-                       BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_2F_X(hw), 2);
-                       OUT_RING  (chan, fui(v->data[idx][0]));
-                       OUT_RING  (chan, fui(v->data[idx][1]));
+                       nvfx_emit_vtx_attr(chan, hw, v->data[idx], 2);
                        break;
                case EMIT_3F:
-                       BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_3F_X(hw), 3);
-                       OUT_RING  (chan, fui(v->data[idx][0]));
-                       OUT_RING  (chan, fui(v->data[idx][1]));
-                       OUT_RING  (chan, fui(v->data[idx][2]));
+                       nvfx_emit_vtx_attr(chan, hw, v->data[idx], 3);
                        break;
                case EMIT_4F:
-                       BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_4F_X(hw), 4);
-                       OUT_RING  (chan, fui(v->data[idx][0]));
-                       OUT_RING  (chan, fui(v->data[idx][1]));
-                       OUT_RING  (chan, fui(v->data[idx][2]));
-                       OUT_RING  (chan, fui(v->data[idx][3]));
+                       nvfx_emit_vtx_attr(chan, hw, v->data[idx], 4);
                        break;
                case 0xff:
                        BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_4F_X(hw), 4);
@@ -231,15 +223,9 @@ nvfx_draw_render_stage(struct nvfx_context *nvfx)
 }
 
 void
-nvfx_draw_elements_swtnl(struct pipe_context *pipe,
-                        struct pipe_resource *idxbuf,
-                        unsigned idxbuf_size, int idxbuf_bias,
-                        unsigned mode, unsigned start, unsigned count)
+nvfx_draw_vbo_swtnl(struct pipe_context *pipe, const struct pipe_draw_info* info)
 {
        struct nvfx_context *nvfx = nvfx_context(pipe);
-       struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
-       struct pipe_transfer *ib_transfer = NULL;
-       struct pipe_transfer *cb_transfer = NULL;
        unsigned i;
        void *map;
 
@@ -247,47 +233,28 @@ nvfx_draw_elements_swtnl(struct pipe_context *pipe,
                return;
        nvfx_state_emit(nvfx);
 
+       /* these must be passed without adding the offsets */
        for (i = 0; i < nvfx->vtxbuf_nr; i++) {
-               map = pipe_buffer_map(pipe, nvfx->vtxbuf[i].buffer,
-                                      PIPE_TRANSFER_READ,
-                                     &vb_transfer[i]);
+               map = nvfx_buffer(nvfx->vtxbuf[i].buffer)->data;
                draw_set_mapped_vertex_buffer(nvfx->draw, i, map);
        }
 
-       if (idxbuf) {
-               map = pipe_buffer_map(pipe, idxbuf,
-                                     PIPE_TRANSFER_READ,
-                                     &ib_transfer);
-               draw_set_mapped_element_buffer(nvfx->draw, idxbuf_size, idxbuf_bias, map);
-       } else {
-               draw_set_mapped_element_buffer(nvfx->draw, 0, 0, NULL);
-       }
+       map = NULL;
+       if (info->indexed && nvfx->idxbuf.buffer)
+               map = nvfx_buffer(nvfx->idxbuf.buffer)->data;
+       draw_set_mapped_index_buffer(nvfx->draw, map);
 
        if (nvfx->constbuf[PIPE_SHADER_VERTEX]) {
                const unsigned nr = nvfx->constbuf_nr[PIPE_SHADER_VERTEX];
 
-               map = pipe_buffer_map(pipe,
-                                     nvfx->constbuf[PIPE_SHADER_VERTEX],
-                                     PIPE_TRANSFER_READ,
-                                     &cb_transfer);
+               map = nvfx_buffer(nvfx->constbuf[PIPE_SHADER_VERTEX])->data;
                draw_set_mapped_constant_buffer(nvfx->draw, PIPE_SHADER_VERTEX, 0,
                                                 map, nr);
        }
 
-       draw_arrays(nvfx->draw, mode, start, count);
-
-       for (i = 0; i < nvfx->vtxbuf_nr; i++)
-               pipe_buffer_unmap(pipe, nvfx->vtxbuf[i].buffer, vb_transfer[i]);
-
-       if (idxbuf)
-               pipe_buffer_unmap(pipe, idxbuf, ib_transfer);
-
-       if (nvfx->constbuf[PIPE_SHADER_VERTEX])
-               pipe_buffer_unmap(pipe, nvfx->constbuf[PIPE_SHADER_VERTEX],
-                                 cb_transfer);
+       draw_vbo(nvfx->draw, info);
 
        draw_flush(nvfx->draw);
-       pipe->flush(pipe, 0, NULL);
 }
 
 static INLINE void
@@ -305,19 +272,19 @@ emit_attrib(struct nvfx_context *nvfx, unsigned hw, unsigned emit,
 void
 nvfx_vtxfmt_validate(struct nvfx_context *nvfx)
 {
-       struct nvfx_fragment_program *fp = nvfx->fragprog;
+       struct nvfx_pipe_fragment_program *pfp = nvfx->fragprog;
        unsigned colour = 0, texcoords = 0, fog = 0, i;
 
        /* Determine needed fragprog inputs */
-       for (i = 0; i < fp->info.num_inputs; i++) {
-               switch (fp->info.input_semantic_name[i]) {
+       for (i = 0; i < pfp->info.num_inputs; i++) {
+               switch (pfp->info.input_semantic_name[i]) {
                case TGSI_SEMANTIC_POSITION:
                        break;
                case TGSI_SEMANTIC_COLOR:
-                       colour |= (1 << fp->info.input_semantic_index[i]);
+                       colour |= (1 << pfp->info.input_semantic_index[i]);
                        break;
                case TGSI_SEMANTIC_GENERIC:
-                       texcoords |= (1 << fp->info.input_semantic_index[i]);
+                       texcoords |= (1 << pfp->info.input_semantic_index[i]);
                        break;
                case TGSI_SEMANTIC_FOG:
                        fog = 1;
index ee41f03b9b8fd7064f64ff75efeb63f266c427c5..275672a31fac18a6f41d91d63efdbc952eec3430 100644 (file)
@@ -2,25 +2,31 @@
 #include "pipe/p_defines.h"
 #include "pipe/p_state.h"
 #include "util/u_inlines.h"
+#include "util/u_debug.h"
 
 #include "pipe/p_shader_tokens.h"
 #include "tgsi/tgsi_parse.h"
 #include "tgsi/tgsi_util.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_ureg.h"
 
 #include "nvfx_context.h"
 #include "nvfx_shader.h"
+#include "nvfx_resource.h"
 
 #define MAX_CONSTS 128
 #define MAX_IMM 32
+
 struct nvfx_fpc {
+       struct nvfx_pipe_fragment_program* pfp;
        struct nvfx_fragment_program *fp;
 
-       uint attrib_map[PIPE_MAX_SHADER_INPUTS];
-
-       unsigned r_temps;
-       unsigned r_temps_discard;
-       struct nvfx_sreg r_result[PIPE_MAX_SHADER_OUTPUTS];
-       struct nvfx_sreg *r_temp;
+       unsigned max_temps;
+       unsigned long long r_temps;
+       unsigned long long r_temps_discard;
+       struct nvfx_reg r_result[PIPE_MAX_SHADER_OUTPUTS];
+       struct nvfx_reg *r_temp;
+       unsigned sprite_coord_temp;
 
        int num_regs;
 
@@ -33,34 +39,40 @@ struct nvfx_fpc {
        } consts[MAX_CONSTS];
        int nr_consts;
 
-       struct nvfx_sreg imm[MAX_IMM];
+       struct nvfx_reg imm[MAX_IMM];
        unsigned nr_imm;
+
+       unsigned char generic_to_slot[256]; /* semantic idx for each input semantic */
+
+       struct util_dynarray if_stack;
+       //struct util_dynarray loop_stack;
+       struct util_dynarray label_relocs;
 };
 
-static INLINE struct nvfx_sreg
+static INLINE struct nvfx_reg
 temp(struct nvfx_fpc *fpc)
 {
-       int idx = ffs(~fpc->r_temps) - 1;
+       int idx = __builtin_ctzll(~fpc->r_temps);
 
-       if (idx < 0) {
+       if (idx >= fpc->max_temps) {
                NOUVEAU_ERR("out of temps!!\n");
                assert(0);
-               return nvfx_sr(NVFXSR_TEMP, 0);
+               return nvfx_reg(NVFXSR_TEMP, 0);
        }
 
-       fpc->r_temps |= (1 << idx);
-       fpc->r_temps_discard |= (1 << idx);
-       return nvfx_sr(NVFXSR_TEMP, idx);
+       fpc->r_temps |= (1ULL << idx);
+       fpc->r_temps_discard |= (1ULL << idx);
+       return nvfx_reg(NVFXSR_TEMP, idx);
 }
 
 static INLINE void
 release_temps(struct nvfx_fpc *fpc)
 {
        fpc->r_temps &= ~fpc->r_temps_discard;
-       fpc->r_temps_discard = 0;
+       fpc->r_temps_discard = 0ULL;
 }
 
-static INLINE struct nvfx_sreg
+static INLINE struct nvfx_reg
 constant(struct nvfx_fpc *fpc, int pipe, float vals[4])
 {
        int idx;
@@ -72,16 +84,9 @@ constant(struct nvfx_fpc *fpc, int pipe, float vals[4])
        fpc->consts[idx].pipe = pipe;
        if (pipe == -1)
                memcpy(fpc->consts[idx].vals, vals, 4 * sizeof(float));
-       return nvfx_sr(NVFXSR_CONST, idx);
+       return nvfx_reg(NVFXSR_CONST, idx);
 }
 
-#define arith(cc,s,o,d,m,s0,s1,s2) \
-       nvfx_fp_arith((cc), (s), NVFX_FP_OP_OPCODE_##o, \
-                       (d), (m), (s0), (s1), (s2))
-#define tex(cc,s,o,u,d,m,s0,s1,s2) \
-       nvfx_fp_tex((cc), (s), NVFX_FP_OP_OPCODE_##o, (u), \
-                   (d), (m), (s0), none, none)
-
 static void
 grow_insns(struct nvfx_fpc *fpc, int size)
 {
@@ -92,23 +97,29 @@ grow_insns(struct nvfx_fpc *fpc, int size)
 }
 
 static void
-emit_src(struct nvfx_fpc *fpc, int pos, struct nvfx_sreg src)
+emit_src(struct nvfx_fpc *fpc, int pos, struct nvfx_src src)
 {
        struct nvfx_fragment_program *fp = fpc->fp;
        uint32_t *hw = &fp->insn[fpc->inst_offset];
        uint32_t sr = 0;
 
-       switch (src.type) {
+       switch (src.reg.type) {
        case NVFXSR_INPUT:
                sr |= (NVFX_FP_REG_TYPE_INPUT << NVFX_FP_REG_TYPE_SHIFT);
-               hw[0] |= (src.index << NVFX_FP_OP_INPUT_SRC_SHIFT);
+               hw[0] |= (src.reg.index << NVFX_FP_OP_INPUT_SRC_SHIFT);
                break;
        case NVFXSR_OUTPUT:
                sr |= NVFX_FP_REG_SRC_HALF;
                /* fall-through */
        case NVFXSR_TEMP:
                sr |= (NVFX_FP_REG_TYPE_TEMP << NVFX_FP_REG_TYPE_SHIFT);
-               sr |= (src.index << NVFX_FP_REG_SRC_SHIFT);
+               sr |= (src.reg.index << NVFX_FP_REG_SRC_SHIFT);
+               break;
+       case NVFXSR_RELOCATED:
+               sr |= (NVFX_FP_REG_TYPE_TEMP << NVFX_FP_REG_TYPE_SHIFT);
+               sr |= (fpc->sprite_coord_temp << NVFX_FP_REG_SRC_SHIFT);
+               //printf("adding relocation at %x for %x\n", fpc->inst_offset, src.index);
+               util_dynarray_append(&fpc->fp->slot_relocations[src.reg.index], unsigned, fpc->inst_offset + pos + 1);
                break;
        case NVFXSR_CONST:
                if (!fpc->have_const) {
@@ -117,18 +128,18 @@ emit_src(struct nvfx_fpc *fpc, int pos, struct nvfx_sreg src)
                }
 
                hw = &fp->insn[fpc->inst_offset];
-               if (fpc->consts[src.index].pipe >= 0) {
+               if (fpc->consts[src.reg.index].pipe >= 0) {
                        struct nvfx_fragment_program_data *fpd;
 
                        fp->consts = realloc(fp->consts, ++fp->nr_consts *
                                             sizeof(*fpd));
                        fpd = &fp->consts[fp->nr_consts - 1];
                        fpd->offset = fpc->inst_offset + 4;
-                       fpd->index = fpc->consts[src.index].pipe;
+                       fpd->index = fpc->consts[src.reg.index].pipe;
                        memset(&fp->insn[fpd->offset], 0, sizeof(uint32_t) * 4);
                } else {
                        memcpy(&fp->insn[fpc->inst_offset + 4],
-                               fpc->consts[src.index].vals,
+                               fpc->consts[src.reg.index].vals,
                                sizeof(uint32_t) * 4);
                }
 
@@ -156,7 +167,7 @@ emit_src(struct nvfx_fpc *fpc, int pos, struct nvfx_sreg src)
 }
 
 static void
-emit_dst(struct nvfx_fpc *fpc, struct nvfx_sreg dst)
+emit_dst(struct nvfx_fpc *fpc, struct nvfx_reg dst)
 {
        struct nvfx_fragment_program *fp = fpc->fp;
        uint32_t *hw = &fp->insn[fpc->inst_offset];
@@ -184,9 +195,7 @@ emit_dst(struct nvfx_fpc *fpc, struct nvfx_sreg dst)
 }
 
 static void
-nvfx_fp_arith(struct nvfx_fpc *fpc, int sat, int op,
-             struct nvfx_sreg dst, int mask,
-             struct nvfx_sreg s0, struct nvfx_sreg s1, struct nvfx_sreg s2)
+nvfx_fp_emit(struct nvfx_fpc *fpc, struct nvfx_insn insn)
 {
        struct nvfx_fragment_program *fp = fpc->fp;
        uint32_t *hw;
@@ -197,68 +206,225 @@ nvfx_fp_arith(struct nvfx_fpc *fpc, int sat, int op,
        hw = &fp->insn[fpc->inst_offset];
        memset(hw, 0, sizeof(uint32_t) * 4);
 
-       if (op == NVFX_FP_OP_OPCODE_KIL)
+       if (insn.op == NVFX_FP_OP_OPCODE_KIL)
                fp->fp_control |= NV34TCL_FP_CONTROL_USES_KIL;
-       hw[0] |= (op << NVFX_FP_OP_OPCODE_SHIFT);
-       hw[0] |= (mask << NVFX_FP_OP_OUTMASK_SHIFT);
-       hw[2] |= (dst.dst_scale << NVFX_FP_OP_DST_SCALE_SHIFT);
+       hw[0] |= (insn.op << NVFX_FP_OP_OPCODE_SHIFT);
+       hw[0] |= (insn.mask << NVFX_FP_OP_OUTMASK_SHIFT);
+       hw[2] |= (insn.scale << NVFX_FP_OP_DST_SCALE_SHIFT);
 
-       if (sat)
+       if (insn.sat)
                hw[0] |= NVFX_FP_OP_OUT_SAT;
 
-       if (dst.cc_update)
+       if (insn.cc_update)
                hw[0] |= NVFX_FP_OP_COND_WRITE_ENABLE;
-       hw[1] |= (dst.cc_test << NVFX_FP_OP_COND_SHIFT);
-       hw[1] |= ((dst.cc_swz[0] << NVFX_FP_OP_COND_SWZ_X_SHIFT) |
-                 (dst.cc_swz[1] << NVFX_FP_OP_COND_SWZ_Y_SHIFT) |
-                 (dst.cc_swz[2] << NVFX_FP_OP_COND_SWZ_Z_SHIFT) |
-                 (dst.cc_swz[3] << NVFX_FP_OP_COND_SWZ_W_SHIFT));
-
-       emit_dst(fpc, dst);
-       emit_src(fpc, 0, s0);
-       emit_src(fpc, 1, s1);
-       emit_src(fpc, 2, s2);
+       hw[1] |= (insn.cc_test << NVFX_FP_OP_COND_SHIFT);
+       hw[1] |= ((insn.cc_swz[0] << NVFX_FP_OP_COND_SWZ_X_SHIFT) |
+                 (insn.cc_swz[1] << NVFX_FP_OP_COND_SWZ_Y_SHIFT) |
+                 (insn.cc_swz[2] << NVFX_FP_OP_COND_SWZ_Z_SHIFT) |
+                 (insn.cc_swz[3] << NVFX_FP_OP_COND_SWZ_W_SHIFT));
+
+       if(insn.unit >= 0)
+       {
+               hw[0] |= (insn.unit << NVFX_FP_OP_TEX_UNIT_SHIFT);
+               fp->samplers |= (1 << insn.unit);
+       }
+
+       emit_dst(fpc, insn.dst);
+       emit_src(fpc, 0, insn.src[0]);
+       emit_src(fpc, 1, insn.src[1]);
+       emit_src(fpc, 2, insn.src[2]);
 }
 
+#define arith(s,o,d,m,s0,s1,s2) \
+       nvfx_insn((s), NVFX_FP_OP_OPCODE_##o, -1, \
+                       (d), (m), (s0), (s1), (s2))
+
+#define tex(s,o,u,d,m,s0,s1,s2) \
+       nvfx_insn((s), NVFX_FP_OP_OPCODE_##o, (u), \
+                   (d), (m), (s0), none, none)
+
+/* IF src.x != 0, as TGSI specifies */
 static void
-nvfx_fp_tex(struct nvfx_fpc *fpc, int sat, int op, int unit,
-           struct nvfx_sreg dst, int mask,
-           struct nvfx_sreg s0, struct nvfx_sreg s1, struct nvfx_sreg s2)
+nv40_fp_if(struct nvfx_fpc *fpc, struct nvfx_src src)
 {
-       struct nvfx_fragment_program *fp = fpc->fp;
+       const struct nvfx_src none = nvfx_src(nvfx_reg(NVFXSR_NONE, 0));
+       struct nvfx_insn insn = arith(0, MOV, none.reg, NVFX_FP_MASK_X, src, none, none);
+       uint32_t *hw;
+       insn.cc_update = 1;
+       nvfx_fp_emit(fpc, insn);
 
-       nvfx_fp_arith(fpc, sat, op, dst, mask, s0, s1, s2);
+       fpc->inst_offset = fpc->fp->insn_len;
+       grow_insns(fpc, 4);
+       hw = &fpc->fp->insn[fpc->inst_offset];
+       /* I really wonder why fp16 precision is used. Presumably the hardware ignores it? */
+       hw[0] = (NV40_FP_OP_BRA_OPCODE_IF << NVFX_FP_OP_OPCODE_SHIFT) |
+               NV40_FP_OP_OUT_NONE |
+               (NVFX_FP_PRECISION_FP16 << NVFX_FP_OP_PRECISION_SHIFT);
+       /* Use .xxxx swizzle so that we check only src[0].x*/
+       hw[1] = (0 << NVFX_FP_OP_COND_SWZ_X_SHIFT) |
+                       (0 << NVFX_FP_OP_COND_SWZ_Y_SHIFT) |
+                       (0 << NVFX_FP_OP_COND_SWZ_Z_SHIFT) |
+                       (0 << NVFX_FP_OP_COND_SWZ_W_SHIFT) |
+                       (NVFX_FP_OP_COND_NE << NVFX_FP_OP_COND_SHIFT);
+       hw[2] = 0; /* | NV40_FP_OP_OPCODE_IS_BRANCH | else_offset */
+       hw[3] = 0; /* | endif_offset */
+       util_dynarray_append(&fpc->if_stack, unsigned, fpc->inst_offset);
+}
+
+/* IF src.x != 0, as TGSI specifies */
+static void
+nv40_fp_cal(struct nvfx_fpc *fpc, unsigned target)
+{
+        struct nvfx_relocation reloc;
+        uint32_t *hw;
+        fpc->inst_offset = fpc->fp->insn_len;
+        grow_insns(fpc, 4);
+        hw = &fpc->fp->insn[fpc->inst_offset];
+        /* I really wonder why fp16 precision is used. Presumably the hardware ignores it? */
+        hw[0] = (NV40_FP_OP_BRA_OPCODE_CAL << NVFX_FP_OP_OPCODE_SHIFT);
+        /* Use .xxxx swizzle so that we check only src[0].x*/
+        hw[1] = (NVFX_SWZ_IDENTITY << NVFX_FP_OP_COND_SWZ_ALL_SHIFT) |
+                        (NVFX_FP_OP_COND_TR << NVFX_FP_OP_COND_SHIFT);
+        hw[2] = NV40_FP_OP_OPCODE_IS_BRANCH; /* | call_offset */
+        hw[3] = 0;
+        reloc.target = target;
+        reloc.location = fpc->inst_offset + 2;
+        util_dynarray_append(&fpc->label_relocs, struct nvfx_relocation, reloc);
+}
+
+static void
+nv40_fp_ret(struct nvfx_fpc *fpc)
+{
+       uint32_t *hw;
+       fpc->inst_offset = fpc->fp->insn_len;
+       grow_insns(fpc, 4);
+       hw = &fpc->fp->insn[fpc->inst_offset];
+       /* I really wonder why fp16 precision is used. Presumably the hardware ignores it? */
+       hw[0] = (NV40_FP_OP_BRA_OPCODE_RET << NVFX_FP_OP_OPCODE_SHIFT);
+       /* Use .xxxx swizzle so that we check only src[0].x*/
+       hw[1] = (NVFX_SWZ_IDENTITY << NVFX_FP_OP_COND_SWZ_ALL_SHIFT) |
+                       (NVFX_FP_OP_COND_TR << NVFX_FP_OP_COND_SHIFT);
+       hw[2] = NV40_FP_OP_OPCODE_IS_BRANCH; /* | call_offset */
+       hw[3] = 0;
+}
 
-       fp->insn[fpc->inst_offset] |= (unit << NVFX_FP_OP_TEX_UNIT_SHIFT);
-       fp->samplers |= (1 << unit);
+static void
+nv40_fp_rep(struct nvfx_fpc *fpc, unsigned count, unsigned target)
+{
+        struct nvfx_relocation reloc;
+        uint32_t *hw;
+        fpc->inst_offset = fpc->fp->insn_len;
+        grow_insns(fpc, 4);
+        hw = &fpc->fp->insn[fpc->inst_offset];
+        /* I really wonder why fp16 precision is used. Presumably the hardware ignores it? */
+        hw[0] = (NV40_FP_OP_BRA_OPCODE_REP << NVFX_FP_OP_OPCODE_SHIFT) |
+                        NV40_FP_OP_OUT_NONE |
+                        (NVFX_FP_PRECISION_FP16 << NVFX_FP_OP_PRECISION_SHIFT);
+        /* Use .xxxx swizzle so that we check only src[0].x*/
+        hw[1] = (NVFX_SWZ_IDENTITY << NVFX_FP_OP_COND_SWZ_ALL_SHIFT) |
+                        (NVFX_FP_OP_COND_TR << NVFX_FP_OP_COND_SHIFT);
+        hw[2] = NV40_FP_OP_OPCODE_IS_BRANCH |
+                        (count << NV40_FP_OP_REP_COUNT1_SHIFT) |
+                        (count << NV40_FP_OP_REP_COUNT2_SHIFT) |
+                        (count << NV40_FP_OP_REP_COUNT3_SHIFT);
+        hw[3] = 0; /* | end_offset */
+        reloc.target = target;
+        reloc.location = fpc->inst_offset + 3;
+        util_dynarray_append(&fpc->label_relocs, struct nvfx_relocation, reloc);
+        //util_dynarray_append(&fpc->loop_stack, unsigned, target);
 }
 
-static INLINE struct nvfx_sreg
+/* warning: this only works forward, and probably only if not inside any IF */
+static void
+nv40_fp_bra(struct nvfx_fpc *fpc, unsigned target)
+{
+        struct nvfx_relocation reloc;
+        uint32_t *hw;
+        fpc->inst_offset = fpc->fp->insn_len;
+        grow_insns(fpc, 4);
+        hw = &fpc->fp->insn[fpc->inst_offset];
+        /* I really wonder why fp16 precision is used. Presumably the hardware ignores it? */
+        hw[0] = (NV40_FP_OP_BRA_OPCODE_IF << NVFX_FP_OP_OPCODE_SHIFT) |
+                NV40_FP_OP_OUT_NONE |
+                (NVFX_FP_PRECISION_FP16 << NVFX_FP_OP_PRECISION_SHIFT);
+        /* Use .xxxx swizzle so that we check only src[0].x*/
+        hw[1] = (NVFX_SWZ_IDENTITY << NVFX_FP_OP_COND_SWZ_X_SHIFT) |
+                        (NVFX_FP_OP_COND_FL << NVFX_FP_OP_COND_SHIFT);
+        hw[2] = NV40_FP_OP_OPCODE_IS_BRANCH; /* | else_offset */
+        hw[3] = 0; /* | endif_offset */
+        reloc.target = target;
+        reloc.location = fpc->inst_offset + 2;
+        util_dynarray_append(&fpc->label_relocs, struct nvfx_relocation, reloc);
+        reloc.target = target;
+        reloc.location = fpc->inst_offset + 3;
+        util_dynarray_append(&fpc->label_relocs, struct nvfx_relocation, reloc);
+}
+
+static void
+nv40_fp_brk(struct nvfx_fpc *fpc)
+{
+       uint32_t *hw;
+       fpc->inst_offset = fpc->fp->insn_len;
+       grow_insns(fpc, 4);
+       hw = &fpc->fp->insn[fpc->inst_offset];
+       /* I really wonder why fp16 precision is used. Presumably the hardware ignores it? */
+       hw[0] = (NV40_FP_OP_BRA_OPCODE_BRK << NVFX_FP_OP_OPCODE_SHIFT) |
+               NV40_FP_OP_OUT_NONE;
+       /* Use .xxxx swizzle so that we check only src[0].x*/
+       hw[1] = (NVFX_SWZ_IDENTITY << NVFX_FP_OP_COND_SWZ_X_SHIFT) |
+                       (NVFX_FP_OP_COND_TR << NVFX_FP_OP_COND_SHIFT);
+       hw[2] = NV40_FP_OP_OPCODE_IS_BRANCH;
+       hw[3] = 0;
+}
+
+static INLINE struct nvfx_src
 tgsi_src(struct nvfx_fpc *fpc, const struct tgsi_full_src_register *fsrc)
 {
-       struct nvfx_sreg src = { 0 };
+       struct nvfx_src src;
 
        switch (fsrc->Register.File) {
        case TGSI_FILE_INPUT:
-               src = nvfx_sr(NVFXSR_INPUT,
-                             fpc->attrib_map[fsrc->Register.Index]);
+               if(fpc->pfp->info.input_semantic_name[fsrc->Register.Index] == TGSI_SEMANTIC_POSITION) {
+                       assert(fpc->pfp->info.input_semantic_index[fsrc->Register.Index] == 0);
+                       src.reg = nvfx_reg(NVFXSR_INPUT, NVFX_FP_OP_INPUT_SRC_POSITION);
+               } else if(fpc->pfp->info.input_semantic_name[fsrc->Register.Index] == TGSI_SEMANTIC_COLOR) {
+                       if(fpc->pfp->info.input_semantic_index[fsrc->Register.Index] == 0)
+                               src.reg = nvfx_reg(NVFXSR_INPUT, NVFX_FP_OP_INPUT_SRC_COL0);
+                       else if(fpc->pfp->info.input_semantic_index[fsrc->Register.Index] == 1)
+                               src.reg = nvfx_reg(NVFXSR_INPUT, NVFX_FP_OP_INPUT_SRC_COL1);
+                       else
+                               assert(0);
+               } else if(fpc->pfp->info.input_semantic_name[fsrc->Register.Index] == TGSI_SEMANTIC_FOG) {
+                       assert(fpc->pfp->info.input_semantic_index[fsrc->Register.Index] == 0);
+                       src.reg = nvfx_reg(NVFXSR_INPUT, NVFX_FP_OP_INPUT_SRC_FOGC);
+               } else if(fpc->pfp->info.input_semantic_name[fsrc->Register.Index] == TGSI_SEMANTIC_FACE) {
+                       /* TODO: check this has the correct values */
+                       /* XXX: what do we do for nv30 here (assuming it lacks facing)?!  */
+                       assert(fpc->pfp->info.input_semantic_index[fsrc->Register.Index] == 0);
+                       src.reg = nvfx_reg(NVFXSR_INPUT, NV40_FP_OP_INPUT_SRC_FACING);
+               } else {
+                       assert(fpc->pfp->info.input_semantic_name[fsrc->Register.Index] == TGSI_SEMANTIC_GENERIC);
+                       src.reg = nvfx_reg(NVFXSR_RELOCATED, fpc->generic_to_slot[fpc->pfp->info.input_semantic_index[fsrc->Register.Index]]);
+               }
                break;
        case TGSI_FILE_CONSTANT:
-               src = constant(fpc, fsrc->Register.Index, NULL);
+               src.reg = constant(fpc, fsrc->Register.Index, NULL);
                break;
        case TGSI_FILE_IMMEDIATE:
                assert(fsrc->Register.Index < fpc->nr_imm);
-               src = fpc->imm[fsrc->Register.Index];
+               src.reg = fpc->imm[fsrc->Register.Index];
                break;
        case TGSI_FILE_TEMPORARY:
-               src = fpc->r_temp[fsrc->Register.Index];
+               src.reg = fpc->r_temp[fsrc->Register.Index];
                break;
        /* NV40 fragprog result regs are just temps, so this is simple */
        case TGSI_FILE_OUTPUT:
-               src = fpc->r_result[fsrc->Register.Index];
+               src.reg = fpc->r_result[fsrc->Register.Index];
                break;
        default:
                NOUVEAU_ERR("bad src file\n");
+               src.reg.index = 0;
+               src.reg.type = 0;
                break;
        }
 
@@ -271,7 +437,7 @@ tgsi_src(struct nvfx_fpc *fpc, const struct tgsi_full_src_register *fsrc)
        return src;
 }
 
-static INLINE struct nvfx_sreg
+static INLINE struct nvfx_reg
 tgsi_dst(struct nvfx_fpc *fpc, const struct tgsi_full_dst_register *fdst) {
        switch (fdst->Register.File) {
        case TGSI_FILE_OUTPUT:
@@ -279,10 +445,10 @@ tgsi_dst(struct nvfx_fpc *fpc, const struct tgsi_full_dst_register *fdst) {
        case TGSI_FILE_TEMPORARY:
                return fpc->r_temp[fdst->Register.Index];
        case TGSI_FILE_NULL:
-               return nvfx_sr(NVFXSR_NONE, 0);
+               return nvfx_reg(NVFXSR_NONE, 0);
        default:
                NOUVEAU_ERR("bad dst file %d\n", fdst->Register.File);
-               return nvfx_sr(NVFXSR_NONE, 0);
+               return nvfx_reg(NVFXSR_NONE, 0);
        }
 }
 
@@ -302,8 +468,10 @@ static boolean
 nvfx_fragprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_fpc *fpc,
                                const struct tgsi_full_instruction *finst)
 {
-       const struct nvfx_sreg none = nvfx_sr(NVFXSR_NONE, 0);
-       struct nvfx_sreg src[3], dst, tmp;
+       const struct nvfx_src none = nvfx_src(nvfx_reg(NVFXSR_NONE, 0));
+       struct nvfx_insn insn;
+       struct nvfx_src src[3], tmp, tmp2;
+       struct nvfx_reg dst;
        int mask, sat, unit = 0;
        int ai = -1, ci = -1, ii = -1;
        int i;
@@ -331,9 +499,8 @@ nvfx_fragprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_fpc *fpc,
                                ai = fsrc->Register.Index;
                                src[i] = tgsi_src(fpc, fsrc);
                        } else {
-                               src[i] = temp(fpc);
-                               arith(fpc, 0, MOV, src[i], NVFX_FP_MASK_ALL,
-                                     tgsi_src(fpc, fsrc), none, none);
+                               src[i] = nvfx_src(temp(fpc));
+                               nvfx_fp_emit(fpc, arith(0, MOV, src[i].reg, NVFX_FP_MASK_ALL, tgsi_src(fpc, fsrc), none, none));
                        }
                        break;
                case TGSI_FILE_CONSTANT:
@@ -342,9 +509,8 @@ nvfx_fragprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_fpc *fpc,
                                ci = fsrc->Register.Index;
                                src[i] = tgsi_src(fpc, fsrc);
                        } else {
-                               src[i] = temp(fpc);
-                               arith(fpc, 0, MOV, src[i], NVFX_FP_MASK_ALL,
-                                     tgsi_src(fpc, fsrc), none, none);
+                               src[i] = nvfx_src(temp(fpc));
+                               nvfx_fp_emit(fpc, arith(0, MOV, src[i].reg, NVFX_FP_MASK_ALL, tgsi_src(fpc, fsrc), none, none));
                        }
                        break;
                case TGSI_FILE_IMMEDIATE:
@@ -353,9 +519,8 @@ nvfx_fragprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_fpc *fpc,
                                ii = fsrc->Register.Index;
                                src[i] = tgsi_src(fpc, fsrc);
                        } else {
-                               src[i] = temp(fpc);
-                               arith(fpc, 0, MOV, src[i], NVFX_FP_MASK_ALL,
-                                     tgsi_src(fpc, fsrc), none, none);
+                               src[i] = nvfx_src(temp(fpc));
+                               nvfx_fp_emit(fpc, arith(0, MOV, src[i].reg, NVFX_FP_MASK_ALL, tgsi_src(fpc, fsrc), none, none));
                        }
                        break;
                case TGSI_FILE_TEMPORARY:
@@ -378,277 +543,345 @@ nvfx_fragprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_fpc *fpc,
 
        switch (finst->Instruction.Opcode) {
        case TGSI_OPCODE_ABS:
-               arith(fpc, sat, MOV, dst, mask, abs(src[0]), none, none);
+               nvfx_fp_emit(fpc, arith(sat, MOV, dst, mask, abs(src[0]), none, none));
                break;
        case TGSI_OPCODE_ADD:
-               arith(fpc, sat, ADD, dst, mask, src[0], src[1], none);
+               nvfx_fp_emit(fpc, arith(sat, ADD, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_CMP:
-               tmp = nvfx_sr(NVFXSR_NONE, 0);
-               tmp.cc_update = 1;
-               arith(fpc, 0, MOV, tmp, 0xf, src[0], none, none);
-               dst.cc_test = NVFX_COND_GE;
-               arith(fpc, sat, MOV, dst, mask, src[2], none, none);
-               dst.cc_test = NVFX_COND_LT;
-               arith(fpc, sat, MOV, dst, mask, src[1], none, none);
+               insn = arith(0, MOV, none.reg, mask, src[0], none, none);
+               insn.cc_update = 1;
+               nvfx_fp_emit(fpc, insn);
+
+               insn = arith(sat, MOV, dst, mask, src[2], none, none);
+               insn.cc_test = NVFX_COND_GE;
+               nvfx_fp_emit(fpc, insn);
+
+               insn = arith(sat, MOV, dst, mask, src[1], none, none);
+               insn.cc_test = NVFX_COND_LT;
+               nvfx_fp_emit(fpc, insn);
                break;
        case TGSI_OPCODE_COS:
-               arith(fpc, sat, COS, dst, mask, src[0], none, none);
+               nvfx_fp_emit(fpc, arith(sat, COS, dst, mask, src[0], none, none));
                break;
        case TGSI_OPCODE_DDX:
                if (mask & (NVFX_FP_MASK_Z | NVFX_FP_MASK_W)) {
-                       tmp = temp(fpc);
-                       arith(fpc, sat, DDX, tmp, NVFX_FP_MASK_X | NVFX_FP_MASK_Y,
-                             swz(src[0], Z, W, Z, W), none, none);
-                       arith(fpc, 0, MOV, tmp, NVFX_FP_MASK_Z | NVFX_FP_MASK_W,
-                             swz(tmp, X, Y, X, Y), none, none);
-                       arith(fpc, sat, DDX, tmp, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, src[0],
-                             none, none);
-                       arith(fpc, 0, MOV, dst, mask, tmp, none, none);
+                       tmp = nvfx_src(temp(fpc));
+                       nvfx_fp_emit(fpc, arith(sat, DDX, tmp.reg, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, swz(src[0], Z, W, Z, W), none, none));
+                       nvfx_fp_emit(fpc, arith(0, MOV, tmp.reg, NVFX_FP_MASK_Z | NVFX_FP_MASK_W, swz(tmp, X, Y, X, Y), none, none));
+                       nvfx_fp_emit(fpc, arith(sat, DDX, tmp.reg, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, src[0], none, none));
+                       nvfx_fp_emit(fpc, arith(0, MOV, dst, mask, tmp, none, none));
                } else {
-                       arith(fpc, sat, DDX, dst, mask, src[0], none, none);
+                       nvfx_fp_emit(fpc, arith(sat, DDX, dst, mask, src[0], none, none));
                }
                break;
        case TGSI_OPCODE_DDY:
                if (mask & (NVFX_FP_MASK_Z | NVFX_FP_MASK_W)) {
-                       tmp = temp(fpc);
-                       arith(fpc, sat, DDY, tmp, NVFX_FP_MASK_X | NVFX_FP_MASK_Y,
-                             swz(src[0], Z, W, Z, W), none, none);
-                       arith(fpc, 0, MOV, tmp, NVFX_FP_MASK_Z | NVFX_FP_MASK_W,
-                             swz(tmp, X, Y, X, Y), none, none);
-                       arith(fpc, sat, DDY, tmp, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, src[0],
-                             none, none);
-                       arith(fpc, 0, MOV, dst, mask, tmp, none, none);
+                       tmp = nvfx_src(temp(fpc));
+                       nvfx_fp_emit(fpc, arith(sat, DDY, tmp.reg, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, swz(src[0], Z, W, Z, W), none, none));
+                       nvfx_fp_emit(fpc, arith(0, MOV, tmp.reg, NVFX_FP_MASK_Z | NVFX_FP_MASK_W, swz(tmp, X, Y, X, Y), none, none));
+                       nvfx_fp_emit(fpc, arith(sat, DDY, tmp.reg, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, src[0], none, none));
+                       nvfx_fp_emit(fpc, arith(0, MOV, dst, mask, tmp, none, none));
                } else {
-                       arith(fpc, sat, DDY, dst, mask, src[0], none, none);
+                       nvfx_fp_emit(fpc, arith(sat, DDY, dst, mask, src[0], none, none));
                }
                break;
+       case TGSI_OPCODE_DP2:
+               tmp = nvfx_src(temp(fpc));
+               nvfx_fp_emit(fpc, arith(0, MUL, tmp.reg, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, src[0], src[1], none));
+               nvfx_fp_emit(fpc, arith(0, ADD, dst, mask, swz(tmp, X, X, X, X), swz(tmp, Y, Y, Y, Y), none));
+               break;
        case TGSI_OPCODE_DP3:
-               arith(fpc, sat, DP3, dst, mask, src[0], src[1], none);
+               nvfx_fp_emit(fpc, arith(sat, DP3, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_DP4:
-               arith(fpc, sat, DP4, dst, mask, src[0], src[1], none);
+               nvfx_fp_emit(fpc, arith(sat, DP4, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_DPH:
-               tmp = temp(fpc);
-               arith(fpc, 0, DP3, tmp, NVFX_FP_MASK_X, src[0], src[1], none);
-               arith(fpc, sat, ADD, dst, mask, swz(tmp, X, X, X, X),
-                     swz(src[1], W, W, W, W), none);
+               tmp = nvfx_src(temp(fpc));
+               nvfx_fp_emit(fpc, arith(0, DP3, tmp.reg, NVFX_FP_MASK_X, src[0], src[1], none));
+               nvfx_fp_emit(fpc, arith(sat, ADD, dst, mask, swz(tmp, X, X, X, X), swz(src[1], W, W, W, W), none));
                break;
        case TGSI_OPCODE_DST:
-               arith(fpc, sat, DST, dst, mask, src[0], src[1], none);
+               nvfx_fp_emit(fpc, arith(sat, DST, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_EX2:
-               arith(fpc, sat, EX2, dst, mask, src[0], none, none);
+               nvfx_fp_emit(fpc, arith(sat, EX2, dst, mask, src[0], none, none));
                break;
        case TGSI_OPCODE_FLR:
-               arith(fpc, sat, FLR, dst, mask, src[0], none, none);
+               nvfx_fp_emit(fpc, arith(sat, FLR, dst, mask, src[0], none, none));
                break;
        case TGSI_OPCODE_FRC:
-               arith(fpc, sat, FRC, dst, mask, src[0], none, none);
+               nvfx_fp_emit(fpc, arith(sat, FRC, dst, mask, src[0], none, none));
                break;
        case TGSI_OPCODE_KILP:
-               arith(fpc, 0, KIL, none, 0, none, none, none);
+               nvfx_fp_emit(fpc, arith(0, KIL, none.reg, 0, none, none, none));
                break;
        case TGSI_OPCODE_KIL:
-               dst = nvfx_sr(NVFXSR_NONE, 0);
-               dst.cc_update = 1;
-               arith(fpc, 0, MOV, dst, NVFX_FP_MASK_ALL, src[0], none, none);
-               dst.cc_update = 0; dst.cc_test = NVFX_COND_LT;
-               arith(fpc, 0, KIL, dst, 0, none, none, none);
+               insn = arith(0, MOV, none.reg, NVFX_FP_MASK_ALL, src[0], none, none);
+               insn.cc_update = 1;
+               nvfx_fp_emit(fpc, insn);
+
+               insn = arith(0, KIL, none.reg, 0, none, none, none);
+               insn.cc_test = NVFX_COND_LT;
+               nvfx_fp_emit(fpc, insn);
                break;
        case TGSI_OPCODE_LG2:
-               arith(fpc, sat, LG2, dst, mask, src[0], none, none);
+               nvfx_fp_emit(fpc, arith(sat, LG2, dst, mask, src[0], none, none));
                break;
 //     case TGSI_OPCODE_LIT:
        case TGSI_OPCODE_LRP:
                if(!nvfx->is_nv4x)
-                       arith(fpc, sat, LRP_NV30, dst, mask, src[0], src[1], src[2]);
+                       nvfx_fp_emit(fpc, arith(sat, LRP_NV30, dst, mask, src[0], src[1], src[2]));
                else {
-                       tmp = temp(fpc);
-                       arith(fpc, 0, MAD, tmp, mask, neg(src[0]), src[2], src[2]);
-                       arith(fpc, sat, MAD, dst, mask, src[0], src[1], tmp);
+                       tmp = nvfx_src(temp(fpc));
+                       nvfx_fp_emit(fpc, arith(0, MAD, tmp.reg, mask, neg(src[0]), src[2], src[2]));
+                       nvfx_fp_emit(fpc, arith(sat, MAD, dst, mask, src[0], src[1], tmp));
                }
                break;
        case TGSI_OPCODE_MAD:
-               arith(fpc, sat, MAD, dst, mask, src[0], src[1], src[2]);
+               nvfx_fp_emit(fpc, arith(sat, MAD, dst, mask, src[0], src[1], src[2]));
                break;
        case TGSI_OPCODE_MAX:
-               arith(fpc, sat, MAX, dst, mask, src[0], src[1], none);
+               nvfx_fp_emit(fpc, arith(sat, MAX, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_MIN:
-               arith(fpc, sat, MIN, dst, mask, src[0], src[1], none);
+               nvfx_fp_emit(fpc, arith(sat, MIN, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_MOV:
-               arith(fpc, sat, MOV, dst, mask, src[0], none, none);
+               nvfx_fp_emit(fpc, arith(sat, MOV, dst, mask, src[0], none, none));
                break;
        case TGSI_OPCODE_MUL:
-               arith(fpc, sat, MUL, dst, mask, src[0], src[1], none);
+               nvfx_fp_emit(fpc, arith(sat, MUL, dst, mask, src[0], src[1], none));
+               break;
+       case TGSI_OPCODE_NOP:
                break;
        case TGSI_OPCODE_POW:
                if(!nvfx->is_nv4x)
-                       arith(fpc, sat, POW_NV30, dst, mask, src[0], src[1], none);
+                       nvfx_fp_emit(fpc, arith(sat, POW_NV30, dst, mask, src[0], src[1], none));
                else {
-                       tmp = temp(fpc);
-                       arith(fpc, 0, LG2, tmp, NVFX_FP_MASK_X,
-                             swz(src[0], X, X, X, X), none, none);
-                       arith(fpc, 0, MUL, tmp, NVFX_FP_MASK_X, swz(tmp, X, X, X, X),
-                             swz(src[1], X, X, X, X), none);
-                       arith(fpc, sat, EX2, dst, mask,
-                             swz(tmp, X, X, X, X), none, none);
+                       tmp = nvfx_src(temp(fpc));
+                       nvfx_fp_emit(fpc, arith(0, LG2, tmp.reg, NVFX_FP_MASK_X, swz(src[0], X, X, X, X), none, none));
+                       nvfx_fp_emit(fpc, arith(0, MUL, tmp.reg, NVFX_FP_MASK_X, swz(tmp, X, X, X, X), swz(src[1], X, X, X, X), none));
+                       nvfx_fp_emit(fpc, arith(sat, EX2, dst, mask, swz(tmp, X, X, X, X), none, none));
                }
                break;
        case TGSI_OPCODE_RCP:
-               arith(fpc, sat, RCP, dst, mask, src[0], none, none);
-               break;
-       case TGSI_OPCODE_RET:
-               assert(0);
+               nvfx_fp_emit(fpc, arith(sat, RCP, dst, mask, src[0], none, none));
                break;
        case TGSI_OPCODE_RFL:
                if(!nvfx->is_nv4x)
-                       arith(fpc, 0, RFL_NV30, dst, mask, src[0], src[1], none);
+                       nvfx_fp_emit(fpc, arith(0, RFL_NV30, dst, mask, src[0], src[1], none));
                else {
-                       tmp = temp(fpc);
-                       arith(fpc, 0, DP3, tmp, NVFX_FP_MASK_X, src[0], src[0], none);
-                       arith(fpc, 0, DP3, tmp, NVFX_FP_MASK_Y, src[0], src[1], none);
-                       arith(fpc, 0, DIV, scale(tmp, 2X), NVFX_FP_MASK_Z,
-                             swz(tmp, Y, Y, Y, Y), swz(tmp, X, X, X, X), none);
-                       arith(fpc, sat, MAD, dst, mask,
-                             swz(tmp, Z, Z, Z, Z), src[0], neg(src[1]));
+                       tmp = nvfx_src(temp(fpc));
+                       nvfx_fp_emit(fpc, arith(0, DP3, tmp.reg, NVFX_FP_MASK_X, src[0], src[0], none));
+                       nvfx_fp_emit(fpc, arith(0, DP3, tmp.reg, NVFX_FP_MASK_Y, src[0], src[1], none));
+                       insn = arith(0, DIV, tmp.reg, NVFX_FP_MASK_Z, swz(tmp, Y, Y, Y, Y), swz(tmp, X, X, X, X), none);
+                       insn.scale = NVFX_FP_OP_DST_SCALE_2X;
+                       nvfx_fp_emit(fpc, insn);
+                       nvfx_fp_emit(fpc, arith(sat, MAD, dst, mask, swz(tmp, Z, Z, Z, Z), src[0], neg(src[1])));
                }
                break;
        case TGSI_OPCODE_RSQ:
                if(!nvfx->is_nv4x)
-                       arith(fpc, sat, RSQ_NV30, dst, mask, abs(swz(src[0], X, X, X, X)), none, none);
+                       nvfx_fp_emit(fpc, arith(sat, RSQ_NV30, dst, mask, abs(swz(src[0], X, X, X, X)), none, none));
                else {
-                       tmp = temp(fpc);
-                       arith(fpc, 0, LG2, scale(tmp, INV_2X), NVFX_FP_MASK_X,
-                             abs(swz(src[0], X, X, X, X)), none, none);
-                       arith(fpc, sat, EX2, dst, mask,
-                             neg(swz(tmp, X, X, X, X)), none, none);
+                       tmp = nvfx_src(temp(fpc));
+                       insn = arith(0, LG2, tmp.reg, NVFX_FP_MASK_X, abs(swz(src[0], X, X, X, X)), none, none);
+                       insn.scale = NVFX_FP_OP_DST_SCALE_INV_2X;
+                       nvfx_fp_emit(fpc, insn);
+                       nvfx_fp_emit(fpc, arith(sat, EX2, dst, mask, neg(swz(tmp, X, X, X, X)), none, none));
                }
                break;
        case TGSI_OPCODE_SCS:
                /* avoid overwriting the source */
                if(src[0].swz[NVFX_SWZ_X] != NVFX_SWZ_X)
                {
-                       if (mask & NVFX_FP_MASK_X) {
-                               arith(fpc, sat, COS, dst, NVFX_FP_MASK_X,
-                                     swz(src[0], X, X, X, X), none, none);
-                       }
-                       if (mask & NVFX_FP_MASK_Y) {
-                               arith(fpc, sat, SIN, dst, NVFX_FP_MASK_Y,
-                                     swz(src[0], X, X, X, X), none, none);
-                       }
+                       if (mask & NVFX_FP_MASK_X)
+                               nvfx_fp_emit(fpc, arith(sat, COS, dst, NVFX_FP_MASK_X, swz(src[0], X, X, X, X), none, none));
+                       if (mask & NVFX_FP_MASK_Y)
+                               nvfx_fp_emit(fpc, arith(sat, SIN, dst, NVFX_FP_MASK_Y, swz(src[0], X, X, X, X), none, none));
                }
                else
                {
-                       if (mask & NVFX_FP_MASK_Y) {
-                               arith(fpc, sat, SIN, dst, NVFX_FP_MASK_Y,
-                                     swz(src[0], X, X, X, X), none, none);
-                       }
-                       if (mask & NVFX_FP_MASK_X) {
-                               arith(fpc, sat, COS, dst, NVFX_FP_MASK_X,
-                                     swz(src[0], X, X, X, X), none, none);
-                       }
+                       if (mask & NVFX_FP_MASK_Y)
+                               nvfx_fp_emit(fpc, arith(sat, SIN, dst, NVFX_FP_MASK_Y, swz(src[0], X, X, X, X), none, none));
+                       if (mask & NVFX_FP_MASK_X)
+                               nvfx_fp_emit(fpc, arith(sat, COS, dst, NVFX_FP_MASK_X, swz(src[0], X, X, X, X), none, none));
                }
                break;
        case TGSI_OPCODE_SEQ:
-               arith(fpc, sat, SEQ, dst, mask, src[0], src[1], none);
+               nvfx_fp_emit(fpc, arith(sat, SEQ, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_SFL:
-               arith(fpc, sat, SFL, dst, mask, src[0], src[1], none);
+               nvfx_fp_emit(fpc, arith(sat, SFL, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_SGE:
-               arith(fpc, sat, SGE, dst, mask, src[0], src[1], none);
+               nvfx_fp_emit(fpc, arith(sat, SGE, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_SGT:
-               arith(fpc, sat, SGT, dst, mask, src[0], src[1], none);
+               nvfx_fp_emit(fpc, arith(sat, SGT, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_SIN:
-               arith(fpc, sat, SIN, dst, mask, src[0], none, none);
+               nvfx_fp_emit(fpc, arith(sat, SIN, dst, mask, src[0], none, none));
                break;
        case TGSI_OPCODE_SLE:
-               arith(fpc, sat, SLE, dst, mask, src[0], src[1], none);
+               nvfx_fp_emit(fpc, arith(sat, SLE, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_SLT:
-               arith(fpc, sat, SLT, dst, mask, src[0], src[1], none);
+               nvfx_fp_emit(fpc, arith(sat, SLT, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_SNE:
-               arith(fpc, sat, SNE, dst, mask, src[0], src[1], none);
+               nvfx_fp_emit(fpc, arith(sat, SNE, dst, mask, src[0], src[1], none));
+               break;
+       case TGSI_OPCODE_SSG:
+               tmp = nvfx_src(temp(fpc));
+               tmp2 = nvfx_src(temp(fpc));
+               nvfx_fp_emit(fpc, arith(0, SGT, tmp.reg, mask, src[0], nvfx_src(nvfx_reg(NVFXSR_CONST, 0)), none));
+               nvfx_fp_emit(fpc, arith(0, SLT, tmp.reg, mask, src[0], nvfx_src(nvfx_reg(NVFXSR_CONST, 0)), none));
+               nvfx_fp_emit(fpc, arith(sat, ADD, dst, mask, tmp, neg(tmp2), none));
                break;
        case TGSI_OPCODE_STR:
-               arith(fpc, sat, STR, dst, mask, src[0], src[1], none);
+               nvfx_fp_emit(fpc, arith(sat, STR, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_SUB:
-               arith(fpc, sat, ADD, dst, mask, src[0], neg(src[1]), none);
+               nvfx_fp_emit(fpc, arith(sat, ADD, dst, mask, src[0], neg(src[1]), none));
                break;
        case TGSI_OPCODE_TEX:
-               tex(fpc, sat, TEX, unit, dst, mask, src[0], none, none);
+               nvfx_fp_emit(fpc, tex(sat, TEX, unit, dst, mask, src[0], none, none));
                break;
-       case TGSI_OPCODE_TXB:
-               tex(fpc, sat, TXB, unit, dst, mask, src[0], none, none);
+        case TGSI_OPCODE_TRUNC:
+                tmp = nvfx_src(temp(fpc));
+                insn = arith(0, MOV, none.reg, mask, src[0], none, none);
+                insn.cc_update = 1;
+                nvfx_fp_emit(fpc, insn);
+
+                nvfx_fp_emit(fpc, arith(0, FLR, tmp.reg, mask, abs(src[0]), none, none));
+                nvfx_fp_emit(fpc, arith(sat, MOV, dst, mask, tmp, none, none));
+
+                insn = arith(sat, MOV, dst, mask, neg(tmp), none, none);
+                insn.cc_test = NVFX_COND_LT;
+                nvfx_fp_emit(fpc, insn);
+                break;
+        case TGSI_OPCODE_TXB:
+                nvfx_fp_emit(fpc, tex(sat, TXB, unit, dst, mask, src[0], none, none));
+                break;
+        case TGSI_OPCODE_TXL:
+                if(nvfx->is_nv4x)
+                        nvfx_fp_emit(fpc, tex(sat, TXL_NV40, unit, dst, mask, src[0], none, none));
+                else /* unsupported on nv30, use TEX and hope they like it */
+                        nvfx_fp_emit(fpc, tex(sat, TEX, unit, dst, mask, src[0], none, none));
+                break;
+        case TGSI_OPCODE_TXP:
+                nvfx_fp_emit(fpc, tex(sat, TXP, unit, dst, mask, src[0], none, none));
+                break;
+       case TGSI_OPCODE_XPD:
+               tmp = nvfx_src(temp(fpc));
+               nvfx_fp_emit(fpc, arith(0, MUL, tmp.reg, mask, swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none));
+               nvfx_fp_emit(fpc, arith(sat, MAD, dst, (mask & ~NVFX_FP_MASK_W), swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), neg(tmp)));
                break;
-       case TGSI_OPCODE_TXP:
-               tex(fpc, sat, TXP, unit, dst, mask, src[0], none, none);
+
+       case TGSI_OPCODE_IF:
+               // MOVRC0 R31 (TR0.xyzw), R<src>:
+               // IF (NE.xxxx) ELSE <else> END <end>
+               if(!nvfx->is_nv4x)
+                       goto nv3x_cflow;
+               nv40_fp_if(fpc, src[0]);
                break;
-       case TGSI_OPCODE_XPD:
-               tmp = temp(fpc);
-               arith(fpc, 0, MUL, tmp, mask,
-                     swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none);
-               arith(fpc, sat, MAD, dst, (mask & ~NVFX_FP_MASK_W),
-                     swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y),
-                     neg(tmp));
+
+       case TGSI_OPCODE_ELSE:
+       {
+               uint32_t *hw;
+               if(!nvfx->is_nv4x)
+                       goto nv3x_cflow;
+               assert(util_dynarray_contains(&fpc->if_stack, unsigned));
+               hw = &fpc->fp->insn[util_dynarray_top(&fpc->if_stack, unsigned)];
+               hw[2] = NV40_FP_OP_OPCODE_IS_BRANCH | fpc->fp->insn_len;
                break;
-       default:
-               NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
-               return FALSE;
        }
 
-       release_temps(fpc);
-       return TRUE;
-}
+       case TGSI_OPCODE_ENDIF:
+       {
+               uint32_t *hw;
+               if(!nvfx->is_nv4x)
+                       goto nv3x_cflow;
+               assert(util_dynarray_contains(&fpc->if_stack, unsigned));
+               hw = &fpc->fp->insn[util_dynarray_pop(&fpc->if_stack, unsigned)];
+               if(!hw[2])
+                       hw[2] = NV40_FP_OP_OPCODE_IS_BRANCH | fpc->fp->insn_len;
+               hw[3] = fpc->fp->insn_len;
+               break;
+       }
 
-static boolean
-nvfx_fragprog_parse_decl_attrib(struct nvfx_context* nvfx, struct nvfx_fpc *fpc,
-                               const struct tgsi_full_declaration *fdec)
-{
-       int hw;
+       case TGSI_OPCODE_BRA:
+               /* This can in limited cases be implemented with an IF with the else and endif labels pointing to the target */
+               /* no state tracker uses this, so don't implement this for now */
+               assert(0);
+               nv40_fp_bra(fpc, finst->Label.Label);
+               break;
 
-       switch (fdec->Semantic.Name) {
-       case TGSI_SEMANTIC_POSITION:
-               hw = NVFX_FP_OP_INPUT_SRC_POSITION;
+       case TGSI_OPCODE_BGNSUB:
+       case TGSI_OPCODE_ENDSUB:
+               /* nothing to do here */
                break;
-       case TGSI_SEMANTIC_COLOR:
-               if (fdec->Semantic.Index == 0) {
-                       hw = NVFX_FP_OP_INPUT_SRC_COL0;
-               } else
-               if (fdec->Semantic.Index == 1) {
-                       hw = NVFX_FP_OP_INPUT_SRC_COL1;
-               } else {
-                       NOUVEAU_ERR("bad colour semantic index\n");
-                       return FALSE;
-               }
+
+       case TGSI_OPCODE_CAL:
+               if(!nvfx->is_nv4x)
+                       goto nv3x_cflow;
+               nv40_fp_cal(fpc, finst->Label.Label);
                break;
-       case TGSI_SEMANTIC_FOG:
-               hw = NVFX_FP_OP_INPUT_SRC_FOGC;
+
+       case TGSI_OPCODE_RET:
+               if(!nvfx->is_nv4x)
+                       goto nv3x_cflow;
+               nv40_fp_ret(fpc);
                break;
-       case TGSI_SEMANTIC_GENERIC:
-               if (fdec->Semantic.Index <= 7) {
-                       hw = NVFX_FP_OP_INPUT_SRC_TC(fdec->Semantic.
-                                                    Index);
-               } else {
-                       NOUVEAU_ERR("bad generic semantic index\n");
-                       return FALSE;
+
+       case TGSI_OPCODE_BGNLOOP:
+               if(!nvfx->is_nv4x)
+                       goto nv3x_cflow;
+               /* TODO: we should support using two nested REPs to allow a > 255 iteration count */
+               nv40_fp_rep(fpc, 255, finst->Label.Label);
+               break;
+
+       case TGSI_OPCODE_ENDLOOP:
+               break;
+
+       case TGSI_OPCODE_BRK:
+               if(!nvfx->is_nv4x)
+                       goto nv3x_cflow;
+               nv40_fp_brk(fpc);
+               break;
+
+       case TGSI_OPCODE_CONT:
+       {
+               static int warned = 0;
+               if(!warned) {
+                       NOUVEAU_ERR("Sorry, the continue keyword is not implemented: ignoring it.\n");
+                       warned = 1;
                }
                break;
-       default:
-               NOUVEAU_ERR("bad input semantic\n");
+       }
+
+        default:
+               NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
                return FALSE;
        }
 
-       fpc->attrib_map[fdec->Range.First] = hw;
+out:
+       release_temps(fpc);
        return TRUE;
+nv3x_cflow:
+       {
+               static int warned = 0;
+               if(!warned) {
+                       NOUVEAU_ERR(
+                                       "Sorry, control flow instructions are not supported in hardware on nv3x: ignoring them\n"
+                                       "If rendering is incorrect, try to disable GLSL support in the application.\n");
+                       warned = 1;
+               }
+       }
+       goto out;
 }
 
 static boolean
@@ -680,8 +913,8 @@ nvfx_fragprog_parse_decl_output(struct nvfx_context* nvfx, struct nvfx_fpc *fpc,
                return FALSE;
        }
 
-       fpc->r_result[idx] = nvfx_sr(NVFXSR_OUTPUT, hw);
-       fpc->r_temps |= (1 << hw);
+       fpc->r_result[idx] = nvfx_reg(NVFXSR_OUTPUT, hw);
+       fpc->r_temps |= (1ULL << hw);
        return TRUE;
 }
 
@@ -690,8 +923,22 @@ nvfx_fragprog_prepare(struct nvfx_context* nvfx, struct nvfx_fpc *fpc)
 {
        struct tgsi_parse_context p;
        int high_temp = -1, i;
+       struct util_semantic_set set;
+       float const0v[4] = {0, 0, 0, 0};
+       struct nvfx_reg const0;
+
+       fpc->fp->num_slots = util_semantic_set_from_program_file(&set, fpc->pfp->pipe.tokens, TGSI_FILE_INPUT);
+       if(fpc->fp->num_slots > 8)
+               return FALSE;
+       util_semantic_layout_from_set(fpc->fp->slot_to_generic, &set, 0, 8);
+       util_semantic_table_from_layout(fpc->generic_to_slot, fpc->fp->slot_to_generic, 0, 8);
 
-       tgsi_parse_init(&p, fpc->fp->pipe.tokens);
+       memset(fpc->fp->slot_to_fp_input, 0xff, sizeof(fpc->fp->slot_to_fp_input));
+
+       const0 = constant(fpc, -1, const0v);
+       assert(const0.index == 0);
+
+       tgsi_parse_init(&p, fpc->pfp->pipe.tokens);
        while (!tgsi_parse_end_of_tokens(&p)) {
                const union tgsi_full_token *tok = &p.FullToken;
 
@@ -702,10 +949,6 @@ nvfx_fragprog_prepare(struct nvfx_context* nvfx, struct nvfx_fpc *fpc)
                        const struct tgsi_full_declaration *fdec;
                        fdec = &p.FullToken.FullDeclaration;
                        switch (fdec->Declaration.File) {
-                       case TGSI_FILE_INPUT:
-                               if (!nvfx_fragprog_parse_decl_attrib(nvfx, fpc, fdec))
-                                       goto out_err;
-                               break;
                        case TGSI_FILE_OUTPUT:
                                if (!nvfx_fragprog_parse_decl_output(nvfx, fpc, fdec))
                                        goto out_err;
@@ -744,40 +987,66 @@ nvfx_fragprog_prepare(struct nvfx_context* nvfx, struct nvfx_fpc *fpc)
        tgsi_parse_free(&p);
 
        if (++high_temp) {
-               fpc->r_temp = CALLOC(high_temp, sizeof(struct nvfx_sreg));
+               fpc->r_temp = CALLOC(high_temp, sizeof(struct nvfx_reg));
                for (i = 0; i < high_temp; i++)
                        fpc->r_temp[i] = temp(fpc);
-               fpc->r_temps_discard = 0;
+               fpc->r_temps_discard = 0ULL;
        }
 
        return TRUE;
 
 out_err:
-       if (fpc->r_temp)
+       if (fpc->r_temp) {
                FREE(fpc->r_temp);
+               fpc->r_temp = NULL;
+       }
        tgsi_parse_free(&p);
        return FALSE;
 }
 
-static void
+DEBUG_GET_ONCE_BOOL_OPTION(nvfx_dump_fp, "NVFX_DUMP_FP", FALSE)
+
+static struct nvfx_fragment_program*
 nvfx_fragprog_translate(struct nvfx_context *nvfx,
-                       struct nvfx_fragment_program *fp)
+                       struct nvfx_pipe_fragment_program *pfp,
+                       boolean emulate_sprite_flipping)
 {
        struct tgsi_parse_context parse;
        struct nvfx_fpc *fpc = NULL;
+       struct util_dynarray insns;
+       struct nvfx_fragment_program* fp = NULL;
+        const int min_size = 4096;
 
-       fpc = CALLOC(1, sizeof(struct nvfx_fpc));
+       fp = CALLOC_STRUCT(nvfx_fragment_program);
+       if(!fp)
+               goto out_err;
+
+       fpc = CALLOC_STRUCT(nvfx_fpc);
        if (!fpc)
-               return;
+               goto out_err;
+
+       fpc->max_temps = nvfx->is_nv4x ? 48 : 32;
+       fpc->pfp = pfp;
        fpc->fp = fp;
        fpc->num_regs = 2;
 
-       if (!nvfx_fragprog_prepare(nvfx, fpc)) {
-               FREE(fpc);
-               return;
-       }
+       if (!nvfx_fragprog_prepare(nvfx, fpc))
+               goto out_err;
 
-       tgsi_parse_init(&parse, fp->pipe.tokens);
+       tgsi_parse_init(&parse, pfp->pipe.tokens);
+       util_dynarray_init(&insns);
+
+       if(emulate_sprite_flipping)
+       {
+               struct nvfx_reg reg = temp(fpc);
+               struct nvfx_src sprite_input = nvfx_src(nvfx_reg(NVFXSR_RELOCATED, fp->num_slots));
+               float v[4] = {1, -1, 0, 0};
+               struct nvfx_src imm = nvfx_src(constant(fpc, -1, v));
+
+               fpc->sprite_coord_temp = reg.index;
+               fpc->r_temps_discard = 0ULL;
+               nvfx_fp_emit(fpc, arith(0, MAD, reg, NVFX_FP_MASK_ALL, sprite_input, swz(imm, X, Y, X, X), swz(imm, Z, X, Z, Z)));
+       }
 
        while (!tgsi_parse_end_of_tokens(&parse)) {
                tgsi_parse_token(&parse);
@@ -787,6 +1056,7 @@ nvfx_fragprog_translate(struct nvfx_context *nvfx,
                {
                        const struct tgsi_full_instruction *finst;
 
+                       util_dynarray_append(&insns, unsigned, fp->insn_len);
                        finst = &parse.FullToken.FullInstruction;
                        if (!nvfx_fragprog_parse_instruction(nvfx, fpc, finst))
                                goto out_err;
@@ -796,6 +1066,14 @@ nvfx_fragprog_translate(struct nvfx_context *nvfx,
                        break;
                }
        }
+       util_dynarray_append(&insns, unsigned, fp->insn_len);
+
+       for(unsigned i = 0; i < fpc->label_relocs.size; i += sizeof(struct nvfx_relocation))
+       {
+               struct nvfx_relocation* label_reloc = (struct nvfx_relocation*)((char*)fpc->label_relocs.data + i);
+               fp->insn[label_reloc->location] |= ((unsigned*)insns.data)[label_reloc->target];
+       }
+       util_dynarray_fini(&insns);
 
        if(!nvfx->is_nv4x)
                fp->fp_control |= (fpc->num_regs-1)/2;
@@ -804,9 +1082,9 @@ nvfx_fragprog_translate(struct nvfx_context *nvfx,
 
        /* Terminate final instruction */
        if(fp->insn)
-                fp->insn[fpc->inst_offset] |= 0x00000001;
+               fp->insn[fpc->inst_offset] |= 0x00000001;
 
-       /* Append NOP + END instruction, may or may not be necessary. */
+       /* Append NOP + END instruction for branches to the end of the program */
        fpc->inst_offset = fp->insn_len;
        grow_insns(fpc, 4);
        fp->insn[fpc->inst_offset + 0] = 0x00000001;
@@ -814,12 +1092,48 @@ nvfx_fragprog_translate(struct nvfx_context *nvfx,
        fp->insn[fpc->inst_offset + 2] = 0x00000000;
        fp->insn[fpc->inst_offset + 3] = 0x00000000;
 
-       fp->translated = TRUE;
-out_err:
+       if(debug_get_option_nvfx_dump_fp())
+       {
+               debug_printf("\n");
+               tgsi_dump(pfp->pipe.tokens, 0);
+
+               debug_printf("\n%s fragment program:\n", nvfx->is_nv4x ? "nv4x" : "nv3x");
+               for (unsigned i = 0; i < fp->insn_len; i += 4)
+                       debug_printf("%3u: %08x %08x %08x %08x\n", i >> 2, fp->insn[i], fp->insn[i + 1], fp->insn[i + 2], fp->insn[i + 3]);
+               debug_printf("\n");
+       }
+
+        fp->prog_size = (fp->insn_len * 4 + 63) & ~63;
+
+        if(fp->prog_size >= min_size)
+                fp->progs_per_bo = 1;
+        else
+                fp->progs_per_bo = min_size / fp->prog_size;
+        fp->bo_prog_idx = fp->progs_per_bo - 1;
+
+out:
        tgsi_parse_free(&parse);
-       if (fpc->r_temp)
-               FREE(fpc->r_temp);
-       FREE(fpc);
+       if(fpc)
+       {
+               if (fpc->r_temp)
+                       FREE(fpc->r_temp);
+               util_dynarray_fini(&fpc->if_stack);
+               util_dynarray_fini(&fpc->label_relocs);
+               //util_dynarray_fini(&fpc->loop_stack);
+               FREE(fpc);
+       }
+       return fp;
+
+out_err:
+       _debug_printf("Error: failed to compile this fragment program:\n");
+       tgsi_dump(pfp->pipe.tokens, 0);
+
+       if(fp)
+       {
+               FREE(fp);
+               fp = NULL;
+       }
+       goto out;
 }
 
 static inline void
@@ -836,53 +1150,189 @@ nvfx_fp_memcpy(void* dst, const void* src, size_t len)
 #endif
 }
 
+/* The hardware only supports immediate constants inside the fragment program,
+ * and at least on nv30 doesn't support an indirect linkage table.
+ *
+ * Hence, we need to patch the fragment program itself both to update constants
+ * and update linkage.
+ *
+ * Using a single fragment program would entail unacceptable stalls if the GPU is
+ * already rendering with that fragment program.
+ * Thus, we instead use a "rotating queue" of buffer objects, each of which is
+ * packed with multiple versions of the same program.
+ *
+ * Whenever we need to patch something, we move to the next program and
+ * patch it. If all buffer objects are in use by the GPU, we allocate another one,
+ * expanding the queue.
+ *
+ * As an additional optimization, we record when all the programs have the
+ * current input slot configuration, and at that point we stop patching inputs.
+ * This happens, for instance, if a given fragment program is always used with
+ * the same vertex program (i.e. always with GLSL), or if the layouts match
+ * enough (non-GLSL).
+ *
+ * Note that instead of using multiple programs, we could push commands
+ * on the FIFO to patch a single program: it's not fully clear which option is
+ * faster, but my guess is that the current way is faster.
+ *
+ * We also track the previous slot assignments for each version and don't
+ * patch if they are the same (this could perhaps be removed).
+ */
+
 void
 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;
-
-       if (!fp->translated)
+       struct nvfx_pipe_fragment_program *pfp = nvfx->fragprog;
+       struct nvfx_vertex_program* vp;
+       /* Gallium always puts the point coord in GENERIC[0]
+        * TODO: this is wrong, Gallium needs to be fixed
+        */
+       unsigned sprite_coord_enable = nvfx->rasterizer->pipe.point_quad_rasterization * (nvfx->rasterizer->pipe.sprite_coord_enable | 1);
+
+       boolean emulate_sprite_flipping = sprite_coord_enable && nvfx->rasterizer->pipe.sprite_coord_mode;
+       unsigned key = emulate_sprite_flipping;
+       struct nvfx_fragment_program* fp;
+
+       fp = pfp->fps[key];
+       if (!fp)
        {
-               const int min_size = 4096;
+               fp = nvfx_fragprog_translate(nvfx, pfp, emulate_sprite_flipping);
 
-               nvfx_fragprog_translate(nvfx, fp);
-               if (!fp->translated) {
-                       static unsigned dummy[8] = {1, 0, 0, 0, 1, 0, 0, 0};
-                       static int warned = 0;
-                       if(!warned)
+               if(!fp)
+               {
+                       if(!nvfx->dummy_fs)
                        {
-                               fprintf(stderr, "nvfx: failed to translate fragment program!\n");
-                               warned = 1;
+                               struct ureg_program *ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
+                               if (ureg)
+                               {
+                                       ureg_END( ureg );
+                                       nvfx->dummy_fs = ureg_create_shader_and_destroy( ureg, &nvfx->pipe );
+                               }
+
+                               if(!nvfx->dummy_fs)
+                               {
+                                       _debug_printf("Error: unable to create a dummy fragment shader: aborting.");
+                                       abort();
+                               }
                        }
 
-                       /* use dummy program: we cannot fail here */
-                       fp->translated = TRUE;
-                       fp->insn = malloc(sizeof(dummy));
-                       memcpy(fp->insn, dummy, sizeof(dummy));
-                       fp->insn_len = sizeof(dummy) / sizeof(dummy[0]);
+                       fp = nvfx_fragprog_translate(nvfx, nvfx->dummy_fs, FALSE);
+                       emulate_sprite_flipping = FALSE;
+
+                       if(!fp)
+                       {
+                               _debug_printf("Error: unable to compile even a dummy fragment shader: aborting.");
+                               abort();
+                       }
                }
-               update = TRUE;
 
-               fp->prog_size = (fp->insn_len * 4 + 63) & ~63;
+               pfp->fps[key] = fp;
+       }
+
+       vp = nvfx->render_mode == HW ? nvfx->vertprog : nvfx->swtnl.vertprog;
 
-               if(fp->prog_size >= min_size)
-                       fp->progs_per_bo = 1;
+       if (fp->last_vp_id != vp->id || fp->last_sprite_coord_enable != sprite_coord_enable) {
+               int sprite_real_input = -1;
+               int sprite_reloc_input;
+               unsigned i;
+               fp->last_vp_id = vp->id;
+               fp->last_sprite_coord_enable = sprite_coord_enable;
+
+               if(sprite_coord_enable)
+               {
+                       sprite_real_input = vp->sprite_fp_input;
+                       if(sprite_real_input < 0)
+                       {
+                               unsigned used_texcoords = 0;
+                               for(unsigned i = 0; i < fp->num_slots; ++i) {
+                                       unsigned generic = fp->slot_to_generic[i];
+                                       if(!((1 << generic) & sprite_coord_enable))
+                                       {
+                                               unsigned char slot_mask = vp->generic_to_fp_input[generic];
+                                               if(slot_mask >= 0xf0)
+                                                       used_texcoords |= 1 << ((slot_mask & 0xf) - NVFX_FP_OP_INPUT_SRC_TC0);
+                                       }
+                               }
+
+                               sprite_real_input = NVFX_FP_OP_INPUT_SRC_TC(__builtin_ctz(~used_texcoords));
+                       }
+
+                       fp->point_sprite_control |= (1 << (sprite_real_input - NVFX_FP_OP_INPUT_SRC_TC0 + 8));
+               }
                else
-                       fp->progs_per_bo = min_size / fp->prog_size;
-               fp->bo_prog_idx = fp->progs_per_bo - 1;
-       }
+                       fp->point_sprite_control = 0;
 
-       /* we must update constants even on "just" fragprog changes, because
-          we don't check whether the current constant buffer matches the latest
-          one bound to this fragment program */
-       if (nvfx->dirty & (NVFX_NEW_FRAGCONST | NVFX_NEW_FRAGPROG))
-               update = TRUE;
+               if(emulate_sprite_flipping)
+                  sprite_reloc_input = 0;
+               else
+                  sprite_reloc_input = sprite_real_input;
 
-       if(update) {
+               for(i = 0; i < fp->num_slots; ++i) {
+                       unsigned generic = fp->slot_to_generic[i];
+                       if((1 << generic) & sprite_coord_enable)
+                       {
+                               if(fp->slot_to_fp_input[i] != sprite_reloc_input)
+                                       goto update_slots;
+                       }
+                       else
+                       {
+                               unsigned char slot_mask = vp->generic_to_fp_input[generic];
+                               if((slot_mask >> 4) & (slot_mask ^ fp->slot_to_fp_input[i]))
+                                       goto update_slots;
+                       }
+               }
+
+               if(emulate_sprite_flipping)
+               {
+                       if(fp->slot_to_fp_input[fp->num_slots] != sprite_real_input)
+                               goto update_slots;
+               }
+
+               if(0)
+               {
+update_slots:
+                       /* optimization: we start updating from the slot we found the first difference in */
+                       for(; i < fp->num_slots; ++i)
+                       {
+                               unsigned generic = fp->slot_to_generic[i];
+                               if((1 << generic) & sprite_coord_enable)
+                                       fp->slot_to_fp_input[i] = sprite_reloc_input;
+                               else
+                                       fp->slot_to_fp_input[i] = vp->generic_to_fp_input[generic] & 0xf;
+                       }
+
+                       fp->slot_to_fp_input[fp->num_slots] = sprite_real_input;
+
+                       if(nvfx->is_nv4x)
+                       {
+                               fp->or = 0;
+                               for(i = 0; i <= fp->num_slots; ++i) {
+                                       unsigned fp_input = fp->slot_to_fp_input[i];
+                                       if(fp_input == NVFX_FP_OP_INPUT_SRC_TC(8))
+                                               fp->or |= (1 << 12);
+                                       else if(fp_input == NVFX_FP_OP_INPUT_SRC_TC(9))
+                                               fp->or |= (1 << 13);
+                                       else if(fp_input >= NVFX_FP_OP_INPUT_SRC_TC(0) && fp_input <= NVFX_FP_OP_INPUT_SRC_TC(7))
+                                               fp->or |= (1 << (fp_input - NVFX_FP_OP_INPUT_SRC_TC0 + 14));
+                               }
+                       }
+
+                       fp->progs_left_with_obsolete_slot_assignments = fp->progs;
+                       goto update;
+               }
+       }
+
+       /* We must update constants even on "just" fragprog changes, because
+         * we don't check whether the current constant buffer matches the latest
+         * one bound to this fragment program.
+         * Doing such a check would likely be a pessimization.
+         */
+       if ((nvfx->hw_fragprog != fp) || (nvfx->dirty & (NVFX_NEW_FRAGPROG | NVFX_NEW_FRAGCONST))) {
                int offset;
+               uint32_t* fpmap;
 
+update:
                ++fp->bo_prog_idx;
                if(fp->bo_prog_idx >= fp->progs_per_bo)
                {
@@ -892,10 +1342,12 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx)
                        }
                        else
                        {
-                               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;
+                               struct nvfx_fragment_program_bo* fpbo = os_malloc_aligned(sizeof(struct nvfx_fragment_program) + (fp->prog_size + 8) * fp->progs_per_bo, 16);
+                               uint8_t* map;
+                               uint8_t* buf;
 
+                               fpbo->slots = (unsigned char*)&fpbo->insn[(fp->prog_size) * fp->progs_per_bo];
+                               memset(fpbo->slots, 0, 8 * fp->progs_per_bo);
                                if(fp->fpbo)
                                {
                                        fpbo->next = fp->fpbo->next;
@@ -905,12 +1357,14 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx)
                                        fpbo->next = fpbo;
                                fp->fpbo = fpbo;
                                fpbo->bo = 0;
+                               fp->progs += fp->progs_per_bo;
+                               fp->progs_left_with_obsolete_slot_assignments += fp->progs_per_bo;
                                nouveau_bo_new(nvfx->screen->base.device, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, 64, fp->prog_size * fp->progs_per_bo, &fpbo->bo);
                                nouveau_bo_map(fpbo->bo, NOUVEAU_BO_NOSYNC);
 
                                map = fpbo->bo->map;
-                               buf = fpbo->insn;
-                               for(i = 0; i < fp->progs_per_bo; ++i)
+                               buf = (uint8_t*)fpbo->insn;
+                               for(unsigned 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);
@@ -922,13 +1376,11 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx)
                }
 
                offset = fp->bo_prog_idx * fp->prog_size;
+               fpmap = (uint32_t*)((char*)fp->fpbo->bo->map + offset);
 
                if(nvfx->constbuf[PIPE_SHADER_FRAGMENT]) {
                        struct pipe_resource* constbuf = nvfx->constbuf[PIPE_SHADER_FRAGMENT];
-                       // TODO: avoid using transfers, just directly the buffer
-                       struct pipe_transfer* transfer;
-                       // TODO: does this check make any sense, or should we do this unconditionally?
-                       uint32_t* map = pipe_buffer_map(&nvfx->pipe, constbuf, PIPE_TRANSFER_READ, &transfer);
+                       uint32_t* map = (uint32_t*)nvfx_buffer(constbuf)->data;
                        uint32_t* fpmap = (uint32_t*)((char*)fp->fpbo->bo->map + offset);
                        uint32_t* buf = (uint32_t*)((char*)fp->fpbo->insn + offset);
                        int i;
@@ -942,12 +1394,61 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx)
                                        nvfx_fp_memcpy(&fpmap[off], &map[idx], 4 * sizeof(uint32_t));
                                }
                        }
-                       pipe_buffer_unmap(&nvfx->pipe, constbuf, transfer);
                }
-       }
 
-       if(update || (nvfx->dirty & NVFX_NEW_FRAGPROG)) {
-               int offset = fp->bo_prog_idx * fp->prog_size;
+               /* we only do this if we aren't sure that all program versions have the
+                * current slot assignments, otherwise we just update constants for speed
+                */
+               if(fp->progs_left_with_obsolete_slot_assignments) {
+                       unsigned char* fpbo_slots = &fp->fpbo->slots[fp->bo_prog_idx * 8];
+                       /* also relocate sprite coord slot, if any */
+                       for(unsigned i = 0; i <= fp->num_slots; ++i) {
+                               unsigned value = fp->slot_to_fp_input[i];;
+                               if(value != fpbo_slots[i]) {
+                                       unsigned* p;
+                                       unsigned* begin = (unsigned*)fp->slot_relocations[i].data;
+                                       unsigned* end = (unsigned*)((char*)fp->slot_relocations[i].data + fp->slot_relocations[i].size);
+                                       //printf("fp %p reloc slot %u/%u: %u -> %u\n", fp, i, fp->num_slots, fpbo_slots[i], value);
+                                       if(value == 0)
+                                       {
+                                               /* was relocated to an input, switch type to temporary */
+                                               for(p = begin; p != end; ++p) {
+                                                       unsigned off = *p;
+                                                       unsigned dw = fp->insn[off];
+                                                       dw &=~ NVFX_FP_REG_TYPE_MASK;
+                                                       //printf("reloc_tmp at %x\n", off);
+                                                       nvfx_fp_memcpy(&fpmap[off], &dw, sizeof(dw));
+                                               }
+                                       } else {
+                                               if(!fpbo_slots[i])
+                                               {
+                                                       /* was relocated to a temporary, switch type to input */
+                                                       for(p= begin; p != end; ++p) {
+                                                               unsigned off = *p;
+                                                               unsigned dw = fp->insn[off];
+                                                               //printf("reloc_in at %x\n", off);
+                                                               dw |= NVFX_FP_REG_TYPE_INPUT << NVFX_FP_REG_TYPE_SHIFT;
+                                                               nvfx_fp_memcpy(&fpmap[off], &dw, sizeof(dw));
+                                                       }
+                                               }
+
+                                               /* set the correct input index */
+                                               for(p = begin; p != end; ++p) {
+                                                       unsigned off = *p & ~3;
+                                                       unsigned dw = fp->insn[off];
+                                                       //printf("reloc&~3 at %x\n", off);
+                                                       dw = (dw & ~NVFX_FP_OP_INPUT_SRC_MASK) | (value << NVFX_FP_OP_INPUT_SRC_SHIFT);
+                                                       nvfx_fp_memcpy(&fpmap[off], &dw, sizeof(dw));
+                                               }
+                                       }
+                                       fpbo_slots[i] = value;
+                               }
+                       }
+                       --fp->progs_left_with_obsolete_slot_assignments;
+               }
+
+               nvfx->hw_fragprog = fp;
+
                MARK_RING(chan, 8, 1);
                OUT_RING(chan, RING_3D(NV34TCL_FP_ACTIVE_PROGRAM, 1));
                OUT_RELOC(chan, fp->fpbo->bo, offset, NOUVEAU_BO_VRAM |
@@ -963,13 +1464,26 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx)
                        OUT_RING(chan, fp->samplers);
                }
        }
+
+       {
+               unsigned pointsprite_control = fp->point_sprite_control | nvfx->rasterizer->pipe.point_quad_rasterization;
+               if(pointsprite_control != nvfx->hw_pointsprite_control)
+               {
+                       WAIT_RING(chan, 2);
+                       OUT_RING(chan, RING_3D(NV34TCL_POINT_SPRITE, 1));
+                       OUT_RING(chan, pointsprite_control);
+                       nvfx->hw_pointsprite_control = pointsprite_control;
+               }
+       }
+
+       nvfx->relocs_needed &=~ NVFX_RELOCATE_FRAGPROG;
 }
 
 void
 nvfx_fragprog_relocate(struct nvfx_context *nvfx)
 {
        struct nouveau_channel* chan = nvfx->screen->base.channel;
-       struct nvfx_fragment_program *fp = nvfx->fragprog;
+       struct nvfx_fragment_program *fp = nvfx->hw_fragprog;
        struct nouveau_bo* bo = fp->fpbo->bo;
        int offset = fp->bo_prog_idx * fp->prog_size;
        unsigned fp_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD; // TODO: GART?
@@ -979,12 +1493,14 @@ nvfx_fragprog_relocate(struct nvfx_context *nvfx)
        OUT_RELOC(chan, bo, offset, fp_flags | NOUVEAU_BO_LOW |
                      NOUVEAU_BO_OR, NV34TCL_FP_ACTIVE_PROGRAM_DMA0,
                      NV34TCL_FP_ACTIVE_PROGRAM_DMA1);
+       nvfx->relocs_needed &=~ NVFX_RELOCATE_FRAGPROG;
 }
 
 void
 nvfx_fragprog_destroy(struct nvfx_context *nvfx,
                      struct nvfx_fragment_program *fp)
 {
+       unsigned i;
        struct nvfx_fragment_program_bo* fpbo = fp->fpbo;
        if(fpbo)
        {
@@ -999,7 +1515,60 @@ nvfx_fragprog_destroy(struct nvfx_context *nvfx,
                while(fpbo != fp->fpbo);
        }
 
+       for(i = 0; i < Elements(fp->slot_relocations); ++i)
+               util_dynarray_fini(&fp->slot_relocations[i]);
+
        if (fp->insn_len)
                FREE(fp->insn);
 }
 
+static void *
+nvfx_fp_state_create(struct pipe_context *pipe,
+                     const struct pipe_shader_state *cso)
+{
+        struct nvfx_pipe_fragment_program *pfp;
+
+        pfp = CALLOC(1, sizeof(struct nvfx_pipe_fragment_program));
+        pfp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+
+        tgsi_scan_shader(pfp->pipe.tokens, &pfp->info);
+
+        return (void *)pfp;
+}
+
+static void
+nvfx_fp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+        struct nvfx_context *nvfx = nvfx_context(pipe);
+
+        nvfx->fragprog = hwcso;
+        nvfx->dirty |= NVFX_NEW_FRAGPROG;
+}
+
+static void
+nvfx_fp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       struct nvfx_pipe_fragment_program *pfp = hwcso;
+       unsigned i;
+
+       for(i = 0; i < Elements(pfp->fps); ++i)
+       {
+               if(pfp->fps[i])
+               {
+                       nvfx_fragprog_destroy(nvfx, pfp->fps[i]);
+                       FREE(pfp->fps[i]);
+               }
+       }
+
+        FREE((void*)pfp->pipe.tokens);
+        FREE(pfp);
+}
+
+void
+nvfx_init_fragprog_functions(struct nvfx_context *nvfx)
+{
+        nvfx->pipe.create_fs_state = nvfx_fp_state_create;
+        nvfx->pipe.bind_fs_state = nvfx_fp_state_bind;
+        nvfx->pipe.delete_fs_state = nvfx_fp_state_delete;
+}
index 0b4a434feccf01a0ad9c15f991f8941d5737706f..6503c7afcbf17aaf4f98b5a34ae7182c9b4112c9 100644 (file)
@@ -1,5 +1,177 @@
 #include "nvfx_context.h"
 #include "nvfx_resource.h"
+#include "nvfx_tex.h"
+
+static void *
+nvfx_sampler_state_create(struct pipe_context *pipe,
+                         const struct pipe_sampler_state *cso)
+{
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       struct nvfx_sampler_state *ps;
+
+       ps = MALLOC(sizeof(struct nvfx_sampler_state));
+
+       /* on nv30, we use this as an internal flag */
+       ps->fmt = cso->normalized_coords ? 0 : NV40TCL_TEX_FORMAT_RECT;
+       ps->en = 0;
+       ps->filt = nvfx_tex_filter(cso) | 0x2000; /*voodoo*/
+       ps->wrap = (nvfx_tex_wrap_mode(cso->wrap_s) << NV34TCL_TX_WRAP_S_SHIFT) |
+                   (nvfx_tex_wrap_mode(cso->wrap_t) << NV34TCL_TX_WRAP_T_SHIFT) |
+                   (nvfx_tex_wrap_mode(cso->wrap_r) << NV34TCL_TX_WRAP_R_SHIFT);
+       ps->compare = FALSE;
+
+       if(cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE)
+       {
+               ps->wrap |= nvfx_tex_wrap_compare_mode(cso->compare_func);
+               ps->compare = TRUE;
+       }
+       ps->bcol = nvfx_tex_border_color(cso->border_color);
+
+       if(nvfx->is_nv4x)
+               nv40_sampler_state_init(pipe, ps, cso);
+       else
+               nv30_sampler_state_init(pipe, ps, cso);
+
+       return (void *)ps;
+}
+
+static void
+nvfx_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       FREE(hwcso);
+}
+
+static void
+nvfx_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
+{
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       unsigned unit;
+
+       for (unit = 0; unit < nr; unit++) {
+               nvfx->tex_sampler[unit] = sampler[unit];
+               nvfx->dirty_samplers |= (1 << unit);
+       }
+
+       for (unit = nr; unit < nvfx->nr_samplers; unit++) {
+               nvfx->tex_sampler[unit] = NULL;
+               nvfx->dirty_samplers |= (1 << unit);
+       }
+
+       nvfx->nr_samplers = nr;
+       nvfx->dirty |= NVFX_NEW_SAMPLER;
+}
+
+static struct pipe_sampler_view *
+nvfx_create_sampler_view(struct pipe_context *pipe,
+                        struct pipe_resource *pt,
+                        const struct pipe_sampler_view *templ)
+{
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       struct nvfx_sampler_view *sv = CALLOC_STRUCT(nvfx_sampler_view);
+       struct nvfx_texture_format *tf = &nvfx_texture_formats[templ->format];
+       unsigned txf;
+
+       if (!sv)
+               return NULL;
+
+       sv->base = *templ;
+       sv->base.reference.count = 1;
+       sv->base.texture = NULL;
+       pipe_resource_reference(&sv->base.texture, pt);
+       sv->base.context = pipe;
+
+       txf = NV34TCL_TX_FORMAT_NO_BORDER;
+
+       switch (pt->target) {
+       case PIPE_TEXTURE_CUBE:
+               txf |= NV34TCL_TX_FORMAT_CUBIC;
+               /* fall-through */
+       case PIPE_TEXTURE_2D:
+       case PIPE_TEXTURE_RECT:
+               txf |= NV34TCL_TX_FORMAT_DIMS_2D;
+               break;
+       case PIPE_TEXTURE_3D:
+               txf |= NV34TCL_TX_FORMAT_DIMS_3D;
+               break;
+       case PIPE_TEXTURE_1D:
+               txf |= NV34TCL_TX_FORMAT_DIMS_1D;
+               break;
+       default:
+               assert(0);
+       }
+       sv->u.init_fmt = txf;
+
+       sv->swizzle = 0
+                       | (tf->src[sv->base.swizzle_r] << NV34TCL_TX_SWIZZLE_S0_Z_SHIFT)
+                       | (tf->src[sv->base.swizzle_g] << NV34TCL_TX_SWIZZLE_S0_Y_SHIFT)
+                       | (tf->src[sv->base.swizzle_b] << NV34TCL_TX_SWIZZLE_S0_X_SHIFT)
+                       | (tf->src[sv->base.swizzle_a] << NV34TCL_TX_SWIZZLE_S0_W_SHIFT)
+                       | (tf->comp[sv->base.swizzle_r] << NV34TCL_TX_SWIZZLE_S1_Z_SHIFT)
+                       | (tf->comp[sv->base.swizzle_g] << NV34TCL_TX_SWIZZLE_S1_Y_SHIFT)
+                       | (tf->comp[sv->base.swizzle_b] << NV34TCL_TX_SWIZZLE_S1_X_SHIFT)
+                       | (tf->comp[sv->base.swizzle_a] << NV34TCL_TX_SWIZZLE_S1_W_SHIFT);
+
+       sv->filt = tf->sign;
+       sv->wrap = tf->wrap;
+       sv->wrap_mask = ~0;
+
+       if (pt->target == PIPE_TEXTURE_CUBE)
+       {
+               sv->offset = 0;
+               sv->npot_size = (pt->width0 << NV34TCL_TX_NPOT_SIZE_W_SHIFT) | pt->height0;
+       }
+       else
+       {
+               sv->offset = nvfx_subresource_offset(pt, 0, sv->base.first_level, 0);
+               sv->npot_size = (u_minify(pt->width0, sv->base.first_level) << NV34TCL_TX_NPOT_SIZE_W_SHIFT) | u_minify(pt->height0, sv->base.first_level);
+
+               /* apparently, we need to ignore the t coordinate for 1D textures to fix piglit tex1d-2dborder */
+               if(pt->target == PIPE_TEXTURE_1D)
+               {
+                       sv->wrap_mask &=~ NV34TCL_TX_WRAP_T_MASK;
+                       sv->wrap |= NV34TCL_TX_WRAP_T_REPEAT;
+               }
+       }
+
+       if(nvfx->is_nv4x)
+               nv40_sampler_view_init(pipe, sv);
+       else
+               nv30_sampler_view_init(pipe, sv);
+
+       return &sv->base;
+}
+
+static void
+nvfx_sampler_view_destroy(struct pipe_context *pipe,
+                         struct pipe_sampler_view *view)
+{
+       pipe_resource_reference(&view->texture, NULL);
+       FREE(view);
+}
+
+static void
+nvfx_set_fragment_sampler_views(struct pipe_context *pipe,
+                               unsigned nr,
+                               struct pipe_sampler_view **views)
+{
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       unsigned unit;
+
+       for (unit = 0; unit < nr; unit++) {
+               pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit],
+                                            views[unit]);
+               nvfx->dirty_samplers |= (1 << unit);
+       }
+
+       for (unit = nr; unit < nvfx->nr_textures; unit++) {
+               pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit],
+                                            NULL);
+               nvfx->dirty_samplers |= (1 << unit);
+       }
+
+       nvfx->nr_textures = nr;
+       nvfx->dirty |= NVFX_NEW_SAMPLER;
+}
 
 void
 nvfx_fragtex_validate(struct nvfx_context *nvfx)
@@ -16,6 +188,10 @@ nvfx_fragtex_validate(struct nvfx_context *nvfx)
                samplers &= ~(1 << unit);
 
                if(nvfx->fragment_sampler_views[unit] && nvfx->tex_sampler[unit]) {
+                       util_dirty_surfaces_use_for_sampling(&nvfx->pipe,
+                                       &((struct nvfx_miptree*)nvfx->fragment_sampler_views[unit]->texture)->dirty_surfaces,
+                                       nvfx_surface_flush);
+
                        if(!nvfx->is_nv4x)
                                nv30_fragtex_set(nvfx, unit);
                        else
@@ -29,6 +205,7 @@ nvfx_fragtex_validate(struct nvfx_context *nvfx)
                }
        }
        nvfx->dirty_samplers = 0;
+       nvfx->relocs_needed &=~ NVFX_RELOCATE_FRAGTEX;
 }
 
 void
@@ -55,4 +232,128 @@ nvfx_fragtex_relocate(struct nvfx_context *nvfx)
                OUT_RELOC(chan, bo, nvfx->hw_txf[unit], tex_flags | NOUVEAU_BO_OR | NOUVEAU_BO_DUMMY,
                                NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
        }
+       nvfx->relocs_needed &=~ NVFX_RELOCATE_FRAGTEX;
+}
+
+void
+nvfx_init_sampling_functions(struct nvfx_context *nvfx)
+{
+       nvfx->pipe.create_sampler_state = nvfx_sampler_state_create;
+       nvfx->pipe.bind_fragment_sampler_states = nvfx_sampler_state_bind;
+       nvfx->pipe.delete_sampler_state = nvfx_sampler_state_delete;
+       nvfx->pipe.set_fragment_sampler_views = nvfx_set_fragment_sampler_views;
+       nvfx->pipe.create_sampler_view = nvfx_create_sampler_view;
+       nvfx->pipe.sampler_view_destroy = nvfx_sampler_view_destroy;
+}
+
+#define NV34TCL_TX_FORMAT_FORMAT_DXT1_RECT NV34TCL_TX_FORMAT_FORMAT_DXT1
+#define NV34TCL_TX_FORMAT_FORMAT_DXT3_RECT NV34TCL_TX_FORMAT_FORMAT_DXT3
+#define NV34TCL_TX_FORMAT_FORMAT_DXT5_RECT NV34TCL_TX_FORMAT_FORMAT_DXT5
+
+#define NV40TCL_TEX_FORMAT_FORMAT_HILO16 NV40TCL_TEX_FORMAT_FORMAT_A16L16
+
+#define NV34TCL_TX_FORMAT_FORMAT_RGBA16F 0x00004a00
+#define NV34TCL_TX_FORMAT_FORMAT_RGBA16F_RECT NV34TCL_TX_FORMAT_FORMAT_RGBA16F
+#define NV34TCL_TX_FORMAT_FORMAT_RGBA32F 0x00004b00
+#define NV34TCL_TX_FORMAT_FORMAT_RGBA32F_RECT NV34TCL_TX_FORMAT_FORMAT_RGBA32F
+#define NV34TCL_TX_FORMAT_FORMAT_R32F 0x00004c00
+#define NV34TCL_TX_FORMAT_FORMAT_R32F_RECT NV34TCL_TX_FORMAT_FORMAT_R32F
+
+// TODO: guess!
+#define NV40TCL_TEX_FORMAT_FORMAT_R32F 0x00001c00
+
+#define SRGB 0x00700000
+
+#define __(m,tf,tfc,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sign,wrap) \
+[PIPE_FORMAT_##m] = { \
+  {NV34TCL_TX_FORMAT_FORMAT_##tf, \
+  NV34TCL_TX_FORMAT_FORMAT_##tfc, \
+  NV34TCL_TX_FORMAT_FORMAT_##tf##_RECT, \
+  NV34TCL_TX_FORMAT_FORMAT_##tfc##_RECT, \
+  NV40TCL_TEX_FORMAT_FORMAT_##tf, \
+  NV40TCL_TEX_FORMAT_FORMAT_##tfc}, \
+  sign, wrap, \
+  {ts0z, ts0y, ts0x, ts0w, 0, 1}, {ts1z, ts1y, ts1x, ts1w, 0, 0} \
 }
+
+#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sign, wrap) \
+       __(m,tf,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sign, wrap)
+
+/* Depth formats works by reading the depth value most significant 8/16 bits.
+ * We are losing precision, but nVidia loses even more by using A8R8G8B8 instead of HILO16
+ * There is no 32-bit integer texture support, so other things are infeasible.
+ *
+ * TODO: is it possible to read 16 bits for Z16? A16 doesn't seem to work, either due to normalization or endianness issues
+ */
+
+#define T 2
+
+#define X 3
+#define Y 2
+#define Z 1
+#define W 0
+
+#define SNORM ((NV34TCL_TX_FILTER_SIGNED_RED) | (NV34TCL_TX_FILTER_SIGNED_GREEN) | (NV34TCL_TX_FILTER_SIGNED_BLUE) | (NV34TCL_TX_FILTER_SIGNED_ALPHA))
+#define UNORM 0
+
+struct nvfx_texture_format
+nvfx_texture_formats[PIPE_FORMAT_COUNT] = {
+       [0 ... PIPE_FORMAT_COUNT - 1] = {{-1, -1, -1, -1, -1, -1}},
+       _(B8G8R8X8_UNORM,       A8R8G8B8,       T, T, T, 1, X, Y, Z, W, UNORM, 0),
+       _(B8G8R8X8_SRGB,        A8R8G8B8,       T, T, T, 1, X, Y, Z, W, UNORM, SRGB),
+       _(B8G8R8A8_UNORM,       A8R8G8B8,       T, T, T, T, X, Y, Z, W, UNORM, 0),
+       _(B8G8R8A8_SRGB,        A8R8G8B8,       T, T, T, T, X, Y, Z, W, UNORM, SRGB),
+
+       _(R8G8B8A8_UNORM,       A8R8G8B8,       T, T, T, T, Z, Y, X, W, UNORM, 0),
+       _(R8G8B8A8_SRGB,        A8R8G8B8,       T, T, T, T, Z, Y, X, W, UNORM, SRGB),
+       _(R8G8B8X8_UNORM,       A8R8G8B8,       T, T, T, 1, Z, Y, X, W, UNORM, 0),
+
+       _(A8R8G8B8_UNORM,       A8R8G8B8,       T, T, T, T, W, Z, Y, X, UNORM, 0),
+       _(A8R8G8B8_SRGB,        A8R8G8B8,       T, T, T, T, W, Z, Y, X, UNORM, SRGB),
+       _(A8B8G8R8_UNORM,       A8R8G8B8,       T, T, T, T, W, X, Y, Z, UNORM, 0),
+       _(A8B8G8R8_SRGB,        A8R8G8B8,       T, T, T, T, W, X, Y, Z, UNORM, SRGB),
+       _(X8R8G8B8_UNORM,       A8R8G8B8,       T, T, T, 1, W, Z, Y, X, UNORM, 0),
+       _(X8R8G8B8_SRGB,        A8R8G8B8,       T, T, T, 1, W, Z, Y, X, UNORM, SRGB),
+
+       _(B5G5R5A1_UNORM,       A1R5G5B5,       T, T, T, T, X, Y, Z, W, UNORM, 0),
+       _(B5G5R5X1_UNORM,       A1R5G5B5,       T, T, T, 1, X, Y, Z, W, UNORM, 0),
+
+       _(B4G4R4A4_UNORM,       A4R4G4B4,       T, T, T, T, X, Y, Z, W, UNORM, 0),
+       _(B4G4R4X4_UNORM,       A4R4G4B4,       T, T, T, 1, X, Y, Z, W, UNORM, 0),
+
+       _(B5G6R5_UNORM,         R5G6B5,         T, T, T, 1, X, Y, Z, W, UNORM, 0),
+
+       _(R8_UNORM,             L8,             T, 0, 0, 1, X, X, X, X, UNORM, 0),
+       _(R8_SNORM,             L8,             T, 0, 0, 1, X, X, X, X, SNORM, 0),
+       _(L8_UNORM,             L8,             T, T, T, 1, X, X, X, X, UNORM, 0),
+       _(L8_SRGB,              L8,             T, T, T, 1, X, X, X, X, UNORM, SRGB),
+       _(A8_UNORM,             L8,             0, 0, 0, T, X, X, X, X, UNORM, 0),
+       _(I8_UNORM,             L8,             T, T, T, T, X, X, X, X, UNORM, 0),
+
+       _(R8G8_UNORM,           A8L8,           T, T, T, T, X, X, X, W, UNORM, 0),
+       _(R8G8_SNORM,           A8L8,           T, T, T, T, X, X, X, W, SNORM, 0),
+       _(L8A8_UNORM,           A8L8,           T, T, T, T, X, X, X, W, UNORM, 0),
+       _(L8A8_SRGB,            A8L8,           T, T, T, T, X, X, X, W, UNORM, SRGB),
+
+       _(DXT1_RGB,             DXT1,           T, T, T, 1, X, Y, Z, W, UNORM, 0),
+       _(DXT1_SRGB,            DXT1,           T, T, T, 1, X, Y, Z, W, UNORM, SRGB),
+       _(DXT1_RGBA,            DXT1,           T, T, T, T, X, Y, Z, W, UNORM, 0),
+       _(DXT1_SRGBA,           DXT1,           T, T, T, T, X, Y, Z, W, UNORM, SRGB),
+       _(DXT3_RGBA,            DXT3,           T, T, T, T, X, Y, Z, W, UNORM, 0),
+       _(DXT3_SRGBA,           DXT3,           T, T, T, T, X, Y, Z, W, UNORM, SRGB),
+       _(DXT5_RGBA,            DXT5,           T, T, T, T, X, Y, Z, W, UNORM, 0),
+       _(DXT5_SRGBA,           DXT5,           T, T, T, T, X, Y, Z, W, UNORM, SRGB),
+
+       __(Z16_UNORM,           A8L8, Z16,      T, T, T, 1, W, W, W, W, UNORM, 0),
+       __(S8_USCALED_Z24_UNORM,HILO16,Z24,     T, T, T, 1, W, W, W, W, UNORM, 0),
+       __(X8Z24_UNORM,         HILO16,Z24,     T, T, T, 1, W, W, W, W, UNORM, 0),
+
+       _(R16_UNORM,            A16,            T, 0, 0, 1, X, X, X, X, UNORM, 0),
+       _(R16_SNORM,            A16,            T, 0, 0, 1, X, X, X, X, SNORM, 0),
+       _(R16G16_UNORM,         HILO16,         T, T, 0, 1, X, Y, X, X, UNORM, 0),
+       _(R16G16_SNORM,         HILO16,         T, T, 0, 1, X, Y, X, X, SNORM, 0),
+
+       _(R16G16B16A16_FLOAT,           RGBA16F,        T, T, T, T, X, Y, Z, W, UNORM, 0),
+       _(R32G32B32A32_FLOAT,           RGBA32F,        T, T, T, T, X, Y, Z, W, UNORM, 0),
+       _(R32_FLOAT,            R32F,   T, 0, 0, 1, X, X, X, X, UNORM, 0)
+};
index b5639bb46455ead6fc3f3829a9f3a0d171bed171..0916aaa8289ba830bc098d7bdb0c1a49f3ba18c9 100644 (file)
 #include "pipe/p_defines.h"
 #include "util/u_inlines.h"
 #include "util/u_format.h"
+#include "util/u_memory.h"
 #include "util/u_math.h"
-
-#include "nvfx_context.h"
+#include "util/u_staging.h"
+#include "state_tracker/drm_driver.h"
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_screen.h"
+#include "nvfx_screen.h"
 #include "nvfx_resource.h"
-#include "nvfx_transfer.h"
-#include "nv04_surface_2d.h"
-
-/* Currently using separate implementations for buffers and textures,
- * even though gallium has a unified abstraction of these objects.
- * Eventually these should be combined, and mechanisms like transfers
- * be adapted to work for both buffer and texture uploads.
- */
 
 static void
-nvfx_miptree_layout(struct nvfx_miptree *mt)
+nvfx_miptree_choose_format(struct nvfx_miptree *mt)
 {
        struct pipe_resource *pt = &mt->base.base;
-       uint width = pt->width0;
-       uint offset = 0;
-       int nr_faces, l, f;
-       uint wide_pitch = pt->bind & (PIPE_BIND_SAMPLER_VIEW |
-                                     PIPE_BIND_DEPTH_STENCIL |
-                                     PIPE_BIND_RENDER_TARGET |
-                                     PIPE_BIND_DISPLAY_TARGET |
-                                     PIPE_BIND_SCANOUT);
-
-       if (pt->target == PIPE_TEXTURE_CUBE) {
-               nr_faces = 6;
-       } else
-       if (pt->target == PIPE_TEXTURE_3D) {
-               nr_faces = pt->depth0;
-       } else {
-               nr_faces = 1;
+       unsigned uniform_pitch = 0;
+       static int no_swizzle = -1;
+       if(no_swizzle < 0)
+               no_swizzle = debug_get_bool_option("NV40_NO_SWIZZLE", FALSE); /* this will break things on nv30 */
+
+       if (!util_is_power_of_two(pt->width0) ||
+           !util_is_power_of_two(pt->height0) ||
+           !util_is_power_of_two(pt->depth0) ||
+           (!nvfx_screen(pt->screen)->is_nv4x && pt->target == PIPE_TEXTURE_RECT)
+           )
+               uniform_pitch = 1;
+
+       if (
+               (pt->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_DISPLAY_TARGET))
+               || (pt->usage & PIPE_USAGE_DYNAMIC) || (pt->usage & PIPE_USAGE_STAGING)
+               || util_format_is_compressed(pt->format)
+               || no_swizzle
+       )
+               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
+
+       /* non compressed formats with uniform pitch must be linear, and vice versa */
+       if(!util_format_is_s3tc(pt->format)
+               && (uniform_pitch || mt->base.base.flags & NVFX_RESOURCE_FLAG_LINEAR))
+       {
+               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
+               uniform_pitch = 1;
        }
 
-       for (l = 0; l <= pt->last_level; l++) {
-               if (wide_pitch && (pt->flags & NVFX_RESOURCE_FLAG_LINEAR))
-                       mt->level[l].pitch = align(util_format_get_stride(pt->format, pt->width0), 64);
-               else
-                       mt->level[l].pitch = util_format_get_stride(pt->format, width);
+       if(uniform_pitch)
+       {
+               mt->linear_pitch = util_format_get_stride(pt->format, pt->width0);
 
-               mt->level[l].image_offset =
-                       CALLOC(nr_faces, sizeof(unsigned));
+               // TODO: this is only a constraint for rendering and not sampling, apparently
+               // we may also want this unconditionally
+               if(pt->bind & (PIPE_BIND_SAMPLER_VIEW |
+                       PIPE_BIND_DEPTH_STENCIL |
+                       PIPE_BIND_RENDER_TARGET |
+                       PIPE_BIND_DISPLAY_TARGET |
+                       PIPE_BIND_SCANOUT))
+                       mt->linear_pitch = align(mt->linear_pitch, 64);
+       }
+       else
+               mt->linear_pitch = 0;
+}
+
+static unsigned
+nvfx_miptree_layout(struct nvfx_miptree *mt)
+{
+       struct pipe_resource* pt = &mt->base.base;
+        uint offset = 0;
 
-               width  = u_minify(width, 1);
+       if(!nvfx_screen(pt->screen)->is_nv4x)
+       {
+               assert(pt->target == PIPE_TEXTURE_RECT
+                       || (util_is_power_of_two(pt->width0) && util_is_power_of_two(pt->height0)));
        }
 
-       for (f = 0; f < nr_faces; f++) {
-               for (l = 0; l < pt->last_level; l++) {
-                       mt->level[l].image_offset[f] = offset;
+       for (unsigned l = 0; l <= pt->last_level; l++)
+       {
+               unsigned size;
+               mt->level_offset[l] = offset;
 
-                       if (!(pt->flags & NVFX_RESOURCE_FLAG_LINEAR) &&
-                           u_minify(pt->width0, l + 1) > 1 && u_minify(pt->height0, l + 1) > 1)
-                               offset += align(mt->level[l].pitch * u_minify(pt->height0, l), 64);
-                       else
-                               offset += mt->level[l].pitch * u_minify(pt->height0, l);
-               }
+               if(mt->linear_pitch)
+                       size = mt->linear_pitch;
+               else
+                       size = util_format_get_stride(pt->format, u_minify(pt->width0, l));
+               size = util_format_get_2d_size(pt->format, size, u_minify(pt->height0, l));
 
-               mt->level[l].image_offset[f] = offset;
-               offset += mt->level[l].pitch * u_minify(pt->height0, l);
+               if(pt->target == PIPE_TEXTURE_3D)
+                       size *= u_minify(pt->depth0, l);
+
+               offset += size;
        }
 
-       mt->total_size = offset;
+       offset = align(offset, 128);
+       mt->face_size = offset;
+       if(mt->base.base.target == PIPE_TEXTURE_CUBE)
+               offset += 5 * mt->face_size;
+       return offset;
 }
 
-static boolean
-nvfx_miptree_get_handle(struct pipe_screen *pscreen,
-                       struct pipe_resource *ptexture,
-                       struct winsys_handle *whandle)
+static void
+nvfx_miptree_surface_final_destroy(struct pipe_surface* ps)
 {
-       struct nvfx_miptree* mt = (struct nvfx_miptree*)ptexture;
-
-       if (!mt || !mt->base.bo)
-               return FALSE;
-
-       return nouveau_screen_bo_get_handle(pscreen,
-                                           mt->base.bo,
-                                           mt->level[0].pitch,
-                                           whandle);
+       struct nvfx_surface* ns = (struct nvfx_surface*)ps;
+       pipe_resource_reference(&ps->texture, 0);
+       pipe_resource_reference((struct pipe_resource**)&ns->temp, 0);
+       FREE(ps);
 }
 
-
-static void
+void
 nvfx_miptree_destroy(struct pipe_screen *screen, struct pipe_resource *pt)
 {
        struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
-       int l;
-
+       util_surfaces_destroy(&mt->surfaces, pt, nvfx_miptree_surface_final_destroy);
        nouveau_screen_bo_release(screen, mt->base.bo);
-
-       for (l = 0; l <= pt->last_level; l++) {
-               if (mt->level[l].image_offset)
-                       FREE(mt->level[l].image_offset);
-       }
-
        FREE(mt);
 }
 
-
-
-
-struct u_resource_vtbl nvfx_miptree_vtbl = 
+static struct nvfx_miptree*
+nvfx_miptree_create_skeleton(struct pipe_screen *pscreen, const struct pipe_resource *pt)
 {
-   nvfx_miptree_get_handle,          /* get_handle */
-   nvfx_miptree_destroy,             /* resource_destroy */
-   NULL,                             /* is_resource_referenced */
-   nvfx_miptree_transfer_new,        /* get_transfer */
-   nvfx_miptree_transfer_del,     /* transfer_destroy */
-   nvfx_miptree_transfer_map,        /* transfer_map */
-   u_default_transfer_flush_region,   /* transfer_flush_region */
-   nvfx_miptree_transfer_unmap,              /* transfer_unmap */
-   u_default_transfer_inline_write    /* transfer_inline_write */
-};
+        struct nvfx_miptree *mt;
 
+        if(pt->width0 > 4096 || pt->height0 > 4096)
+                return NULL;
 
+        mt = CALLOC_STRUCT(nvfx_miptree);
+        if (!mt)
+                return NULL;
 
-struct pipe_resource *
-nvfx_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *pt)
-{
-       struct nvfx_miptree *mt;
-       static int no_swizzle = -1;
-       if(no_swizzle < 0)
-               no_swizzle = debug_get_bool_option("NOUVEAU_NO_SWIZZLE", FALSE);
-
-       mt = CALLOC_STRUCT(nvfx_miptree);
-       if (!mt)
-               return NULL;
-
-       mt->base.base = *pt;
-       mt->base.vtbl = &nvfx_miptree_vtbl;
-       pipe_reference_init(&mt->base.base.reference, 1);
-       mt->base.base.screen = pscreen;
+        mt->base.base = *pt;
+        util_dirty_surfaces_init(&mt->dirty_surfaces);
 
-       /* Swizzled textures must be POT */
-       if (pt->width0 & (pt->width0 - 1) ||
-           pt->height0 & (pt->height0 - 1))
-               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
-       else
-       if (pt->bind & (PIPE_BIND_SCANOUT |
-                       PIPE_BIND_DISPLAY_TARGET |
-                       PIPE_BIND_DEPTH_STENCIL))
-               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
-       else
-       if (pt->usage == PIPE_USAGE_DYNAMIC)
-               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
-       else {
-               switch (pt->format) {
-               case PIPE_FORMAT_B5G6R5_UNORM:
-               case PIPE_FORMAT_L8A8_UNORM:
-               case PIPE_FORMAT_A8_UNORM:
-               case PIPE_FORMAT_L8_UNORM:
-               case PIPE_FORMAT_I8_UNORM:
-                       /* TODO: we can actually swizzle these formats on nv40, we
-                               are just preserving the pre-unification behavior.
-                               The whole 2D code is going to be rewritten anyway. */
-                       if(nvfx_screen(pscreen)->is_nv4x) {
-                               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
-                               break;
-                       }
-               /* TODO: Figure out which formats can be swizzled */
-               case PIPE_FORMAT_B8G8R8A8_UNORM:
-               case PIPE_FORMAT_B8G8R8X8_UNORM:
-               case PIPE_FORMAT_R16_SNORM:
-               {
-                       if (no_swizzle)
-                               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
-                       break;
-               }
-               default:
-                       mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
-               }
-       }
+        pipe_reference_init(&mt->base.base.reference, 1);
+        mt->base.base.screen = pscreen;
 
-       /* apparently we can't render to swizzled surfaces smaller than 64 bytes, so make them linear.
-        * If the user did not ask for a render target, they can still render to it, but it will cost them an extra copy.
-        * This also happens for small mipmaps of large textures. */
-       if (pt->bind & PIPE_BIND_RENDER_TARGET &&
-           util_format_get_stride(pt->format, pt->width0) < 64)
-               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
+        // set this to the actual capabilities, we use it to decide whether to use the 3D engine for copies
+        // TODO: is this the correct way to use Gallium?
+        mt->base.base.bind = pt->bind | PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_DEPTH_STENCIL;
 
-       nvfx_miptree_layout(mt);
+        // on our current driver (and the driver too), format support does not depend on geometry, so don't bother computing it
+        // TODO: may want to revisit this
+        if(!pscreen->is_format_supported(pscreen, pt->format, pt->target, 0, PIPE_BIND_RENDER_TARGET, 0))
+                mt->base.base.bind &=~ PIPE_BIND_RENDER_TARGET;
+        if(!pscreen->is_format_supported(pscreen, pt->format, pt->target, 0, PIPE_BIND_SAMPLER_VIEW, 0))
+                mt->base.base.bind &=~ PIPE_BIND_SAMPLER_VIEW;
+        if(!pscreen->is_format_supported(pscreen, pt->format, pt->target, 0, PIPE_BIND_DEPTH_STENCIL, 0))
+                mt->base.base.bind &=~ PIPE_BIND_DEPTH_STENCIL;
 
-       mt->base.bo = nouveau_screen_bo_new(pscreen, 256,
-            pt->usage, pt->bind, mt->total_size);
-       if (!mt->base.bo) {
-               FREE(mt);
-               return NULL;
-       }
-       return &mt->base.base;
+        return mt;
 }
 
 
-
-
 struct pipe_resource *
-nvfx_miptree_from_handle(struct pipe_screen *pscreen,
-                        const struct pipe_resource *template,
-                        struct winsys_handle *whandle)
+nvfx_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *pt)
 {
-       struct nvfx_miptree *mt;
-       unsigned stride;
+       struct nvfx_miptree* mt = nvfx_miptree_create_skeleton(pscreen, pt);
+        unsigned size;
+       nvfx_miptree_choose_format(mt);
 
-       /* Only supports 2D, non-mipmapped textures for the moment */
-       if (template->target != PIPE_TEXTURE_2D ||
-           template->last_level != 0 ||
-           template->depth0 != 1)
-               return NULL;
+        size = nvfx_miptree_layout(mt);
 
-       mt = CALLOC_STRUCT(nvfx_miptree);
-       if (!mt)
-               return NULL;
+       mt->base.bo = nouveau_screen_bo_new(pscreen, 256, pt->usage, pt->bind, size);
 
-       mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride);
-       if (mt->base.bo == NULL) {
+       if (!mt->base.bo) {
                FREE(mt);
                return NULL;
        }
-
-       mt->base.base = *template;
-       mt->base.vtbl = &nvfx_miptree_vtbl;
-       pipe_reference_init(&mt->base.base.reference, 1);
-       mt->base.base.screen = pscreen;
-       mt->level[0].pitch = stride;
-       mt->level[0].image_offset = CALLOC(1, sizeof(unsigned));
-
-       /* Assume whoever created this buffer expects it to be linear for now */
-       mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
-
-       /* XXX: Need to adjust bo refcount??
-        */
-       /* nouveau_bo_ref(bo, &mt->base.bo); */
        return &mt->base.base;
 }
 
+// TODO: redo this, just calling miptree_layout
+struct pipe_resource *
+nvfx_miptree_from_handle(struct pipe_screen *pscreen, const struct pipe_resource *template, struct winsys_handle *whandle)
+{
+        struct nvfx_miptree* mt = nvfx_miptree_create_skeleton(pscreen, template);
+        unsigned stride;
+        if(whandle->stride) {
+               mt->linear_pitch = whandle->stride;
+               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
+        } else
+               nvfx_miptree_choose_format(mt);
 
+        nvfx_miptree_layout(mt);
 
+        mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride);
+        if (mt->base.bo == NULL) {
+                FREE(mt);
+                return NULL;
+        }
+        return &mt->base.base;
+}
 
-
-/* Surface helpers, not strictly required to implement the resource vtbl:
- */
 struct pipe_surface *
 nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt,
                         unsigned face, unsigned level, unsigned zslice,
                         unsigned flags)
 {
-       struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
-       struct nv04_surface *ns;
-
-       ns = CALLOC_STRUCT(nv04_surface);
-       if (!ns)
-               return NULL;
-       pipe_resource_reference(&ns->base.texture, pt);
-       ns->base.format = pt->format;
-       ns->base.width = u_minify(pt->width0, level);
-       ns->base.height = u_minify(pt->height0, level);
-       ns->base.usage = flags;
-       pipe_reference_init(&ns->base.reference, 1);
-       ns->base.face = face;
-       ns->base.level = level;
-       ns->base.zslice = zslice;
-       ns->pitch = mt->level[level].pitch;
-
-       if (pt->target == PIPE_TEXTURE_CUBE) {
-               ns->base.offset = mt->level[level].image_offset[face];
-       } else
-       if (pt->target == PIPE_TEXTURE_3D) {
-               ns->base.offset = mt->level[level].image_offset[zslice];
-       } else {
-               ns->base.offset = mt->level[level].image_offset[0];
-       }
-
-       /* create a linear temporary that we can render into if
-        * necessary.
-        *
-        * Note that ns->pitch is always a multiple of 64 for linear
-        * surfaces and swizzled surfaces are POT, so ns->pitch & 63
-        * is equivalent to (ns->pitch < 64 && swizzled)
-        */
-
-       if ((ns->pitch & 63) && 
-           (ns->base.usage & PIPE_BIND_RENDER_TARGET))
-       {
-               struct nv04_surface_2d* eng2d  =
-                       ((struct nvfx_screen*)pscreen)->eng2d;
-
-               ns = nv04_surface_wrap_for_render(pscreen, eng2d, ns);
+       struct nvfx_miptree* mt = (struct nvfx_miptree*)pt;
+       struct nvfx_surface *ns;
+
+       ns = (struct nvfx_surface*)util_surfaces_get(&mt->surfaces, sizeof(struct nvfx_surface), pscreen, pt, face, level, zslice, flags);
+       if(ns->base.base.offset == ~0) {
+               util_dirty_surface_init(&ns->base);
+               ns->pitch = nvfx_subresource_pitch(pt, level);
+               ns->base.base.offset = nvfx_subresource_offset(pt, face, level, zslice);
        }
 
-       return &ns->base;
+       return &ns->base.base;
 }
 
 void
 nvfx_miptree_surface_del(struct pipe_surface *ps)
 {
-       struct nv04_surface* ns = (struct nv04_surface*)ps;
-       if(ns->backing)
+       struct nvfx_surface* ns = (struct nvfx_surface*)ps;
+
+       if(!ns->temp)
        {
-               struct nvfx_screen* screen = (struct nvfx_screen*)ps->texture->screen;
-               if(1 /*ns->backing->base.usage & PIPE_BIND_BLIT_DESTINATION*/)
-                       screen->eng2d->copy(screen->eng2d, &ns->backing->base, 0, 0, ps, 0, 0, ns->base.width, ns->base.height);
-               nvfx_miptree_surface_del(&ns->backing->base);
+               util_surfaces_detach(&((struct nvfx_miptree*)ps->texture)->surfaces, ps);
+               pipe_resource_reference(&ps->texture, 0);
+               FREE(ps);
        }
-
-       pipe_resource_reference(&ps->texture, NULL);
-       FREE(ps);
 }
diff --git a/src/gallium/drivers/nvfx/nvfx_push.c b/src/gallium/drivers/nvfx/nvfx_push.c
new file mode 100644 (file)
index 0000000..ffe7e98
--- /dev/null
@@ -0,0 +1,414 @@
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "util/u_inlines.h"
+#include "util/u_format.h"
+#include "util/u_split_prim.h"
+#include "translate/translate.h"
+
+#include "nvfx_context.h"
+#include "nvfx_resource.h"
+
+struct push_context {
+       struct nouveau_channel* chan;
+
+       void *idxbuf;
+       int32_t idxbias;
+
+       float edgeflag;
+       int edgeflag_attr;
+
+       unsigned vertex_length;
+       unsigned max_vertices_per_packet;
+
+       struct translate* translate;
+};
+
+static void
+emit_edgeflag(void *priv, boolean enabled)
+{
+       struct push_context* ctx = priv;
+       struct nouveau_channel *chan = ctx->chan;
+
+       OUT_RING(chan, RING_3D(NV34TCL_EDGEFLAG_ENABLE, 1));
+       OUT_RING(chan, enabled ? 1 : 0);
+}
+
+static void
+emit_vertices_lookup8(void *priv, unsigned start, unsigned count)
+{
+        struct push_context *ctx = priv;
+        uint8_t* elts = (uint8_t*)ctx->idxbuf + start;
+
+        while(count)
+        {
+                unsigned push = MIN2(count, ctx->max_vertices_per_packet);
+                unsigned length = push * ctx->vertex_length;
+
+                OUT_RING(ctx->chan, RING_3D_NI(NV34TCL_VERTEX_DATA, length));
+                ctx->translate->run_elts8(ctx->translate, elts, push, 0, ctx->chan->cur);
+                ctx->chan->cur += length;
+
+                count -= push;
+                elts += push;
+        }
+}
+
+static void
+emit_vertices_lookup16(void *priv, unsigned start, unsigned count)
+{
+       struct push_context *ctx = priv;
+        uint16_t* elts = (uint16_t*)ctx->idxbuf + start;
+
+        while(count)
+        {
+                unsigned push = MIN2(count, ctx->max_vertices_per_packet);
+                unsigned length = push * ctx->vertex_length;
+
+                OUT_RING(ctx->chan, RING_3D_NI(NV34TCL_VERTEX_DATA, length));
+                ctx->translate->run_elts16(ctx->translate, elts, push, 0, ctx->chan->cur);
+                ctx->chan->cur += length;
+
+                count -= push;
+                elts += push;
+        }
+}
+
+static void
+emit_vertices_lookup32(void *priv, unsigned start, unsigned count)
+{
+        struct push_context *ctx = priv;
+        uint32_t* elts = (uint32_t*)ctx->idxbuf + start;
+
+        while(count)
+        {
+                unsigned push = MIN2(count, ctx->max_vertices_per_packet);
+                unsigned length = push * ctx->vertex_length;
+
+                OUT_RING(ctx->chan, RING_3D_NI(NV34TCL_VERTEX_DATA, length));
+                ctx->translate->run_elts(ctx->translate, elts, push, 0, ctx->chan->cur);
+                ctx->chan->cur += length;
+
+                count -= push;
+                elts += push;
+        }
+}
+
+static void
+emit_vertices(void *priv, unsigned start, unsigned count)
+{
+        struct push_context *ctx = priv;
+
+        while(count)
+        {
+               unsigned push = MIN2(count, ctx->max_vertices_per_packet);
+               unsigned length = push * ctx->vertex_length;
+
+               OUT_RING(ctx->chan, RING_3D_NI(NV34TCL_VERTEX_DATA, length));
+               ctx->translate->run(ctx->translate, start, push, 0, ctx->chan->cur);
+               ctx->chan->cur += length;
+
+               count -= push;
+               start += push;
+        }
+}
+
+static void
+emit_ranges(void* priv, unsigned start, unsigned vc, unsigned reg)
+{
+       struct push_context* ctx = priv;
+       struct nouveau_channel *chan = ctx->chan;
+       unsigned nr = (vc & 0xff);
+       if (nr) {
+               OUT_RING(chan, RING_3D(reg, 1));
+               OUT_RING  (chan, ((nr - 1) << 24) | start);
+               start += nr;
+       }
+
+       nr = vc >> 8;
+       while (nr) {
+               unsigned push = nr > 2047 ? 2047 : nr;
+
+               nr -= push;
+
+               OUT_RING(chan, RING_3D_NI(reg, push));
+               while (push--) {
+                       OUT_RING(chan, ((0x100 - 1) << 24) | start);
+                       start += 0x100;
+               }
+       }
+}
+
+static void
+emit_ib_ranges(void* priv, unsigned start, unsigned vc)
+{
+       emit_ranges(priv, start, vc, NV34TCL_VB_INDEX_BATCH);
+}
+
+static void
+emit_vb_ranges(void* priv, unsigned start, unsigned vc)
+{
+       emit_ranges(priv, start, vc, NV34TCL_VB_VERTEX_BATCH);
+}
+
+static INLINE void
+emit_elt8(void* priv, unsigned start, unsigned vc)
+{
+       struct push_context* ctx = priv;
+       struct nouveau_channel *chan = ctx->chan;
+       uint8_t *elts = (uint8_t *)ctx->idxbuf + start;
+       int idxbias = ctx->idxbias;
+
+       if (vc & 1) {
+               OUT_RING(chan, RING_3D(NV34TCL_VB_ELEMENT_U32, 1));
+               OUT_RING  (chan, elts[0]);
+               elts++; vc--;
+       }
+
+       while (vc) {
+               unsigned i;
+               unsigned push = MIN2(vc, 2047 * 2);
+
+               OUT_RING(chan, RING_3D_NI(NV34TCL_VB_ELEMENT_U16, push >> 1));
+               for (i = 0; i < push; i+=2)
+                       OUT_RING(chan, ((elts[i+1] + idxbias) << 16) | (elts[i] + idxbias));
+
+               vc -= push;
+               elts += push;
+       }
+}
+
+static INLINE void
+emit_elt16(void* priv, unsigned start, unsigned vc)
+{
+       struct push_context* ctx = priv;
+       struct nouveau_channel *chan = ctx->chan;
+       uint16_t *elts = (uint16_t *)ctx->idxbuf + start;
+       int idxbias = ctx->idxbias;
+
+       if (vc & 1) {
+               OUT_RING(chan, RING_3D(NV34TCL_VB_ELEMENT_U32, 1));
+               OUT_RING  (chan, elts[0]);
+               elts++; vc--;
+       }
+
+       while (vc) {
+               unsigned i;
+               unsigned push = MIN2(vc, 2047 * 2);
+
+               OUT_RING(chan, RING_3D_NI(NV34TCL_VB_ELEMENT_U16, push >> 1));
+               for (i = 0; i < push; i+=2)
+                       OUT_RING(chan, ((elts[i+1] + idxbias) << 16) | (elts[i] + idxbias));
+
+               vc -= push;
+               elts += push;
+       }
+}
+
+static INLINE void
+emit_elt32(void* priv, unsigned start, unsigned vc)
+{
+       struct push_context* ctx = priv;
+       struct nouveau_channel *chan = ctx->chan;
+       uint32_t *elts = (uint32_t *)ctx->idxbuf + start;
+       int idxbias = ctx->idxbias;
+
+       while (vc) {
+               unsigned push = MIN2(vc, 2047);
+
+               OUT_RING(chan, RING_3D_NI(NV34TCL_VB_ELEMENT_U32, push));
+               assert(AVAIL_RING(chan) >= push);
+               if(idxbias)
+               {
+                       for(unsigned i = 0; i < push; ++i)
+                               OUT_RING(chan, elts[i] + idxbias);
+               }
+               else
+                       OUT_RINGp(chan, elts, push);
+
+               vc -= push;
+               elts += push;
+       }
+}
+
+void
+nvfx_push_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
+{
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       struct nouveau_channel *chan = nvfx->screen->base.channel;
+       struct push_context ctx;
+       struct util_split_prim s;
+       unsigned instances_left = info->instance_count;
+       int vtx_value;
+       unsigned hw_mode = nvgl_primitive(info->mode);
+       int i;
+       struct
+       {
+               uint8_t* map;
+               unsigned step;
+       } per_instance[16];
+       unsigned p_overhead = 64 /* magic fix */
+                       + 4 /* begin/end */
+                       + 4; /* potential edgeflag enable/disable */
+
+       ctx.chan = nvfx->screen->base.channel;
+       ctx.translate = nvfx->vtxelt->translate;
+       ctx.idxbuf = NULL;
+       ctx.vertex_length = nvfx->vtxelt->vertex_length;
+       ctx.max_vertices_per_packet = nvfx->vtxelt->max_vertices_per_packet;
+       ctx.edgeflag = 0.5f;
+       // TODO: figure out if we really want to handle this, and do so in that case
+       ctx.edgeflag_attr = 0xff; // nvfx->vertprog->cfg.edgeflag_in;
+
+       if(!nvfx->use_vertex_buffers)
+       {
+               for(i = 0; i < nvfx->vtxelt->num_per_vertex_buffer_infos; ++i)
+               {
+                       struct nvfx_per_vertex_buffer_info* vbi = &nvfx->vtxelt->per_vertex_buffer_info[i];
+                       struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[vbi->vertex_buffer_index];
+                       uint8_t* data = nvfx_buffer(vb->buffer)->data + vb->buffer_offset;
+                       if(info->indexed)
+                               data += info->index_bias * vb->stride;
+                       ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);
+               }
+
+               if(ctx.edgeflag_attr < 16)
+                       vtx_value = -(ctx.vertex_length + 3);  /* vertex data and edgeflag header and value */
+               else
+               {
+                       p_overhead += 1; /* initial vertex_data header */
+                       vtx_value = -ctx.vertex_length;  /* vertex data and edgeflag header and value */
+               }
+
+               if (info->indexed) {
+                       // XXX: this case and is broken and probably need a new VTX_ATTR push path
+                       if (nvfx->idxbuf.index_size == 1)
+                               s.emit = emit_vertices_lookup8;
+                       else if (nvfx->idxbuf.index_size == 2)
+                               s.emit = emit_vertices_lookup16;
+                       else
+                               s.emit = emit_vertices_lookup32;
+               } else
+                       s.emit = emit_vertices;
+       }
+       else
+       {
+               if(!info->indexed || nvfx->use_index_buffer)
+               {
+                       s.emit = info->indexed ? emit_ib_ranges : emit_vb_ranges;
+                       p_overhead += 3;
+                       vtx_value = 0;
+               }
+               else if (nvfx->idxbuf.index_size == 4)
+               {
+                       s.emit = emit_elt32;
+                       p_overhead += 1;
+                       vtx_value = 8;
+               }
+               else
+               {
+                       s.emit = (nvfx->idxbuf.index_size == 2) ? emit_elt16 : emit_elt8;
+                       p_overhead += 3;
+                       vtx_value = 7;
+               }
+       }
+
+       ctx.idxbias = info->index_bias;
+       if(nvfx->use_vertex_buffers)
+               ctx.idxbias -= nvfx->base_vertex;
+
+       /* map index buffer, if present */
+       if (info->indexed && !nvfx->use_index_buffer)
+               ctx.idxbuf = nvfx_buffer(nvfx->idxbuf.buffer)->data + nvfx->idxbuf.offset;
+
+       s.priv = &ctx;
+       s.edge = emit_edgeflag;
+
+       for (i = 0; i < nvfx->vtxelt->num_per_instance; ++i)
+       {
+               struct nvfx_per_instance_element *ve = &nvfx->vtxelt->per_instance[i];
+               struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->base.vertex_buffer_index];
+               float v[4];
+               per_instance[i].step = info->start_instance % ve->instance_divisor;
+               per_instance[i].map = nvfx_buffer(vb->buffer)->data + vb->buffer_offset + ve->base.src_offset;
+
+               nvfx->vtxelt->per_instance[i].base.fetch_rgba_float(v, per_instance[i].map, 0, 0);
+
+               WAIT_RING(chan, 5);
+               nvfx_emit_vtx_attr(chan, nvfx->vtxelt->per_instance[i].base.idx, v, nvfx->vtxelt->per_instance[i].base.ncomp);
+       }
+
+       /* per-instance loop */
+       while (instances_left--) {
+               int max_verts;
+               boolean done;
+
+               util_split_prim_init(&s, info->mode, info->start, info->count);
+               nvfx_state_emit(nvfx);
+               for(;;) {
+                       max_verts  = AVAIL_RING(chan);
+                       max_verts -= p_overhead;
+
+                       /* if vtx_value < 0, each vertex is -vtx_value words long
+                        * otherwise, each vertex is 2^(vtx_value) / 255 words long (this is an approximation)
+                        */
+                       if(vtx_value < 0)
+                       {
+                               max_verts /= -vtx_value;
+                               max_verts -= (max_verts >> 10); /* vertex data headers */
+                       }
+                       else
+                       {
+                               if(max_verts >= (1 << 23)) /* avoid overflow here */
+                                       max_verts = (1 << 23);
+                               max_verts = (max_verts * 255) >> vtx_value;
+                       }
+
+                       //printf("avail %u max_verts %u\n", AVAIL_RING(chan), max_verts);
+
+                       if(max_verts >= 16)
+                       {
+                               /* XXX: any command a lot of times seems to (mostly) fix corruption that would otherwise happen */
+                               /* this seems to cause issues on nv3x, and also be unneeded there */
+                               if(nvfx->is_nv4x)
+                               {
+                                       int i;
+                                       for(i = 0; i < 32; ++i)
+                                       {
+                                               OUT_RING(chan, RING_3D(0x1dac, 1));
+                                               OUT_RING(chan, 0);
+                                       }
+                               }
+
+                               OUT_RING(chan, RING_3D(NV34TCL_VERTEX_BEGIN_END, 1));
+                               OUT_RING(chan, hw_mode);
+                               done = util_split_prim_next(&s, max_verts);
+                               OUT_RING(chan, RING_3D(NV34TCL_VERTEX_BEGIN_END, 1));
+                               OUT_RING(chan, 0);
+
+                               if(done)
+                                       break;
+                       }
+
+                       FIRE_RING(chan);
+                       nvfx_state_emit(nvfx);
+               }
+
+               /* set data for the next instance, if any changed */
+               for (i = 0; i < nvfx->vtxelt->num_per_instance; ++i)
+               {
+                       struct nvfx_per_instance_element *ve = &nvfx->vtxelt->per_instance[i];
+                       struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->base.vertex_buffer_index];
+
+                       if(++per_instance[i].step == ve->instance_divisor)
+                       {
+                               float v[4];
+                               per_instance[i].map += vb->stride;
+                               per_instance[i].step = 0;
+
+                               nvfx->vtxelt->per_instance[i].base.fetch_rgba_float(v, per_instance[i].map, 0, 0);
+                               WAIT_RING(chan, 5);
+                               nvfx_emit_vtx_attr(chan, nvfx->vtxelt->per_instance[i].base.idx, v, nvfx->vtxelt->per_instance[i].base.ncomp);
+                       }
+               }
+       }
+}
index 10cdeed2a372e21b9cff773eaf884dbec95801ab..39ae893f1b3b8c589453f2080e810c1ef4c96051 100644 (file)
@@ -1,23 +1,15 @@
 
 #include "pipe/p_context.h"
+#include "util/u_staging.h"
 #include "nvfx_resource.h"
 #include "nouveau/nouveau_screen.h"
 
-
-/* This doesn't look quite right - this query is supposed to ask
- * whether the particular context has references to the resource in
- * any unflushed rendering command buffer, and hence requires a
- * pipe->flush() for serializing some modification to that resource.
- *
- * This seems to be answering the question of whether the resource is
- * currently on hardware.
- */
 static unsigned int
 nvfx_resource_is_referenced(struct pipe_context *pipe,
-                           struct pipe_resource *resource,
+                           struct pipe_resource *pr,
                            unsigned face, unsigned level)
 {
-       return nouveau_reference_flags(nvfx_resource(resource)->bo);
+       return !!nouveau_reference_flags(nvfx_resource(pr)->bo);
 }
 
 static struct pipe_resource *
@@ -30,6 +22,15 @@ nvfx_resource_create(struct pipe_screen *screen,
                return nvfx_miptree_create(screen, template);
 }
 
+static void
+nvfx_resource_destroy(struct pipe_screen *screen, struct pipe_resource *pr)
+{
+       if (pr->target == PIPE_BUFFER)
+               return nvfx_buffer_destroy(screen, pr);
+       else
+               return nvfx_miptree_destroy(screen, pr);
+}
+
 static struct pipe_resource *
 nvfx_resource_from_handle(struct pipe_screen * screen,
                          const struct pipe_resource *template,
@@ -41,15 +42,22 @@ nvfx_resource_from_handle(struct pipe_screen * screen,
                return nvfx_miptree_from_handle(screen, template, whandle);
 }
 
+static boolean
+nvfx_resource_get_handle(struct pipe_screen *pscreen,
+                        struct pipe_resource *pr,
+                        struct winsys_handle *whandle)
+{
+       struct nvfx_resource* res = (struct nvfx_resource*)pr;
+
+       if (!res || !res->bo)
+               return FALSE;
+
+       return nouveau_screen_bo_get_handle(pscreen, res->bo, nvfx_subresource_pitch(pr, 0), whandle);
+}
+
 void
 nvfx_init_resource_functions(struct pipe_context *pipe)
 {
-       pipe->get_transfer = u_get_transfer_vtbl;
-       pipe->transfer_map = u_transfer_map_vtbl;
-       pipe->transfer_flush_region = u_transfer_flush_region_vtbl;
-       pipe->transfer_unmap = u_transfer_unmap_vtbl;
-       pipe->transfer_destroy = u_transfer_destroy_vtbl;
-       pipe->transfer_inline_write = u_transfer_inline_write_vtbl;
        pipe->is_resource_referenced = nvfx_resource_is_referenced;
 }
 
@@ -58,10 +66,10 @@ nvfx_screen_init_resource_functions(struct pipe_screen *pscreen)
 {
        pscreen->resource_create = nvfx_resource_create;
        pscreen->resource_from_handle = nvfx_resource_from_handle;
-       pscreen->resource_get_handle = u_resource_get_handle_vtbl;
-       pscreen->resource_destroy = u_resource_destroy_vtbl;
+       pscreen->resource_get_handle = nvfx_resource_get_handle;
+       pscreen->resource_destroy = nvfx_resource_destroy;
        pscreen->user_buffer_create = nvfx_user_buffer_create;
-   
+
        pscreen->get_tex_surface = nvfx_miptree_surface_new;
        pscreen->tex_surface_destroy = nvfx_miptree_surface_del;
 }
index a68c14cf3fbe9ae045a595d6420faf062a247a19..583be4de2ae2596bca94c091fd1163fd701254b3 100644 (file)
@@ -1,44 +1,82 @@
-
 #ifndef NVFX_RESOURCE_H
 #define NVFX_RESOURCE_H
 
 #include "util/u_transfer.h"
+#include "util/u_format.h"
+#include "util/u_math.h"
+#include "util/u_double_list.h"
+#include "util/u_surfaces.h"
+#include "util/u_dirty_surfaces.h"
+#include <nouveau/nouveau_bo.h>
 
 struct pipe_resource;
-struct nouveau_bo;
-
+struct nv04_region;
 
-/* This gets further specialized into either buffer or texture
- * structures.  In the future we'll want to remove much of that
- * distinction, but for now try to keep as close to the existing code
- * as possible and use the vtbl struct to choose between the two
- * underlying implementations.
- */
 struct nvfx_resource {
        struct pipe_resource base;
-       struct u_resource_vtbl *vtbl;
        struct nouveau_bo *bo;
 };
 
+static INLINE
+struct nvfx_resource *nvfx_resource(struct pipe_resource *resource)
+{
+       return (struct nvfx_resource *)resource;
+}
+
+#define NVFX_RESOURCE_FLAG_LINEAR (PIPE_RESOURCE_FLAG_DRV_PRIV << 0)
+#define NVFX_RESOURCE_FLAG_USER (PIPE_RESOURCE_FLAG_DRV_PRIV << 1)
+
+/* is resource mapped into the GPU's address space (i.e. VRAM or GART) ? */
+static INLINE boolean
+nvfx_resource_mapped_by_gpu(struct pipe_resource *resource)
+{
+   return nvfx_resource(resource)->bo->handle;
+}
+
+/* is resource in VRAM? */
+static inline int
+nvfx_resource_on_gpu(struct pipe_resource* pr)
+{
+#if 0
+       // a compiler error here means you need to apply libdrm-nouveau-add-domain.patch to libdrm
+       // TODO: return FALSE if not VRAM and on a PCI-E system
+       return ((struct nvfx_resource*)pr)->bo->domain & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART);
+#else
+       return TRUE;
+#endif
+}
+
 #define NVFX_MAX_TEXTURE_LEVELS  16
 
+/* We have the following invariants for render temporaries
+ *
+ * 1. Render temporaries are always linear
+ * 2. Render temporaries are always up to date
+ * 3. Currently, render temporaries are destroyed when the resource is used for sampling, but kept for any other use
+ *
+ * Also, we do NOT flush temporaries on any pipe->flush().
+ * This is fine, as long as scanout targets and shared resources never need temps.
+ *
+ * TODO: we may want to also support swizzled temporaries to improve performance in some cases.
+ */
+
 struct nvfx_miptree {
-       struct nvfx_resource base;
-       uint total_size;
+        struct nvfx_resource base;
 
-       struct {
-               uint pitch;
-               uint *image_offset;
-       } level[NVFX_MAX_TEXTURE_LEVELS];
+        unsigned linear_pitch; /* for linear textures, 0 for swizzled and compressed textures with level-dependent minimal pitch */
+        unsigned face_size; /* 128-byte aligned face/total size */
+        unsigned level_offset[NVFX_MAX_TEXTURE_LEVELS];
 
-       unsigned image_nr;
+        struct util_surfaces surfaces;
+        struct util_dirty_surfaces dirty_surfaces;
 };
 
-static INLINE 
-struct nvfx_resource *nvfx_resource(struct pipe_resource *resource)
-{
-       return (struct nvfx_resource *)resource;
-}
+struct nvfx_surface {
+       struct util_dirty_surface base;
+       unsigned pitch;
+
+       struct nvfx_miptree* temp;
+};
 
 static INLINE struct nouveau_bo *
 nvfx_surface_buffer(struct pipe_surface *surf)
@@ -48,6 +86,12 @@ nvfx_surface_buffer(struct pipe_surface *surf)
        return mt->bo;
 }
 
+static INLINE struct util_dirty_surfaces*
+nvfx_surface_get_dirty_surfaces(struct pipe_surface* surf)
+{
+       struct nvfx_miptree *mt = (struct nvfx_miptree *)surf->texture;
+       return &mt->dirty_surfaces;
+}
 
 void
 nvfx_init_resource_functions(struct pipe_context *pipe);
@@ -62,30 +106,118 @@ nvfx_screen_init_resource_functions(struct pipe_screen *pscreen);
 struct pipe_resource *
 nvfx_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *pt);
 
+void
+nvfx_miptree_destroy(struct pipe_screen *pscreen,
+                     struct pipe_resource *presource);
+
 struct pipe_resource *
 nvfx_miptree_from_handle(struct pipe_screen *pscreen,
                         const struct pipe_resource *template,
                         struct winsys_handle *whandle);
 
+void
+nvfx_miptree_surface_del(struct pipe_surface *ps);
+
+struct pipe_surface *
+nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt,
+                        unsigned face, unsigned level, unsigned zslice,
+                        unsigned flags);
+
+/* only for miptrees, don't use for buffers */
+
+/* NOTE: for swizzled 3D textures, this just returns the offset of the mipmap level */
+static inline unsigned
+nvfx_subresource_offset(struct pipe_resource* pt, unsigned face, unsigned level, unsigned zslice)
+{
+       if(pt->target == PIPE_BUFFER)
+               return 0;
+       else
+       {
+               struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
+
+               unsigned offset = mt->level_offset[level];
+               if (pt->target == PIPE_TEXTURE_CUBE)
+                       offset += mt->face_size * face;
+               else if (pt->target == PIPE_TEXTURE_3D && mt->linear_pitch)
+                       offset += zslice * util_format_get_2d_size(pt->format, (mt->linear_pitch ? mt->linear_pitch : util_format_get_stride(pt->format, u_minify(pt->width0, level))),  u_minify(pt->height0, level));
+               return offset;
+       }
+}
+
+static inline unsigned
+nvfx_subresource_pitch(struct pipe_resource* pt, unsigned level)
+{
+       if(pt->target == PIPE_BUFFER)
+               return ((struct nvfx_resource*)pt)->bo->size;
+       else
+       {
+               struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
+
+               if(mt->linear_pitch)
+                       return mt->linear_pitch;
+               else
+                       return util_format_get_stride(pt->format, u_minify(pt->width0, level));
+       }
+}
+
+void
+nvfx_surface_create_temp(struct pipe_context* pipe, struct pipe_surface* surf);
+
+void
+nvfx_surface_flush(struct pipe_context* pipe, struct pipe_surface* surf);
+
+struct nvfx_buffer
+{
+       struct nvfx_resource base;
+       uint8_t* data;
+       unsigned size;
+
+       /* the range of data not yet uploaded to the GPU bo */
+       unsigned dirty_begin;
+       unsigned dirty_end;
+
+       /* whether all transfers were unsynchronized */
+       boolean dirty_unsynchronized;
+
+       /* whether it would have been profitable to upload
+        * the latest updated data to the GPU immediately */
+       boolean last_update_static;
+
+       /* how many bytes we need to draw before we deem
+        * the buffer to be static
+        */
+       long long bytes_to_draw_until_static;
+};
+
+static inline struct nvfx_buffer* nvfx_buffer(struct pipe_resource* pr)
+{
+       return (struct nvfx_buffer*)pr;
+}
+
+/* this is an heuristic to determine whether we are better off uploading the
+ * buffer to the GPU, or just continuing pushing it on the FIFO
+ */
+static inline boolean nvfx_buffer_seems_static(struct nvfx_buffer* buffer)
+{
+       return buffer->last_update_static
+               || buffer->bytes_to_draw_until_static < 0;
+}
+
 struct pipe_resource *
 nvfx_buffer_create(struct pipe_screen *pscreen,
                   const struct pipe_resource *template);
 
+void
+nvfx_buffer_destroy(struct pipe_screen *pscreen,
+                    struct pipe_resource *presource);
+
 struct pipe_resource *
 nvfx_user_buffer_create(struct pipe_screen *screen,
                        void *ptr,
                        unsigned bytes,
                        unsigned usage);
 
-
-
 void
-nvfx_miptree_surface_del(struct pipe_surface *ps);
-
-struct pipe_surface *
-nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt,
-                        unsigned face, unsigned level, unsigned zslice,
-                        unsigned flags);
-
+nvfx_buffer_upload(struct nvfx_buffer* buffer);
 
 #endif
index f2525ccb38fbce2abed6f7f91241360f7ed970c1..65ca265d45cdee71997b54b7c8d8177e9b92a171 100644 (file)
@@ -8,23 +8,12 @@
 #include "nvfx_context.h"
 #include "nvfx_screen.h"
 #include "nvfx_resource.h"
+#include "nvfx_tex.h"
 
 #define NV30TCL_CHIPSET_3X_MASK 0x00000003
 #define NV34TCL_CHIPSET_3X_MASK 0x00000010
 #define NV35TCL_CHIPSET_3X_MASK 0x000001e0
 
-/* FIXME: It seems I should not include directly ../../winsys/drm/nouveau/drm/nouveau_drm_api.h
-* to get the pointer to the context front buffer, so I copied nouveau_winsys here.
-* nv30_screen_surface_format_supported() can then use it to enforce creating fbo
-* with same number of bits everywhere.
-*/
-struct nouveau_winsys {
-       struct pipe_winsys base;
-
-       struct pipe_screen *pscreen;
-
-       struct pipe_surface *front;
-};
 #define NV4X_GRCLASS4097_CHIPSETS 0x00000baf
 #define NV4X_GRCLASS4497_CHIPSETS 0x00005450
 #define NV6X_GRCLASS4497_CHIPSETS 0x00000088
@@ -43,7 +32,7 @@ nvfx_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
        case PIPE_CAP_TWO_SIDED_STENCIL:
                return 1;
        case PIPE_CAP_GLSL:
-               return 0;
+               return 1;
        case PIPE_CAP_ANISOTROPIC_FILTER:
                return 1;
        case PIPE_CAP_POINT_SPRITE:
@@ -162,77 +151,74 @@ nvfx_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_cap param)
 }
 
 static boolean
-nvfx_screen_surface_format_supported(struct pipe_screen *pscreen,
+nvfx_screen_is_format_supported(struct pipe_screen *pscreen,
                                     enum pipe_format format,
                                     enum pipe_texture_target target,
                                     unsigned sample_count,
-                                    unsigned tex_usage, unsigned geom_flags)
+                                    unsigned bind, unsigned geom_flags)
 {
        struct nvfx_screen *screen = nvfx_screen(pscreen);
-       struct pipe_surface *front = ((struct nouveau_winsys *) pscreen->winsys)->front;
 
         if (sample_count > 1)
                return FALSE;
 
-       if (tex_usage & PIPE_BIND_RENDER_TARGET) {
+       if (bind & PIPE_BIND_RENDER_TARGET) {
                switch (format) {
                case PIPE_FORMAT_B8G8R8A8_UNORM:
                case PIPE_FORMAT_B8G8R8X8_UNORM:
                case PIPE_FORMAT_B5G6R5_UNORM:
-                       return TRUE;
-               default:
                        break;
+               default:
+                       return FALSE;
                }
-       } else
-       if (tex_usage & PIPE_BIND_DEPTH_STENCIL) {
+       }
+
+       if (bind & PIPE_BIND_DEPTH_STENCIL) {
                switch (format) {
                case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
                case PIPE_FORMAT_X8Z24_UNORM:
-                       return TRUE;
                case PIPE_FORMAT_Z16_UNORM:
-                       /* TODO: this nv30 limitation probably does not exist */
-                       if (!screen->is_nv4x && front)
-                               return (front->format == PIPE_FORMAT_B5G6R5_UNORM);
-                       return TRUE;
-               default:
                        break;
+               default:
+                       return FALSE;
                }
-       } else {
-               switch (format) {
-               if (tex_usage & PIPE_BIND_SAMPLER_VIEW) {
-                       switch (format) {
-                       case PIPE_FORMAT_DXT1_RGB:
-                       case PIPE_FORMAT_DXT1_RGBA:
-                       case PIPE_FORMAT_DXT3_RGBA:
-                       case PIPE_FORMAT_DXT5_RGBA:
-                               return util_format_s3tc_enabled;
-                       default:
-                               break;
-                       }
+       }
+
+       if (bind & PIPE_BIND_SAMPLER_VIEW) {
+               struct nvfx_texture_format* tf = &nvfx_texture_formats[format];
+               if(util_format_is_s3tc(format) && !util_format_s3tc_enabled)
+                       return FALSE;
+
+               if(screen->is_nv4x)
+               {
+                       if(tf->fmt[4] < 0)
+                               return FALSE;
                }
-               case PIPE_FORMAT_B8G8R8A8_UNORM:
-               case PIPE_FORMAT_B8G8R8X8_UNORM:
-               case PIPE_FORMAT_B5G5R5A1_UNORM:
-               case PIPE_FORMAT_B4G4R4A4_UNORM:
-               case PIPE_FORMAT_B5G6R5_UNORM:
-               case PIPE_FORMAT_L8_UNORM:
-               case PIPE_FORMAT_A8_UNORM:
-               case PIPE_FORMAT_I8_UNORM:
-               case PIPE_FORMAT_L8A8_UNORM:
-               case PIPE_FORMAT_Z16_UNORM:
-               case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
-                       return TRUE;
-               /* TODO: does nv30 support this? */
-               case PIPE_FORMAT_R16_SNORM:
-                       return !!screen->is_nv4x;
-               default:
-                       break;
+               else
+               {
+                       if(tf->fmt[0] < 0)
+                               return FALSE;
                }
        }
 
-       return FALSE;
-}
+       // note that we do actually support everything through translate
+       if (bind & PIPE_BIND_VERTEX_BUFFER) {
+               unsigned type = nvfx_vertex_formats[format];
+               if(!type)
+                       return FALSE;
+       }
+
+       if (bind & PIPE_BIND_INDEX_BUFFER) {
+               // 8-bit indices supported, but not in hardware index buffer
+               if(format != PIPE_FORMAT_R16_USCALED && format != PIPE_FORMAT_R32_USCALED)
+                       return FALSE;
+       }
+
+       if(bind & PIPE_BIND_STREAM_OUTPUT)
+               return FALSE;
 
+       return TRUE;
+}
 
 static void
 nvfx_screen_destroy(struct pipe_screen *pscreen)
@@ -245,7 +231,7 @@ nvfx_screen_destroy(struct pipe_screen *pscreen)
        nouveau_notifier_free(&screen->query);
        nouveau_notifier_free(&screen->sync);
        nouveau_grobj_free(&screen->eng3d);
-       nv04_surface_2d_takedown(&screen->eng2d);
+       nvfx_screen_surface_takedown(pscreen);
 
        nouveau_screen_fini(&screen->base);
 
@@ -374,6 +360,14 @@ nvfx_screen_get_vertex_buffer_flags(struct nvfx_screen* screen)
        return vram_hack ? NOUVEAU_BO_VRAM : NOUVEAU_BO_GART;
 }
 
+static void nvfx_channel_flush_notify(struct nouveau_channel* chan)
+{
+       struct nvfx_screen* screen = chan->user_private;
+       struct nvfx_context* nvfx = screen->cur_ctx;
+       if(nvfx)
+               nvfx->relocs_needed = NVFX_RELOCATE_ALL;
+}
+
 struct pipe_screen *
 nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
 {
@@ -395,12 +389,15 @@ nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
                return NULL;
        }
        chan = screen->base.channel;
+       screen->cur_ctx = NULL;
+       chan->user_private = screen;
+       chan->flush_notify = nvfx_channel_flush_notify;
 
        pscreen->winsys = ws;
        pscreen->destroy = nvfx_screen_destroy;
        pscreen->get_param = nvfx_screen_get_param;
        pscreen->get_paramf = nvfx_screen_get_paramf;
-       pscreen->is_format_supported = nvfx_screen_surface_format_supported;
+       pscreen->is_format_supported = nvfx_screen_is_format_supported;
        pscreen->context_create = nvfx_create;
 
        switch (dev->chipset & 0xf0) {
@@ -432,6 +429,11 @@ nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
        }
 
        screen->force_swtnl = debug_get_bool_option("NOUVEAU_SWTNL", FALSE);
+       screen->trace_draw = debug_get_bool_option("NVFX_TRACE_DRAW", FALSE);
+
+       screen->buffer_allocation_cost = debug_get_num_option("NVFX_BUFFER_ALLOCATION_COST", 16384);
+       screen->inline_cost_per_hardware_cost = atof(debug_get_option("NVFX_INLINE_COST_PER_HARDWARE_COST", "1.0"));
+       screen->static_reuse_threshold = atof(debug_get_option("NVFX_STATIC_REUSE_THRESHOLD", "2.0"));
 
        screen->vertex_buffer_reloc_flags = nvfx_screen_get_vertex_buffer_flags(screen);
 
@@ -451,8 +453,7 @@ nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
        }
 
        /* 2D engine setup */
-       screen->eng2d = nv04_surface_2d_init(&screen->base);
-       screen->eng2d->buf = nvfx_surface_buffer;
+       nvfx_screen_surface_init(pscreen);
 
        /* Notifier for sync purposes */
        ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync);
index 5e1c3945aef8cf6a68ad16508335c30a7743c70f..1b79235ae0d294d62c5329b99ccbc467dedc449b 100644 (file)
@@ -1,11 +1,11 @@
 #ifndef __NVFX_SCREEN_H__
 #define __NVFX_SCREEN_H__
 
+#include "pipe/p_compiler.h"
 #include "util/u_double_list.h"
 #include "nouveau/nouveau_screen.h"
-#include "nv04_surface_2d.h"
 
-struct nvfx_context;
+struct pipe_screen;
 
 struct nvfx_screen {
        struct nouveau_screen base;
@@ -16,11 +16,11 @@ struct nvfx_screen {
 
        unsigned is_nv4x; /* either 0 or ~0 */
        boolean force_swtnl;
+       boolean trace_draw;
        unsigned vertex_buffer_reloc_flags;
        unsigned index_buffer_reloc_flags;
 
        /* HW graphics objects */
-       struct nv04_surface_2d *eng2d;
        struct nouveau_grobj *eng3d;
        struct nouveau_notifier *sync;
 
@@ -32,6 +32,20 @@ struct nvfx_screen {
        /* Vtxprog resources */
        struct nouveau_resource *vp_exec_heap;
        struct nouveau_resource *vp_data_heap;
+
+       struct nv04_2d_context* eng2d;
+
+       /* Once the amount of bytes drawn from the buffer reaches the updated size times this value,
+        * we will assume that the buffer will be drawn an huge number of times before the
+        * next modification
+        */
+       float static_reuse_threshold;
+
+       /* Cost of allocating a buffer in terms of the cost of copying a byte to an hardware buffer */
+       unsigned buffer_allocation_cost;
+
+       /* inline_cost/hardware_cost conversion ration */
+       float inline_cost_per_hardware_cost;
 };
 
 static INLINE struct nvfx_screen *
@@ -40,4 +54,7 @@ nvfx_screen(struct pipe_screen *screen)
        return (struct nvfx_screen *)screen;
 }
 
+int nvfx_screen_surface_init(struct pipe_screen *pscreen);
+void nvfx_screen_surface_takedown(struct pipe_screen *pscreen);
+
 #endif
index 50830b39164d796d33df9f9b9a966ed14f9c7a89..35006eec3d47845132ba8f2f5626c6f7ad097e33 100644 (file)
@@ -1,6 +1,12 @@
 #ifndef __NVFX_SHADER_H__
 #define __NVFX_SHADER_H__
 
+#include <stdint.h>
+
+#include "pipe/p_compiler.h"
+
+#define NVFX_SWZ_IDENTITY ((3 << 6) | (2 << 4) | (1 << 2) | (0 << 0))
+
 /* this will resolve to either the NV30 or the NV40 version
  * depending on the current hardware */
 /* unusual, but very fast and compact method */
 /*
  * Each fragment program opcode appears to be comprised of 4 32-bit values.
  *
- *   0 - Opcode, output reg/mask, ATTRIB source
- *   1 - Source 0
- *   2 - Source 1
- *   3 - Source 2
+ * 0: OPDEST
+ *     0: program end
+ *     1-6: destination register
+ *     7: destination register is fp16?? (use for outputs)
+ *     8: set condition code
+ *     9: writemask x
+ *     10: writemask y
+ *     11: writemask z
+ *     12: writemask w
+ *     13-16: source attribute register number (e.g. COL0)
+ *     17-20: texture unit number
+ *     21: expand value on texture operation (x -> 2x - 1)
+ *     22-23: precision 0 = fp32, 1 = fp16, 2 = s1.10 fixed, 3 = s0.8 fixed (nv40-only))
+ *     24-29: opcode
+ *     30: no destination
+ *     31: saturate
+ * 1 - SRC0
+ *     0-17: see common source fields
+ *     18: execute if condition code less
+ *     19: execute if condition code equal
+ *     20: execute if condition code greater
+ *     21-22: condition code swizzle x source component
+ *     23-24: condition code swizzle y source component
+ *     25-26: condition code swizzle z source component
+ *     27-28: condition code swizzle w source component
+ *     29: source 0 absolute
+ *     30: always 0 in renouveau tests
+ *     31: always 0 in renouveau tests
+ * 2 - SRC1
+ *     0-17: see common source fields
+ *     18: source 1 absolute
+ *     19-20: input precision 0 = fp32, 1 = fp16, 2 = s1.10 fixed, 3 = ???
+ *     21-27: always 0 in renouveau tests
+ *     28-30: scale (0 = 1x, 1 = 2x, 2 = 4x, 3 = 8x, 4 = ???, 5, = 1/2, 6 = 1/4, 7 = 1/8)
+ *     31: opcode is branch
+ * 3 - SRC2
+ *     0-17: see common source fields
+ *     18: source 2 absolute
+ *     19-29: address register displacement
+ *     30: use index register
+ *     31: disable perspective-correct interpolation?
  *
+* Common fields of 0, 1, 2 - SRC
+ *     0-1: source register type (0 = temp, 1 = input, 2 = immediate, 3 = ???)
+ *     2-7: source temp register index
+ *     8: source register is fp16??
+ *     9-10: source swizzle x source component
+ *     11-12: source swizzle y source component
+ *     13-14: source swizzle z source component
+ *     15-16: source swizzle w source component
+ *     17: negate
+
  * There appears to be no special difference between result regs and temp regs.
  *     result.color == R0.xyzw
  *     result.depth == R1.z
 
 /* NV40 only fragment program opcodes */
 #define NVFX_FP_OP_OPCODE_TXL_NV40 0x2F
+
 /* The use of these instructions appears to be indicated by bit 31 of DWORD 2.*/
 #define NV40_FP_OP_BRA_OPCODE_BRK                                    0x0
 #define NV40_FP_OP_BRA_OPCODE_CAL                                    0x1
 #define NV40_FP_OP_BRA_OPCODE_REP                                    0x4
 #define NV40_FP_OP_BRA_OPCODE_RET                                    0x5
 
+#define NV40_FP_OP_OUT_NONE         (1 << 30)
 #define NVFX_FP_OP_OUT_SAT          (1 << 31)
 
 /* high order bits of SRC0 */
-#define NVFX_FP_OP_OUT_ABS          (1 << 29)
+#define NVFX_FP_OP_SRC0_ABS          (1 << 29)
 #define NVFX_FP_OP_COND_SWZ_W_SHIFT        27
 #define NVFX_FP_OP_COND_SWZ_W_MASK        (3 << 27)
 #define NVFX_FP_OP_COND_SWZ_Z_SHIFT        25
 #define NVFX_FP_OP_DST_SCALE_INV_2X                                            5
 #define NVFX_FP_OP_DST_SCALE_INV_4X                                            6
 #define NVFX_FP_OP_DST_SCALE_INV_8X                                            7
+#define NVFX_FP_OP_SRC1_ABS          (1 << 18)
 
 /* SRC1 LOOP */
 #define NV40_FP_OP_LOOP_INCR_SHIFT                                            19
 #define NV40_FP_OP_LOOP_COUNT_SHIFT                                            2
 #define NV40_FP_OP_LOOP_COUNT_MASK                                   (0xFF << 2)
 
-/* SRC1 IF */
-#define NV40_FP_OP_ELSE_ID_SHIFT                                               2
-#define NV40_FP_OP_ELSE_ID_MASK                                      (0xFF << 2)
+/* SRC1 IF: absolute offset in dwords */
+#define NV40_FP_OP_ELSE_OFFSET_SHIFT                                           0
+#define NV40_FP_OP_ELSE_OFFSET_MASK                             (0x7FFFFFFF << 0)
 
 /* SRC1 CAL */
-#define NV40_FP_OP_IADDR_SHIFT                                                 2
-#define NV40_FP_OP_IADDR_MASK                                        (0xFF << 2)
+#define NV40_FP_OP_SUB_OFFSET_SHIFT                                                 0
+#define NV40_FP_OP_SUB_OFFSET_MASK                                   (0x7FFFFFFF << 0)
 
 /* SRC1 REP
  *   I have no idea why there are 3 count values here..  but they
 #define NV40_FP_OP_REP_COUNT3_SHIFT                                           19
 #define NV40_FP_OP_REP_COUNT3_MASK                                  (0xFF << 19)
 
-/* SRC2 REP/IF */
-#define NV40_FP_OP_END_ID_SHIFT                                                2
-#define NV40_FP_OP_END_ID_MASK                                       (0xFF << 2)
+/* SRC2 REP/IF: absolute offset in dwords */
+#define NV40_FP_OP_END_OFFSET_SHIFT                                            0
+#define NV40_FP_OP_END_OFFSET_MASK                              (0x7FFFFFFF << 0)
 
 /* high order bits of SRC2 */
 #define NVFX_FP_OP_INDEX_INPUT          (1 << 30)
 #define NVFXSR_INPUT   2
 #define NVFXSR_TEMP    3
 #define NVFXSR_CONST   4
+#define NVFXSR_RELOCATED       5
 
 #define NVFX_COND_FL  0
 #define NVFX_COND_LT  1
 #define NVFX_SWZ_Z 2
 #define NVFX_SWZ_W 3
 
-#define swz(s,x,y,z,w) nvfx_sr_swz((s), NVFX_SWZ_##x, NVFX_SWZ_##y, NVFX_SWZ_##z, NVFX_SWZ_##w)
-#define neg(s) nvfx_sr_neg((s))
-#define abs(s) nvfx_sr_abs((s))
-#define scale(s,v) nvfx_sr_scale((s), NVFX_FP_OP_DST_SCALE_##v)
+#define swz(s,x,y,z,w) nvfx_src_swz((s), NVFX_SWZ_##x, NVFX_SWZ_##y, NVFX_SWZ_##z, NVFX_SWZ_##w)
+#define neg(s) nvfx_src_neg((s))
+#define abs(s) nvfx_src_abs((s))
 
-struct nvfx_sreg {
-       int type;
-       int index;
+struct nvfx_reg {
+       uint8_t type;
+       uint32_t index;
+};
 
-       int dst_scale;
+struct nvfx_src {
+       struct nvfx_reg reg;
 
-       int negate;
-       int abs;
-       int swz[4];
+       /* src only */
+       uint8_t negate : 1;
+       uint8_t abs : 1;
+       uint8_t swz[4];
+};
 
-       int cc_update;
-       int cc_update_reg;
-       int cc_test;
-       int cc_test_reg;
-       int cc_swz[4];
+struct nvfx_insn
+{
+       uint8_t op;
+       char scale;
+       int8_t unit;
+       uint8_t mask;
+       uint8_t cc_swz[4];
+
+       uint8_t sat : 1;
+       uint8_t cc_update : 1;
+       uint8_t cc_update_reg : 1;
+       uint8_t cc_test : 3;
+       uint8_t cc_test_reg : 1;
+
+       struct nvfx_reg dst;
+       struct nvfx_src src[3];
 };
 
-static INLINE struct nvfx_sreg
-nvfx_sr(int type, int index)
+static INLINE struct nvfx_insn
+nvfx_insn(boolean sat, unsigned op, int unit, struct nvfx_reg dst, unsigned mask, struct nvfx_src s0, struct nvfx_src s1, struct nvfx_src s2)
 {
-       struct nvfx_sreg temp = {
-               .type = type,
-               .index = index,
-               .dst_scale = 0,
-               .abs = 0,
-               .negate = 0,
-               .swz = { 0, 1, 2, 3 },
+       struct nvfx_insn insn = {
+               .op = op,
+               .scale = 0,
+               .unit = unit,
+               .sat = sat,
+               .mask = mask,
                .cc_update = 0,
                .cc_update_reg = 0,
                .cc_test = NVFX_COND_TR,
                .cc_test_reg = 0,
                .cc_swz = { 0, 1, 2, 3 },
+               .dst = dst,
+               .src = {s0, s1, s2}
+       };
+       return insn;
+}
+
+static INLINE struct nvfx_reg
+nvfx_reg(int type, int index)
+{
+       struct nvfx_reg temp = {
+               .type = type,
+               .index = index,
        };
        return temp;
 }
 
-static INLINE struct nvfx_sreg
-nvfx_sr_swz(struct nvfx_sreg src, int x, int y, int z, int w)
+static INLINE struct nvfx_src
+nvfx_src(struct nvfx_reg reg)
 {
-       struct nvfx_sreg dst = src;
+       struct nvfx_src temp = {
+               .reg = reg,
+               .abs = 0,
+               .negate = 0,
+               .swz = { 0, 1, 2, 3 },
+       };
+       return temp;
+}
+
+static INLINE struct nvfx_src
+nvfx_src_swz(struct nvfx_src src, int x, int y, int z, int w)
+{
+       struct nvfx_src dst = src;
 
        dst.swz[NVFX_SWZ_X] = src.swz[x];
        dst.swz[NVFX_SWZ_Y] = src.swz[y];
@@ -405,25 +499,23 @@ nvfx_sr_swz(struct nvfx_sreg src, int x, int y, int z, int w)
        return dst;
 }
 
-static INLINE struct nvfx_sreg
-nvfx_sr_neg(struct nvfx_sreg src)
+static INLINE struct nvfx_src
+nvfx_src_neg(struct nvfx_src src)
 {
        src.negate = !src.negate;
        return src;
 }
 
-static INLINE struct nvfx_sreg
-nvfx_sr_abs(struct nvfx_sreg src)
+static INLINE struct nvfx_src
+nvfx_src_abs(struct nvfx_src src)
 {
        src.abs = 1;
        return src;
 }
 
-static INLINE struct nvfx_sreg
-nvfx_sr_scale(struct nvfx_sreg src, int scale)
-{
-       src.dst_scale = scale;
-       return src;
-}
+struct nvfx_relocation {
+        unsigned location;
+        unsigned target;
+};
 
 #endif
index cd58e439d711e6fbb98e7612a5debfc27a3c154b..5bd7dc07f02ac16f56020c6459ddbd3936f566bd 100644 (file)
@@ -1,6 +1,7 @@
 #include "pipe/p_state.h"
 #include "pipe/p_defines.h"
 #include "util/u_inlines.h"
+#include "util/u_framebuffer.h"
 
 #include "draw/draw_context.h"
 
@@ -80,111 +81,6 @@ nvfx_blend_state_delete(struct pipe_context *pipe, void *hwcso)
        FREE(bso);
 }
 
-static void *
-nvfx_sampler_state_create(struct pipe_context *pipe,
-                         const struct pipe_sampler_state *cso)
-{
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-       struct nvfx_sampler_state *ps;
-
-       ps = MALLOC(sizeof(struct nvfx_sampler_state));
-
-       /* on nv30, we use this as an internal flag */
-       ps->fmt = cso->normalized_coords ? 0 : NV40TCL_TEX_FORMAT_RECT;
-       ps->en = 0;
-       ps->filt = nvfx_tex_filter(cso);
-       ps->wrap = (nvfx_tex_wrap_mode(cso->wrap_s) << NV34TCL_TX_WRAP_S_SHIFT) |
-                   (nvfx_tex_wrap_mode(cso->wrap_t) << NV34TCL_TX_WRAP_T_SHIFT) |
-                   (nvfx_tex_wrap_mode(cso->wrap_r) << NV34TCL_TX_WRAP_R_SHIFT) |
-                   nvfx_tex_wrap_compare_mode(cso);
-       ps->bcol = nvfx_tex_border_color(cso->border_color);
-
-       if(nvfx->is_nv4x)
-               nv40_sampler_state_init(pipe, ps, cso);
-       else
-               nv30_sampler_state_init(pipe, ps, cso);
-
-       return (void *)ps;
-}
-
-static void
-nvfx_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
-{
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-       unsigned unit;
-
-       for (unit = 0; unit < nr; unit++) {
-               nvfx->tex_sampler[unit] = sampler[unit];
-               nvfx->dirty_samplers |= (1 << unit);
-       }
-
-       for (unit = nr; unit < nvfx->nr_samplers; unit++) {
-               nvfx->tex_sampler[unit] = NULL;
-               nvfx->dirty_samplers |= (1 << unit);
-       }
-
-       nvfx->nr_samplers = nr;
-       nvfx->dirty |= NVFX_NEW_SAMPLER;
-}
-
-static void
-nvfx_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
-{
-       FREE(hwcso);
-}
-
-static void
-nvfx_set_fragment_sampler_views(struct pipe_context *pipe,
-                               unsigned nr,
-                               struct pipe_sampler_view **views)
-{
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-       unsigned unit;
-
-       for (unit = 0; unit < nr; unit++) {
-               pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit],
-                                            views[unit]);
-               nvfx->dirty_samplers |= (1 << unit);
-       }
-
-       for (unit = nr; unit < nvfx->nr_textures; unit++) {
-               pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit],
-                                            NULL);
-               nvfx->dirty_samplers |= (1 << unit);
-       }
-
-       nvfx->nr_textures = nr;
-       nvfx->dirty |= NVFX_NEW_SAMPLER;
-}
-
-
-static struct pipe_sampler_view *
-nvfx_create_sampler_view(struct pipe_context *pipe,
-                        struct pipe_resource *texture,
-                        const struct pipe_sampler_view *templ)
-{
-       struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
-
-       if (view) {
-               *view = *templ;
-               view->reference.count = 1;
-               view->texture = NULL;
-               pipe_resource_reference(&view->texture, texture);
-               view->context = pipe;
-       }
-
-       return view;
-}
-
-
-static void
-nvfx_sampler_view_destroy(struct pipe_context *pipe,
-                         struct pipe_sampler_view *view)
-{
-       pipe_resource_reference(&view->texture, NULL);
-       FREE(view);
-}
-
 static void *
 nvfx_rasterizer_state_create(struct pipe_context *pipe,
                             const struct pipe_rasterizer_state *cso)
@@ -195,6 +91,7 @@ nvfx_rasterizer_state_create(struct pipe_context *pipe,
        /*XXX: ignored:
         *      point_smooth -nohw
         *      multisample
+        *     sprite_coord_origin
         */
 
        sb_method(sb, NV34TCL_SHADE_MODEL, 1);
@@ -254,19 +151,8 @@ nvfx_rasterizer_state_create(struct pipe_context *pipe,
                sb_data(sb, fui(cso->offset_units * 2));
        }
 
-       sb_method(sb, NV34TCL_POINT_SPRITE, 1);
-       if (cso->point_quad_rasterization) {
-               unsigned psctl = (1 << 0), i;
-
-               for (i = 0; i < 8; i++) {
-                       if ((cso->sprite_coord_enable >> i) & 1)
-                               psctl |= (1 << (8 + i));
-               }
-
-               sb_data(sb, psctl);
-       } else {
-               sb_data(sb, 0);
-       }
+       sb_method(sb, NV34TCL_FLATSHADE_FIRST, 1);
+       sb_data(sb, cso->flatshade_first);
 
        rsso->pipe = *cso;
        rsso->sb_len = sb_len(sb, rsso->sb);
@@ -287,11 +173,11 @@ nvfx_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
                        nvfx->draw_dirty |= NVFX_NEW_SCISSOR;
                }
 
-               if(((struct nvfx_rasterizer_state*)hwcso)->pipe.poly_stipple_enable
-                                       != nvfx->rasterizer->pipe.poly_stipple_enable)
+               if(((struct nvfx_rasterizer_state*)hwcso)->pipe.point_quad_rasterization != nvfx->rasterizer->pipe.point_quad_rasterization
+                               || ((struct nvfx_rasterizer_state*)hwcso)->pipe.sprite_coord_enable != nvfx->rasterizer->pipe.sprite_coord_enable
+                               || ((struct nvfx_rasterizer_state*)hwcso)->pipe.sprite_coord_mode != nvfx->rasterizer->pipe.sprite_coord_mode)
                {
-                       nvfx->dirty |= NVFX_NEW_STIPPLE;
-                       nvfx->draw_dirty |= NVFX_NEW_STIPPLE;
+                       nvfx->dirty |= NVFX_NEW_SPRITE;
                }
        }
 
@@ -315,10 +201,8 @@ nvfx_depth_stencil_alpha_state_create(struct pipe_context *pipe,
        struct nvfx_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso));
        struct nouveau_statebuf_builder sb = sb_init(zsaso->sb);
 
-       sb_method(sb, NV34TCL_DEPTH_FUNC, 3);
+       sb_method(sb, NV34TCL_DEPTH_FUNC, 1);
        sb_data  (sb, nvgl_comparison_op(cso->depth.func));
-       sb_data  (sb, cso->depth.writemask ? 1 : 0);
-       sb_data  (sb, cso->depth.enabled ? 1 : 0);
 
        sb_method(sb, NV34TCL_ALPHA_FUNC_ENABLE, 3);
        sb_data  (sb, cso->alpha.enabled ? 1 : 0);
@@ -377,76 +261,6 @@ nvfx_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
        FREE(zsaso);
 }
 
-static void *
-nvfx_vp_state_create(struct pipe_context *pipe,
-                    const struct pipe_shader_state *cso)
-{
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-       struct nvfx_vertex_program *vp;
-
-       vp = CALLOC(1, sizeof(struct nvfx_vertex_program));
-       vp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
-       vp->draw = draw_create_vertex_shader(nvfx->draw, &vp->pipe);
-
-       return (void *)vp;
-}
-
-static void
-nvfx_vp_state_bind(struct pipe_context *pipe, void *hwcso)
-{
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-
-       nvfx->vertprog = hwcso;
-       nvfx->dirty |= NVFX_NEW_VERTPROG;
-       nvfx->draw_dirty |= NVFX_NEW_VERTPROG;
-}
-
-static void
-nvfx_vp_state_delete(struct pipe_context *pipe, void *hwcso)
-{
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-       struct nvfx_vertex_program *vp = hwcso;
-
-       draw_delete_vertex_shader(nvfx->draw, vp->draw);
-       nvfx_vertprog_destroy(nvfx, vp);
-       FREE((void*)vp->pipe.tokens);
-       FREE(vp);
-}
-
-static void *
-nvfx_fp_state_create(struct pipe_context *pipe,
-                    const struct pipe_shader_state *cso)
-{
-       struct nvfx_fragment_program *fp;
-
-       fp = CALLOC(1, sizeof(struct nvfx_fragment_program));
-       fp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
-
-       tgsi_scan_shader(fp->pipe.tokens, &fp->info);
-
-       return (void *)fp;
-}
-
-static void
-nvfx_fp_state_bind(struct pipe_context *pipe, void *hwcso)
-{
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-
-       nvfx->fragprog = hwcso;
-       nvfx->dirty |= NVFX_NEW_FRAGPROG;
-}
-
-static void
-nvfx_fp_state_delete(struct pipe_context *pipe, void *hwcso)
-{
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-       struct nvfx_fragment_program *fp = hwcso;
-
-       nvfx_fragprog_destroy(nvfx, fp);
-       FREE((void*)fp->pipe.tokens);
-       FREE(fp);
-}
-
 static void
 nvfx_set_blend_color(struct pipe_context *pipe,
                     const struct pipe_blend_color *bcol)
@@ -507,7 +321,10 @@ nvfx_set_framebuffer_state(struct pipe_context *pipe,
 {
        struct nvfx_context *nvfx = nvfx_context(pipe);
 
-       nvfx->framebuffer = *fb;
+       if(fb)
+               util_copy_framebuffer_state(&nvfx->framebuffer, fb);
+       else
+               util_unreference_framebuffer_state(&nvfx->framebuffer);
        nvfx->dirty |= NVFX_NEW_FB;
 }
 
@@ -542,65 +359,6 @@ nvfx_set_viewport_state(struct pipe_context *pipe,
        nvfx->draw_dirty |= NVFX_NEW_VIEWPORT;
 }
 
-static void
-nvfx_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
-                       const struct pipe_vertex_buffer *vb)
-{
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-
-       memcpy(nvfx->vtxbuf, vb, sizeof(*vb) * count);
-       nvfx->vtxbuf_nr = count;
-
-       nvfx->dirty |= NVFX_NEW_ARRAYS;
-       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,
-                         const struct pipe_vertex_element *elements)
-{
-       struct nvfx_vtxelt_state *cso = CALLOC_STRUCT(nvfx_vtxelt_state);
-
-       assert(num_elements < 16); /* not doing fallbacks yet */
-       cso->num_elements = num_elements;
-       memcpy(cso->pipe, elements, num_elements * sizeof(*elements));
-
-/*     nvfx_vtxelt_construct(cso);*/
-
-       return (void *)cso;
-}
-
-static void
-nvfx_vtxelts_state_delete(struct pipe_context *pipe, void *hwcso)
-{
-       FREE(hwcso);
-}
-
-static void
-nvfx_vtxelts_state_bind(struct pipe_context *pipe, void *hwcso)
-{
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-
-       nvfx->vtxelt = hwcso;
-       nvfx->dirty |= NVFX_NEW_ARRAYS;
-       /*nvfx->draw_dirty |= NVFX_NEW_ARRAYS;*/
-}
-
 void
 nvfx_init_state_functions(struct nvfx_context *nvfx)
 {
@@ -608,13 +366,6 @@ nvfx_init_state_functions(struct nvfx_context *nvfx)
        nvfx->pipe.bind_blend_state = nvfx_blend_state_bind;
        nvfx->pipe.delete_blend_state = nvfx_blend_state_delete;
 
-       nvfx->pipe.create_sampler_state = nvfx_sampler_state_create;
-       nvfx->pipe.bind_fragment_sampler_states = nvfx_sampler_state_bind;
-       nvfx->pipe.delete_sampler_state = nvfx_sampler_state_delete;
-       nvfx->pipe.set_fragment_sampler_views = nvfx_set_fragment_sampler_views;
-        nvfx->pipe.create_sampler_view = nvfx_create_sampler_view;
-        nvfx->pipe.sampler_view_destroy = nvfx_sampler_view_destroy;
-
        nvfx->pipe.create_rasterizer_state = nvfx_rasterizer_state_create;
        nvfx->pipe.bind_rasterizer_state = nvfx_rasterizer_state_bind;
        nvfx->pipe.delete_rasterizer_state = nvfx_rasterizer_state_delete;
@@ -626,14 +377,6 @@ nvfx_init_state_functions(struct nvfx_context *nvfx)
        nvfx->pipe.delete_depth_stencil_alpha_state =
                nvfx_depth_stencil_alpha_state_delete;
 
-       nvfx->pipe.create_vs_state = nvfx_vp_state_create;
-       nvfx->pipe.bind_vs_state = nvfx_vp_state_bind;
-       nvfx->pipe.delete_vs_state = nvfx_vp_state_delete;
-
-       nvfx->pipe.create_fs_state = nvfx_fp_state_create;
-       nvfx->pipe.bind_fs_state = nvfx_fp_state_bind;
-       nvfx->pipe.delete_fs_state = nvfx_fp_state_delete;
-
        nvfx->pipe.set_blend_color = nvfx_set_blend_color;
         nvfx->pipe.set_stencil_ref = nvfx_set_stencil_ref;
        nvfx->pipe.set_clip_state = nvfx_set_clip_state;
@@ -643,11 +386,4 @@ nvfx_init_state_functions(struct nvfx_context *nvfx)
        nvfx->pipe.set_polygon_stipple = nvfx_set_polygon_stipple;
        nvfx->pipe.set_scissor_state = nvfx_set_scissor_state;
        nvfx->pipe.set_viewport_state = nvfx_set_viewport_state;
-
-       nvfx->pipe.create_vertex_elements_state = nvfx_vtxelts_state_create;
-       nvfx->pipe.delete_vertex_elements_state = nvfx_vtxelts_state_delete;
-       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;
 }
index 9ceb2577eccca59a1a9098196e220a9a5c3684aa..e9c1f2c26d2476c8d5db039d7a73e985df7d8353 100644 (file)
@@ -4,11 +4,11 @@
 #include "pipe/p_state.h"
 #include "tgsi/tgsi_scan.h"
 #include "nouveau/nouveau_statebuf.h"
+#include "util/u_dynarray.h"
+#include "util/u_linkage.h"
 
 struct nvfx_vertex_program_exec {
        uint32_t data[4];
-       boolean has_branch_offset;
-       int const_index;
 };
 
 struct nvfx_vertex_program_data {
@@ -18,18 +18,20 @@ struct nvfx_vertex_program_data {
 
 struct nvfx_vertex_program {
        struct pipe_shader_state pipe;
+       unsigned long long id;
 
        struct draw_vertex_shader *draw;
 
        boolean translated;
 
-       struct pipe_clip_state ucp;
-
        struct nvfx_vertex_program_exec *insns;
        unsigned nr_insns;
        struct nvfx_vertex_program_data *consts;
        unsigned nr_consts;
 
+       char generic_to_fp_input[256];
+       int sprite_fp_input;
+
        struct nouveau_resource *exec;
        unsigned exec_start;
        struct nouveau_resource *data;
@@ -38,7 +40,10 @@ struct nvfx_vertex_program {
 
        uint32_t ir;
        uint32_t or;
-       uint32_t clip_ctrl;
+       int clip_nr;
+
+       struct util_dynarray branch_relocs;
+       struct util_dynarray const_relocs;
 };
 
 struct nvfx_fragment_program_data {
@@ -49,15 +54,14 @@ struct nvfx_fragment_program_data {
 struct nvfx_fragment_program_bo {
        struct nvfx_fragment_program_bo* next;
        struct nouveau_bo* bo;
+       unsigned char* slots;
        char insn[] __attribute__((aligned(16)));
 };
 
 struct nvfx_fragment_program {
-       struct pipe_shader_state pipe;
-       struct tgsi_shader_info info;
-
-       boolean translated;
        unsigned samplers;
+       unsigned point_sprite_control;
+       unsigned or;
 
        uint32_t *insn;
        int       insn_len;
@@ -65,13 +69,36 @@ struct nvfx_fragment_program {
        struct nvfx_fragment_program_data *consts;
        unsigned nr_consts;
 
+       /* the slot at num_slots is for the sprite coordinate, if any */
+       unsigned num_slots; /* how many input semantics? */
+       unsigned char slot_to_generic[10]; /* semantics */
+       unsigned char slot_to_fp_input[11]; /* current assignment of slots for each used semantic */
+       struct util_dynarray slot_relocations[11];
+
+       /* This is reset to progs on any relocation update, and decreases every time we
+        * move to a new prog due to a constant update
+        * When this is the same as progs, applying relocations is no longer necessary.
+        */
+       unsigned progs_left_with_obsolete_slot_assignments;
+
+       unsigned long long last_vp_id;
+       unsigned last_sprite_coord_enable;
+
        uint32_t fp_control;
 
        unsigned bo_prog_idx;
        unsigned prog_size;
        unsigned progs_per_bo;
+       unsigned progs;
+
        struct nvfx_fragment_program_bo* fpbo;
 };
 
+struct nvfx_pipe_fragment_program {
+        struct pipe_shader_state pipe;
+        struct tgsi_shader_info info;
+
+        struct nvfx_fragment_program* fps[2];
+};
 
 #endif
index f91ae19ecd383f0d7adad5996daef8b5c4334b71..390bca8cdb530dc44fb6bed403cf2aa32b40cfcb 100644 (file)
@@ -1,15 +1,54 @@
 #include "nvfx_context.h"
 #include "nvfx_state.h"
+#include "nvfx_resource.h"
 #include "draw/draw_context.h"
 
 static boolean
 nvfx_state_validate_common(struct nvfx_context *nvfx)
 {
        struct nouveau_channel* chan = nvfx->screen->base.channel;
-       unsigned dirty = nvfx->dirty;
+       unsigned dirty;
+       unsigned still_dirty = 0;
+       int all_swizzled = -1;
+       boolean flush_tex_cache = FALSE;
+       unsigned render_temps;
 
        if(nvfx != nvfx->screen->cur_ctx)
-               dirty = ~0;
+       {
+               nvfx->dirty = ~0;
+               nvfx->hw_vtxelt_nr = 16;
+               nvfx->hw_pointsprite_control = -1;
+               nvfx->hw_vp_output = -1;
+               nvfx->screen->cur_ctx = nvfx;
+               nvfx->relocs_needed = NVFX_RELOCATE_ALL;
+       }
+
+       /* These can trigger use the of 3D engine to copy temporaries.
+        * That will recurse here and thus dirty all 3D state, so we need to this before anything else, and in a loop..
+        * This converges to having clean temps, then binding both fragtexes and framebuffers.
+        */
+       while(nvfx->dirty & (NVFX_NEW_FB | NVFX_NEW_SAMPLER))
+       {
+               if(nvfx->dirty & NVFX_NEW_SAMPLER)
+               {
+                       nvfx->dirty &=~ NVFX_NEW_SAMPLER;
+                       nvfx_fragtex_validate(nvfx);
+
+                       // TODO: only set this if really necessary
+                       flush_tex_cache = TRUE;
+               }
+
+               if(nvfx->dirty & NVFX_NEW_FB)
+               {
+                       nvfx->dirty &=~ NVFX_NEW_FB;
+                       all_swizzled = nvfx_framebuffer_prepare(nvfx);
+
+                       // TODO: make sure this doesn't happen, i.e. fbs have matching formats
+                       assert(all_swizzled >= 0);
+               }
+       }
+
+       dirty = nvfx->dirty;
 
        if(nvfx->render_mode == HW)
        {
@@ -19,11 +58,19 @@ nvfx_state_validate_common(struct nvfx_context *nvfx)
                                return FALSE;
                }
 
-               if(dirty & (NVFX_NEW_ARRAYS))
+               if(dirty & NVFX_NEW_ARRAYS)
                {
                        if(!nvfx_vbo_validate(nvfx))
                                return FALSE;
                }
+
+               if(dirty & NVFX_NEW_INDEX)
+               {
+                       if(nvfx->use_index_buffer)
+                               nvfx_idxbuf_validate(nvfx);
+                       else
+                               still_dirty = NVFX_NEW_INDEX;
+               }
        }
        else
        {
@@ -31,13 +78,10 @@ nvfx_state_validate_common(struct nvfx_context *nvfx)
                if(dirty & (NVFX_NEW_VERTPROG | NVFX_NEW_UCP))
                        nvfx_vertprog_validate(nvfx);
 
-               if(dirty & (NVFX_NEW_ARRAYS | NVFX_NEW_FRAGPROG))
+               if(dirty & (NVFX_NEW_ARRAYS | NVFX_NEW_INDEX | NVFX_NEW_FRAGPROG))
                        nvfx_vtxfmt_validate(nvfx);
        }
 
-       if(dirty & NVFX_NEW_FB)
-               nvfx_state_framebuffer_validate(nvfx);
-
        if(dirty & NVFX_NEW_RAST)
                sb_emit(chan, nvfx->rasterizer->sb, nvfx->rasterizer->sb_len);
 
@@ -47,11 +91,97 @@ nvfx_state_validate_common(struct nvfx_context *nvfx)
        if(dirty & NVFX_NEW_STIPPLE)
                nvfx_state_stipple_validate(nvfx);
 
-       if(dirty & (NVFX_NEW_FRAGPROG | NVFX_NEW_FRAGCONST))
+       if(nvfx->dirty & NVFX_NEW_UCP)
+       {
+               unsigned enables[7] =
+               {
+                               0,
+                               NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0,
+                               NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1,
+                               NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2,
+                               NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE3,
+                               NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE3 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE4,
+                               NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE3 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE4 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE5,
+               };
+
+               if(!nvfx->use_vp_clipping)
+               {
+                       WAIT_RING(chan, 2);
+                       OUT_RING(chan, RING_3D(NV34TCL_VP_CLIP_PLANES_ENABLE, 1));
+                       OUT_RING(chan, 0);
+
+                       WAIT_RING(chan, 6 * 4 + 1);
+                       OUT_RING(chan, RING_3D(NV34TCL_VP_CLIP_PLANE_A(0), nvfx->clip.nr * 4));
+                       OUT_RINGp(chan, &nvfx->clip.ucp[0][0], nvfx->clip.nr * 4);
+               }
+
+               WAIT_RING(chan, 2);
+               OUT_RING(chan, RING_3D(NV34TCL_VP_CLIP_PLANES_ENABLE, 1));
+               OUT_RING(chan, enables[nvfx->clip.nr]);
+       }
+
+       if(nvfx->use_vp_clipping && (nvfx->dirty & (NVFX_NEW_UCP | NVFX_NEW_VERTPROG)))
+       {
+               unsigned i;
+               struct nvfx_vertex_program* vp = nvfx->vertprog;
+               if(nvfx->clip.nr != vp->clip_nr)
+               {
+                       unsigned idx;
+                       WAIT_RING(chan, 14);
+
+                       /* remove last instruction bit */
+                       if(vp->clip_nr >= 0)
+                       {
+                               idx = vp->nr_insns - 7 + vp->clip_nr;
+                               OUT_RING(chan, RING_3D(NV34TCL_VP_UPLOAD_FROM_ID, 1));
+                               OUT_RING(chan,  vp->exec->start + idx);
+                               OUT_RING(chan, RING_3D(NV34TCL_VP_UPLOAD_INST(0), 4));
+                               OUT_RINGp (chan, vp->insns[idx].data, 4);
+                       }
+
+                        /* set last instruction bit */
+                       idx = vp->nr_insns - 7 + nvfx->clip.nr;
+                       OUT_RING(chan, RING_3D(NV34TCL_VP_UPLOAD_FROM_ID, 1));
+                       OUT_RING(chan,  vp->exec->start + idx);
+                       OUT_RING(chan, RING_3D(NV34TCL_VP_UPLOAD_INST(0), 4));
+                       OUT_RINGp(chan, vp->insns[idx].data, 3);
+                       OUT_RING(chan, vp->insns[idx].data[3] | 1);
+                       vp->clip_nr = nvfx->clip.nr;
+               }
+
+               // TODO: only do this for the ones changed
+               WAIT_RING(chan, 6 * 6);
+               for(i = 0; i < nvfx->clip.nr; ++i)
+               {
+                       OUT_RING(chan, RING_3D(NV34TCL_VP_UPLOAD_CONST_ID, 5));
+                       OUT_RING(chan, vp->data->start + i);
+                       OUT_RINGp (chan, nvfx->clip.ucp[i], 4);
+               }
+       }
+
+       if(dirty & (NVFX_NEW_FRAGPROG | NVFX_NEW_FRAGCONST | NVFX_NEW_VERTPROG | NVFX_NEW_SPRITE))
+       {
                nvfx_fragprog_validate(nvfx);
+               if(dirty & NVFX_NEW_FRAGPROG)
+                       flush_tex_cache = TRUE; // TODO: do we need this?
+       }
 
-       if(dirty & NVFX_NEW_SAMPLER)
-               nvfx_fragtex_validate(nvfx);
+       if(nvfx->is_nv4x)
+       {
+               unsigned vp_output = nvfx->vertprog->or | nvfx->hw_fragprog->or;
+               vp_output |= (1 << (nvfx->clip.nr + 6)) - (1 << 6);
+
+               if(vp_output != nvfx->hw_vp_output)
+               {
+                       WAIT_RING(chan, 2);
+                       OUT_RING(chan, RING_3D(NV40TCL_VP_RESULT_EN, 1));
+                       OUT_RING(chan, vp_output);
+                       nvfx->hw_vp_output = vp_output;
+               }
+       }
+
+       if(all_swizzled >= 0)
+               nvfx_framebuffer_validate(nvfx, all_swizzled);
 
        if(dirty & NVFX_NEW_BLEND)
                sb_emit(chan, nvfx->blend->sb, nvfx->blend->sb_len);
@@ -65,31 +195,62 @@ nvfx_state_validate_common(struct nvfx_context *nvfx)
        if(dirty & NVFX_NEW_SR)
                nvfx_state_sr_validate(nvfx);
 
-/* Having this depend on FB looks wrong, but it seems
-   necessary to make this work on nv3x
+/* All these dependencies are wrong, but otherwise
+   etracer, neverball, foobillard, glest totally misrender
    TODO: find the right fix
 */
-       if(dirty & (NVFX_NEW_VIEWPORT | NVFX_NEW_FB))
+       if(dirty & (NVFX_NEW_VIEWPORT | NVFX_NEW_RAST | NVFX_NEW_ZSA) || (all_swizzled >= 0))
+       {
                nvfx_state_viewport_validate(nvfx);
+       }
+
+       if(dirty & NVFX_NEW_ZSA || (all_swizzled >= 0))
+       {
+               WAIT_RING(chan, 3);
+               OUT_RING(chan, RING_3D(NV34TCL_DEPTH_WRITE_ENABLE, 2));
+               OUT_RING(chan, nvfx->framebuffer.zsbuf && nvfx->zsa->pipe.depth.writemask);
+               OUT_RING(chan, nvfx->framebuffer.zsbuf && nvfx->zsa->pipe.depth.enabled);
+       }
 
-       /* TODO: could nv30 need this or something similar too? */
-       if((dirty & (NVFX_NEW_FRAGPROG | NVFX_NEW_SAMPLER)) && nvfx->is_nv4x) {
-               WAIT_RING(chan, 4);
-               OUT_RING(chan, RING_3D(NV40TCL_TEX_CACHE_CTL, 1));
-               OUT_RING(chan, 2);
-               OUT_RING(chan, RING_3D(NV40TCL_TEX_CACHE_CTL, 1));
-               OUT_RING(chan, 1);
+       if(flush_tex_cache)
+       {
+               // TODO: what about nv30?
+               if(nvfx->is_nv4x)
+               {
+                       WAIT_RING(chan, 4);
+                       OUT_RING(chan, RING_3D(NV40TCL_TEX_CACHE_CTL, 1));
+                       OUT_RING(chan, 2);
+                       OUT_RING(chan, RING_3D(NV40TCL_TEX_CACHE_CTL, 1));
+                       OUT_RING(chan, 1);
+               }
        }
-       nvfx->dirty = 0;
+
+       nvfx->dirty = dirty & still_dirty;
+
+       render_temps = nvfx->state.render_temps;
+       if(render_temps)
+       {
+               for(int i = 0; i < nvfx->framebuffer.nr_cbufs; ++i)
+               {
+                       if(render_temps & (1 << i))
+                               util_dirty_surface_set_dirty(nvfx_surface_get_dirty_surfaces(nvfx->framebuffer.cbufs[i]),
+                                               (struct util_dirty_surface*)nvfx->framebuffer.cbufs[i]);
+               }
+
+               if(render_temps & 0x80)
+                       util_dirty_surface_set_dirty(nvfx_surface_get_dirty_surfaces(nvfx->framebuffer.zsbuf),
+                                       (struct util_dirty_surface*)nvfx->framebuffer.zsbuf);
+       }
+
        return TRUE;
 }
 
-void
-nvfx_state_emit(struct nvfx_context *nvfx)
+inline void
+nvfx_state_relocate(struct nvfx_context *nvfx, unsigned relocs)
 {
        struct nouveau_channel* chan = nvfx->screen->base.channel;
        /* we need to ensure there is enough space to output relocations in one go */
-       unsigned max_relocs = 0
+       const unsigned max_relocs = 0
              + 16 /* vertex buffers, incl. dma flag */
              + 2 /* index buffer plus format+dma flag */
              + 2 * 5 /* 4 cbufs + zsbuf, plus dma objects */
@@ -97,18 +258,19 @@ nvfx_state_emit(struct nvfx_context *nvfx)
              + 2 * 4 /* vertex textures plus format+dma flag */
              + 1 /* fragprog incl dma flag */
              ;
+
        MARK_RING(chan, max_relocs * 2, max_relocs * 2);
-       nvfx_state_relocate(nvfx);
-}
 
-void
-nvfx_state_relocate(struct nvfx_context *nvfx)
-{
-       nvfx_framebuffer_relocate(nvfx);
-       nvfx_fragtex_relocate(nvfx);
-       nvfx_fragprog_relocate(nvfx);
-       if (nvfx->render_mode == HW)
+       if(relocs & NVFX_RELOCATE_FRAMEBUFFER)
+               nvfx_framebuffer_relocate(nvfx);
+       if(relocs & NVFX_RELOCATE_FRAGTEX)
+               nvfx_fragtex_relocate(nvfx);
+       if(relocs & NVFX_RELOCATE_FRAGPROG)
+               nvfx_fragprog_relocate(nvfx);
+       if(relocs & NVFX_RELOCATE_VTXBUF)
                nvfx_vbo_relocate(nvfx);
+       if(relocs & NVFX_RELOCATE_IDXBUF)
+               nvfx_idxbuf_relocate(nvfx);
 }
 
 boolean
@@ -173,6 +335,9 @@ nvfx_state_validate_swtnl(struct nvfx_context *nvfx)
                draw_set_vertex_elements(draw, nvfx->vtxelt->num_elements, nvfx->vtxelt->pipe);
        }
 
+       if (nvfx->draw_dirty & NVFX_NEW_INDEX)
+               draw_set_index_buffer(draw, &nvfx->idxbuf);
+
        nvfx_state_validate_common(nvfx);
 
        nvfx->draw_dirty = 0;
index 360e569f77c8bdcf328f44a947dbc57fd514256a..3b869d43a15a2ce62dc39214067e442a1c8c7d7b 100644 (file)
@@ -1,21 +1,55 @@
 #include "nvfx_context.h"
 #include "nvfx_resource.h"
-#include "nouveau/nouveau_util.h"
+#include "util/u_format.h"
 
+static inline boolean
+nvfx_surface_linear_renderable(struct pipe_surface* surf)
+{
+       return (surf->texture->flags & NVFX_RESOURCE_FLAG_LINEAR)
+               && !(surf->offset & 63)
+               && !(((struct nvfx_surface*)surf)->pitch & 63);
+}
 
+static inline boolean
+nvfx_surface_swizzled_renderable(struct pipe_framebuffer_state* fb, struct pipe_surface* surf)
+{
+       /* TODO: return FALSE if we have a format not supporting swizzled rendering (e.g. r8); currently those are not supported at all */
+       return !((struct nvfx_miptree*)surf->texture)->linear_pitch
+               && (surf->texture->target != PIPE_TEXTURE_3D || u_minify(surf->texture->depth0, surf->level) <= 1)
+               && !(surf->offset & 127)
+               && (surf->width == fb->width)
+               && (surf->height == fb->height)
+               && !((struct nvfx_surface*)surf)->temp;
+}
 
-void
-nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)
+static boolean
+nvfx_surface_get_render_target(struct pipe_surface* surf, int all_swizzled, struct nvfx_render_target* target)
+{
+       struct nvfx_surface* ns = (struct nvfx_surface*)surf;
+       if(!ns->temp)
+       {
+               target->bo = ((struct nvfx_miptree*)surf->texture)->base.bo;
+               target->offset = surf->offset;
+               target->pitch = align(ns->pitch, 64);
+               assert(target->pitch);
+               return FALSE;
+       }
+       else
+       {
+               target->offset = 0;
+               target->pitch = ns->temp->linear_pitch;
+               target->bo = ns->temp->base.bo;
+               assert(target->pitch);
+               return TRUE;
+       }
+}
+
+int
+nvfx_framebuffer_prepare(struct nvfx_context *nvfx)
 {
        struct pipe_framebuffer_state *fb = &nvfx->framebuffer;
-       struct nouveau_channel *chan = nvfx->screen->base.channel;
-       uint32_t rt_enable = 0, rt_format = 0;
-       int i, colour_format = 0, zeta_format = 0;
-       int depth_only = 0;
-       unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
-       unsigned w = fb->width;
-       unsigned h = fb->height;
-       int colour_bits = 32, zeta_bits = 32;
+       int i, color_format = 0, zeta_format = 0;
+       int all_swizzled = 1;
 
        if(!nvfx->is_nv4x)
                assert(fb->nr_cbufs <= 2);
@@ -23,113 +57,135 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)
                assert(fb->nr_cbufs <= 4);
 
        for (i = 0; i < fb->nr_cbufs; i++) {
-               if (colour_format)
-                       assert(colour_format == fb->cbufs[i]->format);
-               else
-                       colour_format = fb->cbufs[i]->format;
-
-               rt_enable |= (NV34TCL_RT_ENABLE_COLOR0 << i);
-               nvfx->hw_rt[i].bo = nvfx_surface_buffer(fb->cbufs[i]);
-               nvfx->hw_rt[i].offset = fb->cbufs[i]->offset;
-               nvfx->hw_rt[i].pitch = ((struct nv04_surface *)fb->cbufs[i])->pitch;
+               if (color_format) {
+                       if(color_format != fb->cbufs[i]->format)
+                               return -1;
+               } else
+                       color_format = fb->cbufs[i]->format;
+
+               if(!nvfx_surface_swizzled_renderable(fb, fb->cbufs[i]))
+                       all_swizzled = 0;
        }
-       for(; i < 4; ++i)
-               nvfx->hw_rt[i].bo = 0;
 
+       if (fb->zsbuf) {
+               /* TODO: return FALSE if we have a format not supporting a depth buffer (e.g. r8); currently those are not supported at all */
+               if(!nvfx_surface_swizzled_renderable(fb, fb->zsbuf))
+                       all_swizzled = 0;
+
+               if(all_swizzled && util_format_get_blocksize(color_format) != util_format_get_blocksize(zeta_format))
+                       all_swizzled = 0;
+       }
+
+       for (i = 0; i < fb->nr_cbufs; i++) {
+               if(!((struct nvfx_surface*)fb->cbufs[i])->temp && !all_swizzled && !nvfx_surface_linear_renderable(fb->cbufs[i]))
+                       nvfx_surface_create_temp(&nvfx->pipe, fb->cbufs[i]);
+       }
+
+       if(fb->zsbuf) {
+               if(!((struct nvfx_surface*)fb->zsbuf)->temp && !all_swizzled && !nvfx_surface_linear_renderable(fb->zsbuf))
+                       nvfx_surface_create_temp(&nvfx->pipe, fb->zsbuf);
+       }
+
+       return all_swizzled;
+}
+
+void
+nvfx_framebuffer_validate(struct nvfx_context *nvfx, unsigned prepare_result)
+{
+       struct pipe_framebuffer_state *fb = &nvfx->framebuffer;
+       struct nouveau_channel *chan = nvfx->screen->base.channel;
+       uint32_t rt_enable, rt_format;
+       int i;
+       unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
+       unsigned w = fb->width;
+       unsigned h = fb->height;
+
+       rt_enable = (NV34TCL_RT_ENABLE_COLOR0 << fb->nr_cbufs) - 1;
        if (rt_enable & (NV34TCL_RT_ENABLE_COLOR1 |
                         NV40TCL_RT_ENABLE_COLOR2 | NV40TCL_RT_ENABLE_COLOR3))
                rt_enable |= NV34TCL_RT_ENABLE_MRT;
 
+       nvfx->state.render_temps = 0;
+
+       for (i = 0; i < fb->nr_cbufs; i++)
+               nvfx->state.render_temps |= nvfx_surface_get_render_target(fb->cbufs[i], prepare_result, &nvfx->hw_rt[i]) << i;
+
+       for(; i < 4; ++i)
+               nvfx->hw_rt[i].bo = 0;
+
        if (fb->zsbuf) {
-               zeta_format = fb->zsbuf->format;
-               nvfx->hw_zeta.bo = nvfx_surface_buffer(fb->zsbuf);
-               nvfx->hw_zeta.offset = fb->zsbuf->offset;
-               nvfx->hw_zeta.pitch = ((struct nv04_surface *)fb->zsbuf)->pitch;
-       }
-       else
-               nvfx->hw_zeta.bo = 0;
-
-       if (rt_enable & (NV34TCL_RT_ENABLE_COLOR0 | NV34TCL_RT_ENABLE_COLOR1 |
-               NV40TCL_RT_ENABLE_COLOR2 | NV40TCL_RT_ENABLE_COLOR3)) {
-               /* Render to at least a colour buffer */
-               if (!(fb->cbufs[0]->texture->flags & NVFX_RESOURCE_FLAG_LINEAR)) {
-                       assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1)));
-                       for (i = 1; i < fb->nr_cbufs; i++)
-                               assert(!(fb->cbufs[i]->texture->flags & NVFX_RESOURCE_FLAG_LINEAR));
-
-                       rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED |
-                               (log2i(fb->cbufs[0]->width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT) |
-                               (log2i(fb->cbufs[0]->height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT);
-               }
-               else
-                       rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR;
-       } else if (fb->zsbuf) {
-               depth_only = 1;
-
-               /* Render to depth buffer only */
-               if (!(fb->zsbuf->texture->usage & NVFX_RESOURCE_FLAG_LINEAR)) {
-                       assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1)));
-
-                       rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED |
-                               (log2i(fb->zsbuf->width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT) |
-                               (log2i(fb->zsbuf->height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT);
-               }
-               else
-                       rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR;
-       } else {
-               return;
+               nvfx->state.render_temps |= nvfx_surface_get_render_target(fb->zsbuf, prepare_result, &nvfx->hw_zeta) << 7;
+
+               assert(util_format_get_stride(fb->zsbuf->format, fb->width) <= nvfx->hw_zeta.pitch);
+               assert(nvfx->hw_zeta.offset + nvfx->hw_zeta.pitch * fb->height <= nvfx->hw_zeta.bo->size);
        }
 
-       switch (colour_format) {
-       case PIPE_FORMAT_B8G8R8X8_UNORM:
-               rt_format |= NV34TCL_RT_FORMAT_COLOR_X8R8G8B8;
-               break;
-       case PIPE_FORMAT_B8G8R8A8_UNORM:
-       case 0:
-               rt_format |= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8;
-               break;
-       case PIPE_FORMAT_B5G6R5_UNORM:
+       if (prepare_result) {
+               assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1)));
+
+               rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED |
+                       (util_logbase2(fb->width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT) |
+                       (util_logbase2(fb->height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT);
+       } else
+               rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR;
+
+       if(fb->nr_cbufs > 0) {
+               switch (fb->cbufs[0]->format) {
+               case PIPE_FORMAT_B8G8R8X8_UNORM:
+                       rt_format |= NV34TCL_RT_FORMAT_COLOR_X8R8G8B8;
+                       break;
+               case PIPE_FORMAT_B8G8R8A8_UNORM:
+               case 0:
+                       rt_format |= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8;
+                       break;
+               case PIPE_FORMAT_B5G6R5_UNORM:
+                       rt_format |= NV34TCL_RT_FORMAT_COLOR_R5G6B5;
+                       break;
+               default:
+                       assert(0);
+               }
+       } else if(fb->zsbuf && util_format_get_blocksize(fb->zsbuf->format) == 2)
                rt_format |= NV34TCL_RT_FORMAT_COLOR_R5G6B5;
-               colour_bits = 16;
-               break;
-       default:
-               assert(0);
-       }
+       else
+               rt_format |= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8;
 
-       switch (zeta_format) {
-       case PIPE_FORMAT_Z16_UNORM:
+       if(fb->zsbuf) {
+               switch (fb->zsbuf->format) {
+               case PIPE_FORMAT_Z16_UNORM:
+                       rt_format |= NV34TCL_RT_FORMAT_ZETA_Z16;
+                       break;
+               case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+               case PIPE_FORMAT_X8Z24_UNORM:
+               case 0:
+                       rt_format |= NV34TCL_RT_FORMAT_ZETA_Z24S8;
+                       break;
+               default:
+                       assert(0);
+               }
+       } else if(fb->nr_cbufs && util_format_get_blocksize(fb->cbufs[0]->format) == 2)
                rt_format |= NV34TCL_RT_FORMAT_ZETA_Z16;
-               zeta_bits = 16;
-               break;
-       case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
-       case PIPE_FORMAT_X8Z24_UNORM:
-       case 0:
+       else
                rt_format |= NV34TCL_RT_FORMAT_ZETA_Z24S8;
-               break;
-       default:
-               assert(0);
-       }
 
-       if ((!nvfx->is_nv4x) && colour_bits > zeta_bits) {
-               /* TODO: does this limitation really exist?
-                  TODO: can it be worked around somehow? */
-               assert(0);
-       }
+       if ((rt_enable & NV34TCL_RT_ENABLE_COLOR0) || fb->zsbuf) {
+               struct nvfx_render_target *rt0 = &nvfx->hw_rt[0];
+               uint32_t pitch;
 
-       if ((rt_enable & NV34TCL_RT_ENABLE_COLOR0)
-               || ((!nvfx->is_nv4x) && depth_only)) {
-               struct nvfx_render_target *rt0 = (depth_only ? &nvfx->hw_zeta : &nvfx->hw_rt[0]);
-               uint32_t pitch = rt0->pitch;
+               if(!(rt_enable & NV34TCL_RT_ENABLE_COLOR0))
+                       rt0 = &nvfx->hw_zeta;
+
+               pitch = rt0->pitch;
 
                if(!nvfx->is_nv4x)
                {
-                       if (nvfx->hw_zeta.bo) {
+                       if (nvfx->hw_zeta.bo)
                                pitch |= (nvfx->hw_zeta.pitch << 16);
-                       } else {
+                       else
                                pitch |= (pitch << 16);
-                       }
                }
 
+               //printf("rendering to bo %p [%i] at offset %i with pitch %i\n", rt0->bo, rt0->bo->handle, rt0->offset, pitch);
+
                OUT_RING(chan, RING_3D(NV34TCL_DMA_COLOR0, 1));
                OUT_RELOC(chan, rt0->bo, 0,
                              rt_flags | NOUVEAU_BO_OR,
@@ -182,7 +238,7 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)
                }
        }
 
-       if (zeta_format) {
+       if (fb->zsbuf) {
                OUT_RING(chan, RING_3D(NV34TCL_DMA_ZETA, 1));
                OUT_RELOC(chan, nvfx->hw_zeta.bo, 0,
                              rt_flags | NOUVEAU_BO_OR,
@@ -196,6 +252,10 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)
                        OUT_RING(chan, nvfx->hw_zeta.pitch);
                }
        }
+       else if(nvfx->is_nv4x) {
+               OUT_RING(chan, RING_3D(NV40TCL_ZETA_PITCH, 1));
+               OUT_RING(chan, 64);
+       }
 
        OUT_RING(chan, RING_3D(NV34TCL_RT_ENABLE, 1));
        OUT_RING(chan, rt_enable);
@@ -218,6 +278,7 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)
                OUT_RING(chan, RING_3D(NV34TCL_VIEWPORT_TX_ORIGIN, 1));
                OUT_RING(chan, 0);
        }
+       nvfx->relocs_needed &=~ NVFX_RELOCATE_FRAMEBUFFER;
 }
 
 void
@@ -247,4 +308,5 @@ nvfx_framebuffer_relocate(struct nvfx_context *nvfx)
        DO(NV40, 3);
 
        DO_(nvfx->hw_zeta, NV34, ZETA);
+       nvfx->relocs_needed &=~ NVFX_RELOCATE_FRAMEBUFFER;
 }
index 4da968f093fdb54e7276037632c2a19ecb4eb864..b76e9dd3824344af4c166b4b07742efe74084fc6 100644 (file)
@@ -4,23 +4,8 @@ void
 nvfx_state_stipple_validate(struct nvfx_context *nvfx)
 {
        struct nouveau_channel *chan = nvfx->screen->base.channel;
-       struct pipe_rasterizer_state *rast = &nvfx->rasterizer->pipe;
 
-       if ((rast->poly_stipple_enable == 0 && nvfx->state.stipple_enabled == 0))
-               return;
-
-       if (rast->poly_stipple_enable) {
-               unsigned i;
-
-               WAIT_RING(chan, 35);
-               OUT_RING(chan, RING_3D(NV34TCL_POLYGON_STIPPLE_ENABLE, 1));
-               OUT_RING(chan, 1);
-               OUT_RING(chan, RING_3D(NV34TCL_POLYGON_STIPPLE_PATTERN(0), 32));
-               for (i = 0; i < 32; i++)
-                       OUT_RING(chan, nvfx->stipple[i]);
-       } else {
-               WAIT_RING(chan, 2);
-               OUT_RING(chan, RING_3D(NV34TCL_POLYGON_STIPPLE_ENABLE, 1));
-               OUT_RING(chan, 0);
-       }
+       WAIT_RING(chan, 33);
+       OUT_RING(chan, RING_3D(NV34TCL_POLYGON_STIPPLE_PATTERN(0), 32));
+       OUT_RINGp(chan, nvfx->stipple, 32);
 }
index a605d2b7545fcd42c36bc3e22790f518e5eb3055..a5931b6e1526e75d3878643e7ebf50407b29a252 100644 (file)
  *
  **************************************************************************/
 
+#include "pipe/p_context.h"
+#include "pipe/p_format.h"
+#include "util/u_format.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "util/u_pack_color.h"
+#include "util/u_blitter.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_screen.h"
 #include "nvfx_context.h"
+#include "nvfx_screen.h"
 #include "nvfx_resource.h"
-#include "pipe/p_defines.h"
-#include "util/u_inlines.h"
-#include "util/u_pack_color.h"
+#include "nv04_2d.h"
+
+#include <nouveau/nouveau_bo.h>
+
+static INLINE void
+nvfx_region_set_format(struct nv04_region* rgn, enum pipe_format format)
+{
+       unsigned bits = util_format_get_blocksizebits(format);
+       switch(bits)
+       {
+       case 8:
+               rgn->bpps = 0;
+               break;
+       case 16:
+               rgn->bpps = 1;
+               break;
+       case 32:
+               rgn->bpps = 2;
+               break;
+       default:
+               {
+                       int shift;
+                       assert(util_is_power_of_two(bits));
+                       shift = util_logbase2(bits) - 3;
+                       assert(shift >= 2);
+                       rgn->bpps = 2;
+                       shift -= 2;
+
+                       rgn->x = util_format_get_nblocksx(format, rgn->x) << shift;
+                       rgn->y = util_format_get_nblocksy(format, rgn->y);
+               }
+       }
+}
+
+static INLINE void
+nvfx_region_fixup_swizzled(struct nv04_region* rgn, unsigned zslice, unsigned width, unsigned height, unsigned depth)
+{
+       // TODO: move this code to surface creation?
+       if((depth <= 1) && (height <= 1 || width <= 2))
+               rgn->pitch = width << rgn->bpps;
+       else if(depth > 1 && height <= 2 && width <= 2)
+       {
+               rgn->pitch = width << rgn->bpps;
+               rgn->offset += (zslice * width * height) << rgn->bpps;
+       }
+       else
+       {
+               rgn->pitch = 0;
+               rgn->z = zslice;
+               rgn->w = width;
+               rgn->h = height;
+               rgn->d = depth;
+       }
+}
+
+static INLINE void
+nvfx_region_init_for_surface(struct nv04_region* rgn, struct nvfx_surface* surf, unsigned x, unsigned y, bool for_write)
+{
+       rgn->x = x;
+       rgn->y = y;
+       rgn->z = 0;
+       nvfx_region_set_format(rgn, surf->base.base.format);
+
+       if(surf->temp)
+       {
+               rgn->bo = surf->temp->base.bo;
+               rgn->offset = 0;
+               rgn->pitch = surf->temp->linear_pitch;
+
+               if(for_write)
+                       util_dirty_surface_set_dirty(nvfx_surface_get_dirty_surfaces(&surf->base.base), &surf->base);
+       } else {
+               rgn->bo = ((struct nvfx_resource*)surf->base.base.texture)->bo;
+               rgn->offset = surf->base.base.offset;
+               rgn->pitch = surf->pitch;
+
+               if(!(surf->base.base.texture->flags & NVFX_RESOURCE_FLAG_LINEAR))
+                       nvfx_region_fixup_swizzled(rgn, surf->base.base.zslice, surf->base.base.width, surf->base.base.height, u_minify(surf->base.base.texture->depth0, surf->base.base.level));
+       }
+}
+
+static INLINE void
+nvfx_region_init_for_subresource(struct nv04_region* rgn, struct pipe_resource* pt, struct pipe_subresource sub, unsigned x, unsigned y, unsigned z, bool for_write)
+{
+       if(pt->target != PIPE_BUFFER)
+       {
+               struct nvfx_surface* ns = (struct nvfx_surface*)util_surfaces_peek(&((struct nvfx_miptree*)pt)->surfaces, pt, sub.face, sub.level, z);
+               if(ns && util_dirty_surface_is_dirty(&ns->base))
+               {
+                       nvfx_region_init_for_surface(rgn, ns, x, y, for_write);
+                       return;
+               }
+       }
+
+       rgn->bo = ((struct nvfx_resource*)pt)->bo;
+       rgn->offset = nvfx_subresource_offset(pt, sub.face, sub.level, z);
+       rgn->pitch = nvfx_subresource_pitch(pt, sub.level);
+       rgn->x = x;
+       rgn->y = y;
+       rgn->z = 0;
+
+       nvfx_region_set_format(rgn, pt->format);
+       if(!(pt->flags & NVFX_RESOURCE_FLAG_LINEAR))
+               nvfx_region_fixup_swizzled(rgn, z, u_minify(pt->width0, sub.level), u_minify(pt->height0, sub.level), u_minify(pt->depth0, sub.level));
+}
+
+// TODO: actually test this for all formats, it's probably wrong for some...
+
+static INLINE int
+nvfx_surface_format(enum pipe_format format)
+{
+       switch(util_format_get_blocksize(format)) {
+       case 1:
+               return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
+       case 2:
+               //return NV04_CONTEXT_SURFACES_2D_FORMAT_Y16;
+               return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
+       case 4:
+               //if(format == PIPE_FORMAT_B8G8R8X8_UNORM || format == PIPE_FORMAT_B8G8R8A8_UNORM)
+                       return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
+               //else
+               //      return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
+       default:
+               return -1;
+       }
+}
+
+static INLINE int
+nv04_scaled_image_format(enum pipe_format format)
+{
+       switch(util_format_get_blocksize(format)) {
+       case 1:
+               return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8;
+       case 2:
+               //if(format == PIPE_FORMAT_B5G5R5A1_UNORM)
+               //      return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5;
+               //else
+                       return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
+       case 4:
+               if(format == PIPE_FORMAT_B8G8R8X8_UNORM)
+                       return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
+               else
+                       return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
+       default:
+               return -1;
+       }
+}
+
+// XXX: must save index buffer too!
+static struct blitter_context*
+nvfx_get_blitter(struct pipe_context* pipe, int copy)
+{
+       struct nvfx_context* nvfx = nvfx_context(pipe);
+
+       struct blitter_context* blitter = nvfx->blitter;
+       if(!blitter)
+               nvfx->blitter = blitter = util_blitter_create(pipe);
+
+       util_blitter_save_blend(blitter, nvfx->blend);
+       util_blitter_save_depth_stencil_alpha(blitter, nvfx->zsa);
+       util_blitter_save_stencil_ref(blitter, &nvfx->stencil_ref);
+       util_blitter_save_rasterizer(blitter, nvfx->rasterizer);
+       util_blitter_save_fragment_shader(blitter, nvfx->fragprog);
+       util_blitter_save_vertex_shader(blitter, nvfx->vertprog);
+       util_blitter_save_viewport(blitter, &nvfx->viewport);
+       util_blitter_save_framebuffer(blitter, &nvfx->framebuffer);
+       util_blitter_save_clip(blitter, &nvfx->clip);
+       util_blitter_save_vertex_elements(blitter, nvfx->vtxelt);
+       util_blitter_save_vertex_buffers(blitter, nvfx->vtxbuf_nr, nvfx->vtxbuf);
+
+       if(copy)
+       {
+               util_blitter_save_fragment_sampler_states(blitter, nvfx->nr_samplers, (void**)nvfx->tex_sampler);
+               util_blitter_save_fragment_sampler_views(blitter, nvfx->nr_textures, nvfx->fragment_sampler_views);
+       }
+
+       return blitter;
+}
+
+static unsigned
+nvfx_region_clone(struct nv04_2d_context* ctx, struct nv04_region* rgn, unsigned w, unsigned h, boolean for_read)
+{
+       unsigned begin = nv04_region_begin(rgn, w, h);
+       unsigned end = nv04_region_end(rgn, w, h);
+       unsigned size = end - begin;
+       struct nouveau_bo* bo = 0;
+       nouveau_bo_new(rgn->bo->device, NOUVEAU_BO_MAP | NOUVEAU_BO_GART, 256, size, &bo);
+
+       if(for_read || (size > ((w * h) << rgn->bpps)))
+               nv04_memcpy(ctx, bo, 0, rgn->bo, rgn->offset + begin, size);
+
+       rgn->bo = bo;
+       rgn->offset = -begin;
+       return begin;
+}
 
 static void
-nvfx_surface_copy(struct pipe_context *pipe,
-                 struct pipe_resource *dest, struct pipe_subresource subdst,
-                 unsigned destx, unsigned desty, unsigned destz,
-                 struct pipe_resource *src, struct pipe_subresource subsrc,
+nvfx_resource_copy_region(struct pipe_context *pipe,
+                 struct pipe_resource *dstr, struct pipe_subresource subdst,
+                 unsigned dstx, unsigned dsty, unsigned dstz,
+                 struct pipe_resource *srcr, struct pipe_subresource subsrc,
                  unsigned srcx, unsigned srcy, unsigned srcz,
-                 unsigned width, unsigned height)
+                 unsigned w, unsigned h)
 {
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-       struct nv04_surface_2d *eng2d = nvfx->screen->eng2d;
-       struct pipe_surface *ps_dst, *ps_src;
+       static int copy_threshold = -1;
+       struct nv04_2d_context *ctx = nvfx_screen(pipe->screen)->eng2d;
+       struct nv04_region dst, src;
+       int dst_to_gpu;
+       int src_on_gpu;
+       boolean small;
+       int ret;
+
+       if(!w || !h)
+               return;
+
+       if(copy_threshold < 0)
+               copy_threshold = debug_get_num_option("NOUVEAU_COPY_THRESHOLD", 4);
+
+       dst_to_gpu = dstr->usage != PIPE_USAGE_DYNAMIC && dstr->usage != PIPE_USAGE_STAGING;
+       src_on_gpu = nvfx_resource_on_gpu(srcr);
+
+       nvfx_region_init_for_subresource(&dst, dstr, subdst, dstx, dsty, dstz, TRUE);
+       nvfx_region_init_for_subresource(&src, srcr, subsrc, srcx, srcy, srcz, FALSE);
+       w = util_format_get_stride(dstr->format, w) >> dst.bpps;
+       h = util_format_get_nblocksy(dstr->format, h);
 
-       ps_src = nvfx_miptree_surface_new(pipe->screen, src, subsrc.face,
-                                         subsrc.level, srcz, 0 /* bind flags */);
-       ps_dst = nvfx_miptree_surface_new(pipe->screen, dest, subdst.face,
-                                         subdst.level, destz, 0 /* bindflags */);
+       small = (w * h <= copy_threshold);
+       if((!dst_to_gpu || !src_on_gpu) && small)
+               ret = -1; /* use the CPU */
+       else
+               ret = nv04_region_copy_2d(ctx, &dst, &src, w, h,
+                       dstr->target == PIPE_BUFFER ? -1 : nvfx_surface_format(dstr->format),
+                       dstr->target == PIPE_BUFFER ? -1 : nv04_scaled_image_format(dstr->format),
+                       dst_to_gpu, src_on_gpu);
+       if(!ret)
+       {}
+       else if(ret > 0 && dstr->bind & PIPE_BIND_RENDER_TARGET && srcr->bind & PIPE_BIND_SAMPLER_VIEW)
+       {
+               struct blitter_context* blitter = nvfx_get_blitter(pipe, 1);
+               util_blitter_copy_region(blitter, dstr, subdst, dstx, dsty, dstz, srcr, subsrc, srcx, srcy, srcz, w, h, TRUE);
+       }
+       else
+       {
+               struct nv04_region dstt = dst;
+               struct nv04_region srct = src;
+               unsigned dstbegin = 0;
 
-       eng2d->copy(eng2d, ps_dst, destx, desty, ps_src, srcx, srcy, width, height);
+               if(!small)
+               {
+                       if(src_on_gpu)
+                               nvfx_region_clone(ctx, &srct, w, h, TRUE);
 
-       nvfx_miptree_surface_del(ps_src);
-       nvfx_miptree_surface_del(ps_dst);
+                       if(dst_to_gpu)
+                               dstbegin = nvfx_region_clone(ctx, &dstt, w, h, FALSE);
+               }
+
+               nv04_region_copy_cpu(&dstt, &srct, w, h);
+
+               if(srct.bo != src.bo)
+                       nouveau_screen_bo_release(pipe->screen, srct.bo);
+
+               if(dstt.bo != dst.bo)
+               {
+                       nv04_memcpy(ctx, dst.bo, dst.offset + dstbegin, dstt.bo, 0, dstt.bo->size);
+                       nouveau_screen_bo_release(pipe->screen, dstt.bo);
+               }
+       }
+}
+
+static int
+nvfx_surface_fill(struct pipe_context* pipe, struct pipe_surface *dsts,
+                 unsigned dx, unsigned dy, unsigned w, unsigned h, unsigned value)
+{
+       struct nv04_2d_context *ctx = nvfx_screen(pipe->screen)->eng2d;
+       struct nv04_region dst;
+       int ret;
+       /* Always try to use the GPU right now, if possible
+        * If the user wanted the surface data on the CPU, he would have cleared with memset (hopefully) */
+
+       // we don't care about interior pixel order since we set all them to the same value
+       nvfx_region_init_for_surface(&dst, (struct nvfx_surface*)dsts, dx, dy, TRUE);
+
+       w = util_format_get_stride(dsts->format, w) >> dst.bpps;
+       h = util_format_get_nblocksy(dsts->format, h);
+
+       ret = nv04_region_fill_2d(ctx, &dst, w, h, value);
+       if(ret > 0 && dsts->texture->bind & PIPE_BIND_RENDER_TARGET)
+               return 1;
+       else if(ret)
+       {
+               struct nv04_region dstt = dst;
+               unsigned dstbegin = 0;
+
+               if(nvfx_resource_on_gpu(dsts->texture))
+                       dstbegin = nvfx_region_clone(ctx, &dstt, w, h, FALSE);
+
+               nv04_region_fill_cpu(&dstt, w, h, value);
+
+               if(dstt.bo != dst.bo)
+               {
+                       nv04_memcpy(ctx, dst.bo, dst.offset + dstbegin, dstt.bo, 0, dstt.bo->size);
+                       nouveau_screen_bo_release(pipe->screen, dstt.bo);
+               }
+       }
+
+       return 0;
+}
+
+
+void
+nvfx_screen_surface_takedown(struct pipe_screen *pscreen)
+{
+       nv04_2d_context_takedown(nvfx_screen(pscreen)->eng2d);
+       nvfx_screen(pscreen)->eng2d = 0;
+}
+
+int
+nvfx_screen_surface_init(struct pipe_screen *pscreen)
+{
+       struct nv04_2d_context* ctx = nv04_2d_context_init(nouveau_screen(pscreen)->channel);
+       if(!ctx)
+               return -1;
+       nvfx_screen(pscreen)->eng2d = ctx;
+       return 0;
+}
+
+static void
+nvfx_surface_copy_temp(struct pipe_context* pipe, struct pipe_surface* surf, int to_temp)
+{
+       struct nvfx_surface* ns = (struct nvfx_surface*)surf;
+       struct pipe_subresource tempsr, surfsr;
+       struct nvfx_context* nvfx = nvfx_context(pipe);
+
+       // TODO: we really should do this validation before setting these variable in draw calls
+       unsigned use_vertex_buffers = nvfx->use_vertex_buffers;
+       boolean use_index_buffer = nvfx->use_index_buffer;
+       unsigned base_vertex = nvfx->base_vertex;
+
+       tempsr.face = 0;
+       tempsr.level = 0;
+       surfsr.face = surf->face;
+       surfsr.level = surf->level;
+
+       if(to_temp)
+               nvfx_resource_copy_region(pipe, &ns->temp->base.base, tempsr, 0, 0, 0, surf->texture, surfsr, 0, 0, surf->zslice, surf->width, surf->height);
+       else
+               nvfx_resource_copy_region(pipe, surf->texture, surfsr, 0, 0, surf->zslice, &ns->temp->base.base, tempsr, 0, 0, 0, surf->width, surf->height);
+
+       nvfx->use_vertex_buffers = use_vertex_buffers;
+       nvfx->use_index_buffer = use_index_buffer;
+        nvfx->base_vertex = base_vertex;
+
+       nvfx->dirty |= NVFX_NEW_ARRAYS;
+       nvfx->draw_dirty |= NVFX_NEW_ARRAYS;
+}
+
+void
+nvfx_surface_create_temp(struct pipe_context* pipe, struct pipe_surface* surf)
+{
+       struct nvfx_surface* ns = (struct nvfx_surface*)surf;
+       struct pipe_resource template;
+       memset(&template, 0, sizeof(struct pipe_resource));
+       template.target = PIPE_TEXTURE_2D;
+       template.format = surf->format;
+       template.width0 = surf->width;
+       template.height0 = surf->height;
+       template.depth0 = 1;
+       template.nr_samples = surf->texture->nr_samples;
+       template.flags = NVFX_RESOURCE_FLAG_LINEAR;
+
+       ns->temp = (struct nvfx_miptree*)nvfx_miptree_create(pipe->screen, &template);
+       nvfx_surface_copy_temp(pipe, surf, 1);
+}
+
+void
+nvfx_surface_flush(struct pipe_context* pipe, struct pipe_surface* surf)
+{
+       struct nvfx_context* nvfx = (struct nvfx_context*)pipe;
+       struct nvfx_surface* ns = (struct nvfx_surface*)surf;
+       boolean bound = FALSE;
+
+       /* must be done before the copy, otherwise the copy will use the temp as destination */
+       util_dirty_surface_set_clean(nvfx_surface_get_dirty_surfaces(surf), &ns->base);
+
+       nvfx_surface_copy_temp(pipe, surf, 0);
+
+       if(nvfx->framebuffer.zsbuf == surf)
+               bound = TRUE;
+       else
+       {
+               for(unsigned i = 0; i < nvfx->framebuffer.nr_cbufs; ++i)
+               {
+                       if(nvfx->framebuffer.cbufs[i] == surf)
+                       {
+                               bound = TRUE;
+                               break;
+                       }
+               }
+       }
+
+       if(!bound)
+               pipe_resource_reference((struct pipe_resource**)&ns->temp, 0);
 }
 
 static void
@@ -62,12 +450,16 @@ nvfx_clear_render_target(struct pipe_context *pipe,
                         unsigned dstx, unsigned dsty,
                         unsigned width, unsigned height)
 {
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-       struct nv04_surface_2d *eng2d = nvfx->screen->eng2d;
        union util_color uc;
        util_pack_color(rgba, dst->format, &uc);
 
-       eng2d->fill(eng2d, dst, dstx, dsty, width, height, uc.ui);
+       if(util_format_get_blocksizebits(dst->format) > 32
+               || nvfx_surface_fill(pipe, dst, dstx, dsty, width, height, uc.ui))
+       {
+               // TODO: probably should use hardware clear here instead if possible
+               struct blitter_context* blitter = nvfx_get_blitter(pipe, 0);
+               util_blitter_clear_render_target(blitter, dst, rgba, dstx, dsty, width, height);
+       }
 }
 
 static void
@@ -79,18 +471,20 @@ nvfx_clear_depth_stencil(struct pipe_context *pipe,
                         unsigned dstx, unsigned dsty,
                         unsigned width, unsigned height)
 {
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-       struct nv04_surface_2d *eng2d = nvfx->screen->eng2d;
-
-       eng2d->fill(eng2d, dst, dstx, dsty, width, height,
-                   util_pack_z_stencil(dst->format, depth, stencil));
+       if(util_format_get_blocksizebits(dst->format) > 32
+               || nvfx_surface_fill(pipe, dst, dstx, dsty, width, height, util_pack_z_stencil(dst->format, depth, stencil)))
+       {
+               // TODO: probably should use hardware clear here instead if possible
+               struct blitter_context* blitter = nvfx_get_blitter(pipe, 0);
+               util_blitter_clear_depth_stencil(blitter, dst, clear_flags, depth, stencil, dstx, dsty, width, height);
+       }
 }
 
 
 void
 nvfx_init_surface_functions(struct nvfx_context *nvfx)
 {
-       nvfx->pipe.resource_copy_region = nvfx_surface_copy;
+       nvfx->pipe.resource_copy_region = nvfx_resource_copy_region;
        nvfx->pipe.clear_render_target = nvfx_clear_render_target;
        nvfx->pipe.clear_depth_stencil = nvfx_clear_depth_stencil;
 }
index 69187a79e792d9221adcfb4e9344ff6289e90114..34be936a891d93b3c76e32e10a7a3d48103a80a0 100644 (file)
@@ -1,6 +1,11 @@
 #ifndef NVFX_TEX_H_
 #define NVFX_TEX_H_
 
+#include "util/u_math.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include <nouveau/nouveau_class.h>
+
 static inline unsigned
 nvfx_tex_wrap_mode(unsigned wrap) {
        unsigned ret;
@@ -31,7 +36,7 @@ nvfx_tex_wrap_mode(unsigned wrap) {
                ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP;
                break;
        default:
-               NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
+               assert(0);
                ret = NV34TCL_TX_WRAP_S_REPEAT;
                break;
        }
@@ -40,31 +45,29 @@ nvfx_tex_wrap_mode(unsigned wrap) {
 }
 
 static inline unsigned
-nvfx_tex_wrap_compare_mode(const struct pipe_sampler_state* cso)
+nvfx_tex_wrap_compare_mode(unsigned func)
 {
-       if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
-               switch (cso->compare_func) {
-               case PIPE_FUNC_NEVER:
-                       return NV34TCL_TX_WRAP_RCOMP_NEVER;
-               case PIPE_FUNC_GREATER:
-                       return NV34TCL_TX_WRAP_RCOMP_GREATER;
-               case PIPE_FUNC_EQUAL:
-                       return NV34TCL_TX_WRAP_RCOMP_EQUAL;
-               case PIPE_FUNC_GEQUAL:
-                       return NV34TCL_TX_WRAP_RCOMP_GEQUAL;
-               case PIPE_FUNC_LESS:
-                       return NV34TCL_TX_WRAP_RCOMP_LESS;
-               case PIPE_FUNC_NOTEQUAL:
-                       return NV34TCL_TX_WRAP_RCOMP_NOTEQUAL;
-               case PIPE_FUNC_LEQUAL:
-                       return NV34TCL_TX_WRAP_RCOMP_LEQUAL;
-               case PIPE_FUNC_ALWAYS:
-                       return NV34TCL_TX_WRAP_RCOMP_ALWAYS;
-               default:
-                       break;
-               }
+       switch (func) {
+       case PIPE_FUNC_NEVER:
+               return NV34TCL_TX_WRAP_RCOMP_NEVER;
+       case PIPE_FUNC_GREATER:
+               return NV34TCL_TX_WRAP_RCOMP_GREATER;
+       case PIPE_FUNC_EQUAL:
+               return NV34TCL_TX_WRAP_RCOMP_EQUAL;
+       case PIPE_FUNC_GEQUAL:
+               return NV34TCL_TX_WRAP_RCOMP_GEQUAL;
+       case PIPE_FUNC_LESS:
+               return NV34TCL_TX_WRAP_RCOMP_LESS;
+       case PIPE_FUNC_NOTEQUAL:
+               return NV34TCL_TX_WRAP_RCOMP_NOTEQUAL;
+       case PIPE_FUNC_LEQUAL:
+               return NV34TCL_TX_WRAP_RCOMP_LEQUAL;
+       case PIPE_FUNC_ALWAYS:
+               return NV34TCL_TX_WRAP_RCOMP_ALWAYS;
+       default:
+               assert(0);
+               return 0;
        }
-       return 0;
 }
 
 static inline unsigned nvfx_tex_filter(const struct pipe_sampler_state* cso)
@@ -128,6 +131,45 @@ struct nvfx_sampler_state {
        uint32_t en;
        uint32_t filt;
        uint32_t bcol;
+       uint32_t min_lod;
+       uint32_t max_lod;
+       boolean compare;
+};
+
+struct nvfx_sampler_view {
+       struct pipe_sampler_view base;
+       int offset;
+       uint32_t swizzle;
+       uint32_t npot_size;
+       uint32_t filt;
+       uint32_t wrap_mask;
+       uint32_t wrap;
+       uint32_t lod_offset;
+       uint32_t max_lod_limit;
+       union
+       {
+               struct
+               {
+                       uint32_t fmt[4]; /* nv30 has 4 entries, nv40 one */
+                       int rect;
+               } nv30;
+               struct
+               {
+                       uint32_t fmt[2]; /* nv30 has 4 entries, nv40 one */
+                       uint32_t npot_size2; /* nv40 only */
+               } nv40;
+               uint32_t init_fmt;
+       } u;
 };
 
+struct nvfx_texture_format {
+       int fmt[6];
+       unsigned sign;
+       unsigned wrap;
+       unsigned char src[6];
+       unsigned char comp[6];
+};
+
+extern struct nvfx_texture_format nvfx_texture_formats[PIPE_FORMAT_COUNT];
+
 #endif /* NVFX_TEX_H_ */
index 9ff0a93d3077d5b9805457f4ad4eba19002c8bf0..7cb47a20f645818ecb046b24a258051b3e312c4f 100644 (file)
 #include "util/u_format.h"
 #include "util/u_memory.h"
 #include "util/u_math.h"
-#include "nouveau/nouveau_winsys.h"
+#include "util/u_staging.h"
 #include "nvfx_context.h"
 #include "nvfx_screen.h"
 #include "nvfx_state.h"
 #include "nvfx_resource.h"
 #include "nvfx_transfer.h"
 
-struct nvfx_transfer {
-       struct pipe_transfer base;
-       struct pipe_surface *surface;
-       boolean direct;
-};
-
-static void
-nvfx_compatible_transfer_tex(struct pipe_resource *pt, unsigned width, unsigned height,
-                            unsigned bind,
-                             struct pipe_resource *template)
-{
-       memset(template, 0, sizeof(struct pipe_resource));
-       template->target = pt->target;
-       template->format = pt->format;
-       template->width0 = width;
-       template->height0 = height;
-       template->depth0 = 1;
-       template->last_level = 0;
-       template->nr_samples = pt->nr_samples;
-       template->bind = bind;
-       template->usage = PIPE_USAGE_DYNAMIC;
-       template->flags = NVFX_RESOURCE_FLAG_LINEAR;
-}
-
-
-static unsigned nvfx_transfer_bind_flags( unsigned transfer_usage )
+struct nvfx_staging_transfer
 {
-       unsigned bind = 0;
+       struct util_staging_transfer base;
 
-#if 0
-       if (transfer_usage & PIPE_TRANSFER_WRITE)
-               bind |= PIPE_BIND_BLIT_SOURCE;
-
-       if (transfer_usage & PIPE_TRANSFER_READ)
-               bind |= PIPE_BIND_BLIT_DESTINATION;
-#endif
-
-       return bind;
-}
+       unsigned offset;
+       unsigned map_count;
+};
 
 struct pipe_transfer *
-nvfx_miptree_transfer_new(struct pipe_context *pipe,
+nvfx_transfer_new(struct pipe_context *pipe,
                          struct pipe_resource *pt,
                          struct pipe_subresource sr,
                          unsigned usage,
                          const struct pipe_box *box)
 {
-       struct pipe_screen *pscreen = pipe->screen;
-       struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
-       struct nvfx_transfer *tx;
-       struct pipe_resource tx_tex_template, *tx_tex;
-       static int no_transfer = -1;
-       unsigned bind = nvfx_transfer_bind_flags(usage);
-       if(no_transfer < 0)
-               no_transfer = debug_get_bool_option("NOUVEAU_NO_TRANSFER", FALSE);
-
-
-       tx = CALLOC_STRUCT(nvfx_transfer);
-       if (!tx)
-               return NULL;
-
-       /* Don't handle 3D transfers yet.
-        */
-       assert(box->depth == 1);
-
-       pipe_resource_reference(&tx->base.resource, pt);
-       tx->base.sr = sr;
-       tx->base.usage = usage;
-       tx->base.box = *box;
-       tx->base.stride = mt->level[sr.level].pitch;
-
-       /* Direct access to texture */
-       if ((pt->usage == PIPE_USAGE_DYNAMIC ||
-            no_transfer) &&
-           pt->flags & NVFX_RESOURCE_FLAG_LINEAR)
+        if((usage & (PIPE_TRANSFER_UNSYNCHRONIZED | PIPE_TRANSFER_DONTBLOCK)) == PIPE_TRANSFER_DONTBLOCK)
+        {
+                struct nouveau_bo* bo = ((struct nvfx_resource*)pt)->bo;
+                if(bo && nouveau_bo_busy(bo, NOUVEAU_BO_WR))
+                        return NULL;
+        }
+
+       if(pt->target == PIPE_BUFFER)
        {
-               tx->direct = true;
-
-               /* XXX: just call the internal nvfx function.  
-                */
-               tx->surface = pscreen->get_tex_surface(pscreen, pt,
-                                                      sr.face, sr.level,
-                                                      box->z,
-                                                      bind);
-               return &tx->base;
-       }
+               // it would be nice if we could avoid all this ridiculous overhead...
+               struct pipe_transfer* tx;
+               struct nvfx_buffer* buffer = nvfx_buffer(pt);
+
+               tx = CALLOC_STRUCT(pipe_transfer);
+               if (!tx)
+                       return NULL;
 
-       tx->direct = false;
+               pipe_resource_reference(&tx->resource, pt);
+               tx->sr = sr;
+               tx->usage = usage;
+               tx->box = *box;
 
-       nvfx_compatible_transfer_tex(pt, box->width, box->height, bind, &tx_tex_template);
+               tx->slice_stride = tx->stride = util_format_get_stride(pt->format, box->width);
+               tx->data = buffer->data + util_format_get_stride(pt->format, box->x);
 
-       tx_tex = pscreen->resource_create(pscreen, &tx_tex_template);
-       if (!tx_tex)
+               return tx;
+       }
+       else
        {
-               FREE(tx);
-               return NULL;
+               struct nvfx_staging_transfer* tx;
+               bool direct = !nvfx_resource_on_gpu(pt) && pt->flags & NVFX_RESOURCE_FLAG_LINEAR;
+
+               tx = CALLOC_STRUCT(nvfx_staging_transfer);
+               if(!tx)
+                       return NULL;
+
+               util_staging_transfer_init(pipe, pt, sr, usage, box, direct, &tx->base);
+
+               if(direct)
+               {
+                       tx->base.base.stride = nvfx_subresource_pitch(pt, sr.level);
+                       tx->base.base.slice_stride = tx->base.base.stride * u_minify(pt->height0, sr.level);
+                       tx->offset = nvfx_subresource_offset(pt, sr.face, sr.level, box->z)
+                               + util_format_get_2d_size(pt->format, tx->base.base.stride, box->y)
+                               + util_format_get_stride(pt->format, box->x);
+               }
+               else
+               {
+                       tx->base.base.stride = nvfx_subresource_pitch(tx->base.staging_resource, 0);
+                       tx->base.base.slice_stride = tx->base.base.stride * tx->base.staging_resource->height0;
+                       tx->offset = 0;
+               }
+
+               assert(tx->base.base.stride);
+
+               return &tx->base.base;
        }
+}
 
-       tx->base.stride = ((struct nvfx_miptree*)tx_tex)->level[0].pitch;
-
-       tx->surface = pscreen->get_tex_surface(pscreen, tx_tex,
-                                              0, 0, 0,
-                                              bind);
-
-       pipe_resource_reference(&tx_tex, NULL);
-
-       if (!tx->surface)
+static void nvfx_buffer_dirty_interval(struct nvfx_buffer* buffer, unsigned begin, unsigned size, boolean unsynchronized)
+{
+       struct nvfx_screen* screen = nvfx_screen(buffer->base.base.screen);
+       buffer->last_update_static = buffer->bytes_to_draw_until_static < 0;
+       if(buffer->dirty_begin == buffer->dirty_end)
        {
-               pipe_surface_reference(&tx->surface, NULL);
-               FREE(tx);
-               return NULL;
+               buffer->dirty_begin = begin;
+               buffer->dirty_end = begin + size;
+               buffer->dirty_unsynchronized = unsynchronized;
+       }
+       else
+       {
+               buffer->dirty_begin = MIN2(buffer->dirty_begin, begin);
+               buffer->dirty_end = MAX2(buffer->dirty_end, begin + size);
+               buffer->dirty_unsynchronized &= unsynchronized;
        }
 
-       if (usage & PIPE_TRANSFER_READ) {
-               struct nvfx_screen *nvscreen = nvfx_screen(pscreen);
-               struct pipe_surface *src;
+       if(unsynchronized)
+       {
+               // TODO: revisit this, it doesn't seem quite right
+               //printf("UNSYNC UPDATE %p %u %u\n", buffer, begin, size);
+               buffer->bytes_to_draw_until_static += size * screen->static_reuse_threshold;
+       }
+       else
+               buffer->bytes_to_draw_until_static = buffer->size * screen->static_reuse_threshold;
+}
 
-               src = pscreen->get_tex_surface(pscreen, pt,
-                                              sr.face, sr.level, box->z,
-                                              0 /*PIPE_BIND_BLIT_SOURCE*/);
+static void nvfx_transfer_flush_region( struct pipe_context *pipe,
+                                     struct pipe_transfer *ptx,
+                                     const struct pipe_box *box)
+{
+       if(ptx->resource->target == PIPE_BUFFER && (ptx->usage & PIPE_TRANSFER_FLUSH_EXPLICIT))
+       {
+               struct nvfx_buffer* buffer = nvfx_buffer(ptx->resource);
+               nvfx_buffer_dirty_interval(buffer,
+                               (uint8_t*)ptx->data - buffer->data + util_format_get_stride(buffer->base.base.format, box->x),
+                               util_format_get_stride(buffer->base.base.format, box->width),
+                               !!(ptx->usage & PIPE_TRANSFER_UNSYNCHRONIZED));
+       }
+}
 
-               /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
-               /* TODO: Check if SIFM can un-swizzle */
-               nvscreen->eng2d->copy(nvscreen->eng2d,
-                                     tx->surface, 0, 0,
-                                     src,
-                                     box->x, box->y,
-                                     box->width, box->height);
+static void
+nvfx_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *ptx)
+{
+       if(ptx->resource->target == PIPE_BUFFER)
+       {
+               struct nvfx_buffer* buffer = nvfx_buffer(ptx->resource);
+               if((ptx->usage & (PIPE_TRANSFER_WRITE | PIPE_TRANSFER_FLUSH_EXPLICIT)) == PIPE_TRANSFER_WRITE)
+                       nvfx_buffer_dirty_interval(buffer,
+                               (uint8_t*)ptx->data - buffer->data,
+                               ptx->stride,
+                               !!(ptx->usage & PIPE_TRANSFER_UNSYNCHRONIZED));
+               pipe_resource_reference(&ptx->resource, 0);
+               FREE(ptx);
+       }
+       else
+       {
+               struct nouveau_channel* chan = nvfx_context(pipe)->screen->base.channel;
+               util_staging_transfer_destroy(pipe, ptx);
 
-               pipe_surface_reference(&src, NULL);
+               FIRE_RING(chan);
        }
+}
 
-       return &tx->base;
+void *
+nvfx_transfer_map(struct pipe_context *pipe, struct pipe_transfer *ptx)
+{
+       if(ptx->resource->target == PIPE_BUFFER)
+               return ptx->data;
+       else
+       {
+               struct nvfx_staging_transfer *tx = (struct nvfx_staging_transfer *)ptx;
+               if(!ptx->data)
+               {
+                       struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->base.staging_resource;
+                       uint8_t *map = nouveau_screen_bo_map(pipe->screen, mt->base.bo, nouveau_screen_transfer_flags(ptx->usage));
+                       ptx->data = map + tx->offset;
+               }
+
+               ++tx->map_count;
+               return ptx->data;
+       }
 }
 
 void
-nvfx_miptree_transfer_del(struct pipe_context *pipe,
-                         struct pipe_transfer *ptx)
+nvfx_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *ptx)
 {
-       struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx;
-
-       if (!tx->direct && (ptx->usage & PIPE_TRANSFER_WRITE)) {
-               struct pipe_screen *pscreen = pipe->screen;
-               struct nvfx_screen *nvscreen = nvfx_screen(pscreen);
-               struct pipe_surface *dst;
-
-               dst = pscreen->get_tex_surface(pscreen,
-                                              ptx->resource,
-                                              ptx->sr.face,
-                                              ptx->sr.level,
-                                              ptx->box.z,
-                                              0 /*PIPE_BIND_BLIT_DESTINATION*/);
-
-               /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
-               nvscreen->eng2d->copy(nvscreen->eng2d,
-                                     dst, ptx->box.x, ptx->box.y,
-                                     tx->surface, 0, 0,
-                                     ptx->box.width, ptx->box.height);
-
-               pipe_surface_reference(&dst, NULL);
+       if(ptx->resource->target != PIPE_BUFFER)
+       {
+               struct nvfx_staging_transfer *tx = (struct nvfx_staging_transfer *)ptx;
+               struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->base.staging_resource;
+
+               if(!--tx->map_count)
+               {
+                       nouveau_screen_bo_unmap(pipe->screen, mt->base.bo);
+                       ptx->data = 0;
+               }
        }
-
-       pipe_surface_reference(&tx->surface, NULL);
-       pipe_resource_reference(&ptx->resource, NULL);
-       FREE(ptx);
 }
 
-void *
-nvfx_miptree_transfer_map(struct pipe_context *pipe, struct pipe_transfer *ptx)
+static void nvfx_transfer_inline_write( struct pipe_context *pipe,
+                                     struct pipe_resource *pr,
+                                     struct pipe_subresource sr,
+                                     unsigned usage,
+                                     const struct pipe_box *box,
+                                     const void *data,
+                                     unsigned stride,
+                                     unsigned slice_stride)
 {
-       struct pipe_screen *pscreen = pipe->screen;
-       struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx;
-       struct nv04_surface *ns = (struct nv04_surface *)tx->surface;
-       struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture;
-       uint8_t *map = nouveau_screen_bo_map(pscreen, mt->base.bo,
-                                            nouveau_screen_transfer_flags(ptx->usage));
-
-       if(!tx->direct)
-               return map + ns->base.offset;
+       if(pr->target != PIPE_BUFFER)
+       {
+               u_default_transfer_inline_write(pipe, pr, sr, usage, box, data, stride, slice_stride);
+       }
        else
-               return (map + ns->base.offset + 
-                       ptx->box.y * ns->pitch + 
-                       ptx->box.x * util_format_get_blocksize(ptx->resource->format));
+       {
+               struct nvfx_buffer* buffer = nvfx_buffer(pr);
+               unsigned begin = util_format_get_stride(pr->format, box->x);
+               unsigned size = util_format_get_stride(pr->format, box->width);
+               memcpy(buffer->data + begin, data, size);
+               nvfx_buffer_dirty_interval(buffer, begin, size,
+                               !!(pr->flags & PIPE_TRANSFER_UNSYNCHRONIZED));
+       }
 }
 
 void
-nvfx_miptree_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *ptx)
+nvfx_init_transfer_functions(struct pipe_context *pipe)
 {
-       struct pipe_screen *pscreen = pipe->screen;
-       struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx;
-       struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture;
-
-       nouveau_screen_bo_unmap(pscreen, mt->base.bo);
+       pipe->get_transfer = nvfx_transfer_new;
+       pipe->transfer_map = nvfx_transfer_map;
+       pipe->transfer_flush_region = nvfx_transfer_flush_region;
+       pipe->transfer_unmap = nvfx_transfer_unmap;
+       pipe->transfer_destroy = nvfx_transfer_destroy;
+       pipe->transfer_inline_write = nvfx_transfer_inline_write;
 }
index 3e3317b2c7b46607122a06f950f85baa36f10f12..20f20d5b0b8b0e0ae106670282853d9f71b5cc0b 100644 (file)
@@ -7,19 +7,17 @@
 
 
 struct pipe_transfer *
-nvfx_miptree_transfer_new(struct pipe_context *pcontext,
+nvfx_transfer_new(struct pipe_context *pcontext,
                          struct pipe_resource *pt,
                          struct pipe_subresource sr,
                          unsigned usage,
                          const struct pipe_box *box);
-void
-nvfx_miptree_transfer_del(struct pipe_context *pcontext,
-                         struct pipe_transfer *ptx);
+
 void *
-nvfx_miptree_transfer_map(struct pipe_context *pcontext,
+nvfx_transfer_map(struct pipe_context *pcontext,
                          struct pipe_transfer *ptx);
 void
-nvfx_miptree_transfer_unmap(struct pipe_context *pcontext,
+nvfx_transfer_unmap(struct pipe_context *pcontext,
                            struct pipe_transfer *ptx);
 
 
index 4aa37938425c0600a820a84c2a259133521b4ee7..e6e9a8f2e4019ea3907e69b172067e3551e0b893 100644 (file)
@@ -2,6 +2,7 @@
 #include "pipe/p_state.h"
 #include "util/u_inlines.h"
 #include "util/u_format.h"
+#include "translate/translate.h"
 
 #include "nvfx_context.h"
 #include "nvfx_state.h"
 #include "nouveau/nouveau_channel.h"
 #include "nouveau/nouveau_class.h"
 #include "nouveau/nouveau_pushbuf.h"
-#include "nouveau/nouveau_util.h"
 
-static INLINE int
-nvfx_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp)
+static inline unsigned
+util_guess_unique_indices_count(unsigned mode, unsigned indices)
 {
-       switch (pipe) {
-       case PIPE_FORMAT_R32_FLOAT:
-       case PIPE_FORMAT_R32G32_FLOAT:
-       case PIPE_FORMAT_R32G32B32_FLOAT:
-       case PIPE_FORMAT_R32G32B32A32_FLOAT:
-               *fmt = NV34TCL_VTXFMT_TYPE_FLOAT;
-               break;
-       case PIPE_FORMAT_R16_FLOAT:
-       case PIPE_FORMAT_R16G16_FLOAT:
-       case PIPE_FORMAT_R16G16B16_FLOAT:
-       case PIPE_FORMAT_R16G16B16A16_FLOAT:
-               *fmt = NV34TCL_VTXFMT_TYPE_HALF;
-               break;
-       case PIPE_FORMAT_R8_UNORM:
-       case PIPE_FORMAT_R8G8_UNORM:
-       case PIPE_FORMAT_R8G8B8_UNORM:
-       case PIPE_FORMAT_R8G8B8A8_UNORM:
-               *fmt = NV34TCL_VTXFMT_TYPE_UBYTE;
-               break;
-       case PIPE_FORMAT_R16_SSCALED:
-       case PIPE_FORMAT_R16G16_SSCALED:
-       case PIPE_FORMAT_R16G16B16_SSCALED:
-       case PIPE_FORMAT_R16G16B16A16_SSCALED:
-               *fmt = NV34TCL_VTXFMT_TYPE_USHORT;
-               break;
-       default:
-               NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe));
-               return 1;
+       /* Euler's formula gives V =
+        * = E - F + 2 =
+        * = F * (polygon_edges / 2 - 1) + 2 =
+        * =  F * (polygon_edges - 2) / 2 + 2 =
+        * =  indices * (polygon_edges - 2) / (2 * indices_per_face) + 2
+        * =  indices * (1 / 2 - 1 / polygon_edges) + 2
+        */
+       switch(mode)
+       {
+       case PIPE_PRIM_LINES:
+               return indices >> 1;
+       case PIPE_PRIM_TRIANGLES:
+       {
+               // avoid an expensive division by 3 using the multiplicative inverse mod 2^32
+               unsigned q;
+               unsigned inv3 = 2863311531;
+               indices >>= 1;
+               q = indices * inv3;
+               if(unlikely(q >= indices))
+               {
+                       q += inv3;
+                       if(q >= indices)
+                               q += inv3;
+               }
+               return indices + 2;
+               //return indices / 6 + 2;
        }
-
-       switch (pipe) {
-       case PIPE_FORMAT_R8_UNORM:
-       case PIPE_FORMAT_R32_FLOAT:
-       case PIPE_FORMAT_R16_FLOAT:
-       case PIPE_FORMAT_R16_SSCALED:
-               *ncomp = 1;
-               break;
-       case PIPE_FORMAT_R8G8_UNORM:
-       case PIPE_FORMAT_R32G32_FLOAT:
-       case PIPE_FORMAT_R16G16_FLOAT:
-       case PIPE_FORMAT_R16G16_SSCALED:
-               *ncomp = 2;
-               break;
-       case PIPE_FORMAT_R8G8B8_UNORM:
-       case PIPE_FORMAT_R32G32B32_FLOAT:
-       case PIPE_FORMAT_R16G16B16_FLOAT:
-       case PIPE_FORMAT_R16G16B16_SSCALED:
-               *ncomp = 3;
-               break;
-       case PIPE_FORMAT_R8G8B8A8_UNORM:
-       case PIPE_FORMAT_R32G32B32A32_FLOAT:
-       case PIPE_FORMAT_R16G16B16A16_FLOAT:
-       case PIPE_FORMAT_R16G16B16A16_SSCALED:
-               *ncomp = 4;
-               break;
+       // guess that indexed quads are created by successive connections, since a closed mesh seems unlikely
+       case PIPE_PRIM_QUADS:
+               return (indices >> 1) + 2;
+       //      return (indices >> 2) + 2; // if it is a closed mesh
        default:
-               NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe));
-               return 1;
+               return indices;
        }
-
-       return 0;
 }
 
-static boolean
-nvfx_vbo_set_idxbuf(struct nvfx_context *nvfx, struct pipe_resource *ib,
-                   unsigned ib_size)
+static unsigned nvfx_decide_upload_mode(struct pipe_context *pipe, const struct pipe_draw_info *info)
 {
-       unsigned type;
-
-       if (!ib) {
-               nvfx->idxbuf_buffer = NULL;
-               nvfx->idxbuf_format = 0xdeadbeef;
-               return FALSE;
+       struct nvfx_context* nvfx = nvfx_context(pipe);
+       unsigned hardware_cost = 0;
+       unsigned inline_cost = 0;
+       unsigned unique_vertices;
+       unsigned upload_mode;
+       float best_index_cost_for_hardware_vertices_as_inline_cost;
+       boolean prefer_hardware_indices;
+       unsigned index_inline_cost;
+       unsigned index_hardware_cost;
+       if (info->indexed)
+               unique_vertices = util_guess_unique_indices_count(info->mode, info->count);
+       else
+               unique_vertices = info->count;
+
+       /* Here we try to figure out if we are better off writing vertex data directly on the FIFO,
+        * or create hardware buffer objects and pointing the hardware to them.
+        *
+        * This is done by computing the total memcpy cost of each option, ignoring uploads
+        * if we think that the buffer is static and thus the upload cost will be amortized over
+        * future draw calls.
+        *
+        * For instance, if everything looks static, we will always create buffer objects, while if
+        * everything is a user buffer and we are not doing indexed drawing, we never do.
+        *
+        * Other interesting cases are where a small user vertex buffer, but a huge user index buffer,
+        * where we will upload the vertex buffer, so that we can use hardware index lookup, and
+        * the opposite case, where we instead do index lookup in software to avoid uploading
+        * a huge amount of vertex data that is not going to be used.
+        *
+        * Otherwise, we generally move to the GPU the after it has been pushed
+        * NVFX_STATIC_BUFFER_MIN_REUSE_TIMES times to the GPU without having
+        * been updated with a transfer (or just the buffer having been destroyed).
+        *
+        * There is no special handling for user buffers, since applications can use
+        * OpenGL VBOs in a one-shot fashion. OpenGL 3/4 core profile forces this
+        * by the way.
+        *
+        * Note that currently we don't support only putting some data on the FIFO, and
+        * some on vertex buffers (constant and instanced data is independent from this).
+        *
+        * nVidia doesn't seem to do this either, even though it should be at least
+        * doable with VTX_ATTR and possibly with VERTEX_DATA too if not indexed.
+        */
+
+       for (unsigned i = 0; i < nvfx->vtxelt->num_per_vertex_buffer_infos; i++)
+       {
+               struct nvfx_per_vertex_buffer_info* vbi = &nvfx->vtxelt->per_vertex_buffer_info[i];
+               struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[vbi->vertex_buffer_index];
+               struct nvfx_buffer* buffer = nvfx_buffer(vb->buffer);
+               buffer->bytes_to_draw_until_static -= vbi->per_vertex_size * unique_vertices;
+               if (!nvfx_buffer_seems_static(buffer))
+               {
+                       hardware_cost += buffer->dirty_end - buffer->dirty_begin;
+                       if (!buffer->base.bo)
+                               hardware_cost += nvfx->screen->buffer_allocation_cost;
+               }
+               inline_cost += vbi->per_vertex_size * info->count;
        }
 
-       if (!nvfx->screen->index_buffer_reloc_flags || ib_size == 1)
-               return FALSE;
+       best_index_cost_for_hardware_vertices_as_inline_cost = 0.0f;
+       prefer_hardware_indices = FALSE;
+       index_inline_cost = 0;
+       index_hardware_cost = 0;
 
-       switch (ib_size) {
-       case 2:
-               type = NV34TCL_IDXBUF_FORMAT_TYPE_U16;
-               break;
-       case 4:
-               type = NV34TCL_IDXBUF_FORMAT_TYPE_U32;
-               break;
-       default:
-               return FALSE;
-       }
+       if (info->indexed)
+       {
+               index_inline_cost = nvfx->idxbuf.index_size * info->count;
+               if (nvfx->screen->index_buffer_reloc_flags
+                       && (nvfx->idxbuf.index_size == 2 || nvfx->idxbuf.index_size == 4)
+                       && !(nvfx->idxbuf.offset & (nvfx->idxbuf.index_size - 1)))
+               {
+                       struct nvfx_buffer* buffer = nvfx_buffer(nvfx->idxbuf.buffer);
+                       buffer->bytes_to_draw_until_static -= index_inline_cost;
 
-       if (ib != nvfx->idxbuf_buffer ||
-           type != nvfx->idxbuf_format) {
-               nvfx->dirty |= NVFX_NEW_ARRAYS;
-               nvfx->idxbuf_buffer = ib;
-               nvfx->idxbuf_format = type;
-       }
+                       prefer_hardware_indices = TRUE;
 
-       return TRUE;
-}
+                       if (!nvfx_buffer_seems_static(buffer))
+                       {
+                               index_hardware_cost = buffer->dirty_end - buffer->dirty_begin;
+                               if (!buffer->base.bo)
+                                       index_hardware_cost += nvfx->screen->buffer_allocation_cost;
+                       }
 
-// type must be floating point
-static inline void
-nvfx_vbo_static_attrib(struct nvfx_context *nvfx,
-                      int attrib, struct pipe_vertex_element *ve,
-                      struct pipe_vertex_buffer *vb, unsigned ncomp)
-{
-       struct pipe_transfer *transfer;
-       struct nouveau_channel* chan = nvfx->screen->base.channel;
-       void *map;
-       float *v;
-
-       map  = pipe_buffer_map(&nvfx->pipe, vb->buffer, PIPE_TRANSFER_READ, &transfer);
-       map = (uint8_t *) map + vb->buffer_offset + ve->src_offset;
-
-       v = map;
-
-       switch (ncomp) {
-       case 4:
-               OUT_RING(chan, RING_3D(NV34TCL_VTX_ATTR_4F_X(attrib), 4));
-               OUT_RING(chan, fui(v[0]));
-               OUT_RING(chan, fui(v[1]));
-               OUT_RING(chan,  fui(v[2]));
-               OUT_RING(chan,  fui(v[3]));
-               break;
-       case 3:
-               OUT_RING(chan, RING_3D(NV34TCL_VTX_ATTR_3F_X(attrib), 3));
-               OUT_RING(chan,  fui(v[0]));
-               OUT_RING(chan,  fui(v[1]));
-               OUT_RING(chan,  fui(v[2]));
-               break;
-       case 2:
-               OUT_RING(chan, RING_3D(NV34TCL_VTX_ATTR_2F_X(attrib), 2));
-               OUT_RING(chan,  fui(v[0]));
-               OUT_RING(chan,  fui(v[1]));
-               break;
-       case 1:
-               OUT_RING(chan, RING_3D(NV34TCL_VTX_ATTR_1F(attrib), 1));
-               OUT_RING(chan,  fui(v[0]));
-               break;
+                       if ((float) index_inline_cost < (float) index_hardware_cost * nvfx->screen->inline_cost_per_hardware_cost)
+                       {
+                               best_index_cost_for_hardware_vertices_as_inline_cost = (float) index_inline_cost;
+                       }
+                       else
+                       {
+                               best_index_cost_for_hardware_vertices_as_inline_cost = (float) index_hardware_cost * nvfx->screen->inline_cost_per_hardware_cost;
+                               prefer_hardware_indices = TRUE;
+                       }
+               }
        }
 
-       pipe_buffer_unmap(&nvfx->pipe, vb->buffer, transfer);
+       /* let's finally figure out which of the 3 paths we want to take */
+       if ((float) (inline_cost + index_inline_cost) > ((float) hardware_cost * nvfx->screen->inline_cost_per_hardware_cost + best_index_cost_for_hardware_vertices_as_inline_cost))
+               upload_mode = 1 + prefer_hardware_indices;
+       else
+               upload_mode = 0;
+
+#ifdef DEBUG
+        if (unlikely(nvfx->screen->trace_draw))
+          {
+                  fprintf(stderr, "DRAW");
+                  if (info->indexed)
+                  {
+                          fprintf(stderr, "_IDX%u", nvfx->idxbuf.index_size);
+                          if (info->index_bias)
+                                  fprintf(stderr, " biased %u", info->index_bias);
+                          fprintf(stderr, " idxrange %u -> %u", info->min_index, info->max_index);
+                  }
+                  if (info->instance_count > 1)
+                          fprintf(stderr, " %u instances from %u", info->instance_count, info->indexed);
+                  fprintf(stderr, " start %u count %u prim %u", info->start, info->count, info->mode);
+                  if (!upload_mode)
+                          fprintf(stderr, " -> inline vertex data");
+                  else if (upload_mode == 2 || !info->indexed)
+                          fprintf(stderr, " -> buffer range");
+                  else
+                          fprintf(stderr, " -> inline indices");
+                  fprintf(stderr, " [ivtx %u hvtx %u iidx %u hidx %u bidx %f] <", inline_cost, hardware_cost, index_inline_cost, index_hardware_cost, best_index_cost_for_hardware_vertices_as_inline_cost);
+                  for (unsigned i = 0; i < nvfx->vtxelt->num_per_vertex_buffer_infos; ++i)
+                  {
+                          struct nvfx_per_vertex_buffer_info* vbi = &nvfx->vtxelt->per_vertex_buffer_info[i];
+                          struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[vbi->vertex_buffer_index];
+                          struct nvfx_buffer* buffer = nvfx_buffer(vb->buffer);
+                          if (i)
+                                  fprintf(stderr, ", ");
+                          fprintf(stderr, "%p%s left %Li", buffer, buffer->last_update_static ? " static" : "", buffer->bytes_to_draw_until_static);
+                  }
+                  fprintf(stderr, ">\n");
+          }
+#endif
+
+       return upload_mode;
 }
 
-static void
-nvfx_draw_arrays(struct pipe_context *pipe,
-                unsigned mode, unsigned start, unsigned count)
+void nvfx_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
 {
        struct nvfx_context *nvfx = nvfx_context(pipe);
-       struct nvfx_screen *screen = nvfx->screen;
-       struct nouveau_channel *chan = screen->base.channel;
-       unsigned restart = 0;
-
-       nvfx_vbo_set_idxbuf(nvfx, NULL, 0);
-       if (nvfx->screen->force_swtnl || !nvfx_state_validate(nvfx)) {
-               nvfx_draw_elements_swtnl(pipe, NULL, 0, 0,
-                                           mode, start, count);
-                return;
-       }
+       unsigned upload_mode = 0;
 
-       while (count) {
-               unsigned vc, nr, avail;
+       if (!nvfx->vtxelt->needs_translate)
+               upload_mode = nvfx_decide_upload_mode(pipe, info);
 
-               nvfx_state_emit(nvfx);
+       nvfx->use_index_buffer = upload_mode > 1;
 
-               avail = AVAIL_RING(chan);
-               avail -= 16 + (avail >> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
+       if ((upload_mode > 0) != nvfx->use_vertex_buffers)
+       {
+               nvfx->use_vertex_buffers = (upload_mode > 0);
+               nvfx->dirty |= NVFX_NEW_ARRAYS;
+               nvfx->draw_dirty |= NVFX_NEW_ARRAYS;
+       }
 
-               vc = nouveau_vbuf_split(avail, 6, 256,
-                                       mode, start, count, &restart);
-               if (!vc) {
-                       FIRE_RING(chan);
-                       continue;
+       if (upload_mode > 0)
+       {
+               for (unsigned i = 0; i < nvfx->vtxelt->num_per_vertex_buffer_infos; i++)
+               {
+                       struct nvfx_per_vertex_buffer_info* vbi = &nvfx->vtxelt->per_vertex_buffer_info[i];
+                       struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[vbi->vertex_buffer_index];
+                       nvfx_buffer_upload(nvfx_buffer(vb->buffer));
                }
 
-               OUT_RING(chan, RING_3D(NV34TCL_VERTEX_BEGIN_END, 1));
-               OUT_RING  (chan, nvgl_primitive(mode));
+               if (upload_mode > 1)
+               {
+                       nvfx_buffer_upload(nvfx_buffer(nvfx->idxbuf.buffer));
 
-               nr = (vc & 0xff);
-               if (nr) {
-                       OUT_RING(chan, RING_3D(NV34TCL_VB_VERTEX_BATCH, 1));
-                       OUT_RING  (chan, ((nr - 1) << 24) | start);
-                       start += nr;
+                       if (unlikely(info->index_bias != nvfx->base_vertex))
+                       {
+                               nvfx->base_vertex = info->index_bias;
+                               nvfx->dirty |= NVFX_NEW_ARRAYS;
+                       }
                }
-
-               nr = vc >> 8;
-               while (nr) {
-                       unsigned push = nr > 2047 ? 2047 : nr;
-
-                       nr -= push;
-
-                       OUT_RING(chan, RING_3D_NI(NV34TCL_VB_VERTEX_BATCH, push));
-                       while (push--) {
-                               OUT_RING(chan, ((0x100 - 1) << 24) | start);
-                               start += 0x100;
+               else
+               {
+                       if (unlikely(info->start < nvfx->base_vertex && nvfx->base_vertex))
+                       {
+                               nvfx->base_vertex = 0;
+                               nvfx->dirty |= NVFX_NEW_ARRAYS;
                        }
                }
-
-               OUT_RING(chan, RING_3D(NV34TCL_VERTEX_BEGIN_END, 1));
-               OUT_RING  (chan, 0);
-
-               count -= vc;
-               start = restart;
        }
 
-       pipe->flush(pipe, 0, NULL);
+       if (nvfx->screen->force_swtnl || !nvfx_state_validate(nvfx))
+               nvfx_draw_vbo_swtnl(pipe, info);
+       else
+               nvfx_push_vbo(pipe, info);
 }
 
-static INLINE void
-nvfx_draw_elements_u08(struct nvfx_context *nvfx, void *ib,
-                      unsigned mode, unsigned start, unsigned count)
+boolean
+nvfx_vbo_validate(struct nvfx_context *nvfx)
 {
-       struct nvfx_screen *screen = nvfx->screen;
-       struct nouveau_channel *chan = screen->base.channel;
+       struct nouveau_channel* chan = nvfx->screen->base.channel;
+       int i;
+       int elements = MAX2(nvfx->vtxelt->num_elements, nvfx->hw_vtxelt_nr);
+       unsigned vb_flags = nvfx->screen->vertex_buffer_reloc_flags | NOUVEAU_BO_RD;
 
-       while (count) {
-               uint8_t *elts = (uint8_t *)ib + start;
-               unsigned vc, push, restart = 0, avail;
+       if (!elements)
+               return TRUE;
 
-               nvfx_state_emit(nvfx);
+       MARK_RING(chan, (5 + 2) * 16 + 2 + 11, 16 + 2);
+       for(unsigned i = 0; i < nvfx->vtxelt->num_constant; ++i)
+       {
+               struct nvfx_low_frequency_element *ve = &nvfx->vtxelt->constant[i];
+               struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
+               struct nvfx_buffer* buffer = nvfx_buffer(vb->buffer);
+               float v[4];
+               ve->fetch_rgba_float(v, buffer->data + vb->buffer_offset + ve->src_offset, 0, 0);
+               nvfx_emit_vtx_attr(chan, ve->idx, v, ve->ncomp);
+       }
 
-               avail = AVAIL_RING(chan);
-               avail -= 16 + (avail >> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
 
-               vc = nouveau_vbuf_split(avail, 6, 2,
-                                       mode, start, count, &restart);
-               if (vc == 0) {
-                       FIRE_RING(chan);
-                       continue;
-               }
-               count -= vc;
+       OUT_RING(chan, RING_3D(NV34TCL_VTXFMT(0), elements));
+       if(nvfx->use_vertex_buffers)
+       {
+               unsigned idx = 0;
+               for (i = 0; i < nvfx->vtxelt->num_per_vertex; i++) {
+                       struct nvfx_per_vertex_element *ve = &nvfx->vtxelt->per_vertex[i];
+                       struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
 
-               OUT_RING(chan, RING_3D(NV34TCL_VERTEX_BEGIN_END, 1));
-               OUT_RING  (chan, nvgl_primitive(mode));
+                       if(idx != ve->idx)
+                       {
+                               assert(idx < ve->idx);
+                               OUT_RINGp(chan, &nvfx->vtxelt->vtxfmt[idx], ve->idx - idx);
+                               idx = ve->idx;
+                       }
 
-               if (vc & 1) {
-                       OUT_RING(chan, RING_3D(NV34TCL_VB_ELEMENT_U32, 1));
-                       OUT_RING  (chan, elts[0]);
-                       elts++; vc--;
+                       OUT_RING(chan, nvfx->vtxelt->vtxfmt[idx] | (vb->stride << NV34TCL_VTXFMT_STRIDE_SHIFT));
+                       ++idx;
                }
+               if(idx != nvfx->vtxelt->num_elements)
+                       OUT_RINGp(chan, &nvfx->vtxelt->vtxfmt[idx], nvfx->vtxelt->num_elements - idx);
+       }
+       else
+               OUT_RINGp(chan, nvfx->vtxelt->vtxfmt, nvfx->vtxelt->num_elements);
 
-               while (vc) {
-                       unsigned i;
-
-                       push = MIN2(vc, 2047 * 2);
-
-                       OUT_RING(chan, RING_3D_NI(NV34TCL_VB_ELEMENT_U16, push >> 1));
-                       for (i = 0; i < push; i+=2)
-                               OUT_RING(chan, (elts[i+1] << 16) | elts[i]);
+       for(i = nvfx->vtxelt->num_elements; i < elements; ++i)
+               OUT_RING(chan, NV34TCL_VTXFMT_TYPE_32_FLOAT);
 
-                       vc -= push;
-                       elts += push;
+       if(nvfx->is_nv4x) {
+               unsigned i;
+               /* seems to be some kind of cache flushing */
+               for(i = 0; i < 3; ++i) {
+                       OUT_RING(chan, RING_3D(0x1718, 1));
+                       OUT_RING(chan, 0);
                }
-
-               OUT_RING(chan, RING_3D(NV34TCL_VERTEX_BEGIN_END, 1));
-               OUT_RING  (chan, 0);
-
-               start = restart;
        }
-}
-
-static INLINE void
-nvfx_draw_elements_u16(struct nvfx_context *nvfx, void *ib,
-                      unsigned mode, unsigned start, unsigned count)
-{
-       struct nvfx_screen *screen = nvfx->screen;
-       struct nouveau_channel *chan = screen->base.channel;
-
-       while (count) {
-               uint16_t *elts = (uint16_t *)ib + start;
-               unsigned vc, push, restart = 0, avail;
-
-               nvfx_state_emit(nvfx);
-
-               avail = AVAIL_RING(chan);
-               avail -= 16 + (avail >> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
 
-               vc = nouveau_vbuf_split(avail, 6, 2,
-                                       mode, start, count, &restart);
-               if (vc == 0) {
-                       FIRE_RING(chan);
-                       continue;
-               }
-               count -= vc;
+       OUT_RING(chan, RING_3D(NV34TCL_VTXBUF_ADDRESS(0), elements));
+       if(nvfx->use_vertex_buffers)
+       {
+               unsigned idx = 0;
+               for (i = 0; i < nvfx->vtxelt->num_per_vertex; i++) {
+                       struct nvfx_per_vertex_element *ve = &nvfx->vtxelt->per_vertex[i];
+                       struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
+                       struct nouveau_bo* bo = nvfx_resource(vb->buffer)->bo;
 
-               OUT_RING(chan, RING_3D(NV34TCL_VERTEX_BEGIN_END, 1));
-               OUT_RING  (chan, nvgl_primitive(mode));
+                       for(; idx < ve->idx; ++idx)
+                               OUT_RING(chan, 0);
 
-               if (vc & 1) {
-                       OUT_RING(chan, RING_3D(NV34TCL_VB_ELEMENT_U32, 1));
-                       OUT_RING  (chan, elts[0]);
-                       elts++; vc--;
+                       OUT_RELOC(chan, bo,
+                                       vb->buffer_offset + ve->src_offset + nvfx->base_vertex * vb->stride,
+                                       vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
+                                       0, NV34TCL_VTXBUF_ADDRESS_DMA1);
+                       ++idx;
                }
 
-               while (vc) {
-                       unsigned i;
-
-                       push = MIN2(vc, 2047 * 2);
-
-                       OUT_RING(chan, RING_3D_NI(NV34TCL_VB_ELEMENT_U16, push >> 1));
-                       for (i = 0; i < push; i+=2)
-                               OUT_RING(chan, (elts[i+1] << 16) | elts[i]);
-
-                       vc -= push;
-                       elts += push;
-               }
+               for(; idx < elements; ++idx)
+                       OUT_RING(chan, 0);
+       }
+       else
+       {
+               for (i = 0; i < elements; i++)
+                       OUT_RING(chan, 0);
+       }
 
-               OUT_RING(chan, RING_3D(NV34TCL_VERTEX_BEGIN_END, 1));
-               OUT_RING  (chan, 0);
+       OUT_RING(chan, RING_3D(0x1710, 1));
+       OUT_RING(chan, 0);
 
-               start = restart;
-       }
+       nvfx->hw_vtxelt_nr = nvfx->vtxelt->num_elements;
+       nvfx->relocs_needed &=~ NVFX_RELOCATE_VTXBUF;
+       return TRUE;
 }
 
-static INLINE void
-nvfx_draw_elements_u32(struct nvfx_context *nvfx, void *ib,
-                      unsigned mode, unsigned start, unsigned count)
+void
+nvfx_vbo_relocate(struct nvfx_context *nvfx)
 {
-       struct nvfx_screen *screen = nvfx->screen;
-       struct nouveau_channel *chan = screen->base.channel;
-
-       while (count) {
-               uint32_t *elts = (uint32_t *)ib + start;
-               unsigned vc, push, restart = 0, avail;
-
-               nvfx_state_emit(nvfx);
-
-               avail = AVAIL_RING(chan);
-               avail -= 16 + (avail >> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
-
-               vc = nouveau_vbuf_split(avail, 5, 1,
-                                       mode, start, count, &restart);
-               if (vc == 0) {
-                       FIRE_RING(chan);
-                       continue;
-               }
-               count -= vc;
-
-               OUT_RING(chan, RING_3D(NV34TCL_VERTEX_BEGIN_END, 1));
-               OUT_RING  (chan, nvgl_primitive(mode));
-
-               while (vc) {
-                       push = MIN2(vc, 2047);
-
-                       OUT_RING(chan, RING_3D_NI(NV34TCL_VB_ELEMENT_U32, push));
-                       OUT_RINGp    (chan, elts, push);
+       struct nouveau_channel* chan;
+       unsigned vb_flags;
+       int i;
 
-                       vc -= push;
-                       elts += push;
-               }
+        if(!nvfx->use_vertex_buffers)
+                return;
 
-               OUT_RING(chan, RING_3D(NV34TCL_VERTEX_BEGIN_END, 1));
-               OUT_RING  (chan, 0);
+       chan = nvfx->screen->base.channel;
+       vb_flags = nvfx->screen->vertex_buffer_reloc_flags | NOUVEAU_BO_RD | NOUVEAU_BO_DUMMY;
 
-               start = restart;
+       MARK_RING(chan, 2 * 16 + 3, 2 * 16 + 3);
+        for (i = 0; i < nvfx->vtxelt->num_per_vertex; i++) {
+                struct nvfx_per_vertex_element *ve = &nvfx->vtxelt->per_vertex[i];
+                struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
+                struct nouveau_bo* bo = nvfx_resource(vb->buffer)->bo;
+
+                OUT_RELOC(chan, bo, RING_3D(NV34TCL_VTXBUF_ADDRESS(ve->idx), 1),
+                               vb_flags, 0, 0);
+                OUT_RELOC(chan, bo, vb->buffer_offset + ve->src_offset + nvfx->base_vertex * vb->stride,
+                               vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
+                               0, NV34TCL_VTXBUF_ADDRESS_DMA1);
        }
+        nvfx->relocs_needed &=~ NVFX_RELOCATE_VTXBUF;
 }
 
 static void
-nvfx_draw_elements_inline(struct pipe_context *pipe,
-                         struct pipe_resource *ib,
-                         unsigned ib_size, int ib_bias,
-                         unsigned mode, unsigned start, unsigned count)
+nvfx_idxbuf_emit(struct nvfx_context* nvfx, unsigned ib_flags)
 {
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-       struct pipe_transfer *transfer;
-       void *map;
-
-       map = pipe_buffer_map(pipe, ib, PIPE_TRANSFER_READ, &transfer);
-       if (!ib) {
-               NOUVEAU_ERR("failed mapping ib\n");
-               return;
-       }
+       struct nouveau_channel* chan = nvfx->screen->base.channel;
+       unsigned ib_format = (nvfx->idxbuf.index_size == 2) ? NV34TCL_IDXBUF_FORMAT_TYPE_U16 : NV34TCL_IDXBUF_FORMAT_TYPE_U32;
+       struct nouveau_bo* bo = nvfx_resource(nvfx->idxbuf.buffer)->bo;
+       ib_flags |= nvfx->screen->index_buffer_reloc_flags | NOUVEAU_BO_RD;
 
-       assert(ib_bias == 0);
-
-       switch (ib_size) {
-       case 1:
-               nvfx_draw_elements_u08(nvfx, map, mode, start, count);
-               break;
-       case 2:
-               nvfx_draw_elements_u16(nvfx, map, mode, start, count);
-               break;
-       case 4:
-               nvfx_draw_elements_u32(nvfx, map, mode, start, count);
-               break;
-       default:
-               NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size);
-               break;
-       }
+       assert(nvfx->screen->index_buffer_reloc_flags);
 
-       pipe_buffer_unmap(pipe, ib, transfer);
+       MARK_RING(chan, 3, 3);
+       if(ib_flags & NOUVEAU_BO_DUMMY)
+               OUT_RELOC(chan, bo, RING_3D(NV34TCL_IDXBUF_ADDRESS, 2), ib_flags, 0, 0);
+       else
+               OUT_RING(chan, RING_3D(NV34TCL_IDXBUF_ADDRESS, 2));
+       OUT_RELOC(chan, bo, nvfx->idxbuf.offset + 1, ib_flags | NOUVEAU_BO_LOW, 0, 0);
+       OUT_RELOC(chan, bo, ib_format, ib_flags | NOUVEAU_BO_OR,
+                       0, NV34TCL_IDXBUF_FORMAT_DMA1);
+       nvfx->relocs_needed &=~ NVFX_RELOCATE_IDXBUF;
 }
 
-static void
-nvfx_draw_elements_vbo(struct pipe_context *pipe,
-                      unsigned mode, unsigned start, unsigned count)
+void
+nvfx_idxbuf_validate(struct nvfx_context* nvfx)
 {
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-       struct nvfx_screen *screen = nvfx->screen;
-       struct nouveau_channel *chan = screen->base.channel;
-       unsigned restart = 0;
+       nvfx_idxbuf_emit(nvfx, 0);
+}
 
-       while (count) {
-               unsigned nr, vc, avail;
+void
+nvfx_idxbuf_relocate(struct nvfx_context* nvfx)
+{
+       nvfx_idxbuf_emit(nvfx, NOUVEAU_BO_DUMMY);
+}
 
-               nvfx_state_emit(nvfx);
+unsigned nvfx_vertex_formats[PIPE_FORMAT_COUNT] =
+{
+       [PIPE_FORMAT_R32_FLOAT] = NV34TCL_VTXFMT_TYPE_32_FLOAT,
+       [PIPE_FORMAT_R32G32_FLOAT] = NV34TCL_VTXFMT_TYPE_32_FLOAT,
+       [PIPE_FORMAT_R32G32B32A32_FLOAT] = NV34TCL_VTXFMT_TYPE_32_FLOAT,
+       [PIPE_FORMAT_R32G32B32_FLOAT] = NV34TCL_VTXFMT_TYPE_32_FLOAT,
+       [PIPE_FORMAT_R16_FLOAT] = NV34TCL_VTXFMT_TYPE_16_FLOAT,
+       [PIPE_FORMAT_R16G16_FLOAT] = NV34TCL_VTXFMT_TYPE_16_FLOAT,
+       [PIPE_FORMAT_R16G16B16_FLOAT] = NV34TCL_VTXFMT_TYPE_16_FLOAT,
+       [PIPE_FORMAT_R16G16B16A16_FLOAT] = NV34TCL_VTXFMT_TYPE_16_FLOAT,
+       [PIPE_FORMAT_R8_UNORM] = NV34TCL_VTXFMT_TYPE_8_UNORM,
+       [PIPE_FORMAT_R8G8_UNORM] = NV34TCL_VTXFMT_TYPE_8_UNORM,
+       [PIPE_FORMAT_R8G8B8_UNORM] = NV34TCL_VTXFMT_TYPE_8_UNORM,
+       [PIPE_FORMAT_R8G8B8A8_UNORM] = NV34TCL_VTXFMT_TYPE_8_UNORM,
+       [PIPE_FORMAT_R8G8B8A8_USCALED] = NV34TCL_VTXFMT_TYPE_8_USCALED,
+       [PIPE_FORMAT_R16_SNORM] = NV34TCL_VTXFMT_TYPE_16_SNORM,
+       [PIPE_FORMAT_R16G16_SNORM] = NV34TCL_VTXFMT_TYPE_16_SNORM,
+       [PIPE_FORMAT_R16G16B16_SNORM] = NV34TCL_VTXFMT_TYPE_16_SNORM,
+       [PIPE_FORMAT_R16G16B16A16_SNORM] = NV34TCL_VTXFMT_TYPE_16_SNORM,
+       [PIPE_FORMAT_R16_SSCALED] = NV34TCL_VTXFMT_TYPE_16_SSCALED,
+       [PIPE_FORMAT_R16G16_SSCALED] = NV34TCL_VTXFMT_TYPE_16_SSCALED,
+       [PIPE_FORMAT_R16G16B16_SSCALED] = NV34TCL_VTXFMT_TYPE_16_SSCALED,
+       [PIPE_FORMAT_R16G16B16A16_SSCALED] = NV34TCL_VTXFMT_TYPE_16_SSCALED,
+};
+
+static void *
+nvfx_vtxelts_state_create(struct pipe_context *pipe,
+                         unsigned num_elements,
+                         const struct pipe_vertex_element *elements)
+{
+       struct nvfx_vtxelt_state *cso = CALLOC_STRUCT(nvfx_vtxelt_state);
+       struct translate_key transkey;
+       unsigned per_vertex_size[16];
+       unsigned vb_compacted_index[16];
 
-               avail = AVAIL_RING(chan);
-               avail -= 16 + (avail >> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
+       if(num_elements > 16)
+       {
+               _debug_printf("Error: application attempted to use %u vertex elements, but only 16 are supported: ignoring the rest\n", num_elements);
+               num_elements = 16;
+       }
 
-               vc = nouveau_vbuf_split(avail, 6, 256,
-                                       mode, start, count, &restart);
-               if (!vc) {
-                       FIRE_RING(chan);
-                       continue;
-               }
+       memset(per_vertex_size, 0, sizeof(per_vertex_size));
+       memcpy(cso->pipe, elements, num_elements * sizeof(elements[0]));
+       cso->num_elements = num_elements;
+       cso->needs_translate = FALSE;
+
+       transkey.nr_elements = 0;
+       transkey.output_stride = 0;
+
+       for(unsigned i = 0; i < num_elements; ++i)
+        {
+               const struct pipe_vertex_element* ve = &elements[i];
+               if(!ve->instance_divisor)
+                        per_vertex_size[ve->vertex_buffer_index] += util_format_get_stride(ve->src_format, 1);
+        }
+
+        for(unsigned i = 0; i < 16; ++i)
+        {
+                if(per_vertex_size[i])
+                {
+                        unsigned idx = cso->num_per_vertex_buffer_infos++;
+                        cso->per_vertex_buffer_info[idx].vertex_buffer_index = i;
+                        cso->per_vertex_buffer_info[idx].per_vertex_size = per_vertex_size[i];
+                        vb_compacted_index[i] = idx;
+                }
+        }
+
+       for(unsigned i = 0; i < num_elements; ++i)
+       {
+               const struct pipe_vertex_element* ve = &elements[i];
+               unsigned type = nvfx_vertex_formats[ve->src_format];
+               unsigned ncomp = util_format_get_nr_components(ve->src_format);
 
-               OUT_RING(chan, RING_3D(NV34TCL_VERTEX_BEGIN_END, 1));
-               OUT_RING  (chan, nvgl_primitive(mode));
+               //if(ve->frequency != PIPE_ELEMENT_FREQUENCY_PER_VERTEX)
+               if(ve->instance_divisor)
+               {
+                       struct nvfx_low_frequency_element* lfve;
+                       cso->vtxfmt[i] = NV34TCL_VTXFMT_TYPE_32_FLOAT;
+
+                       //if(ve->frequency == PIPE_ELEMENT_FREQUENCY_CONSTANT)
+                       if(0)
+                               lfve = &cso->constant[cso->num_constant++];
+                       else
+                       {
+                               lfve = &cso->per_instance[cso->num_per_instance++].base;
+                               ((struct nvfx_per_instance_element*)lfve)->instance_divisor = ve->instance_divisor;
+                       }
 
-               nr = (vc & 0xff);
-               if (nr) {
-                       OUT_RING(chan, RING_3D(NV34TCL_VB_INDEX_BATCH, 1));
-                       OUT_RING  (chan, ((nr - 1) << 24) | start);
-                       start += nr;
+                        lfve->idx = i;
+                        lfve->vertex_buffer_index = ve->vertex_buffer_index;
+                        lfve->src_offset = ve->src_offset;
+                        lfve->fetch_rgba_float = util_format_description(ve->src_format)->fetch_rgba_float;
+                        lfve->ncomp = ncomp;
                }
-
-               nr = vc >> 8;
-               while (nr) {
-                       unsigned push = nr > 2047 ? 2047 : nr;
-
-                       nr -= push;
-
-                       OUT_RING(chan, RING_3D_NI(NV34TCL_VB_INDEX_BATCH, push));
-                       while (push--) {
-                               OUT_RING(chan, ((0x100 - 1) << 24) | start);
-                               start += 0x100;
+               else
+               {
+                       unsigned idx;
+
+                       idx = cso->num_per_vertex++;
+                       cso->per_vertex[idx].idx = i;
+                       cso->per_vertex[idx].vertex_buffer_index = ve->vertex_buffer_index;
+                       cso->per_vertex[idx].src_offset = ve->src_offset;
+
+                       idx = transkey.nr_elements++;
+                       transkey.element[idx].input_format = ve->src_format;
+                       transkey.element[idx].input_buffer = vb_compacted_index[ve->vertex_buffer_index];
+                       transkey.element[idx].input_offset = ve->src_offset;
+                       transkey.element[idx].instance_divisor = 0;
+                       transkey.element[idx].type = TRANSLATE_ELEMENT_NORMAL;
+                       if(type)
+                       {
+                               transkey.element[idx].output_format = ve->src_format;
+                               cso->vtxfmt[i] = (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | type;
+                       }
+                       else
+                       {
+                               unsigned float32[4] = {PIPE_FORMAT_R32_FLOAT, PIPE_FORMAT_R32G32_FLOAT, PIPE_FORMAT_R32G32B32_FLOAT, PIPE_FORMAT_R32G32B32A32_FLOAT};
+                               transkey.element[idx].output_format = float32[ncomp - 1];
+                               cso->needs_translate = TRUE;
+                               cso->vtxfmt[i] = (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | NV34TCL_VTXFMT_TYPE_32_FLOAT;
                        }
+                       transkey.element[idx].output_offset = transkey.output_stride;
+                       transkey.output_stride += (util_format_get_stride(transkey.element[idx].output_format, 1) + 3) & ~3;
                }
+       }
 
-               OUT_RING(chan, RING_3D(NV34TCL_VERTEX_BEGIN_END, 1));
-               OUT_RING  (chan, 0);
+       cso->translate = translate_create(&transkey);
+       cso->vertex_length = transkey.output_stride >> 2;
+       cso->max_vertices_per_packet = 2047 / cso->vertex_length;
 
-               count -= vc;
-               start = restart;
-       }
+       return (void *)cso;
 }
 
 static void
-nvfx_draw_elements(struct pipe_context *pipe,
-                  struct pipe_resource *indexBuffer,
-                  unsigned indexSize, int indexBias,
-                  unsigned mode, unsigned start, unsigned count)
+nvfx_vtxelts_state_delete(struct pipe_context *pipe, void *hwcso)
 {
-       struct nvfx_context *nvfx = nvfx_context(pipe);
-       boolean idxbuf;
-
-       idxbuf = nvfx_vbo_set_idxbuf(nvfx, indexBuffer, indexSize);
-       if (nvfx->screen->force_swtnl || !nvfx_state_validate(nvfx)) {
-               nvfx_draw_elements_swtnl(pipe,
-                                        indexBuffer, indexSize, indexBias,
-                                        mode, start, count);
-               return;
-       }
-
-       if (idxbuf) {
-               nvfx_draw_elements_vbo(pipe, mode, start, count);
-       } else {
-               nvfx_draw_elements_inline(pipe,
-                                         indexBuffer, indexSize, indexBias,
-                                         mode, start, count);
-       }
-
-       pipe->flush(pipe, 0, NULL);
+       FREE(hwcso);
 }
 
-void
-nvfx_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
+static void
+nvfx_vtxelts_state_bind(struct pipe_context *pipe, void *hwcso)
 {
        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);
-       }
+       nvfx->vtxelt = hwcso;
+       nvfx->use_vertex_buffers = -1;
+       nvfx->draw_dirty |= NVFX_NEW_ARRAYS;
 }
 
-boolean
-nvfx_vbo_validate(struct nvfx_context *nvfx)
+static void
+nvfx_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
+                       const struct pipe_vertex_buffer *vb)
 {
-       struct nouveau_channel* chan = nvfx->screen->base.channel;
-       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);
-       uint32_t vtxfmt[16];
-       unsigned vb_flags = nvfx->screen->vertex_buffer_reloc_flags | NOUVEAU_BO_RD;
-
-       if (!elements)
-               return TRUE;
-
-       nvfx->vbo_bo = 0;
-
-       MARK_RING(chan, (5 + 2) * 16 + 2 + 11, 16 + 2);
-       for (i = 0; i < nvfx->vtxelt->num_elements; i++) {
-               struct pipe_vertex_element *ve;
-               struct pipe_vertex_buffer *vb;
-               unsigned type, ncomp;
-
-               ve = &nvfx->vtxelt->pipe[i];
-               vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
-
-               if (nvfx_vbo_format_to_hw(ve->src_format, &type, &ncomp)) {
-                       MARK_UNDO(chan);
-                       nvfx->fallback_swtnl |= NVFX_NEW_ARRAYS;
-                       return FALSE;
-               }
+       struct nvfx_context *nvfx = nvfx_context(pipe);
 
-               if (!vb->stride && type == NV34TCL_VTXFMT_TYPE_FLOAT) {
-                       nvfx_vbo_static_attrib(nvfx, i, ve, vb, ncomp);
-                       vtxfmt[i] = type;
-               } else {
-                       vtxfmt[i] = ((vb->stride << NV34TCL_VTXFMT_STRIDE_SHIFT) |
-                               (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | type);
-                       nvfx->vbo_bo |= (1 << i);
-               }
+       for(unsigned i = 0; i < count; ++i)
+       {
+               pipe_resource_reference(&nvfx->vtxbuf[i].buffer, vb[i].buffer);
+               nvfx->vtxbuf[i].buffer_offset = vb[i].buffer_offset;
+               nvfx->vtxbuf[i].max_index = vb[i].max_index;
+               nvfx->vtxbuf[i].stride = vb[i].stride;
        }
 
-       for(; i < elements; ++i)
-               vtxfmt[i] = NV34TCL_VTXFMT_TYPE_FLOAT;
+       for(unsigned i = count; i < nvfx->vtxbuf_nr; ++i)
+               pipe_resource_reference(&nvfx->vtxbuf[i].buffer, 0);
 
-       OUT_RING(chan, RING_3D(NV34TCL_VTXFMT(0), elements));
-       OUT_RINGp(chan, vtxfmt, elements);
-
-       if(nvfx->is_nv4x) {
-               unsigned i;
-               /* seems to be some kind of cache flushing */
-               for(i = 0; i < 3; ++i) {
-                       OUT_RING(chan, RING_3D(0x1718, 1));
-                       OUT_RING(chan, 0);
-               }
-       }
-
-       OUT_RING(chan, RING_3D(NV34TCL_VTXBUF_ADDRESS(0), elements));
-       for (i = 0; i < nvfx->vtxelt->num_elements; i++) {
-               struct pipe_vertex_element *ve;
-               struct pipe_vertex_buffer *vb;
+       nvfx->vtxbuf_nr = count;
+       nvfx->use_vertex_buffers = -1;
+       nvfx->draw_dirty |= NVFX_NEW_ARRAYS;
+}
 
-               ve = &nvfx->vtxelt->pipe[i];
-               vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
+static void
+nvfx_set_index_buffer(struct pipe_context *pipe,
+                     const struct pipe_index_buffer *ib)
+{
+       struct nvfx_context *nvfx = nvfx_context(pipe);
 
-               if (!(nvfx->vbo_bo & (1 << i)))
-                       OUT_RING(chan, 0);
-               else
-               {
-                       struct nouveau_bo* bo = nvfx_resource(vb->buffer)->bo;
-                       OUT_RELOC(chan, bo,
-                                vb->buffer_offset + ve->src_offset,
-                                vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
-                                0, NV34TCL_VTXBUF_ADDRESS_DMA1);
-               }
+       if(ib)
+       {
+               pipe_resource_reference(&nvfx->idxbuf.buffer, ib->buffer);
+               nvfx->idxbuf.index_size = ib->index_size;
+               nvfx->idxbuf.offset = ib->offset;
        }
-
-        for (; i < elements; i++)
-               OUT_RING(chan, 0);
-
-       OUT_RING(chan, RING_3D(0x1710, 1));
-       OUT_RING(chan, 0);
-
-       if (ib) {
-               unsigned ib_flags = nvfx->screen->index_buffer_reloc_flags | NOUVEAU_BO_RD;
-               struct nouveau_bo* bo = nvfx_resource(ib)->bo;
-
-               assert(nvfx->screen->index_buffer_reloc_flags);
-
-               OUT_RING(chan, RING_3D(NV34TCL_IDXBUF_ADDRESS, 2));
-               OUT_RELOC(chan, bo, 0, ib_flags | NOUVEAU_BO_LOW, 0, 0);
-               OUT_RELOC(chan, bo, ib_format, ib_flags | NOUVEAU_BO_OR,
-                                 0, NV34TCL_IDXBUF_FORMAT_DMA1);
+       else
+       {
+               pipe_resource_reference(&nvfx->idxbuf.buffer, 0);
+               nvfx->idxbuf.index_size = 0;
+               nvfx->idxbuf.offset = 0;
        }
 
-       nvfx->hw_vtxelt_nr = nvfx->vtxelt->num_elements;
-       return TRUE;
+       nvfx->dirty |= NVFX_NEW_INDEX;
+       nvfx->draw_dirty |= NVFX_NEW_INDEX;
 }
 
 void
-nvfx_vbo_relocate(struct nvfx_context *nvfx)
+nvfx_init_vbo_functions(struct nvfx_context *nvfx)
 {
-       struct nouveau_channel* chan = nvfx->screen->base.channel;
-       unsigned vb_flags = nvfx->screen->vertex_buffer_reloc_flags | NOUVEAU_BO_RD | NOUVEAU_BO_DUMMY;
-       int i;
+       nvfx->pipe.set_vertex_buffers = nvfx_set_vertex_buffers;
+       nvfx->pipe.set_index_buffer = nvfx_set_index_buffer;
 
-       MARK_RING(chan, 2 * 16 + 3, 2 * 16 + 3);
-       for(i = 0; i < nvfx->vtxelt->num_elements; ++i) {
-               if(nvfx->vbo_bo & (1 << i)) {
-                       struct pipe_vertex_element *ve = &nvfx->vtxelt->pipe[i];
-                       struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
-                       struct nouveau_bo* bo = nvfx_resource(vb->buffer)->bo;
-                       OUT_RELOC(chan, bo, RING_3D(NV34TCL_VTXBUF_ADDRESS(i), 1),
-                                       vb_flags, 0, 0);
-                       OUT_RELOC(chan, bo, vb->buffer_offset + ve->src_offset,
-                                       vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
-                                       0, NV34TCL_VTXBUF_ADDRESS_DMA1);
-               }
-       }
-
-       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_buffer)->bo;
-
-               assert(nvfx->screen->index_buffer_reloc_flags);
-
-               OUT_RELOC(chan, bo, RING_3D(NV34TCL_IDXBUF_ADDRESS, 2),
-                               ib_flags, 0, 0);
-               OUT_RELOC(chan, bo, 0,
-                               ib_flags | NOUVEAU_BO_LOW, 0, 0);
-               OUT_RELOC(chan, bo, nvfx->idxbuf_format,
-                               ib_flags | NOUVEAU_BO_OR,
-                               0, NV34TCL_IDXBUF_FORMAT_DMA1);
-       }
+       nvfx->pipe.create_vertex_elements_state = nvfx_vtxelts_state_create;
+       nvfx->pipe.delete_vertex_elements_state = nvfx_vtxelts_state_delete;
+       nvfx->pipe.bind_vertex_elements_state = nvfx_vtxelts_state_bind;
 }
index 24d9846310e001413d4519b98add36f7aaccf9dc..ea7e88c56138b17a88cbc0bb968f4eabe6032601 100644 (file)
@@ -1,15 +1,19 @@
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_state.h"
-#include "util/u_inlines.h"
+#include "util/u_linkage.h"
+#include "util/u_debug.h"
 
 #include "pipe/p_shader_tokens.h"
 #include "tgsi/tgsi_parse.h"
 #include "tgsi/tgsi_dump.h"
 #include "tgsi/tgsi_util.h"
 
+#include "draw/draw_context.h"
+
 #include "nvfx_context.h"
 #include "nvfx_state.h"
+#include "nvfx_resource.h"
 
 /* TODO (at least...):
  *  1. Indexed consts  + ARL
 #include "nv30_vertprog.h"
 #include "nv40_vertprog.h"
 
-#define NVFX_VP_INST_DEST_CLIP(n) ((~0 - 6) + (n))
+struct nvfx_loop_entry
+{
+       unsigned brk_target;
+       unsigned cont_target;
+};
 
 struct nvfx_vpc {
+       struct nvfx_context* nvfx;
        struct nvfx_vertex_program *vp;
 
        struct nvfx_vertex_program_exec *vpi;
 
        unsigned r_temps;
        unsigned r_temps_discard;
-       struct nvfx_sreg r_result[PIPE_MAX_SHADER_OUTPUTS];
-       struct nvfx_sreg *r_address;
-       struct nvfx_sreg *r_temp;
+       struct nvfx_reg r_result[PIPE_MAX_SHADER_OUTPUTS];
+       struct nvfx_reg *r_address;
+       struct nvfx_reg *r_temp;
 
-       struct nvfx_sreg *imm;
+       struct nvfx_reg *imm;
        unsigned nr_imm;
 
        unsigned hpos_idx;
+
+       struct util_dynarray label_relocs;
+       struct util_dynarray loop_stack;
 };
 
-static struct nvfx_sreg
+static struct nvfx_reg
 temp(struct nvfx_vpc *vpc)
 {
        int idx = ffs(~vpc->r_temps) - 1;
@@ -52,22 +64,22 @@ temp(struct nvfx_vpc *vpc)
        if (idx < 0) {
                NOUVEAU_ERR("out of temps!!\n");
                assert(0);
-               return nvfx_sr(NVFXSR_TEMP, 0);
+               return nvfx_reg(NVFXSR_TEMP, 0);
        }
 
        vpc->r_temps |= (1 << idx);
        vpc->r_temps_discard |= (1 << idx);
-       return nvfx_sr(NVFXSR_TEMP, idx);
+       return nvfx_reg(NVFXSR_TEMP, idx);
 }
 
-static INLINE void
+static inline void
 release_temps(struct nvfx_vpc *vpc)
 {
        vpc->r_temps &= ~vpc->r_temps_discard;
        vpc->r_temps_discard = 0;
 }
 
-static struct nvfx_sreg
+static struct nvfx_reg
 constant(struct nvfx_vpc *vpc, int pipe, float x, float y, float z, float w)
 {
        struct nvfx_vertex_program *vp = vpc->vp;
@@ -77,7 +89,7 @@ constant(struct nvfx_vpc *vpc, int pipe, float x, float y, float z, float w)
        if (pipe >= 0) {
                for (idx = 0; idx < vp->nr_consts; idx++) {
                        if (vp->consts[idx].index == pipe)
-                               return nvfx_sr(NVFXSR_CONST, idx);
+                               return nvfx_reg(NVFXSR_CONST, idx);
                }
        }
 
@@ -90,35 +102,36 @@ constant(struct nvfx_vpc *vpc, int pipe, float x, float y, float z, float w)
        vpd->value[1] = y;
        vpd->value[2] = z;
        vpd->value[3] = w;
-       return nvfx_sr(NVFXSR_CONST, idx);
+       return nvfx_reg(NVFXSR_CONST, idx);
 }
 
-#define arith(cc,s,o,d,m,s0,s1,s2) \
-       nvfx_vp_arith(nvfx, (cc), NVFX_VP_INST_SLOT_##s, NVFX_VP_INST_##s##_OP_##o, (d), (m), (s0), (s1), (s2))
+#define arith(s,o,d,m,s0,s1,s2) \
+       nvfx_insn(0, (NVFX_VP_INST_SLOT_##s << 7) | NVFX_VP_INST_##s##_OP_##o, -1, (d), (m), (s0), (s1), (s2))
 
 static void
-emit_src(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, uint32_t *hw, int pos, struct nvfx_sreg src)
+emit_src(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, uint32_t *hw, int pos, struct nvfx_src src)
 {
        struct nvfx_vertex_program *vp = vpc->vp;
        uint32_t sr = 0;
+       struct nvfx_relocation reloc;
 
-       switch (src.type) {
+       switch (src.reg.type) {
        case NVFXSR_TEMP:
                sr |= (NVFX_VP(SRC_REG_TYPE_TEMP) << NVFX_VP(SRC_REG_TYPE_SHIFT));
-               sr |= (src.index << NVFX_VP(SRC_TEMP_SRC_SHIFT));
+               sr |= (src.reg.index << NVFX_VP(SRC_TEMP_SRC_SHIFT));
                break;
        case NVFXSR_INPUT:
                sr |= (NVFX_VP(SRC_REG_TYPE_INPUT) <<
                       NVFX_VP(SRC_REG_TYPE_SHIFT));
-               vp->ir |= (1 << src.index);
-               hw[1] |= (src.index << NVFX_VP(INST_INPUT_SRC_SHIFT));
+               vp->ir |= (1 << src.reg.index);
+               hw[1] |= (src.reg.index << NVFX_VP(INST_INPUT_SRC_SHIFT));
                break;
        case NVFXSR_CONST:
                sr |= (NVFX_VP(SRC_REG_TYPE_CONST) <<
                       NVFX_VP(SRC_REG_TYPE_SHIFT));
-               assert(vpc->vpi->const_index == -1 ||
-                      vpc->vpi->const_index == src.index);
-               vpc->vpi->const_index = src.index;
+               reloc.location = vp->nr_insns - 1;
+               reloc.target = src.reg.index;
+               util_dynarray_append(&vp->const_relocs, struct nvfx_relocation, reloc);
                break;
        case NVFXSR_NONE:
                sr |= (NVFX_VP(SRC_REG_TYPE_INPUT) <<
@@ -161,100 +174,67 @@ emit_src(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, uint32_t *hw, int pos,
 }
 
 static void
-emit_dst(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, uint32_t *hw, int slot, struct nvfx_sreg dst)
+emit_dst(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, uint32_t *hw, int slot, struct nvfx_reg dst)
 {
        struct nvfx_vertex_program *vp = vpc->vp;
 
        switch (dst.type) {
+       case NVFXSR_NONE:
+               if(!nvfx->is_nv4x)
+                       hw[0] |= NV30_VP_INST_DEST_TEMP_ID_MASK;
+               else {
+                       hw[3] |= NV40_VP_INST_DEST_MASK;
+                       if (slot == 0)
+                               hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK;
+                       else
+                               hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK;
+               }
+               break;
        case NVFXSR_TEMP:
                if(!nvfx->is_nv4x)
                        hw[0] |= (dst.index << NV30_VP_INST_DEST_TEMP_ID_SHIFT);
                else {
                        hw[3] |= NV40_VP_INST_DEST_MASK;
-                       if (slot == 0) {
-                               hw[0] |= (dst.index <<
-                                         NV40_VP_INST_VEC_DEST_TEMP_SHIFT);
-                       } else {
-                               hw[3] |= (dst.index <<
-                                         NV40_VP_INST_SCA_DEST_TEMP_SHIFT);
-                       }
+                       if (slot == 0)
+                               hw[0] |= (dst.index << NV40_VP_INST_VEC_DEST_TEMP_SHIFT);
+                       else
+                               hw[3] |= (dst.index << NV40_VP_INST_SCA_DEST_TEMP_SHIFT);
                }
                break;
        case NVFXSR_OUTPUT:
                /* TODO: this may be wrong because on nv30 COL0 and BFC0 are swapped */
-               switch (dst.index) {
-               case NVFX_VP_INST_DEST_CLIP(0):
-                       vp->or |= (1 << 6);
-                       vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0;
-                       dst.index = NVFX_VP(INST_DEST_FOGC);
-                       break;
-               case NVFX_VP_INST_DEST_CLIP(1):
-                       vp->or |= (1 << 7);
-                       vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1;
-                       dst.index = NVFX_VP(INST_DEST_FOGC);
-                       break;
-               case NVFX_VP_INST_DEST_CLIP(2):
-                       vp->or |= (1 << 8);
-                       vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2;
-                       dst.index = NVFX_VP(INST_DEST_FOGC);
-                       break;
-               case NVFX_VP_INST_DEST_CLIP(3):
-                       vp->or |= (1 << 9);
-                       vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE3;
-                       dst.index = NVFX_VP(INST_DEST_PSZ);
-                       break;
-               case NVFX_VP_INST_DEST_CLIP(4):
-                       vp->or |= (1 << 10);
-                       vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE4;
-                       dst.index = NVFX_VP(INST_DEST_PSZ);
-                       break;
-               case NVFX_VP_INST_DEST_CLIP(5):
-                       vp->or |= (1 << 11);
-                       vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE5;
-                       dst.index = NVFX_VP(INST_DEST_PSZ);
-                       break;
-               default:
-                       if(!nvfx->is_nv4x) {
-                               switch (dst.index) {
-                               case NV30_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break;
-                               case NV30_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break;
-                               case NV30_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break;
-                               case NV30_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break;
-                               case NV30_VP_INST_DEST_FOGC: vp->or |= (1 << 4); break;
-                               case NV30_VP_INST_DEST_PSZ  : vp->or |= (1 << 5); break;
-                               case NV30_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break;
-                               case NV30_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break;
-                               case NV30_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break;
-                               case NV30_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break;
-                               case NV30_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break;
-                               case NV30_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break;
-                               case NV30_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break;
-                               case NV30_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break;
-                               }
-                       } else {
-                               switch (dst.index) {
-                               case NV40_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break;
-                               case NV40_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break;
-                               case NV40_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break;
-                               case NV40_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break;
-                               case NV40_VP_INST_DEST_FOGC: vp->or |= (1 << 4); break;
-                               case NV40_VP_INST_DEST_PSZ  : vp->or |= (1 << 5); break;
-                               case NV40_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break;
-                               case NV40_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break;
-                               case NV40_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break;
-                               case NV40_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break;
-                               case NV40_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break;
-                               case NV40_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break;
-                               case NV40_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break;
-                               case NV40_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break;
-                               }
+               if(nvfx->is_nv4x) {
+                       switch (dst.index) {
+                       case NV30_VP_INST_DEST_CLP(0):
+                               dst.index = NVFX_VP(INST_DEST_FOGC);
+                               break;
+                       case NV30_VP_INST_DEST_CLP(1):
+                               dst.index = NVFX_VP(INST_DEST_FOGC);
+                               break;
+                       case NV30_VP_INST_DEST_CLP(2):
+                               dst.index = NVFX_VP(INST_DEST_FOGC);
+                               break;
+                       case NV30_VP_INST_DEST_CLP(3):
+                               dst.index = NVFX_VP(INST_DEST_PSZ);
+                               break;
+                       case NV30_VP_INST_DEST_CLP(4):
+                               dst.index = NVFX_VP(INST_DEST_PSZ);
+                               break;
+                       case NV30_VP_INST_DEST_CLP(5):
+                               dst.index = NVFX_VP(INST_DEST_PSZ);
+                               break;
+                       case NV40_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break;
+                       case NV40_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break;
+                       case NV40_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break;
+                       case NV40_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break;
+                       case NV40_VP_INST_DEST_FOGC: vp->or |= (1 << 4); break;
+                       case NV40_VP_INST_DEST_PSZ  : vp->or |= (1 << 5); break;
                        }
-                       break;
                }
 
                if(!nvfx->is_nv4x) {
                        hw[3] |= (dst.index << NV30_VP_INST_DEST_SHIFT);
-                       hw[0] |= NV30_VP_INST_VEC_DEST_TEMP_MASK | (1<<20);
+                       hw[0] |= NV30_VP_INST_VEC_DEST_TEMP_MASK;
 
                        /*XXX: no way this is entirely correct, someone needs to
                         *     figure out what exactly it is.
@@ -264,7 +244,7 @@ emit_dst(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, uint32_t *hw, int slot
                        hw[3] |= (dst.index << NV40_VP_INST_DEST_SHIFT);
                        if (slot == 0) {
                                hw[0] |= NV40_VP_INST_VEC_RESULT;
-                               hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK | (1<<20);
+                               hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK;
                        } else {
                                hw[3] |= NV40_VP_INST_SCA_RESULT;
                                hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK;
@@ -277,26 +257,27 @@ emit_dst(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, uint32_t *hw, int slot
 }
 
 static void
-nvfx_vp_arith(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, int slot, int op,
-             struct nvfx_sreg dst, int mask,
-             struct nvfx_sreg s0, struct nvfx_sreg s1,
-             struct nvfx_sreg s2)
+nvfx_vp_emit(struct nvfx_vpc *vpc, struct nvfx_insn insn)
 {
+       struct nvfx_context* nvfx = vpc->nvfx;
        struct nvfx_vertex_program *vp = vpc->vp;
+       unsigned slot = insn.op >> 7;
+       unsigned op = insn.op & 0x7f;
        uint32_t *hw;
 
        vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi));
        vpc->vpi = &vp->insns[vp->nr_insns - 1];
        memset(vpc->vpi, 0, sizeof(*vpc->vpi));
-       vpc->vpi->const_index = -1;
 
        hw = vpc->vpi->data;
 
-       hw[0] |= (NVFX_COND_TR << NVFX_VP(INST_COND_SHIFT));
-       hw[0] |= ((0 << NVFX_VP(INST_COND_SWZ_X_SHIFT)) |
-                 (1 << NVFX_VP(INST_COND_SWZ_Y_SHIFT)) |
-                 (2 << NVFX_VP(INST_COND_SWZ_Z_SHIFT)) |
-                 (3 << NVFX_VP(INST_COND_SWZ_W_SHIFT)));
+       hw[0] |= (insn.cc_test << NVFX_VP(INST_COND_SHIFT));
+       hw[0] |= ((insn.cc_swz[0] << NVFX_VP(INST_COND_SWZ_X_SHIFT)) |
+                 (insn.cc_swz[1] << NVFX_VP(INST_COND_SWZ_Y_SHIFT)) |
+                 (insn.cc_swz[2] << NVFX_VP(INST_COND_SWZ_Z_SHIFT)) |
+                 (insn.cc_swz[3] << NVFX_VP(INST_COND_SWZ_W_SHIFT)));
+       if(insn.cc_update)
+               hw[0] |= NVFX_VP(INST_COND_UPDATE_ENABLE);
 
        if(!nvfx->is_nv4x) {
                if(slot == 0)
@@ -309,54 +290,56 @@ nvfx_vp_arith(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, int slot, int op,
 //             hw[3] |= NVFX_VP(INST_SCA_DEST_TEMP_MASK);
 //             hw[3] |= (mask << NVFX_VP(INST_VEC_WRITEMASK_SHIFT));
 
-               if (dst.type == NVFXSR_OUTPUT) {
+               if (insn.dst.type == NVFXSR_OUTPUT) {
                        if (slot)
-                               hw[3] |= (mask << NV30_VP_INST_SDEST_WRITEMASK_SHIFT);
+                               hw[3] |= (insn.mask << NV30_VP_INST_SDEST_WRITEMASK_SHIFT);
                        else
-                               hw[3] |= (mask << NV30_VP_INST_VDEST_WRITEMASK_SHIFT);
+                               hw[3] |= (insn.mask << NV30_VP_INST_VDEST_WRITEMASK_SHIFT);
                } else {
                        if (slot)
-                               hw[3] |= (mask << NV30_VP_INST_STEMP_WRITEMASK_SHIFT);
+                               hw[3] |= (insn.mask << NV30_VP_INST_STEMP_WRITEMASK_SHIFT);
                        else
-                               hw[3] |= (mask << NV30_VP_INST_VTEMP_WRITEMASK_SHIFT);
+                               hw[3] |= (insn.mask << NV30_VP_INST_VTEMP_WRITEMASK_SHIFT);
                }
         } else {
                if (slot == 0) {
                        hw[1] |= (op << NV40_VP_INST_VEC_OPCODE_SHIFT);
                        hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK;
-                       hw[3] |= (mask << NV40_VP_INST_VEC_WRITEMASK_SHIFT);
+                       hw[3] |= (insn.mask << NV40_VP_INST_VEC_WRITEMASK_SHIFT);
            } else {
                        hw[1] |= (op << NV40_VP_INST_SCA_OPCODE_SHIFT);
-                       hw[0] |= (NV40_VP_INST_VEC_DEST_TEMP_MASK | (1 << 20));
-                       hw[3] |= (mask << NV40_VP_INST_SCA_WRITEMASK_SHIFT);
+                       hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK ;
+                       hw[3] |= (insn.mask << NV40_VP_INST_SCA_WRITEMASK_SHIFT);
                }
        }
 
-       emit_dst(nvfx, vpc, hw, slot, dst);
-       emit_src(nvfx, vpc, hw, 0, s0);
-       emit_src(nvfx, vpc, hw, 1, s1);
-       emit_src(nvfx, vpc, hw, 2, s2);
+       emit_dst(nvfx, vpc, hw, slot, insn.dst);
+       emit_src(nvfx, vpc, hw, 0, insn.src[0]);
+       emit_src(nvfx, vpc, hw, 1, insn.src[1]);
+       emit_src(nvfx, vpc, hw, 2, insn.src[2]);
 }
 
-static INLINE struct nvfx_sreg
+static inline struct nvfx_src
 tgsi_src(struct nvfx_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
-       struct nvfx_sreg src = { 0 };
+       struct nvfx_src src;
 
        switch (fsrc->Register.File) {
        case TGSI_FILE_INPUT:
-               src = nvfx_sr(NVFXSR_INPUT, fsrc->Register.Index);
+               src.reg = nvfx_reg(NVFXSR_INPUT, fsrc->Register.Index);
                break;
        case TGSI_FILE_CONSTANT:
-               src = constant(vpc, fsrc->Register.Index, 0, 0, 0, 0);
+               src.reg = constant(vpc, fsrc->Register.Index, 0, 0, 0, 0);
                break;
        case TGSI_FILE_IMMEDIATE:
-               src = vpc->imm[fsrc->Register.Index];
+               src.reg = vpc->imm[fsrc->Register.Index];
                break;
        case TGSI_FILE_TEMPORARY:
-               src = vpc->r_temp[fsrc->Register.Index];
+               src.reg = vpc->r_temp[fsrc->Register.Index];
                break;
        default:
                NOUVEAU_ERR("bad src file\n");
+               src.reg.index = 0;
+               src.reg.type = 0;
                break;
        }
 
@@ -369,11 +352,14 @@ tgsi_src(struct nvfx_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
        return src;
 }
 
-static INLINE struct nvfx_sreg
+static INLINE struct nvfx_reg
 tgsi_dst(struct nvfx_vpc *vpc, const struct tgsi_full_dst_register *fdst) {
-       struct nvfx_sreg dst = { 0 };
+       struct nvfx_reg dst;
 
        switch (fdst->Register.File) {
+       case TGSI_FILE_NULL:
+               dst = nvfx_reg(NVFXSR_NONE, 0);
+               break;
        case TGSI_FILE_OUTPUT:
                dst = vpc->r_result[fdst->Register.Index];
                break;
@@ -384,14 +370,16 @@ tgsi_dst(struct nvfx_vpc *vpc, const struct tgsi_full_dst_register *fdst) {
                dst = vpc->r_address[fdst->Register.Index];
                break;
        default:
-               NOUVEAU_ERR("bad dst file\n");
+               NOUVEAU_ERR("bad dst file %i\n", fdst->Register.File);
+               dst.index = 0;
+               dst.type = 0;
                break;
        }
 
        return dst;
 }
 
-static INLINE int
+static inline int
 tgsi_mask(uint tgsi)
 {
        int mask = 0;
@@ -405,10 +393,14 @@ tgsi_mask(uint tgsi)
 
 static boolean
 nvfx_vertprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_vpc *vpc,
-                               const struct tgsi_full_instruction *finst)
+                               unsigned idx, const struct tgsi_full_instruction *finst)
 {
-       struct nvfx_sreg src[3], dst, tmp;
-       struct nvfx_sreg none = nvfx_sr(NVFXSR_NONE, 0);
+       struct nvfx_src src[3], tmp;
+       struct nvfx_reg dst;
+       struct nvfx_src none = nvfx_src(nvfx_reg(NVFXSR_NONE, 0));
+       struct nvfx_insn insn;
+       struct nvfx_relocation reloc;
+       struct nvfx_loop_entry loop;
        int mask;
        int ai = -1, ci = -1, ii = -1;
        int i;
@@ -436,9 +428,8 @@ nvfx_vertprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_vpc *vpc,
                                ai = fsrc->Register.Index;
                                src[i] = tgsi_src(vpc, fsrc);
                        } else {
-                               src[i] = temp(vpc);
-                               arith(vpc, VEC, MOV, src[i], NVFX_VP_MASK_ALL,
-                                     tgsi_src(vpc, fsrc), none, none);
+                               src[i] = nvfx_src(temp(vpc));
+                               nvfx_vp_emit(vpc, arith(VEC, MOV, src[i].reg, NVFX_VP_MASK_ALL, tgsi_src(vpc, fsrc), none, none));
                        }
                        break;
                case TGSI_FILE_CONSTANT:
@@ -447,9 +438,8 @@ nvfx_vertprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_vpc *vpc,
                                ci = fsrc->Register.Index;
                                src[i] = tgsi_src(vpc, fsrc);
                        } else {
-                               src[i] = temp(vpc);
-                               arith(vpc, VEC, MOV, src[i], NVFX_VP_MASK_ALL,
-                                     tgsi_src(vpc, fsrc), none, none);
+                               src[i] = nvfx_src(temp(vpc));
+                               nvfx_vp_emit(vpc, arith(VEC, MOV, src[i].reg, NVFX_VP_MASK_ALL, tgsi_src(vpc, fsrc), none, none));
                        }
                        break;
                case TGSI_FILE_IMMEDIATE:
@@ -458,9 +448,8 @@ nvfx_vertprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_vpc *vpc,
                                ii = fsrc->Register.Index;
                                src[i] = tgsi_src(vpc, fsrc);
                        } else {
-                               src[i] = temp(vpc);
-                               arith(vpc, VEC, MOV, src[i], NVFX_VP_MASK_ALL,
-                                     tgsi_src(vpc, fsrc), none, none);
+                               src[i] = nvfx_src(temp(vpc));
+                               nvfx_vp_emit(vpc, arith(VEC, MOV, src[i].reg, NVFX_VP_MASK_ALL, tgsi_src(vpc, fsrc), none, none));
                        }
                        break;
                case TGSI_FILE_TEMPORARY:
@@ -477,128 +466,231 @@ nvfx_vertprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_vpc *vpc,
 
        switch (finst->Instruction.Opcode) {
        case TGSI_OPCODE_ABS:
-               arith(vpc, VEC, MOV, dst, mask, abs(src[0]), none, none);
+               nvfx_vp_emit(vpc, arith(VEC, MOV, dst, mask, abs(src[0]), none, none));
                break;
        case TGSI_OPCODE_ADD:
-               arith(vpc, VEC, ADD, dst, mask, src[0], none, src[1]);
+               nvfx_vp_emit(vpc, arith(VEC, ADD, dst, mask, src[0], none, src[1]));
                break;
        case TGSI_OPCODE_ARL:
-               arith(vpc, VEC, ARL, dst, mask, src[0], none, none);
+               nvfx_vp_emit(vpc, arith(VEC, ARL, dst, mask, src[0], none, none));
+               break;
+       case TGSI_OPCODE_CMP:
+               insn = arith(VEC, MOV, none.reg, mask, src[0], none, none);
+               insn.cc_update = 1;
+               nvfx_vp_emit(vpc, insn);
+
+               insn = arith(VEC, MOV, dst, mask, src[2], none, none);
+               insn.cc_test = NVFX_COND_GE;
+               nvfx_vp_emit(vpc, insn);
+
+               insn = arith(VEC, MOV, dst, mask, src[1], none, none);
+               insn.cc_test = NVFX_COND_LT;
+               nvfx_vp_emit(vpc, insn);
                break;
        case TGSI_OPCODE_COS:
-               arith(vpc, SCA, COS, dst, mask, none, none, src[0]);
+               nvfx_vp_emit(vpc, arith(SCA, COS, dst, mask, none, none, src[0]));
                break;
+        case TGSI_OPCODE_DP2:
+                tmp = nvfx_src(temp(vpc));
+                nvfx_vp_emit(vpc, arith(VEC, MUL, tmp.reg, NVFX_VP_MASK_X | NVFX_VP_MASK_Y, src[0], src[1], none));
+                nvfx_vp_emit(vpc, arith(VEC, ADD, dst, mask, swz(tmp, X, X, X, X), swz(tmp, Y, Y, Y, Y), none));
+                break;
        case TGSI_OPCODE_DP3:
-               arith(vpc, VEC, DP3, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, DP3, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_DP4:
-               arith(vpc, VEC, DP4, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, DP4, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_DPH:
-               arith(vpc, VEC, DPH, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, DPH, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_DST:
-               arith(vpc, VEC, DST, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, DST, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_EX2:
-               arith(vpc, SCA, EX2, dst, mask, none, none, src[0]);
+               nvfx_vp_emit(vpc, arith(SCA, EX2, dst, mask, none, none, src[0]));
                break;
        case TGSI_OPCODE_EXP:
-               arith(vpc, SCA, EXP, dst, mask, none, none, src[0]);
+               nvfx_vp_emit(vpc, arith(SCA, EXP, dst, mask, none, none, src[0]));
                break;
        case TGSI_OPCODE_FLR:
-               arith(vpc, VEC, FLR, dst, mask, src[0], none, none);
+               nvfx_vp_emit(vpc, arith(VEC, FLR, dst, mask, src[0], none, none));
                break;
        case TGSI_OPCODE_FRC:
-               arith(vpc, VEC, FRC, dst, mask, src[0], none, none);
+               nvfx_vp_emit(vpc, arith(VEC, FRC, dst, mask, src[0], none, none));
                break;
        case TGSI_OPCODE_LG2:
-               arith(vpc, SCA, LG2, dst, mask, none, none, src[0]);
+               nvfx_vp_emit(vpc, arith(SCA, LG2, dst, mask, none, none, src[0]));
                break;
        case TGSI_OPCODE_LIT:
-               arith(vpc, SCA, LIT, dst, mask, none, none, src[0]);
+               nvfx_vp_emit(vpc, arith(SCA, LIT, dst, mask, none, none, src[0]));
                break;
        case TGSI_OPCODE_LOG:
-               arith(vpc, SCA, LOG, dst, mask, none, none, src[0]);
+               nvfx_vp_emit(vpc, arith(SCA, LOG, dst, mask, none, none, src[0]));
                break;
        case TGSI_OPCODE_LRP:
-               tmp = temp(vpc);
-               arith(vpc, VEC, MAD, tmp, mask, neg(src[0]), src[2], src[2]);
-               arith(vpc, VEC, MAD, dst, mask, src[0], src[1], tmp);
+               tmp = nvfx_src(temp(vpc));
+               nvfx_vp_emit(vpc, arith(VEC, MAD, tmp.reg, mask, neg(src[0]), src[2], src[2]));
+               nvfx_vp_emit(vpc, arith(VEC, MAD, dst, mask, src[0], src[1], tmp));
                break;
        case TGSI_OPCODE_MAD:
-               arith(vpc, VEC, MAD, dst, mask, src[0], src[1], src[2]);
+               nvfx_vp_emit(vpc, arith(VEC, MAD, dst, mask, src[0], src[1], src[2]));
                break;
        case TGSI_OPCODE_MAX:
-               arith(vpc, VEC, MAX, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, MAX, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_MIN:
-               arith(vpc, VEC, MIN, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, MIN, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_MOV:
-               arith(vpc, VEC, MOV, dst, mask, src[0], none, none);
+               nvfx_vp_emit(vpc, arith(VEC, MOV, dst, mask, src[0], none, none));
                break;
        case TGSI_OPCODE_MUL:
-               arith(vpc, VEC, MUL, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, MUL, dst, mask, src[0], src[1], none));
+               break;
+       case TGSI_OPCODE_NOP:
                break;
        case TGSI_OPCODE_POW:
-               tmp = temp(vpc);
-               arith(vpc, SCA, LG2, tmp, NVFX_VP_MASK_X, none, none,
-                     swz(src[0], X, X, X, X));
-               arith(vpc, VEC, MUL, tmp, NVFX_VP_MASK_X, swz(tmp, X, X, X, X),
-                     swz(src[1], X, X, X, X), none);
-               arith(vpc, SCA, EX2, dst, mask, none, none,
-                     swz(tmp, X, X, X, X));
+               tmp = nvfx_src(temp(vpc));
+               nvfx_vp_emit(vpc, arith(SCA, LG2, tmp.reg, NVFX_VP_MASK_X, none, none, swz(src[0], X, X, X, X)));
+               nvfx_vp_emit(vpc, arith(VEC, MUL, tmp.reg, NVFX_VP_MASK_X, swz(tmp, X, X, X, X), swz(src[1], X, X, X, X), none));
+               nvfx_vp_emit(vpc, arith(SCA, EX2, dst, mask, none, none, swz(tmp, X, X, X, X)));
                break;
        case TGSI_OPCODE_RCP:
-               arith(vpc, SCA, RCP, dst, mask, none, none, src[0]);
-               break;
-       case TGSI_OPCODE_RET:
+               nvfx_vp_emit(vpc, arith(SCA, RCP, dst, mask, none, none, src[0]));
                break;
        case TGSI_OPCODE_RSQ:
-               arith(vpc, SCA, RSQ, dst, mask, none, none, abs(src[0]));
+               nvfx_vp_emit(vpc, arith(SCA, RSQ, dst, mask, none, none, abs(src[0])));
                break;
        case TGSI_OPCODE_SEQ:
-               arith(vpc, VEC, SEQ, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, SEQ, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_SFL:
-               arith(vpc, VEC, SFL, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, SFL, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_SGE:
-               arith(vpc, VEC, SGE, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, SGE, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_SGT:
-               arith(vpc, VEC, SGT, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, SGT, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_SIN:
-               arith(vpc, SCA, SIN, dst, mask, none, none, src[0]);
+               nvfx_vp_emit(vpc, arith(SCA, SIN, dst, mask, none, none, src[0]));
                break;
        case TGSI_OPCODE_SLE:
-               arith(vpc, VEC, SLE, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, SLE, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_SLT:
-               arith(vpc, VEC, SLT, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, SLT, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_SNE:
-               arith(vpc, VEC, SNE, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, SNE, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_SSG:
-               arith(vpc, VEC, SSG, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, SSG, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_STR:
-               arith(vpc, VEC, STR, dst, mask, src[0], src[1], none);
+               nvfx_vp_emit(vpc, arith(VEC, STR, dst, mask, src[0], src[1], none));
                break;
        case TGSI_OPCODE_SUB:
-               arith(vpc, VEC, ADD, dst, mask, src[0], none, neg(src[1]));
+               nvfx_vp_emit(vpc, arith(VEC, ADD, dst, mask, src[0], none, neg(src[1])));
                break;
+        case TGSI_OPCODE_TRUNC:
+                tmp = nvfx_src(temp(vpc));
+                insn = arith(VEC, MOV, none.reg, mask, src[0], none, none);
+                insn.cc_update = 1;
+                nvfx_vp_emit(vpc, insn);
+
+                nvfx_vp_emit(vpc, arith(VEC, FLR, tmp.reg, mask, abs(src[0]), none, none));
+                nvfx_vp_emit(vpc, arith(VEC, MOV, dst, mask, tmp, none, none));
+
+                insn = arith(VEC, MOV, dst, mask, neg(tmp), none, none);
+                insn.cc_test = NVFX_COND_LT;
+                nvfx_vp_emit(vpc, insn);
+                break;
        case TGSI_OPCODE_XPD:
-               tmp = temp(vpc);
-               arith(vpc, VEC, MUL, tmp, mask,
-                     swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none);
-               arith(vpc, VEC, MAD, dst, (mask & ~NVFX_VP_MASK_W),
-                     swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y),
-                     neg(tmp));
+               tmp = nvfx_src(temp(vpc));
+               nvfx_vp_emit(vpc, arith(VEC, MUL, tmp.reg, mask, swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none));
+               nvfx_vp_emit(vpc, arith(VEC, MAD, dst, (mask & ~NVFX_VP_MASK_W), swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), neg(tmp)));
+               break;
+
+       case TGSI_OPCODE_IF:
+               insn = arith(VEC, MOV, none.reg, NVFX_VP_MASK_X, src[0], none, none);
+               insn.cc_update = 1;
+               nvfx_vp_emit(vpc, insn);
+
+               reloc.location = vpc->vp->nr_insns;
+               reloc.target = finst->Label.Label + 1;
+               util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
+
+               insn = arith(SCA, BRA, none.reg, 0, none, none, none);
+               insn.cc_test = NVFX_COND_EQ;
+               insn.cc_swz[0] = insn.cc_swz[1] = insn.cc_swz[2] = insn.cc_swz[3] = 0;
+               nvfx_vp_emit(vpc, insn);
                break;
+
+       case TGSI_OPCODE_ELSE:
+       case TGSI_OPCODE_BRA:
+       case TGSI_OPCODE_CAL:
+               reloc.location = vpc->vp->nr_insns;
+               reloc.target = finst->Label.Label;
+               util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
+
+               if(finst->Instruction.Opcode == TGSI_OPCODE_CAL)
+                       insn = arith(SCA, CAL, none.reg, 0, none, none, none);
+               else
+                       insn = arith(SCA, BRA, none.reg, 0, none, none, none);
+               nvfx_vp_emit(vpc, insn);
+               break;
+
+       case TGSI_OPCODE_RET:
+               tmp = none;
+               tmp.swz[0] = tmp.swz[1] = tmp.swz[2] = tmp.swz[3] = 0;
+               nvfx_vp_emit(vpc, arith(SCA, RET, none.reg, 0, none, none, tmp));
+               break;
+
+       case TGSI_OPCODE_BGNSUB:
+       case TGSI_OPCODE_ENDSUB:
+       case TGSI_OPCODE_ENDIF:
+               /* nothing to do here */
+               break;
+
+       case TGSI_OPCODE_BGNLOOP:
+               loop.cont_target = idx;
+               loop.brk_target = finst->Label.Label + 1;
+               util_dynarray_append(&vpc->loop_stack, struct nvfx_loop_entry, loop);
+               break;
+
+       case TGSI_OPCODE_ENDLOOP:
+               loop = util_dynarray_pop(&vpc->loop_stack, struct nvfx_loop_entry);
+
+               reloc.location = vpc->vp->nr_insns;
+               reloc.target = loop.cont_target;
+               util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
+
+               nvfx_vp_emit(vpc, arith(SCA, BRA, none.reg, 0, none, none, none));
+               break;
+
+       case TGSI_OPCODE_CONT:
+               loop = util_dynarray_top(&vpc->loop_stack, struct nvfx_loop_entry);
+
+               reloc.location = vpc->vp->nr_insns;
+               reloc.target = loop.cont_target;
+               util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
+
+               nvfx_vp_emit(vpc, arith(SCA, BRA, none.reg, 0, none, none, none));
+               break;
+
+       case TGSI_OPCODE_BRK:
+               loop = util_dynarray_top(&vpc->loop_stack, struct nvfx_loop_entry);
+
+               reloc.location = vpc->vp->nr_insns;
+               reloc.target = loop.brk_target;
+               util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
+
+               nvfx_vp_emit(vpc, arith(SCA, BRA, none.reg, 0, none, none, none));
+               break;
+
        default:
                NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
                return FALSE;
@@ -649,12 +741,8 @@ nvfx_vertprog_parse_decl_output(struct nvfx_context* nvfx, struct nvfx_vpc *vpc,
                hw = NVFX_VP(INST_DEST_PSZ);
                break;
        case TGSI_SEMANTIC_GENERIC:
-               if (fdec->Semantic.Index <= 7) {
-                       hw = NVFX_VP(INST_DEST_TC(fdec->Semantic.Index));
-               } else {
-                       NOUVEAU_ERR("bad generic semantic index\n");
-                       return FALSE;
-               }
+               hw = (vpc->vp->generic_to_fp_input[fdec->Semantic.Index] & 0xf)
+                       + NVFX_VP(INST_DEST_TC(0)) - NVFX_FP_OP_INPUT_SRC_TC(0);
                break;
        case TGSI_SEMANTIC_EDGEFLAG:
                /* not really an error just a fallback */
@@ -665,7 +753,7 @@ nvfx_vertprog_parse_decl_output(struct nvfx_context* nvfx, struct nvfx_vpc *vpc,
                return FALSE;
        }
 
-       vpc->r_result[idx] = nvfx_sr(NVFXSR_OUTPUT, hw);
+       vpc->r_result[idx] = nvfx_reg(NVFXSR_OUTPUT, hw);
        return TRUE;
 }
 
@@ -674,6 +762,36 @@ nvfx_vertprog_prepare(struct nvfx_context* nvfx, struct nvfx_vpc *vpc)
 {
        struct tgsi_parse_context p;
        int high_temp = -1, high_addr = -1, nr_imm = 0, i;
+       struct util_semantic_set set;
+       unsigned char sem_layout[8];
+       unsigned num_outputs;
+
+       num_outputs = util_semantic_set_from_program_file(&set, vpc->vp->pipe.tokens, TGSI_FILE_OUTPUT);
+
+       if(num_outputs > 8) {
+               NOUVEAU_ERR("too many vertex program outputs: %i\n", num_outputs);
+               return FALSE;
+       }
+       util_semantic_layout_from_set(sem_layout, &set, 8, 8);
+
+       /* hope 0xf is (0, 0, 0, 1) initialized; otherwise, we are _probably_ not required to do this */
+       memset(vpc->vp->generic_to_fp_input, 0x0f, sizeof(vpc->vp->generic_to_fp_input));
+       for(int i = 0; i < 8; ++i) {
+               if(sem_layout[i] == 0xff)
+                       continue;
+               //printf("vp: GENERIC[%i] to fpreg %i\n", sem_layout[i], NVFX_FP_OP_INPUT_SRC_TC(0) + i);
+               vpc->vp->generic_to_fp_input[sem_layout[i]] = 0xf0 | NVFX_FP_OP_INPUT_SRC_TC(i);
+       }
+
+       vpc->vp->sprite_fp_input = -1;
+       for(int i = 0; i < 8; ++i)
+       {
+               if(sem_layout[i] == 0xff)
+               {
+                       vpc->vp->sprite_fp_input = NVFX_FP_OP_INPUT_SRC_TC(i);
+                       break;
+               }
+       }
 
        tgsi_parse_init(&p, vpc->vp->pipe.tokens);
        while (!tgsi_parse_end_of_tokens(&p)) {
@@ -737,18 +855,18 @@ nvfx_vertprog_prepare(struct nvfx_context* nvfx, struct nvfx_vpc *vpc)
        tgsi_parse_free(&p);
 
        if (nr_imm) {
-               vpc->imm = CALLOC(nr_imm, sizeof(struct nvfx_sreg));
+               vpc->imm = CALLOC(nr_imm, sizeof(struct nvfx_reg));
                assert(vpc->imm);
        }
 
        if (++high_temp) {
-               vpc->r_temp = CALLOC(high_temp, sizeof(struct nvfx_sreg));
+               vpc->r_temp = CALLOC(high_temp, sizeof(struct nvfx_reg));
                for (i = 0; i < high_temp; i++)
                        vpc->r_temp[i] = temp(vpc);
        }
 
        if (++high_addr) {
-               vpc->r_address = CALLOC(high_addr, sizeof(struct nvfx_sreg));
+               vpc->r_address = CALLOC(high_addr, sizeof(struct nvfx_reg));
                for (i = 0; i < high_addr; i++)
                        vpc->r_address[i] = temp(vpc);
        }
@@ -757,20 +875,31 @@ nvfx_vertprog_prepare(struct nvfx_context* nvfx, struct nvfx_vpc *vpc)
        return TRUE;
 }
 
+DEBUG_GET_ONCE_BOOL_OPTION(nvfx_dump_vp, "NVFX_DUMP_VP", FALSE)
+
 static void
 nvfx_vertprog_translate(struct nvfx_context *nvfx,
                        struct nvfx_vertex_program *vp)
 {
        struct tgsi_parse_context parse;
        struct nvfx_vpc *vpc = NULL;
-       struct nvfx_sreg none = nvfx_sr(NVFXSR_NONE, 0);
+       struct nvfx_src none = nvfx_src(nvfx_reg(NVFXSR_NONE, 0));
+       struct util_dynarray insns;
        int i;
 
        vpc = CALLOC(1, sizeof(struct nvfx_vpc));
        if (!vpc)
                return;
+       vpc->nvfx = nvfx;
        vpc->vp = vp;
 
+       /* reserve space for ucps */
+       if(nvfx->use_vp_clipping)
+       {
+               for(i = 0; i < 6; ++i)
+                       constant(vpc, -1, 0, 0, 0, 0);
+       }
+
        if (!nvfx_vertprog_prepare(nvfx, vpc)) {
                FREE(vpc);
                return;
@@ -780,13 +909,15 @@ nvfx_vertprog_translate(struct nvfx_context *nvfx,
         * planes are enabled.  We need to append code to the vtxprog
         * to handle clip planes later.
         */
-       if (vp->ucp.nr)  {
+       /* TODO: maybe support patching this depending on whether there are ucps: not sure if it is really matters much */
+       if (nvfx->use_vp_clipping)  {
                vpc->r_result[vpc->hpos_idx] = temp(vpc);
                vpc->r_temps_discard = 0;
        }
 
        tgsi_parse_init(&parse, vp->pipe.tokens);
 
+       util_dynarray_init(&insns);
        while (!tgsi_parse_end_of_tokens(&parse)) {
                tgsi_parse_token(&parse);
 
@@ -809,8 +940,10 @@ nvfx_vertprog_translate(struct nvfx_context *nvfx,
                case TGSI_TOKEN_TYPE_INSTRUCTION:
                {
                        const struct tgsi_full_instruction *finst;
+                       unsigned idx = insns.size >> 2;
+                       util_dynarray_append(&insns, unsigned, vp->nr_insns);
                        finst = &parse.FullToken.FullInstruction;
-                       if (!nvfx_vertprog_parse_instruction(nvfx, vpc, finst))
+                       if (!nvfx_vertprog_parse_instruction(nvfx, vpc, idx, finst))
                                goto out_err;
                }
                        break;
@@ -819,43 +952,87 @@ nvfx_vertprog_translate(struct nvfx_context *nvfx,
                }
        }
 
+       util_dynarray_append(&insns, unsigned, vp->nr_insns);
+
+       for(unsigned i = 0; i < vpc->label_relocs.size; i += sizeof(struct nvfx_relocation))
+       {
+               struct nvfx_relocation* label_reloc = (struct nvfx_relocation*)((char*)vpc->label_relocs.data + i);
+               struct nvfx_relocation hw_reloc;
+
+               hw_reloc.location = label_reloc->location;
+               hw_reloc.target = ((unsigned*)insns.data)[label_reloc->target];
+
+               //debug_printf("hw %u -> tgsi %u = hw %u\n", hw_reloc.location, label_reloc->target, hw_reloc.target);
+
+               util_dynarray_append(&vp->branch_relocs, struct nvfx_relocation, hw_reloc);
+       }
+       util_dynarray_fini(&insns);
+       util_dynarray_trim(&vp->branch_relocs);
+
+       /* XXX: what if we add a RET before?!  make sure we jump here...*/
+
        /* Write out HPOS if it was redirected to a temp earlier */
        if (vpc->r_result[vpc->hpos_idx].type != NVFXSR_OUTPUT) {
-               struct nvfx_sreg hpos = nvfx_sr(NVFXSR_OUTPUT,
+               struct nvfx_reg hpos = nvfx_reg(NVFXSR_OUTPUT,
                                                NVFX_VP(INST_DEST_POS));
-               struct nvfx_sreg htmp = vpc->r_result[vpc->hpos_idx];
+               struct nvfx_src htmp = nvfx_src(vpc->r_result[vpc->hpos_idx]);
 
-               arith(vpc, VEC, MOV, hpos, NVFX_VP_MASK_ALL, htmp, none, none);
+               nvfx_vp_emit(vpc, arith(VEC, MOV, hpos, NVFX_VP_MASK_ALL, htmp, none, none));
        }
 
        /* Insert code to handle user clip planes */
-       for (i = 0; i < vp->ucp.nr; i++) {
-               struct nvfx_sreg cdst = nvfx_sr(NVFXSR_OUTPUT,
-                                               NVFX_VP_INST_DEST_CLIP(i));
-               struct nvfx_sreg ceqn = constant(vpc, -1,
-                                                nvfx->clip.ucp[i][0],
-                                                nvfx->clip.ucp[i][1],
-                                                nvfx->clip.ucp[i][2],
-                                                nvfx->clip.ucp[i][3]);
-               struct nvfx_sreg htmp = vpc->r_result[vpc->hpos_idx];
-               unsigned mask;
-
-               switch (i) {
-               case 0: case 3: mask = NVFX_VP_MASK_Y; break;
-               case 1: case 4: mask = NVFX_VP_MASK_Z; break;
-               case 2: case 5: mask = NVFX_VP_MASK_W; break;
-               default:
-                       NOUVEAU_ERR("invalid clip dist #%d\n", i);
-                       goto out_err;
+       if(nvfx->use_vp_clipping)
+       {
+               for (i = 0; i < 6; i++) {
+                       struct nvfx_reg cdst = nvfx_reg(NVFXSR_OUTPUT, NV30_VP_INST_DEST_CLP(i));
+                       struct nvfx_src ceqn = nvfx_src(nvfx_reg(NVFXSR_CONST, i));
+                       struct nvfx_src htmp = nvfx_src(vpc->r_result[vpc->hpos_idx]);
+                       unsigned mask;
+
+                       if(nvfx->is_nv4x)
+                       {
+                               switch (i) {
+                               case 0: case 3: mask = NVFX_VP_MASK_Y; break;
+                               case 1: case 4: mask = NVFX_VP_MASK_Z; break;
+                               case 2: case 5: mask = NVFX_VP_MASK_W; break;
+                               default:
+                                       NOUVEAU_ERR("invalid clip dist #%d\n", i);
+                                       goto out_err;
+                               }
+                       }
+                       else
+                               mask = NVFX_VP_MASK_X;
+
+                       nvfx_vp_emit(vpc, arith(VEC, DP4, cdst, mask, htmp, ceqn, none));
                }
+       }
+       else
+       {
+               if(vp->nr_insns)
+                       vp->insns[vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST;
 
-               arith(vpc, VEC, DP4, cdst, mask, htmp, ceqn, none);
+               nvfx_vp_emit(vpc, arith(VEC, NOP, none.reg, 0, none, none, none));
+               vp->insns[vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST;
        }
 
-       vp->insns[vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST;
+       if(debug_get_option_nvfx_dump_vp())
+       {
+               debug_printf("\n");
+               tgsi_dump(vp->pipe.tokens, 0);
+
+               debug_printf("\n%s vertex program:\n", nvfx->is_nv4x ? "nv4x" : "nv3x");
+               for (i = 0; i < vp->nr_insns; i++)
+                       debug_printf("%3u: %08x %08x %08x %08x\n", i, vp->insns[i].data[0], vp->insns[i].data[1], vp->insns[i].data[2], vp->insns[i].data[3]);
+               debug_printf("\n");
+       }
+
+       vp->clip_nr = -1;
+       vp->exec_start = -1;
        vp->translated = TRUE;
 out_err:
        tgsi_parse_free(&parse);
+       util_dynarray_fini(&vpc->label_relocs);
+       util_dynarray_fini(&vpc->loop_stack);
        if (vpc->r_temp)
                FREE(vpc->r_temp);
        if (vpc->r_address)
@@ -868,26 +1045,17 @@ out_err:
 boolean
 nvfx_vertprog_validate(struct nvfx_context *nvfx)
 {
-       struct pipe_context *pipe = &nvfx->pipe;
        struct nvfx_screen *screen = nvfx->screen;
        struct nouveau_channel *chan = screen->base.channel;
        struct nouveau_grobj *eng3d = screen->eng3d;
        struct nvfx_vertex_program *vp;
        struct pipe_resource *constbuf;
-       struct pipe_transfer *transfer = NULL;
        boolean upload_code = FALSE, upload_data = FALSE;
        int i;
 
        if (nvfx->render_mode == HW) {
                vp = nvfx->vertprog;
                constbuf = nvfx->constbuf[PIPE_SHADER_VERTEX];
-
-               // TODO: ouch! can't we just use constant slots for these?!
-               if ((nvfx->dirty & NVFX_NEW_UCP) ||
-                   memcmp(&nvfx->clip, &vp->ucp, sizeof(vp->ucp))) {
-                       nvfx_vertprog_destroy(nvfx, vp);
-                       memcpy(&vp->ucp, &nvfx->clip, sizeof(vp->ucp));
-               }
        } else {
                vp = nvfx->swtnl.vertprog;
                constbuf = NULL;
@@ -918,7 +1086,11 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
                        }
 
                        if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec))
-                               assert(0);
+                       {
+                               debug_printf("Vertex shader too long: %u instructions\n", vplen);
+                               nvfx->fallback_swtnl |= NVFX_NEW_VERTPROG;
+                               return FALSE;
+                       }
                }
 
                upload_code = TRUE;
@@ -937,7 +1109,11 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
                        }
 
                        if (nouveau_resource_alloc(heap, vp->nr_consts, vp, &vp->data))
-                               assert(0);
+                        {
+                                debug_printf("Vertex shader uses too many constants: %u constants\n", vp->nr_consts);
+                                nvfx->fallback_swtnl |= NVFX_NEW_VERTPROG;
+                                return FALSE;
+                        }
                }
 
                /*XXX: handle this some day */
@@ -952,44 +1128,57 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
         * fixup offsets and register IDs.
         */
        if (vp->exec_start != vp->exec->start) {
-               for (i = 0; i < vp->nr_insns; i++) {
-                       struct nvfx_vertex_program_exec *vpi = &vp->insns[i];
+               //printf("vp_relocs %u -> %u\n", vp->exec_start, vp->exec->start);
+               for(unsigned i = 0; i < vp->branch_relocs.size; i += sizeof(struct nvfx_relocation))
+               {
+                       struct nvfx_relocation* reloc = (struct nvfx_relocation*)((char*)vp->branch_relocs.data + i);
+                       uint32_t* hw = vp->insns[reloc->location].data;
+                       unsigned target = vp->exec->start + reloc->target;
+
+                       //debug_printf("vp_reloc hw %u -> hw %u\n", reloc->location, target);
 
-                       if (vpi->has_branch_offset) {
-                               assert(0);
+                       if(!nvfx->is_nv4x)
+                       {
+                               hw[2] &=~ NV30_VP_INST_IADDR_MASK;
+                               hw[2] |= (target & 0x1ff) << NV30_VP_INST_IADDR_SHIFT;
+                       }
+                       else
+                       {
+                               hw[3] &=~ NV40_VP_INST_IADDRL_MASK;
+                               hw[3] |= (target & 7) << NV40_VP_INST_IADDRL_SHIFT;
+
+                               hw[2] &=~ NV40_VP_INST_IADDRH_MASK;
+                               hw[2] |= ((target >> 3) & 0x3f) << NV40_VP_INST_IADDRH_SHIFT;
                        }
                }
 
                vp->exec_start = vp->exec->start;
        }
 
-       if (vp->nr_consts && vp->data_start != vp->data->start) {
-               for (i = 0; i < vp->nr_insns; i++) {
-                       struct nvfx_vertex_program_exec *vpi = &vp->insns[i];
+       if (vp->data_start != vp->data->start) {
+               for(unsigned i = 0; i < vp->const_relocs.size; i += sizeof(struct nvfx_relocation))
+               {
+                       struct nvfx_relocation* reloc = (struct nvfx_relocation*)((char*)vp->const_relocs.data + i);
+                       struct nvfx_vertex_program_exec *vpi = &vp->insns[reloc->location];
 
-                       if (vpi->const_index >= 0) {
-                               vpi->data[1] &= ~NVFX_VP(INST_CONST_SRC_MASK);
-                               vpi->data[1] |=
-                                       (vpi->const_index + vp->data->start) <<
+                       vpi->data[1] &= ~NVFX_VP(INST_CONST_SRC_MASK);
+                       vpi->data[1] |=
+                                       (reloc->target + vp->data->start) <<
                                        NVFX_VP(INST_CONST_SRC_SHIFT);
-
-                       }
                }
 
                vp->data_start = vp->data->start;
+               upload_code = TRUE;
        }
 
        /* Update + Upload constant values */
        if (vp->nr_consts) {
                float *map = NULL;
 
-               if (constbuf) {
-                       map = pipe_buffer_map(pipe, constbuf,
-                                             PIPE_TRANSFER_READ,
-                                             &transfer);
-               }
+               if (constbuf)
+                       map = (float*)nvfx_buffer(constbuf)->data;
 
-               for (i = 0; i < vp->nr_consts; i++) {
+               for (i = nvfx->use_vp_clipping ? 6 : 0; i < vp->nr_consts; i++) {
                        struct nvfx_vertex_program_data *vpd = &vp->consts[i];
 
                        if (vpd->index >= 0) {
@@ -1005,41 +1194,28 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
                        OUT_RING  (chan, i + vp->data->start);
                        OUT_RINGp (chan, (uint32_t *)vpd->value, 4);
                }
-
-               if (constbuf)
-                       pipe_buffer_unmap(pipe, constbuf, transfer);
        }
 
        /* Upload vtxprog */
        if (upload_code) {
-#if 0
-               for (i = 0; i < vp->nr_insns; i++) {
-                       NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[0]);
-                       NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[1]);
-                       NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[2]);
-                       NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[3]);
-               }
-#endif
                BEGIN_RING(chan, eng3d, NV34TCL_VP_UPLOAD_FROM_ID, 1);
                OUT_RING  (chan, vp->exec->start);
                for (i = 0; i < vp->nr_insns; i++) {
                        BEGIN_RING(chan, eng3d, NV34TCL_VP_UPLOAD_INST(0), 4);
                        OUT_RINGp (chan, vp->insns[i].data, 4);
                }
+               vp->clip_nr = -1;
        }
 
-       if(nvfx->dirty & (NVFX_NEW_VERTPROG | NVFX_NEW_UCP))
+       if(nvfx->dirty & (NVFX_NEW_VERTPROG))
        {
-               WAIT_RING(chan, 7);
+               WAIT_RING(chan, 6);
                OUT_RING(chan, RING_3D(NV34TCL_VP_START_FROM_ID, 1));
                OUT_RING(chan, vp->exec->start);
                if(nvfx->is_nv4x) {
-                       OUT_RING(chan, RING_3D(NV40TCL_VP_ATTRIB_EN, 2));
+                       OUT_RING(chan, RING_3D(NV40TCL_VP_ATTRIB_EN, 1));
                        OUT_RING(chan, vp->ir);
-                       OUT_RING(chan, vp->or);
                }
-               OUT_RING(chan, RING_3D(NV34TCL_VP_CLIP_PLANES_ENABLE, 1));
-               OUT_RING(chan, vp->clip_ctrl);
        }
 
        return TRUE;
@@ -1048,25 +1224,63 @@ nvfx_vertprog_validate(struct nvfx_context *nvfx)
 void
 nvfx_vertprog_destroy(struct nvfx_context *nvfx, struct nvfx_vertex_program *vp)
 {
-       vp->translated = FALSE;
-
-       if (vp->nr_insns) {
+       if (vp->nr_insns)
                FREE(vp->insns);
-               vp->insns = NULL;
-               vp->nr_insns = 0;
-       }
 
-       if (vp->nr_consts) {
+       if (vp->nr_consts)
                FREE(vp->consts);
-               vp->consts = NULL;
-               vp->nr_consts = 0;
-       }
 
        nouveau_resource_free(&vp->exec);
-       vp->exec_start = 0;
        nouveau_resource_free(&vp->data);
-       vp->data_start = 0;
-       vp->data_start_min = 0;
 
-       vp->ir = vp->or = vp->clip_ctrl = 0;
+       util_dynarray_fini(&vp->branch_relocs);
+       util_dynarray_fini(&vp->const_relocs);
+}
+
+static void *
+nvfx_vp_state_create(struct pipe_context *pipe,
+                     const struct pipe_shader_state *cso)
+{
+        struct nvfx_context *nvfx = nvfx_context(pipe);
+        struct nvfx_vertex_program *vp;
+
+        // TODO: use a 64-bit atomic here!
+        static unsigned long long id = 0;
+
+        vp = CALLOC(1, sizeof(struct nvfx_vertex_program));
+        vp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+        vp->draw = draw_create_vertex_shader(nvfx->draw, &vp->pipe);
+        vp->id = ++id;
+
+        return (void *)vp;
+}
+
+static void
+nvfx_vp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+        struct nvfx_context *nvfx = nvfx_context(pipe);
+
+        nvfx->vertprog = hwcso;
+        nvfx->dirty |= NVFX_NEW_VERTPROG;
+        nvfx->draw_dirty |= NVFX_NEW_VERTPROG;
+}
+
+static void
+nvfx_vp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+        struct nvfx_context *nvfx = nvfx_context(pipe);
+        struct nvfx_vertex_program *vp = hwcso;
+
+        draw_delete_vertex_shader(nvfx->draw, vp->draw);
+        nvfx_vertprog_destroy(nvfx, vp);
+        FREE((void*)vp->pipe.tokens);
+        FREE(vp);
+}
+
+void
+nvfx_init_vertprog_functions(struct nvfx_context *nvfx)
+{
+        nvfx->pipe.create_vs_state = nvfx_vp_state_create;
+        nvfx->pipe.bind_vs_state = nvfx_vp_state_bind;
+        nvfx->pipe.delete_vs_state = nvfx_vp_state_delete;
 }
index e8b6c4f7af8e90e78c580a082e1a31d97ee36726..624dadd07d78b4dc00768bcbf580c68ede548d39 100644 (file)
@@ -65,7 +65,7 @@ static void r300_release_referenced_objects(struct r300_context *r300)
     unsigned i;
 
     /* Framebuffer state. */
-    util_assign_framebuffer_state(fb, NULL);
+    util_unreference_framebuffer_state(fb);
 
     /* Textures. */
     for (i = 0; i < textures->sampler_view_count; i++)
@@ -99,8 +99,10 @@ static void r300_destroy_context(struct pipe_context* context)
     struct r300_context* r300 = r300_context(context);
     struct r300_atom *atom;
 
-    util_blitter_destroy(r300->blitter);
-    draw_destroy(r300->draw);
+    if (r300->blitter)
+        util_blitter_destroy(r300->blitter);
+    if (r300->draw)
+        draw_destroy(r300->draw);
 
     /* Print stats, if enabled. */
     if (SCREEN_DBG_ON(r300->screen, DBG_STATS)) {
@@ -112,40 +114,48 @@ static void r300_destroy_context(struct pipe_context* context)
         }
     }
 
-    u_upload_destroy(r300->upload_vb);
-    u_upload_destroy(r300->upload_ib);
+    if (r300->upload_vb)
+        u_upload_destroy(r300->upload_vb);
+    if (r300->upload_ib)
+        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);
+    if (r300->tran.translate_cache)
+        translate_cache_destroy(r300->tran.translate_cache);
 
+    /* XXX: This function assumes r300->query_list was initialized */
     r300_release_referenced_objects(r300);
 
-    r300->rws->cs_destroy(r300->cs);
+    if (r300->zmask_mm)
+        r300_hyperz_destroy_mm(r300);
+
+    if (r300->cs)
+        r300->rws->cs_destroy(r300->cs);
 
+    /* XXX: No way to tell if this was initialized or not? */
     util_mempool_destroy(&r300->pool_transfers);
 
     r300_update_num_contexts(r300->screen, -1);
 
-    FREE(r300->aa_state.state);
-    FREE(r300->blend_color_state.state);
-    FREE(r300->clip_state.state);
-    FREE(r300->fb_state.state);
-    FREE(r300->gpu_flush.state);
-    FREE(r300->hyperz_state.state);
-    FREE(r300->invariant_state.state);
-    FREE(r300->rs_block_state.state);
-    FREE(r300->scissor_state.state);
-    FREE(r300->textures_state.state);
-    FREE(r300->vap_invariant_state.state);
-    FREE(r300->viewport_state.state);
-    FREE(r300->ztop_state.state);
-    FREE(r300->fs_constants.state);
-    FREE(r300->vs_constants.state);
-    if (!r300->screen->caps.has_tcl) {
-        FREE(r300->vertex_stream_state.state);
+    /* Free the structs allocated in r300_setup_atoms() */
+    if (r300->aa_state.state) {
+        FREE(r300->aa_state.state);
+        FREE(r300->blend_color_state.state);
+        FREE(r300->clip_state.state);
+        FREE(r300->fb_state.state);
+        FREE(r300->gpu_flush.state);
+        FREE(r300->hyperz_state.state);
+        FREE(r300->invariant_state.state);
+        FREE(r300->rs_block_state.state);
+        FREE(r300->scissor_state.state);
+        FREE(r300->textures_state.state);
+        FREE(r300->vap_invariant_state.state);
+        FREE(r300->viewport_state.state);
+        FREE(r300->ztop_state.state);
+        FREE(r300->fs_constants.state);
+        FREE(r300->vs_constants.state);
+        if (!r300->screen->caps.has_tcl) {
+            FREE(r300->vertex_stream_state.state);
+        }
     }
     FREE(r300);
 }
@@ -158,12 +168,14 @@ void r300_flush_cb(void *data)
 }
 
 #define R300_INIT_ATOM(atomname, atomsize) \
+ do { \
     r300->atomname.name = #atomname; \
     r300->atomname.state = NULL; \
     r300->atomname.size = atomsize; \
     r300->atomname.emit = r300_emit_##atomname; \
     r300->atomname.dirty = FALSE; \
-    insert_at_tail(&r300->atom_list, &r300->atomname);
+    insert_at_tail(&r300->atom_list, &r300->atomname); \
+ } while (0)
 
 static void r300_setup_atoms(struct r300_context* r300)
 {
@@ -404,19 +416,21 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
 
     r300->context.destroy = r300_destroy_context;
 
-    r300->cs = rws->cs_create(rws);
+    make_empty_list(&r300->query_list);
 
     util_mempool_create(&r300->pool_transfers,
                         sizeof(struct pipe_transfer), 64,
                         UTIL_MEMPOOL_SINGLETHREADED);
 
+    r300->cs = rws->cs_create(rws);
+    if (r300->cs == NULL)
+        goto fail;
+
     if (!r300screen->caps.has_tcl) {
         /* Create a Draw. This is used for SW TCL. */
         r300->draw = draw_create(&r300->context);
         /* Enable our renderer. */
         draw_set_rasterize_stage(r300->draw, r300_draw_stage(r300));
-        /* Enable Draw's clipping. */
-        draw_set_driver_clipping(r300->draw, FALSE);
         /* Disable converting points/lines to triangles. */
         draw_wide_line_threshold(r300->draw, 10000000.f);
         draw_wide_point_threshold(r300->draw, 10000000.f);
@@ -424,8 +438,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
 
     r300_setup_atoms(r300);
 
-    make_empty_list(&r300->query_list);
-
     r300_init_blit_functions(r300);
     r300_init_flush_functions(r300);
     r300_init_query_functions(r300);
@@ -433,6 +445,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
     r300_init_resource_functions(r300);
 
     r300->blitter = util_blitter_create(&r300->context);
+    if (r300->blitter == NULL)
+        goto fail;
 
     /* Render functions must be initialized after blitter. */
     r300_init_render_functions(r300);
@@ -441,22 +455,25 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
 
     /* setup hyper-z mm */
     if (r300->rws->get_value(r300->rws, R300_CAN_HYPERZ))
-        r300_hyperz_init_mm(r300);
+        if (!r300_hyperz_init_mm(r300))
+            goto fail;
 
     r300->upload_ib = u_upload_create(&r300->context,
                                      32 * 1024, 16,
                                      PIPE_BIND_INDEX_BUFFER);
 
     if (r300->upload_ib == NULL)
-        goto no_upload_ib;
+        goto fail;
 
     r300->upload_vb = u_upload_create(&r300->context,
                                      128 * 1024, 16,
                                      PIPE_BIND_VERTEX_BUFFER);
     if (r300->upload_vb == NULL)
-        goto no_upload_vb;
+        goto fail;
 
     r300->tran.translate_cache = translate_cache_create();
+    if (r300->tran.translate_cache == NULL)
+        goto fail;
 
     r300_init_states(&r300->context);
 
@@ -486,10 +503,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
 
     return &r300->context;
 
- no_upload_ib:
-    u_upload_destroy(r300->upload_ib);
- no_upload_vb:
-    FREE(r300);
+ fail:
+    r300_destroy_context(&r300->context);
     return NULL;
 }
 
index 6fa7f470f986e0f51a975eed42214891ee6738ca..8f0e86fd37809a736e0dc80fd8f94a2f8b81f694 100644 (file)
@@ -254,8 +254,8 @@ struct r300_ztop_state {
 struct r300_constant_buffer {
     /* Buffer of constants */
     uint32_t *ptr;
-    /* Total number of vec4s */
-    unsigned count;
+    /* Remapping table. */
+    unsigned *remap_table;
 };
 
 /* Query object.
@@ -449,6 +449,7 @@ struct r300_context {
     struct r300_screen *screen;
     /* Draw module. Used mostly for SW TCL. */
     struct draw_context* draw;
+    size_t draw_vbo_size;
     /* Accelerated blit support. */
     struct blitter_context* blitter;
     /* Stencil two-sided reference value fallback. */
@@ -649,6 +650,11 @@ void r300_translate_index_buffer(struct r300_context *r300,
 /* r300_render_stencilref.c */
 void r300_plug_in_stencil_ref_fallback(struct r300_context *r300);
 
+/* r300_render.c */
+void r300_draw_flush_vbuf(struct r300_context *r300);
+boolean r500_index_bias_supported(struct r300_context *r300);
+void r500_emit_index_bias(struct r300_context *r300, int index_bias);
+
 /* r300_state.c */
 enum r300_fb_state_change {
     R300_CHANGED_FB_STATE = 0,
index d0fd45349e3b37cc513113c29700592a865d203c..232259e21d17b06070f8130f33fb0c67dd9301ad 100644 (file)
@@ -180,9 +180,18 @@ void r300_emit_fs_constants(struct r300_context* r300, unsigned size, void *stat
 
     BEGIN_CS(size);
     OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, count * 4);
-    for (i = 0; i < count; i++)
-        for (j = 0; j < 4; j++)
-            OUT_CS(pack_float24(*(float*)&buf->ptr[i*4+j]));
+    if (buf->remap_table){
+        for (i = 0; i < count; i++) {
+            float *data = (float*)&buf->ptr[buf->remap_table[i]*4];
+            for (j = 0; j < 4; j++)
+                OUT_CS(pack_float24(data[j]));
+        }
+    } else {
+        for (i = 0; i < count; i++)
+            for (j = 0; j < 4; j++)
+                OUT_CS(pack_float24(*(float*)&buf->ptr[i*4+j]));
+    }
+
     END_CS;
 }
 
@@ -226,7 +235,7 @@ void r500_emit_fs_constants(struct r300_context* r300, unsigned size, void *stat
 {
     struct r300_fragment_shader *fs = r300_fs(r300);
     struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state;
-    unsigned count = fs->shader->externals_count * 4;
+    unsigned count = fs->shader->externals_count;
     CS_LOCALS(r300);
 
     if (count == 0)
@@ -234,8 +243,15 @@ void r500_emit_fs_constants(struct r300_context* r300, unsigned size, void *stat
 
     BEGIN_CS(size);
     OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST);
-    OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, count);
-    OUT_CS_TABLE(buf->ptr, count);
+    OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, count * 4);
+    if (buf->remap_table){
+        for (unsigned i = 0; i < count; i++) {
+            uint32_t *data = &buf->ptr[buf->remap_table[i]*4];
+            OUT_CS_TABLE(data, 4);
+        }
+    } else {
+        OUT_CS_TABLE(buf->ptr, count * 4);
+    }
     END_CS;
 }
 
@@ -893,7 +909,7 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state)
 
     unsigned pvs_num_slots = MIN3(vtx_mem_size / input_count,
                                   vtx_mem_size / output_count, 10);
-    unsigned pvs_num_controllers = MIN2(vtx_mem_size / temp_count, 6);
+    unsigned pvs_num_controllers = MIN2(vtx_mem_size / temp_count, 5);
 
     unsigned imm_first = vs->externals_count;
     unsigned imm_end = vs->code.constants.Count;
@@ -961,6 +977,7 @@ void r300_emit_vs_constants(struct r300_context* r300,
     unsigned count =
         ((struct r300_vertex_shader*)r300->vs_state.state)->externals_count;
     struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state;
+    unsigned i;
     CS_LOCALS(r300);
 
     if (!count)
@@ -971,7 +988,14 @@ void r300_emit_vs_constants(struct r300_context* r300,
                (r300->screen->caps.is_r500 ?
                R500_PVS_CONST_START : R300_PVS_CONST_START));
     OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, count * 4);
-    OUT_CS_TABLE(buf->ptr, count * 4);
+    if (buf->remap_table){
+        for (i = 0; i < count; i++) {
+            uint32_t *data = &buf->ptr[buf->remap_table[i]*4];
+            OUT_CS_TABLE(data, 4);
+        }
+    } else {
+        OUT_CS_TABLE(buf->ptr, count * 4);
+    }
     END_CS;
 }
 
@@ -1219,6 +1243,8 @@ unsigned r300_get_num_cs_end_dwords(struct r300_context *r300)
     /* Emitted in flush. */
     dwords += 26; /* emit_query_end */
     dwords += r300->hyperz_state.size + 2; /* emit_hyperz_end + zcache flush */
+    if (r500_index_bias_supported(r300))
+        dwords += 2;
 
     return dwords;
 }
index fe182b6615b7578cc1f15e7b10b5ef0fc66bc277..2b5d2e42ba5bb6ff9079998583655371b7898005 100644 (file)
@@ -43,9 +43,14 @@ static void r300_flush(struct pipe_context* pipe,
     u_upload_flush(r300->upload_vb);
     u_upload_flush(r300->upload_ib);
 
+    if (r300->draw)
+       r300_draw_flush_vbuf(r300);
+
     if (r300->dirty_hw) {
         r300_emit_hyperz_end(r300);
         r300_emit_query_end(r300);
+        if (r500_index_bias_supported(r300))
+            r500_emit_index_bias(r300, 0);
 
         r300->flush_counter++;
         r300->rws->cs_flush(r300->cs);
index 2a0c30620adf4f4cac91fdb35f3f1b0911ff79f8..9845e546109cb126f2d74d010007215c142d43e6 100644 (file)
@@ -257,17 +257,17 @@ static void r300_emit_fs_code_to_buffer(
         shader->cb_code_size = 19 +
                                ((code->inst_end + 1) * 6) +
                                imm_count * 7 +
-                              code->int_constant_count * 2;
+                               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);
         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,
+                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,
@@ -386,6 +386,7 @@ static void r300_translate_fragment_shader(
     compiler.state = shader->compare_state;
     compiler.Base.is_r500 = r300->screen->caps.is_r500;
     compiler.Base.max_temp_regs = compiler.Base.is_r500 ? 128 : 32;
+    compiler.Base.remove_unused_constants = TRUE;
     compiler.AllocateHwInputs = &allocate_hardware_inputs;
     compiler.UserData = &shader->inputs;
 
@@ -431,9 +432,8 @@ static void r300_translate_fragment_shader(
     }
 
     if (compiler.Base.Error) {
-        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);
+        fprintf(stderr, "r300 FP: Compiler Error:\n%sUsing a dummy shader"
+                " instead.\n", compiler.Base.ErrorMsg);
 
         if (shader->dummy) {
             fprintf(stderr, "r300 FP: Cannot compile the dummy shader! "
@@ -447,7 +447,12 @@ static void r300_translate_fragment_shader(
     }
 
     /* Initialize numbers of constants for each type. */
-    shader->externals_count = ttr.immediate_offset;
+    shader->externals_count = 0;
+    for (i = 0;
+         i < shader->code.constants.Count &&
+         shader->code.constants.Constants[i].Type == RC_CONSTANT_EXTERNAL; i++) {
+        shader->externals_count = i+1;
+    }
     shader->immediates_count = 0;
     shader->rc_state_count = 0;
 
index 811b5646e163ab8c2eb138c78f6ae2bb0a81eb3e..eb5b0c36f8fa893d8f1807ec36e4fd6386659b31 100644 (file)
@@ -354,7 +354,12 @@ void r300_zmask_alloc_block(struct r300_context *r300, struct r300_surface *surf
     /* 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)
+        tex->desc.b.b.target != PIPE_TEXTURE_2D &&
+        tex->desc.b.b.target != PIPE_TEXTURE_RECT)
+        return;
+
+    /* Cannot flush zmask of 16-bit zbuffers. */
+    if (util_format_get_blocksizebits(tex->desc.b.b.format) == 16)
         return;
 
     if (tex->zmask_mem[level])
@@ -373,23 +378,36 @@ void r300_zmask_alloc_block(struct r300_context *r300, struct r300_surface *surf
     return;
 }
 
-void r300_hyperz_init_mm(struct r300_context *r300)
+boolean 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->zmask_mm = u_mmInit(0, r300screen->caps.zmask_ram * frag_pipes);
+    if (!r300->zmask_mm)
+      return FALSE;
+
+    if (r300screen->caps.hiz_ram) {
       r300->hiz_mm = u_mmInit(0, r300screen->caps.hiz_ram * frag_pipes);
+      if (!r300->hiz_mm) {
+        u_mmDestroy(r300->zmask_mm);
+        r300->zmask_mm = NULL;
+        return FALSE;
+      }
+    }
 
-    r300->zmask_mm = u_mmInit(0, r300screen->caps.zmask_ram * frag_pipes);
+    return TRUE;
 }
 
 void r300_hyperz_destroy_mm(struct r300_context *r300)
 {
     struct r300_screen* r300screen = r300->screen;
 
-    if (r300screen->caps.hiz_ram)
+    if (r300screen->caps.hiz_ram) {
       u_mmDestroy(r300->hiz_mm);
+      r300->hiz_mm = NULL;
+    }
 
     u_mmDestroy(r300->zmask_mm);
+    r300->zmask_mm = NULL;
 }
index 09e1ff6625ca7605bc38bc9b7ca4125d49805788..30a23ec6493686bfebe961968e4a08be1b48c5e4 100644 (file)
@@ -30,6 +30,6 @@ 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);
+boolean r300_hyperz_init_mm(struct r300_context *r300);
 void r300_hyperz_destroy_mm(struct r300_context *r300);
 #endif
index 60d3b600cb7fcdd1f4b7c658e93bf486d2595335..6bea783f69703f55f9e73dc8721a8e850a363388 100644 (file)
@@ -1607,6 +1607,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #      define R300_TX_FORMAT_3D                   (1 << 25)
 #      define R300_TX_FORMAT_CUBIC_MAP            (2 << 25)
+#      define R300_TX_FORMAT_TEX_COORD_TYPE_MASK  (0x3 << 25)
 
        /* alpha modes, convenience mostly */
        /* if you have alpha, pick constant appropriate to the
index 86b11ca0458566af85aa115a2cad20b1dd5d2ef8..20bad2c56f55029e3f3534447c12238222fd84a5 100644 (file)
@@ -118,13 +118,13 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300,
     return color_control;
 }
 
-static boolean index_bias_supported(struct r300_context *r300)
+boolean r500_index_bias_supported(struct r300_context *r300)
 {
     return r300->screen->caps.is_r500 &&
            r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0);
 }
 
-static void r500_emit_index_bias(struct r300_context *r300, int index_bias)
+void r500_emit_index_bias(struct r300_context *r300, int index_bias)
 {
     CS_LOCALS(r300);
 
@@ -199,7 +199,7 @@ static void r300_prepare_for_rendering(struct r300_context *r300,
     boolean emit_aos       = flags & PREP_EMIT_AOS;
     boolean emit_aos_swtcl = flags & PREP_EMIT_AOS_SWTCL;
     boolean indexed        = flags & PREP_INDEXED;
-    boolean hw_index_bias  = index_bias_supported(r300);
+    boolean hw_index_bias  = r500_index_bias_supported(r300);
 
     /* Add dirty state, index offset, and AOS. */
     if (first_draw) {
@@ -506,7 +506,7 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
         translate = TRUE;
     }
 
-    if (indexBias && !index_bias_supported(r300)) {
+    if (indexBias && !r500_index_bias_supported(r300)) {
         r300_split_index_bias(r300, indexBias, &buffer_offset, &index_offset);
     }
 
@@ -680,18 +680,11 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe,
     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_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_set_mapped_index_buffer(r300->draw, indices);
 
-    draw_arrays(r300->draw, info->mode, info->start, count);
+    draw_vbo(r300->draw, info);
 
     /* XXX Not sure whether this is the best fix.
      * It prevents CS from being rejected and weird assertion failures. */
@@ -707,8 +700,7 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe,
 
     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);
+        draw_set_mapped_index_buffer(r300->draw, NULL);
     }
 }
 
@@ -726,8 +718,6 @@ struct r300_render {
     unsigned hwprim;
 
     /* VBO */
-    struct pipe_resource* vbo;
-    size_t vbo_size;
     size_t vbo_offset;
     size_t vbo_max_used;
     void * vbo_ptr;
@@ -759,31 +749,31 @@ static boolean r300_render_allocate_vertices(struct vbuf_render* render,
     struct pipe_screen* screen = r300->context.screen;
     size_t size = (size_t)vertex_size * (size_t)count;
 
-    if (size + r300render->vbo_offset > r300render->vbo_size)
+    if (size + r300render->vbo_offset > r300->draw_vbo_size)
     {
-        pipe_resource_reference(&r300->vbo, NULL);
-        r300render->vbo = pipe_buffer_create(screen,
-                                             PIPE_BIND_VERTEX_BUFFER,
-                                             R300_MAX_DRAW_VBO_SIZE);
+       pipe_resource_reference(&r300->vbo, NULL);
+        r300->vbo = pipe_buffer_create(screen,
+                                      PIPE_BIND_VERTEX_BUFFER,
+                                      R300_MAX_DRAW_VBO_SIZE);
         r300render->vbo_offset = 0;
-        r300render->vbo_size = R300_MAX_DRAW_VBO_SIZE;
+        r300->draw_vbo_size = R300_MAX_DRAW_VBO_SIZE;
     }
 
     r300render->vertex_size = vertex_size;
-    r300->vbo = r300render->vbo;
     r300->vbo_offset = r300render->vbo_offset;
 
-    return (r300render->vbo) ? TRUE : FALSE;
+    return (r300->vbo) ? TRUE : FALSE;
 }
 
 static void* r300_render_map_vertices(struct vbuf_render* render)
 {
     struct r300_render* r300render = r300_render(render);
+    struct r300_context* r300 = r300render->r300;
 
     assert(!r300render->vbo_transfer);
 
     r300render->vbo_ptr = pipe_buffer_map(&r300render->r300->context,
-                                         r300render->vbo,
+                                         r300->vbo,
                                           PIPE_TRANSFER_WRITE,
                                          &r300render->vbo_transfer);
 
@@ -798,12 +788,13 @@ static void r300_render_unmap_vertices(struct vbuf_render* render,
 {
     struct r300_render* r300render = r300_render(render);
     struct pipe_context* context = &r300render->r300->context;
+    struct r300_context* r300 = r300render->r300;
 
     assert(r300render->vbo_transfer);
 
     r300render->vbo_max_used = MAX2(r300render->vbo_max_used,
                                     r300render->vertex_size * (max + 1));
-    pipe_buffer_unmap(context, r300render->vbo, r300render->vbo_transfer);
+    pipe_buffer_unmap(context, r300->vbo, r300render->vbo_transfer);
 
     r300render->vbo_transfer = NULL;
 }
@@ -880,7 +871,7 @@ static void r300_render_draw_elements(struct vbuf_render* render,
     struct r300_context* r300 = r300render->r300;
     int i;
     unsigned end_cs_dwords;
-    unsigned max_index = (r300render->vbo_size - r300render->vbo_offset) /
+    unsigned max_index = (r300->draw_vbo_size - r300render->vbo_offset) /
                          (r300render->r300->vertex_info.size * 4) - 1;
     unsigned short_count;
     unsigned free_dwords;
@@ -956,8 +947,6 @@ static struct vbuf_render* r300_render_create(struct r300_context* r300)
     r300render->base.release_vertices = r300_render_release_vertices;
     r300render->base.destroy = r300_render_destroy;
 
-    r300render->vbo = NULL;
-    r300render->vbo_size = 0;
     r300render->vbo_offset = 0;
 
     return &r300render->base;
@@ -986,6 +975,12 @@ struct draw_stage* r300_draw_stage(struct r300_context* r300)
     return stage;
 }
 
+void r300_draw_flush_vbuf(struct r300_context *r300)
+{
+    pipe_resource_reference(&r300->vbo, NULL);
+    r300->draw_vbo_size = 0;
+}
+
 /****************************************************************************
  *                         End of SW TCL functions                          *
  ***************************************************************************/
index 239edd98e320d34f7a19ebe4a2b83a645eea12aa..8ccb63964e78882886ce274c1453165d937d0550 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "draw/draw_context.h"
 
-#include "util/u_blitter.h"
+#include "util/u_framebuffer.h"
 #include "util/u_math.h"
 #include "util/u_mm.h"
 #include "util/u_memory.h"
@@ -748,7 +748,7 @@ static void
     /* The tiling flags are dependent on the surface miplevel, unfortunately. */
     r300_fb_set_tiling_flags(r300, state);
 
-    util_assign_framebuffer_state(r300->fb_state.state, state);
+    util_copy_framebuffer_state(r300->fb_state.state, state);
 
     r300_mark_fb_state_dirty(r300, R300_CHANGED_FB_STATE);
 
@@ -865,6 +865,9 @@ void r300_mark_fs_code_dirty(struct r300_context *r300)
         r300->fs_rc_constant_state.size = fs->shader->rc_state_count * 5;
         r300->fs_constants.size = fs->shader->externals_count * 4 + 1;
     }
+
+    ((struct r300_constant_buffer*)r300->fs_constants.state)->remap_table =
+            fs->shader->code.constants_remap_table;
 }
 
 /* Bind fragment shader state. */
@@ -937,9 +940,9 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
     uint32_t stuffing_enable;       /* R300_GB_ENABLE: 0x4008 */
 
     /* Point sprites texture coordinates, 0: lower left, 1: upper right */
-    float point_texcoord_left;      /* R300_GA_POINT_S0: 0x4200 */
+    float point_texcoord_left = 0;  /* R300_GA_POINT_S0: 0x4200 */
     float point_texcoord_bottom = 0;/* R300_GA_POINT_T0: 0x4204 */
-    float point_texcoord_right;     /* R300_GA_POINT_S1: 0x4208 */
+    float point_texcoord_right = 1; /* R300_GA_POINT_S1: 0x4208 */
     float point_texcoord_top = 0;   /* R300_GA_POINT_T1: 0x420c */
     CB_LOCALS;
 
@@ -947,6 +950,11 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
     rs->rs = *state;
     rs->rs_draw = *state;
 
+    /* Generate point sprite texture coordinates in GENERIC0
+     * if point_quad_rasterization is TRUE. */
+    rs->rs.sprite_coord_enable = state->point_quad_rasterization *
+                                 (state->sprite_coord_enable | 1);
+
     /* Override some states for Draw. */
     rs->rs_draw.sprite_coord_enable = 0; /* We can do this in HW. */
 
@@ -1048,16 +1056,13 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
 
     /* Point sprites */
     stuffing_enable = 0;
-    if (state->sprite_coord_enable) {
+    if (rs->rs.sprite_coord_enable) {
         stuffing_enable = R300_GB_POINT_STUFF_ENABLE;
-       for (i = 0; i < 8; i++) {
-           if (state->sprite_coord_enable & (1 << i))
+        for (i = 0; i < 8; i++) {
+            if (rs->rs.sprite_coord_enable & (1 << i))
                 stuffing_enable |=
                     R300_GB_TEX_ST << (R300_GB_TEX0_SOURCE_SHIFT + (i*2));
-       }
-
-        point_texcoord_left = 0.0f;
-        point_texcoord_right = 1.0f;
+        }
 
         switch (state->sprite_coord_mode) {
             case PIPE_SPRITE_COORD_UPPER_LEFT:
@@ -1208,8 +1213,8 @@ static void*
 
     /* Unfortunately, r300-r500 don't support floating-point mipmap lods. */
     /* We must pass these to the merge function to clamp them properly. */
-    sampler->min_lod = MAX2((unsigned)state->min_lod, 0);
-    sampler->max_lod = MAX2((unsigned)ceilf(state->max_lod), 0);
+    sampler->min_lod = (unsigned)MAX2(state->min_lod, 0);
+    sampler->max_lod = (unsigned)MAX2(ceilf(state->max_lod), 0);
 
     lod_bias = CLAMP((int)(state->lod_bias * 32 + 1), -(1 << 9), (1 << 9) - 1);
 
@@ -1548,7 +1553,12 @@ static void r300_set_index_buffer(struct pipe_context* pipe,
         memset(&r300->index_buffer, 0, sizeof(r300->index_buffer));
     }
 
-    /* TODO make this more like a state */
+    if (r300->screen->caps.has_tcl) {
+       /* TODO make this more like a state */
+    }
+    else {
+       draw_set_index_buffer(r300->draw, ib);
+    }
 }
 
 /* Initialize the PSC tables. */
@@ -1765,6 +1775,9 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader)
             r300->vs_constants.size = 0;
         }
 
+        ((struct r300_constant_buffer*)r300->vs_constants.state)->remap_table =
+                vs->code.constants_remap_table;
+
         r300->pvs_flush.dirty = TRUE;
     } else {
         draw_bind_vertex_shader(r300->draw,
@@ -1779,6 +1792,8 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader)
 
     if (r300->screen->caps.has_tcl) {
         rc_constants_destroy(&vs->code.constants);
+        if (vs->code.constants_remap_table)
+            FREE(vs->code.constants_remap_table);
     } else {
         draw_delete_vertex_shader(r300->draw,
                 (struct draw_vertex_shader*)vs->draw_vs);
@@ -1795,47 +1810,28 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
     struct r300_context* r300 = r300_context(pipe);
     struct r300_constant_buffer *cbuf;
     uint32_t *mapped = r300_buffer(buf)->user_buffer;
-    int max_size = 0, max_size_bytes = 0, clamped_size = 0;
 
     switch (shader) {
         case PIPE_SHADER_VERTEX:
             cbuf = (struct r300_constant_buffer*)r300->vs_constants.state;
-            max_size = 256;
             break;
         case PIPE_SHADER_FRAGMENT:
             cbuf = (struct r300_constant_buffer*)r300->fs_constants.state;
-            if (r300->screen->caps.is_r500) {
-                max_size = 256;
-            } else {
-                max_size = 32;
-            }
             break;
         default:
             assert(0);
             return;
     }
-    max_size_bytes = max_size * 4 * sizeof(float);
 
     if (buf == NULL || buf->width0 == 0 ||
         (mapped = r300_buffer(buf)->constant_buffer) == NULL) {
-        cbuf->count = 0;
         return;
     }
 
     if (shader == PIPE_SHADER_FRAGMENT ||
         (shader == PIPE_SHADER_VERTEX && r300->screen->caps.has_tcl)) {
         assert((buf->width0 % (4 * sizeof(float))) == 0);
-
-        /* Check the size of the constant buffer. */
-        /* XXX Subtract immediates and RC_STATE_* variables. */
-        if (buf->width0 > max_size_bytes) {
-            fprintf(stderr, "r300: Max size of the constant buffer is "
-                          "%i*4 floats.\n", max_size);
-        }
-
-        clamped_size = MIN2(buf->width0, max_size_bytes);
-        cbuf->count = clamped_size / (4 * sizeof(float));
-        cbuf->ptr = mapped;
+        cbuf->ptr = mapped + index*4;
     }
 
     if (shader == PIPE_SHADER_VERTEX) {
index 4a63ed7fc13fdd85f581a74f719f835e93ba86b8..960dfdbaf0363dffc226cdb5f6e42fe5319b5b1e 100644 (file)
@@ -211,7 +211,7 @@ static void r300_rs_col(struct r300_rs_block* rs, int id, int ptr,
 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);
+    assert(type == WRITE_COLOR);
     rs->inst[id] |= R300_RS_INST_COL_CN_WRITE |
                     R300_RS_INST_COL_ADDR(fp_offset);
 }
@@ -592,6 +592,25 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
             texstate->filter1 = sampler->filter1;
             texstate->border_color = sampler->border_color;
 
+            /* determine min/max levels */
+            max_level = MIN3(sampler->max_lod + view->base.first_level,
+                             tex->desc.b.b.last_level, view->base.last_level);
+            min_level = MIN2(sampler->min_lod + view->base.first_level,
+                             max_level);
+
+            if (tex->desc.is_npot && min_level > 0) {
+                /* Even though we do not implement mipmapping for NPOT
+                 * textures, we should at least honor the minimum level
+                 * which is allowed to be displayed. We do this by setting up
+                 * an i-th mipmap level as the zero level. */
+                r300_texture_setup_format_state(r300->screen, &tex->desc,
+                                                min_level,
+                                                &texstate->format);
+                texstate->format.tile_config |=
+                        tex->desc.offset_in_bytes[min_level] & 0xffffffe0;
+                assert((tex->desc.offset_in_bytes[min_level] & 0x1f) == 0);
+            }
+
             /* Assign a texture cache region. */
             texstate->format.format1 |= view->texcache_region;
 
@@ -654,12 +673,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
                     texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE);
                 }
             } else {
-                /* determine min/max levels */
                 /* the MAX_MIP level is the largest (finest) one */
-                max_level = MIN3(sampler->max_lod + view->base.first_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);
                 texstate->filter0 |= R300_TX_MAX_MIP_LEVEL(min_level);
             }
index da8eadd3b535c15fc1c3d5f2d5b0b0c5b01a1275..66f6d80bd0c9dc71369f43dbcd47af129b3c0263 100644 (file)
@@ -541,48 +541,55 @@ boolean r300_is_sampler_format_supported(enum pipe_format format)
     return r300_translate_texformat(format, 0, TRUE) != ~0;
 }
 
-static void r300_texture_setup_immutable_state(struct r300_screen* screen,
-                                               struct r300_texture* tex)
+void r300_texture_setup_format_state(struct r300_screen *screen,
+                                     struct r300_texture_desc *desc,
+                                     unsigned level,
+                                     struct r300_texture_format_state *out)
 {
-    struct r300_texture_format_state* f = &tex->tx_format;
-    struct pipe_resource *pt = &tex->desc.b.b;
+    struct pipe_resource *pt = &desc->b.b;
     boolean is_r500 = screen->caps.is_r500;
 
+    /* Mask out all the fields we change. */
+    out->format0 = 0;
+    out->format1 &= ~R300_TX_FORMAT_TEX_COORD_TYPE_MASK;
+    out->format2 &= R500_TXFORMAT_MSB;
+    out->tile_config = 0;
+
     /* Set sampler state. */
-    f->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) |
-                 R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff);
+    out->format0 = R300_TX_WIDTH((u_minify(pt->width0, level) - 1) & 0x7ff) |
+                   R300_TX_HEIGHT((u_minify(pt->height0, level) - 1) & 0x7ff);
 
-    if (tex->desc.uses_stride_addressing) {
+    if (desc->uses_stride_addressing) {
         /* rectangles love this */
-        f->format0 |= R300_TX_PITCH_EN;
-        f->format2 = (tex->desc.stride_in_pixels[0] - 1) & 0x1fff;
+        out->format0 |= R300_TX_PITCH_EN;
+        out->format2 = (desc->stride_in_pixels[level] - 1) & 0x1fff;
     } else {
         /* 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);
+        out->format0 |=
+            R300_TX_DEPTH(util_logbase2(u_minify(pt->depth0, level)) & 0xf);
     }
 
-    f->format1 = 0;
     if (pt->target == PIPE_TEXTURE_CUBE) {
-        f->format1 |= R300_TX_FORMAT_CUBIC_MAP;
+        out->format1 |= R300_TX_FORMAT_CUBIC_MAP;
     }
     if (pt->target == PIPE_TEXTURE_3D) {
-        f->format1 |= R300_TX_FORMAT_3D;
+        out->format1 |= R300_TX_FORMAT_3D;
     }
 
     /* large textures on r500 */
     if (is_r500)
     {
         if (pt->width0 > 2048) {
-            f->format2 |= R500_TXWIDTH_BIT11;
+            out->format2 |= R500_TXWIDTH_BIT11;
         }
         if (pt->height0 > 2048) {
-            f->format2 |= R500_TXHEIGHT_BIT11;
+            out->format2 |= R500_TXHEIGHT_BIT11;
         }
     }
 
-    f->tile_config = R300_TXO_MACRO_TILE(tex->desc.macrotile[0]) |
-                     R300_TXO_MICRO_TILE(tex->desc.microtile);
+    out->tile_config = R300_TXO_MACRO_TILE(desc->macrotile[level]) |
+                       R300_TXO_MICRO_TILE(desc->microtile);
 }
 
 static void r300_texture_setup_fb_state(struct r300_screen* screen,
@@ -716,7 +723,7 @@ r300_texture_create_object(struct r300_screen *rscreen,
         return NULL;
     }
     /* Initialize the hardware state. */
-    r300_texture_setup_immutable_state(rscreen, tex);
+    r300_texture_setup_format_state(rscreen, &tex->desc, 0, &tex->tx_format);
     r300_texture_setup_fb_state(rscreen, tex);
 
     tex->desc.b.vtbl = &r300_texture_vtbl;
@@ -754,7 +761,8 @@ struct pipe_resource *r300_texture_create(struct pipe_screen *screen,
     /* Refuse to create a texture with size 0. */
     if (!base->width0 ||
         (!base->height0 && (base->target == PIPE_TEXTURE_2D ||
-                            base->target == PIPE_TEXTURE_CUBE)) ||
+                            base->target == PIPE_TEXTURE_CUBE ||
+                            base->target == PIPE_TEXTURE_RECT)) ||
         (!base->depth0 && base->target == PIPE_TEXTURE_3D)) {
         fprintf(stderr, "r300: texture_create: "
                 "Got invalid texture dimensions: %ix%ix%i\n",
@@ -787,7 +795,8 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen,
     unsigned stride, size;
 
     /* Support only 2D textures without mipmaps */
-    if (base->target != PIPE_TEXTURE_2D ||
+    if ((base->target != PIPE_TEXTURE_2D &&
+          base->target != PIPE_TEXTURE_RECT) ||
         base->depth0 != 1 ||
         base->last_level != 0) {
         return NULL;
index a4524320fdac7cdb6e9b445abaa842be6ad7a254..c4588a0c90b7852dd7bf07fea939a1ca6360e285 100644 (file)
 #ifndef R300_TEXTURE_H
 #define R300_TEXTURE_H
 
+#include "pipe/p_compiler.h"
 #include "pipe/p_format.h"
 
 struct pipe_screen;
 struct pipe_resource;
 struct winsys_handle;
+struct r300_texture_format_state;
+struct r300_texture_desc;
 struct r300_texture;
 struct r300_screen;
 
@@ -50,6 +53,10 @@ boolean r300_is_zs_format_supported(enum pipe_format format);
 
 boolean r300_is_sampler_format_supported(enum pipe_format format);
 
+void r300_texture_setup_format_state(struct r300_screen *screen,
+                                     struct r300_texture_desc *desc,
+                                     unsigned level,
+                                     struct r300_texture_format_state *out);
 
 struct pipe_resource*
 r300_texture_from_handle(struct pipe_screen* screen,
index 5d690e8c33276d44ba3c854d4b2bd5b3d6be48e2..2fe5d721881fd6a87d898a72dd642a173393a2ba 100644 (file)
@@ -184,7 +184,8 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc,
 
         /* 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.target != PIPE_TEXTURE_2D &&
+             desc->b.b.target != PIPE_TEXTURE_RECT) ||
             desc->b.b.last_level != 0) {
             height = util_next_power_of_two(height);
         }
@@ -202,7 +203,8 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc,
                  * 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) &&
+                     desc->b.b.target == PIPE_TEXTURE_2D ||
+                     desc->b.b.target == PIPE_TEXTURE_RECT) &&
                     height >= tile_height * 3) {
                     height = align(height, tile_height * 2);
                 }
index 95de66f6549a845492d25069b5da12f7d25a04ec..3d7fe1fb4731cc352af6ec14fe88091b74673bdf 100644 (file)
@@ -24,6 +24,7 @@
 #ifndef R300_TEXTURE_DESC_H
 #define R300_TEXTURE_DESC_H
 
+#include "pipe/p_format.h"
 #include "r300_defines.h"
 
 struct pipe_resource;
index dd697b9c374b6d811d617a50844ec15395f343e6..a4911b9a2a692fa7ed3814151d4cb476762d8c6f 100644 (file)
@@ -97,13 +97,13 @@ static unsigned translate_opcode(unsigned opcode)
      /* case TGSI_OPCODE_BRA: return RC_OPCODE_BRA; */
      /* case TGSI_OPCODE_CAL: return RC_OPCODE_CAL; */
      /* case TGSI_OPCODE_RET: return RC_OPCODE_RET; */
-     /* case TGSI_OPCODE_SSG: return RC_OPCODE_SSG; */
+        case TGSI_OPCODE_SSG: return RC_OPCODE_SSG;
         case TGSI_OPCODE_CMP: return RC_OPCODE_CMP;
         case TGSI_OPCODE_SCS: return RC_OPCODE_SCS;
         case TGSI_OPCODE_TXB: return RC_OPCODE_TXB;
      /* case TGSI_OPCODE_NRM: return RC_OPCODE_NRM; */
      /* case TGSI_OPCODE_DIV: return RC_OPCODE_DIV; */
-     /* case TGSI_OPCODE_DP2: return RC_OPCODE_DP2; */
+        case TGSI_OPCODE_DP2: return RC_OPCODE_DP2;
         case TGSI_OPCODE_TXL: return RC_OPCODE_TXL;
         case TGSI_OPCODE_BRK: return RC_OPCODE_BRK;
         case TGSI_OPCODE_IF: return RC_OPCODE_IF;
index 54c8de124192a48b3629c17736eae192d614d13c..5f8dbb28d0c2a7157b45d73d99635a6ec6001b29 100644 (file)
@@ -196,6 +196,7 @@ void r300_translate_vertex_shader(struct r300_context *r300,
 {
     struct r300_vertex_program_compiler compiler;
     struct tgsi_to_rc ttr;
+    unsigned i;
 
     /* Setup the compiler */
     rc_init(&compiler.Base);
@@ -205,6 +206,7 @@ void r300_translate_vertex_shader(struct r300_context *r300,
     compiler.UserData = vs;
     compiler.Base.is_r500 = r300->screen->caps.is_r500;
     compiler.Base.max_temp_regs = 32;
+    compiler.Base.remove_unused_constants = TRUE;
 
     if (compiler.Base.Debug) {
         DBG(r300, DBG_VP, "r300: Initial vertex program\n");
@@ -227,9 +229,8 @@ void r300_translate_vertex_shader(struct r300_context *r300,
     /* Invoke the compiler */
     r3xx_compile_vertex_program(&compiler);
     if (compiler.Base.Error) {
-        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);
+        fprintf(stderr, "r300 VP: Compiler error:\n%sUsing a dummy shader"
+                " instead.\n", compiler.Base.ErrorMsg);
 
         if (vs->dummy) {
             fprintf(stderr, "r300 VP: Cannot compile the dummy shader! "
@@ -243,7 +244,15 @@ void r300_translate_vertex_shader(struct r300_context *r300,
     }
 
     /* Initialize numbers of constants for each type. */
-    vs->externals_count = ttr.immediate_offset;
+    vs->externals_count = 0;
+    for (i = 0;
+         i < vs->code.constants.Count &&
+         vs->code.constants.Constants[i].Type == RC_CONSTANT_EXTERNAL; i++) {
+        vs->externals_count = i+1;
+    }
+    for (; i < vs->code.constants.Count; i++) {
+        assert(vs->code.constants.Constants[i].Type == RC_CONSTANT_IMMEDIATE);
+    }
     vs->immediates_count = vs->code.constants.Count - vs->externals_count;
 
     /* And, finally... */
index 187780750fa02bb77a1f78b20f14e94e5c97461c..4597332399a2321313b8084a2bf0249b026b9009 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "r300_defines.h"
 
+struct winsys_handle;
 struct r300_winsys_screen;
 
 struct r300_winsys_buffer;
index 9ea9d4354d6952dca3f3b80a080a763cdfb8e235..6483dac70398dfed47c849b01d6e73796796b525 100644 (file)
@@ -76,6 +76,27 @@ int r600_bc_init(struct r600_bc *bc, enum radeon_family family)
 {
        LIST_INITHEAD(&bc->cf);
        bc->family = family;
+       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:
+               bc->chiprev = 0;
+               break;
+       case CHIP_RV770:
+       case CHIP_RV730:
+       case CHIP_RV710:
+       case CHIP_RV740:
+               bc->chiprev = 1;
+               break;
+       default:
+               R600_ERR("unknown family %d\n", bc->family);
+               return -EINVAL;
+       }
        return 0;
 }
 
@@ -107,7 +128,7 @@ int r600_bc_add_output(struct r600_bc *bc, const struct r600_bc_output *output)
        return 0;
 }
 
-int r600_bc_add_alu(struct r600_bc *bc, const struct r600_bc_alu *alu)
+int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int type)
 {
        struct r600_bc_alu *nalu = r600_bc_alu();
        struct r600_bc_alu *lalu;
@@ -119,7 +140,7 @@ int r600_bc_add_alu(struct r600_bc *bc, const struct r600_bc_alu *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) ||
+       if (bc->cf_last == NULL || bc->cf_last->inst != (type << 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);
@@ -127,7 +148,7 @@ int r600_bc_add_alu(struct r600_bc *bc, const struct r600_bc_alu *alu)
                        free(nalu);
                        return r;
                }
-               bc->cf_last->inst = V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3;
+               bc->cf_last->inst = (type << 3);
        }
        if (alu->last && (bc->cf_last->ndw >> 1) >= 124) {
                bc->force_add_cf = 1;
@@ -162,6 +183,11 @@ int r600_bc_add_alu(struct r600_bc *bc, const struct r600_bc_alu *alu)
        return 0;
 }
 
+int r600_bc_add_alu(struct r600_bc *bc, const struct r600_bc_alu *alu)
+{
+       return r600_bc_add_alu_type(bc, alu, V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU);
+}
+
 int r600_bc_add_literal(struct r600_bc *bc, const u32 *value)
 {
        struct r600_bc_alu *alu;
@@ -172,7 +198,17 @@ int r600_bc_add_literal(struct r600_bc *bc, const u32 *value)
        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) ||
+       if (bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_JUMP ||
+           bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_ELSE ||
+           bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_LOOP_START_NO_AL ||
+           bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_LOOP_BREAK ||
+           bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_LOOP_CONTINUE ||
+           bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_LOOP_END ||
+           bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_POP) {
+               return 0;
+       }
+       if (((bc->cf_last->inst != (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3)) &&
+            (bc->cf_last->inst != (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3))) ||
                LIST_IS_EMPTY(&bc->cf_last->alu)) {
                R600_ERR("last CF is not ALU (%p)\n", bc->cf_last);
                return -EINVAL;
@@ -241,6 +277,18 @@ int r600_bc_add_tex(struct r600_bc *bc, const struct r600_bc_tex *tex)
        return 0;
 }
 
+int r600_bc_add_cfinst(struct r600_bc *bc, int inst)
+{
+       int r;
+       r = r600_bc_add_cf(bc);
+       if (r)
+               return r;
+
+       bc->cf_last->cond = V_SQ_CF_COND_ACTIVE;
+       bc->cf_last->inst = inst;
+       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) |
@@ -292,38 +340,44 @@ static int r600_bc_alu_build(struct r600_bc *bc, struct r600_bc_alu *alu, unsign
        unsigned i;
 
        /* don't replace gpr by pv or ps for destination register */
+       bc->bytecode[id++] = S_SQ_ALU_WORD0_SRC0_SEL(alu->src[0].sel) |
+                               S_SQ_ALU_WORD0_SRC0_REL(alu->src[0].rel) |
+                               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_REL(alu->src[1].rel) |
+                               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);
+
        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_DST_REL(alu->dst.rel) |
                                        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_REL(alu->src[2].rel) |
                                        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_DST_REL(alu->dst.rel) |
                                        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);
+                                       S_SQ_ALU_WORD1_BANK_SWIZZLE(0) |
+                                       S_SQ_ALU_WORD1_OP2_UPDATE_EXECUTE_MASK(alu->predicate) |
+                                       S_SQ_ALU_WORD1_OP2_UPDATE_PRED(alu->predicate);
        }
        if (alu->last) {
+               if (alu->nliteral && !alu->literal_added) {
+                       R600_ERR("Bug in ALU processing for instruction 0x%08x, literal not added correctly\n");
+               }
                for (i = 0; i < alu->nliteral; i++) {
                        bc->bytecode[id++] = alu->value[i];
                }
@@ -337,6 +391,7 @@ static int r600_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf)
 
        switch (cf->inst) {
        case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3):
+       case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 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) |
@@ -364,6 +419,20 @@ static int r600_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf)
                        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;
+       case V_SQ_CF_WORD1_SQ_CF_INST_JUMP:
+       case V_SQ_CF_WORD1_SQ_CF_INST_ELSE:
+       case V_SQ_CF_WORD1_SQ_CF_INST_POP:
+       case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_START_NO_AL:
+       case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_END:
+       case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_CONTINUE:
+       case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_BREAK:
+               bc->bytecode[id++] = S_SQ_CF_WORD0_ADDR(cf->cf_addr >> 1);
+               bc->bytecode[id++] = S_SQ_CF_WORD1_CF_INST(cf->inst) |
+                                       S_SQ_CF_WORD1_BARRIER(1) |
+                                       S_SQ_CF_WORD1_COND(cf->cond) |
+                                       S_SQ_CF_WORD1_POP_COUNT(cf->pop_count);
+
+               break;
        default:
                R600_ERR("unsupported CF instruction (0x%X)\n", cf->inst);
                return -EINVAL;
@@ -380,6 +449,8 @@ int r600_bc_build(struct r600_bc *bc)
        unsigned addr;
        int r;
 
+       if (bc->callstack[0].max > 0)
+           bc->nstack = ((bc->callstack[0].max + 3) >> 2) + 2;
 
        /* first path compute addr of each CF block */
        /* addr start after all the CF instructions */
@@ -387,6 +458,7 @@ int r600_bc_build(struct r600_bc *bc)
        LIST_FOR_EACH_ENTRY(cf, &bc->cf, list) {
                switch (cf->inst) {
                case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3):
+               case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3):
                        break;
                case V_SQ_CF_WORD1_SQ_CF_INST_TEX:
                case V_SQ_CF_WORD1_SQ_CF_INST_VTX:
@@ -398,6 +470,14 @@ int r600_bc_build(struct r600_bc *bc)
                case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
                case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
                        break;
+               case V_SQ_CF_WORD1_SQ_CF_INST_JUMP:
+               case V_SQ_CF_WORD1_SQ_CF_INST_ELSE:
+               case V_SQ_CF_WORD1_SQ_CF_INST_POP:
+               case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_START_NO_AL:
+               case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_END:
+               case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_CONTINUE:
+               case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_BREAK:
+                       break;
                default:
                        R600_ERR("unsupported CF instruction (0x%X)\n", cf->inst);
                        return -EINVAL;
@@ -417,22 +497,13 @@ int r600_bc_build(struct r600_bc *bc)
                        return r;
                switch (cf->inst) {
                case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3):
+               case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 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:
+                               switch(bc->chiprev) {
+                               case 0:
                                        r = r600_bc_alu_build(bc, alu, addr);
                                        break;
-                               case CHIP_RV770:
-                               case CHIP_RV730:
-                               case CHIP_RV710:
-                               case CHIP_RV740:
+                               case 1:
                                        r = r700_bc_alu_build(bc, alu, addr);
                                        break;
                                default:
@@ -466,6 +537,13 @@ int r600_bc_build(struct r600_bc *bc)
                        break;
                case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT:
                case V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT_DONE:
+               case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_START_NO_AL:
+               case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_END:
+               case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_CONTINUE:
+               case V_SQ_CF_WORD1_SQ_CF_INST_LOOP_BREAK:
+               case V_SQ_CF_WORD1_SQ_CF_INST_JUMP:
+               case V_SQ_CF_WORD1_SQ_CF_INST_ELSE:
+               case V_SQ_CF_WORD1_SQ_CF_INST_POP:
                        break;
                default:
                        R600_ERR("unsupported CF instruction (0x%X)\n", cf->inst);
index 10d98afaf00ce6830a88ee82f5909c95b524f2c3..9e65fcdd4fa14b83be1c85eebe1df59becd2decd 100644 (file)
@@ -31,6 +31,7 @@ struct r600_bc_alu_src {
        unsigned                        chan;
        unsigned                        neg;
        unsigned                        abs;
+       unsigned                        rel;
 };
 
 struct r600_bc_alu_dst {
@@ -38,6 +39,7 @@ struct r600_bc_alu_dst {
        unsigned                        chan;
        unsigned                        clamp;
        unsigned                        write;
+       unsigned                        rel;
 };
 
 struct r600_bc_alu {
@@ -47,6 +49,7 @@ struct r600_bc_alu {
        unsigned                        inst;
        unsigned                        last;
        unsigned                        is_op3;
+       unsigned                        predicate;
        unsigned                        nliteral;
        unsigned                        literal_added;
        u32                             value[4];
@@ -114,22 +117,55 @@ struct r600_bc_cf {
        unsigned                        addr;
        unsigned                        ndw;
        unsigned                        id;
+       unsigned                        cond;
+       unsigned                        pop_count;
+       unsigned                        cf_addr; /* control flow addr */
        struct list_head                alu;
        struct list_head                tex;
        struct list_head                vtx;
        struct r600_bc_output           output;
 };
 
+#define FC_NONE 0
+#define FC_IF 1
+#define FC_LOOP 2
+#define FC_REP 3
+#define FC_PUSH_VPM 4
+#define FC_PUSH_WQM 5
+
+struct r600_cf_stack_entry {
+       int type;
+       struct r600_bc_cf *start;
+       struct r600_bc_cf **mid; /* used to store the else point */
+       int num_mid;
+};
+
+#define SQ_MAX_CALL_DEPTH 0x00000020
+struct r600_cf_callstack {
+       unsigned fc_sp_before_entry;
+       int sub_desc_index;
+       int current;
+       int max;
+};
+       
 struct r600_bc {
        enum radeon_family              family;
+       int chiprev; /* 0 - r600, 1 - r700, 2 - evergreen */
        struct list_head                cf;
        struct r600_bc_cf               *cf_last;
        unsigned                        ndw;
        unsigned                        ncf;
        unsigned                        ngpr;
+       unsigned                        nstack;
        unsigned                        nresource;
        unsigned                        force_add_cf;
        u32                             *bytecode;
+
+       u32 fc_sp;
+       struct r600_cf_stack_entry fc_stack[32];
+
+       unsigned call_sp;
+       struct r600_cf_callstack callstack[SQ_MAX_CALL_DEPTH];
 };
 
 int r600_bc_init(struct r600_bc *bc, enum radeon_family family);
@@ -139,5 +175,6 @@ 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);
-
+int r600_bc_add_cfinst(struct r600_bc *bc, int inst);
+int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int type);
 #endif
index f4eedfe4cb1f4df0f187f1d496e3f744babf4a66..e6ded342e59a9038aabb2265702c13f5d8c1cd1a 100644 (file)
@@ -24,6 +24,7 @@
  *      Jerome Glisse
  *      Marek Olšák
  */
+#include <errno.h>
 #include <pipe/p_screen.h>
 #include <util/u_blitter.h>
 #include <util/u_inlines.h>
 #include "util/u_surface.h"
 #include "r600_screen.h"
 #include "r600_context.h"
+#include "r600d.h"
 
-static void r600_blitter_save_states(struct r600_context *rctx)
+static void r600_blitter_save_states(struct pipe_context *ctx)
 {
+       struct r600_context *rctx = r600_context(ctx);
+
        util_blitter_save_blend(rctx->blitter, rctx->blend);
        util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->dsa);
        if (rctx->stencil_ref) {
@@ -47,48 +51,58 @@ static void r600_blitter_save_states(struct r600_context *rctx)
        if (rctx->viewport) {
                util_blitter_save_viewport(rctx->blitter, &rctx->viewport->state.viewport);
        }
-       /* XXX util_blitter_save_clip(rctx->blitter, &rctx->clip); */
+       if (rctx->clip) {
+               util_blitter_save_clip(rctx->blitter, &rctx->clip->state.clip);
+       }
        util_blitter_save_vertex_buffers(rctx->blitter, rctx->nvertex_buffer,
                                        rctx->vertex_buffer);
 
        /* remove ptr so they don't get deleted */
        rctx->blend = NULL;
+       rctx->clip = NULL;
        rctx->vs_shader = NULL;
        rctx->ps_shader = NULL;
        rctx->rasterizer = NULL;
        rctx->dsa = NULL;
        rctx->vertex_elements = NULL;
+
+       /* suspend queries */
+       r600_queries_suspend(ctx);
 }
 
 static void r600_clear(struct pipe_context *ctx, unsigned buffers,
-                      const float *rgba, double depth, unsigned stencil)
+                       const float *rgba, double depth, unsigned stencil)
 {
        struct r600_context *rctx = r600_context(ctx);
        struct pipe_framebuffer_state *fb = &rctx->framebuffer->state.framebuffer;
 
-       r600_blitter_save_states(rctx);
+       r600_blitter_save_states(ctx);
        util_blitter_clear(rctx->blitter, fb->width, fb->height,
                                fb->nr_cbufs, buffers, rgba, depth,
                                stencil);
+       /* resume queries */
+       r600_queries_resume(ctx);
 }
 
-static void r600_clear_render_target(struct pipe_context *pipe,
+static void r600_clear_render_target(struct pipe_context *ctx,
                                     struct pipe_surface *dst,
                                     const float *rgba,
                                     unsigned dstx, unsigned dsty,
                                     unsigned width, unsigned height)
 {
-       struct r600_context *rctx = r600_context(pipe);
+       struct r600_context *rctx = r600_context(ctx);
        struct pipe_framebuffer_state *fb = &rctx->framebuffer->state.framebuffer;
 
-       r600_blitter_save_states(rctx);
+       r600_blitter_save_states(ctx);
        util_blitter_save_framebuffer(rctx->blitter, fb);
 
        util_blitter_clear_render_target(rctx->blitter, dst, rgba,
                                         dstx, dsty, width, height);
+       /* resume queries */
+       r600_queries_resume(ctx);
 }
 
-static void r600_clear_depth_stencil(struct pipe_context *pipe,
+static void r600_clear_depth_stencil(struct pipe_context *ctx,
                                     struct pipe_surface *dst,
                                     unsigned clear_flags,
                                     double depth,
@@ -96,17 +110,20 @@ static void r600_clear_depth_stencil(struct pipe_context *pipe,
                                     unsigned dstx, unsigned dsty,
                                     unsigned width, unsigned height)
 {
-       struct r600_context *rctx = r600_context(pipe);
+       struct r600_context *rctx = r600_context(ctx);
        struct pipe_framebuffer_state *fb = &rctx->framebuffer->state.framebuffer;
 
-       r600_blitter_save_states(rctx);
+       r600_blitter_save_states(ctx);
        util_blitter_save_framebuffer(rctx->blitter, fb);
 
        util_blitter_clear_depth_stencil(rctx->blitter, dst, clear_flags, depth, stencil,
                                         dstx, dsty, width, height);
+       /* resume queries */
+       r600_queries_resume(ctx);
 }
 
-static void r600_resource_copy_region(struct pipe_context *pipe,
+
+static void r600_resource_copy_region(struct pipe_context *ctx,
                                      struct pipe_resource *dst,
                                      struct pipe_subresource subdst,
                                      unsigned dstx, unsigned dsty, unsigned dstz,
@@ -115,7 +132,7 @@ static void r600_resource_copy_region(struct pipe_context *pipe,
                                      unsigned srcx, unsigned srcy, unsigned srcz,
                                      unsigned width, unsigned height)
 {
-       util_resource_copy_region(pipe, dst, subdst, dstx, dsty, dstz,
+       util_resource_copy_region(ctx, dst, subdst, dstx, dsty, dstz,
                                  src, subsrc, srcx, srcy, srcz, width, height);
 }
 
@@ -126,3 +143,446 @@ void r600_init_blit_functions(struct r600_context *rctx)
        rctx->context.clear_depth_stencil = r600_clear_depth_stencil;
        rctx->context.resource_copy_region = r600_resource_copy_region;
 }
+
+
+struct r600_blit_states {
+       struct radeon_state     rasterizer;
+       struct radeon_state     dsa;
+       struct radeon_state     blend;
+       struct radeon_state     cb_cntl;
+       struct radeon_state     vgt;
+       struct radeon_state     draw;
+       struct radeon_state     vs_constant0;
+       struct radeon_state     vs_constant1;
+       struct radeon_state     vs_constant2;
+       struct radeon_state     vs_constant3;
+       struct radeon_state     ps_shader;
+       struct radeon_state     vs_shader;
+       struct radeon_state     vs_resource0;
+       struct radeon_state     vs_resource1;
+};
+
+static int r600_blit_state_vs_resources(struct r600_screen *rscreen, struct r600_blit_states *bstates)
+{
+       struct radeon_state *rstate;
+       struct radeon_bo *bo;
+       u32 vbo[] = {
+               0xBF800000, 0xBF800000, 0x3F800000, 0x3F800000,
+               0x3F000000, 0x3F000000, 0x3F000000, 0x00000000,
+               0x3F800000, 0xBF800000, 0x3F800000, 0x3F800000,
+               0x3F000000, 0x3F000000, 0x3F000000, 0x00000000,
+               0x3F800000, 0x3F800000, 0x3F800000, 0x3F800000,
+               0x3F000000, 0x3F000000, 0x3F000000, 0x00000000,
+               0xBF800000, 0x3F800000, 0x3F800000, 0x3F800000,
+               0x3F000000, 0x3F000000, 0x3F000000, 0x00000000
+       };
+
+       /* simple shader */
+       bo = radeon_bo(rscreen->rw, 0, 128, 4096, NULL);
+       if (bo == NULL) {
+               return -ENOMEM;
+       }
+       if (radeon_bo_map(rscreen->rw, bo)) {
+               radeon_bo_decref(rscreen->rw, bo);
+               return -ENOMEM;
+       }
+       memcpy(bo->data, vbo, 128);
+       radeon_bo_unmap(rscreen->rw, bo);
+
+       rstate = &bstates->vs_resource0;
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_RESOURCE, 0, R600_SHADER_VS);
+
+       /* set states (most default value are 0 and struct already
+        * initialized to 0, thus avoid resetting them)
+        */
+       rstate->states[R600_VS_RESOURCE__RESOURCE160_WORD0] = 0x00000000;
+       rstate->states[R600_VS_RESOURCE__RESOURCE160_WORD1] = 0x00000080;
+       rstate->states[R600_VS_RESOURCE__RESOURCE160_WORD2] = 0x02302000;
+       rstate->states[R600_VS_RESOURCE__RESOURCE160_WORD3] = 0x00000000;
+       rstate->states[R600_VS_RESOURCE__RESOURCE160_WORD4] = 0x00000000;
+       rstate->states[R600_VS_RESOURCE__RESOURCE160_WORD5] = 0x00000000;
+       rstate->states[R600_VS_RESOURCE__RESOURCE160_WORD6] = 0xC0000000;
+       rstate->bo[0] = bo;
+       rstate->nbo = 1;
+       rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
+       if (radeon_state_pm4(rstate)) {
+               radeon_state_fini(rstate);
+               return -ENOMEM;
+       }
+
+       rstate = &bstates->vs_resource1;
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_RESOURCE, 1, R600_SHADER_VS);
+       rstate->states[R600_VS_RESOURCE__RESOURCE160_WORD0] = 0x00000010;
+       rstate->states[R600_VS_RESOURCE__RESOURCE160_WORD1] = 0x00000070;
+       rstate->states[R600_VS_RESOURCE__RESOURCE160_WORD2] = 0x02302000;
+       rstate->states[R600_VS_RESOURCE__RESOURCE160_WORD3] = 0x00000000;
+       rstate->states[R600_VS_RESOURCE__RESOURCE160_WORD4] = 0x00000000;
+       rstate->states[R600_VS_RESOURCE__RESOURCE160_WORD5] = 0x00000000;
+       rstate->states[R600_VS_RESOURCE__RESOURCE160_WORD6] = 0xC0000000;
+       rstate->bo[0] = radeon_bo_incref(rscreen->rw, bo);
+       rstate->nbo = 1;
+       rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
+       if (radeon_state_pm4(rstate)) {
+               radeon_state_fini(rstate);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static void r600_blit_state_vs_shader(struct r600_screen *rscreen, struct radeon_state *rstate)
+{
+       struct radeon_bo *bo;
+       u32 shader_bc_r600[] = {
+               0x00000004, 0x81000400,
+               0x00000008, 0xA01C0000,
+               0xC001A03C, 0x94000688,
+               0xC0024000, 0x94200688,
+               0x7C000000, 0x002D1001,
+               0x00080000, 0x00000000,
+               0x7C000100, 0x002D1002,
+               0x00080000, 0x00000000,
+               0x00000001, 0x00601910,
+               0x00000401, 0x20601910,
+               0x00000801, 0x40601910,
+               0x80000C01, 0x60601910,
+               0x00000002, 0x00801910,
+               0x00000402, 0x20801910,
+               0x00000802, 0x40801910,
+               0x80000C02, 0x60801910
+       };
+       u32 shader_bc_r700[] = {
+               0x00000004, 0x81000400,
+               0x00000008, 0xA01C0000,
+               0xC001A03C, 0x94000688,
+               0xC0024000, 0x94200688,
+               0x7C000000, 0x002D1001,
+               0x00080000, 0x00000000,
+               0x7C000100, 0x002D1002,
+               0x00080000, 0x00000000,
+               0x00000001, 0x00600C90,
+               0x00000401, 0x20600C90,
+               0x00000801, 0x40600C90,
+               0x80000C01, 0x60600C90,
+               0x00000002, 0x00800C90,
+               0x00000402, 0x20800C90,
+               0x00000802, 0x40800C90,
+               0x80000C02, 0x60800C90
+       };
+
+       /* simple shader */
+       bo = radeon_bo(rscreen->rw, 0, 128, 4096, NULL);
+       if (bo == NULL) {
+               return;
+       }
+       if (radeon_bo_map(rscreen->rw, bo)) {
+               radeon_bo_decref(rscreen->rw, bo);
+               return;
+       }
+       switch (rscreen->chip_class) {
+       case R600:
+               memcpy(bo->data, shader_bc_r600, 128);
+               break;
+       case R700:
+               memcpy(bo->data, shader_bc_r700, 128);
+               break;
+       default:
+               R600_ERR("unsupported chip family\n");
+               radeon_bo_unmap(rscreen->rw, bo);
+               radeon_bo_decref(rscreen->rw, bo);
+               return;
+       }
+       radeon_bo_unmap(rscreen->rw, bo);
+
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_SHADER, 0, R600_SHADER_VS);
+
+       /* set states (most default value are 0 and struct already
+        * initialized to 0, thus avoid resetting them)
+        */
+       rstate->states[R600_VS_SHADER__SPI_VS_OUT_ID_0] = 0x03020100;
+       rstate->states[R600_VS_SHADER__SPI_VS_OUT_ID_1] = 0x07060504;
+       rstate->states[R600_VS_SHADER__SQ_PGM_RESOURCES_VS] = 0x00000005;
+
+       rstate->bo[0] = bo;
+       rstate->bo[1] = radeon_bo_incref(rscreen->rw, bo);
+       rstate->nbo = 2;
+       rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
+       rstate->placement[2] = RADEON_GEM_DOMAIN_GTT;
+
+       radeon_state_pm4(rstate);
+}
+
+static void r600_blit_state_ps_shader(struct r600_screen *rscreen, struct radeon_state *rstate)
+{
+       struct radeon_bo *bo;
+       u32 shader_bc_r600[] = {
+               0x00000002, 0xA00C0000,
+               0xC0008000, 0x94200688,
+               0x00000000, 0x00201910,
+               0x00000400, 0x20201910,
+               0x00000800, 0x40201910,
+               0x80000C00, 0x60201910
+       };
+       u32 shader_bc_r700[] = {
+               0x00000002, 0xA00C0000,
+               0xC0008000, 0x94200688,
+               0x00000000, 0x00200C90,
+               0x00000400, 0x20200C90,
+               0x00000800, 0x40200C90,
+               0x80000C00, 0x60200C90
+       };
+
+       /* simple shader */
+       bo = radeon_bo(rscreen->rw, 0, 128, 4096, NULL);
+       if (bo == NULL) {
+               radeon_bo_decref(rscreen->rw, bo);
+               return;
+       }
+       if (radeon_bo_map(rscreen->rw, bo)) {
+               return;
+       }
+       switch (rscreen->chip_class) {
+       case R600:
+               memcpy(bo->data, shader_bc_r600, 48);
+               break;
+       case R700:
+               memcpy(bo->data, shader_bc_r700, 48);
+               break;
+       default:
+               R600_ERR("unsupported chip family\n");
+               radeon_bo_unmap(rscreen->rw, bo);
+               radeon_bo_decref(rscreen->rw, bo);
+               return;
+       }
+       radeon_bo_unmap(rscreen->rw, bo);
+
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_SHADER, 0, R600_SHADER_PS);
+
+       /* set states (most default value are 0 and struct already
+        * initialized to 0, thus avoid resetting them)
+        */
+       rstate->states[R600_PS_SHADER__SPI_PS_INPUT_CNTL_0] = 0x00000C00;
+       rstate->states[R600_PS_SHADER__SPI_PS_IN_CONTROL_0] = 0x10000001;
+       rstate->states[R600_PS_SHADER__SQ_PGM_EXPORTS_PS] = 0x00000002;
+       rstate->states[R600_PS_SHADER__SQ_PGM_RESOURCES_PS] = 0x00000002;
+
+       rstate->bo[0] = bo;
+       rstate->nbo = 1;
+       rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
+
+       radeon_state_pm4(rstate);
+}
+
+static void r600_blit_state_vgt(struct r600_screen *rscreen, struct radeon_state *rstate)
+{
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_VGT, 0, 0);
+
+       /* set states (most default value are 0 and struct already
+        * initialized to 0, thus avoid resetting them)
+        */
+       rstate->states[R600_VGT__VGT_DMA_NUM_INSTANCES] = 0x00000001;
+       rstate->states[R600_VGT__VGT_MAX_VTX_INDX] = 0x00FFFFFF;
+       rstate->states[R600_VGT__VGT_PRIMITIVE_TYPE] = 0x00000005;
+
+       radeon_state_pm4(rstate);
+}
+
+static void r600_blit_state_draw(struct r600_screen *rscreen, struct radeon_state *rstate)
+{
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_DRAW, 0, 0);
+
+       /* set states (most default value are 0 and struct already
+        * initialized to 0, thus avoid resetting them)
+        */
+       rstate->states[R600_DRAW__VGT_DRAW_INITIATOR] = 0x00000002;
+       rstate->states[R600_DRAW__VGT_NUM_INDICES] = 0x00000004;
+
+       radeon_state_pm4(rstate);
+}
+
+static void r600_blit_state_vs_constant(struct r600_screen *rscreen, struct radeon_state *rstate,
+                                       unsigned id, float c0, float c1, float c2, float c3)
+{
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_CONSTANT, id, R600_SHADER_VS);
+
+       /* set states (most default value are 0 and struct already
+        * initialized to 0, thus avoid resetting them)
+        */
+       rstate->states[R600_VS_CONSTANT__SQ_ALU_CONSTANT0_256] = fui(c0);
+       rstate->states[R600_VS_CONSTANT__SQ_ALU_CONSTANT1_256] = fui(c1);
+       rstate->states[R600_VS_CONSTANT__SQ_ALU_CONSTANT2_256] = fui(c2);
+       rstate->states[R600_VS_CONSTANT__SQ_ALU_CONSTANT3_256] = fui(c3);
+
+       radeon_state_pm4(rstate);
+}
+
+static void r600_blit_state_rasterizer(struct r600_screen *rscreen, struct radeon_state *rstate)
+{
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_RASTERIZER, 0, 0);
+
+       /* set states (most default value are 0 and struct already
+        * initialized to 0, thus avoid resetting them)
+        */
+       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_CL_GB_VERT_CLIP_ADJ] = 0x3F800000;
+       rstate->states[R600_RASTERIZER__PA_CL_GB_VERT_DISC_ADJ] = 0x3F800000;
+       rstate->states[R600_RASTERIZER__PA_SC_LINE_CNTL] = 0x00000400;
+       rstate->states[R600_RASTERIZER__PA_SC_LINE_STIPPLE] = 0x00000005;
+       rstate->states[R600_RASTERIZER__PA_SU_LINE_CNTL] = 0x00000008;
+       rstate->states[R600_RASTERIZER__PA_SU_POINT_MINMAX] = 0x80000000;
+       rstate->states[R600_RASTERIZER__PA_SU_SC_MODE_CNTL] = 0x00080004;
+       rstate->states[R600_RASTERIZER__SPI_INTERP_CONTROL_0] = 0x00000001;
+
+       radeon_state_pm4(rstate);
+}
+
+static void r600_blit_state_dsa(struct r600_screen *rscreen, struct radeon_state *rstate)
+{
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_DSA, 0, 0);
+
+       /* set states (most default value are 0 and struct already
+        * initialized to 0, thus avoid resetting them)
+        */
+       rstate->states[R600_DSA__DB_ALPHA_TO_MASK] = 0x0000AA00;
+       rstate->states[R600_DSA__DB_DEPTH_CLEAR] = 0x3F800000;
+       rstate->states[R600_DSA__DB_RENDER_CONTROL] = 0x00000060;
+       rstate->states[R600_DSA__DB_RENDER_OVERRIDE] = 0x0000002A;
+       rstate->states[R600_DSA__DB_SHADER_CONTROL] = 0x00000210;
+
+       radeon_state_pm4(rstate);
+}
+
+static void r600_blit_state_blend(struct r600_screen *rscreen, struct radeon_state *rstate)
+{
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_BLEND, 0, 0);
+       radeon_state_pm4(rstate);
+}
+
+static void r600_blit_state_cb_cntl(struct r600_screen *rscreen, struct radeon_state *rstate)
+{
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_CB_CNTL, 0, 0);
+       rstate->states[R600_CB_CNTL__CB_CLRCMP_CONTROL] = 0x01000000;
+       rstate->states[R600_CB_CNTL__CB_CLRCMP_DST] = 0x000000FF;
+       rstate->states[R600_CB_CNTL__CB_CLRCMP_MSK] = 0xFFFFFFFF;
+       rstate->states[R600_CB_CNTL__CB_COLOR_CONTROL] = 0x00CC0080;
+       rstate->states[R600_CB_CNTL__CB_SHADER_MASK] = 0x0000000F;
+       rstate->states[R600_CB_CNTL__CB_TARGET_MASK] = 0x0000000F;
+       rstate->states[R600_CB_CNTL__PA_SC_AA_MASK] = 0xFFFFFFFF;
+       radeon_state_pm4(rstate);
+}
+
+static int r600_blit_states_init(struct pipe_context *ctx, struct r600_blit_states *bstates)
+{
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+
+       r600_blit_state_ps_shader(rscreen, &bstates->ps_shader);
+       r600_blit_state_vs_shader(rscreen, &bstates->vs_shader);
+       r600_blit_state_vgt(rscreen, &bstates->vgt);
+       r600_blit_state_draw(rscreen, &bstates->draw);
+       r600_blit_state_vs_constant(rscreen, &bstates->vs_constant0, 0, 1.0, 0.0, 0.0, 0.0);
+       r600_blit_state_vs_constant(rscreen, &bstates->vs_constant1, 1, 0.0, 1.0, 0.0, 0.0);
+       r600_blit_state_vs_constant(rscreen, &bstates->vs_constant2, 2, 0.0, 0.0, -0.00199900055, 0.0);
+       r600_blit_state_vs_constant(rscreen, &bstates->vs_constant3, 3, 0.0, 0.0, -0.99900049, 1.0);
+       r600_blit_state_rasterizer(rscreen, &bstates->rasterizer);
+       r600_blit_state_dsa(rscreen, &bstates->dsa);
+       r600_blit_state_blend(rscreen, &bstates->blend);
+       r600_blit_state_cb_cntl(rscreen, &bstates->cb_cntl);
+       r600_blit_state_vs_resources(rscreen, bstates);
+       return 0;
+}
+
+static void r600_blit_states_destroy(struct pipe_context *ctx, struct r600_blit_states *bstates)
+{
+       radeon_state_fini(&bstates->ps_shader);
+       radeon_state_fini(&bstates->vs_shader);
+       radeon_state_fini(&bstates->vs_resource0);
+       radeon_state_fini(&bstates->vs_resource1);
+}
+
+int r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
+{
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+       struct r600_context *rctx = r600_context(ctx);
+       struct radeon_draw draw;
+       struct r600_blit_states bstates;
+       int r;
+
+       r = r600_texture_scissor(ctx, rtexture, level);
+       if (r) {
+               return r;
+       }
+       r = r600_texture_cb(ctx, rtexture, 0, level);
+       if (r) {
+               return r;
+       }
+       r = r600_texture_db(ctx, rtexture, level);
+       if (r) {
+               return r;
+       }
+       r = r600_texture_viewport(ctx, rtexture, level);
+       if (r) {
+               return r;
+       }
+
+       r = r600_blit_states_init(ctx, &bstates);
+       if (r) {
+               return r;
+       }
+       bstates.dsa.states[R600_DSA__DB_RENDER_CONTROL] = 0x0000008C;
+       bstates.cb_cntl.states[R600_CB_CNTL__CB_TARGET_MASK] = 0x00000001;
+       /* force rebuild */
+       bstates.dsa.cpm4 = bstates.cb_cntl.cpm4 = 0;
+       if (radeon_state_pm4(&bstates.dsa)) {
+               goto out;
+       }
+       if (radeon_state_pm4(&bstates.cb_cntl)) {
+               goto out;
+       }
+
+       r = radeon_draw_init(&draw, rscreen->rw);
+       if (r) {
+               R600_ERR("failed creating draw for uncompressing textures\n");
+               goto out;
+       }
+
+       radeon_draw_bind(&draw, &bstates.vs_shader);
+       radeon_draw_bind(&draw, &bstates.ps_shader);
+       radeon_draw_bind(&draw, &bstates.rasterizer);
+       radeon_draw_bind(&draw, &bstates.dsa);
+       radeon_draw_bind(&draw, &bstates.blend);
+       radeon_draw_bind(&draw, &bstates.cb_cntl);
+       radeon_draw_bind(&draw, &rctx->config);
+       radeon_draw_bind(&draw, &bstates.vgt);
+       radeon_draw_bind(&draw, &bstates.draw);
+       radeon_draw_bind(&draw, &bstates.vs_resource0);
+       radeon_draw_bind(&draw, &bstates.vs_resource1);
+       radeon_draw_bind(&draw, &bstates.vs_constant0);
+       radeon_draw_bind(&draw, &bstates.vs_constant1);
+       radeon_draw_bind(&draw, &bstates.vs_constant2);
+       radeon_draw_bind(&draw, &bstates.vs_constant3);
+       radeon_draw_bind(&draw, &rtexture->viewport[level]);
+       radeon_draw_bind(&draw, &rtexture->scissor[level]);
+       radeon_draw_bind(&draw, &rtexture->cb[0][level]);
+       radeon_draw_bind(&draw, &rtexture->db[level]);
+
+       /* suspend queries */
+       r600_queries_suspend(ctx);
+
+       /* schedule draw*/
+       r = radeon_ctx_set_draw(&rctx->ctx, &draw);
+       if (r == -EBUSY) {
+               r600_flush(ctx, 0, NULL);
+               r = radeon_ctx_set_draw(&rctx->ctx, &draw);
+       }
+       if (r) {
+               goto out;
+       }
+
+       /* resume queries */
+       r600_queries_resume(ctx);
+
+out:
+       r600_blit_states_destroy(ctx, &bstates);
+       return r;
+}
index edde80c660a0daae512e5545208888701c2a47ea..7a0e5b4049f135de1b120d914cfe3b22ea596fb1 100644 (file)
 #include "r600_resource.h"
 #include "r600d.h"
 
+
 static void r600_destroy_context(struct pipe_context *context)
 {
        struct r600_context *rctx = r600_context(context);
 
+       rctx->rasterizer = r600_context_state_decref(rctx->rasterizer);
+       rctx->poly_stipple = r600_context_state_decref(rctx->poly_stipple);
+       rctx->scissor = r600_context_state_decref(rctx->scissor);
+       rctx->clip = r600_context_state_decref(rctx->clip);
+       rctx->ps_shader = r600_context_state_decref(rctx->ps_shader);
+       rctx->vs_shader = r600_context_state_decref(rctx->vs_shader);
+       rctx->depth = r600_context_state_decref(rctx->depth);
+       rctx->stencil = r600_context_state_decref(rctx->stencil);
+       rctx->alpha = r600_context_state_decref(rctx->alpha);
+       rctx->dsa = r600_context_state_decref(rctx->dsa);
+       rctx->blend = r600_context_state_decref(rctx->blend);
+       rctx->stencil_ref = r600_context_state_decref(rctx->stencil_ref);
+       rctx->viewport = r600_context_state_decref(rctx->viewport);
+       rctx->framebuffer = r600_context_state_decref(rctx->framebuffer);
+       radeon_ctx_fini(&rctx->ctx);
        FREE(rctx);
 }
 
@@ -45,27 +61,35 @@ 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;
+       struct r600_query *rquery;
        static int dc = 0;
        char dname[256];
 
-       if (radeon_ctx_pm4(rctx->ctx))
-               return;
+       /* suspend queries */
+       r600_queries_suspend(ctx);
        /* FIXME dumping should be removed once shader support instructions
         * without throwing bad code
         */
-       if (!rctx->ctx->cpm4)
+       if (!rctx->ctx.cdwords)
                goto out;
+#if 0
        sprintf(dname, "gallium-%08d.bof", dc);
-       if (dc < 1)
-               radeon_ctx_dump_bof(rctx->ctx, dname);
+       if (dc < 2) {
+               radeon_ctx_dump_bof(&rctx->ctx, dname);
+               R600_ERR("dumped %s\n", dname);
+       }
+#endif
 #if 1
-       radeon_ctx_submit(rctx->ctx);
+       radeon_ctx_submit(&rctx->ctx);
 #endif
+       LIST_FOR_EACH_ENTRY(rquery, &rctx->query_list, list) {
+               rquery->flushed = true;
+       }
        dc++;
 out:
-       rctx->ctx = radeon_ctx_decref(rctx->ctx);
-       rctx->ctx = radeon_ctx(rscreen->rw);
+       radeon_ctx_clear(&rctx->ctx);
+       /* resume queries */
+       r600_queries_resume(ctx);
 }
 
 static void r600_init_config(struct r600_context *rctx)
@@ -207,9 +231,9 @@ static void r600_init_config(struct r600_context *rctx)
                num_es_stack_entries = 0;
                break;
        }
-       rctx->hw_states.config = radeon_state(rctx->rw, R600_CONFIG_TYPE, R600_CONFIG);
+       radeon_state_init(&rctx->config, rctx->rw, R600_STATE_CONFIG, 0, 0);
 
-       rctx->hw_states.config->states[R600_CONFIG__SQ_CONFIG] = 0x00000000;
+       rctx->config.states[R600_CONFIG__SQ_CONFIG] = 0x00000000;
        switch (family) {
        case CHIP_RV610:
        case CHIP_RV620:
@@ -218,75 +242,85 @@ static void r600_init_config(struct r600_context *rctx)
        case CHIP_RV710:
                break;
        default:
-               rctx->hw_states.config->states[R600_CONFIG__SQ_CONFIG] |= S_008C00_VC_ENABLE(1);
+               rctx->config.states[R600_CONFIG__SQ_CONFIG] |= S_008C00_VC_ENABLE(1);
                break;
        }
-       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_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->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__VC_ENHANCE] = 0x00000000;
+       rctx->config.states[R600_CONFIG__SX_MISC] = 0x00000000;
 
-       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);
+       if (family >= CHIP_RV770) {
+               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__DB_DEBUG] = 0x00000000;
+               rctx->config.states[R600_CONFIG__DB_WATERMARKS] = 0x00420204;
+               rctx->config.states[R600_CONFIG__SPI_THREAD_GROUPING] = 0x00000000;
+               rctx->config.states[R600_CONFIG__PA_SC_MODE_CNTL] = 0x00514000;
+       } else {
+               rctx->config.states[R600_CONFIG__SQ_DYN_GPR_CNTL_PS_FLUSH_REQ] = 0x00000000;
+               rctx->config.states[R600_CONFIG__TA_CNTL_AUX] = 0x07000003;
+               rctx->config.states[R600_CONFIG__DB_DEBUG] = 0x82000000;
+               rctx->config.states[R600_CONFIG__DB_WATERMARKS] = 0x01020204;
+               rctx->config.states[R600_CONFIG__SPI_THREAD_GROUPING] = 0x00000001;
+               rctx->config.states[R600_CONFIG__PA_SC_MODE_CNTL] = 0x00004010;
+       }
+       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__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);
 }
 
 struct pipe_context *r600_create_context(struct pipe_screen *screen, void *priv)
@@ -320,7 +354,7 @@ struct pipe_context *r600_create_context(struct pipe_screen *screen, void *priv)
 
        r600_init_config(rctx);
 
-       rctx->ctx = radeon_ctx(rscreen->rw);
-       rctx->draw = radeon_draw(rscreen->rw);
+       radeon_ctx_init(&rctx->ctx, rscreen->rw);
+       radeon_draw_init(&rctx->draw, rscreen->rw);
        return &rctx->context;
 }
index 76d5de865324439d37464c21e6f79d1343e6c382..cea0813054597bb633bb25e5fdc2150945681792 100644 (file)
 #include <tgsi/tgsi_parse.h>
 #include <tgsi/tgsi_util.h>
 #include <util/u_blitter.h>
+#include <util/u_double_list.h>
 #include "radeon.h"
 #include "r600_shader.h"
 
+#define R600_QUERY_STATE_STARTED       (1 << 0)
+#define R600_QUERY_STATE_ENDED         (1 << 1)
+#define R600_QUERY_STATE_SUSPENDED     (1 << 2)
+
+struct r600_query {
+       u64                                     result;
+       /* The kind of query. Currently only OQ is supported. */
+       unsigned                                type;
+       /* How many results have been written, in dwords. It's incremented
+        * after end_query and flush. */
+       unsigned                                num_results;
+       /* if we've flushed the query */
+       boolean                                 flushed;
+       unsigned                                state;
+       /* The buffer where query results are stored. */
+       struct radeon_bo                        *buffer;
+       unsigned                                buffer_size;
+       /* linked list of queries */
+       struct list_head                        list;
+       struct radeon_state                     rstate;
+};
+
 /* XXX move this to a more appropriate place */
 union pipe_states {
        struct pipe_rasterizer_state            rasterizer;
@@ -72,13 +95,16 @@ enum pipe_state_type {
        pipe_type_count
 };
 
+#define R600_MAX_RSTATE                16
+
 struct r600_context_state {
        union pipe_states               state;
        unsigned                        refcount;
        unsigned                        type;
-       struct radeon_state             *rstate;
+       struct radeon_state             rstate[R600_MAX_RSTATE];
        struct r600_shader              shader;
        struct radeon_bo                *bo;
+       unsigned                        nrstate;
 };
 
 struct r600_vertex_element
@@ -89,28 +115,25 @@ struct r600_vertex_element
 };
 
 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 radeon_state     rasterizer;
+       struct radeon_state     scissor;
+       struct radeon_state     dsa;
+       struct radeon_state     cb_cntl;
 };
 
 struct r600_context {
        struct pipe_context             context;
        struct r600_screen              *screen;
        struct radeon                   *rw;
-       struct radeon_ctx               *ctx;
+       struct radeon_ctx               ctx;
        struct blitter_context          *blitter;
-       struct radeon_draw              *draw;
+       struct radeon_draw              draw;
+       struct radeon_state             config;
+       /* FIXME get rid of those vs_resource,vs/ps_constant */
+       struct radeon_state             vs_resource[160];
+       unsigned                        vs_nresource;
+       struct radeon_state             vs_constant[256];
+       struct radeon_state             ps_constant[256];
        /* hw states */
        struct r600_context_hw_states   hw_states;
        /* pipe states */
@@ -134,14 +157,15 @@ struct r600_context {
        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 radeon_state             *ps_sampler[PIPE_MAX_ATTRIBS];
+       struct radeon_state             *vs_sampler[PIPE_MAX_ATTRIBS];
+       struct radeon_state             *ps_sampler_view[PIPE_MAX_ATTRIBS];
+       struct radeon_state             *vs_sampler_view[PIPE_MAX_ATTRIBS];
        struct r600_vertex_element      *vertex_elements;
        struct pipe_vertex_buffer       vertex_buffer[PIPE_MAX_ATTRIBS];
        struct pipe_index_buffer        index_buffer;
-       struct pipe_blend_color         blend_color;
+       struct pipe_blend_color         blend_color;
+       struct list_head                query_list;
 };
 
 /* Convenience cast wrapper. */
@@ -150,13 +174,18 @@ static INLINE struct r600_context *r600_context(struct pipe_context *pipe)
     return (struct r600_context*)pipe;
 }
 
+static INLINE struct r600_query* r600_query(struct pipe_query* q)
+{
+    return (struct r600_query*)q;
+}
+
 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);
+int r600_context_hw_states(struct pipe_context *ctx);
 
 void r600_draw_vbo(struct pipe_context *ctx,
                    const struct pipe_draw_info *info);
@@ -178,4 +207,10 @@ extern int r600_pipe_shader_update(struct pipe_context *ctx,
 uint32_t r600_translate_texformat(enum pipe_format format,
                                  const unsigned char *swizzle_view, 
                                  uint32_t *word4_p, uint32_t *yuv_format_p);
+
+/* query */
+extern void r600_queries_resume(struct pipe_context *ctx);
+extern void r600_queries_suspend(struct pipe_context *ctx);
+
+
 #endif
index f0584551620dfd96b1013e1b031a95f6976c54a0..fabd337d239c757ba6d6b248df319ca3d4d7713d 100644 (file)
@@ -31,6 +31,7 @@
 #include <util/u_math.h>
 #include <util/u_inlines.h>
 #include <util/u_memory.h>
+#include "radeon.h"
 #include "r600_screen.h"
 #include "r600_context.h"
 #include "r600_resource.h"
@@ -38,8 +39,8 @@
 
 struct r600_draw {
        struct pipe_context     *ctx;
-       struct radeon_state     *draw;
-       struct radeon_state     *vgt;
+       struct radeon_state     draw;
+       struct radeon_state     vgt;
        unsigned                mode;
        unsigned                start;
        unsigned                count;
@@ -51,6 +52,7 @@ static int r600_draw_common(struct r600_draw *draw)
 {
        struct r600_context *rctx = r600_context(draw->ctx);
        struct r600_screen *rscreen = rctx->screen;
+       /* FIXME vs_resource */
        struct radeon_state *vs_resource;
        struct r600_resource *rbuffer;
        unsigned i, j, offset, format, prim;
@@ -58,7 +60,7 @@ static int r600_draw_common(struct r600_draw *draw)
        struct pipe_vertex_buffer *vertex_buffer;
        int r;
 
-       r = r600_context_hw_states(rctx);
+       r = r600_context_hw_states(draw->ctx);
        if (r)
                return r;
        switch (draw->index_size) {
@@ -81,6 +83,7 @@ static int r600_draw_common(struct r600_draw *draw)
        r = r600_conv_pipe_prim(draw->mode, &prim);
        if (r)
                return r;
+
        /* rebuild vertex shader if input format changed */
        r = r600_pipe_shader_update(draw->ctx, rctx->vs_shader);
        if (r)
@@ -88,26 +91,24 @@ 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->rstate);
-       if (r)
-               return r;
-       r = radeon_draw_set(rctx->draw, rctx->ps_shader->rstate);
-       if (r)
-               return r;
+       radeon_draw_bind(&rctx->draw, &rctx->vs_shader->rstate[0]);
+       radeon_draw_bind(&rctx->draw, &rctx->ps_shader->rstate[0]);
 
+       for (i = 0 ; i < rctx->vs_nresource; i++) {
+               radeon_state_fini(&rctx->vs_resource[i]);
+       }
        for (i = 0 ; i < rctx->vertex_elements->count; i++) {
+               vs_resource = &rctx->vs_resource[i];
                j = rctx->vertex_elements->elements[i].vertex_buffer_index;
                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;
+               radeon_state_init(vs_resource, rscreen->rw, R600_STATE_RESOURCE, i, R600_SHADER_VS);
                vs_resource->bo[0] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
                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_WORD1] = rbuffer->bo->size - offset - 1;
                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;
@@ -116,59 +117,61 @@ static int r600_draw_common(struct r600_draw *draw)
                vs_resource->states[R600_PS_RESOURCE__RESOURCE0_WORD6] = 0xC0000000;
                vs_resource->placement[0] = RADEON_GEM_DOMAIN_GTT;
                vs_resource->placement[1] = RADEON_GEM_DOMAIN_GTT;
-               r = radeon_draw_set_new(rctx->draw, vs_resource);
-               if (r)
+               r = radeon_state_pm4(vs_resource);
+               if (r) {
                        return r;
+               }
+               radeon_draw_bind(&rctx->draw, vs_resource);
        }
+       rctx->vs_nresource = rctx->vertex_elements->count;
        /* FIXME start need to change winsys */
-       draw->draw = radeon_state(rscreen->rw, R600_DRAW_TYPE, R600_DRAW);
-       if (draw->draw == NULL)
-               return -ENOMEM;
-       draw->draw->states[R600_DRAW__VGT_NUM_INDICES] = draw->count;
-       draw->draw->states[R600_DRAW__VGT_DRAW_INITIATOR] = vgt_draw_initiator;
+       radeon_state_init(&draw->draw, rscreen->rw, R600_STATE_DRAW, 0, 0);
+       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_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;
-               draw->draw->nbo = 1;
+               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;
+               draw->draw.nbo = 1;
        }
-       r = radeon_draw_set_new(rctx->draw, draw->draw);
-       if (r)
+       r = radeon_state_pm4(&draw->draw);
+       if (r) {
                return r;
-       draw->vgt = radeon_state(rscreen->rw, R600_VGT_TYPE, R600_VGT);
-       if (draw->vgt == NULL)
-               return -ENOMEM;
-       draw->vgt->states[R600_VGT__VGT_PRIMITIVE_TYPE] = prim;
-       draw->vgt->states[R600_VGT__VGT_MAX_VTX_INDX] = 0x00FFFFFF;
-       draw->vgt->states[R600_VGT__VGT_MIN_VTX_INDX] = 0x00000000;
-       draw->vgt->states[R600_VGT__VGT_INDX_OFFSET] = draw->start;
-       draw->vgt->states[R600_VGT__VGT_MULTI_PRIM_IB_RESET_INDX] = 0x00000000;
-       draw->vgt->states[R600_VGT__VGT_DMA_INDEX_TYPE] = vgt_dma_index_type;
-       draw->vgt->states[R600_VGT__VGT_PRIMITIVEID_EN] = 0x00000000;
-       draw->vgt->states[R600_VGT__VGT_DMA_NUM_INSTANCES] = 0x00000001;
-       draw->vgt->states[R600_VGT__VGT_MULTI_PRIM_IB_RESET_EN] = 0x00000000;
-       draw->vgt->states[R600_VGT__VGT_INSTANCE_STEP_RATE_0] = 0x00000000;
-       draw->vgt->states[R600_VGT__VGT_INSTANCE_STEP_RATE_1] = 0x00000000;
-       r = radeon_draw_set_new(rctx->draw, draw->vgt);
-       if (r)
+       }
+       radeon_draw_bind(&rctx->draw, &draw->draw);
+
+       radeon_state_init(&draw->vgt, rscreen->rw, R600_STATE_VGT, 0, 0);
+       draw->vgt.states[R600_VGT__VGT_PRIMITIVE_TYPE] = prim;
+       draw->vgt.states[R600_VGT__VGT_MAX_VTX_INDX] = 0x00FFFFFF;
+       draw->vgt.states[R600_VGT__VGT_MIN_VTX_INDX] = 0x00000000;
+       draw->vgt.states[R600_VGT__VGT_INDX_OFFSET] = draw->start;
+       draw->vgt.states[R600_VGT__VGT_MULTI_PRIM_IB_RESET_INDX] = 0x00000000;
+       draw->vgt.states[R600_VGT__VGT_DMA_INDEX_TYPE] = vgt_dma_index_type;
+       draw->vgt.states[R600_VGT__VGT_PRIMITIVEID_EN] = 0x00000000;
+       draw->vgt.states[R600_VGT__VGT_DMA_NUM_INSTANCES] = 0x00000001;
+       draw->vgt.states[R600_VGT__VGT_MULTI_PRIM_IB_RESET_EN] = 0x00000000;
+       draw->vgt.states[R600_VGT__VGT_INSTANCE_STEP_RATE_0] = 0x00000000;
+       draw->vgt.states[R600_VGT__VGT_INSTANCE_STEP_RATE_1] = 0x00000000;
+       r = radeon_state_pm4(&draw->vgt);
+       if (r) {
                return r;
-       /* FIXME */
-       r = radeon_ctx_set_draw_new(rctx->ctx, rctx->draw);
+       }
+       radeon_draw_bind(&rctx->draw, &draw->vgt);
+
+       r = radeon_ctx_set_draw(&rctx->ctx, &rctx->draw);
        if (r == -EBUSY) {
                r600_flush(draw->ctx, 0, NULL);
-               r = radeon_ctx_set_draw_new(rctx->ctx, rctx->draw);
+               r = radeon_ctx_set_draw(&rctx->ctx, &rctx->draw);
        }
-       if (r)
-               return r;
-       rctx->draw = radeon_draw_duplicate(rctx->draw);
-       return 0;
+       return r;
 }
 
 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;
+       int r;
 
        assert(info->index_bias == 0);
 
@@ -189,5 +192,7 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
                draw.index_size = 0;
                draw.index_buffer = NULL;
        }
-       r600_draw_common(&draw);
+       r = r600_draw_common(&draw);
+       if (r)
+         fprintf(stderr,"draw common failed %d\n", r);
 }
index 9b02ae680e72b0704f6fd82a2d27a346da09aca0..530940ed843e2989b6127ed9dee5fafad9e6f20e 100644 (file)
  *      Jerome Glisse
  *      Corbin Simpson
  */
+#include <errno.h>
 #include <util/u_inlines.h>
 #include <util/u_format.h>
 #include <util/u_memory.h>
 #include "r600_screen.h"
 #include "r600_context.h"
 
-static struct pipe_query *r600_create_query(struct pipe_context *pipe, unsigned query_type)
+static void r600_query_begin(struct r600_context *rctx, struct r600_query *rquery)
 {
-       return NULL;
+       struct r600_screen *rscreen = rctx->screen;
+       struct radeon_state *rstate = &rquery->rstate;
+
+       radeon_state_fini(rstate);
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_QUERY_BEGIN, 0, 0);
+       rstate->states[R600_QUERY__OFFSET] = rquery->num_results;
+       rstate->bo[0] = radeon_bo_incref(rscreen->rw, rquery->buffer);
+       rstate->nbo = 1;
+       rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
+       if (radeon_state_pm4(rstate)) {
+               radeon_state_fini(rstate);
+       }
+}
+
+static void r600_query_end(struct r600_context *rctx, struct r600_query *rquery)
+{
+       struct r600_screen *rscreen = rctx->screen;
+       struct radeon_state *rstate = &rquery->rstate;
+
+       radeon_state_fini(rstate);
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_QUERY_END, 0, 0);
+       rstate->states[R600_QUERY__OFFSET] = rquery->num_results + 8;
+       rstate->bo[0] = radeon_bo_incref(rscreen->rw, rquery->buffer);
+       rstate->nbo = 1;
+       rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
+       if (radeon_state_pm4(rstate)) {
+               radeon_state_fini(rstate);
+       }
 }
 
-static void r600_destroy_query(struct pipe_context *pipe, struct pipe_query *query)
+static struct pipe_query *r600_create_query(struct pipe_context *ctx, unsigned query_type)
 {
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+       struct r600_context *rctx = r600_context(ctx);
+       struct r600_query *q;
+
+       if (query_type != PIPE_QUERY_OCCLUSION_COUNTER)
+               return NULL;
+
+       q = CALLOC_STRUCT(r600_query);
+       if (!q)
+               return NULL;
+
+       q->type = query_type;
+       LIST_ADDTAIL(&q->list, &rctx->query_list);
+       q->buffer_size = 4096;
+
+       q->buffer = radeon_bo(rscreen->rw, 0, q->buffer_size, 1, NULL);
+       if (!q->buffer) {
+               FREE(q);
+               return NULL;
+       }
+       return (struct pipe_query *)q;
+}
+
+static void r600_destroy_query(struct pipe_context *ctx,
+                              struct pipe_query *query)
+{
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+       struct r600_query *q = r600_query(query);
+
+       radeon_bo_decref(rscreen->rw, q->buffer);
+       LIST_DEL(&q->list);
        FREE(query);
 }
 
-static void r600_begin_query(struct pipe_context *pipe, struct pipe_query *query)
+static void r600_query_result(struct pipe_context *ctx, struct r600_query *rquery)
 {
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+       u64 start, end;
+       u32 *results;
+       int i;
+
+       radeon_bo_wait(rscreen->rw, rquery->buffer);
+       radeon_bo_map(rscreen->rw, rquery->buffer);
+       results = rquery->buffer->data;
+       for (i = 0; i < rquery->num_results; i += 4) {
+               start = (u64)results[i] | (u64)results[i + 1] << 32;
+               end = (u64)results[i + 2] | (u64)results[i + 3] << 32;
+               if ((start & 0x8000000000000000UL) && (end & 0x8000000000000000UL)) {
+                       rquery->result += end - start;
+               }
+       }
+       radeon_bo_unmap(rscreen->rw, rquery->buffer);
+       rquery->num_results = 0;
 }
 
-static void r600_end_query(struct pipe_context *pipe, struct pipe_query *query)
+static void r600_query_resume(struct pipe_context *ctx, struct r600_query *rquery)
 {
+       struct r600_context *rctx = r600_context(ctx);
+
+       if (rquery->num_results >= ((rquery->buffer_size >> 2) - 2)) {
+               /* running out of space */
+               if (!rquery->flushed) {
+                       ctx->flush(ctx, 0, NULL);
+               }
+               r600_query_result(ctx, rquery);
+       }
+       r600_query_begin(rctx, rquery);
+       rquery->flushed = false;
+}
+
+static void r600_query_suspend(struct pipe_context *ctx, struct r600_query *rquery)
+{
+       struct r600_context *rctx = r600_context(ctx);
+
+       r600_query_end(rctx, rquery);
+       rquery->num_results += 16;
 }
 
-static boolean r600_get_query_result(struct pipe_context *pipe,
+static void r600_begin_query(struct pipe_context *ctx, struct pipe_query *query)
+{
+       struct r600_context *rctx = r600_context(ctx);
+       struct r600_query *rquery = r600_query(query);
+       int r;
+
+       rquery->state = R600_QUERY_STATE_STARTED;
+       rquery->num_results = 0;
+       rquery->flushed = false;
+       r600_query_resume(ctx, rquery);
+       r = radeon_ctx_set_query_state(&rctx->ctx, &rquery->rstate);
+       if (r == -EBUSY) {
+               /* this shouldn't happen */
+               R600_ERR("had to flush while emitting end query\n");
+               ctx->flush(ctx, 0, NULL);
+               r = radeon_ctx_set_query_state(&rctx->ctx, &rquery->rstate);
+       }
+}
+
+static void r600_end_query(struct pipe_context *ctx, struct pipe_query *query)
+{
+       struct r600_context *rctx = r600_context(ctx);
+       struct r600_query *rquery = r600_query(query);
+       int r;
+
+       rquery->state &= ~R600_QUERY_STATE_STARTED;
+       rquery->state |= R600_QUERY_STATE_ENDED;
+       r600_query_suspend(ctx, rquery);
+       r = radeon_ctx_set_query_state(&rctx->ctx, &rquery->rstate);
+       if (r == -EBUSY) {
+               /* this shouldn't happen */
+               R600_ERR("had to flush while emitting end query\n");
+               ctx->flush(ctx, 0, NULL);
+               r = radeon_ctx_set_query_state(&rctx->ctx, &rquery->rstate);
+       }
+}
+
+void r600_queries_suspend(struct pipe_context *ctx)
+{
+       struct r600_context *rctx = r600_context(ctx);
+       struct r600_query *rquery;
+       int r;
+
+       LIST_FOR_EACH_ENTRY(rquery, &rctx->query_list, list) {
+               if (rquery->state & R600_QUERY_STATE_STARTED) {
+                       r600_query_suspend(ctx, rquery);
+                       r = radeon_ctx_set_query_state(&rctx->ctx, &rquery->rstate);
+                       if (r == -EBUSY) {
+                               /* this shouldn't happen */
+                               R600_ERR("had to flush while emitting end query\n");
+                               ctx->flush(ctx, 0, NULL);
+                               r = radeon_ctx_set_query_state(&rctx->ctx, &rquery->rstate);
+                       }
+               }
+               rquery->state |= R600_QUERY_STATE_SUSPENDED;
+       }
+}
+
+void r600_queries_resume(struct pipe_context *ctx)
+{
+       struct r600_context *rctx = r600_context(ctx);
+       struct r600_query *rquery;
+       int r;
+
+       LIST_FOR_EACH_ENTRY(rquery, &rctx->query_list, list) {
+               if (rquery->state & R600_QUERY_STATE_STARTED) {
+                       r600_query_resume(ctx, rquery);
+                       r = radeon_ctx_set_query_state(&rctx->ctx, &rquery->rstate);
+                       if (r == -EBUSY) {
+                               /* this shouldn't happen */
+                               R600_ERR("had to flush while emitting end query\n");
+                               ctx->flush(ctx, 0, NULL);
+                               r = radeon_ctx_set_query_state(&rctx->ctx, &rquery->rstate);
+                       }
+               }
+               rquery->state &= ~R600_QUERY_STATE_SUSPENDED;
+       }
+}
+
+static boolean r600_get_query_result(struct pipe_context *ctx,
                                        struct pipe_query *query,
-                                       boolean wait, void *result)
+                                       boolean wait, void *vresult)
 {
+       struct r600_query *rquery = r600_query(query);
+       uint64_t *result = (uint64_t*)vresult;
+
+       if (!rquery->flushed) {
+               ctx->flush(ctx, 0, NULL);
+               rquery->flushed = true;
+       }
+       r600_query_result(ctx, rquery);
+       *result = rquery->result;
+       rquery->result = 0;
        return TRUE;
 }
 
 void r600_init_query_functions(struct r600_context* rctx)
 {
+       LIST_INITHEAD(&rctx->query_list);
+
        rctx->context.create_query = r600_create_query;
        rctx->context.destroy_query = r600_destroy_query;
        rctx->context.begin_query = r600_begin_query;
index bb90e76fb78dae66677d8925f58ea7f46f1a9e54..129667ad20fc79517bf348f9ce7799ce4ead12a0 100644 (file)
@@ -44,10 +44,22 @@ struct r600_resource_texture {
        struct r600_resource            resource;
        unsigned long                   offset[PIPE_MAX_TEXTURE_LEVELS];
        unsigned long                   pitch[PIPE_MAX_TEXTURE_LEVELS];
+       unsigned long                   width[PIPE_MAX_TEXTURE_LEVELS];
+       unsigned long                   height[PIPE_MAX_TEXTURE_LEVELS];
        unsigned long                   layer_size[PIPE_MAX_TEXTURE_LEVELS];
        unsigned long                   pitch_override;
        unsigned long                   bpt;
        unsigned long                   size;
+       unsigned                        tilled;
+       unsigned                        array_mode;
+       unsigned                        tile_type;
+       unsigned                        depth;
+       unsigned                        dirty;
+       struct radeon_bo                *uncompressed;
+       struct radeon_state             scissor[PIPE_MAX_TEXTURE_LEVELS];
+       struct radeon_state             cb[8][PIPE_MAX_TEXTURE_LEVELS];
+       struct radeon_state             db[PIPE_MAX_TEXTURE_LEVELS];
+       struct radeon_state             viewport[PIPE_MAX_TEXTURE_LEVELS];
 };
 
 void r600_init_context_resource_functions(struct r600_context *r600);
index cdaca9ed7dbf487f5027a4118089ebef8c0fb7ac..a047a49a6c55cd7d55e4f5dfd90b54dedf4fb8bb 100644 (file)
@@ -69,6 +69,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
        case PIPE_CAP_TEXTURE_SWIZZLE:
        case PIPE_CAP_INDEP_BLEND_ENABLE:
        case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
+       case PIPE_CAP_DEPTH_CLAMP:
                return 1;
 
        /* Unsupported features (boolean caps). */
@@ -77,7 +78,6 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
        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. */
@@ -234,11 +234,34 @@ static void r600_destroy_screen(struct pipe_screen* pscreen)
 struct pipe_screen *r600_screen_create(struct radeon *rw)
 {
        struct r600_screen* rscreen;
+       enum radeon_family family = radeon_get_family(rw);
 
        rscreen = CALLOC_STRUCT(r600_screen);
        if (rscreen == NULL) {
                return NULL;
        }
+
+       switch (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:
+               rscreen->chip_class = R600;
+               break;
+       case CHIP_RV770:
+       case CHIP_RV730:
+       case CHIP_RV710:
+       case CHIP_RV740:
+               rscreen->chip_class = R700;
+               break;
+       default:
+               FREE(rscreen);
+               return NULL;
+       }
        rscreen->rw = rw;
        rscreen->screen.winsys = (struct pipe_winsys*)rw;
        rscreen->screen.destroy = r600_destroy_screen;
index 53b560c617f000f1bf5e05dee7e6dedc92964ed2..b9938f117a83d95bfd2d6a10859afbd711bbd883 100644 (file)
@@ -30,6 +30,7 @@
 #include <radeon_drm.h>
 #include "radeon.h"
 #include "util/u_transfer.h"
+#include "r600_resource.h"
 
 /* Texture transfer. */
 struct r600_transfer {
@@ -38,11 +39,19 @@ struct r600_transfer {
        /* Buffer transfer. */
        struct pipe_transfer            *buffer_transfer;
        unsigned                        offset;
+       struct pipe_resource            *linear_texture;
+};
+
+enum chip_class {
+       R600,
+       R700,
+       EVERGREEN,
 };
 
 struct r600_screen {
        struct pipe_screen              screen;
        struct radeon                   *rw;
+       enum chip_class                 chip_class;
 };
 
 static INLINE struct r600_screen *r600_screen(struct pipe_screen *screen)
@@ -62,7 +71,7 @@ unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context,
 struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen,
                                              struct winsys_handle *whandle);
 
-/* Texture transfer functions. */
+/* r600_texture.c texture transfer functions. */
 struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
                                                struct pipe_resource *texture,
                                                struct pipe_subresource sr,
@@ -74,7 +83,14 @@ void* r600_texture_transfer_map(struct pipe_context *ctx,
                                struct pipe_transfer* transfer);
 void r600_texture_transfer_unmap(struct pipe_context *ctx,
                                 struct pipe_transfer* transfer);
+int r600_texture_scissor(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level);
+int r600_texture_cb(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned cb, unsigned level);
+int r600_texture_db(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level);
+int r600_texture_from_depth(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level);
+int r600_texture_viewport(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level);
 
+/* r600_blit.c */
+int r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level);
 
 /* helpers */
 int r600_conv_pipe_format(unsigned pformat, unsigned *format);
index 956c7e7930cfd0e68221e73504158f64f196f6d1..0ba26a23112f82ae36dc0adb9e4458a144ca3f02 100644 (file)
@@ -48,6 +48,9 @@ struct r600_shader_ctx {
        struct r600_bc                          *bc;
        struct r600_shader                      *shader;
        u32                                     value[4];
+       u32                                     *literals;
+       u32                                     nliterals;
+       u32                                     max_driver_temp_used;
 };
 
 struct r600_shader_tgsi_instruction {
@@ -105,8 +108,8 @@ int r600_pipe_shader_create(struct pipe_context *ctx,
        struct r600_screen *rscreen = r600_screen(ctx->screen);
        int r;
 
-fprintf(stderr, "--------------------------------------------------------------\n");
-tgsi_dump(tokens, 0);
+//fprintf(stderr, "--------------------------------------------------------------\n");
+//tgsi_dump(tokens, 0);
        if (rpshader == NULL)
                return -ENOMEM;
        rpshader->shader.family = radeon_get_family(rscreen->rw);
@@ -120,7 +123,7 @@ tgsi_dump(tokens, 0);
                R600_ERR("building bytecode failed !\n");
                return r;
        }
-fprintf(stderr, "______________________________________________________________\n");
+//fprintf(stderr, "______________________________________________________________\n");
        return 0;
 }
 
@@ -131,10 +134,9 @@ static int r600_pipe_shader_vs(struct pipe_context *ctx, struct r600_context_sta
        struct radeon_state *state;
        unsigned i, tmp;
 
-       rpshader->rstate = radeon_state_decref(rpshader->rstate);
-       state = radeon_state(rscreen->rw, R600_VS_SHADER_TYPE, R600_VS_SHADER);
-       if (state == NULL)
-               return -ENOMEM;
+       state = &rpshader->rstate[0];
+       radeon_state_fini(&rpshader->rstate[0]);
+       radeon_state_init(state, rscreen->rw, R600_STATE_SHADER, 0, R600_SHADER_VS);
        for (i = 0; i < 10; i++) {
                state->states[R600_VS_SHADER__SPI_VS_OUT_ID_0 + i] = 0;
        }
@@ -144,12 +146,13 @@ static int r600_pipe_shader_vs(struct pipe_context *ctx, struct r600_context_sta
                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;
+       state->states[R600_VS_SHADER__SQ_PGM_RESOURCES_VS] = S_028868_NUM_GPRS(rshader->bc.ngpr) |
+               S_028868_STACK_SIZE(rshader->bc.nstack);
+       state->bo[0] = radeon_bo_incref(rscreen->rw, rpshader->bo);
+       state->bo[1] = radeon_bo_incref(rscreen->rw, rpshader->bo);
+       state->nbo = 2;
+       state->placement[0] = RADEON_GEM_DOMAIN_GTT;
+       state->placement[2] = RADEON_GEM_DOMAIN_GTT;
        return radeon_state_pm4(state);
 }
 
@@ -161,17 +164,20 @@ static int r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_context_sta
        struct r600_context *rctx = r600_context(ctx);
        struct radeon_state *state;
        unsigned i, tmp, exports_ps, num_cout;
+       boolean have_pos = FALSE;
 
+       state = &rpshader->rstate[0];
        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;
+       radeon_state_fini(state);
+       radeon_state_init(state, rscreen->rw, R600_STATE_SHADER, 0, R600_SHADER_PS);
        for (i = 0; i < rshader->ninput; i++) {
                tmp = S_028644_SEMANTIC(i);
                tmp |= S_028644_SEL_CENTROID(1);
+               if (rshader->input[i].name == TGSI_SEMANTIC_POSITION)
+                       have_pos = TRUE;
                if (rshader->input[i].name == TGSI_SEMANTIC_COLOR ||
-                       rshader->input[i].name == TGSI_SEMANTIC_BCOLOR) {
+                   rshader->input[i].name == TGSI_SEMANTIC_BCOLOR ||
+                   rshader->input[i].name == TGSI_SEMANTIC_POSITION) {
                        tmp |= S_028644_FLAT_SHADE(rshader->flat_shade);
                }
                if (rasterizer->sprite_coord_enable & (1 << i)) {
@@ -190,15 +196,24 @@ static int r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_context_sta
                        num_cout++;
                }
        }
+       if (!exports_ps) {
+               /* always at least export 1 component per pixel */
+               exports_ps = 2;
+       }
        state->states[R600_PS_SHADER__SPI_PS_IN_CONTROL_0] = S_0286CC_NUM_INTERP(rshader->ninput) |
                                                        S_0286CC_PERSP_GRADIENT_ENA(1);
+       if (have_pos) {
+               state->states[R600_PS_SHADER__SPI_PS_IN_CONTROL_0] |=  S_0286CC_POSITION_ENA(1) |
+                                                                      S_0286CC_BARYC_SAMPLE_CNTL(1);
+               state->states[R600_PS_SHADER__SPI_INPUT_Z] |= 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->bc.ngpr);
+       state->states[R600_PS_SHADER__SQ_PGM_RESOURCES_PS] = S_028868_NUM_GPRS(rshader->bc.ngpr) |
+               S_028868_STACK_SIZE(rshader->bc.nstack);
        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;
+       state->bo[0] = radeon_bo_incref(rscreen->rw, rpshader->bo);
+       state->nbo = 1;
+       state->placement[0] = RADEON_GEM_DOMAIN_GTT;
        return radeon_state_pm4(state);
 }
 
@@ -268,21 +283,24 @@ static int tgsi_is_supported(struct r600_shader_ctx *ctx)
                R600_ERR("predicate unsupported\n");
                return -EINVAL;
        }
+#if 0
        if (i->Instruction.Label) {
                R600_ERR("label unsupported\n");
                return -EINVAL;
        }
+#endif
        for (j = 0; j < i->Instruction.NumSrcRegs; j++) {
-               if (i->Src[j].Register.Indirect ||
-                       i->Src[j].Register.Dimension ||
+               if (i->Src[j].Register.Dimension ||
                        i->Src[j].Register.Absolute) {
-                       R600_ERR("unsupported src (indirect|dimension|absolute)\n");
+                       R600_ERR("unsupported src %d (dimension %d|absolute %d)\n", j,
+                                i->Src[j].Register.Dimension,
+                                i->Src[j].Register.Absolute);
                        return -EINVAL;
                }
        }
        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");
+               if (i->Dst[j].Register.Dimension) {
+                       R600_ERR("unsupported dst (dimension)\n");
                        return -EINVAL;
                }
        }
@@ -333,6 +351,7 @@ static int tgsi_declaration(struct r600_shader_ctx *ctx)
        case TGSI_FILE_CONSTANT:
        case TGSI_FILE_TEMPORARY:
        case TGSI_FILE_SAMPLER:
+       case TGSI_FILE_ADDRESS:
                break;
        default:
                R600_ERR("unsupported file %d declaration\n", d->Declaration.File);
@@ -341,6 +360,11 @@ static int tgsi_declaration(struct r600_shader_ctx *ctx)
        return 0;
 }
 
+static int r600_get_temp(struct r600_shader_ctx *ctx)
+{
+       return ctx->temp_reg + ctx->max_driver_temp_used++;
+}
+
 int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader)
 {
        struct tgsi_full_immediate *immediate;
@@ -362,9 +386,15 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s
        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]. 
+       /* Values [0,127] correspond to GPR[0..127].
+        * Values [128,159] correspond to constant buffer bank 0
+        * Values [160,191] correspond to constant buffer bank 1
+        * Values [256,511] correspond to cfile constants c[0..255].
         * Other special values are shown in the list below.
+        * 244  ALU_SRC_1_DBL_L: special constant 1.0 double-float, LSW. (RV670+)
+        * 245  ALU_SRC_1_DBL_M: special constant 1.0 double-float, MSW. (RV670+)
+        * 246  ALU_SRC_0_5_DBL_L: special constant 0.5 double-float, LSW. (RV670+)
+        * 247  ALU_SRC_0_5_DBL_M: special constant 0.5 double-float, MSW. (RV670+)
         * 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.
@@ -389,15 +419,24 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s
        ctx.temp_reg = ctx.file_offset[TGSI_FILE_TEMPORARY] +
                        ctx.info.file_count[TGSI_FILE_TEMPORARY];
 
+       ctx.nliterals = 0;
+       ctx.literals = NULL;
+
        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;
+                       ctx.literals = realloc(ctx.literals, (ctx.nliterals + 1) * 16);
+                       if(ctx.literals == NULL) {
+                               r = -ENOMEM;
+                               goto out_err;
+                       }
+                       ctx.literals[ctx.nliterals * 4 + 0] = immediate->u[0].Uint;
+                       ctx.literals[ctx.nliterals * 4 + 1] = immediate->u[1].Uint;
+                       ctx.literals[ctx.nliterals * 4 + 2] = immediate->u[2].Uint;
+                       ctx.literals[ctx.nliterals * 4 + 3] = immediate->u[3].Uint;
+                       ctx.nliterals++;
                        break;
                case TGSI_TOKEN_TYPE_DECLARATION:
                        r = tgsi_declaration(&ctx);
@@ -408,6 +447,9 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s
                        r = tgsi_is_supported(&ctx);
                        if (r)
                                goto out_err;
+                       ctx.max_driver_temp_used = 0;
+                       /* reserve first tmp for everyone */
+                       r600_get_temp(&ctx);
                        opcode = ctx.parse.FullToken.FullInstruction.Instruction.Opcode;
                        ctx.inst_info = &r600_shader_tgsi_instruction[opcode];
                        r = ctx.inst_info->process(&ctx);
@@ -458,6 +500,8 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s
                                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].swizzle_x = 2;
+                               output[i].swizzle_y = output[i].swizzle_z = output[i].swizzle_w = 7;
                                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);
@@ -504,7 +548,7 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s
                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].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
                output[0].array_base = 0;
                output[0].inst = V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT;
                noutput++;
@@ -525,9 +569,11 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s
                if (r)
                        goto out_err;
        }
+       free(ctx.literals);
        tgsi_parse_free(&ctx.parse);
        return 0;
 out_err:
+       free(ctx.literals);
        tgsi_parse_free(&ctx.parse);
        return r;
 }
@@ -547,11 +593,19 @@ static int tgsi_src(struct r600_shader_ctx *ctx,
                        const struct tgsi_full_src_register *tgsi_src,
                        struct r600_bc_alu_src *r600_src)
 {
+       int index;
        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;
+               index = tgsi_src->Register.Index;
+               ctx->value[0] = ctx->literals[index * 4 + 0];
+               ctx->value[1] = ctx->literals[index * 4 + 1];
+               ctx->value[2] = ctx->literals[index * 4 + 2];
+               ctx->value[3] = ctx->literals[index * 4 + 3];
        }
+       if (tgsi_src->Register.Indirect)
+               r600_src->rel = V_SQ_REL_RELATIVE;
        r600_src->neg = tgsi_src->Register.Negate;
        r600_src->sel += ctx->file_offset[tgsi_src->Register.File];
        return 0;
@@ -568,6 +622,8 @@ static int tgsi_dst(struct r600_shader_ctx *ctx,
        r600_dst->sel += ctx->file_offset[tgsi_dst->Register.File];
        r600_dst->chan = swizzle;
        r600_dst->write = 1;
+       if (tgsi_dst->Register.Indirect)
+               r600_dst->rel = V_SQ_REL_RELATIVE;
        if (inst->Instruction.Saturate) {
                r600_dst->clamp = 1;
        }
@@ -607,12 +663,13 @@ static int tgsi_split_constant(struct r600_shader_ctx *ctx, struct r600_bc_alu_s
        }
        for (i = 0, j = nconst - 1; i < inst->Instruction.NumSrcRegs; i++) {
                if (inst->Src[j].Register.File == TGSI_FILE_CONSTANT && j > 0) {
+                       int treg = r600_get_temp(ctx);
                        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].sel = r600_src[j].sel;
                                alu.src[0].chan = k;
-                               alu.dst.sel = ctx->temp_reg + j;
+                               alu.dst.sel = treg;
                                alu.dst.chan = k;
                                alu.dst.write = 1;
                                if (k == 3)
@@ -621,37 +678,90 @@ static int tgsi_split_constant(struct r600_shader_ctx *ctx, struct r600_bc_alu_s
                                if (r)
                                        return r;
                        }
-                       r600_src[0].sel = ctx->temp_reg + j;
+                       r600_src[j].sel = treg;
                        j--;
                }
        }
        return 0;
 }
 
-static int tgsi_op2(struct r600_shader_ctx *ctx)
+/* need to move any immediate into a temp - for trig functions which use literal for PI stuff */
+static int tgsi_split_literal_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, nliteral, r;
+
+       for (i = 0, nliteral = 0; i < inst->Instruction.NumSrcRegs; i++) {
+               if (inst->Src[i].Register.File == TGSI_FILE_IMMEDIATE) {
+                       nliteral++;
+               }
+       }
+       for (i = 0, j = 0; i < inst->Instruction.NumSrcRegs; i++) {
+               if (inst->Src[j].Register.File == TGSI_FILE_IMMEDIATE) {
+                       int treg = r600_get_temp(ctx);
+                       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[j].sel;
+                               alu.src[0].chan = k;
+                               alu.dst.sel = treg;
+                               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;
+                       }
+                       r = r600_bc_add_literal(ctx->bc, ctx->value);
+                       if (r)
+                               return r;
+                       r600_src[j].sel = treg;
+                       j++;
+               }
+       }
+       return 0;
+}
+
+static int tgsi_op2_s(struct r600_shader_ctx *ctx, int swap)
 {
        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;
+       int lasti = 0;
+
+       for (i = 0; i < 4; i++) {
+               if (inst->Dst[0].Register.WriteMask & (1 << i)) {
+                       lasti = i;
+               }
+       }
 
        r = tgsi_split_constant(ctx, r600_src);
        if (r)
                return r;
-       for (i = 0; i < 4; i++) {
+       for (i = 0; i < lasti + 1; i++) {
+               if (!(inst->Dst[0].Register.WriteMask & (1 << i)))
+                       continue;
+
                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;
+               r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
+               if (r)
+                       return r;
+               
+               alu.inst = ctx->inst_info->r600_opcode;
+               if (!swap) {
                        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;
+               } else {
+                       alu.src[0] = r600_src[1];
+                       alu.src[0].chan = tgsi_chan(&inst->Src[1], i);
+
+                       alu.src[1] = r600_src[0];
+                       alu.src[1].chan = tgsi_chan(&inst->Src[0], i);
                }
                /* handle some special cases */
                switch (ctx->inst_info->tgsi_opcode) {
@@ -664,7 +774,7 @@ static int tgsi_op2(struct r600_shader_ctx *ctx)
                default:
                        break;
                }
-               if (i == 3) {
+               if (i == lasti) {
                        alu.last = 1;
                }
                r = r600_bc_add_alu(ctx->bc, &alu);
@@ -674,24 +784,154 @@ static int tgsi_op2(struct r600_shader_ctx *ctx)
        return 0;
 }
 
-static int tgsi_kill(struct r600_shader_ctx *ctx)
+static int tgsi_op2(struct r600_shader_ctx *ctx)
+{
+       return tgsi_op2_s(ctx, 0);
+}
+
+static int tgsi_op2_swap(struct r600_shader_ctx *ctx)
+{
+       return tgsi_op2_s(ctx, 1);
+}
+
+/* 
+ * r600 - trunc to -PI..PI range
+ * r700 - normalize by dividing by 2PI
+ * see fdo bug 27901
+ */
+static int tgsi_setup_trig(struct r600_shader_ctx *ctx,
+                          struct r600_bc_alu_src r600_src[3])
+{
+       struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+       int r;
+       uint32_t lit_vals[4];
+       struct r600_bc_alu alu;
+       
+       memset(lit_vals, 0, 4*4);
+       r = tgsi_split_constant(ctx, r600_src);
+       if (r)
+               return r;
+
+       r = tgsi_split_literal_constant(ctx, r600_src);
+       if (r)
+               return r;
+
+       lit_vals[0] = fui(1.0 /(3.1415926535 * 2));
+       lit_vals[1] = fui(0.5f);
+
+       memset(&alu, 0, sizeof(struct r600_bc_alu));
+       alu.inst = V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD;
+       alu.is_op3 = 1;
+
+       alu.dst.chan = 0;
+       alu.dst.sel = ctx->temp_reg;
+       alu.dst.write = 1;
+
+       alu.src[0] = r600_src[0];
+       alu.src[0].chan = tgsi_chan(&inst->Src[0], 0);
+               
+       alu.src[1].sel = V_SQ_ALU_SRC_LITERAL;
+       alu.src[1].chan = 0;
+       alu.src[2].sel = V_SQ_ALU_SRC_LITERAL;
+       alu.src[2].chan = 1;
+       alu.last = 1;
+       r = r600_bc_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+       r = r600_bc_add_literal(ctx->bc, lit_vals);
+       if (r)
+               return r;
+
+       memset(&alu, 0, sizeof(struct r600_bc_alu));
+       alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FRACT;
+               
+       alu.dst.chan = 0;
+       alu.dst.sel = ctx->temp_reg;
+       alu.dst.write = 1;
+
+       alu.src[0].sel = ctx->temp_reg;
+       alu.src[0].chan = 0;
+       alu.last = 1;
+       r = r600_bc_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       if (ctx->bc->chiprev == 0) {
+               lit_vals[0] = fui(3.1415926535897f * 2.0f);
+               lit_vals[1] = fui(-3.1415926535897f);
+       } else {
+               lit_vals[0] = fui(1.0f);
+               lit_vals[1] = fui(-0.5f);
+       }
+
+       memset(&alu, 0, sizeof(struct r600_bc_alu));
+       alu.inst = V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD;
+       alu.is_op3 = 1;
+
+       alu.dst.chan = 0;
+       alu.dst.sel = ctx->temp_reg;
+       alu.dst.write = 1;
+
+       alu.src[0].sel = ctx->temp_reg;
+       alu.src[0].chan = 0;
+               
+       alu.src[1].sel = V_SQ_ALU_SRC_LITERAL;
+       alu.src[1].chan = 0;
+       alu.src[2].sel = V_SQ_ALU_SRC_LITERAL;
+       alu.src[2].chan = 1;
+       alu.last = 1;
+       r = r600_bc_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+       r = r600_bc_add_literal(ctx->bc, lit_vals);
+       if (r)
+               return r;
+       return 0;
+}
+
+static int tgsi_trig(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;
+       int lasti = 0;
 
+       r = tgsi_setup_trig(ctx, r600_src);
+       if (r)
+               return r;
+
+       memset(&alu, 0, sizeof(struct r600_bc_alu));
+       alu.inst = ctx->inst_info->r600_opcode;
+       alu.dst.chan = 0;
+       alu.dst.sel = ctx->temp_reg;
+       alu.dst.write = 1;
+
+       alu.src[0].sel = ctx->temp_reg;
+       alu.src[0].chan = 0;
+       alu.last = 1;
+       r = r600_bc_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       /* replicate result */
        for (i = 0; i < 4; i++) {
+               if (inst->Dst[0].Register.WriteMask & (1 << i))
+                       lasti = i;
+       }
+       for (i = 0; i < lasti + 1; i++) {
+               if (!(inst->Dst[0].Register.WriteMask & (1 << i)))
+                       continue;
+
                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]);
+               alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV;
+
+               alu.src[0].sel = ctx->temp_reg;
+               r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
                if (r)
                        return r;
-               alu.src[1].chan = tgsi_chan(&inst->Src[0], i);
-               if (i == 3) {
+               if (i == lasti)
                        alu.last = 1;
-               }
                r = r600_bc_add_alu(ctx->bc, &alu);
                if (r)
                        return r;
@@ -699,30 +939,70 @@ static int tgsi_kill(struct r600_shader_ctx *ctx)
        return 0;
 }
 
-static int tgsi_slt(struct r600_shader_ctx *ctx)
+static int tgsi_scs(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;
+       int r;
 
-       r = tgsi_split_constant(ctx, r600_src);
+       r = tgsi_setup_trig(ctx, r600_src);
+       if (r)
+               return r;
+
+
+       /* dst.x = COS */
+       memset(&alu, 0, sizeof(struct r600_bc_alu));
+       alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_COS;
+       r = tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst);
+       if (r)
+               return r;
+
+       alu.src[0].sel = ctx->temp_reg;
+       alu.src[0].chan = 0;
+       alu.last = 1;
+       r = r600_bc_add_alu(ctx->bc, &alu);
+       if (r)
+               return r;
+
+       /* dst.y = SIN */
+       memset(&alu, 0, sizeof(struct r600_bc_alu));
+       alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SIN;
+       r = tgsi_dst(ctx, &inst->Dst[0], 1, &alu.dst);
+       if (r)
+               return r;
+
+       alu.src[0].sel = ctx->temp_reg;
+       alu.src[0].chan = 0;
+       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));
-               if (!(inst->Dst[0].Register.WriteMask & (1 << i))) {
-                       alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
-                       alu.dst.chan = i;
+               alu.inst = ctx->inst_info->r600_opcode;
+
+               alu.dst.chan = i;
+
+               alu.src[0].sel = V_SQ_ALU_SRC_0;
+
+               if (ctx->inst_info->tgsi_opcode == TGSI_OPCODE_KILP) {
+                       alu.src[1].sel = V_SQ_ALU_SRC_1;
+                       alu.src[1].neg = 1;
                } 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);
+                       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;
@@ -731,6 +1011,13 @@ static int tgsi_slt(struct r600_shader_ctx *ctx)
                if (r)
                        return r;
        }
+       r = r600_bc_add_literal(ctx->bc, ctx->value);
+       if (r)
+               return r;
+
+       /* kill must be last in ALU */
+       ctx->bc->force_add_cf = 1;
+       ctx->shader->uses_kill = TRUE;
        return 0;
 }
 
@@ -738,12 +1025,20 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
 {
        struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
        struct r600_bc_alu alu;
+       struct r600_bc_alu_src r600_src[3];
        int r;
 
+       r = tgsi_split_constant(ctx, r600_src);
+       if (r)
+               return r;
+       r = tgsi_split_literal_constant(ctx, r600_src);
+       if (r)
+               return 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].sel  = V_SQ_ALU_SRC_1; /*1.0*/
        alu.src[0].chan = 0;
        r = tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst);
        if (r)
@@ -756,11 +1051,9 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
        /* 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);
+       alu.src[0] = r600_src[0];
+       alu.src[1].sel  = V_SQ_ALU_SRC_0; /*0.0*/
+       alu.src[1].chan = 0;
        r = tgsi_dst(ctx, &inst->Dst[0], 1, &alu.dst);
        if (r)
                return r;
@@ -769,18 +1062,10 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
        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].sel  = V_SQ_ALU_SRC_1;
        alu.src[0].chan = 0;
        r = tgsi_dst(ctx, &inst->Dst[0], 3, &alu.dst);
        if (r)
@@ -791,6 +1076,10 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
        if (r)
                return r;
 
+       r = r600_bc_add_literal(ctx->bc, ctx->value);
+       if (r)
+               return r;
+
        if (inst->Dst[0].Register.WriteMask & (1 << 2))
        {
                int chan;
@@ -799,9 +1088,7 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
                /* 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] = r600_src[0];
                alu.src[0].chan = tgsi_chan(&inst->Src[0], 1);
                r = tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst);
                if (r)
@@ -811,21 +1098,22 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
                if (r)
                        return r;
 
+               r = r600_bc_add_literal(ctx->bc, ctx->value);
+               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] = r600_src[0];
                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] = r600_src[0];
                alu.src[2].chan = tgsi_chan(&inst->Src[0], 0);
                alu.dst.sel = ctx->temp_reg;
                alu.dst.chan = 0;
@@ -836,6 +1124,9 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
                if (r)
                        return r;
 
+               r = r600_bc_add_literal(ctx->bc, ctx->value);
+               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;
@@ -880,36 +1171,168 @@ static int tgsi_trans(struct r600_shader_ctx *ctx)
        return 0;
 }
 
-static int tgsi_trans_srcx_replicate(struct r600_shader_ctx *ctx)
+static int tgsi_helper_tempx_replicate(struct r600_shader_ctx *ctx)
 {
        struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
        struct r600_bc_alu alu;
-       int i, j, r;
+       int i, 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);
-       }
+       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_trans_srcx_replicate(struct r600_shader_ctx *ctx)
+{
+       struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+       struct r600_bc_alu alu;
+       int i, r;
+
+       memset(&alu, 0, sizeof(struct r600_bc_alu));
+       alu.inst = ctx->inst_info->r600_opcode;
+       for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
+               r = tgsi_src(ctx, &inst->Src[i], &alu.src[i]);
+               if (r)
+                       return r;
+               alu.src[i].chan = tgsi_chan(&inst->Src[i], 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;
+       r = r600_bc_add_literal(ctx->bc, ctx->value);
        if (r)
                return r;
        /* replicate result */
+       return tgsi_helper_tempx_replicate(ctx);
+}
+
+static int tgsi_pow(struct r600_shader_ctx *ctx)
+{
+       struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+       struct r600_bc_alu alu;
+       int r;
+
+       /* LOG2(a) */
+       memset(&alu, 0, sizeof(struct r600_bc_alu));
+       alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE;
+       r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
+       if (r)
+               return r;
+       alu.src[0].chan = tgsi_chan(&inst->Src[0], 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;
+       r = r600_bc_add_literal(ctx->bc,ctx->value);
+       if (r)
+               return r;
+       /* b * LOG2(a) */
+       memset(&alu, 0, sizeof(struct r600_bc_alu));
+       alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL_IEEE;
+       r = tgsi_src(ctx, &inst->Src[1], &alu.src[0]);
+       if (r)
+               return r;
+       alu.src[0].chan = tgsi_chan(&inst->Src[1], 0);
+       alu.src[1].sel = ctx->temp_reg;
+       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;
+       r = r600_bc_add_literal(ctx->bc,ctx->value);
+       if (r)
+               return r;
+       /* POW(a,b) = EXP2(b * LOG2(a))*/
+       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.dst.sel = ctx->temp_reg;
+       alu.dst.write = 1;
+       alu.last = 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;
+       return tgsi_helper_tempx_replicate(ctx);
+}
+
+static int tgsi_ssg(struct r600_shader_ctx *ctx)
+{
+       struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+       struct r600_bc_alu alu;
+       struct r600_bc_alu_src r600_src[3];
+       int i, r;
+
+       r = tgsi_split_constant(ctx, r600_src);
+       if (r)
+               return r;
+
+       /* tmp = (src > 0 ? 1 : src) */
        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.inst = V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDGT;
+               alu.is_op3 = 1;
+
+               alu.dst.sel = ctx->temp_reg;
                alu.dst.chan = i;
+
+               alu.src[0] = r600_src[0];
+               alu.src[0].chan = tgsi_chan(&inst->Src[0], i);
+
+               alu.src[1].sel = V_SQ_ALU_SRC_1;
+
+               alu.src[2] = r600_src[0];
+               alu.src[2].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;
+       }
+       r = r600_bc_add_literal(ctx->bc, ctx->value);
+       if (r)
+               return r;
+
+       /* dst = (-tmp > 0 ? -1 : tmp) */
+       for (i = 0; i < 4; i++) {
+               memset(&alu, 0, sizeof(struct r600_bc_alu));
+               alu.inst = V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDGT;
+               alu.is_op3 = 1;
                r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
                if (r)
                        return r;
-               alu.dst.write = (inst->Dst[0].Register.WriteMask >> i) & 1;
+
+               alu.src[0].sel = ctx->temp_reg;
+               alu.src[0].chan = i;
+               alu.src[0].neg = 1;
+
+               alu.src[1].sel = V_SQ_ALU_SRC_1;
+               alu.src[1].neg = 1;
+
+               alu.src[2].sel = ctx->temp_reg;
+               alu.src[2].chan = i;
+
                if (i == 3)
                        alu.last = 1;
                r = r600_bc_add_alu(ctx->bc, &alu);
@@ -1006,16 +1429,23 @@ static int tgsi_dp(struct r600_shader_ctx *ctx)
                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].sel = alu.src[1].sel = V_SQ_ALU_SRC_0;
                                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].sel = alu.src[1].sel = V_SQ_ALU_SRC_0;
                                alu.src[0].chan = alu.src[1].chan = 0;
                        }
                        break;
+               case TGSI_OPCODE_DPH:
+                       if (i == 3) {
+                               alu.src[0].sel = V_SQ_ALU_SRC_1;
+                               alu.src[0].chan = 0;
+                               alu.src[0].neg = 0;
+                       }
+                       break;
                default:
                        break;
                }
@@ -1035,75 +1465,197 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
        struct r600_bc_tex tex;
        struct r600_bc_alu alu;
        unsigned src_gpr;
-       int r;
+       int r, i;
+       int opcode;
+       boolean src_not_temp = inst->Src[0].Register.File != TGSI_FILE_TEMPORARY;
+       uint32_t lit_vals[4];
 
        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;
+       if (inst->Instruction.Opcode == TGSI_OPCODE_TXP) {
+               /* Add perspective divide */
+               memset(&alu, 0, sizeof(struct r600_bc_alu));
+               alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE;
+               r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
+               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;
+               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;
+               
+               for (i = 0; i < 3; 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 = 3;
+                       r = tgsi_src(ctx, &inst->Src[0], &alu.src[1]);
+                       if (r)
+                               return r;
+                       alu.src[1].chan = tgsi_chan(&inst->Src[0], i);
+                       alu.dst.sel = ctx->temp_reg;
+                       alu.dst.chan = i;
+                       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 = V_SQ_ALU_SRC_1;
+               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_not_temp = false;
+               src_gpr = ctx->temp_reg;
+       }
+
+       if (inst->Texture.Texture == TGSI_TEXTURE_CUBE) {
+               int src_chan, src2_chan;
+
+               /* tmp1.xyzw = CUBE(R0.zzxy, R0.yxzz) */
+               for (i = 0; i < 4; i++) {
+                       memset(&alu, 0, sizeof(struct r600_bc_alu));
+                       alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_CUBE;
+                       switch (i) {
+                       case 0:
+                               src_chan = 2;
+                               src2_chan = 1;
+                               break;
+                       case 1:
+                               src_chan = 2;
+                               src2_chan = 0;
+                               break;
+                       case 2:
+                               src_chan = 0;
+                               src2_chan = 2;
+                               break;
+                       case 3:
+                               src_chan = 1;
+                               src2_chan = 2;
+                               break;
+                       }
+                       r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
+                       if (r)
+                               return r;
+                       alu.src[0].chan = tgsi_chan(&inst->Src[0], src_chan);
+                       r = tgsi_src(ctx, &inst->Src[0], &alu.src[1]);
+                       if (r)
+                               return r;
+                       alu.src[1].chan = tgsi_chan(&inst->Src[0], src2_chan);
+                       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;
+               }
+
+               /* tmp1.z = RCP_e(|tmp1.z|) */
+               memset(&alu, 0, sizeof(struct r600_bc_alu));
+               alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIP_IEEE;
+               alu.src[0].sel = ctx->temp_reg;
+               alu.src[0].chan = 2;
+               alu.src[0].abs = 1;
+               alu.dst.sel = ctx->temp_reg;
+               alu.dst.chan = 2;
+               alu.dst.write = 1;
+               alu.last = 1;
+               r = r600_bc_add_alu(ctx->bc, &alu);
+               if (r)
+                       return r;
+               
+               /* MULADD R0.x,  R0.x,  PS1,  (0x3FC00000, 1.5f).x
+                * MULADD R0.y,  R0.y,  PS1,  (0x3FC00000, 1.5f).x
+                * muladd has no writemask, have to use another temp 
+                */
+               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].sel = ctx->temp_reg;
+               alu.src[0].chan = 0;
+               alu.src[1].sel = ctx->temp_reg;
+               alu.src[1].chan = 2;
+               
+               alu.src[2].sel = V_SQ_ALU_SRC_LITERAL;
+               alu.src[2].chan = 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_OP3_SQ_OP3_INST_MULADD;
+               alu.is_op3 = 1;
+
+               alu.src[0].sel = ctx->temp_reg;
+               alu.src[0].chan = 1;
+               alu.src[1].sel = ctx->temp_reg;
+               alu.src[1].chan = 2;
+               
+               alu.src[2].sel = V_SQ_ALU_SRC_LITERAL;
+               alu.src[2].chan = 0;
+
+               alu.dst.sel = ctx->temp_reg;
+               alu.dst.chan = 1;
+               alu.dst.write = 1;
+
+               alu.last = 1;
+               r = r600_bc_add_alu(ctx->bc, &alu);
+               if (r)
+                       return r;
+
+               lit_vals[0] = fui(1.5f);
+
+               r = r600_bc_add_literal(ctx->bc, lit_vals);
+               if (r)
+                       return r;
+               src_not_temp = false;
+               src_gpr = ctx->temp_reg;
+       }
+
+       if (src_not_temp) {
+               for (i = 0; i < 4; i++) {
+                       memset(&alu, 0, sizeof(struct r600_bc_alu));
+                       alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV;
+                       alu.src[0].sel = src_gpr;
+                       alu.src[0].chan = 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;
+               }
+               src_gpr = ctx->temp_reg;
+       }
+       
+       opcode = ctx->inst_info->r600_opcode;
+       if (opcode == SQ_TEX_INST_SAMPLE &&
+           (inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D || inst->Texture.Texture == TGSI_TEXTURE_SHADOW2D))
+               opcode = SQ_TEX_INST_SAMPLE_C;
 
-       /* 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.inst = 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;
@@ -1117,13 +1669,30 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
        tex.src_sel_z = 2;
        tex.src_sel_w = 3;
 
+       if (inst->Texture.Texture == TGSI_TEXTURE_CUBE) {
+               tex.src_sel_x = 1;
+               tex.src_sel_y = 0;
+               tex.src_sel_z = 3;
+               tex.src_sel_w = 1;
+       }
+
        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);
+
+       if (inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D || inst->Texture.Texture == TGSI_TEXTURE_SHADOW2D)
+               tex.src_sel_w = 2;
+
+       r = r600_bc_add_tex(ctx->bc, &tex);
+       if (r)
+               return r;
+
+       /* add shadow ambient support  - gallium doesn't do it yet */
+       return 0;
+       
 }
 
 static int tgsi_lrp(struct r600_shader_ctx *ctx)
@@ -1141,7 +1710,7 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx)
        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].sel = V_SQ_ALU_SRC_1;
                alu.src[0].chan = 0;
                alu.src[1] = r600_src[0];
                alu.src[1].chan = tgsi_chan(&inst->Src[0], i);
@@ -1205,23 +1774,654 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx)
        return tgsi_helper_copy(ctx, inst);
 }
 
+static int tgsi_cmp(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 use_temp = 0;
+       int i, r;
+
+       r = tgsi_split_constant(ctx, r600_src);
+       if (r)
+               return r;
+
+       if (inst->Dst[0].Register.WriteMask != 0xf)
+               use_temp = 1;
+
+       for (i = 0; i < 4; i++) {
+               memset(&alu, 0, sizeof(struct r600_bc_alu));
+               alu.inst = V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDGE;
+               alu.src[0] = r600_src[0];
+               alu.src[0].chan = tgsi_chan(&inst->Src[0], i);
+
+               alu.src[1] = r600_src[2];
+               alu.src[1].chan = tgsi_chan(&inst->Src[2], i);
+
+               alu.src[2] = r600_src[1];
+               alu.src[2].chan = tgsi_chan(&inst->Src[1], i);
+
+               if (use_temp)
+                       alu.dst.sel = ctx->temp_reg;
+               else {
+                       r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
+                       if (r)
+                               return r;
+               }
+               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;
+       }       
+       if (use_temp)
+               return tgsi_helper_copy(ctx, inst);
+       return 0;
+}
+
+static int tgsi_xpd(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;
+       uint32_t use_temp = 0;
+       int i, r;
+
+       if (inst->Dst[0].Register.WriteMask != 0xf)
+               use_temp = 1;
+
+       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 = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL;
+
+               alu.src[0] = r600_src[0];
+               switch (i) {
+               case 0:
+                       alu.src[0].chan = tgsi_chan(&inst->Src[0], 2);
+                       break;
+               case 1:
+                       alu.src[0].chan = tgsi_chan(&inst->Src[0], 0);
+                       break;
+               case 2:
+                       alu.src[0].chan = tgsi_chan(&inst->Src[0], 1);
+                       break;
+               case 3:
+                       alu.src[0].sel = V_SQ_ALU_SRC_0;
+                       alu.src[0].chan = i;
+               }
+
+               alu.src[1] = r600_src[1];
+               switch (i) {
+               case 0:
+                       alu.src[1].chan = tgsi_chan(&inst->Src[1], 1);
+                       break;
+               case 1:
+                       alu.src[1].chan = tgsi_chan(&inst->Src[1], 2);
+                       break;
+               case 2:
+                       alu.src[1].chan = tgsi_chan(&inst->Src[1], 0);
+                       break;
+               case 3:
+                       alu.src[1].sel = V_SQ_ALU_SRC_0;
+                       alu.src[1].chan = i;
+               }
+
+               alu.dst.sel = ctx->temp_reg;
+               alu.dst.chan = i;
+               alu.dst.write = 1;
+
+               if (i == 3)
+                       alu.last = 1;
+               r = r600_bc_add_alu(ctx->bc, &alu);
+               if (r)
+                       return r;
+       }
+
+       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.src[0] = r600_src[0];
+               switch (i) {
+               case 0:
+                       alu.src[0].chan = tgsi_chan(&inst->Src[0], 1);
+                       break;
+               case 1:
+                       alu.src[0].chan = tgsi_chan(&inst->Src[0], 2);
+                       break;
+               case 2:
+                       alu.src[0].chan = tgsi_chan(&inst->Src[0], 0);
+                       break;
+               case 3:
+                       alu.src[0].sel = V_SQ_ALU_SRC_0;
+                       alu.src[0].chan = i;
+               }
+
+               alu.src[1] = r600_src[1];
+               switch (i) {
+               case 0:
+                       alu.src[1].chan = tgsi_chan(&inst->Src[1], 2);
+                       break;
+               case 1:
+                       alu.src[1].chan = tgsi_chan(&inst->Src[1], 0);
+                       break;
+               case 2:
+                       alu.src[1].chan = tgsi_chan(&inst->Src[1], 1);
+                       break;
+               case 3:
+                       alu.src[1].sel = V_SQ_ALU_SRC_0;
+                       alu.src[1].chan = i;
+               }
+
+               alu.src[2].sel = ctx->temp_reg;
+               alu.src[2].neg = 1;
+               alu.src[2].chan = i;
+
+               if (use_temp)
+                       alu.dst.sel = ctx->temp_reg;
+               else {
+                       r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
+                       if (r)
+                               return r;
+               }
+               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;
+       }
+       if (use_temp)
+               return tgsi_helper_copy(ctx, inst);
+       return 0;
+}
+
+static int tgsi_exp(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 r;
+
+       /* result.x = 2^floor(src); */
+       if (inst->Dst[0].Register.WriteMask & 1) {
+               memset(&alu, 0, sizeof(struct r600_bc_alu));
+
+               alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLOOR;
+               r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
+               if (r)
+                       return r;
+
+               alu.src[0].chan = tgsi_chan(&inst->Src[0], 0);
+
+               alu.dst.sel = ctx->temp_reg;
+               alu.dst.chan = 0;
+               alu.dst.write = 1;
+               alu.last = 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;
+
+               alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE;
+               alu.src[0].sel = ctx->temp_reg;
+               alu.src[0].chan = 0;
+
+               alu.dst.sel = ctx->temp_reg;
+               alu.dst.chan = 0;
+               alu.dst.write = 1;
+               alu.last = 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;
+       }
+               
+       /* result.y = tmp - floor(tmp); */
+       if ((inst->Dst[0].Register.WriteMask >> 1) & 1) {
+               memset(&alu, 0, sizeof(struct r600_bc_alu));
+
+               alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FRACT;
+               alu.src[0] = r600_src[0];
+               r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
+               if (r)
+                       return r;
+               alu.src[0].chan = tgsi_chan(&inst->Src[0], 0);
+
+               alu.dst.sel = ctx->temp_reg;
+//             r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
+//             if (r)
+//                     return r;
+               alu.dst.write = 1;
+               alu.dst.chan = 1;
+
+               alu.last = 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;
+       }
+
+       /* result.z = RoughApprox2ToX(tmp);*/
+       if ((inst->Dst[0].Register.WriteMask >> 2) & 0x1) {
+               memset(&alu, 0, sizeof(struct r600_bc_alu));
+               alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE;
+               r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
+               if (r)
+                       return r;
+               alu.src[0].chan = tgsi_chan(&inst->Src[0], 0);
+
+               alu.dst.sel = ctx->temp_reg;
+               alu.dst.write = 1;
+               alu.dst.chan = 2;
+
+               alu.last = 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;
+       }
+
+       /* result.w = 1.0;*/
+       if ((inst->Dst[0].Register.WriteMask >> 3) & 0x1) {
+               memset(&alu, 0, sizeof(struct r600_bc_alu));
+
+               alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV;
+               alu.src[0].sel = V_SQ_ALU_SRC_1;
+               alu.src[0].chan = 0;
+
+               alu.dst.sel = ctx->temp_reg;
+               alu.dst.chan = 3;
+               alu.dst.write = 1;
+               alu.last = 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;
+       }
+       return tgsi_helper_copy(ctx, inst);
+}
+
+static int tgsi_arl(struct r600_shader_ctx *ctx)
+{
+       /* TODO from r600c, ar values don't persist between clauses */
+       struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+       struct r600_bc_alu alu;
+       int r;
+       memset(&alu, 0, sizeof(struct r600_bc_alu));
+
+       alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_FLOOR;
+
+       r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
+       if (r)
+               return r;
+       alu.src[0].chan = tgsi_chan(&inst->Src[0], 0);
+
+       alu.last = 1;
+
+       r = r600_bc_add_alu_type(ctx->bc, &alu, V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU);
+       if (r)
+               return r;
+       return 0;
+}
+
+static int tgsi_opdst(struct r600_shader_ctx *ctx)
+{
+       struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+       struct r600_bc_alu alu;
+       int i, r = 0;
+
+       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;
+               r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
+               if (r)
+                       return r;
+       
+               if (i == 0 || i == 3) {
+                       alu.src[0].sel = V_SQ_ALU_SRC_1;
+               } else {
+                       r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
+                       if (r)
+                               return r;
+                       alu.src[0].chan = tgsi_chan(&inst->Src[0], i);
+               }
+
+               if (i == 0 || i == 2) {
+                       alu.src[1].sel = V_SQ_ALU_SRC_1;
+               } else {
+                       r = tgsi_src(ctx, &inst->Src[1], &alu.src[1]);
+                       if (r)
+                               return r;
+                       alu.src[1].chan = tgsi_chan(&inst->Src[1], i);
+               }
+               if (i == 3)
+                       alu.last = 1;
+               r = r600_bc_add_alu(ctx->bc, &alu);
+               if (r)
+                       return r;
+       }
+       return 0;
+}
+
+static int emit_logic_pred(struct r600_shader_ctx *ctx, int opcode)
+{
+       struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+       struct r600_bc_alu alu;
+       int r;
+
+       memset(&alu, 0, sizeof(struct r600_bc_alu));
+       alu.inst = opcode;
+       alu.predicate = 1;
+
+       alu.dst.sel = ctx->temp_reg;
+       alu.dst.write = 1;
+       alu.dst.chan = 0;
+
+       r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
+       if (r)
+               return r;
+       alu.src[0].chan = tgsi_chan(&inst->Src[0], 0);
+       alu.src[1].sel = V_SQ_ALU_SRC_0;
+       alu.src[1].chan = 0;
+       
+       alu.last = 1;
+
+       r = r600_bc_add_alu_type(ctx->bc, &alu, V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE);
+       if (r)
+               return r;
+       return 0;
+}
+
+static int pops(struct r600_shader_ctx *ctx, int pops)
+{
+       r600_bc_add_cfinst(ctx->bc, V_SQ_CF_WORD1_SQ_CF_INST_POP);      
+       ctx->bc->cf_last->pop_count = pops;
+       return 0;
+}
+
+static inline void callstack_decrease_current(struct r600_shader_ctx *ctx, unsigned reason)
+{
+       switch(reason) {
+       case FC_PUSH_VPM:
+               ctx->bc->callstack[ctx->bc->call_sp].current--;
+               break;
+       case FC_PUSH_WQM:
+       case FC_LOOP:
+               ctx->bc->callstack[ctx->bc->call_sp].current -= 4;
+               break;
+       case FC_REP:
+               /* TOODO : for 16 vp asic should -= 2; */
+               ctx->bc->callstack[ctx->bc->call_sp].current --;
+               break;
+       }
+}
+
+static inline void callstack_check_depth(struct r600_shader_ctx *ctx, unsigned reason, unsigned check_max_only)
+{
+       if (check_max_only) {
+               int diff;
+               switch (reason) {
+               case FC_PUSH_VPM:
+                       diff = 1;
+                       break;
+               case FC_PUSH_WQM:
+                       diff = 4;
+                       break;
+               }
+               if ((ctx->bc->callstack[ctx->bc->call_sp].current + diff) >
+                   ctx->bc->callstack[ctx->bc->call_sp].max) {
+                       ctx->bc->callstack[ctx->bc->call_sp].max =
+                               ctx->bc->callstack[ctx->bc->call_sp].current + diff;
+               }
+               return;
+       }                                       
+       switch (reason) {
+       case FC_PUSH_VPM:
+               ctx->bc->callstack[ctx->bc->call_sp].current++;
+               break;
+       case FC_PUSH_WQM:
+       case FC_LOOP:
+               ctx->bc->callstack[ctx->bc->call_sp].current += 4;
+               break;
+       case FC_REP:
+               ctx->bc->callstack[ctx->bc->call_sp].current++;
+               break;
+       }
+
+       if ((ctx->bc->callstack[ctx->bc->call_sp].current) >
+           ctx->bc->callstack[ctx->bc->call_sp].max) {
+               ctx->bc->callstack[ctx->bc->call_sp].max =
+                       ctx->bc->callstack[ctx->bc->call_sp].current;
+       }
+}
+
+static void fc_set_mid(struct r600_shader_ctx *ctx, int fc_sp)
+{
+       struct r600_cf_stack_entry *sp = &ctx->bc->fc_stack[fc_sp];
+
+       sp->mid = (struct r600_bc_cf **)realloc((void *)sp->mid,
+                                               sizeof(struct r600_bc_cf *) * (sp->num_mid + 1));
+       sp->mid[sp->num_mid] = ctx->bc->cf_last;
+       sp->num_mid++;
+}
+
+static void fc_pushlevel(struct r600_shader_ctx *ctx, int type)
+{
+       ctx->bc->fc_sp++;
+       ctx->bc->fc_stack[ctx->bc->fc_sp].type = type;
+       ctx->bc->fc_stack[ctx->bc->fc_sp].start = ctx->bc->cf_last;
+}
+
+static void fc_poplevel(struct r600_shader_ctx *ctx)
+{
+       struct r600_cf_stack_entry *sp = &ctx->bc->fc_stack[ctx->bc->fc_sp];
+       if (sp->mid) {
+               free(sp->mid);
+               sp->mid = NULL;
+       }
+       sp->num_mid = 0;
+       sp->start = NULL;
+       sp->type = 0;
+       ctx->bc->fc_sp--;
+}
+
+#if 0
+static int emit_return(struct r600_shader_ctx *ctx)
+{
+       r600_bc_add_cfinst(ctx->bc, V_SQ_CF_WORD1_SQ_CF_INST_RETURN);
+       return 0;
+}
+
+static int emit_jump_to_offset(struct r600_shader_ctx *ctx, int pops, int offset)
+{
+
+       r600_bc_add_cfinst(ctx->bc, V_SQ_CF_WORD1_SQ_CF_INST_JUMP);
+       ctx->bc->cf_last->pop_count = pops;
+       /* TODO work out offset */
+       return 0;
+}
+
+static int emit_setret_in_loop_flag(struct r600_shader_ctx *ctx, unsigned flag_value)
+{
+       return 0;
+}
+
+static void emit_testflag(struct r600_shader_ctx *ctx)
+{
+       
+}
+
+static void emit_return_on_flag(struct r600_shader_ctx *ctx, unsigned ifidx)
+{
+       emit_testflag(ctx);
+       emit_jump_to_offset(ctx, 1, 4);
+       emit_setret_in_loop_flag(ctx, V_SQ_ALU_SRC_0);
+       pops(ctx, ifidx + 1);
+       emit_return(ctx);
+}
+
+static void break_loop_on_flag(struct r600_shader_ctx *ctx, unsigned fc_sp)
+{
+       emit_testflag(ctx);
+
+       r600_bc_add_cfinst(ctx->bc, ctx->inst_info->r600_opcode);
+       ctx->bc->cf_last->pop_count = 1;
+
+       fc_set_mid(ctx, fc_sp);
+
+       pops(ctx, 1);
+}
+#endif
+
+static int tgsi_if(struct r600_shader_ctx *ctx)
+{
+       emit_logic_pred(ctx, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE);
+
+       r600_bc_add_cfinst(ctx->bc, V_SQ_CF_WORD1_SQ_CF_INST_JUMP);
+
+       fc_pushlevel(ctx, FC_IF);
+
+       callstack_check_depth(ctx, FC_PUSH_VPM, 0);
+       return 0;
+}
+
+static int tgsi_else(struct r600_shader_ctx *ctx)
+{
+       r600_bc_add_cfinst(ctx->bc, V_SQ_CF_WORD1_SQ_CF_INST_ELSE);
+       ctx->bc->cf_last->pop_count = 1;
+
+       fc_set_mid(ctx, ctx->bc->fc_sp);
+       ctx->bc->fc_stack[ctx->bc->fc_sp].start->cf_addr = ctx->bc->cf_last->id;
+       return 0;
+}
+
+static int tgsi_endif(struct r600_shader_ctx *ctx)
+{
+       pops(ctx, 1);
+       if (ctx->bc->fc_stack[ctx->bc->fc_sp].type != FC_IF) {
+               R600_ERR("if/endif unbalanced in shader\n");
+               return -1;
+       }
+
+       if (ctx->bc->fc_stack[ctx->bc->fc_sp].mid == NULL) {
+               ctx->bc->fc_stack[ctx->bc->fc_sp].start->cf_addr = ctx->bc->cf_last->id + 2;
+               ctx->bc->fc_stack[ctx->bc->fc_sp].start->pop_count = 1;
+       } else {
+               ctx->bc->fc_stack[ctx->bc->fc_sp].mid[0]->cf_addr = ctx->bc->cf_last->id + 2;
+       }
+       fc_poplevel(ctx);
+
+       callstack_decrease_current(ctx, FC_PUSH_VPM);
+       return 0;
+}
+
+static int tgsi_bgnloop(struct r600_shader_ctx *ctx)
+{
+       r600_bc_add_cfinst(ctx->bc, V_SQ_CF_WORD1_SQ_CF_INST_LOOP_START_NO_AL);
+
+       fc_pushlevel(ctx, FC_LOOP);
+
+       /* check stack depth */
+       callstack_check_depth(ctx, FC_LOOP, 0);
+       return 0;
+}
+
+static int tgsi_endloop(struct r600_shader_ctx *ctx)
+{
+       int i;
+
+       r600_bc_add_cfinst(ctx->bc, V_SQ_CF_WORD1_SQ_CF_INST_LOOP_END);
+
+       if (ctx->bc->fc_stack[ctx->bc->fc_sp].type != FC_LOOP) {
+               R600_ERR("loop/endloop in shader code are not paired.\n");
+               return -EINVAL;
+       }
+
+       /* fixup loop pointers - from r600isa
+          LOOP END points to CF after LOOP START,
+          LOOP START point to CF after LOOP END
+          BRK/CONT point to LOOP END CF
+       */
+       ctx->bc->cf_last->cf_addr = ctx->bc->fc_stack[ctx->bc->fc_sp].start->id + 2;
+
+       ctx->bc->fc_stack[ctx->bc->fc_sp].start->cf_addr = ctx->bc->cf_last->id + 2;
+
+       for (i = 0; i < ctx->bc->fc_stack[ctx->bc->fc_sp].num_mid; i++) {
+               ctx->bc->fc_stack[ctx->bc->fc_sp].mid[i]->cf_addr = ctx->bc->cf_last->id;
+       }
+       /* TODO add LOOPRET support */
+       fc_poplevel(ctx);
+       callstack_decrease_current(ctx, FC_LOOP);
+       return 0;
+}
+
+static int tgsi_loop_brk_cont(struct r600_shader_ctx *ctx)
+{
+       unsigned int fscp;
+
+       for (fscp = ctx->bc->fc_sp; fscp > 0; fscp--)
+       {
+               if (FC_LOOP == ctx->bc->fc_stack[fscp].type)
+                       break;
+       }
+
+       if (fscp == 0) {
+               R600_ERR("Break not inside loop/endloop pair\n");
+               return -EINVAL;
+       }
+
+       r600_bc_add_cfinst(ctx->bc, ctx->inst_info->r600_opcode);
+       ctx->bc->cf_last->pop_count = 1;
+
+       fc_set_mid(ctx, fscp);
+
+       pops(ctx, 1);
+       callstack_check_depth(ctx, FC_PUSH_VPM, 1);
+       return 0;
+}
+
 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_ARL,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_arl},
        {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_EXP,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_exp},
        {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_DST,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_opdst},
        {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_SLT,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGT, tgsi_op2_swap},
+       {TGSI_OPCODE_SGE,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGE, tgsi_op2},
        {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},
@@ -1232,38 +2432,38 @@ static struct r600_shader_tgsi_instruction r600_shader_tgsi_instruction[] = {
        /* 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_FRC,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FRACT, tgsi_op2},
        {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_FLR,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLOOR, tgsi_op2},
        {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},
+       {TGSI_OPCODE_LG2,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_IEEE, tgsi_trans_srcx_replicate},
+       {TGSI_OPCODE_POW,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_pow},
+       {TGSI_OPCODE_XPD,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_xpd},
        /* 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_DPH,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_DOT4, tgsi_dp},
+       {TGSI_OPCODE_COS,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_COS, tgsi_trig},
+       {TGSI_OPCODE_DDX,       0, SQ_TEX_INST_GET_GRADIENTS_H, tgsi_tex},
+       {TGSI_OPCODE_DDY,       0, SQ_TEX_INST_GET_GRADIENTS_V, tgsi_tex},
+       {TGSI_OPCODE_KILP,      0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT, tgsi_kill},  /* 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_SEQ,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETE, tgsi_op2},
        {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_SGT,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGT, tgsi_op2},
+       {TGSI_OPCODE_SIN,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SIN, tgsi_trig},
+       {TGSI_OPCODE_SLE,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETGE, tgsi_op2_swap},
+       {TGSI_OPCODE_SNE,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SETNE, tgsi_op2},
        {TGSI_OPCODE_STR,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
-       {TGSI_OPCODE_TEX,       0, 0x10, tgsi_tex},
+       {TGSI_OPCODE_TEX,       0, SQ_TEX_INST_SAMPLE, 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_TXP,       0, SQ_TEX_INST_SAMPLE, 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},
@@ -1274,21 +2474,21 @@ static struct r600_shader_tgsi_instruction r600_shader_tgsi_instruction[] = {
        {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_SSG,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_ssg},
+       {TGSI_OPCODE_CMP,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_cmp},
+       {TGSI_OPCODE_SCS,       0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_scs},
+       {TGSI_OPCODE_TXB,       0, SQ_TEX_INST_SAMPLE_L, tgsi_tex},
        {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},
+       {TGSI_OPCODE_BRK,       0, V_SQ_CF_WORD1_SQ_CF_INST_LOOP_BREAK, tgsi_loop_brk_cont},
+       {TGSI_OPCODE_IF,        0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_if},
        /* 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},
+       {TGSI_OPCODE_ELSE,      0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_else},
+       {TGSI_OPCODE_ENDIF,     0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_endif},
        /* 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},
@@ -1297,7 +2497,7 @@ static struct r600_shader_tgsi_instruction r600_shader_tgsi_instruction[] = {
        {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_TRUNC,     0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_TRUNC, tgsi_trans_srcx_replicate},
        {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},
@@ -1308,12 +2508,12 @@ static struct r600_shader_tgsi_instruction r600_shader_tgsi_instruction[] = {
        {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_CONT,      0, V_SQ_CF_WORD1_SQ_CF_INST_LOOP_CONTINUE, tgsi_loop_brk_cont},
        {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_BGNLOOP,   0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_bgnloop},
        {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_ENDLOOP,   0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_endloop},
        {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},
index 2ee7780ead0a6e611d10aeb6556c9ec8c5f05afd..7c722c07cbe365d96c03fd4f0dee9a027092d0d9 100644 (file)
@@ -42,6 +42,7 @@ struct r600_shader {
        struct r600_shader_io   input[32];
        struct r600_shader_io   output[32];
        enum radeon_family      family;
+       boolean                 uses_kill;
 };
 
 #endif
index 002660c654a10ed7142cc92088f2beddca2f3608..fa7a31742af440706f024ff2444cda0a60c38ce8 100644 (file)
 #define   S_SQ_ALU_WORD0_SRC0_SEL(x)                                 (((x) & 0x1FF) << 0)
 #define   G_SQ_ALU_WORD0_SRC0_SEL(x)                                 (((x) >> 0) & 0x1FF)
 #define   C_SQ_ALU_WORD0_SRC0_SEL                                    0xFFFFFE00
+/*
+ * 244  ALU_SRC_1_DBL_L: special constant 1.0 double-float, LSW. (RV670+)
+ * 245  ALU_SRC_1_DBL_M: special constant 1.0 double-float, MSW. (RV670+)
+ * 246  ALU_SRC_0_5_DBL_L: special constant 0.5 double-float, LSW. (RV670+)
+ * 247  ALU_SRC_0_5_DBL_M: special constant 0.5 double-float, MSW. (RV670+)
+ * 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.
+ */
+#define     V_SQ_ALU_SRC_0                                           0x000000F8
+#define     V_SQ_ALU_SRC_1                                           0x000000F9
+#define     V_SQ_ALU_SRC_1_INT                                       0x000000FA
+#define     V_SQ_ALU_SRC_M_1_INT                                     0x000000FB
+#define     V_SQ_ALU_SRC_0_5                                         0x000000FC
+#define     V_SQ_ALU_SRC_LITERAL                                     0x000000FD
 #define   S_SQ_ALU_WORD0_SRC0_REL(x)                                 (((x) & 0x1) << 9)
 #define   G_SQ_ALU_WORD0_SRC0_REL(x)                                 (((x) >> 9) & 0x1)
 #define   C_SQ_ALU_WORD0_SRC0_REL                                    0xFFFFFDFF
 #define   G_SQ_TEX_WORD2_SRC_SEL_W(x)                                (((x) >> 29) & 0x7)
 #define   C_SQ_TEX_WORD2_SRC_SEL_W                                   0x1FFFFFFF
 
+#define V_SQ_CF_COND_ACTIVE                             0x00
+#define V_SQ_CF_COND_FALSE                              0x01
+#define V_SQ_CF_COND_BOOL                               0x02
+#define V_SQ_CF_COND_NOT_BOOL                           0x03
+
+#define V_SQ_REL_ABSOLUTE 0
+#define V_SQ_REL_RELATIVE 1
 #endif
index 3efd409ae0d8a02f348e74d24b7d09bfdac80c36..66cab7d7a6ec177e2790cb0dd85998479d9744f9 100644 (file)
 #include "r600d.h"
 #include "r600_state_inlines.h"
 
+static void r600_blend(struct r600_context *rctx, struct radeon_state *rstate, const struct pipe_blend_state *state);
+static void r600_viewport(struct r600_context *rctx, struct radeon_state *rstate, const struct pipe_viewport_state *state);
+static void r600_ucp(struct r600_context *rctx, struct radeon_state *rstate, const struct pipe_clip_state *state);
+static void r600_sampler(struct r600_context *rctx, struct radeon_state *rstate, const struct pipe_sampler_state *state, unsigned id);
+static void r600_resource(struct pipe_context *ctx, struct radeon_state *rstate, const struct pipe_sampler_view *view, unsigned id);
+static void r600_cb(struct r600_context *rctx, struct radeon_state *rstate,
+                       const struct pipe_framebuffer_state *state, int cb);
+static void r600_db(struct r600_context *rctx, struct radeon_state *rstate,
+                       const struct pipe_framebuffer_state *state);
+
+
 static void *r600_create_blend_state(struct pipe_context *ctx,
                                        const struct pipe_blend_state *state)
 {
@@ -81,11 +92,12 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c
        struct r600_context *rctx = r600_context(ctx);
        struct r600_context_state *rstate;
 
-       rstate = r600_context_state(rctx, pipe_sampler_type, state);
+       rstate = r600_context_state(rctx, pipe_sampler_view_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;
+       r600_resource(ctx, &rstate->rstate[0], &rstate->state.sampler_view, 0);
        return &rstate->state.sampler_view;
 }
 
@@ -223,12 +235,24 @@ static void r600_bind_ps_sampler(struct pipe_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];
+               if (rstate) {
+                       rstate->nrstate = 0;
+               }
        }
        for (i = 0; i < count; i++) {
                rstate = (struct r600_context_state *)states[i];
-               rctx->ps_sampler[i] = r600_context_state_incref(rstate);
+               if (rstate) {
+                       if (rstate->nrstate >= R600_MAX_RSTATE)
+                               continue;
+                       if (rstate->nrstate) {
+                               memcpy(&rstate->rstate[rstate->nrstate], &rstate->rstate[0], sizeof(struct radeon_state));
+                       }
+                       radeon_state_convert(&rstate->rstate[rstate->nrstate], R600_STATE_SAMPLER, i, R600_SHADER_PS);
+                       rctx->ps_sampler[i] = &rstate->rstate[rstate->nrstate];
+                       rstate->nrstate++;
+               }
        }
        rctx->ps_nsampler = count;
 }
@@ -240,12 +264,24 @@ static void r600_bind_vs_sampler(struct pipe_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];
+               if (rstate) {
+                       rstate->nrstate = 0;
+               }
        }
        for (i = 0; i < count; i++) {
                rstate = (struct r600_context_state *)states[i];
-               rctx->vs_sampler[i] = r600_context_state_incref(rstate);
+               if (rstate) {
+                       if (rstate->nrstate >= R600_MAX_RSTATE)
+                               continue;
+                       if (rstate->nrstate) {
+                               memcpy(&rstate->rstate[rstate->nrstate], &rstate->rstate[0], sizeof(struct radeon_state));
+                       }
+                       radeon_state_convert(&rstate->rstate[rstate->nrstate], R600_STATE_SAMPLER, i, R600_SHADER_VS);
+                       rctx->vs_sampler[i] = &rstate->rstate[rstate->nrstate];
+                       rstate->nrstate++;
+               }
        }
        rctx->vs_nsampler = count;
 }
@@ -268,6 +304,13 @@ static void r600_set_blend_color(struct pipe_context *ctx,
 static void r600_set_clip_state(struct pipe_context *ctx,
                                const struct pipe_clip_state *state)
 {
+       struct r600_context *rctx = r600_context(ctx);
+       struct r600_context_state *rstate;
+
+       rstate = r600_context_state(rctx, pipe_clip_type, state);
+       r600_bind_state(ctx, rstate);
+       /* refcount is taken care of this */
+       r600_delete_state(ctx, rstate);
 }
 
 static void r600_set_constant_buffer(struct pipe_context *ctx,
@@ -276,19 +319,21 @@ static void r600_set_constant_buffer(struct pipe_context *ctx,
 {
        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;
+       unsigned nconstant = 0, i, type, shader_class;
+       struct radeon_state *rstate, *rstates;
        struct pipe_transfer *transfer;
        u32 *ptr;
 
+       type = R600_STATE_CONSTANT;
+
        switch (shader) {
        case PIPE_SHADER_VERTEX:
-               id = R600_VS_CONSTANT;
-               type = R600_VS_CONSTANT_TYPE;
+               shader_class = R600_SHADER_VS;
+               rstates = rctx->vs_constant;
                break;
        case PIPE_SHADER_FRAGMENT:
-               id = R600_PS_CONSTANT;
-               type = R600_PS_CONSTANT_TYPE;
+               shader_class = R600_SHADER_PS;
+               rstates = rctx->ps_constant;
                break;
        default:
                R600_ERR("unsupported %d\n", shader);
@@ -300,17 +345,15 @@ static void r600_set_constant_buffer(struct pipe_context *ctx,
                if (ptr == NULL)
                        return;
                for (i = 0; i < nconstant; i++) {
-                       rstate = radeon_state(rscreen->rw, type, id + i);
-                       if (rstate == NULL)
-                               return;
+                       rstate = &rstates[i];
+                       radeon_state_init(rstate, rscreen->rw, type, i, shader_class);
                        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;
+                       radeon_draw_bind(&rctx->draw, rstate);
                }
                pipe_buffer_unmap(ctx, buffer, transfer);
        }
@@ -324,12 +367,24 @@ static void r600_set_ps_sampler_view(struct pipe_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];
+               if (rstate) {
+                       rstate->nrstate = 0;
+               }
        }
        for (i = 0; i < count; i++) {
                rstate = (struct r600_context_state *)views[i];
-               rctx->ps_sampler_view[i] = r600_context_state_incref(rstate);
+               if (rstate) {
+                       if (rstate->nrstate >= R600_MAX_RSTATE)
+                               continue;
+                       if (rstate->nrstate) {
+                               memcpy(&rstate->rstate[rstate->nrstate], &rstate->rstate[0], sizeof(struct radeon_state));
+                       }
+                       radeon_state_convert(&rstate->rstate[rstate->nrstate], R600_STATE_RESOURCE, i, R600_SHADER_PS);
+                       rctx->ps_sampler_view[i] = &rstate->rstate[rstate->nrstate];
+                       rstate->nrstate++;
+               }
        }
        rctx->ps_nsampler_view = count;
 }
@@ -342,12 +397,24 @@ static void r600_set_vs_sampler_view(struct pipe_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];
+               if (rstate) {
+                       rstate->nrstate = 0;
+               }
        }
        for (i = 0; i < count; i++) {
                rstate = (struct r600_context_state *)views[i];
-               rctx->vs_sampler_view[i] = r600_context_state_incref(rstate);
+               if (rstate) {
+                       if (rstate->nrstate >= R600_MAX_RSTATE)
+                               continue;
+                       if (rstate->nrstate) {
+                               memcpy(&rstate->rstate[rstate->nrstate], &rstate->rstate[0], sizeof(struct radeon_state));
+                       }
+                       radeon_state_convert(&rstate->rstate[rstate->nrstate], R600_STATE_RESOURCE, i, R600_SHADER_VS);
+                       rctx->vs_sampler_view[i] = &rstate->rstate[rstate->nrstate];
+                       rstate->nrstate++;
+               }
        }
        rctx->vs_nsampler_view = count;
 }
@@ -360,6 +427,12 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx,
 
        rstate = r600_context_state(rctx, pipe_framebuffer_type, state);
        r600_bind_state(ctx, rstate);
+       for (int i = 0; i < state->nr_cbufs; i++) {
+               r600_cb(rctx, &rstate->rstate[i+1], state, i);
+       }
+       if (state->zsbuf) {
+               r600_db(rctx, &rstate->rstate[0], state);
+       }
 }
 
 static void r600_set_polygon_stipple(struct pipe_context *ctx,
@@ -525,7 +598,7 @@ struct r600_context_state *r600_context_state_decref(struct r600_context_state *
                R600_ERR("invalid type %d\n", rstate->type);
                return NULL;
        }
-       radeon_state_decref(rstate->rstate);
+       radeon_state_fini(&rstate->rstate[0]);
        FREE(rstate);
        return NULL;
 }
@@ -558,6 +631,7 @@ struct r600_context_state *r600_context_state(struct r600_context *rctx, unsigne
                break;
        case pipe_viewport_type:
                rstate->state.viewport = (*states).viewport;
+               r600_viewport(rctx, &rstate->rstate[0], &rstate->state.viewport);
                break;
        case pipe_depth_type:
                rstate->state.depth = (*states).depth;
@@ -573,6 +647,7 @@ struct r600_context_state *r600_context_state(struct r600_context *rctx, unsigne
                break;
        case pipe_clip_type:
                rstate->state.clip = (*states).clip;
+               r600_ucp(rctx, &rstate->rstate[0], &rstate->state.clip);
                break;
        case pipe_stencil_type:
                rstate->state.stencil = (*states).stencil;
@@ -585,6 +660,7 @@ struct r600_context_state *r600_context_state(struct r600_context *rctx, unsigne
                break;
        case pipe_blend_type:
                rstate->state.blend = (*states).blend;
+               r600_blend(rctx, &rstate->rstate[0], &rstate->state.blend);
                break;
        case pipe_stencil_ref_type:
                rstate->state.stencil_ref = (*states).stencil_ref;
@@ -599,6 +675,7 @@ struct r600_context_state *r600_context_state(struct r600_context *rctx, unsigne
                break;
        case pipe_sampler_type:
                rstate->state.sampler = (*states).sampler;
+               r600_sampler(rctx, &rstate->rstate[0], &rstate->state.sampler, 0);
                break;
        default:
                R600_ERR("invalid type %d\n", rstate->type);
@@ -608,16 +685,12 @@ struct r600_context_state *r600_context_state(struct r600_context *rctx, unsigne
        return rstate;
 }
 
-static struct radeon_state *r600_blend(struct r600_context *rctx)
+static void r600_blend(struct r600_context *rctx, struct radeon_state *rstate, const struct pipe_blend_state *state)
 {
        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;
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_BLEND, 0, 0);
        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]);
@@ -661,29 +734,38 @@ static struct radeon_state *r600_blend(struct r600_context *rctx)
                        rstate->states[R600_BLEND__CB_BLEND_CONTROL] = bc;
        }
 
-       if (radeon_state_pm4(rstate)) {
-               radeon_state_decref(rstate);
-               return NULL;
+       radeon_state_pm4(rstate);
+}
+
+static void r600_ucp(struct r600_context *rctx, struct radeon_state *rstate,
+                       const struct pipe_clip_state *state)
+{
+       struct r600_screen *rscreen = rctx->screen;
+
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_UCP, 0, 0);
+
+       for (int i = 0; i < state->nr; i++) {
+               rstate->states[i * 4 + 0] = fui(state->ucp[i][0]);
+               rstate->states[i * 4 + 1] = fui(state->ucp[i][1]);
+               rstate->states[i * 4 + 2] = fui(state->ucp[i][2]);
+               rstate->states[i * 4 + 3] = fui(state->ucp[i][3]);
        }
-       return rstate;
+       radeon_state_pm4(rstate);
 }
 
-static struct radeon_state *r600_cb(struct r600_context *rctx, int cb)
+static void r600_cb(struct r600_context *rctx, struct radeon_state *rstate,
+                       const struct pipe_framebuffer_state *state, int cb)
 {
        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 = 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 + cb, R600_CB0 + cb);
-       if (rstate == NULL)
-               return NULL;
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_CB0 + cb, 0, 0);
        rtex = (struct r600_resource_texture*)state->cbufs[cb]->texture;
        rbuffer = &rtex->resource;
        rstate->bo[0] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
@@ -710,7 +792,7 @@ static struct radeon_state *r600_cb(struct r600_context *rctx, int cb)
                S_0280A0_SOURCE_FORMAT(1) |
                S_0280A0_NUMBER_TYPE(ntype);
 
-       rstate->states[R600_CB0__CB_COLOR0_BASE] = 0x00000000;
+       rstate->states[R600_CB0__CB_COLOR0_BASE] = state->cbufs[cb]->offset >> 8;
        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);
@@ -718,32 +800,29 @@ static struct radeon_state *r600_cb(struct r600_context *rctx, int cb)
        rstate->states[R600_CB0__CB_COLOR0_FRAG] = 0x00000000;
        rstate->states[R600_CB0__CB_COLOR0_TILE] = 0x00000000;
        rstate->states[R600_CB0__CB_COLOR0_MASK] = 0x00000000;
-       if (radeon_state_pm4(rstate)) {
-               radeon_state_decref(rstate);
-               return NULL;
-       }
-       return rstate;
+       radeon_state_pm4(rstate);
 }
 
-static struct radeon_state *r600_db(struct r600_context *rctx)
+static void r600_db(struct r600_context *rctx, struct radeon_state *rstate,
+                       const struct pipe_framebuffer_state *state)
 {
        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;
 
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_DB, 0, 0);
        if (state->zsbuf == NULL)
-               return NULL;
-
-       rstate = radeon_state(rscreen->rw, R600_DB_TYPE, R600_DB);
-       if (rstate == NULL)
-               return NULL;
+               return;
 
        rtex = (struct r600_resource_texture*)state->zsbuf->texture;
+       rtex->tilled = 1;
+       rtex->array_mode = 2;
+       rtex->tile_type = 1;
+       rtex->depth = 1;
        rbuffer = &rtex->resource;
+
        rstate->bo[0] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
        rstate->nbo = 1;
        rstate->placement[0] = RADEON_GEM_DOMAIN_VRAM;
@@ -751,31 +830,30 @@ static struct radeon_state *r600_db(struct r600_context *rctx)
        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 |
+       rstate->states[R600_DB__DB_DEPTH_BASE] = state->zsbuf->offset >> 8;
+       rstate->states[R600_DB__DB_DEPTH_INFO] = S_028010_ARRAY_MODE(rtex->array_mode) |
                                        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;
+       radeon_state_pm4(rstate);
 }
 
-static struct radeon_state *r600_rasterizer(struct r600_context *rctx)
+static void r600_rasterizer(struct r600_context *rctx, struct radeon_state *rstate)
 {
        const struct pipe_rasterizer_state *state = &rctx->rasterizer->state.rasterizer;
        const struct pipe_framebuffer_state *fb = &rctx->framebuffer->state.framebuffer;
+       const struct pipe_clip_state *clip = NULL;
        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 (rctx->clip)
+               clip = &rctx->clip->state.clip;
        if (fb->zsbuf) {
                offset_units = state->offset_units;
                offset_scale = state->offset_scale * 12.0f;
@@ -796,7 +874,7 @@ static struct radeon_state *r600_rasterizer(struct r600_context *rctx)
                        break;
                default:
                        R600_ERR("unsupported %d\n", fb->zsbuf->texture->format);
-                       return NULL;
+                       return;
                }
        }
        offset_db_fmt_cntl |= S_028DF8_POLY_OFFSET_NEG_NUM_DB_BITS(depth);
@@ -805,9 +883,7 @@ static struct radeon_state *r600_rasterizer(struct r600_context *rctx)
                prov_vtx = 0;
 
        rctx->flat_shade = state->flatshade;
-       rstate = radeon_state(rscreen->rw, R600_RASTERIZER_TYPE, R600_RASTERIZER);
-       if (rstate == NULL)
-               return NULL;
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_RASTERIZER, 0, 0);
        rstate->states[R600_RASTERIZER__SPI_INTERP_CONTROL_0] = 0x00000001;
        if (state->sprite_coord_enable) {
                rstate->states[R600_RASTERIZER__SPI_INTERP_CONTROL_0] |=
@@ -821,7 +897,12 @@ static struct radeon_state *r600_rasterizer(struct r600_context *rctx)
                                        S_0286D4_PNT_SPRITE_TOP_1(1);
                }
        }
-       rstate->states[R600_RASTERIZER__PA_CL_CLIP_CNTL] = 0x00000000;
+       rstate->states[R600_RASTERIZER__PA_CL_CLIP_CNTL] = 0;
+       if (clip) {
+               rstate->states[R600_RASTERIZER__PA_CL_CLIP_CNTL] = S_028810_PS_UCP_MODE(3) | ((1 << clip->nr) - 1);
+               rstate->states[R600_RASTERIZER__PA_CL_CLIP_CNTL] |= S_028810_ZCLIP_NEAR_DISABLE(clip->depth_clamp);
+               rstate->states[R600_RASTERIZER__PA_CL_CLIP_CNTL] |= S_028810_ZCLIP_FAR_DISABLE(clip->depth_clamp);
+       }
        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) |
@@ -835,7 +916,7 @@ static struct radeon_state *r600_rasterizer(struct r600_context *rctx)
                        S_02881C_VS_OUT_MISC_VEC_ENA(state->point_size_per_vertex);
        rstate->states[R600_RASTERIZER__PA_CL_NANINF_CNTL] = 0x00000000;
        /* point size 12.4 fixed point */
-       tmp = (unsigned)(state->point_size * 8.0 / 2.0);
+       tmp = (unsigned)(state->point_size * 8.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;
@@ -852,19 +933,14 @@ static struct radeon_state *r600_rasterizer(struct r600_context *rctx)
        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;
-       }
-       return rstate;
+       radeon_state_pm4(rstate);
 }
 
-static struct radeon_state *r600_scissor(struct r600_context *rctx)
+static void r600_scissor(struct r600_context *rctx, struct radeon_state *rstate)
 {
        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;
 
@@ -881,9 +957,7 @@ static struct radeon_state *r600_scissor(struct r600_context *rctx)
        }
        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 NULL;
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_SCISSOR, 0, 0);
        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;
@@ -903,22 +977,14 @@ static struct radeon_state *r600_scissor(struct r600_context *rctx)
        rstate->states[R600_SCISSOR__PA_SC_GENERIC_SCISSOR_BR] = br;
        rstate->states[R600_SCISSOR__PA_SC_VPORT_SCISSOR_0_TL] = tl;
        rstate->states[R600_SCISSOR__PA_SC_VPORT_SCISSOR_0_BR] = br;
-       if (radeon_state_pm4(rstate)) {
-               radeon_state_decref(rstate);
-               return NULL;
-       }
-       return rstate;
+       radeon_state_pm4(rstate);
 }
 
-static struct radeon_state *r600_viewport(struct r600_context *rctx)
+static void r600_viewport(struct r600_context *rctx, struct radeon_state *rstate, const struct pipe_viewport_state *state)
 {
-       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 NULL;
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_VIEWPORT, 0, 0);
        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] = fui(state->scale[0]);
@@ -928,29 +994,28 @@ static struct radeon_state *r600_viewport(struct r600_context *rctx)
        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 NULL;
-       }
-       return rstate;
+       radeon_state_pm4(rstate);
 }
 
-static struct radeon_state *r600_dsa(struct r600_context *rctx)
+static void r600_dsa(struct r600_context *rctx, struct radeon_state *rstate)
 {
        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;
+       struct r600_shader *rshader;
        int i;
 
-       rstate = radeon_state(rscreen->rw, R600_DSA_TYPE, R600_DSA);
-       if (rstate == NULL)
-               return NULL;
+       if (rctx->ps_shader == NULL) {
+               return;
+       }
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_DSA, 0, 0);
 
        db_shader_control = 0x210;
+       rshader = &rctx->ps_shader->shader;
+       if (rshader->uses_kill)
+               db_shader_control |= (1 << 6);
        for (i = 0; i < rshader->noutput; i++) {
                if (rshader->output[i].name == TGSI_SEMANTIC_POSITION)
                        db_shader_control |= 1;
@@ -1008,11 +1073,7 @@ static struct radeon_state *r600_dsa(struct r600_context *rctx)
        rstate->states[R600_DSA__DB_SRESULTS_COMPARE_STATE1] = 0x00000000;
        rstate->states[R600_DSA__DB_PRELOAD_CONTROL] = 0x00000000;
        rstate->states[R600_DSA__DB_ALPHA_TO_MASK] = 0x0000AA00;
-       if (radeon_state_pm4(rstate)) {
-               radeon_state_decref(rstate);
-               return NULL;
-       }
-       return rstate;
+       radeon_state_pm4(rstate);
 }
 
 static inline unsigned r600_tex_wrap(unsigned wrap)
@@ -1090,16 +1151,12 @@ 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)
+static void r600_sampler(struct r600_context *rctx, struct radeon_state *rstate,
+                       const struct pipe_sampler_state *state, unsigned id)
 {
        struct r600_screen *rscreen = rctx->screen;
-       struct radeon_state *rstate;
 
-       rstate = radeon_state(rscreen->rw, R600_PS_SAMPLER_TYPE, id);
-       if (rstate == NULL)
-               return NULL;
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_SAMPLER, id, R600_SHADER_PS);
        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)) |
@@ -1114,11 +1171,7 @@ static struct radeon_state *r600_sampler(struct r600_context *rctx,
                        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;
+       radeon_state_pm4(rstate);
 }
 
 static inline unsigned r600_tex_swizzle(unsigned swizzle)
@@ -1160,6 +1213,7 @@ static inline unsigned r600_tex_dim(unsigned dim)
        case PIPE_TEXTURE_1D:
                return V_038000_SQ_TEX_DIM_1D;
        case PIPE_TEXTURE_2D:
+       case PIPE_TEXTURE_RECT:
                return V_038000_SQ_TEX_DIM_2D;
        case PIPE_TEXTURE_3D:
                return V_038000_SQ_TEX_DIM_3D;
@@ -1168,19 +1222,20 @@ static inline unsigned r600_tex_dim(unsigned dim)
        }
 }
 
-static struct radeon_state *r600_resource(struct r600_context *rctx,
-                                       const struct pipe_sampler_view *view,
-                                       unsigned id)
+static void r600_resource(struct pipe_context *ctx, struct radeon_state *rstate,
+                       const struct pipe_sampler_view *view, unsigned id)
 {
+       struct r600_context *rctx = r600_context(ctx);
        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];
+       uint32_t word4 = 0, yuv_format = 0, pitch = 0;
+       unsigned char swizzle[4], array_mode = 0, tile_type = 0;
+       int r;
 
+       rstate->cpm4 = 0;
        swizzle[0] = view->swizzle_r;
        swizzle[1] = view->swizzle_g;
        swizzle[2] = view->swizzle_b;
@@ -1188,37 +1243,49 @@ static struct radeon_state *r600_resource(struct r600_context *rctx,
        format = r600_translate_texformat(view->texture->format,
                                          swizzle,
                                          &word4, &yuv_format);
-       if (format == ~0)
-               return NULL;
+       if (format == ~0) {
+               return;
+       }
        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;
+               return;
        }
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_RESOURCE, id, R600_SHADER_PS);
        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);
+       if (tmp->depth) {
+               r = r600_texture_from_depth(ctx, tmp, view->first_level);
+               if (r) {
+                       return;
+               }
+               rstate->bo[0] = radeon_bo_incref(rscreen->rw, tmp->uncompressed);
+               rstate->bo[1] = radeon_bo_incref(rscreen->rw, tmp->uncompressed);
+       } else {
+               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;
 
+       pitch = (tmp->pitch[0] / tmp->bpt);
+       pitch = (pitch + 0x7) & ~0x7;
+
        /* 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_TILE_MODE(array_mode) |
+                       S_038000_TILE_TYPE(tile_type) |
+                       S_038000_PITCH((pitch / 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_WORD2] = tmp->offset[0] >> 8;
        rstate->states[R600_PS_RESOURCE__RESOURCE0_WORD3] = tmp->offset[1] >> 8;
        rstate->states[R600_PS_RESOURCE__RESOURCE0_WORD4] =
                        word4 | 
@@ -1232,17 +1299,12 @@ static struct radeon_state *r600_resource(struct r600_context *rctx,
                        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;
+       radeon_state_pm4(rstate);
 }
 
-static struct radeon_state *r600_cb_cntl(struct r600_context *rctx)
+static void r600_cb_cntl(struct r600_context *rctx, struct radeon_state *rstate)
 {
        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;
@@ -1257,7 +1319,7 @@ static struct radeon_state *r600_cb_cntl(struct r600_context *rctx)
        }
 
        if (pbs->logicop_enable) {
-               color_control |= (pbs->logicop_func) << 16;
+               color_control |= (pbs->logicop_func << 16) | (pbs->logicop_func << 20);
        } else {
                color_control |= (0xcc << 16);
        }
@@ -1277,7 +1339,7 @@ static struct radeon_state *r600_cb_cntl(struct r600_context *rctx)
                        target_mask |= (pbs->rt[0].colormask << (4 * i));
                }
        }
-       rstate = radeon_state(rscreen->rw, R600_CB_CNTL_TYPE, R600_CB_CNTL);
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_CB_CNTL, 0, 0);
        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;
@@ -1289,115 +1351,51 @@ static struct radeon_state *r600_cb_cntl(struct r600_context *rctx)
        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;
+       radeon_state_pm4(rstate);
 }
 
-int r600_context_hw_states(struct r600_context *rctx)
+int r600_context_hw_states(struct pipe_context *ctx)
 {
+       struct r600_context *rctx = r600_context(ctx);
        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]);
+       /* build new states */
+       r600_rasterizer(rctx, &rctx->hw_states.rasterizer);
+       r600_scissor(rctx, &rctx->hw_states.scissor);
+       r600_dsa(rctx, &rctx->hw_states.dsa);
+       r600_cb_cntl(rctx, &rctx->hw_states.cb_cntl);
+
+       /* bind states */
+       radeon_draw_bind(&rctx->draw, &rctx->hw_states.rasterizer);
+       radeon_draw_bind(&rctx->draw, &rctx->hw_states.scissor);
+       radeon_draw_bind(&rctx->draw, &rctx->hw_states.dsa);
+       radeon_draw_bind(&rctx->draw, &rctx->hw_states.cb_cntl);
+
+       radeon_draw_bind(&rctx->draw, &rctx->config);
+
+       if (rctx->viewport) {
+               radeon_draw_bind(&rctx->draw, &rctx->viewport->rstate[0]);
        }
-       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;
+       if (rctx->blend) {
+               radeon_draw_bind(&rctx->draw, &rctx->blend->rstate[0]);
        }
-       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;
+       if (rctx->clip) {
+               radeon_draw_bind(&rctx->draw, &rctx->clip->rstate[0]);
        }
-       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);
+       for (i = 0; i < rctx->framebuffer->state.framebuffer.nr_cbufs; i++) {
+               radeon_draw_bind(&rctx->draw, &rctx->framebuffer->rstate[i+1]);
+       }
+       if (rctx->framebuffer->state.framebuffer.zsbuf) {
+               radeon_draw_bind(&rctx->draw, &rctx->framebuffer->rstate[0]);
        }
-       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);
+                       radeon_draw_bind(&rctx->draw, rctx->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;
+                       radeon_draw_bind(&rctx->draw, rctx->ps_sampler_view[i]);
                }
        }
        return 0;
index f93c20da35e820a8bd09757210d91327af037b31..84866825aab022de9013b9df1eef9ccba57a866f 100644 (file)
@@ -252,6 +252,7 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format)
        case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
        case PIPE_FORMAT_X8B8G8R8_UNORM:
        case PIPE_FORMAT_X8R8G8B8_UNORM:
+       case PIPE_FORMAT_R8G8B8_UNORM:
                return V_0280A0_COLOR_8_8_8_8;
 
        case PIPE_FORMAT_R10G10B10A2_UNORM:
@@ -262,7 +263,10 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format)
 
        case PIPE_FORMAT_Z24X8_UNORM:
        case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
-               return V_0280A0_COLOR_24_8;
+               return V_0280A0_COLOR_8_24;
+
+       case PIPE_FORMAT_R32_FLOAT:
+               return V_0280A0_COLOR_32_FLOAT;
 
                /* 64-bit buffers. */
        case PIPE_FORMAT_R16G16B16A16_UNORM:
@@ -275,6 +279,7 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format)
 
                /* 128-bit buffers. */
        case PIPE_FORMAT_R32G32B32_FLOAT:
+               return V_0280A0_COLOR_32_32_32_FLOAT;
        case PIPE_FORMAT_R32G32B32A32_FLOAT:
                return V_0280A0_COLOR_32_32_32_32_FLOAT;
 
index 30d79ebdd6ffb3af06ec11754cb38de9c3f040cd..b6698e3885ce0d74c660efb4aeb4487a9f99138c 100644 (file)
@@ -24,6 +24,7 @@
  *      Jerome Glisse
  *      Corbin Simpson
  */
+#include <errno.h>
 #include <pipe/p_screen.h>
 #include <util/u_format.h>
 #include <util/u_math.h>
 #include "r600_screen.h"
 #include "r600_context.h"
 #include "r600_resource.h"
+#include "r600_state_inlines.h"
 #include "r600d.h"
 
 extern struct u_resource_vtbl r600_texture_vtbl;
 
+/* Copy from a tiled texture to a detiled one. */
+static void r600_copy_from_tiled_texture(struct pipe_context *ctx, struct r600_transfer *rtransfer)
+{
+       struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer;
+       struct pipe_resource *texture = transfer->resource;
+       struct pipe_subresource subdst;
+
+       subdst.face = 0;
+       subdst.level = 0;
+       ctx->resource_copy_region(ctx, rtransfer->linear_texture,
+                               subdst, 0, 0, 0, texture, transfer->sr,
+                               transfer->box.x, transfer->box.y, transfer->box.z,
+                               transfer->box.width, transfer->box.height);
+}
+
 static unsigned long r600_texture_get_offset(struct r600_resource_texture *rtex,
                                        unsigned level, unsigned zslice,
                                        unsigned face)
@@ -65,7 +82,9 @@ static void r600_setup_miptree(struct r600_screen *rscreen, struct r600_resource
        for (i = 0, offset = 0; i <= ptex->last_level; i++) {
                w = u_minify(ptex->width0, i);
                h = u_minify(ptex->height0, i);
+               h = util_next_power_of_two(h);
                pitch = util_format_get_stride(ptex->format, align(w, 64));
+               pitch = align(pitch, 256);
                layer_size = pitch * h;
                if (ptex->target == PIPE_TEXTURE_CUBE)
                        size = layer_size * 6;
@@ -74,6 +93,8 @@ static void r600_setup_miptree(struct r600_screen *rscreen, struct r600_resource
                rtex->offset[i] = offset;
                rtex->layer_size[i] = layer_size;
                rtex->pitch[i] = pitch;
+               rtex->width[i] = w;
+               rtex->height[i] = h;
                offset += size;
        }
        rtex->size = offset;
@@ -104,10 +125,22 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
                FREE(rtex);
                return NULL;
        }
-
        return &resource->base.b;
 }
 
+static void r600_texture_destroy_state(struct pipe_resource *ptexture)
+{
+       struct r600_resource_texture *rtexture = (struct r600_resource_texture*)ptexture;
+
+       for (int i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++) {
+               radeon_state_fini(&rtexture->scissor[i]);
+               radeon_state_fini(&rtexture->db[i]);
+               for (int j = 0; j < 8; j++) {
+                       radeon_state_fini(&rtexture->cb[j][i]);
+               }
+       }
+}
+
 static void r600_texture_destroy(struct pipe_screen *screen,
                                 struct pipe_resource *ptex)
 {
@@ -118,6 +151,10 @@ static void r600_texture_destroy(struct pipe_screen *screen,
        if (resource->bo) {
                radeon_bo_decref(rscreen->rw, resource->bo);
        }
+       if (rtex->uncompressed) {
+               radeon_bo_decref(rscreen->rw, rtex->uncompressed);
+       }
+       r600_texture_destroy_state(ptex);
        FREE(rtex);
 }
 
@@ -168,7 +205,8 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen,
        }
 
        /* Support only 2D textures without mipmaps */
-       if (templ->target != PIPE_TEXTURE_2D || templ->depth0 != 1 || templ->last_level != 0)
+       if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) ||
+             templ->depth0 != 1 || templ->last_level != 0)
                return NULL;
 
        rtex = CALLOC_STRUCT(r600_resource_texture);
@@ -181,9 +219,12 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen,
        pipe_reference_init(&resource->base.b.reference, 1);
        resource->base.b.screen = screen;
        resource->bo = bo;
+       rtex->depth = 0;
        rtex->pitch_override = whandle->stride;
        rtex->bpt = util_format_get_blocksize(templ->format);
        rtex->pitch[0] = whandle->stride;
+       rtex->width[0] = templ->width0;
+       rtex->height[0] = templ->height0;
        rtex->offset[0] = 0;
        rtex->size = align(rtex->pitch[0] * templ->height0, 64);
 
@@ -205,6 +246,7 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
                                                const struct pipe_box *box)
 {
        struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
+       struct pipe_resource resource;
        struct r600_transfer *trans;
 
        trans = CALLOC_STRUCT(r600_transfer);
@@ -216,48 +258,117 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
        trans->transfer.box = *box;
        trans->transfer.stride = rtex->pitch[sr.level];
        trans->offset = r600_texture_get_offset(rtex, sr.level, box->z, sr.face);
+       if (rtex->tilled && !rtex->depth) {
+               resource.target = PIPE_TEXTURE_2D;
+               resource.format = texture->format;
+               resource.width0 = box->width;
+               resource.height0 = box->height;
+               resource.depth0 = 0;
+               resource.last_level = 0;
+               resource.nr_samples = 0;
+               resource.usage = PIPE_USAGE_DYNAMIC;
+               resource.bind = 0;
+               resource.flags = 0;
+               /* For texture reading, the temporary (detiled) texture is used as
+                * a render target when blitting from a tiled texture. */
+               if (usage & PIPE_TRANSFER_READ) {
+                       resource.bind |= PIPE_BIND_RENDER_TARGET;
+               }
+               /* For texture writing, the temporary texture is used as a sampler
+                * when blitting into a tiled texture. */
+               if (usage & PIPE_TRANSFER_WRITE) {
+                       resource.bind |= PIPE_BIND_SAMPLER_VIEW;
+               }
+               /* Create the temporary texture. */
+               trans->linear_texture = ctx->screen->resource_create(ctx->screen, &resource);
+               if (trans->linear_texture == NULL) {
+                       R600_ERR("failed to create temporary texture to hold untiled copy\n");
+                       pipe_resource_reference(&trans->transfer.resource, NULL);
+                       FREE(trans);
+                       return NULL;
+               }
+               if (usage & PIPE_TRANSFER_READ) {
+                       /* We cannot map a tiled texture directly because the data is
+                        * in a different order, therefore we do detiling using a blit. */
+                       r600_copy_from_tiled_texture(ctx, trans);
+                       /* Always referenced in the blit. */
+                       ctx->flush(ctx, 0, NULL);
+               }
+       }
        return &trans->transfer;
 }
 
 void r600_texture_transfer_destroy(struct pipe_context *ctx,
-                                  struct pipe_transfer *trans)
+                                  struct pipe_transfer *transfer)
 {
-       pipe_resource_reference(&trans->resource, NULL);
-       FREE(trans);
+       struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
+
+       if (rtransfer->linear_texture) {
+               pipe_resource_reference(&rtransfer->linear_texture, NULL);
+       }
+       pipe_resource_reference(&transfer->resource, NULL);
+       FREE(transfer);
 }
 
 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;
+       struct radeon_bo *bo;
        enum pipe_format format = transfer->resource->format;
        struct r600_screen *rscreen = r600_screen(ctx->screen);
+       struct r600_resource_texture *rtex;
+       unsigned long offset = 0;
        char *map;
+       int r;
 
        r600_flush(ctx, 0, NULL);
-
-       resource = (struct r600_resource *)transfer->resource;
-       if (radeon_bo_map(rscreen->rw, resource->bo)) {
+       if (rtransfer->linear_texture) {
+               bo = ((struct r600_resource *)rtransfer->linear_texture)->bo;
+       } else {
+               rtex = (struct r600_resource_texture*)transfer->resource;
+               if (rtex->depth) {
+                       r = r600_texture_from_depth(ctx, rtex, transfer->sr.level);
+                       if (r) {
+                               return NULL;
+                       }
+                       r600_flush(ctx, 0, NULL);
+                       bo = rtex->uncompressed;
+               } else {
+                       bo = ((struct r600_resource *)transfer->resource)->bo;
+               }
+               offset = 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 (radeon_bo_map(rscreen->rw, bo)) {
                return NULL;
        }
-       radeon_bo_wait(rscreen->rw, resource->bo);
-
-       map = resource->bo->data;
+       radeon_bo_wait(rscreen->rw, bo);
 
-       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);
+       map = bo->data;
+       return map + offset;
 }
 
 void r600_texture_transfer_unmap(struct pipe_context *ctx,
                                 struct pipe_transfer* transfer)
 {
+       struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
        struct r600_screen *rscreen = r600_screen(ctx->screen);
-       struct r600_resource *resource;
-
-       resource = (struct r600_resource *)transfer->resource;
-       radeon_bo_unmap(rscreen->rw, resource->bo);
+       struct r600_resource_texture *rtex;
+       struct radeon_bo *bo;
+
+       if (rtransfer->linear_texture) {
+               bo = ((struct r600_resource *)rtransfer->linear_texture)->bo;
+       } else {
+               rtex = (struct r600_resource_texture*)transfer->resource;
+               if (rtex->depth) {
+                       bo = rtex->uncompressed;
+               } else {
+                       bo = ((struct r600_resource *)transfer->resource)->bo;
+               }
+       }
+       radeon_bo_unmap(rscreen->rw, bo);
 }
 
 struct u_resource_vtbl r600_texture_vtbl =
@@ -280,51 +391,51 @@ void r600_init_screen_texture_functions(struct pipe_screen *screen)
 }
 
 static unsigned r600_get_swizzle_combined(const unsigned char *swizzle_format,
-                                         const unsigned char *swizzle_view)
+               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;
+       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 */
@@ -344,19 +455,21 @@ uint32_t r600_translate_texformat(enum pipe_format format,
        };
        desc = util_format_description(format);
 
+       word4 |= r600_get_swizzle_combined(desc->swizzle, swizzle_view);
+
        /* 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;
+                       result = V_0280A0_COLOR_16;
                        goto out_word4;
                case PIPE_FORMAT_Z24X8_UNORM:
-                       result = V_028010_DEPTH_X8_24;
+                       result = V_0280A0_COLOR_8_24;
                        goto out_word4;
                case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
-                       result = V_028010_DEPTH_8_24;
+                       result = V_0280A0_COLOR_8_24;
                        goto out_word4;
                default:
                        goto out_unknown;
@@ -382,8 +495,6 @@ uint32_t r600_translate_texformat(enum pipe_format format,
                break;
        }
        
-       word4 |= r600_get_swizzle_combined(desc->swizzle, swizzle_view);
-
        /* S3TC formats. TODO */
        if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
                goto out_unknown;
@@ -519,9 +630,221 @@ out_word4:
                *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;
 }
+
+int r600_texture_from_depth(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
+{
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+       int r;
+
+       if (!rtexture->depth) {
+               /* This shouldn't happen maybe print a warning */
+               return 0;
+       }
+       if (rtexture->uncompressed && !rtexture->dirty) {
+               /* Uncompressed bo already in good state */
+               return 0;
+       }
+
+       /* allocate uncompressed texture */
+       if (rtexture->uncompressed == NULL) {
+               rtexture->uncompressed = radeon_bo(rscreen->rw, 0, rtexture->size, 4096, NULL);
+               if (rtexture->uncompressed == NULL) {
+                       return -ENOMEM;
+               }
+       }
+
+       /* render a rectangle covering whole buffer to uncompress depth */
+       r = r600_blit_uncompress_depth(ctx, rtexture, level);
+       if (r) {
+               return r;
+       }
+
+       rtexture->dirty = 0;
+       return 0;
+}
+
+static void r600_texture_state_scissor(struct r600_screen *rscreen,
+                                       struct r600_resource_texture *rtexture,
+                                       unsigned level)
+{
+       struct radeon_state *rstate = &rtexture->scissor[level];
+
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_SCISSOR, 0, 0);
+       /* set states (most default value are 0 and struct already
+        * initialized to 0, thus avoid resetting them)
+        */
+       rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_0_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
+       rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_0_TL] = 0x80000000;
+       rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_1_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
+       rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_1_TL] = 0x80000000;
+       rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_2_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
+       rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_2_TL] = 0x80000000;
+       rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_3_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
+       rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_3_TL] = 0x80000000;
+       rstate->states[R600_SCISSOR__PA_SC_CLIPRECT_RULE] = 0x0000FFFF;
+       rstate->states[R600_SCISSOR__PA_SC_EDGERULE] = 0xAAAAAAAA;
+       rstate->states[R600_SCISSOR__PA_SC_GENERIC_SCISSOR_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
+       rstate->states[R600_SCISSOR__PA_SC_GENERIC_SCISSOR_TL] = 0x80000000;
+       rstate->states[R600_SCISSOR__PA_SC_SCREEN_SCISSOR_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
+       rstate->states[R600_SCISSOR__PA_SC_SCREEN_SCISSOR_TL] = 0x80000000;
+       rstate->states[R600_SCISSOR__PA_SC_VPORT_SCISSOR_0_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
+       rstate->states[R600_SCISSOR__PA_SC_VPORT_SCISSOR_0_TL] = 0x80000000;
+       rstate->states[R600_SCISSOR__PA_SC_WINDOW_SCISSOR_BR] = S_028244_BR_X(rtexture->width[level]) | S_028244_BR_Y(rtexture->height[level]);
+       rstate->states[R600_SCISSOR__PA_SC_WINDOW_SCISSOR_TL] = 0x80000000;
+
+       radeon_state_pm4(rstate);
+}
+
+static void r600_texture_state_cb(struct r600_screen *rscreen, struct r600_resource_texture *rtexture, unsigned cb, unsigned level)
+{
+       struct radeon_state *rstate;
+       struct r600_resource *rbuffer;
+       unsigned pitch, slice;
+       unsigned color_info;
+       unsigned format, swap, ntype;
+       const struct util_format_description *desc;
+
+       rstate = &rtexture->cb[cb][level];
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_CB0 + cb, 0, 0);
+       rbuffer = &rtexture->resource;
+
+       /* set states (most default value are 0 and struct already
+        * initialized to 0, thus avoid resetting them)
+        */
+       pitch = (rtexture->pitch[level] / rtexture->bpt) / 8 - 1;
+       slice = (rtexture->pitch[level] / rtexture->bpt) * rtexture->height[level] / 64 - 1;
+       ntype = 0;
+       desc = util_format_description(rbuffer->base.b.format);
+       if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
+               ntype = V_0280A0_NUMBER_SRGB;
+       format = r600_translate_colorformat(rtexture->resource.base.b.format);
+       swap = r600_translate_colorswap(rtexture->resource.base.b.format);
+       if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
+               rstate->bo[0] = radeon_bo_incref(rscreen->rw, rtexture->uncompressed);
+               rstate->bo[1] = radeon_bo_incref(rscreen->rw, rtexture->uncompressed);
+               rstate->bo[2] = radeon_bo_incref(rscreen->rw, rtexture->uncompressed);
+               rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
+               rstate->placement[2] = RADEON_GEM_DOMAIN_GTT;
+               rstate->placement[4] = RADEON_GEM_DOMAIN_GTT;
+               rstate->nbo = 3;
+               color_info = 0;
+       } else {
+               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);
+               rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
+               rstate->placement[2] = RADEON_GEM_DOMAIN_GTT;
+               rstate->placement[4] = RADEON_GEM_DOMAIN_GTT;
+               rstate->nbo = 3;
+               color_info = S_0280A0_SOURCE_FORMAT(1);
+       }
+       color_info |= S_0280A0_FORMAT(format) |
+               S_0280A0_COMP_SWAP(swap) |
+               S_0280A0_BLEND_CLAMP(1) |
+               S_0280A0_NUMBER_TYPE(ntype);
+       rstate->states[R600_CB0__CB_COLOR0_BASE] = rtexture->offset[level] >> 8;
+       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);
+
+       radeon_state_pm4(rstate);
+}
+
+static void r600_texture_state_db(struct r600_screen *rscreen, struct r600_resource_texture *rtexture, unsigned level)
+{
+       struct radeon_state *rstate = &rtexture->db[level];
+       struct r600_resource *rbuffer;
+       unsigned pitch, slice, format;
+
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_DB, 0, 0);
+       rbuffer = &rtexture->resource;
+       rtexture->tilled = 1;
+       rtexture->array_mode = 2;
+       rtexture->tile_type = 1;
+       rtexture->depth = 1;
+
+       /* set states (most default value are 0 and struct already
+        * initialized to 0, thus avoid resetting them)
+        */
+       pitch = (rtexture->pitch[level] / rtexture->bpt) / 8 - 1;
+       slice = (rtexture->pitch[level] / rtexture->bpt) * rtexture->height[level] / 64 - 1;
+       format = r600_translate_dbformat(rbuffer->base.b.format);
+       rstate->states[R600_DB__DB_DEPTH_BASE] = rtexture->offset[level] >> 8;
+       rstate->states[R600_DB__DB_DEPTH_INFO] = S_028010_ARRAY_MODE(rtexture->array_mode) |
+                                       S_028010_FORMAT(format);
+       rstate->states[R600_DB__DB_DEPTH_VIEW] = 0x00000000;
+       rstate->states[R600_DB__DB_PREFETCH_LIMIT] = (rtexture->height[level] / 8) -1;
+       rstate->states[R600_DB__DB_DEPTH_SIZE] = S_028000_PITCH_TILE_MAX(pitch) |
+                                               S_028000_SLICE_TILE_MAX(slice);
+       rstate->bo[0] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
+       rstate->placement[0] = RADEON_GEM_DOMAIN_GTT;
+       rstate->nbo = 1;
+
+       radeon_state_pm4(rstate);
+}
+
+int r600_texture_scissor(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
+{
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+
+       if (!rtexture->scissor[level].cpm4) {
+               r600_texture_state_scissor(rscreen, rtexture, level);
+       }
+       return 0;
+}
+
+static void r600_texture_state_viewport(struct r600_screen *rscreen, struct r600_resource_texture *rtexture, unsigned level)
+{
+       struct radeon_state *rstate = &rtexture->viewport[level];
+
+       radeon_state_init(rstate, rscreen->rw, R600_STATE_VIEWPORT, 0, 0);
+
+       /* set states (most default value are 0 and struct already
+        * initialized to 0, thus avoid resetting them)
+        */
+       rstate->states[R600_VIEWPORT__PA_CL_VPORT_XOFFSET_0] = fui((float)rtexture->width[level]/2.0);
+       rstate->states[R600_VIEWPORT__PA_CL_VPORT_XSCALE_0] = fui((float)rtexture->width[level]/2.0);
+       rstate->states[R600_VIEWPORT__PA_CL_VPORT_YOFFSET_0] = fui((float)rtexture->height[level]/2.0);
+       rstate->states[R600_VIEWPORT__PA_CL_VPORT_YSCALE_0] = fui((float)-rtexture->height[level]/2.0);
+       rstate->states[R600_VIEWPORT__PA_CL_VPORT_ZOFFSET_0] = 0x3F000000;
+       rstate->states[R600_VIEWPORT__PA_CL_VPORT_ZSCALE_0] = 0x3F000000;
+       rstate->states[R600_VIEWPORT__PA_CL_VTE_CNTL] = 0x0000043F;
+       rstate->states[R600_VIEWPORT__PA_SC_VPORT_ZMAX_0] = 0x3F800000;
+
+       radeon_state_pm4(rstate);
+}
+
+int r600_texture_cb(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned cb, unsigned level)
+{
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+
+       if (!rtexture->cb[cb][level].cpm4) {
+               r600_texture_state_cb(rscreen, rtexture, cb, level);
+       }
+       return 0;
+}
+
+int r600_texture_db(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
+{
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+
+       if (!rtexture->db[level].cpm4) {
+               r600_texture_state_db(rscreen, rtexture, level);
+       }
+       return 0;
+}
+
+int r600_texture_viewport(struct pipe_context *ctx, struct r600_resource_texture *rtexture, unsigned level)
+{
+       struct r600_screen *rscreen = r600_screen(ctx->screen);
+
+       if (!rtexture->viewport[level].cpm4) {
+               r600_texture_state_viewport(rscreen, rtexture, level);
+       }
+       return 0;
+}
index 53388f822ea10545a161225882afbfb12a65894f..7b9a983d53b30cb53a0935b38cb0fc3911a3298e 100644 (file)
 #define     V_0280A0_COLOR_16_16_16_16_FLOAT           0x00000020
 #define     V_0280A0_COLOR_32_32_32_32                 0x00000022
 #define     V_0280A0_COLOR_32_32_32_32_FLOAT           0x00000023
+#define     V_0280A0_COLOR_32_32_32_FLOAT              0x00000030
 #define   S_0280A0_ARRAY_MODE(x)                       (((x) & 0xF) << 8)
 #define   G_0280A0_ARRAY_MODE(x)                       (((x) >> 8) & 0xF)
 #define   C_0280A0_ARRAY_MODE                          0xFFFFF0FF
 #define   G_0286D4_PNT_SPRITE_TOP_1(x)                 (((x) >> 14) & 0x1)
 #define   C_0286D4_PNT_SPRITE_TOP_1                    0xFFFFBFFF
 
+#define SQ_TEX_INST_LD 0x03
+#define SQ_TEX_INST_GET_GRADIENTS_H 0x7
+#define SQ_TEX_INST_GET_GRADIENTS_V 0x8
+
+#define SQ_TEX_INST_SAMPLE 0x10
+#define SQ_TEX_INST_SAMPLE_L 0x11
+#define SQ_TEX_INST_SAMPLE_C 0x18
 #endif
index 8f00a4895a0c82a184dc43158c3669aede8332dc..aaac8de528354cbd26ebd75aab3c348dec77ed1c 100644 (file)
@@ -77,6 +77,14 @@ enum radeon_family {
        CHIP_LAST,
 };
 
+enum {
+       R600_SHADER_PS = 1,
+       R600_SHADER_VS,
+       R600_SHADER_GS,
+       R600_SHADER_FS,
+       R600_SHADER_MAX = R600_SHADER_FS,
+};
+
 enum radeon_family radeon_get_family(struct radeon *rw);
 
 /*
@@ -98,22 +106,23 @@ struct radeon_bo *radeon_bo_incref(struct radeon *radeon, struct radeon_bo *bo);
 struct radeon_bo *radeon_bo_decref(struct radeon *radeon, struct radeon_bo *bo);
 int radeon_bo_wait(struct radeon *radeon, struct radeon_bo *bo);
 
+struct radeon_stype_info;
 /*
  * states functions
  */
 struct radeon_state {
        struct radeon                   *radeon;
        unsigned                        refcount;
-       unsigned                        type;
+       struct radeon_stype_info        *stype;
+       unsigned                        state_id;
        unsigned                        id;
+       unsigned                        shader_index;
        unsigned                        nstates;
-       u32                             *states;
+       u32                             states[64];
        unsigned                        npm4;
        unsigned                        cpm4;
        u32                             pm4_crc;
-       u32                             *pm4;
-       u32                             nimmd;
-       u32                             *immd;
+       u32                             pm4[128];
        unsigned                        nbo;
        struct radeon_bo                *bo[4];
        unsigned                        nreloc;
@@ -123,38 +132,22 @@ struct radeon_state {
        unsigned                        bo_dirty[4];
 };
 
-struct radeon_state *radeon_state(struct radeon *radeon, u32 type, u32 id);
-struct radeon_state *radeon_state_incref(struct radeon_state *state);
-struct radeon_state *radeon_state_decref(struct radeon_state *state);
+int radeon_state_init(struct radeon_state *rstate, struct radeon *radeon, u32 type, u32 id, u32 shader_class);
+void radeon_state_fini(struct radeon_state *state);
 int radeon_state_pm4(struct radeon_state *state);
+int radeon_state_convert(struct radeon_state *state, u32 stype, u32 id, u32 shader_type);
 
 /*
  * draw functions
  */
 struct radeon_draw {
-       unsigned                        refcount;
        struct radeon                   *radeon;
-       unsigned                        nstate;
        struct radeon_state             **state;
-       unsigned                        cpm4;
 };
 
-struct radeon_draw *radeon_draw(struct radeon *radeon);
-struct radeon_draw *radeon_draw_duplicate(struct radeon_draw *draw);
-struct radeon_draw *radeon_draw_incref(struct radeon_draw *draw);
-struct radeon_draw *radeon_draw_decref(struct radeon_draw *draw);
-int radeon_draw_set(struct radeon_draw *draw, struct radeon_state *state);
-int radeon_draw_set_new(struct radeon_draw *draw, struct radeon_state *state);
-int radeon_draw_check(struct radeon_draw *draw);
-
-struct radeon_ctx *radeon_ctx(struct radeon *radeon);
-struct radeon_ctx *radeon_ctx_decref(struct radeon_ctx *ctx);
-struct radeon_ctx *radeon_ctx_incref(struct radeon_ctx *ctx);
-int radeon_ctx_set_draw(struct radeon_ctx *ctx, struct radeon_draw *draw);
-int radeon_ctx_set_draw_new(struct radeon_ctx *ctx, struct radeon_draw *draw);
-int radeon_ctx_pm4(struct radeon_ctx *ctx);
-int radeon_ctx_submit(struct radeon_ctx *ctx);
-void radeon_ctx_dump_bof(struct radeon_ctx *ctx, const char *file);
+int radeon_draw_init(struct radeon_draw *draw, struct radeon *radeon);
+void radeon_draw_bind(struct radeon_draw *draw, struct radeon_state *state);
+void radeon_draw_unbind(struct radeon_draw *draw, struct radeon_state *state);
 
 /*
  * radeon context functions
@@ -169,95 +162,57 @@ struct radeon_cs_reloc {
 #pragma pack()
 
 struct radeon_ctx {
-       int                             refcount;
        struct radeon                   *radeon;
        u32                             *pm4;
-       u32                             cpm4;
-       u32                             draw_cpm4;
-       unsigned                        id;
-       unsigned                        next_id;
+       int                             cdwords;
+       int                             ndwords;
        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_init(struct radeon_ctx *ctx, struct radeon *radeon);
+void radeon_ctx_fini(struct radeon_ctx *ctx);
+void radeon_ctx_clear(struct radeon_ctx *ctx);
+int radeon_ctx_set_draw(struct radeon_ctx *ctx, struct radeon_draw *draw);
+int radeon_ctx_submit(struct radeon_ctx *ctx);
+void radeon_ctx_dump_bof(struct radeon_ctx *ctx, const char *file);
+int radeon_ctx_set_query_state(struct radeon_ctx *ctx, struct radeon_state *state);
+
 /*
  * R600/R700
  */
 
-#define R600_NSTATE                            1280
-#define R600_NTYPE                             32
+enum r600_stype {
+       R600_STATE_CONFIG,
+       R600_STATE_CB_CNTL,
+       R600_STATE_RASTERIZER,
+       R600_STATE_VIEWPORT,
+       R600_STATE_SCISSOR,
+       R600_STATE_BLEND,
+       R600_STATE_DSA,
+       R600_STATE_SHADER,          /* has PS,VS,GS,FS variants */
+       R600_STATE_CONSTANT,        /* has PS,VS,GS,FS variants */
+       R600_STATE_RESOURCE,        /* has PS,VS,GS,FS variants */
+       R600_STATE_SAMPLER,         /* has PS,VS,GS,FS variants */
+       R600_STATE_SAMPLER_BORDER,  /* has PS,VS,GS,FS variants */
+       R600_STATE_CB0,
+       R600_STATE_CB1,
+       R600_STATE_CB2,
+       R600_STATE_CB3,
+       R600_STATE_CB4,
+       R600_STATE_CB5,
+       R600_STATE_CB6,
+       R600_STATE_CB7,
+       R600_STATE_DB,
+       R600_STATE_QUERY_BEGIN,
+       R600_STATE_QUERY_END,
+       R600_STATE_UCP,
+       R600_STATE_VGT,
+       R600_STATE_DRAW,
+};
 
-#define R600_CONFIG                            0
-#define R600_CONFIG_TYPE                               0
-#define R600_CB_CNTL                           1
-#define R600_CB_CNTL_TYPE                              1
-#define R600_RASTERIZER                                2
-#define R600_RASTERIZER_TYPE                           2
-#define R600_VIEWPORT                          3
-#define R600_VIEWPORT_TYPE                             3
-#define R600_SCISSOR                           4
-#define R600_SCISSOR_TYPE                              4
-#define R600_BLEND                             5
-#define R600_BLEND_TYPE                                5
-#define R600_DSA                               6
-#define R600_DSA_TYPE                          6
-#define R600_VS_SHADER                         7
-#define R600_VS_SHADER_TYPE                            7
-#define R600_PS_SHADER                         8
-#define R600_PS_SHADER_TYPE                            8
-#define R600_PS_CONSTANT                               9
-#define R600_PS_CONSTANT_TYPE                          9
-#define R600_VS_CONSTANT                               265
-#define R600_VS_CONSTANT_TYPE                          10
-#define R600_PS_RESOURCE                               521
-#define R600_PS_RESOURCE_TYPE                          11
-#define R600_VS_RESOURCE                               681
-#define R600_VS_RESOURCE_TYPE                          12
-#define R600_FS_RESOURCE                               841
-#define R600_FS_RESOURCE_TYPE                          13
-#define R600_GS_RESOURCE                               1001
-#define R600_GS_RESOURCE_TYPE                          14
-#define R600_PS_SAMPLER                                1161
-#define R600_PS_SAMPLER_TYPE                           15
-#define R600_VS_SAMPLER                                1179
-#define R600_VS_SAMPLER_TYPE                           16
-#define R600_GS_SAMPLER                                1197
-#define R600_GS_SAMPLER_TYPE                           17
-#define R600_PS_SAMPLER_BORDER                         1215
-#define R600_PS_SAMPLER_BORDER_TYPE                            18
-#define R600_VS_SAMPLER_BORDER                         1233
-#define R600_VS_SAMPLER_BORDER_TYPE                            19
-#define R600_GS_SAMPLER_BORDER                         1251
-#define R600_GS_SAMPLER_BORDER_TYPE                            20
-#define R600_CB0                               1269
-#define R600_CB0_TYPE                          21
-#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
@@ -639,9 +594,40 @@ struct radeon_ctx {
 /* R600_DRAW */
 #define R600_DRAW__VGT_NUM_INDICES                     0
 #define R600_DRAW__VGT_DMA_BASE_HI                     1
-#define R600_DRAW__VGT_DMA_BASE                        2
+#define R600_DRAW__VGT_DMA_BASE                                2
 #define R600_DRAW__VGT_DRAW_INITIATOR                  3
-#define R600_DRAW_SIZE                         4
-#define R600_DRAW_PM4                          128
+#define R600_DRAW_SIZE                                 4
+#define R600_DRAW_PM4                                  128
+/* R600_CLIP */
+#define R600_CLIP__PA_CL_UCP_X_0                       0
+#define R600_CLIP__PA_CL_UCP_Y_0                       1
+#define R600_CLIP__PA_CL_UCP_Z_0                       2
+#define R600_CLIP__PA_CL_UCP_W_0                       3
+#define R600_CLIP__PA_CL_UCP_X_1                       4
+#define R600_CLIP__PA_CL_UCP_Y_1                       5
+#define R600_CLIP__PA_CL_UCP_Z_1                       6
+#define R600_CLIP__PA_CL_UCP_W_1                       7
+#define R600_CLIP__PA_CL_UCP_X_2                       8
+#define R600_CLIP__PA_CL_UCP_Y_2                       9
+#define R600_CLIP__PA_CL_UCP_Z_2                       10
+#define R600_CLIP__PA_CL_UCP_W_2                       11
+#define R600_CLIP__PA_CL_UCP_X_3                       12
+#define R600_CLIP__PA_CL_UCP_Y_3                       13
+#define R600_CLIP__PA_CL_UCP_Z_3                       14
+#define R600_CLIP__PA_CL_UCP_W_3                       15
+#define R600_CLIP__PA_CL_UCP_X_4                       16
+#define R600_CLIP__PA_CL_UCP_Y_4                       17
+#define R600_CLIP__PA_CL_UCP_Z_4                       18
+#define R600_CLIP__PA_CL_UCP_W_4                       19
+#define R600_CLIP__PA_CL_UCP_X_5                       20
+#define R600_CLIP__PA_CL_UCP_Y_5                       21
+#define R600_CLIP__PA_CL_UCP_Z_5                       22
+#define R600_CLIP__PA_CL_UCP_W_5                       23
+#define R600_CLIP_SIZE                                 24
+#define R600_CLIP_PM4                                  128
+/* R600 QUERY BEGIN/END */
+#define R600_QUERY__OFFSET                     0
+#define R600_QUERY_SIZE                                1
+#define R600_QUERY_PM4                         128
 
 #endif
index 386c8acb8cee0123b86e187b99f1fe76716bad00..01b4ca985d0ea8cbdb212cc2619df3c060f32654 100644 (file)
@@ -75,14 +75,10 @@ softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode)
    buf = (void*)((int32_t*)buf + offset);
    draw_set_mapped_vertex_buffer(draw, 0, buf);
 
-   draw_set_mapped_element_buffer_range(draw,
-                                        0, 0,
-                                        start,
-                                        start + count - 1,
-                                        NULL);
+   draw_set_mapped_index_buffer(draw, NULL);
 
    /* draw! */
-   draw_arrays_instanced(draw, mode, start, count, 0, 1);
+   draw_arrays(draw, mode, start, count);
 
    /* unmap vertex/index buffers - will cause draw module to flush */
    draw_set_mapped_vertex_buffer(draw, 0, NULL);
@@ -138,28 +134,20 @@ softpipe_draw_vbo(struct pipe_context *pipe,
    }
 
    /* Map index buffer, if present */
-   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);
-   }
+   if (info->indexed && sp->index_buffer.buffer)
+      mapped_indices = softpipe_resource(sp->index_buffer.buffer)->data;
 
-   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_set_mapped_index_buffer(draw, mapped_indices);
 
    /* draw! */
-   draw_arrays_instanced(draw, info->mode, info->start, info->count,
-         info->start_instance, info->instance_count);
+   draw_vbo(draw, info);
 
    /* 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 (mapped_indices) {
-      draw_set_mapped_element_buffer(draw, 0, 0, NULL);
+      draw_set_mapped_index_buffer(draw, NULL);
    }
 
    /*
index 4a53ef048f38673f6973ed9b161a2d5827a98e5f..1071011db0ef1bff225eea5977a33f33cecef545 100644 (file)
@@ -31,6 +31,7 @@
 
 
 #include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
 #include "draw/draw_context.h"
 #include "sp_flush.h"
 #include "sp_context.h"
index 93af6ee5b02a780b72c3ba4dc1fa7e7a437c59da..73ae2dea561e588ea24461be234ac611f20defa9 100644 (file)
@@ -199,6 +199,7 @@ softpipe_is_format_supported( struct pipe_screen *screen,
    assert(target == PIPE_BUFFER ||
           target == PIPE_TEXTURE_1D ||
           target == PIPE_TEXTURE_2D ||
+          target == PIPE_TEXTURE_RECT ||
           target == PIPE_TEXTURE_3D ||
           target == PIPE_TEXTURE_CUBE);
 
index 880a7c7cd2642151f0c545863599289099cbbc2f..b650fcaea5cb55797542c93e355873252af34169 100644 (file)
@@ -100,5 +100,5 @@ softpipe_set_index_buffer(struct pipe_context *pipe,
    else
       memset(&softpipe->index_buffer, 0, sizeof(softpipe->index_buffer));
 
-   /* TODO make this more like a state */
+   draw_set_index_buffer(softpipe->draw, ib);
 }
index cf7ab81405c5fb5ead4e4d4b5651550de6b3c838..e654bb77c29f5d3a70003a1e80ea25b308c23c1e 100644 (file)
@@ -1785,6 +1785,7 @@ get_lambda_func(const union sp_sampler_key key)
    case PIPE_TEXTURE_1D:
       return compute_lambda_1d;
    case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_RECT:
    case PIPE_TEXTURE_CUBE:
       return compute_lambda_2d;
    case PIPE_TEXTURE_3D:
@@ -1809,6 +1810,7 @@ get_img_filter(const union sp_sampler_key key,
          return img_filter_1d_linear;
       break;
    case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_RECT:
       /* Try for fast path:
        */
       if (key.bits.is_pot &&
index 7b2dfe25496585f26d282d3e43391c8fe97daef2..e975f3b02fa3fcaff2e4fa23ac35236d750dca22 100644 (file)
@@ -67,7 +67,7 @@ void surface_to_surfaceid(struct svga_winsys_context *swc, // IN
       id->mipmap = s->real_level;
    }
    else {
-      id->sid = SVGA3D_INVALID_ID;
+      swc->surface_relocation(swc, &id->sid, NULL, flags);
       id->face = 0;
       id->mipmap = 0;
    }
index 3b30b9e341ea3de8116c3e604effe4e80874049c..cd3f6b89825e846e0900234844ec5ad9e029dd7c 100644 (file)
@@ -214,6 +214,11 @@ void svga_context_flush( struct svga_context *svga,
 
    svga_screen_cache_flush(svgascreen, fence);
 
+   /* To force the reemission of rendertargets and texture bindings at
+    * the beginning of every command buffer.
+    */
+   svga->dirty |= SVGA_NEW_COMMAND_BUFFER;
+
    if (SVGA_DEBUG & DEBUG_SYNC) {
       if (fence)
          svga->pipe.screen->fence_finish( svga->pipe.screen, fence, 0);
index 67a7614c8afaa5a09f3e5dcc944eec44cff0ddfc..1fb5a04887f70e6b52e26ee3963812f0f2c4217d 100644 (file)
@@ -382,6 +382,7 @@ struct svga_context
 #define SVGA_NEW_ZERO_STRIDE         0x2000000
 #define SVGA_NEW_TEXTURE_FLAGS       0x4000000
 #define SVGA_NEW_STENCIL_REF         0x8000000
+#define SVGA_NEW_COMMAND_BUFFER      0x10000000
 
 
 
index de08bc5e562879f92cd35095077f704b5ba29c31..001ec3616c4017d1e92fb74ffff6cbd94d323c10 100644 (file)
@@ -146,23 +146,15 @@ retry:
 }
 
 
-
-
-
 static void
-svga_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 prim, unsigned start, unsigned count)
+svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
 {
    struct svga_context *svga = svga_context( pipe );
-   unsigned reduced_prim = u_reduced_prim(prim);
+   unsigned reduced_prim = u_reduced_prim( info->mode );
+   unsigned count = info->count;
    enum pipe_error ret = 0;
 
-   if (!u_trim_pipe_prim( prim, &count ))
+   if (!u_trim_pipe_prim( info->mode, &count ))
       return;
 
    /*
@@ -187,34 +179,32 @@ svga_draw_range_elements( struct pipe_context *pipe,
       return;
 #endif
 
-   if (svga->state.sw.need_swtnl)
-   {
-      ret = svga_swtnl_draw_range_elements( svga, 
-                                            index_buffer, 
-                                            index_size,
-                                            index_bias,
-                                            min_index, max_index,
-                                            prim,
-                                            start, count );
+   if (svga->state.sw.need_swtnl) {
+      ret = svga_swtnl_draw_vbo( svga, info );
    }
    else {
-      if (index_buffer) {
+      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;
+
          ret = retry_draw_range_elements( svga,
-                                          index_buffer,
-                                          index_size,
-                                          index_bias,
-                                          min_index,
-                                          max_index,
-                                          prim,
-                                          start,
-                                          count,
+                                          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,
                                           TRUE );
       }
       else {
-         ret = retry_draw_arrays( svga, 
-                                  prim, 
-                                  start, 
-                                  count,
+         ret = retry_draw_arrays( svga,
+                                  info->mode,
+                                  info->start,
+                                  info->count,
                                   TRUE );
       }
    }
@@ -226,30 +216,6 @@ svga_draw_range_elements( struct pipe_context *pipe,
 }
 
 
-static void
-svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
-{
-   struct svga_context *svga = svga_context(pipe);
-
-   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_vbo = svga_draw_vbo;
index ff83c750aafa57085ecc7e2557301e4c9fd71335..26eb03a895a81ae4ad4ebb28c85c838f500c08a3 100644 (file)
@@ -583,7 +583,8 @@ svga_texture_from_handle(struct pipe_screen *screen,
    assert(screen);
 
    /* Only supports one type */
-   if (template->target != PIPE_TEXTURE_2D ||
+   if ((template->target != PIPE_TEXTURE_2D &&
+       template->target != PIPE_TEXTURE_RECT) ||
        template->last_level != 0 ||
        template->depth0 != 1) {
       return NULL;
index bd92f003432b06c2feed805b59d4d50030b0c9d5..fcbb35e797253243fad076b461d0e2e4c85a2b84 100644 (file)
@@ -43,15 +43,18 @@ static int emit_framebuffer( struct svga_context *svga,
 {
    const struct pipe_framebuffer_state *curr = &svga->curr.framebuffer;
    struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
+   boolean reemit = !!(dirty & SVGA_NEW_COMMAND_BUFFER);
    unsigned i;
    enum pipe_error ret;
 
-   /* XXX: Need shadow state in svga->hw to eliminate redundant
-    * uploads, especially of NULL buffers.
+   /*
+    * We need to reemit non-null surface bindings, even when they are not
+    * dirty, to ensure that the resources are paged in.
     */
    
    for(i = 0; i < PIPE_MAX_COLOR_BUFS; ++i) {
-      if (curr->cbufs[i] != hw->cbufs[i]) {
+      if (curr->cbufs[i] != hw->cbufs[i] ||
+          (reemit && hw->cbufs[i])) {
          if (svga->curr.nr_fbs++ > 8)
             return PIPE_ERROR_OUT_OF_MEMORY;
 
@@ -64,7 +67,8 @@ static int emit_framebuffer( struct svga_context *svga,
    }
 
    
-   if (curr->zsbuf != hw->zsbuf) {
+   if (curr->zsbuf != hw->zsbuf ||
+       (reemit && hw->zsbuf)) {
       ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_DEPTH, curr->zsbuf);
       if (ret != PIPE_OK)
          return ret;
@@ -92,7 +96,8 @@ static int emit_framebuffer( struct svga_context *svga,
 struct svga_tracked_state svga_hw_framebuffer = 
 {
    "hw framebuffer state",
-   SVGA_NEW_FRAME_BUFFER,
+   SVGA_NEW_FRAME_BUFFER |
+   SVGA_NEW_COMMAND_BUFFER,
    emit_framebuffer
 };
 
index 76a2dae14355707a1347f227abae156d67b59497..4a50b19474c10214e4ae3b7fc853d76c4988df94 100644 (file)
@@ -56,6 +56,7 @@ static int
 update_tss_binding(struct svga_context *svga, 
                    unsigned dirty )
 {
+   boolean reemit = !!(dirty & SVGA_NEW_COMMAND_BUFFER);
    unsigned i;
    unsigned count = MAX2( svga->curr.num_sampler_views,
                           svga->state.hw_draw.num_views );
@@ -107,12 +108,18 @@ update_tss_binding(struct svga_context *svga,
                                                 max_lod);
       }
 
-      if (view->dirty) {
+      /*
+       * We need to reemit non-null texture bindings, even when they are not
+       * dirty, to ensure that the resources are paged in.
+       */
+
+      if (view->dirty ||
+          (reemit && view->v)) {
          queue.bind[queue.bind_count].unit = i;
          queue.bind[queue.bind_count].view = view;
          queue.bind_count++;
       } 
-      else if (view->v) {
+      if (!view->dirty && view->v) {
          svga_validate_sampler_view(svga, view->v);
       }
    }
@@ -128,18 +135,21 @@ update_tss_binding(struct svga_context *svga,
          goto fail;
 
       for (i = 0; i < queue.bind_count; i++) {
+         struct svga_winsys_surface *handle;
+
          ts[i].stage = queue.bind[i].unit;
          ts[i].name = SVGA3D_TS_BIND_TEXTURE;
 
          if (queue.bind[i].view->v) {
-            svga->swc->surface_relocation(svga->swc,
-                                          &ts[i].value,
-                                          queue.bind[i].view->v->handle,
-                                          SVGA_RELOC_READ);
+            handle = queue.bind[i].view->v->handle;
          }
          else {
-            ts[i].value = SVGA3D_INVALID_ID;
+            handle = NULL;
          }
+         svga->swc->surface_relocation(svga->swc,
+                                       &ts[i].value,
+                                       handle,
+                                       SVGA_RELOC_READ);
          
          queue.bind[i].view->dirty = FALSE;
       }
@@ -157,7 +167,8 @@ fail:
 struct svga_tracked_state svga_hw_tss_binding = {
    "texture binding emit",
    SVGA_NEW_TEXTURE_BINDING |
-   SVGA_NEW_SAMPLER,
+   SVGA_NEW_SAMPLER |
+   SVGA_NEW_COMMAND_BUFFER,
    update_tss_binding
 };
 
index 65c675f99c94cd6269d86d1a39a49dea2375184c..fc094e514282deb200f9d2d474fd35a938e94f6d 100644 (file)
@@ -38,15 +38,8 @@ void svga_destroy_swtnl( struct svga_context *svga );
 
 
 enum pipe_error
-svga_swtnl_draw_range_elements(struct svga_context *svga,
-                               struct pipe_resource *indexBuffer,
-                               unsigned indexSize,
-                               int indexBias,
-                               unsigned min_index,
-                               unsigned max_index,
-                               unsigned prim, 
-                               unsigned start, 
-                               unsigned count);
+svga_swtnl_draw_vbo(struct svga_context *svga,
+                    const struct pipe_draw_info *info);
 
 
 #endif
index eb71c23195b7b327ba232ba2aea2b02da00e33ba..814e8edd70fb6fafec62c78fcdeeb6f5a872354b 100644 (file)
 
 
 enum pipe_error
-svga_swtnl_draw_range_elements(struct svga_context *svga,
-                               struct pipe_resource *indexBuffer,
-                               unsigned indexSize,
-                               int indexBias,
-                               unsigned min_index,
-                               unsigned max_index,
-                               unsigned prim, unsigned start, unsigned count)
+svga_swtnl_draw_vbo(struct svga_context *svga,
+                    const struct pipe_draw_info *info)
 {
    struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
    struct pipe_transfer *ib_transfer = NULL;
@@ -76,19 +71,18 @@ svga_swtnl_draw_range_elements(struct svga_context *svga,
       draw_set_mapped_vertex_buffer(draw, i, map);
    }
 
+   /* TODO move this to update_swtnl_draw */
+   draw_set_index_buffer(draw, &svga->curr.ib);
+
    /* Map index buffer, if present */
-   if (indexBuffer) {
-      map = pipe_buffer_map(&svga->pipe, indexBuffer,
+   map = NULL;
+   if (info->indexed && svga->curr.ib.buffer) {
+      map = pipe_buffer_map(&svga->pipe, svga->curr.ib.buffer,
                             PIPE_TRANSFER_READ,
-                           &ib_transfer);
-
-      draw_set_mapped_element_buffer_range(draw, 
-                                           indexSize, indexBias,
-                                           min_index,
-                                           max_index,
-                                           map);
+                            &ib_transfer);
    }
-   
+   draw_set_mapped_index_buffer(draw, map);
+
    if (svga->curr.cb[PIPE_SHADER_VERTEX]) {
       map = pipe_buffer_map(&svga->pipe,
                             svga->curr.cb[PIPE_SHADER_VERTEX],
@@ -101,7 +95,7 @@ svga_swtnl_draw_range_elements(struct svga_context *svga,
          svga->curr.cb[PIPE_SHADER_VERTEX]->width0);
    }
 
-   draw_arrays(svga->swtnl.draw, prim, start, count);
+   draw_vbo(draw, info);
 
    draw_flush(svga->swtnl.draw);
 
@@ -117,9 +111,9 @@ svga_swtnl_draw_range_elements(struct svga_context *svga,
       draw_set_mapped_vertex_buffer(draw, i, NULL);
    }
 
-   if (indexBuffer) {
-      pipe_buffer_unmap(&svga->pipe, indexBuffer, ib_transfer);
-      draw_set_mapped_element_buffer(draw, 0, 0, NULL);
+   if (ib_transfer) {
+      pipe_buffer_unmap(&svga->pipe, svga->curr.ib.buffer, ib_transfer);
+      draw_set_mapped_index_buffer(draw, NULL);
    }
 
    if (svga->curr.cb[PIPE_SHADER_VERTEX]) {
@@ -157,7 +151,8 @@ boolean svga_init_swtnl( struct svga_context *svga )
    draw_install_aapoint_stage(svga->swtnl.draw, &svga->pipe);
    draw_install_pstipple_stage(svga->swtnl.draw, &svga->pipe);
 
-   draw_set_driver_clipping(svga->swtnl.draw, debug_get_bool_option("SVGA_SWTNL_FSE", FALSE));
+   if (debug_get_bool_option("SVGA_SWTNL_FSE", FALSE))
+      draw_set_driver_clipping(svga->swtnl.draw, TRUE, TRUE);
 
    return TRUE;
 
index 48eced2ecea33d3fe266b45ca4d4fd8179991996..b4e90a957d0fb16af03ebb1f921698e7bc097da7 100644 (file)
@@ -353,6 +353,7 @@ static INLINE ubyte svga_tgsi_sampler_type( struct svga_shader_emitter *emit,
    case PIPE_TEXTURE_1D:
       return SVGA3DSAMP_2D;
    case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_RECT:
       return SVGA3DSAMP_2D;
    case PIPE_TEXTURE_3D:
       return SVGA3DSAMP_VOLUME;
index 67e1f22a70138c618ef3b751ac88c5634fe0c4de..72dccdf150291e6fa113db209a52f4867cebf829 100644 (file)
@@ -806,6 +806,20 @@ static boolean emit_cmp(struct svga_shader_emitter *emit,
    const struct src_register src2 = translate_src_register(
       emit, &insn->Src[2] );
 
+   if (emit->unit == PIPE_SHADER_VERTEX) {
+      SVGA3dShaderDestToken temp = get_temp(emit);
+      struct src_register zero = scalar(get_zero_immediate(emit), TGSI_SWIZZLE_X);
+
+      /* Since vertex shaders don't support the CMP instruction,
+       * simulate it with SLT and LRP instructions.
+       *    SLT  TMP, SRC0, 0.0
+       *    LRP  DST, TMP, SRC1, SRC2
+       */
+      if (!submit_op2(emit, inst_token(SVGA3DOP_SLT), temp, src0, zero))
+         return FALSE;
+      return submit_op3(emit, inst_token(SVGA3DOP_LRP), dst, src(temp), src1, src2);
+   }
+
    /* CMP  DST, SRC0, SRC2, SRC1 */
    return submit_op3( emit, inst_token( SVGA3DOP_CMP ), dst, src0, src2, src1);
 }
@@ -2682,6 +2696,11 @@ needs_to_create_zero( struct svga_shader_emitter *emit )
          return TRUE;
    }
 
+   if (emit->unit == PIPE_SHADER_VERTEX) {
+      if (emit->info.opcode_count[TGSI_OPCODE_CMP] >= 1)
+         return TRUE;
+   }
+
    if (emit->info.opcode_count[TGSI_OPCODE_IF] >= 1 ||
        emit->info.opcode_count[TGSI_OPCODE_BGNLOOP] >= 1 ||
        emit->info.opcode_count[TGSI_OPCODE_DDX] >= 1 ||
index 84e5a6a8242f3ebccb5081db486f7fca0d1ff0d4..271cd4aff5ec2c4c1a26cbba7f0ad7159d9cd6d0 100644 (file)
@@ -885,7 +885,7 @@ trace_sampler_view_destroy(struct pipe_context *_pipe,
    trace_dump_arg(ptr, pipe);
    trace_dump_arg(ptr, view);
 
-   pipe->sampler_view_destroy(pipe, view);
+   pipe_sampler_view_reference(&tr_view->sampler_view, NULL);
 
    trace_dump_call_end();
 
@@ -1002,7 +1002,7 @@ trace_context_set_index_buffer(struct pipe_context *_pipe,
    trace_dump_call_begin("pipe_context", "set_index_buffer");
 
    trace_dump_arg(ptr, pipe);
-   trace_dump_arg(index_buffer, ib);
+   trace_dump_arg(index_buffer, _ib);
 
    pipe->set_index_buffer(pipe, ib);
 
@@ -1063,7 +1063,10 @@ trace_context_clear(struct pipe_context *_pipe,
 
    trace_dump_arg(ptr, pipe);
    trace_dump_arg(uint, buffers);
-   trace_dump_arg_array(float, rgba, 4);
+   if (rgba)
+      trace_dump_arg_array(float, rgba, 4);
+   else
+      trace_dump_null();
    trace_dump_arg(float, depth);
    trace_dump_arg(uint, stencil);
 
index 1fa3ec8300ab7d688397b0ee748d52652c0d55fe..0a5be43f6bf0e6472d76aa50f49de6b6914359bd 100644 (file)
@@ -79,6 +79,14 @@ typedef unsigned char boolean;
 #define FALSE false
 #endif
 
+#ifndef va_copy
+#ifdef __va_copy
+#define va_copy(dest, src) __va_copy((dest), (src))
+#else
+#define va_copy(dest, src) (dest) = (src)
+#endif
+#endif
+
 /* Function inlining */
 #ifndef INLINE
 #  ifdef __cplusplus
index 0579962ec69212eabbffb38df998401e91a7759f..0e53aef6d2e277f318f1e81907920f557b5d737b 100644 (file)
 #ifndef PIPE_CONTEXT_H
 #define PIPE_CONTEXT_H
 
-#include "p_state.h"
-
+#include "p_compiler.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-   
-struct pipe_screen;
+
+struct pipe_blend_color;
+struct pipe_blend_state;
+struct pipe_box;
+struct pipe_clip_state;
+struct pipe_depth_stencil_alpha_state;
+struct pipe_draw_info;
 struct pipe_fence_handle;
-struct pipe_state_cache;
+struct pipe_framebuffer_state;
+struct pipe_index_buffer;
 struct pipe_query;
-struct pipe_winsys;
+struct pipe_poly_stipple;
+struct pipe_rasterizer_state;
+struct pipe_resource;
+struct pipe_sampler_state;
+struct pipe_sampler_view;
+struct pipe_scissor_state;
+struct pipe_shader_state;
+struct pipe_stencil_ref;
+struct pipe_stream_output_state;
+struct pipe_subresource;
+struct pipe_surface;
+struct pipe_vertex_buffer;
+struct pipe_vertex_element;
+struct pipe_viewport_state;
 
 /**
  * Gallium rendering context.  Basically:
index 00aa2076ed5f13c501595f23bdc5ac132057ca3e..627b5ae53807ebcf470d2ad997e91a08fcdaebd5 100644 (file)
@@ -28,7 +28,7 @@
 #ifndef PIPE_DEFINES_H
 #define PIPE_DEFINES_H
 
-#include "p_format.h"
+#include "p_compiler.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -135,13 +135,15 @@ enum pipe_error {
 #define PIPE_STENCIL_OP_DECR_WRAP  6
 #define PIPE_STENCIL_OP_INVERT     7
 
-/** Texture types */
+/** Texture types.
+ * See the documentation for info on PIPE_TEXTURE_RECT vs PIPE_TEXTURE_2D */
 enum pipe_texture_target {
    PIPE_BUFFER       = 0,
    PIPE_TEXTURE_1D   = 1,
    PIPE_TEXTURE_2D   = 2,
    PIPE_TEXTURE_3D   = 3,
    PIPE_TEXTURE_CUBE = 4,
+   PIPE_TEXTURE_RECT = 5,
    PIPE_MAX_TEXTURE_TYPES
 };
 
index 436c3f627a824417b1cfac0515626b160a7c1cdd..06412f4894c8ffcadde6b7b7eb9f71ea5388549b 100644 (file)
@@ -29,8 +29,6 @@
 #ifndef PIPE_FORMAT_H
 #define PIPE_FORMAT_H
 
-#include "p_compiler.h"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
index 9df20ea8581e25799ef7432db2b34a50b03844c8..c4bd17e92bbace41c3ed8e9a9bcf86a7123b3c93 100644 (file)
@@ -33,8 +33,6 @@
 extern "C" {
 #endif
 
-#include "p_compiler.h"
-
 
 struct tgsi_header
 {
index 0f1a44cde42efb12f38f4889acd991d89c9ffb98..9a2b31da50dcef9566e49c5343626a4a3eab7a8e 100644 (file)
@@ -43,7 +43,6 @@
 #include "p_compiler.h"
 #include "p_defines.h"
 #include "p_format.h"
-#include "p_screen.h"
 
 
 #ifdef __cplusplus
index 59b0e337c9216efdc3fb14ab67a46bf04eaf097b..6a99b234aa57c6179cfa5d4b4cd773decbfb5599 100644 (file)
@@ -1,3 +1,30 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
 #ifndef GALLIUM_RAW_H
 #define GALLIUM_RAW_H
 
@@ -14,6 +41,7 @@
  * those for parsing text representations of TGSI shaders.
  */
 
+#include "pipe/p_compiler.h"
 #include "pipe/p_format.h"
 
 struct pipe_screen;
index 692c49d7cd536f4f6c069ca42bb5c641a0f114bb..35b870a8a323c7639d246c3d7942bd4664b93367 100644 (file)
@@ -34,7 +34,6 @@
 
 #include "pipe/p_compiler.h"
 #include "dri_wrapper.h"
-#include "main/mtypes.h"
 
 struct pipe_context;
 struct pipe_fence;
index 6ad2c7da4d6bf219e2c8a1d5fcbf9bbace4bdd22..0ab4dd189312659f7e3f74661a51062126dbe4db 100644 (file)
@@ -383,6 +383,11 @@ dri_init_screen_helper(struct dri_screen *screen,
    if (!screen->st_api)
       return NULL;
 
+   if(pscreen->get_param(pscreen, PIPE_CAP_NPOT_TEXTURES))
+      screen->target = PIPE_TEXTURE_2D;
+   else
+      screen->target = PIPE_TEXTURE_RECT;
+
    driParseOptionInfo(&screen->optionCache,
                       __driConfigOptions, __driNConfigOptions);
 
index 53ccce145ba2eab125318adfb6071724c59ee91d..849f399b2f8198674794ad3a5af9e95b25b919c3 100644 (file)
@@ -68,6 +68,7 @@ struct dri_screen
    boolean d_depth_bits_last;
    boolean sd_depth_bits_last;
    boolean auto_fake_front;
+   enum pipe_texture_target target;
 };
 
 /** cast wrapper */
index 47005c17e2bd600ee370a43db5cf9458701a7abb..93f910a26d6470da1d8e4b2e0a348fe591ba916e 100644 (file)
@@ -195,7 +195,7 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable,
       pipe_resource_reference(&drawable->textures[i], NULL);
 
    memset(&templ, 0, sizeof(templ));
-   templ.target = PIPE_TEXTURE_2D;
+   templ.target = screen->target;
    templ.last_level = 0;
    templ.width0 = dri_drawable->w;
    templ.height0 = dri_drawable->h;
@@ -342,7 +342,7 @@ dri2_create_image_from_name(__DRIcontext *context,
    memset(&templ, 0, sizeof(templ));
    templ.bind = tex_usage;
    templ.format = pf;
-   templ.target = PIPE_TEXTURE_2D;
+   templ.target = screen->target;
    templ.last_level = 0;
    templ.width0 = width;
    templ.height0 = height;
index 249ccd7fcf67f1d6b4b635f2702960a390e5a1f8..04bba631aeb7b77562a751cfc5da20a6fb29fd36 100644 (file)
@@ -216,7 +216,7 @@ drisw_allocate_textures(struct dri_drawable *drawable,
    }
 
    memset(&templ, 0, sizeof(templ));
-   templ.target = PIPE_TEXTURE_2D;
+   templ.target = screen->target;
    templ.width0 = width;
    templ.height0 = height;
    templ.depth0 = 1;
index 9e9e479e7e0a1484a60986c2cdff8f4b702b10c1..4199d7c6baab82737233152486fbe9568e112eb9 100644 (file)
@@ -24,7 +24,7 @@ x11_SOURCES = $(wildcard x11/*.c) \
 x11_OBJECTS = $(x11_SOURCES:.c=.o)
 
 
-kms_INCLUDES = $(shell pkg-config --cflags-only-I libdrm)
+kms_INCLUDES = -I$(TOP)/src/gallium/winsys $(shell pkg-config --cflags-only-I libdrm)
 kms_SOURCES = $(wildcard kms/*.c)
 kms_OBJECTS = $(kms_SOURCES:.c=.o)
 
index e71aec35b7351911433b8831fbbe17f8a21f971c..efcce25e3171b85367815f757aa04be24e50c249 100644 (file)
@@ -21,6 +21,7 @@ if 'egl' in env['statetrackers']:
         'common/egl_g3d_api.c',
         'common/egl_g3d_image.c',
         'common/egl_g3d_st.c',
+        'common/egl_g3d_sync.c',
         'common/native_helper.c',
     ]
 
index 56d575ffe08c4f7884612b8d9bea88061e5eb8f5..4e653bdf3b26590c7dccdd6edc7fc221974d4e60 100644 (file)
@@ -530,6 +530,18 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
    if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER))
       dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
 
+   dpy->Extensions.KHR_reusable_sync = EGL_TRUE;
+   dpy->Extensions.KHR_fence_sync = EGL_TRUE;
+
+   dpy->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
+   dpy->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
+   dpy->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
+
+   if (dpy->Platform == _EGL_PLATFORM_DRM) {
+      dpy->Extensions.MESA_drm_display = EGL_TRUE;
+      dpy->Extensions.MESA_drm_image = EGL_TRUE;
+   }
+
    if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
       _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
       goto fail;
index f33dc91cf9076c756fce5ac949e0be2a28309f5e..be450bbede35a700b585d955b9bc890e3d0837d2 100644 (file)
 #include "pipe/p_screen.h"
 #include "pipe/p_context.h"
 #include "pipe/p_format.h"
+#include "os/os_thread.h"
 #include "egldriver.h"
 #include "egldisplay.h"
 #include "eglcontext.h"
 #include "eglsurface.h"
 #include "eglconfig.h"
 #include "eglimage.h"
+#include "eglsync.h"
 #include "eglscreen.h"
 #include "eglmode.h"
 
@@ -99,6 +101,24 @@ struct egl_g3d_image {
 _EGL_DRIVER_STANDARD_TYPECASTS(egl_g3d)
 _EGL_DRIVER_TYPECAST(egl_g3d_image, _EGLImage, obj)
 
+#ifdef EGL_KHR_reusable_sync
+
+struct egl_g3d_sync {
+   _EGLSync base;
+
+   int refs;
+
+   /* the mutex protects only the condvar, not the struct */
+   pipe_mutex mutex;
+   pipe_condvar condvar;
+
+   /* for fence sync */
+   struct pipe_fence_handle *fence;
+};
+_EGL_DRIVER_TYPECAST(egl_g3d_sync, _EGLSync, obj)
+
+#endif /* EGL_KHR_reusable_sync */
+
 #ifdef EGL_MESA_screen_surface
 
 struct egl_g3d_screen {
index edac72a82232da8c7d5a9ef9c4865569486fbda0..3ec53653f449502194f99866eb6c2d6ae539114e 100644 (file)
@@ -34,6 +34,7 @@
 #include "egl_g3d.h"
 #include "egl_g3d_api.h"
 #include "egl_g3d_image.h"
+#include "egl_g3d_sync.h"
 #include "egl_g3d_st.h"
 #include "egl_g3d_loader.h"
 #include "native.h"
@@ -103,7 +104,7 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
    }
 
    gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi,
-         &gconf->stvis, (gshare) ? gshare->stctxi : NULL);
+         (gconf) ? &gconf->stvis : NULL, (gshare) ? gshare->stctxi : NULL);
    if (!gctx->stctxi) {
       FREE(gctx);
       return NULL;
@@ -437,16 +438,19 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
       ok = gctx->stapi->make_current(gctx->stapi, gctx->stctxi,
             (gdraw) ? gdraw->stfbi : NULL, (gread) ? gread->stfbi : NULL);
       if (ok) {
-         gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gdraw->stfbi);
-         if (gread != gdraw) {
+         if (gdraw) {
             gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi,
-                  gread->stfbi);
-         }
+                  gdraw->stfbi);
 
-         if (gdraw->base.Type == EGL_WINDOW_BIT) {
-            gctx->base.WindowRenderBuffer =
-               (gdraw->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) ?
-               EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
+            if (gdraw->base.Type == EGL_WINDOW_BIT) {
+               gctx->base.WindowRenderBuffer =
+                  (gdraw->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) ?
+                  EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
+            }
+         }
+         if (gread && gread != gdraw) {
+            gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi,
+                  gread->stfbi);
          }
       }
    }
@@ -805,6 +809,17 @@ egl_g3d_init_driver_api(_EGLDriver *drv)
 
    drv->API.CreateImageKHR = egl_g3d_create_image;
    drv->API.DestroyImageKHR = egl_g3d_destroy_image;
+#ifdef EGL_MESA_drm_image
+   drv->API.CreateDRMImageMESA = egl_g3d_create_drm_image;
+   drv->API.ExportDRMImageMESA = egl_g3d_export_drm_image;
+#endif
+
+#ifdef EGL_KHR_reusable_sync
+   drv->API.CreateSyncKHR = egl_g3d_create_sync;
+   drv->API.DestroySyncKHR = egl_g3d_destroy_sync;
+   drv->API.ClientWaitSyncKHR = egl_g3d_client_wait_sync;
+   drv->API.SignalSyncKHR = egl_g3d_signal_sync;
+#endif
 
 #ifdef EGL_MESA_screen_surface
    drv->API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface;
index 1e13cfcf7e9fbdda5bc9ffa3e6614e6986e05c9a..558638e72f014ed2e93bc992a5d7ee132d17b364 100644 (file)
 #include "util/u_rect.h"
 #include "util/u_inlines.h"
 #include "eglcurrent.h"
+#include "egllog.h"
 
 #include "native.h"
 #include "egl_g3d.h"
 #include "egl_g3d_api.h"
 #include "egl_g3d_image.h"
 
+/* move this to native display? */
+#include "state_tracker/drm_driver.h"
+
 /**
  * Reference and return the front left buffer of the native pixmap.
  */
@@ -67,6 +71,165 @@ egl_g3d_reference_native_pixmap(_EGLDisplay *dpy, EGLNativePixmapType pix)
    return textures[natt];
 }
 
+#ifdef EGL_MESA_drm_image
+
+static struct pipe_resource *
+egl_g3d_create_drm_buffer(_EGLDisplay *dpy, const EGLint *attribs)
+{
+   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+   struct pipe_screen *screen = gdpy->native->screen;
+   struct pipe_resource templ;
+   EGLint width = 0, height = 0, format = 0, use = 0;
+   EGLint valid_use;
+   EGLint i, err = EGL_SUCCESS;
+
+   for (i = 0; attribs[i] != EGL_NONE; i++) {
+      EGLint attr = attribs[i++];
+      EGLint val = attribs[i];
+
+      switch (attr) {
+      case EGL_WIDTH:
+        width = val;
+         break;
+      case EGL_HEIGHT:
+        height = val;
+         break;
+      case EGL_DRM_BUFFER_FORMAT_MESA:
+        format = val;
+         break;
+      case EGL_DRM_BUFFER_USE_MESA:
+        use = val;
+         break;
+      default:
+         err = EGL_BAD_ATTRIBUTE;
+         break;
+      }
+
+      if (err != EGL_SUCCESS) {
+         _eglLog(_EGL_DEBUG, "bad image attribute 0x%04x", attr);
+         return NULL;
+      }
+   }
+
+   if (width <= 0 || height <= 0) {
+      _eglLog(_EGL_DEBUG, "bad width or height (%dx%d)", width, height);
+      return NULL;
+   }
+
+   switch (format) {
+   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
+      format = PIPE_FORMAT_B8G8R8A8_UNORM;
+      break;
+   default:
+      _eglLog(_EGL_DEBUG, "bad image format value 0x%04x", format);
+      return NULL;
+      break;
+   }
+
+   valid_use = EGL_DRM_BUFFER_USE_SCANOUT_MESA |
+               EGL_DRM_BUFFER_USE_SHARE_MESA;
+   if (use & ~valid_use) {
+      _eglLog(_EGL_DEBUG, "bad image use bit 0x%04x", use);
+      return NULL;
+   }
+
+   memset(&templ, 0, sizeof(templ));
+   templ.target = PIPE_TEXTURE_2D;
+   templ.format = format;
+   templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+   templ.width0 = width;
+   templ.height0 = height;
+   templ.depth0 = 1;
+
+   /*
+    * XXX fix apps (e.g. wayland) and pipe drivers (e.g. i915) and remove the
+    * size check
+    */
+   if ((use & EGL_DRM_BUFFER_USE_SCANOUT_MESA) &&
+       width >= 640 && height >= 480)
+      templ.bind |= PIPE_BIND_SCANOUT;
+   if (use & EGL_DRM_BUFFER_USE_SHARE_MESA)
+      templ.bind |= PIPE_BIND_SHARED;
+
+   return screen->resource_create(screen, &templ);
+}
+
+static struct pipe_resource *
+egl_g3d_reference_drm_buffer(_EGLDisplay *dpy, EGLint name,
+                             const EGLint *attribs)
+{
+   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+   struct pipe_screen *screen = gdpy->native->screen;
+   struct pipe_resource templ;
+   struct winsys_handle wsh;
+   EGLint width = 0, height = 0, format = 0, stride = 0;
+   EGLint i, err = EGL_SUCCESS;
+
+   /* winsys_handle is in theory platform-specific */
+   if (dpy->Platform != _EGL_PLATFORM_DRM)
+      return NULL;
+
+   for (i = 0; attribs[i] != EGL_NONE; i++) {
+      EGLint attr = attribs[i++];
+      EGLint val = attribs[i];
+
+      switch (attr) {
+      case EGL_WIDTH:
+        width = val;
+         break;
+      case EGL_HEIGHT:
+        height = val;
+         break;
+      case EGL_DRM_BUFFER_FORMAT_MESA:
+        format = val;
+         break;
+      case EGL_DRM_BUFFER_STRIDE_MESA:
+        stride = val;
+         break;
+      default:
+         err = EGL_BAD_ATTRIBUTE;
+         break;
+      }
+
+      if (err != EGL_SUCCESS) {
+         _eglLog(_EGL_DEBUG, "bad image attribute 0x%04x", attr);
+         return NULL;
+      }
+   }
+
+   if (width <= 0 || height <= 0 || stride <= 0) {
+      _eglLog(_EGL_DEBUG, "bad width, height, or stride (%dx%dx%d)",
+            width, height, stride);
+      return NULL;
+   }
+
+   switch (format) {
+   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
+      format = PIPE_FORMAT_B8G8R8A8_UNORM;
+      break;
+   default:
+      _eglLog(_EGL_DEBUG, "bad image format value 0x%04x", format);
+      return NULL;
+      break;
+   }
+
+   memset(&templ, 0, sizeof(templ));
+   templ.target = PIPE_TEXTURE_2D;
+   templ.format = format;
+   templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+   templ.width0 = width;
+   templ.height0 = height;
+   templ.depth0 = 1;
+
+   memset(&wsh, 0, sizeof(wsh));
+   wsh.handle = (unsigned) name;
+   wsh.stride = stride;
+
+   return screen->resource_from_handle(screen, &templ, &wsh);
+}
+
+#endif /* EGL_MESA_drm_image */
+
 _EGLImage *
 egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
                      EGLenum target, EGLClientBuffer buffer,
@@ -92,6 +255,11 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
       ptex = egl_g3d_reference_native_pixmap(dpy,
             (EGLNativePixmapType) buffer);
       break;
+#ifdef EGL_MESA_drm_image
+   case EGL_DRM_BUFFER_MESA:
+      ptex = egl_g3d_reference_drm_buffer(dpy, (EGLint) buffer, attribs);
+      break;
+#endif
    default:
       ptex = NULL;
       break;
@@ -134,3 +302,80 @@ egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img)
 
    return EGL_TRUE;
 }
+
+_EGLImage *
+egl_g3d_create_drm_image(_EGLDriver *drv, _EGLDisplay *dpy,
+                         const EGLint *attribs)
+{
+   struct egl_g3d_image *gimg;
+   struct pipe_resource *ptex;
+
+   gimg = CALLOC_STRUCT(egl_g3d_image);
+   if (!gimg) {
+      _eglError(EGL_BAD_ALLOC, "eglCreateDRMImageKHR");
+      return NULL;
+   }
+
+   if (!_eglInitImage(&gimg->base, dpy, attribs)) {
+      FREE(gimg);
+      return NULL;
+   }
+
+#ifdef EGL_MESA_drm_image
+   ptex = egl_g3d_create_drm_buffer(dpy, attribs);
+#else
+   ptex = NULL;
+#endif
+   if (!ptex) {
+      FREE(gimg);
+      return NULL;
+   }
+
+   /* transfer the ownership to the image */
+   gimg->texture = ptex;
+   gimg->face = 0;
+   gimg->level = 0;
+   gimg->zslice = 0;
+
+   return &gimg->base;
+}
+
+EGLBoolean
+egl_g3d_export_drm_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img,
+                        EGLint *name, EGLint *handle, EGLint *stride)
+{
+   struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+   struct egl_g3d_image *gimg = egl_g3d_image(img);
+   struct pipe_screen *screen = gdpy->native->screen;
+   struct winsys_handle wsh;
+
+   /* winsys_handle is in theory platform-specific */
+   if (dpy->Platform != _EGL_PLATFORM_DRM)
+      return EGL_FALSE;
+
+   /* get shared handle */
+   if (name) {
+      memset(&handle, 0, sizeof(handle));
+      wsh.type = DRM_API_HANDLE_TYPE_SHARED;
+      if (!screen->resource_get_handle(screen, gimg->texture, &wsh)) {
+         return EGL_FALSE;
+      }
+
+      *name = wsh.handle;
+   }
+
+   /* get KMS handle */
+   if (handle || stride) {
+      memset(&wsh, 0, sizeof(wsh));
+      wsh.type = DRM_API_HANDLE_TYPE_KMS;
+      if (!screen->resource_get_handle(screen, gimg->texture, &wsh))
+         return EGL_FALSE;
+
+      if (handle)
+         *handle = wsh.handle;
+      if (stride)
+         *stride = wsh.stride;
+   }
+
+   return EGL_TRUE;
+}
index adda9333715d69d3259f2f00aa2aae17a482b4c2..f051da82837da5cad789f405ce6788743bb38942 100644 (file)
@@ -39,4 +39,12 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
 EGLBoolean
 egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
 
+_EGLImage *
+egl_g3d_create_drm_image(_EGLDriver *drv, _EGLDisplay *dpy,
+                         const EGLint *attribs);
+
+EGLBoolean
+egl_g3d_export_drm_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img,
+                        EGLint *name, EGLint *handle, EGLint *stride);
+
 #endif /* _EGL_G3D_IMAGE_H_ */
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_sync.c b/src/gallium/state_trackers/egl/common/egl_g3d_sync.c
new file mode 100644 (file)
index 0000000..ec74e9e
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * 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:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#include "util/u_memory.h"
+#include "util/u_atomic.h"
+#include "os/os_thread.h"
+#include "eglsync.h"
+#include "eglcurrent.h"
+
+#include "egl_g3d.h"
+#include "egl_g3d_sync.h"
+
+#ifdef EGL_KHR_reusable_sync
+
+/**
+ * Wait for the conditional variable.
+ */
+static EGLint
+egl_g3d_wait_sync_condvar(struct egl_g3d_sync *gsync, EGLTimeKHR timeout)
+{
+   _EGLDisplay *dpy = gsync->base.Resource.Display;
+
+   pipe_mutex_lock(gsync->mutex);
+
+   /* unlock display lock just before waiting */
+   _eglUnlockMutex(&dpy->Mutex);
+
+   /* No timed wait.  Always treat timeout as EGL_FOREVER_KHR */
+   pipe_condvar_wait(gsync->condvar, gsync->mutex);
+
+   _eglLockMutex(&dpy->Mutex);
+
+   pipe_mutex_unlock(gsync->mutex);
+
+   return EGL_CONDITION_SATISFIED_KHR;
+}
+
+/**
+ * Signal the conditional variable.
+ */
+static void
+egl_g3d_signal_sync_condvar(struct egl_g3d_sync *gsync)
+{
+   pipe_mutex_lock(gsync->mutex);
+   pipe_condvar_broadcast(gsync->condvar);
+   pipe_mutex_unlock(gsync->mutex);
+}
+
+/**
+ * Insert a fence command to the command stream of the current context.
+ */
+static EGLint
+egl_g3d_insert_fence_sync(struct egl_g3d_sync *gsync)
+{
+   _EGLContext *ctx = _eglGetCurrentContext();
+   struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+
+   /* already checked in egl_g3d_create_sync */
+   assert(gctx);
+
+   /* insert the fence command */
+   gctx->stctxi->flush(gctx->stctxi, 0x0, &gsync->fence);
+   if (!gsync->fence)
+      gsync->base.SyncStatus = EGL_SIGNALED_KHR;
+
+   return EGL_SUCCESS;
+}
+
+/**
+ * Wait for the fence sync to be signaled.
+ */
+static EGLint
+egl_g3d_wait_fence_sync(struct egl_g3d_sync *gsync, EGLTimeKHR timeout)
+{
+   EGLint ret;
+
+   if (gsync->fence) {
+      _EGLDisplay *dpy = gsync->base.Resource.Display;
+      struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+      struct pipe_screen *screen = gdpy->native->screen;
+      struct pipe_fence_handle *fence = gsync->fence;
+
+      gsync->fence = NULL;
+
+      _eglUnlockMutex(&dpy->Mutex);
+      /* no timed finish? */
+      screen->fence_finish(screen, fence, 0x0);
+      ret = EGL_CONDITION_SATISFIED_KHR;
+      _eglLockMutex(&dpy->Mutex);
+
+      gsync->base.SyncStatus = EGL_SIGNALED_KHR;
+
+      screen->fence_reference(screen, &fence, NULL);
+      egl_g3d_signal_sync_condvar(gsync);
+   }
+   else {
+      ret = egl_g3d_wait_sync_condvar(gsync, timeout);
+   }
+
+   return ret;
+}
+
+static INLINE void
+egl_g3d_ref_sync(struct egl_g3d_sync *gsync)
+{
+   p_atomic_inc(&gsync->refs);
+}
+
+static INLINE void
+egl_g3d_unref_sync(struct egl_g3d_sync *gsync)
+{
+   if (p_atomic_dec_zero(&gsync->refs)) {
+      pipe_condvar_destroy(gsync->condvar);
+      pipe_mutex_destroy(gsync->mutex);
+
+      if (gsync->fence) {
+         struct egl_g3d_display *gdpy =
+            egl_g3d_display(gsync->base.Resource.Display);
+         struct pipe_screen *screen = gdpy->native->screen;
+
+         screen->fence_reference(screen, &gsync->fence, NULL);
+      }
+
+      FREE(gsync);
+   }
+}
+
+_EGLSync *
+egl_g3d_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
+                    EGLenum type, const EGLint *attrib_list)
+{
+   _EGLContext *ctx = _eglGetCurrentContext();
+   struct egl_g3d_sync *gsync;
+   EGLint err;
+
+   if (!ctx || ctx->Resource.Display != dpy) {
+      _eglError(EGL_BAD_MATCH, "eglCreateSyncKHR");
+      return NULL;
+   }
+
+   gsync = CALLOC_STRUCT(egl_g3d_sync);
+   if (!gsync) {
+      _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
+      return NULL;
+   }
+
+   if (!_eglInitSync(&gsync->base, dpy, type, attrib_list)) {
+      FREE(gsync);
+      return NULL;
+   }
+
+   switch (type) {
+   case EGL_SYNC_REUSABLE_KHR:
+      err = EGL_SUCCESS;
+      break;
+   case EGL_SYNC_FENCE_KHR:
+      err = egl_g3d_insert_fence_sync(gsync);
+      break;
+   default:
+      err = EGL_BAD_ATTRIBUTE;
+      break;
+   }
+
+   if (err != EGL_SUCCESS) {
+      _eglError(err, "eglCreateSyncKHR");
+      FREE(gsync);
+      return NULL;
+   }
+
+   pipe_mutex_init(gsync->mutex);
+   pipe_condvar_init(gsync->condvar);
+   p_atomic_set(&gsync->refs, 1);
+
+   return &gsync->base;
+}
+
+EGLBoolean
+egl_g3d_destroy_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync)
+{
+   struct egl_g3d_sync *gsync = egl_g3d_sync(sync);
+
+   switch (gsync->base.Type) {
+   case EGL_SYNC_REUSABLE_KHR:
+      /* signal the waiters */
+      if (gsync->base.SyncStatus != EGL_SIGNALED_KHR) {
+         gsync->base.SyncStatus = EGL_SIGNALED_KHR;
+         egl_g3d_signal_sync_condvar(gsync);
+      }
+      break;
+   default:
+      break;
+   }
+
+   egl_g3d_unref_sync(gsync);
+
+   return EGL_TRUE;
+}
+
+EGLint
+egl_g3d_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                         EGLint flags, EGLTimeKHR timeout)
+{
+   struct egl_g3d_sync *gsync = egl_g3d_sync(sync);
+   EGLint ret = EGL_CONDITION_SATISFIED_KHR;
+
+   if (gsync->base.SyncStatus != EGL_SIGNALED_KHR) {
+      /* flush if there is a current context */
+      if (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) {
+         _EGLContext *ctx = _eglGetCurrentContext();
+         struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+
+         if (gctx)
+            gctx->stctxi->flush(gctx->stctxi, PIPE_FLUSH_RENDER_CACHE , NULL);
+      }
+
+      if (timeout) {
+         /* reference the sync object in case it is destroyed while waiting */
+         egl_g3d_ref_sync(gsync);
+
+         switch (gsync->base.Type) {
+         case EGL_SYNC_REUSABLE_KHR:
+            ret = egl_g3d_wait_sync_condvar(gsync, timeout);
+            break;
+         case EGL_SYNC_FENCE_KHR:
+            ret = egl_g3d_wait_fence_sync(gsync, timeout);
+         default:
+            break;
+         }
+
+         egl_g3d_unref_sync(gsync);
+      }
+      else {
+         ret = EGL_TIMEOUT_EXPIRED_KHR;
+      }
+   }
+
+   return ret;
+}
+
+EGLBoolean
+egl_g3d_signal_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                    EGLenum mode)
+{
+   struct egl_g3d_sync *gsync = egl_g3d_sync(sync);
+
+   /* only for reusable sync */
+   if (sync->Type != EGL_SYNC_REUSABLE_KHR)
+      return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR");
+
+   if (gsync->base.SyncStatus != mode) {
+      gsync->base.SyncStatus = mode;
+      if (mode == EGL_SIGNALED_KHR)
+         egl_g3d_signal_sync_condvar(gsync);
+   }
+
+   return EGL_TRUE;
+}
+
+#endif /* EGL_KHR_reusable_sync */
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_sync.h b/src/gallium/state_trackers/egl/common/egl_g3d_sync.h
new file mode 100644 (file)
index 0000000..3179ca0
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * 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:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#ifndef _EGL_G3D_SYNC_H_
+#define _EGL_G3D_SYNC_H_
+
+#include "egl_g3d.h"
+
+#ifdef EGL_KHR_reusable_sync
+
+_EGLSync *
+egl_g3d_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
+                    EGLenum type, const EGLint *attrib_list);
+
+EGLBoolean
+egl_g3d_destroy_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync);
+
+EGLint
+egl_g3d_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                         EGLint flags, EGLTimeKHR timeout);
+
+EGLBoolean
+egl_g3d_signal_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
+                    EGLenum mode);
+
+#endif /* EGL_KHR_reusable_sync */
+
+#endif /* _EGL_G3D_SYNC_H_ */
index d4e8fbc9131fffa86553ff9dfb2c9a4291de5b06..208f73306cb575a1ec620c45724e225c54c21572 100644 (file)
 
 #include "native_kms.h"
 
+/* see get_drm_screen_name */
+#include <radeon_drm.h>
+#include "radeon/drm/radeon_drm.h"
+
 static boolean
 kms_surface_validate(struct native_surface *nsurf, uint attachment_mask,
                      unsigned int *seq_num, struct pipe_resource **textures,
@@ -584,7 +588,9 @@ kms_display_get_configs(struct native_display *ndpy, int *num_configs)
 
       nconf->color_format = format;
 
-      nconf->scanout_bit = TRUE;
+      /* support KMS */
+      if (kdpy->resources)
+         nconf->scanout_bit = TRUE;
    }
 
    configs = MALLOC(sizeof(*configs));
@@ -664,6 +670,27 @@ kms_display_destroy(struct native_display *ndpy)
    FREE(kdpy);
 }
 
+static const char *
+get_drm_screen_name(int fd, drmVersionPtr version)
+{
+   const char *name = version->name;
+
+   if (name && !strcmp(name, "radeon")) {
+      int chip_id;
+      struct drm_radeon_info info;
+
+      memset(&info, 0, sizeof(info));
+      info.request = RADEON_INFO_DEVICE_ID;
+      info.value = pointer_to_intptr(&chip_id);
+      if (drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)) != 0)
+         return NULL;
+
+      name = is_r3xx(chip_id) ? "r300" : "r600";
+   }
+
+   return name;
+}
+
 /**
  * Initialize KMS and pipe screen.
  */
@@ -672,6 +699,7 @@ kms_display_init_screen(struct native_display *ndpy)
 {
    struct kms_display *kdpy = kms_display(ndpy);
    drmVersionPtr version;
+   const char *name;
 
    version = drmGetVersion(kdpy->fd);
    if (!version) {
@@ -679,8 +707,11 @@ kms_display_init_screen(struct native_display *ndpy)
       return FALSE;
    }
 
-   kdpy->base.screen = kdpy->event_handler->new_drm_screen(&kdpy->base,
-         version->name, kdpy->fd);;
+   name = get_drm_screen_name(kdpy->fd, version);
+   if (name) {
+      kdpy->base.screen =
+         kdpy->event_handler->new_drm_screen(&kdpy->base, name, kdpy->fd);
+   }
    drmFreeVersion(version);
 
    if (!kdpy->base.screen) {
@@ -717,32 +748,32 @@ kms_create_display(int fd, struct native_event_handler *event_handler,
       return NULL;
    }
 
+   kdpy->base.destroy = kms_display_destroy;
+   kdpy->base.get_param = kms_display_get_param;
+   kdpy->base.get_configs = kms_display_get_configs;
+
    /* resources are fixed, unlike crtc, connector, or encoder */
    kdpy->resources = drmModeGetResources(kdpy->fd);
-   if (!kdpy->resources) {
-      kms_display_destroy(&kdpy->base);
-      return NULL;
-   }
+   if (kdpy->resources) {
+      kdpy->saved_crtcs =
+         CALLOC(kdpy->resources->count_crtcs, sizeof(*kdpy->saved_crtcs));
+      if (!kdpy->saved_crtcs) {
+         kms_display_destroy(&kdpy->base);
+         return NULL;
+      }
 
-   kdpy->saved_crtcs =
-      CALLOC(kdpy->resources->count_crtcs, sizeof(*kdpy->saved_crtcs));
-   if (!kdpy->saved_crtcs) {
-      kms_display_destroy(&kdpy->base);
-      return NULL;
-   }
+      kdpy->shown_surfaces =
+         CALLOC(kdpy->resources->count_crtcs, sizeof(*kdpy->shown_surfaces));
+      if (!kdpy->shown_surfaces) {
+         kms_display_destroy(&kdpy->base);
+         return NULL;
+      }
 
-   kdpy->shown_surfaces =
-      CALLOC(kdpy->resources->count_crtcs, sizeof(*kdpy->shown_surfaces));
-   if (!kdpy->shown_surfaces) {
-      kms_display_destroy(&kdpy->base);
-      return NULL;
+      kdpy->base.modeset = &kms_display_modeset;
+   }
+   else {
+      _eglLog(_EGL_DEBUG, "Failed to get KMS resources.  Disable modeset.");
    }
-
-   kdpy->base.destroy = kms_display_destroy;
-   kdpy->base.get_param = kms_display_get_param;
-   kdpy->base.get_configs = kms_display_get_configs;
-
-   kdpy->base.modeset = &kms_display_modeset;
 
    return &kdpy->base;
 }
index eb8d6a1933397b3295f5e6bf2afc1ab85c7a40cb..dcd50e19d73e7ee325e48fcc665c48e7aed25327 100644 (file)
 #include "GL/glx.h"
 
 #include "xm_api.h"
-#include "main/context.h"
-#include "main/macros.h"
-#include "main/imports.h"
-#include "main/version.h"
 
 
 /* This indicates the client-side GLX API and GLX encoder version. */
@@ -603,8 +599,8 @@ destroy_visuals_on_display(Display *dpy)
 static int
 close_display_callback(Display *dpy, XExtCodes *codes)
 {
-   destroy_visuals_on_display(dpy);
    xmesa_destroy_buffers_on_display(dpy);
+   destroy_visuals_on_display(dpy);
    return 0;
 }
 
@@ -1299,7 +1295,7 @@ glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
    XMesaContext xm_dst = dst->xmesaContext;
    (void) dpy;
    if (MakeCurrent_PrevContext == src) {
-      _mesa_Flush();
+      glFlush();
    }
    XMesaCopyContext(xm_src, xm_dst, mask);
 }
index 8903b0e6cbd44e121702a7877d93bf661cc4bfde..0aa37e150b8c6f24341be53ec6d49b6a6e24fe74 100644 (file)
@@ -30,8 +30,7 @@
  */
 
 
-#include "main/context.h"
-#include "main/imports.h"
+#include "main/core.h"
 #include <GL/glx.h>
 
 
index c0c418306fb84cd0cee24e62eb4e10cb2a3a9a7c..eb4ce742669e75e122f727dfe0e1a67c0ff163af 100644 (file)
@@ -56,7 +56,6 @@
 #include "xm_api.h"
 #include "xm_st.h"
 
-#include "main/context.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_screen.h"
 #include "pipe/p_context.h"
 static struct xm_driver driver;
 static struct st_api *stapi;
 
+/* Default strict invalidate to false.  This means we will not call
+ * XGetGeometry after every swapbuffers, which allows swapbuffers to
+ * remain asynchronous.  For apps running at 100fps with synchronous
+ * swapping, a 10% boost is typical.  For gears, I see closer to 20%
+ * speedup.
+ *
+ * Note that the work of copying data on swapbuffers doesn't disappear
+ * - this change just allows the X server to execute the PutImage
+ * asynchronously without us effectively blocked until its completion.
+ *
+ * This speeds up even llvmpipe's threaded rasterization as the
+ * swapbuffers operation was a large part of the serial component of
+ * an llvmpipe frame.
+ *
+ * The downside of this is correctness - applications which don't call
+ * glViewport on window resizes will get incorrect rendering.  A
+ * better solution would be to have per-frame but asynchronous
+ * invalidation.  Xcb almost looks as if it could provide this, but
+ * the API doesn't seem to quite be there.
+ */
+boolean xmesa_strict_invalidate = FALSE;
+
 void xmesa_set_driver( const struct xm_driver *templ )
 {
    driver = *templ;
    stapi = driver.create_st_api();
+
+   xmesa_strict_invalidate =
+      debug_get_bool_option("XMESA_STRICT_INVALIDATE", FALSE);
 }
 
 
@@ -91,7 +115,12 @@ static int
 xmesa_get_param(struct st_manager *smapi,
                 enum st_manager_param param)
 {
-   return 0;
+   switch(param) {
+   case ST_MANAGER_BROKEN_INVALIDATE:
+      return !xmesa_strict_invalidate;
+   default:
+      return 0;
+   }
 }
 
 static XMesaDisplay
@@ -263,7 +292,6 @@ xmesa_get_window_size(Display *dpy, XMesaBuffer b,
    Status stat;
 
    pipe_mutex_lock(xmdpy->mutex);
-   XSync(b->xm_visual->display, 0); /* added for Chromium */
    stat = get_drawable_size(dpy, b->ws.drawable, width, height);
    pipe_mutex_unlock(xmdpy->mutex);
 
@@ -726,15 +754,39 @@ XMesaVisual XMesaCreateVisual( Display *display,
       alpha_bits = v->mesa_visual.alphaBits;
    }
 
-   _mesa_initialize_visual( &v->mesa_visual,
-                            db_flag, stereo_flag,
-                            red_bits, green_bits,
-                            blue_bits, alpha_bits,
-                            depth_size,
-                            stencil_size,
-                            accum_red_size, accum_green_size,
-                            accum_blue_size, accum_alpha_size,
-                            0 );
+   /* initialize visual */
+   {
+      __GLcontextModes *vis = &v->mesa_visual;
+
+      vis->rgbMode          = GL_TRUE;
+      vis->doubleBufferMode = db_flag;
+      vis->stereoMode       = stereo_flag;
+
+      vis->redBits          = red_bits;
+      vis->greenBits        = green_bits;
+      vis->blueBits         = blue_bits;
+      vis->alphaBits        = alpha_bits;
+      vis->rgbBits          = red_bits + green_bits + blue_bits;
+
+      vis->indexBits      = 0;
+      vis->depthBits      = depth_size;
+      vis->stencilBits    = stencil_size;
+
+      vis->accumRedBits   = accum_red_size;
+      vis->accumGreenBits = accum_green_size;
+      vis->accumBlueBits  = accum_blue_size;
+      vis->accumAlphaBits = accum_alpha_size;
+
+      vis->haveAccumBuffer   = accum_red_size > 0;
+      vis->haveDepthBuffer   = depth_size > 0;
+      vis->haveStencilBuffer = stencil_size > 0;
+
+      vis->numAuxBuffers = 0;
+      vis->level = 0;
+      vis->pixmapMode = 0;
+      vis->sampleBuffers = 0;
+      vis->samples = 0;
+   }
 
    v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
    if (db_flag)
@@ -1154,7 +1206,7 @@ void XMesaFlush( XMesaContext c )
          xmdpy->screen->fence_finish(xmdpy->screen, fence, 0);
          xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL);
       }
-      XSync( c->xm_visual->display, False );
+      XFlush( c->xm_visual->display );
    }
 }
 
index 4f2c8a6e6a9a8ddf25d9a1db3e159d99f421e56e..f209b14ea1342b47c3523d63bc0d372d0b44a0f4 100644 (file)
@@ -57,7 +57,7 @@ and create a window, you must do the following to use the X/Mesa interface:
 #define XMESA_H
 
 
-#include "main/mtypes.h"
+#include "main/core.h" /* for GLvisual and MESA_VERSION_STRING */
 #include "state_tracker/st_api.h"
 #include "os/os_thread.h"
 
@@ -378,6 +378,6 @@ xmesa_buffer_height(XMesaBuffer b)
    return b->height;
 }
 
-
+extern boolean xmesa_strict_invalidate;
 
 #endif
index c62eb8bfbd1d3bbb651f406c49758ce0aa759fcf..0f74b3f7aa3268626c1b07fa5b18e1e3bb9f5248 100644 (file)
  *    Chia-I Wu <olv@lunarg.com>
  */
 
-#include "util/u_memory.h"
-#include "util/u_inlines.h"
-
 #include "xm_api.h"
 #include "xm_st.h"
 
+#include "util/u_inlines.h"
+
 struct xmesa_st_framebuffer {
    XMesaDisplay display;
    XMesaBuffer buffer;
    struct pipe_screen *screen;
 
    struct st_visual stvis;
+   enum pipe_texture_target target;
 
    unsigned texture_width, texture_height, texture_mask;
    struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
@@ -139,7 +139,7 @@ xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
    }
 
    memset(&templ, 0, sizeof(templ));
-   templ.target = PIPE_TEXTURE_2D;
+   templ.target = xstfb->target;
    templ.width0 = width;
    templ.height0 = height;
    templ.depth0 = 1;
@@ -210,6 +210,12 @@ xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
    /* record newly allocated textures */
    new_mask = statt_mask & ~xstfb->texture_mask;
 
+   /* If xmesa_strict_invalidate is not set, we will not yet have
+    * called XGetGeometry().  Do so here:
+    */
+   if (!xmesa_strict_invalidate)
+      xmesa_check_buffer_size(xstfb->buffer);
+
    resized = (xstfb->buffer->width != xstfb->texture_width ||
               xstfb->buffer->height != xstfb->texture_height);
 
@@ -251,7 +257,8 @@ xmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
    boolean ret;
 
    ret = xmesa_st_framebuffer_display(stfbi, statt);
-   if (ret)
+
+   if (ret && xmesa_strict_invalidate)
       xmesa_check_buffer_size(xstfb->buffer);
 
    return ret;
@@ -279,6 +286,10 @@ xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b)
    xstfb->buffer = b;
    xstfb->screen = xmdpy->screen;
    xstfb->stvis = b->xm_visual->stvis;
+   if(xstfb->screen->get_param(xstfb->screen, PIPE_CAP_NPOT_TEXTURES))
+      xstfb->target = PIPE_TEXTURE_2D;
+   else
+      xstfb->target = PIPE_TEXTURE_RECT;
 
    stfbi->visual = &xstfb->stvis;
    stfbi->flush_front = xmesa_st_framebuffer_flush_front;
@@ -322,7 +333,8 @@ xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi)
          *back = tmp;
       }
 
-      xmesa_check_buffer_size(xstfb->buffer);
+      if (xmesa_strict_invalidate)
+        xmesa_check_buffer_size(xstfb->buffer);
    }
 }
 
index 0fb7cd83069254950343fc505f1f2c83bba33932..a0e14b96016c7c9af67986dc66faa8d45fb5da4e 100644 (file)
@@ -33,7 +33,7 @@
 
 /* for _mesa_share_state */
 #include "state_tracker/st_context.h"
-#include "main/context.h"
+#include "main/core.h"
 
 #include "stw_icd.h"
 #include "stw_device.h"
index a107c71bdab0c2be1646502bbe6c480e845f8385..37809d084ce4c4ee4c826416c26b1aecdde58b0c 100644 (file)
@@ -27,7 +27,7 @@
 
 #include <windows.h>
 
-#include "glapi/glthread.h"
+#include "glapi/glapi.h"
 #include "util/u_debug.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
index e606477e975fb6d02c698273a1a4ec89ea3f4dd0..18ac48236965ad00de6f5cb7f3aea9dda44d2070 100644 (file)
  * 
  **************************************************************************/
 
-#include "main/mtypes.h"
-#include "main/context.h"
-
 #include "pipe/p_format.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_screen.h"
 
 #include "util/u_format.h"
 #include "util/u_debug.h"
+#include "util/u_memory.h"
 
 #include "stw_icd.h"
 #include "stw_device.h"
index d405172773c592a92b6f50a1802f92c555916476..282c9f643c28899b890accc7a685da8c548a80dc 100644 (file)
@@ -34,8 +34,6 @@
 #define PFD_SUPPORT_COMPOSITION 0x00008000
 #endif
 
-#include "main/mtypes.h"
-
 #include "pipe/p_compiler.h"
 #include "pipe/p_format.h"
 #include "state_tracker/st_api.h"
index de05f96d231779a38fa298482dda415469bc4cae..59961e982aa5c4995ef8c870028b838963a5342b 100644 (file)
@@ -1,11 +1,12 @@
 # -*-makefile-*-
 
+
 ifeq ($(MESA_LLVM),1)
 PIPE_DRIVERS += $(TOP)/src/gallium/drivers/llvmpipe/libllvmpipe.a
 LDFLAGS += $(LLVM_LDFLAGS)
-LD = g++
 DRIVER_EXTRAS = $(LLVM_LIBS)
-USE_CXX=1
+else
+LDFLAGS += -lstdc++
 endif
 
 MESA_MODULES = \
@@ -75,15 +76,11 @@ default: depend symlinks $(TOP)/$(LIB_DIR)/gallium $(LIBNAME) $(LIBNAME_STAGING)
 
 $(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(PIPE_DRIVERS) Makefile \
                $(TOP)/src/mesa/drivers/dri/Makefile.template $(TOP)/src/mesa/drivers/dri/common/dri_test.o
-       $(MKLIB) -o $@.tmp -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \
+       $(MKLIB) -o $@.tmp -noprefix -linker '$(CXX)' -ldflags '$(LDFLAGS)' \
                $(OBJECTS) $(PIPE_DRIVERS) \
                 -Wl,--start-group $(MESA_MODULES) -Wl,--end-group \
                  $(DRI_LIB_DEPS) $(DRIVER_EXTRAS)
-       if [ "x${USE_CXX}" == "x" ]; then \
-               $(CC) $(CFLAGS) -o $@.test $(TOP)/src/mesa/drivers/dri/common/dri_test.o $@.tmp $(DRI_LIB_DEPS); \
-       else \
-               $(CXX) $(CFLAGS) -o $@.test $(TOP)/src/mesa/drivers/dri/common/dri_test.o $@.tmp $(DRI_LIB_DEPS); \
-       fi
+       $(CXX) $(CFLAGS) -o $@.test $(TOP)/src/mesa/drivers/dri/common/dri_test.o $@.tmp $(DRI_LIB_DEPS);
        @rm -f $@.test
        mv -f $@.tmp $@
 
index f8276b155587a1621a71d0d6011c93c49affc245..e447d093610d2727341dc95659a408fb603a2e4d 100644 (file)
@@ -1,18 +1,13 @@
 import os
 Import('*')
-       
+
 # Compatibility with old build scripts:
 #
 if 'mesa' in env['statetrackers']:
-       if 'xlib' in env['winsys']:
-               SConscript([
-                       'libgl-xlib/SConscript',
-               ])
-
-       if 'gdi' in env['winsys']:
-               SConscript([
-                       'libgl-gdi/SConscript',
-               ])
+    if 'xlib' in env['winsys'] and 'libgl-xlib' not in env['targets']:
+        env['targets'].append('libgl-xlib')
+    if 'gdi' in env['winsys'] and 'libgl-gdi' not in env['targets']:
+        env['targets'].append('libgl-gdi')
 
 if not 'graw-xlib' in env['targets'] and not 'graw-null' in env['targets'] and not env['msvc']:
         # XXX: disable until MSVC can link correctly
diff --git a/src/gallium/targets/dri-r300/Makefile b/src/gallium/targets/dri-r300/Makefile
new file mode 100644 (file)
index 0000000..9afbb13
--- /dev/null
@@ -0,0 +1,27 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = r300_dri.so
+
+PIPE_DRIVERS = \
+       $(TOP)/src/gallium/state_trackers/dri/drm/libdridrm.a \
+       $(TOP)/src/gallium/winsys/radeon/drm/libradeonwinsys.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/r300/libr300.a
+
+C_SOURCES = \
+       target.c \
+       $(COMMON_GALLIUM_SOURCES) \
+       $(DRIVER_SOURCES)
+
+DRIVER_DEFINES = \
+       -DGALLIUM_RBUG -DGALLIUM_TRACE -DGALLIUM_GALAHAD
+
+include ../Makefile.dri
+
+DRI_LIB_DEPS += -ldrm_radeon
+
+symlinks:
diff --git a/src/gallium/targets/dri-r300/SConscript b/src/gallium/targets/dri-r300/SConscript
new file mode 100644 (file)
index 0000000..33a458f
--- /dev/null
@@ -0,0 +1,30 @@
+Import('*')
+
+if not 'r300' in env['drivers']:
+    print 'warning: r300 pipe driver not built skipping r300_dri.so'
+    Return()
+
+env = drienv.Clone()
+
+env.ParseConfig('pkg-config --cflags --libs libdrm_radeon')
+
+env.Append(CPPDEFINES = ['GALLIUM_RBUG', 'GALLIUM_TRACE', 'GALLIUM_GALAHAD'])
+
+env.Prepend(LIBS = [
+    st_dri,
+    radeonwinsys,
+    r300,
+    galahad,
+    trace,
+    rbug,
+    mesa,
+    glsl,
+    gallium,
+    COMMON_DRI_DRM_OBJECTS
+])
+
+env.SharedLibrary(
+    target ='r300_dri.so',
+    source = 'target.c',
+    SHLIBPREFIX = '',
+)
diff --git a/src/gallium/targets/dri-r300/target.c b/src/gallium/targets/dri-r300/target.c
new file mode 100644 (file)
index 0000000..2ecf345
--- /dev/null
@@ -0,0 +1,26 @@
+
+#include "target-helpers/inline_debug_helper.h"
+#include "state_tracker/drm_driver.h"
+#include "radeon/drm/radeon_drm_public.h"
+#include "r300/r300_public.h"
+
+static struct pipe_screen *
+create_screen(int fd)
+{
+   struct r300_winsys_screen *sws;
+   struct pipe_screen *screen;
+
+   sws = r300_drm_winsys_screen_create(fd);
+   if (!sws)
+      return NULL;
+
+   screen = r300_screen_create(sws);
+   if (!screen)
+      return NULL;
+
+   screen = debug_screen_wrap(screen);
+
+   return screen;
+}
+
+DRM_DRIVER_DESCRIPTOR("r300", "radeon", create_screen)
index 932303d194efd123f03202f52a617e1218526aa9..661283de6a837784bb49f7cf33ebf650cf1387b6 100644 (file)
@@ -4,12 +4,12 @@ include $(TOP)/configs/current
 LIBNAME = r600_dri.so
 
 PIPE_DRIVERS = \
+       $(TOP)/src/gallium/drivers/r600/libr600.a \
        $(TOP)/src/gallium/state_trackers/dri/drm/libdridrm.a \
        $(TOP)/src/gallium/winsys/r600/drm/libr600winsys.a \
        $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
        $(TOP)/src/gallium/drivers/trace/libtrace.a \
-       $(TOP)/src/gallium/drivers/rbug/librbug.a \
-       $(TOP)/src/gallium/drivers/r600/libr600.a
+       $(TOP)/src/gallium/drivers/rbug/librbug.a
 
 C_SOURCES = \
        target.c \
@@ -21,6 +21,6 @@ DRIVER_DEFINES = \
 
 include ../Makefile.dri
 
-DRI_LIB_DEPS += -ldrm_radeon
+DRI_LIB_DEPS +=
 
 symlinks:
diff --git a/src/gallium/targets/dri-radeong/Makefile b/src/gallium/targets/dri-radeong/Makefile
deleted file mode 100644 (file)
index 3f9ec36..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-TOP = ../../../..
-include $(TOP)/configs/current
-
-LIBNAME = radeong_dri.so
-
-PIPE_DRIVERS = \
-       $(TOP)/src/gallium/state_trackers/dri/drm/libdridrm.a \
-       $(TOP)/src/gallium/winsys/radeon/drm/libradeonwinsys.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/r300/libr300.a
-
-C_SOURCES = \
-       target.c \
-       $(COMMON_GALLIUM_SOURCES) \
-       $(DRIVER_SOURCES)
-
-DRIVER_DEFINES = \
-       -DGALLIUM_RBUG -DGALLIUM_TRACE -DGALLIUM_GALAHAD
-
-include ../Makefile.dri
-
-DRI_LIB_DEPS += -ldrm_radeon
-
-symlinks:
diff --git a/src/gallium/targets/dri-radeong/SConscript b/src/gallium/targets/dri-radeong/SConscript
deleted file mode 100644 (file)
index 1402c3b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-Import('*')
-
-if not 'r300' in env['drivers']:
-    print 'warning: r300 pipe driver not built skipping radeong_dri.so'
-    Return()
-
-env = drienv.Clone()
-
-env.ParseConfig('pkg-config --cflags --libs libdrm_radeon')
-
-env.Append(CPPDEFINES = ['GALLIUM_RBUG', 'GALLIUM_TRACE', 'GALLIUM_GALAHAD'])
-
-env.Prepend(LIBS = [
-    st_dri,
-    radeonwinsys,
-    r300,
-    galahad,
-    trace,
-    rbug,
-    mesa,
-    glsl,
-    gallium,
-    COMMON_DRI_DRM_OBJECTS
-])
-
-env.SharedLibrary(
-    target ='radeon_dri.so',
-    source = 'target.c',
-    SHLIBPREFIX = '',
-)
diff --git a/src/gallium/targets/dri-radeong/target.c b/src/gallium/targets/dri-radeong/target.c
deleted file mode 100644 (file)
index 5a0a8dc..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-
-#include "target-helpers/inline_debug_helper.h"
-#include "state_tracker/drm_driver.h"
-#include "radeon/drm/radeon_drm_public.h"
-#include "r300/r300_public.h"
-
-static struct pipe_screen *
-create_screen(int fd)
-{
-   struct r300_winsys_screen *sws;
-   struct pipe_screen *screen;
-
-   sws = r300_drm_winsys_screen_create(fd);
-   if (!sws)
-      return NULL;
-
-   screen = r300_screen_create(sws);
-   if (!screen)
-      return NULL;
-
-   screen = debug_screen_wrap(screen);
-
-   return screen;
-}
-
-DRM_DRIVER_DESCRIPTOR("radeon", "radeon", create_screen)
index ec2f865c3177ac9634a40267a5b90f01db9cfca9..4655d791170eeb14a938dc57f5757c6f236b854b 100644 (file)
@@ -33,6 +33,8 @@
 #include "target-helpers/inline_debug_helper.h"
 #include "egldriver.h"
 
+static struct st_api *stapis[ST_API_COUNT];
+
 static uint
 get_api_mask(void)
 {
@@ -57,7 +59,11 @@ get_api_mask(void)
 static struct st_api *
 get_st_api(enum st_api_type api)
 {
-   struct st_api *stapi = NULL;
+   struct st_api *stapi;
+
+   stapi = stapis[api];
+   if (stapi)
+      return stapi;
 
    switch (api) {
 #if FEATURE_GL
@@ -84,13 +90,33 @@ get_st_api(enum st_api_type api)
          break;
    }
 
+   stapis[api] = stapi;
+
    return stapi;
 }
 
 static struct st_api *
 guess_gl_api(void)
 {
-   return NULL;
+   struct st_api *stapi = NULL;
+
+#if FEATURE_GL
+   stapi = get_st_api(ST_API_OPENGL);
+   if (stapi)
+      return stapi;
+#endif
+#if FEATURE_ES1
+   stapi = get_st_api(ST_API_OPENGL_ES1);
+   if (stapi)
+      return stapi;
+#endif
+#if FEATURE_ES2
+   stapi = get_st_api(ST_API_OPENGL_ES2);
+   if (stapi)
+      return stapi;
+#endif
+
+   return stapi;
 }
 
 static struct pipe_screen *
@@ -127,7 +153,16 @@ init_loader(struct egl_g3d_loader *loader)
 static void
 egl_g3d_unload(_EGLDriver *drv)
 {
+   int i;
+
    egl_g3d_destroy_driver(drv);
+
+   for (i = 0; i < ST_API_COUNT; i++) {
+      if (stapis[i]) {
+         stapis[i]->destroy(stapis[i]);
+         stapis[i] = NULL;
+      }
+   }
 }
 
 static struct egl_g3d_loader loader;
index 1e4bb4d94c2d6ae86227b498547ce2f72efc7b50..2784fd0d100d3da8d61b8bd24f71146752980fec 100644 (file)
@@ -90,13 +90,20 @@ nouveau_LIBS := \
        $(TOP)/src/gallium/drivers/nv50/libnv50.a \
        $(TOP)/src/gallium/drivers/nouveau/libnouveau.a
 
-# radeon pipe driver
-radeon_CPPFLAGS :=
-radeon_SYS := -ldrm -ldrm_radeon
-radeon_LIBS := \
+# r300 pipe driver
+r300_CPPFLAGS :=
+r300_SYS := -ldrm -ldrm_radeon
+r300_LIBS := \
        $(TOP)/src/gallium/winsys/radeon/drm/libradeonwinsys.a \
        $(TOP)/src/gallium/drivers/r300/libr300.a
 
+# r600 pipe driver
+r600_CPPFLAGS :=
+r600_SYS := -ldrm -ldrm_radeon
+r600_LIBS := \
+       $(TOP)/src/gallium/winsys/r600/drm/libr600winsys.a \
+       $(TOP)/src/gallium/drivers/r600/libr600.a
+
 # vmwgfx pipe driver
 vmwgfx_CPPFLAGS :=
 vmwgfx_SYS :=
@@ -119,17 +126,17 @@ endif
 
 # OpenGL state tracker
 GL_CPPFLAGS := -I$(TOP)/src/mesa $(API_DEFINES)
-GL_SYS := -lpthread -lm -L$(TOP)/$(LIB_DIR) -l$(GL_LIB)
+GL_SYS := $(DRI_LIB_DEPS) -L$(TOP)/$(LIB_DIR) -l$(GL_LIB)
 GL_LIBS := $(TOP)/src/mesa/libmesagallium.a
 
 # OpenGL ES 1.x state tracker
 GLESv1_CM_CPPFLAGS := -I$(TOP)/src/mesa
-GLESv1_CM_SYS := -lpthread -lm -L$(TOP)/$(LIB_DIR) -l$(GLESv1_CM_LIB)
+GLESv1_CM_SYS := $(DRI_LIB_DEPS) -L$(TOP)/$(LIB_DIR) -l$(GLESv1_CM_LIB)
 GLESv1_CM_LIBS := $(TOP)/src/mesa/libes1gallium.a
 
 # OpenGL ES 2.x state tracker
 GLESv2_CPPFLAGS := -I$(TOP)/src/mesa
-GLESv2_SYS := -lpthread -lm -L$(TOP)/$(LIB_DIR) -l$(GLESv2_LIB)
+GLESv2_SYS := $(DRI_LIB_DEPS) -L$(TOP)/$(LIB_DIR) -l$(GLESv2_LIB)
 GLESv2_LIBS := $(TOP)/src/mesa/libes2gallium.a
 
 # OpenVG state tracker
@@ -151,7 +158,10 @@ ifneq ($(findstring nouveau/drm,$(GALLIUM_WINSYS_DIRS)),)
 OUTPUTS += nouveau
 endif
 ifneq ($(findstring radeon/drm,$(GALLIUM_WINSYS_DIRS)),)
-OUTPUTS += radeon
+OUTPUTS += r300
+endif
+ifneq ($(findstring r600/drm,$(GALLIUM_WINSYS_DIRS)),)
+OUTPUTS += r600
 endif
 ifneq ($(findstring svga/drm,$(GALLIUM_WINSYS_DIRS)),)
 OUTPUTS += vmwgfx
@@ -188,8 +198,11 @@ $(OUTPUT_PATH)/$(PIPE_PREFIX)i965.so: pipe_i965.o $(i965_LIBS)
 $(OUTPUT_PATH)/$(PIPE_PREFIX)nouveau.so: pipe_nouveau.o $(nouveau_LIBS)
        $(call mklib,nouveau)
 
-$(OUTPUT_PATH)/$(PIPE_PREFIX)radeon.so: pipe_radeon.o $(radeon_LIBS)
-       $(call mklib,radeon)
+$(OUTPUT_PATH)/$(PIPE_PREFIX)r300.so: pipe_r300.o $(r300_LIBS)
+       $(call mklib,r300)
+
+$(OUTPUT_PATH)/$(PIPE_PREFIX)r600.so: pipe_r600.o $(r600_LIBS)
+       $(call mklib,r600)
 
 $(OUTPUT_PATH)/$(PIPE_PREFIX)vmwgfx.so: pipe_vmwgfx.o $(vmwgfx_LIBS)
        $(call mklib,vmwgfx)
index d9d89485c3cde1c40a7c9752215c3e0354410e5f..a573b212179195712916e0b45685177a73c2cad1 100644 (file)
@@ -155,24 +155,23 @@ load_pipe_module(struct pipe_module *pmod, const char *name)
    if (!pmod->name)
       return FALSE;
 
+   _eglLog(_EGL_DEBUG, "searching for pipe module %s", pmod->name);
    _eglSearchPathForEach(dlopen_pipe_module_cb, (void *) pmod);
    if (pmod->lib) {
       pmod->drmdd = (const struct drm_driver_descriptor *)
          util_dl_get_proc_address(pmod->lib, "driver_descriptor");
-      if (pmod->drmdd) {
-         if (pmod->drmdd->driver_name) {
-            /* driver name mismatch */
-            if (strcmp(pmod->drmdd->driver_name, pmod->name) != 0)
-               pmod->drmdd = NULL;
-         }
-         else {
-            /* swrast */
-            pmod->swrast_create_screen =
-               (struct pipe_screen *(*)(struct sw_winsys *))
-               util_dl_get_proc_address(pmod->lib, "swrast_create_screen");
-            if (!pmod->swrast_create_screen)
-               pmod->drmdd = NULL;
-         }
+
+      /* sanity check on the name */
+      if (pmod->drmdd && strcmp(pmod->drmdd->name, pmod->name) != 0)
+         pmod->drmdd = NULL;
+
+      /* swrast */
+      if (pmod->drmdd && !pmod->drmdd->driver_name) {
+         pmod->swrast_create_screen =
+            (struct pipe_screen *(*)(struct sw_winsys *))
+            util_dl_get_proc_address(pmod->lib, "swrast_create_screen");
+         if (!pmod->swrast_create_screen)
+            pmod->drmdd = NULL;
       }
 
       if (!pmod->drmdd) {
diff --git a/src/gallium/targets/egl/pipe_r300.c b/src/gallium/targets/egl/pipe_r300.c
new file mode 100644 (file)
index 0000000..d84bb92
--- /dev/null
@@ -0,0 +1,27 @@
+
+#include "target-helpers/inline_debug_helper.h"
+#include "state_tracker/drm_driver.h"
+#include "radeon/drm/radeon_drm_public.h"
+#include "r300/r300_public.h"
+
+static struct pipe_screen *
+create_screen(int fd)
+{
+   struct r300_winsys_screen *sws;
+   struct pipe_screen *screen;
+
+   sws = r300_drm_winsys_screen_create(fd);
+   if (!sws)
+      return NULL;
+
+   screen = r300_screen_create(sws);
+   if (!screen)
+      return NULL;
+
+   screen = debug_screen_wrap(screen);
+
+   return screen;
+}
+
+PUBLIC
+DRM_DRIVER_DESCRIPTOR("r300", "radeon", create_screen)
diff --git a/src/gallium/targets/egl/pipe_r600.c b/src/gallium/targets/egl/pipe_r600.c
new file mode 100644 (file)
index 0000000..486a659
--- /dev/null
@@ -0,0 +1,27 @@
+
+#include "state_tracker/drm_driver.h"
+#include "target-helpers/inline_debug_helper.h"
+#include "r600/drm/r600_drm_public.h"
+#include "r600/r600_public.h"
+
+static struct pipe_screen *
+create_screen(int fd)
+{
+   struct radeon *rw;
+   struct pipe_screen *screen;
+
+   rw = r600_drm_winsys_create(fd);
+   if (!rw)
+      return NULL;
+
+   screen = r600_screen_create(rw);
+   if (!screen)
+      return NULL;
+
+   screen = debug_screen_wrap(screen);
+
+   return screen;
+}
+
+PUBLIC
+DRM_DRIVER_DESCRIPTOR("r600", "radeon", create_screen)
diff --git a/src/gallium/targets/egl/pipe_radeon.c b/src/gallium/targets/egl/pipe_radeon.c
deleted file mode 100644 (file)
index 35550bc..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-
-#include "target-helpers/inline_debug_helper.h"
-#include "state_tracker/drm_driver.h"
-#include "radeon/drm/radeon_drm_public.h"
-#include "r300/r300_public.h"
-
-static struct pipe_screen *
-create_screen(int fd)
-{
-   struct r300_winsys_screen *sws;
-   struct pipe_screen *screen;
-
-   sws = r300_drm_winsys_screen_create(fd);
-   if (!sws)
-      return NULL;
-
-   screen = r300_screen_create(sws);
-   if (!screen)
-      return NULL;
-
-   screen = debug_screen_wrap(screen);
-
-   return screen;
-}
-
-PUBLIC
-DRM_DRIVER_DESCRIPTOR("radeon", "radeon", create_screen)
index 47aca4464db9fdb5b4f14951ae9a30abd60d3aef..fc7c9ae6f9219137e19d0e30357bcd970aeb8169 100644 (file)
@@ -1,6 +1,7 @@
 
 #include "pipe/p_compiler.h"
 #include "pipe/p_context.h"
+#include "pipe/p_state.h"
 #include "tgsi/tgsi_text.h"
 #include "util/u_memory.h"
 #include "state_tracker/graw.h"
index 41120ba3c70f1b78ffba2eee73f9064fee811b69..8b64a0b819c8fd8a605e909bd563d5d3b8511130 100644 (file)
@@ -1,5 +1,6 @@
 #include "pipe/p_compiler.h"
 #include "pipe/p_context.h"
+#include "pipe/p_screen.h"
 #include "util/u_debug.h"
 #include "util/u_memory.h"
 #include "target-helpers/wrap_screen.h"
index 144084f74f838cbda095da3ccee3243dde9e479e..12fe403f62f7339094d5c1ce9d11ef832eac1ffd 100644 (file)
@@ -17,6 +17,7 @@ if env['platform'] == 'windows':
         'user32',
         'kernel32',
         'ws2_32',
+        talloc,
     ])
 
     sources = []
index e745023ba598ce439066e41e4e4b01b7463c02bf..fe0541543ab1985ce02b0289117cab318ea55b3e 100644 (file)
@@ -68,8 +68,9 @@ $(TOP)/$(LIB_DIR)/gallium:
 # Make the libGL.so library
 $(TOP)/$(LIB_DIR)/gallium/$(GL_LIB_NAME): $(XLIB_TARGET_OBJECTS) $(LIBS) Makefile
        $(TOP)/bin/mklib -o $(GL_LIB) \
-               -linker "$(CC)" \
+               -linker "$(CXX)" \
                -major $(GL_MAJOR) -minor $(GL_MINOR) -patch $(GL_TINY) \
+               -cplusplus \
                -install $(TOP)/$(LIB_DIR)/gallium \
                $(MKLIB_OPTIONS) $(XLIB_TARGET_OBJECTS) \
                -Wl,--start-group $(LIBS) -Wl,--end-group $(GL_LIB_DEPS)
index 78703fd096d295d853e52a0b6277b7311179f694..88e216a65be30a39297ae4096f11d36bf9de6302 100644 (file)
@@ -35,6 +35,7 @@ env.Prepend(LIBS = [
     mesa,
     glsl,
     gallium,
+    'talloc'
 ])
 
 sources = [
index 69b4ddd33f77eda52823f0abefb408959f2b5374..5a9c80c856666e9d7ac01f2f1e34748947fdd363 100644 (file)
@@ -36,6 +36,7 @@
 #include "state_tracker/xlib_sw_winsys.h"
 #include "xm_public.h"
 
+#include "state_tracker/st_api.h"
 #include "state_tracker/st_gl_api.h"
 
 /* piggy back on this libGL for OpenGL support in EGL */
index 58706dab93d10fdf2c1db1012ba6011030f558db..089d05c62379e82c337e6558942e752133e30d60 100755 (executable)
@@ -55,7 +55,7 @@ def tex_coords(texture, face, level, zslice):
         [0.0, 1.0],
     ] 
     
-    if texture.target == PIPE_TEXTURE_2D:
+    if texture.target == PIPE_TEXTURE_2D or texture.target == PIPE_TEXTURE_RECT:
         return [[s, t, 0.0] for s, t in st]
     elif texture.target == PIPE_TEXTURE_3D:
         depth = texture.get_depth(level)
diff --git a/src/gallium/tools/addr2line.sh b/src/gallium/tools/addr2line.sh
new file mode 100755 (executable)
index 0000000..34dec14
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/bash
+# This script processes symbols output by Gallium using glibc to human-readable function names
+
+lastbin=
+i=-1
+dir="$(mktemp -d)"
+input="$1"
+
+# Gather all unique addresses for each binary
+sed -nre 's|([^ ]*/[^ ]*)\(\+0x([^)]*).*|\1 \2|p' "$input"|sort|uniq|while read bin addr; do
+       if test "$lastbin" != "$bin"; then
+               ((++i))
+               lastbin="$bin"
+               echo "$bin" > "$dir/$i.addrs.bin"
+       fi
+       echo "$addr" >> "$dir/$i.addrs"
+done
+
+# Construct a sed script to convert hex address to human readable form, and apply it
+for i in "$dir"/*.addrs; do
+       bin="$(<"$i.bin")"
+       addr2line -p -e "$bin" -a -f < "$i"|sed -nre 's@^0x0*([^:]*): ([^?]*)$@s|'"$bin"'(+0x\1)|\2|g@gp'
+       rm -f "$i" "$i.bin"
+done|sed -f - "$input"
+
+rmdir "$dir"
index 660dbd0c332e99244088bc2b1e596a847740bd6c..d4bf124ce6f2c28ae43831098b2298734cdb0d48 100644 (file)
@@ -19,7 +19,8 @@ nouveau_drm_destroy_winsys(struct pipe_winsys *s)
 {
        struct nouveau_winsys *nv_winsys = nouveau_winsys(s);
        struct nouveau_screen *nv_screen= nouveau_screen(nv_winsys->pscreen);
-       nouveau_device_close(&nv_screen->device);
+       if (nv_screen)
+               nouveau_device_close(&nv_screen->device);
        FREE(nv_winsys);
 }
 
index d17d6e7954f6e602f03901e93c82aa69170e3122..71d65f0feab648c87bdce1000ddffe06c6933ac6 100644 (file)
@@ -30,6 +30,8 @@
 #include "radeon_priv.h"
 #include "r600d.h"
 
+#include "util/u_memory.h"
+
 static int r600_state_pm4_resource(struct radeon_state *state);
 static int r600_state_pm4_cb0(struct radeon_state *state);
 static int r600_state_pm4_vgt(struct radeon_state *state);
@@ -38,24 +40,69 @@ static int r600_state_pm4_shader(struct radeon_state *state);
 static int r600_state_pm4_draw(struct radeon_state *state);
 static int r600_state_pm4_config(struct radeon_state *state);
 static int r600_state_pm4_generic(struct radeon_state *state);
+static int r600_state_pm4_query_begin(struct radeon_state *state);
+static int r600_state_pm4_query_end(struct radeon_state *state);
 static int r700_state_pm4_config(struct radeon_state *state);
 static int r700_state_pm4_cb0(struct radeon_state *state);
 static int r700_state_pm4_db(struct radeon_state *state);
 
 #include "r600_states.h"
 
+
+#define SUB_NONE(param) { { 0, R600_names_##param, (sizeof(R600_names_##param)/sizeof(struct radeon_register)) } }
+#define SUB_PS(param) { R600_SHADER_PS, R600_names_##param, (sizeof(R600_names_##param)/sizeof(struct radeon_register)) }
+#define SUB_VS(param) { R600_SHADER_VS, R600_names_##param, (sizeof(R600_names_##param)/sizeof(struct radeon_register)) }
+#define SUB_GS(param) { R600_SHADER_GS, R600_names_##param, (sizeof(R600_names_##param)/sizeof(struct radeon_register)) }
+#define SUB_FS(param) { R600_SHADER_FS, R600_names_##param, (sizeof(R600_names_##param)/sizeof(struct radeon_register)) }
+
+/* some of these are overriden at runtime for R700 */
+struct radeon_stype_info r600_stypes[] = {
+       { R600_STATE_CONFIG, 1, 0, r600_state_pm4_config, SUB_NONE(CONFIG), },
+       { R600_STATE_CB_CNTL, 1, 0, r600_state_pm4_generic, SUB_NONE(CB_CNTL) },
+       { R600_STATE_RASTERIZER, 1, 0, r600_state_pm4_generic, SUB_NONE(RASTERIZER) },
+       { R600_STATE_VIEWPORT, 1, 0, r600_state_pm4_generic, SUB_NONE(VIEWPORT) },
+       { R600_STATE_SCISSOR, 1, 0, r600_state_pm4_generic, SUB_NONE(SCISSOR) },
+       { R600_STATE_BLEND, 1, 0, r600_state_pm4_generic, SUB_NONE(BLEND), },
+       { R600_STATE_DSA, 1, 0, r600_state_pm4_generic, SUB_NONE(DSA), },
+       { R600_STATE_SHADER, 1, 0, r600_state_pm4_shader, { SUB_PS(PS_SHADER), SUB_VS(VS_SHADER) } },
+       { R600_STATE_CONSTANT, 256, 0x10, r600_state_pm4_generic,  { SUB_PS(PS_CONSTANT), SUB_VS(VS_CONSTANT) } },
+       { R600_STATE_RESOURCE, 160, 0x1c, r600_state_pm4_resource, { SUB_PS(PS_RESOURCE), SUB_VS(VS_RESOURCE), SUB_GS(GS_RESOURCE), SUB_FS(FS_RESOURCE)} },
+       { R600_STATE_SAMPLER, 18, 0xc, r600_state_pm4_generic, { SUB_PS(PS_SAMPLER), SUB_VS(VS_SAMPLER), SUB_GS(GS_SAMPLER) } },
+       { R600_STATE_SAMPLER_BORDER, 18, 0x10, r600_state_pm4_generic, { SUB_PS(PS_SAMPLER_BORDER), SUB_VS(VS_SAMPLER_BORDER), SUB_GS(GS_SAMPLER_BORDER) } },
+       { R600_STATE_CB0, 1, 0, r600_state_pm4_cb0, SUB_NONE(CB0) },
+       { R600_STATE_CB1, 1, 0, r600_state_pm4_cb0, SUB_NONE(CB1) },
+       { R600_STATE_CB2, 1, 0, r600_state_pm4_cb0, SUB_NONE(CB2) },
+       { R600_STATE_CB3, 1, 0, r600_state_pm4_cb0, SUB_NONE(CB3) },
+       { R600_STATE_CB4, 1, 0, r600_state_pm4_cb0, SUB_NONE(CB4) },
+       { R600_STATE_CB5, 1, 0, r600_state_pm4_cb0, SUB_NONE(CB5) },
+       { R600_STATE_CB6, 1, 0, r600_state_pm4_cb0, SUB_NONE(CB6) },
+       { R600_STATE_CB7, 1, 0, r600_state_pm4_cb0, SUB_NONE(CB7) },
+       { R600_STATE_QUERY_BEGIN, 1, 0, r600_state_pm4_query_begin, SUB_NONE(VGT_EVENT) },
+       { R600_STATE_QUERY_END, 1, 0, r600_state_pm4_query_end, SUB_NONE(VGT_EVENT) },
+       { R600_STATE_DB, 1, 0, r600_state_pm4_db, SUB_NONE(DB) },
+       { R600_STATE_UCP, 1, 0, r600_state_pm4_generic, SUB_NONE(UCP) },
+       { R600_STATE_VGT, 1, 0, r600_state_pm4_vgt, SUB_NONE(VGT) },
+       { R600_STATE_DRAW, 1, 0, r600_state_pm4_draw, SUB_NONE(DRAW) },
+};
+#define STYPES_SIZE Elements(r600_stypes)
+
+static const struct radeon_register *get_regs(struct radeon_state *state)
+{
+       return state->stype->reginfo[state->shader_index].regs;
+}
+
 /*
  * r600/r700 state functions
  */
 static int r600_state_pm4_bytecode(struct radeon_state *state, unsigned offset, unsigned id, unsigned nreg)
 {
-       const struct radeon_register *regs = state->radeon->type[state->type].regs;
+       const struct radeon_register *regs = get_regs(state);
        unsigned i;
        int r;
 
        if (!offset) {
                fprintf(stderr, "%s invalid register for state %d %d\n",
-                       __func__, state->type, id);
+                       __func__, state->stype->stype, id);
                return -EINVAL;
        }
        if (offset >= R600_CONFIG_REG_OFFSET && offset < R600_CONFIG_REG_END) {
@@ -114,19 +161,18 @@ static int r600_state_pm4_bytecode(struct radeon_state *state, unsigned offset,
 
 static int r600_state_pm4_generic(struct radeon_state *state)
 {
-       struct radeon *radeon = state->radeon;
-       unsigned i, offset, nreg, type, coffset, loffset, soffset;
+       const struct radeon_register *regs = get_regs(state);
+       unsigned i, offset, nreg, coffset, loffset, soffset;
        unsigned start;
        int r;
 
        if (!state->nstates)
                return 0;
-       type = state->type;
-       soffset = (state->id - radeon->type[type].id) * radeon->type[type].stride;
-       offset = loffset = radeon->type[type].regs[0].offset + soffset;
+       soffset = state->id * state->stype->stride;
+       offset = loffset = regs[0].offset + soffset;
        start = 0;
        for (i = 1, nreg = 1; i < state->nstates; i++) {
-               coffset = radeon->type[type].regs[i].offset + soffset;
+               coffset = regs[i].offset + soffset;
                if (coffset == (loffset + 4)) {
                        nreg++;
                        loffset = coffset;
@@ -233,20 +279,54 @@ static int r600_state_pm4_config(struct radeon_state *state)
        state->pm4[state->cpm4++] = 0x80000000;
        state->pm4[state->cpm4++] = 0x80000000;
        state->pm4[state->cpm4++] = PKT3(PKT3_EVENT_WRITE, 0);
-       state->pm4[state->cpm4++] = 0x00000016;
+       state->pm4[state->cpm4++] = EVENT_TYPE_CACHE_FLUSH_AND_INV_EVENT;
        state->pm4[state->cpm4++] = PKT3(PKT3_SET_CONFIG_REG, 1);
        state->pm4[state->cpm4++] = 0x00000010;
        state->pm4[state->cpm4++] = 0x00028000;
        return r600_state_pm4_generic(state);
 }
 
+static int r600_state_pm4_query_begin(struct radeon_state *state)
+{
+       int r;
+
+       state->cpm4 = 0;
+       state->pm4[state->cpm4++] = PKT3(PKT3_EVENT_WRITE, 2);
+       state->pm4[state->cpm4++] = EVENT_TYPE_ZPASS_DONE;
+       state->pm4[state->cpm4++] = state->states[0];
+       state->pm4[state->cpm4++] = 0x0;
+       state->pm4[state->cpm4++] = PKT3(PKT3_NOP, 0);
+       r = radeon_state_reloc(state, state->cpm4, 0);
+       if (r)
+               return r;
+       state->pm4[state->cpm4++] = state->bo[0]->handle;
+       return 0;
+}
+
+static int r600_state_pm4_query_end(struct radeon_state *state)
+{
+       int r;
+
+       state->cpm4 = 0;
+       state->pm4[state->cpm4++] = PKT3(PKT3_EVENT_WRITE, 2);
+       state->pm4[state->cpm4++] = EVENT_TYPE_ZPASS_DONE;
+       state->pm4[state->cpm4++] = state->states[0];
+       state->pm4[state->cpm4++] = 0x0;
+       state->pm4[state->cpm4++] = PKT3(PKT3_NOP, 0);
+       r = radeon_state_reloc(state, state->cpm4, 0);
+       if (r)
+               return r;
+       state->pm4[state->cpm4++] = state->bo[0]->handle;
+       return 0;
+}
+
 static int r700_state_pm4_config(struct radeon_state *state)
 {
        state->pm4[state->cpm4++] = PKT3(PKT3_CONTEXT_CONTROL, 1);
        state->pm4[state->cpm4++] = 0x80000000;
        state->pm4[state->cpm4++] = 0x80000000;
        state->pm4[state->cpm4++] = PKT3(PKT3_EVENT_WRITE, 0);
-       state->pm4[state->cpm4++] = 0x00000016;
+       state->pm4[state->cpm4++] = EVENT_TYPE_CACHE_FLUSH_AND_INV_EVENT;
        state->pm4[state->cpm4++] = PKT3(PKT3_SET_CONFIG_REG, 1);
        state->pm4[state->cpm4++] = 0x00000010;
        state->pm4[state->cpm4++] = 0x00028000;
@@ -287,7 +367,6 @@ static int r600_state_pm4_vgt(struct radeon_state *state)
 
 static int r600_state_pm4_draw(struct radeon_state *state)
 {
-       unsigned i;
        int r;
 
        if (state->nbo) {
@@ -301,20 +380,13 @@ static int r600_state_pm4_draw(struct radeon_state *state)
                if (r)
                        return r;
                state->pm4[state->cpm4++] = state->bo[0]->handle;
-       } else if  (state->nimmd) {
-               state->pm4[state->cpm4++] = PKT3(PKT3_DRAW_INDEX_IMMD, state->nimmd + 1);
-               state->pm4[state->cpm4++] = state->states[R600_DRAW__VGT_NUM_INDICES];
-               state->pm4[state->cpm4++] = state->states[R600_DRAW__VGT_DRAW_INITIATOR];
-               for (i = 0; i < state->nimmd; i++) {
-                       state->pm4[state->cpm4++] = state->immd[i];
-               }
        } else {
                state->pm4[state->cpm4++] = PKT3(PKT3_DRAW_INDEX_AUTO, 1);
                state->pm4[state->cpm4++] = state->states[R600_DRAW__VGT_NUM_INDICES];
                state->pm4[state->cpm4++] = state->states[R600_DRAW__VGT_DRAW_INITIATOR];
        }
        state->pm4[state->cpm4++] = PKT3(PKT3_EVENT_WRITE, 0);
-       state->pm4[state->cpm4++] = 0x00000016;
+       state->pm4[state->cpm4++] = EVENT_TYPE_CACHE_FLUSH_AND_INV_EVENT;
        return 0;
 }
 
@@ -322,8 +394,9 @@ static int r600_state_pm4_resource(struct radeon_state *state)
 {
        u32 flags, type, nbo, offset, soffset;
        int r;
+       const struct radeon_register *regs = get_regs(state);
 
-       soffset = (state->id - state->radeon->type[state->type].id) * state->radeon->type[state->type].stride;
+       soffset = state->id * state->stype->stride;
        type = G_038018_TYPE(state->states[6]);
        switch (type) {
        case 2:
@@ -342,7 +415,7 @@ static int r600_state_pm4_resource(struct radeon_state *state)
                return -EINVAL;
        }
        r600_state_pm4_with_flush(state, flags);
-       offset = state->radeon->type[state->type].regs[0].offset + soffset;
+       offset = regs[0].offset + soffset;
        state->pm4[state->cpm4++] = PKT3(PKT3_SET_RESOURCE, 7);
        state->pm4[state->cpm4++] = (offset - R_038000_SQ_TEX_RESOURCE_WORD0_0) >> 2;
        state->pm4[state->cpm4++] = state->states[0];
@@ -367,33 +440,62 @@ static int r600_state_pm4_resource(struct radeon_state *state)
        return 0;
 }
 
-int r600_init(struct radeon *radeon)
+
+static void r600_modify_type_array(struct radeon *radeon)
 {
+       int i;
        switch (radeon->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:
-               radeon->ntype = R600_NTYPE;
-               radeon->nstate = R600_NSTATE;
-               radeon->type = R600_types;
-               break;
        case CHIP_RV770:
        case CHIP_RV730:
        case CHIP_RV710:
        case CHIP_RV740:
-               radeon->ntype = R600_NTYPE;
-               radeon->nstate = R600_NSTATE;
-               radeon->type = R700_types;
                break;
        default:
-               fprintf(stderr, "%s unknown or unsupported chipset 0x%04X\n",
-                       __func__, radeon->device);
-               return -EINVAL;
+               return;
+       }
+
+       /* r700 needs some mods */
+       for (i = 0; i < radeon->nstype; i++) {
+               struct radeon_stype_info *info = &radeon->stype[i];
+               
+               switch(info->stype) {
+               case R600_STATE_CONFIG:
+                       info->pm4 = r700_state_pm4_config;
+                       break;
+               case R600_STATE_CB0:
+                       info->pm4 = r700_state_pm4_cb0;
+                       break;
+               case R600_STATE_DB:
+                       info->pm4 = r700_state_pm4_db;
+               };
        }
+}
+
+static void r600_build_types_array(struct radeon *radeon)
+{
+       int i, j;
+       int id = 0;
+
+       for (i = 0; i < STYPES_SIZE; i++) {
+               r600_stypes[i].base_id = id;
+               r600_stypes[i].npm4 = 128;
+               if (r600_stypes[i].reginfo[0].shader_type == 0) {
+                       id += r600_stypes[i].num;
+               } else {
+                       for (j = 0; j < R600_SHADER_MAX; j++) {
+                               if (r600_stypes[i].reginfo[j].shader_type)
+                                       id += r600_stypes[i].num;
+                       }
+               }
+       }
+       radeon->stype = r600_stypes;
+       radeon->nstype = STYPES_SIZE;
+
+       r600_modify_type_array(radeon);
+}
+
+int r600_init(struct radeon *radeon)
+{
+       r600_build_types_array(radeon);
        return 0;
 }
index e40c77d8f6c89d4d6ca6163405c1e28c9021264e..09d79d498d89def18f676ab282f934715b5c1eb0 100644 (file)
@@ -17,7 +17,7 @@
 #ifndef R600_STATES_H
 #define R600_STATES_H
 
-static const struct radeon_register R600_CONFIG_names[] = {
+static const struct radeon_register R600_names_CONFIG[] = {
        {0x00008C00, 0, 0, "SQ_CONFIG"},
        {0x00008C04, 0, 0, "SQ_GPR_RESOURCE_MGMT_1"},
        {0x00008C08, 0, 0, "SQ_GPR_RESOURCE_MGMT_2"},
@@ -61,7 +61,7 @@ static const struct radeon_register R600_CONFIG_names[] = {
        {0x00028B20, 0, 0, "VGT_STRMOUT_BUFFER_EN"},
 };
 
-static const struct radeon_register R600_CB_CNTL_names[] = {
+static const struct radeon_register R600_names_CB_CNTL[] = {
        {0x00028120, 0, 0, "CB_CLEAR_RED"},
        {0x00028124, 0, 0, "CB_CLEAR_GREEN"},
        {0x00028128, 0, 0, "CB_CLEAR_BLUE"},
@@ -82,7 +82,7 @@ static const struct radeon_register R600_CB_CNTL_names[] = {
        {0x00028C48, 0, 0, "PA_SC_AA_MASK"},
 };
 
-static const struct radeon_register R600_RASTERIZER_names[] = {
+static const struct radeon_register R600_names_RASTERIZER[] = {
        {0x000286D4, 0, 0, "SPI_INTERP_CONTROL_0"},
        {0x00028810, 0, 0, "PA_CL_CLIP_CNTL"},
        {0x00028814, 0, 0, "PA_SU_SC_MODE_CNTL"},
@@ -106,7 +106,7 @@ static const struct radeon_register R600_RASTERIZER_names[] = {
        {0x00028E0C, 0, 0, "PA_SU_POLY_OFFSET_BACK_OFFSET"},
 };
 
-static const struct radeon_register R600_VIEWPORT_names[] = {
+static const struct radeon_register R600_names_VIEWPORT[] = {
        {0x000282D0, 0, 0, "PA_SC_VPORT_ZMIN_0"},
        {0x000282D4, 0, 0, "PA_SC_VPORT_ZMAX_0"},
        {0x0002843C, 0, 0, "PA_CL_VPORT_XSCALE_0"},
@@ -118,7 +118,7 @@ static const struct radeon_register R600_VIEWPORT_names[] = {
        {0x00028818, 0, 0, "PA_CL_VTE_CNTL"},
 };
 
-static const struct radeon_register R600_SCISSOR_names[] = {
+static const struct radeon_register R600_names_SCISSOR[] = {
        {0x00028030, 0, 0, "PA_SC_SCREEN_SCISSOR_TL"},
        {0x00028034, 0, 0, "PA_SC_SCREEN_SCISSOR_BR"},
        {0x00028200, 0, 0, "PA_SC_WINDOW_OFFSET"},
@@ -140,7 +140,7 @@ static const struct radeon_register R600_SCISSOR_names[] = {
        {0x00028254, 0, 0, "PA_SC_VPORT_SCISSOR_0_BR"},
 };
 
-static const struct radeon_register R600_BLEND_names[] = {
+static const struct radeon_register R600_names_BLEND[] = {
        {0x00028414, 0, 0, "CB_BLEND_RED"},
        {0x00028418, 0, 0, "CB_BLEND_GREEN"},
        {0x0002841C, 0, 0, "CB_BLEND_BLUE"},
@@ -156,7 +156,7 @@ static const struct radeon_register R600_BLEND_names[] = {
        {0x00028804, 0, 0, "CB_BLEND_CONTROL"},
 };
 
-static const struct radeon_register R600_DSA_names[] = {
+static const struct radeon_register R600_names_DSA[] = {
        {0x00028028, 0, 0, "DB_STENCIL_CLEAR"},
        {0x0002802C, 0, 0, "DB_DEPTH_CLEAR"},
        {0x00028410, 0, 0, "SX_ALPHA_TEST_CONTROL"},
@@ -175,7 +175,7 @@ static const struct radeon_register R600_DSA_names[] = {
        {0x00028D44, 0, 0, "DB_ALPHA_TO_MASK"},
 };
 
-static const struct radeon_register R600_VS_SHADER_names[] = {
+static const struct radeon_register R600_names_VS_SHADER[] = {
        {0x00028380, 0, 0, "SQ_VTX_SEMANTIC_0"},
        {0x00028384, 0, 0, "SQ_VTX_SEMANTIC_1"},
        {0x00028388, 0, 0, "SQ_VTX_SEMANTIC_2"},
@@ -227,7 +227,7 @@ static const struct radeon_register R600_VS_SHADER_names[] = {
        {0x000288DC, 0, 0, "SQ_PGM_CF_OFFSET_FS"},
 };
 
-static const struct radeon_register R600_PS_SHADER_names[] = {
+static const struct radeon_register R600_names_PS_SHADER[] = {
        {0x00028644, 0, 0, "SPI_PS_INPUT_CNTL_0"},
        {0x00028648, 0, 0, "SPI_PS_INPUT_CNTL_1"},
        {0x0002864C, 0, 0, "SPI_PS_INPUT_CNTL_2"},
@@ -269,21 +269,48 @@ static const struct radeon_register R600_PS_SHADER_names[] = {
        {0x000288CC, 0, 0, "SQ_PGM_CF_OFFSET_PS"},
 };
 
-static const struct radeon_register R600_PS_CONSTANT_names[] = {
+static const struct radeon_register R600_names_PS_CONSTANT[] = {
        {0x00030000, 0, 0, "SQ_ALU_CONSTANT0_0"},
        {0x00030004, 0, 0, "SQ_ALU_CONSTANT1_0"},
        {0x00030008, 0, 0, "SQ_ALU_CONSTANT2_0"},
        {0x0003000C, 0, 0, "SQ_ALU_CONSTANT3_0"},
 };
 
-static const struct radeon_register R600_VS_CONSTANT_names[] = {
+static const struct radeon_register R600_names_VS_CONSTANT[] = {
        {0x00031000, 0, 0, "SQ_ALU_CONSTANT0_256"},
        {0x00031004, 0, 0, "SQ_ALU_CONSTANT1_256"},
        {0x00031008, 0, 0, "SQ_ALU_CONSTANT2_256"},
        {0x0003100C, 0, 0, "SQ_ALU_CONSTANT3_256"},
 };
 
-static const struct radeon_register R600_PS_RESOURCE_names[] = {
+static const struct radeon_register R600_names_UCP[] = {
+       {0x00028E20, 0, 0, "PA_CL_UCP0_X"},
+       {0x00028E24, 0, 0, "PA_CL_UCP0_Y"},
+       {0x00028E28, 0, 0, "PA_CL_UCP0_Z"},
+       {0x00028E2C, 0, 0, "PA_CL_UCP0_W"},
+       {0x00028E30, 0, 0, "PA_CL_UCP1_X"},
+       {0x00028E34, 0, 0, "PA_CL_UCP1_Y"},
+       {0x00028E38, 0, 0, "PA_CL_UCP1_Z"},
+       {0x00028E3C, 0, 0, "PA_CL_UCP1_W"},
+       {0x00028E40, 0, 0, "PA_CL_UCP2_X"},
+       {0x00028E44, 0, 0, "PA_CL_UCP2_Y"},
+       {0x00028E48, 0, 0, "PA_CL_UCP2_Z"},
+       {0x00028E4C, 0, 0, "PA_CL_UCP2_W"},
+       {0x00028E50, 0, 0, "PA_CL_UCP3_X"},
+       {0x00028E54, 0, 0, "PA_CL_UCP3_Y"},
+       {0x00028E58, 0, 0, "PA_CL_UCP3_Z"},
+       {0x00028E5C, 0, 0, "PA_CL_UCP3_W"},
+       {0x00028E60, 0, 0, "PA_CL_UCP4_X"},
+       {0x00028E64, 0, 0, "PA_CL_UCP4_Y"},
+       {0x00028E68, 0, 0, "PA_CL_UCP4_Z"},
+       {0x00028E6C, 0, 0, "PA_CL_UCP4_W"},
+       {0x00028E70, 0, 0, "PA_CL_UCP5_X"},
+       {0x00028E74, 0, 0, "PA_CL_UCP5_Y"},
+       {0x00028E78, 0, 0, "PA_CL_UCP5_Z"},
+       {0x00028E7C, 0, 0, "PA_CL_UCP5_W"},
+};
+
+static const struct radeon_register R600_names_PS_RESOURCE[] = {
        {0x00038000, 0, 0, "RESOURCE0_WORD0"},
        {0x00038004, 0, 0, "RESOURCE0_WORD1"},
        {0x00038008, 0, 0, "RESOURCE0_WORD2"},
@@ -293,7 +320,7 @@ static const struct radeon_register R600_PS_RESOURCE_names[] = {
        {0x00038018, 0, 0, "RESOURCE0_WORD6"},
 };
 
-static const struct radeon_register R600_VS_RESOURCE_names[] = {
+static const struct radeon_register R600_names_VS_RESOURCE[] = {
        {0x00039180, 0, 0, "RESOURCE160_WORD0"},
        {0x00039184, 0, 0, "RESOURCE160_WORD1"},
        {0x00039188, 0, 0, "RESOURCE160_WORD2"},
@@ -303,7 +330,7 @@ static const struct radeon_register R600_VS_RESOURCE_names[] = {
        {0x00039198, 0, 0, "RESOURCE160_WORD6"},
 };
 
-static const struct radeon_register R600_FS_RESOURCE_names[] = {
+static const struct radeon_register R600_names_FS_RESOURCE[] = {
        {0x0003A300, 0, 0, "RESOURCE320_WORD0"},
        {0x0003A304, 0, 0, "RESOURCE320_WORD1"},
        {0x0003A308, 0, 0, "RESOURCE320_WORD2"},
@@ -313,7 +340,7 @@ static const struct radeon_register R600_FS_RESOURCE_names[] = {
        {0x0003A318, 0, 0, "RESOURCE320_WORD6"},
 };
 
-static const struct radeon_register R600_GS_RESOURCE_names[] = {
+static const struct radeon_register R600_names_GS_RESOURCE[] = {
        {0x0003A4C0, 0, 0, "RESOURCE336_WORD0"},
        {0x0003A4C4, 0, 0, "RESOURCE336_WORD1"},
        {0x0003A4C8, 0, 0, "RESOURCE336_WORD2"},
@@ -323,46 +350,46 @@ static const struct radeon_register R600_GS_RESOURCE_names[] = {
        {0x0003A4D8, 0, 0, "RESOURCE336_WORD6"},
 };
 
-static const struct radeon_register R600_PS_SAMPLER_names[] = {
+static const struct radeon_register R600_names_PS_SAMPLER[] = {
        {0x0003C000, 0, 0, "SQ_TEX_SAMPLER_WORD0_0"},
        {0x0003C004, 0, 0, "SQ_TEX_SAMPLER_WORD1_0"},
        {0x0003C008, 0, 0, "SQ_TEX_SAMPLER_WORD2_0"},
 };
 
-static const struct radeon_register R600_VS_SAMPLER_names[] = {
+static const struct radeon_register R600_names_VS_SAMPLER[] = {
        {0x0003C0D8, 0, 0, "SQ_TEX_SAMPLER_WORD0_18"},
        {0x0003C0DC, 0, 0, "SQ_TEX_SAMPLER_WORD1_18"},
        {0x0003C0E0, 0, 0, "SQ_TEX_SAMPLER_WORD2_18"},
 };
 
-static const struct radeon_register R600_GS_SAMPLER_names[] = {
+static const struct radeon_register R600_names_GS_SAMPLER[] = {
        {0x0003C1B0, 0, 0, "SQ_TEX_SAMPLER_WORD0_36"},
        {0x0003C1B4, 0, 0, "SQ_TEX_SAMPLER_WORD1_36"},
        {0x0003C1B8, 0, 0, "SQ_TEX_SAMPLER_WORD2_36"},
 };
 
-static const struct radeon_register R600_PS_SAMPLER_BORDER_names[] = {
+static const struct radeon_register R600_names_PS_SAMPLER_BORDER[] = {
        {0x0000A400, 0, 0, "TD_PS_SAMPLER0_BORDER_RED"},
        {0x0000A404, 0, 0, "TD_PS_SAMPLER0_BORDER_GREEN"},
        {0x0000A408, 0, 0, "TD_PS_SAMPLER0_BORDER_BLUE"},
        {0x0000A40C, 0, 0, "TD_PS_SAMPLER0_BORDER_ALPHA"},
 };
 
-static const struct radeon_register R600_VS_SAMPLER_BORDER_names[] = {
+static const struct radeon_register R600_names_VS_SAMPLER_BORDER[] = {
        {0x0000A600, 0, 0, "TD_VS_SAMPLER0_BORDER_RED"},
        {0x0000A604, 0, 0, "TD_VS_SAMPLER0_BORDER_GREEN"},
        {0x0000A608, 0, 0, "TD_VS_SAMPLER0_BORDER_BLUE"},
        {0x0000A60C, 0, 0, "TD_VS_SAMPLER0_BORDER_ALPHA"},
 };
 
-static const struct radeon_register R600_GS_SAMPLER_BORDER_names[] = {
+static const struct radeon_register R600_names_GS_SAMPLER_BORDER[] = {
        {0x0000A800, 0, 0, "TD_GS_SAMPLER0_BORDER_RED"},
        {0x0000A804, 0, 0, "TD_GS_SAMPLER0_BORDER_GREEN"},
        {0x0000A808, 0, 0, "TD_GS_SAMPLER0_BORDER_BLUE"},
        {0x0000A80C, 0, 0, "TD_GS_SAMPLER0_BORDER_ALPHA"},
 };
 
-static const struct radeon_register R600_CB0_names[] = {
+static const struct radeon_register R600_names_CB0[] = {
        {0x00028040, 1, 0, "CB_COLOR0_BASE"},
        {0x000280A0, 0, 0, "CB_COLOR0_INFO"},
        {0x00028060, 0, 0, "CB_COLOR0_SIZE"},
@@ -372,7 +399,7 @@ static const struct radeon_register R600_CB0_names[] = {
        {0x00028100, 0, 0, "CB_COLOR0_MASK"},
 };
 
-static const struct radeon_register R600_CB1_names[] = {
+static const struct radeon_register R600_names_CB1[] = {
        {0x00028044, 1, 0, "CB_COLOR1_BASE"},
        {0x000280A4, 0, 0, "CB_COLOR1_INFO"},
        {0x00028064, 0, 0, "CB_COLOR1_SIZE"},
@@ -382,7 +409,7 @@ static const struct radeon_register R600_CB1_names[] = {
        {0x00028104, 0, 0, "CB_COLOR1_MASK"},
 };
 
-static const struct radeon_register R600_CB2_names[] = {
+static const struct radeon_register R600_names_CB2[] = {
        {0x00028048, 1, 0, "CB_COLOR2_BASE"},
        {0x000280A8, 0, 0, "CB_COLOR2_INFO"},
        {0x00028068, 0, 0, "CB_COLOR2_SIZE"},
@@ -392,7 +419,7 @@ static const struct radeon_register R600_CB2_names[] = {
        {0x00028108, 0, 0, "CB_COLOR2_MASK"},
 };
 
-static const struct radeon_register R600_CB3_names[] = {
+static const struct radeon_register R600_names_CB3[] = {
        {0x0002804C, 1, 0, "CB_COLOR3_BASE"},
        {0x000280AC, 0, 0, "CB_COLOR3_INFO"},
        {0x0002806C, 0, 0, "CB_COLOR3_SIZE"},
@@ -402,7 +429,7 @@ static const struct radeon_register R600_CB3_names[] = {
        {0x0002810C, 0, 0, "CB_COLOR3_MASK"},
 };
 
-static const struct radeon_register R600_CB4_names[] = {
+static const struct radeon_register R600_names_CB4[] = {
        {0x00028050, 1, 0, "CB_COLOR4_BASE"},
        {0x000280B0, 0, 0, "CB_COLOR4_INFO"},
        {0x00028070, 0, 0, "CB_COLOR4_SIZE"},
@@ -412,7 +439,7 @@ static const struct radeon_register R600_CB4_names[] = {
        {0x00028110, 0, 0, "CB_COLOR4_MASK"},
 };
 
-static const struct radeon_register R600_CB5_names[] = {
+static const struct radeon_register R600_names_CB5[] = {
        {0x00028054, 1, 0, "CB_COLOR5_BASE"},
        {0x000280B4, 0, 0, "CB_COLOR5_INFO"},
        {0x00028074, 0, 0, "CB_COLOR5_SIZE"},
@@ -422,7 +449,7 @@ static const struct radeon_register R600_CB5_names[] = {
        {0x00028114, 0, 0, "CB_COLOR5_MASK"},
 };
 
-static const struct radeon_register R600_CB6_names[] = {
+static const struct radeon_register R600_names_CB6[] = {
        {0x00028058, 1, 0, "CB_COLOR6_BASE"},
        {0x000280B8, 0, 0, "CB_COLOR6_INFO"},
        {0x00028078, 0, 0, "CB_COLOR6_SIZE"},
@@ -432,7 +459,7 @@ static const struct radeon_register R600_CB6_names[] = {
        {0x00028118, 0, 0, "CB_COLOR6_MASK"},
 };
 
-static const struct radeon_register R600_CB7_names[] = {
+static const struct radeon_register R600_names_CB7[] = {
        {0x0002805C, 1, 0, "CB_COLOR7_BASE"},
        {0x000280BC, 0, 0, "CB_COLOR7_INFO"},
        {0x0002807C, 0, 0, "CB_COLOR7_SIZE"},
@@ -442,7 +469,7 @@ static const struct radeon_register R600_CB7_names[] = {
        {0x0002811C, 0, 0, "CB_COLOR7_MASK"},
 };
 
-static const struct radeon_register R600_DB_names[] = {
+static const struct radeon_register R600_names_DB[] = {
        {0x0002800C, 1, 0, "DB_DEPTH_BASE"},
        {0x00028000, 0, 0, "DB_DEPTH_SIZE"},
        {0x00028004, 0, 0, "DB_DEPTH_VIEW"},
@@ -451,7 +478,7 @@ static const struct radeon_register R600_DB_names[] = {
        {0x00028D34, 0, 0, "DB_PREFETCH_LIMIT"},
 };
 
-static const struct radeon_register R600_VGT_names[] = {
+static const struct radeon_register R600_names_VGT[] = {
        {0x00008958, 0, 0, "VGT_PRIMITIVE_TYPE"},
        {0x00028400, 0, 0, "VGT_MAX_VTX_INDX"},
        {0x00028404, 0, 0, "VGT_MIN_VTX_INDX"},
@@ -465,81 +492,15 @@ static const struct radeon_register R600_VGT_names[] = {
        {0x00028AA4, 0, 0, "VGT_INSTANCE_STEP_RATE_1"},
 };
 
-static const struct radeon_register R600_DRAW_names[] = {
+static const struct radeon_register R600_names_DRAW[] = {
        {0x00008970, 0, 0, "VGT_NUM_INDICES"},
        {0x000287E4, 0, 0, "VGT_DMA_BASE_HI"},
        {0x000287E8, 1, 0, "VGT_DMA_BASE"},
        {0x000287F0, 0, 0, "VGT_DRAW_INITIATOR"},
 };
 
-static struct radeon_type R600_types[] = {
-       { 128,    0, 0x00000000, 0x00000000, 0x0000, 0, "R600_CONFIG", 41, r600_state_pm4_config, R600_CONFIG_names},
-       { 128,    1, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB_CNTL", 18, r600_state_pm4_generic, R600_CB_CNTL_names},
-       { 128,    2, 0x00000000, 0x00000000, 0x0000, 0, "R600_RASTERIZER", 21, r600_state_pm4_generic, R600_RASTERIZER_names},
-       { 128,    3, 0x00000000, 0x00000000, 0x0000, 0, "R600_VIEWPORT", 9, r600_state_pm4_generic, R600_VIEWPORT_names},
-       { 128,    4, 0x00000000, 0x00000000, 0x0000, 0, "R600_SCISSOR", 19, r600_state_pm4_generic, R600_SCISSOR_names},
-       { 128,    5, 0x00000000, 0x00000000, 0x0000, 0, "R600_BLEND", 13, r600_state_pm4_generic, R600_BLEND_names},
-       { 128,    6, 0x00000000, 0x00000000, 0x0000, 0, "R600_DSA", 16, r600_state_pm4_generic, R600_DSA_names},
-       { 128,    7, 0x00000000, 0x00000000, 0x0000, 0, "R600_VS_SHADER", 49, r600_state_pm4_shader, R600_VS_SHADER_names},
-       { 128,    8, 0x00000000, 0x00000000, 0x0000, 0, "R600_PS_SHADER", 39, r600_state_pm4_shader, R600_PS_SHADER_names},
-       { 128,    9, 0x00030000, 0x00031000, 0x0010, 0, "R600_PS_CONSTANT", 4, r600_state_pm4_generic, R600_PS_CONSTANT_names},
-       { 128,  265, 0x00031000, 0x00032000, 0x0010, 0, "R600_VS_CONSTANT", 4, r600_state_pm4_generic, R600_VS_CONSTANT_names},
-       { 128,  521, 0x00038000, 0x00039180, 0x001C, 0, "R600_PS_RESOURCE", 7, r600_state_pm4_resource, R600_PS_RESOURCE_names},
-       { 128,  681, 0x00039180, 0x0003A300, 0x001C, 0, "R600_VS_RESOURCE", 7, r600_state_pm4_resource, R600_VS_RESOURCE_names},
-       { 128,  841, 0x00039180, 0x0003A300, 0x001C, 0, "R600_FS_RESOURCE", 7, r600_state_pm4_resource, R600_FS_RESOURCE_names},
-       { 128, 1001, 0x00039180, 0x0003A300, 0x001C, 0, "R600_GS_RESOURCE", 7, r600_state_pm4_resource, R600_GS_RESOURCE_names},
-       { 128, 1161, 0x0003C000, 0x0003C0D8, 0x000C, 0, "R600_PS_SAMPLER", 3, r600_state_pm4_generic, R600_PS_SAMPLER_names},
-       { 128, 1179, 0x0003C0D8, 0x0003C1B0, 0x000C, 0, "R600_VS_SAMPLER", 3, r600_state_pm4_generic, R600_VS_SAMPLER_names},
-       { 128, 1197, 0x0003C1B0, 0x0003C288, 0x000C, 0, "R600_GS_SAMPLER", 3, r600_state_pm4_generic, R600_GS_SAMPLER_names},
-       { 128, 1215, 0x0000A400, 0x0000A520, 0x0010, 0, "R600_PS_SAMPLER_BORDER", 4, r600_state_pm4_generic, R600_PS_SAMPLER_BORDER_names},
-       { 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_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[] = {
-       { 128,    0, 0x00000000, 0x00000000, 0x0000, 0, "R600_CONFIG", 41, r700_state_pm4_config, R600_CONFIG_names},
-       { 128,    1, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB_CNTL", 18, r600_state_pm4_generic, R600_CB_CNTL_names},
-       { 128,    2, 0x00000000, 0x00000000, 0x0000, 0, "R600_RASTERIZER", 21, r600_state_pm4_generic, R600_RASTERIZER_names},
-       { 128,    3, 0x00000000, 0x00000000, 0x0000, 0, "R600_VIEWPORT", 9, r600_state_pm4_generic, R600_VIEWPORT_names},
-       { 128,    4, 0x00000000, 0x00000000, 0x0000, 0, "R600_SCISSOR", 19, r600_state_pm4_generic, R600_SCISSOR_names},
-       { 128,    5, 0x00000000, 0x00000000, 0x0000, 0, "R600_BLEND", 13, r600_state_pm4_generic, R600_BLEND_names},
-       { 128,    6, 0x00000000, 0x00000000, 0x0000, 0, "R600_DSA", 16, r600_state_pm4_generic, R600_DSA_names},
-       { 128,    7, 0x00000000, 0x00000000, 0x0000, 0, "R600_VS_SHADER", 49, r600_state_pm4_shader, R600_VS_SHADER_names},
-       { 128,    8, 0x00000000, 0x00000000, 0x0000, 0, "R600_PS_SHADER", 39, r600_state_pm4_shader, R600_PS_SHADER_names},
-       { 128,    9, 0x00030000, 0x00031000, 0x0010, 0, "R600_PS_CONSTANT", 4, r600_state_pm4_generic, R600_PS_CONSTANT_names},
-       { 128,  265, 0x00031000, 0x00032000, 0x0010, 0, "R600_VS_CONSTANT", 4, r600_state_pm4_generic, R600_VS_CONSTANT_names},
-       { 128,  521, 0x00038000, 0x00039180, 0x001C, 0, "R600_PS_RESOURCE", 7, r600_state_pm4_resource, R600_PS_RESOURCE_names},
-       { 128,  681, 0x00039180, 0x0003A300, 0x001C, 0, "R600_VS_RESOURCE", 7, r600_state_pm4_resource, R600_VS_RESOURCE_names},
-       { 128,  841, 0x00039180, 0x0003A300, 0x001C, 0, "R600_FS_RESOURCE", 7, r600_state_pm4_resource, R600_FS_RESOURCE_names},
-       { 128, 1001, 0x00039180, 0x0003A300, 0x001C, 0, "R600_GS_RESOURCE", 7, r600_state_pm4_resource, R600_GS_RESOURCE_names},
-       { 128, 1161, 0x0003C000, 0x0003C0D8, 0x000C, 0, "R600_PS_SAMPLER", 3, r600_state_pm4_generic, R600_PS_SAMPLER_names},
-       { 128, 1179, 0x0003C0D8, 0x0003C1B0, 0x000C, 0, "R600_VS_SAMPLER", 3, r600_state_pm4_generic, R600_VS_SAMPLER_names},
-       { 128, 1197, 0x0003C1B0, 0x0003C288, 0x000C, 0, "R600_GS_SAMPLER", 3, r600_state_pm4_generic, R600_GS_SAMPLER_names},
-       { 128, 1215, 0x0000A400, 0x0000A520, 0x0010, 0, "R600_PS_SAMPLER_BORDER", 4, r600_state_pm4_generic, R600_PS_SAMPLER_BORDER_names},
-       { 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_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},
+static const struct radeon_register R600_names_VGT_EVENT[] = {
+       {0x00028A90, 1, 0, "VGT_EVENT_INITIATOR"},
 };
 
 #endif
index 5d13378627ea77b1160622f352a131bc652b52da..e8c2dc0651c1373506492e32d760aa011c1a7287 100644 (file)
@@ -82,6 +82,9 @@
 #define PKT3_SET_CTL_CONST                     0x6F
 #define PKT3_SURFACE_BASE_UPDATE               0x73
 
+#define EVENT_TYPE_ZPASS_DONE                  0x15
+#define EVENT_TYPE_CACHE_FLUSH_AND_INV_EVENT   0x16
+
 #define PKT_TYPE_S(x)                   (((x) & 0x3) << 30)
 #define PKT_TYPE_G(x)                   (((x) >> 30) & 0x3)
 #define PKT_TYPE_C                      0x3FFFFFFF
index 80b0a1d39729ddfa2817e1a1955edbee0a60453e..e2d813ebac71e270bd6121d3eab7dc8009d51204 100644 (file)
@@ -42,24 +42,13 @@ static int radeon_get_device(struct radeon *radeon)
        return r;
 }
 
-/* symbol missing drove me crazy hack to get symbol exported */
-static void fake(void)
-{
-       struct radeon_ctx *ctx;
-       struct radeon_draw *draw;
-
-       ctx = radeon_ctx(NULL);
-       draw = radeon_draw(NULL);
-}
-
 struct radeon *radeon_new(int fd, unsigned device)
 {
        struct radeon *radeon;
-       int r;
+       int r, i, id;
 
        radeon = calloc(1, sizeof(*radeon));
        if (radeon == NULL) {
-               fake();
                return NULL;
        }
        radeon->fd = fd;
@@ -131,6 +120,19 @@ struct radeon *radeon_new(int fd, unsigned device)
                        __func__, radeon->device);
                break;
        }
+       radeon->state_type_id = calloc(radeon->nstype, sizeof(unsigned));
+       if (radeon->state_type_id == NULL) {
+               return radeon_decref(radeon);
+       }
+       for (i = 0, id = 0; i < radeon->nstype; i++) {
+               radeon->state_type_id[i] = id;
+               for (int j = 0; j < radeon->nstype; j++) {
+                       if (radeon->stype[j].stype != i)
+                               continue;
+                       id += radeon->stype[j].num;
+               }
+       }
+       radeon->nstate_per_shader = id;
        return radeon;
 }
 
@@ -153,47 +155,3 @@ struct radeon *radeon_decref(struct radeon *radeon)
        free(radeon);
        return NULL;
 }
-
-int radeon_reg_id(struct radeon *radeon, unsigned offset, unsigned *typeid, unsigned *stateid, unsigned *id)
-{
-       unsigned i, j;
-
-       for (i = 0; i < radeon->ntype; i++) {
-               if (radeon->type[i].range_start) {
-                       if (offset >= radeon->type[i].range_start && offset < radeon->type[i].range_end) {
-                               *typeid = i;
-                               j = offset - radeon->type[i].range_start;
-                               j /= radeon->type[i].stride;
-                               *stateid = radeon->type[i].id + j;
-                               *id = (offset - radeon->type[i].range_start - radeon->type[i].stride * j) / 4;
-                               return 0;
-                       }
-               } else {
-                       for (j = 0; j < radeon->type[i].nstates; j++) {
-                               if (radeon->type[i].regs[j].offset == offset) {
-                                       *typeid = i;
-                                       *stateid = radeon->type[i].id;
-                                       *id = j;
-                                       return 0;
-                               }
-                       }
-               }
-       }
-       fprintf(stderr, "%s unknown register 0x%08X\n", __func__, offset);
-       return -EINVAL;
-}
-
-unsigned radeon_type_from_id(struct radeon *radeon, unsigned id)
-{
-       unsigned i;
-
-       for (i = 0; i < radeon->ntype - 1; i++) {
-               if (radeon->type[i].id == id)
-                       return i;
-               if (id > radeon->type[i].id && id < radeon->type[i + 1].id)
-                       return i;
-       }
-       if (radeon->type[i].id == id)
-               return i;
-       return -1;
-}
index f259ae7fb57dfae04fc1f93bbbf6da9bad8f1609..a1306f6e9d2f077799d9441b9aa744122017cbaf 100644 (file)
@@ -145,7 +145,9 @@ struct radeon_bo *radeon_bo_decref(struct radeon *radeon, struct radeon_bo *bo)
                return NULL;
        }
 
-       munmap(bo->data, bo->size);
+       if (bo->map_count) {
+               munmap(bo->data, bo->size);
+       }
        memset(&args, 0, sizeof(args));
        args.handle = bo->handle;
        drmIoctl(radeon->fd, DRM_IOCTL_GEM_CLOSE, &args);
index 45b706bb0f966d3df37975158218c523afadab88..47fca76136825902c0b774b0f0854a7a260acc17 100644 (file)
 #include "radeon_drm.h"
 #include "bof.h"
 
-int radeon_ctx_set_bo_new(struct radeon_ctx *ctx, struct radeon_bo *bo)
+static int radeon_ctx_set_bo_new(struct radeon_ctx *ctx, struct radeon_bo *bo)
 {
-       void *ptr;
-
-       ptr = realloc(ctx->bo, sizeof(struct radeon_bo) * (ctx->nbo + 1));
-       if (ptr == NULL) {
-               return -ENOMEM;
-       }
-       ctx->bo = ptr;
+       if (ctx->nbo >= RADEON_CTX_MAX_PM4)
+               return -EBUSY;
        ctx->bo[ctx->nbo] = bo;
        ctx->nbo++;
        return 0;
 }
 
-struct radeon_bo *radeon_ctx_get_bo(struct radeon_ctx *ctx, unsigned reloc)
+static struct radeon_bo *radeon_ctx_get_bo(struct radeon_ctx *ctx, unsigned reloc)
 {
        struct radeon_cs_reloc *greloc;
        unsigned i;
@@ -59,7 +54,7 @@ struct radeon_bo *radeon_ctx_get_bo(struct radeon_ctx *ctx, unsigned reloc)
        return NULL;
 }
 
-void radeon_ctx_get_placement(struct radeon_ctx *ctx, unsigned reloc, u32 *placement)
+static void radeon_ctx_get_placement(struct radeon_ctx *ctx, unsigned reloc, u32 *placement)
 {
        struct radeon_cs_reloc *greloc;
        unsigned i;
@@ -76,50 +71,57 @@ void radeon_ctx_get_placement(struct radeon_ctx *ctx, unsigned reloc, u32 *place
        }
 }
 
-struct radeon_ctx *radeon_ctx(struct radeon *radeon)
+void radeon_ctx_clear(struct radeon_ctx *ctx)
 {
-       struct radeon_ctx *ctx;
-
-       if (radeon == NULL)
-               return NULL;
-       ctx = calloc(1, sizeof(*ctx));
-       if (ctx == NULL)
-               return NULL;
-       ctx->radeon = radeon_incref(radeon);
-       return ctx;
+       for (int i = 0; i < ctx->nbo; i++) {
+               ctx->bo[i] = radeon_bo_decref(ctx->radeon, ctx->bo[i]);
+       }
+       ctx->ndwords = RADEON_CTX_MAX_PM4;
+       ctx->cdwords = 0;
+       ctx->nreloc = 0;
+       ctx->nbo = 0;
 }
 
-struct radeon_ctx *radeon_ctx_incref(struct radeon_ctx *ctx)
+int radeon_ctx_init(struct radeon_ctx *ctx, struct radeon *radeon)
 {
-       ctx->refcount++;
-       return ctx;
+       if (radeon == NULL)
+               return -EINVAL;
+       memset(ctx, 0, sizeof(struct radeon_ctx));
+       ctx->radeon = radeon_incref(radeon);
+       radeon_ctx_clear(ctx);
+       ctx->pm4 = malloc(RADEON_CTX_MAX_PM4 * 4);
+       if (ctx->pm4 == NULL) {
+               radeon_ctx_fini(ctx);
+               return -ENOMEM;
+       }
+       ctx->reloc = malloc(sizeof(struct radeon_cs_reloc) * RADEON_CTX_MAX_PM4);
+       if (ctx->reloc == NULL) {
+               radeon_ctx_fini(ctx);
+               return -ENOMEM;
+       }
+       ctx->bo = malloc(sizeof(void *) * RADEON_CTX_MAX_PM4);
+       if (ctx->bo == NULL) {
+               radeon_ctx_fini(ctx);
+               return -ENOMEM;
+       }
+       return 0;
 }
 
-struct radeon_ctx *radeon_ctx_decref(struct radeon_ctx *ctx)
+void radeon_ctx_fini(struct radeon_ctx *ctx)
 {
        unsigned i;
 
        if (ctx == NULL)
-               return NULL;
-       if (--ctx->refcount > 0) {
-               return NULL;
-       }
+               return;
 
-       for (i = 0; i < ctx->ndraw; i++) {
-               ctx->draw[i] = radeon_draw_decref(ctx->draw[i]);
-       }
        for (i = 0; i < ctx->nbo; i++) {
                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);
        free(ctx->reloc);
-       memset(ctx, 0, sizeof(*ctx));
-       free(ctx);
-       return NULL;
+       memset(ctx, 0, sizeof(struct radeon_ctx));
 }
 
 static int radeon_ctx_state_bo(struct radeon_ctx *ctx, struct radeon_state *state)
@@ -152,17 +154,17 @@ int radeon_ctx_submit(struct radeon_ctx *ctx)
        uint64_t chunk_array[2];
        int r = 0;
 
-       if (!ctx->cpm4)
+       if (!ctx->cdwords)
                return 0;
 #if 0
-       for (r = 0; r < ctx->cpm4; r++) {
+       for (r = 0; r < ctx->cdwords; r++) {
                fprintf(stderr, "0x%08X\n", ctx->pm4[r]);
        }
 #endif
        drmib.num_chunks = 2;
        drmib.chunks = (uint64_t)(uintptr_t)chunk_array;
        chunks[0].chunk_id = RADEON_CHUNK_ID_IB;
-       chunks[0].length_dw = ctx->cpm4;
+       chunks[0].length_dw = ctx->cdwords;
        chunks[0].chunk_data = (uint64_t)(uintptr_t)ctx->pm4;
        chunks[1].chunk_id = RADEON_CHUNK_ID_RELOCS;
        chunks[1].length_dw = ctx->nreloc * sizeof(struct radeon_cs_reloc) / 4;
@@ -180,7 +182,6 @@ static int radeon_ctx_reloc(struct radeon_ctx *ctx, struct radeon_bo *bo,
                        unsigned id, unsigned *placement)
 {
        unsigned i;
-       struct radeon_cs_reloc *ptr;
 
        for (i = 0; i < ctx->nreloc; i++) {
                if (ctx->reloc[i].handle == bo->handle) {
@@ -188,14 +189,13 @@ static int radeon_ctx_reloc(struct radeon_ctx *ctx, struct radeon_bo *bo,
                        return 0;
                }
        }
-       ptr = realloc(ctx->reloc, sizeof(struct radeon_cs_reloc) * (ctx->nreloc + 1));
-       if (ptr == NULL)
-               return -ENOMEM;
-       ctx->reloc = ptr;
-       ptr[ctx->nreloc].handle = bo->handle;
-       ptr[ctx->nreloc].read_domain = placement[0] | placement [1];
-       ptr[ctx->nreloc].write_domain = placement[0] | placement [1];
-       ptr[ctx->nreloc].flags = 0;
+       if (ctx->nreloc >= RADEON_CTX_MAX_PM4) {
+               return -EBUSY;
+       }
+       ctx->reloc[ctx->nreloc].handle = bo->handle;
+       ctx->reloc[ctx->nreloc].read_domain = placement[0] | placement [1];
+       ctx->reloc[ctx->nreloc].write_domain = placement[0] | placement [1];
+       ctx->reloc[ctx->nreloc].flags = 0;
        ctx->pm4[id] = ctx->nreloc * sizeof(struct radeon_cs_reloc) / 4;
        ctx->nreloc++;
        return 0;
@@ -208,97 +208,80 @@ static int radeon_ctx_state_schedule(struct radeon_ctx *ctx, struct radeon_state
 
        if (state == NULL)
                return 0;
-       memcpy(&ctx->pm4[ctx->id], state->pm4, state->cpm4 * 4);
+       if (state->cpm4 > ctx->ndwords) {
+               return -EBUSY;
+       }
+       memcpy(&ctx->pm4[ctx->cdwords], state->pm4, state->cpm4 * 4);
        for (i = 0; i < state->nreloc; i++) {
                rid = state->reloc_pm4_id[i];
                bid = state->reloc_bo_id[i];
-               cid = ctx->id + rid;
+               cid = ctx->cdwords + rid;
                r = radeon_ctx_reloc(ctx, state->bo[bid], cid,
                                        &state->placement[bid * 2]);
                if (r) {
-                       fprintf(stderr, "%s state %d failed to reloc\n", __func__, state->type);
+                       fprintf(stderr, "%s state %d failed to reloc\n", __func__, state->stype->stype);
                        return r;
                }
        }
-       ctx->id += state->cpm4;
+       ctx->cdwords += state->cpm4;
+       ctx->ndwords -= state->cpm4;
        return 0;
 }
 
-int radeon_ctx_set_draw_new(struct radeon_ctx *ctx, struct radeon_draw *draw)
+int radeon_ctx_set_query_state(struct radeon_ctx *ctx, struct radeon_state *state)
 {
-       struct radeon_draw *pdraw = NULL;
-       struct radeon_draw **ndraw;
-       struct radeon_state *nstate, *ostate;
-       unsigned cpm4, i, cstate;
-       void *tmp;
        int r = 0;
 
-       ndraw = realloc(ctx->draw, sizeof(void*) * (ctx->ndraw + 1));
-       if (ndraw == NULL)
-               return -ENOMEM;
-       ctx->draw = ndraw;
-       for (i = 0; i < draw->nstate; i++) {
-               r = radeon_ctx_state_bo(ctx, draw->state[i]);
-               if (r)
-                       return r;
-       }
-       r = radeon_draw_check(draw);
+       /* !!! ONLY ACCEPT QUERY STATE HERE !!! */
+       r = radeon_state_pm4(state);
        if (r)
                return r;
-       if (draw->cpm4 >= RADEON_CTX_MAX_PM4) {
-               fprintf(stderr, "%s single draw too big %d, max %d\n",
-                       __func__, draw->cpm4, RADEON_CTX_MAX_PM4);
+       /* BEGIN/END query are balanced in the same cs so account for END
+        * END query when scheduling BEGIN query
+        */
+       switch (state->stype->stype) {
+       case R600_STATE_QUERY_BEGIN:
+               /* is there enough place for begin & end */
+               if ((state->cpm4 * 2) > ctx->ndwords)
+                       return -EBUSY;
+               ctx->ndwords -= state->cpm4;
+               break;
+       case R600_STATE_QUERY_END:
+               ctx->ndwords += state->cpm4;
+               break;
+       default:
                return -EINVAL;
        }
-       tmp = realloc(ctx->state, (ctx->nstate + draw->nstate) * sizeof(void*));
-       if (tmp == NULL)
-               return -ENOMEM;
-       ctx->state = tmp;
-       pdraw = ctx->cdraw;
-       for (i = 0, cpm4 = 0, cstate = ctx->nstate; i < draw->nstate - 1; i++) {
-               nstate = draw->state[i];
-               if (nstate) {
-                       if (pdraw && pdraw->state[i]) {
-                               ostate = pdraw->state[i];
-                               if (ostate->pm4_crc != nstate->pm4_crc) {
-                                       ctx->state[cstate++] = nstate;
-                                       cpm4 += nstate->cpm4;
-                               }
-                       } else {
-                               ctx->state[cstate++] = nstate;
-                               cpm4 += nstate->cpm4;
-                       }
-               }
-       }
-       /* The last state is the draw state always add it */
-       if (draw->state[i] == NULL) {
-               fprintf(stderr, "%s no draw command\n", __func__);
-               return -EINVAL;
-       }
-       ctx->state[cstate++] = draw->state[i];
-       cpm4 += draw->state[i]->cpm4;
-       if ((ctx->draw_cpm4 + cpm4) > RADEON_CTX_MAX_PM4) {
-               /* need to flush */
-               return -EBUSY;
-       }
-       ctx->draw_cpm4 += cpm4;
-       ctx->nstate = cstate;
-       ctx->draw[ctx->ndraw++] = draw;
-       ctx->cdraw = draw;
-       return 0;
+       return radeon_ctx_state_schedule(ctx, state);
 }
 
 int radeon_ctx_set_draw(struct radeon_ctx *ctx, struct radeon_draw *draw)
 {
-       int r;
+       unsigned previous_cdwords;
+       int r = 0;
 
-       radeon_draw_incref(draw);
-       r = radeon_ctx_set_draw_new(ctx, draw);
-       if (r)
-               radeon_draw_decref(draw);
-       return r;
+       for (int i = 0; i < (ctx->radeon->nstate_per_shader * R600_SHADER_MAX); i++) {
+               r = radeon_ctx_state_bo(ctx, draw->state[i]);
+               if (r)
+                       return r;
+       }
+       previous_cdwords = ctx->cdwords;
+       for (int i = 0, id = 0; i < ctx->radeon->nstate_per_shader; i++) {
+               for (int j = 0; j < R600_SHADER_MAX; j++) {
+                       id = j * ctx->radeon->nstate_per_shader + i;
+                       if (draw->state[id]) {
+                               r = radeon_ctx_state_schedule(ctx, draw->state[id]);
+                               if (r) {
+                                       ctx->cdwords = previous_cdwords;
+                                       return r;
+                               }
+                       }
+               }
+       }
+       return 0;
 }
 
+#if 0
 int radeon_ctx_pm4(struct radeon_ctx *ctx)
 {
        unsigned i;
@@ -310,9 +293,6 @@ int radeon_ctx_pm4(struct radeon_ctx *ctx)
        if (ctx->pm4 == NULL)
                return -EINVAL;
        for (i = 0, ctx->id = 0; i < ctx->nstate; i++) {
-               r = radeon_ctx_state_schedule(ctx, ctx->state[i]);
-               if (r)
-                       return r;
        }
        if (ctx->id != ctx->draw_cpm4) {
                fprintf(stderr, "%s miss predicted pm4 size %d for %d\n",
@@ -322,6 +302,7 @@ int radeon_ctx_pm4(struct radeon_ctx *ctx)
        ctx->cpm4 = ctx->draw_cpm4;
        return 0;
 }
+#endif
 
 void radeon_ctx_dump_bof(struct radeon_ctx *ctx, const char *file)
 {
@@ -349,8 +330,8 @@ printf("%d relocs\n", ctx->nreloc);
        bof_decref(blob);
        blob = NULL;
        /* dump cs */
-printf("%d pm4\n", ctx->cpm4);
-       blob = bof_blob(ctx->cpm4 * 4, ctx->pm4);
+printf("%d pm4\n", ctx->cdwords);
+       blob = bof_blob(ctx->cdwords * 4, ctx->pm4);
        if (blob == NULL)
                goto out_err;
        if (bof_object_set(root, "pm4", blob))
@@ -366,7 +347,6 @@ printf("%d pm4\n", ctx->cpm4);
                if (bo == NULL)
                        goto out_err;
                size = bof_int32(ctx->bo[i]->size);
-printf("[%d] %d bo\n", i, size);
                if (size == NULL)
                        goto out_err;
                if (bof_object_set(bo, "size", size))
index 4413ed79fbdce95a64bb801408946f945c252803..b992c4a55dc5a9e81413b00f1b8b81924f527fbe 100644 (file)
 /*
  * draw functions
  */
-struct radeon_draw *radeon_draw(struct radeon *radeon)
+int radeon_draw_init(struct radeon_draw *draw, struct radeon *radeon)
 {
-       struct radeon_draw *draw;
-
-       draw = calloc(1, sizeof(*draw));
-       if (draw == NULL)
-               return NULL;
-       draw->nstate = radeon->nstate;
        draw->radeon = radeon;
-       draw->refcount = 1;
-       draw->state = calloc(1, sizeof(void*) * draw->nstate);
-       if (draw->state == NULL) {
-               free(draw);
-               return NULL;
-       }
-       return draw;
-}
-
-struct radeon_draw *radeon_draw_incref(struct radeon_draw *draw)
-{
-       draw->refcount++;
-       return draw;
-}
-
-struct radeon_draw *radeon_draw_decref(struct radeon_draw *draw)
-{
-       unsigned i;
-
-       if (draw == NULL)
-               return NULL;
-       if (--draw->refcount > 0)
-               return NULL;
-       for (i = 0; i < draw->nstate; i++) {
-               draw->state[i] = radeon_state_decref(draw->state[i]);
-       }
-       free(draw->state);
-       memset(draw, 0, sizeof(*draw));
-       free(draw);
-       return NULL;
-}
-
-int radeon_draw_set_new(struct radeon_draw *draw, struct radeon_state *state)
-{
-       if (state == NULL)
-               return 0;
-       if (state->type >= draw->radeon->ntype)
-               return -EINVAL;
-       draw->state[state->id] = radeon_state_decref(draw->state[state->id]);
-       draw->state[state->id] = state;
+       draw->state = calloc(radeon->nstate_per_shader * R600_SHADER_MAX, sizeof(void*));
+       if (draw->state == NULL)
+               return -ENOMEM;
        return 0;
 }
 
-int radeon_draw_set(struct radeon_draw *draw, struct radeon_state *state)
+void radeon_draw_bind(struct radeon_draw *draw, struct radeon_state *state)
 {
        if (state == NULL)
-               return 0;
-       radeon_state_incref(state);
-       return radeon_draw_set_new(draw, state);
+               return;
+       draw->state[state->state_id] = state;
 }
 
-int radeon_draw_check(struct radeon_draw *draw)
+void radeon_draw_unbind(struct radeon_draw *draw, struct radeon_state *state)
 {
-       unsigned i;
-       int r;
-
-       r = radeon_draw_pm4(draw);
-       if (r)
-               return r;
-       for (i = 0, draw->cpm4 = 0; i < draw->nstate; i++) {
-               if (draw->state[i]) {
-                       draw->cpm4 += draw->state[i]->cpm4;
-               }
-       }
-       return 0;
-}
-
-struct radeon_draw *radeon_draw_duplicate(struct radeon_draw *draw)
-{
-       struct radeon_draw *ndraw;
-       unsigned i;
-
-       if (draw == NULL)
-               return NULL;
-       ndraw = radeon_draw(draw->radeon);
-       if (ndraw == NULL) {
-               return NULL;
-       }
-       for (i = 0; i < draw->nstate; i++) {
-               if (radeon_draw_set(ndraw, draw->state[i])) {
-                       radeon_draw_decref(ndraw);
-                       return NULL;
-               }
-       }
-       return ndraw;
-}
-
-int radeon_draw_pm4(struct radeon_draw *draw)
-{
-       unsigned i;
-       int r;
-
-       for (i = 0; i < draw->nstate; i++) {
-               r = radeon_state_pm4(draw->state[i]);
-               if (r)
-                       return r;
+       if (state == NULL)
+               return;
+       if (draw->state[state->state_id] == state) {
+               draw->state[state->state_id] = NULL;
        }
-       return 0;
 }
index 96c0d060f7ea14c7662b52c5d696df004bcb70b7..84e552ba4d3b1c2b766a28c2f095e8bcc3b536d8 100644 (file)
@@ -37,17 +37,20 @@ struct radeon_register {
        char                            name[64];
 };
 
-struct radeon_type {
-       unsigned                        npm4;
-       unsigned                        id;
-       unsigned                        range_start;
-       unsigned                        range_end;
-       unsigned                        stride;
-       unsigned                        immediate;
-       char                            name[64];
+struct radeon_sub_type {
+       int                             shader_type;
+       const struct radeon_register    *regs;
        unsigned                        nstates;
+};
+
+struct radeon_stype_info {
+       unsigned                        stype;
+       unsigned                        num;
+       unsigned                        stride;
        radeon_state_pm4_t              pm4;
-       const struct radeon_register    *regs;
+       struct radeon_sub_type          reginfo[R600_SHADER_MAX];
+       unsigned                        base_id;
+       unsigned                        npm4;
 };
 
 struct radeon {
@@ -55,9 +58,10 @@ struct radeon {
        int                             refcount;
        unsigned                        device;
        unsigned                        family;
-       unsigned                        nstate;
-       unsigned                        ntype;
-       const struct radeon_type        *type;
+       unsigned                        nstype;
+       unsigned                        nstate_per_shader;
+       unsigned                        *state_type_id;
+       struct radeon_stype_info        *stype;
 };
 
 extern struct radeon *radeon_new(int fd, unsigned device);
@@ -65,15 +69,6 @@ extern struct radeon *radeon_incref(struct radeon *radeon);
 extern struct radeon *radeon_decref(struct radeon *radeon);
 extern unsigned radeon_family_from_device(unsigned device);
 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);
-
-
-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);
-void radeon_ctx_get_placement(struct radeon_ctx *ctx, unsigned reloc, u32 *placement);
-int radeon_ctx_set_draw_new(struct radeon_ctx *ctx, struct radeon_draw *draw);
-int radeon_ctx_draw(struct radeon_ctx *ctx);
 
 /*
  * r600/r700 context functions
index 308288557a48d79fad28dc13a4fe8113494faf06..ac60485b280fd2df4d2d89067a406941954076ec 100644 (file)
 /*
  * state core functions
  */
-struct radeon_state *radeon_state(struct radeon *radeon, u32 type, u32 id)
+int radeon_state_init(struct radeon_state *state, struct radeon *radeon, u32 stype, u32 id, u32 shader_type)
 {
-       struct radeon_state *state;
+       struct radeon_stype_info *found = NULL;
+       int i, j, shader_index = -1;
 
-       if (type > radeon->ntype) {
-               fprintf(stderr, "%s invalid type %d\n", __func__, type);
-               return NULL;
+       /* traverse the stype array */
+       for (i = 0; i < radeon->nstype; i++) {
+               /* if the type doesn't match, if the shader doesn't match */
+               if (stype != radeon->stype[i].stype)
+                       continue;
+               if (shader_type) {
+                       for (j = 0; j < 4; j++) {
+                               if (radeon->stype[i].reginfo[j].shader_type == shader_type) {
+                                       shader_index = j;
+                                       break;
+                               }
+                       }
+                       if (shader_index == -1)
+                               continue;
+               } else {
+                       if (radeon->stype[i].reginfo[0].shader_type)
+                               continue;
+                       else
+                               shader_index = 0;
+               }
+               if (id > radeon->stype[i].num)
+                       continue;
+               
+               found = &radeon->stype[i];
+               break;
        }
-       if (id > radeon->nstate) {
-               fprintf(stderr, "%s invalid state id %d\n", __func__, id);
-               return NULL;
+
+       if (!found) {
+               fprintf(stderr, "%s invalid type %d/id %d/shader class %d\n", __func__, stype, id, shader_type);
+               return -EINVAL;
        }
-       state = calloc(1, sizeof(*state));
-       if (state == NULL)
-               return NULL;
+
+       memset(state, 0, sizeof(struct radeon_state));
+       state->state_id = radeon->nstate_per_shader * shader_index + radeon->state_type_id[stype] + id;
+       state->stype = found;
        state->radeon = radeon;
-       state->type = type;
        state->id = id;
+       state->shader_index = shader_index;
        state->refcount = 1;
-       state->npm4 = radeon->type[type].npm4;
-       state->nstates = radeon->type[type].nstates;
-       state->states = calloc(1, state->nstates * 4);
-       state->pm4 = calloc(1, radeon->type[type].npm4 * 4);
-       if (state->states == NULL || state->pm4 == NULL) {
-               radeon_state_decref(state);
-               return NULL;
-       }
-       return state;
+       state->npm4 = found->npm4;
+       state->nstates = found->reginfo[shader_index].nstates;
+       return 0;
 }
 
-struct radeon_state *radeon_state_duplicate(struct radeon_state *state)
+int radeon_state_convert(struct radeon_state *state, u32 stype, u32 id, u32 shader_type)
 {
-       struct radeon_state *nstate = radeon_state(state->radeon, state->type, state->id);
-       unsigned i;
+       struct radeon_stype_info *found = NULL;
+       int i, j, shader_index = -1;
 
        if (state == NULL)
-               return NULL;
-       nstate->cpm4 = state->cpm4;
-       nstate->nbo = state->nbo;
-       nstate->nreloc = state->nreloc;
-       memcpy(nstate->states, state->states, state->nstates * 4);
-       memcpy(nstate->pm4, state->pm4, state->npm4 * 4);
-       memcpy(nstate->placement, state->placement, 8 * 4);
-       memcpy(nstate->reloc_pm4_id, state->reloc_pm4_id, 8 * 4);
-       memcpy(nstate->reloc_bo_id, state->reloc_bo_id, 8 * 4);
-       memcpy(nstate->bo_dirty, state->bo_dirty, 4 * 4);
-       for (i = 0; i < state->nbo; i++) {
-               nstate->bo[i] = radeon_bo_incref(state->radeon, state->bo[i]);
+               return 0;
+       /* traverse the stype array */
+       for (i = 0; i < state->radeon->nstype; i++) {
+               /* if the type doesn't match, if the shader doesn't match */
+               if (stype != state->radeon->stype[i].stype)
+                       continue;
+               if (shader_type) {
+                       for (j = 0; j < 4; j++) {
+                               if (state->radeon->stype[i].reginfo[j].shader_type == shader_type) {
+                                       shader_index = j;
+                                       break;
+                               }
+                       }
+                       if (shader_index == -1)
+                               continue;
+               } else {
+                       if (state->radeon->stype[i].reginfo[0].shader_type)
+                               continue;
+                       else
+                               shader_index = 0;
+               }
+               if (id > state->radeon->stype[i].num)
+                       continue;
+               
+               found = &state->radeon->stype[i];
+               break;
        }
-       return nstate;
-}
 
-struct radeon_state *radeon_state_incref(struct radeon_state *state)
-{
-       state->refcount++;
-       return state;
+       if (!found) {
+               fprintf(stderr, "%s invalid type %d/id %d/shader class %d\n", __func__, stype, id, shader_type);
+               return -EINVAL;
+       }
+
+       if (found->reginfo[shader_index].nstates != state->nstates) {
+               fprintf(stderr, "invalid type change from (%d %d %d) to (%d %d %d)\n",
+                       state->stype->stype, state->id, state->shader_index, stype, id, shader_index);
+       }
+
+       state->stype = found;
+       state->id = id;
+       state->shader_index = shader_index;
+       state->state_id = state->radeon->nstate_per_shader * shader_index + state->radeon->state_type_id[stype] + id;
+       return radeon_state_pm4(state);
 }
 
-struct radeon_state *radeon_state_decref(struct radeon_state *state)
+void radeon_state_fini(struct radeon_state *state)
 {
        unsigned i;
 
        if (state == NULL)
                return NULL;
-       if (--state->refcount > 0) {
-               return NULL;
-       }
        for (i = 0; i < state->nbo; i++) {
                state->bo[i] = radeon_bo_decref(state->radeon, state->bo[i]);
        }
-       free(state->immd);
-       free(state->states);
-       free(state->pm4);
-       memset(state, 0, sizeof(*state));
-       free(state);
-       return NULL;
+       memset(state, 0, sizeof(struct radeon_state));
 }
 
 int radeon_state_replace_always(struct radeon_state *ostate,
@@ -147,12 +181,13 @@ int radeon_state_pm4(struct radeon_state *state)
 {
        int r;
 
-       if (state == NULL || state->cpm4)
+       if (state == NULL)
                return 0;
-       r = state->radeon->type[state->type].pm4(state);
+       state->cpm4 = 0;
+       r = state->stype->pm4(state);
        if (r) {
                fprintf(stderr, "%s failed to build PM4 for state(%d %d)\n",
-                       __func__, state->type, state->id);
+                       __func__, state->stype->stype, state->id);
                return r;
        }
        state->pm4_crc = crc32(state->pm4, state->cpm4 * 4);
index b997abda9b0724dd8f394d79fd844b55893f5ed9..3a76098b655b223c6c586cffb3ab56f258d82e22 100644 (file)
@@ -52,6 +52,7 @@ struct wrapper_sw_winsys
    struct sw_winsys base;
    struct pipe_screen *screen;
    struct pipe_context *pipe;
+   enum pipe_texture_target target;
 };
 
 struct wrapper_sw_displaytarget
@@ -145,7 +146,7 @@ wsw_dt_create(struct sw_winsys *ws,
     * XXX Why don't we just get the template.
     */
    memset(&templ, 0, sizeof(templ));
-   templ.target = PIPE_TEXTURE_2D;
+   templ.target = wsw->target;
    templ.width0 = width;
    templ.height0 = height;
    templ.format = format;
@@ -291,6 +292,11 @@ wrapper_sw_winsys_warp_pipe_screen(struct pipe_screen *screen)
    if (!wsw->pipe)
       goto err_free;
 
+   if(screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES))
+      wsw->target = PIPE_TEXTURE_2D;
+   else
+      wsw->target = PIPE_TEXTURE_RECT;
+
    return &wsw->base;
 
 err_free:
diff --git a/src/glsl/.dir-locals.el b/src/glsl/.dir-locals.el
new file mode 100644 (file)
index 0000000..be19e29
--- /dev/null
@@ -0,0 +1,3 @@
+((c-mode . ((c-basic-offset . 3)))
+ (c++-mode . ((c-basic-offset . 3)))
+)
diff --git a/src/glsl/.gitignore b/src/glsl/.gitignore
new file mode 100644 (file)
index 0000000..4c21231
--- /dev/null
@@ -0,0 +1,2 @@
+glsl_compiler
+glsl_parser.output
index ca7f2d2ac7d1c9985de5d3366dad43146c8dc857..aedca0f0d15d13787054e11a26bce90e42ca8344 100644 (file)
-# src/glsl/Makefile
+#src/glsl/pp/Makefile
 
 TOP = ../..
 
 include $(TOP)/configs/current
 
-SUBDIRS = pp cl apps
+LIBNAME = glsl
 
-default install clean:
-       @for dir in $(SUBDIRS) ; do \
-               if [ -d $$dir ] ; then \
-                       (cd $$dir && $(MAKE) $@) || exit 1; \
-               fi \
-       done
+LIBGLCPP_SOURCES = \
+       glcpp/glcpp-lex.c \
+       glcpp/glcpp-parse.c \
+       glcpp/pp.c
 
+GLCPP_SOURCES = \
+       $(LIBGLCPP_SOURCES) \
+       glcpp/glcpp.c
+
+C_SOURCES = \
+       $(LIBGLCPP_SOURCES)
+
+CXX_SOURCES = \
+       ast_expr.cpp \
+       ast_function.cpp \
+       ast_to_hir.cpp \
+       ast_type.cpp \
+       builtin_function.cpp \
+       glsl_lexer.cpp \
+       glsl_parser.cpp \
+       glsl_parser_extras.cpp \
+       glsl_types.cpp \
+       glsl_symbol_table.cpp \
+       hir_field_selection.cpp \
+       ir_algebraic.cpp \
+       ir_basic_block.cpp \
+       ir_clone.cpp \
+       ir_constant_expression.cpp \
+       ir_constant_folding.cpp \
+       ir_constant_propagation.cpp \
+       ir_constant_variable.cpp \
+       ir_copy_propagation.cpp \
+       ir.cpp \
+       ir_dead_code.cpp \
+       ir_dead_code_local.cpp \
+       ir_dead_functions.cpp \
+       ir_div_to_mul_rcp.cpp \
+       ir_explog_to_explog2.cpp \
+       ir_expression_flattening.cpp \
+       ir_function_can_inline.cpp \
+       ir_function.cpp \
+       ir_function_inlining.cpp \
+       ir_hierarchical_visitor.cpp \
+       ir_hv_accept.cpp \
+       ir_if_return.cpp \
+       ir_if_simplification.cpp \
+       ir_if_to_cond_assign.cpp \
+       ir_import_prototypes.cpp \
+       ir_mat_op_to_vec.cpp \
+       ir_mod_to_fract.cpp \
+       ir_noop_swizzle.cpp \
+       ir_print_visitor.cpp \
+       ir_reader.cpp \
+       ir_rvalue_visitor.cpp \
+       ir_set_program_inouts.cpp \
+       ir_structure_splitting.cpp \
+       ir_sub_to_add_neg.cpp \
+       ir_swizzle_swizzle.cpp \
+       ir_tree_grafting.cpp \
+       ir_validate.cpp \
+       ir_variable.cpp \
+       ir_variable_refcount.cpp \
+       ir_vec_index_to_cond_assign.cpp \
+       ir_vec_index_to_swizzle.cpp \
+       linker.cpp \
+       link_functions.cpp \
+       s_expression.cpp
+
+LIBS = \
+       $(TOP)/src/glsl/libglsl.a \
+       $(TALLOC_LIBS)
+
+APPS = glsl_compiler glcpp/glcpp
+
+GLSL2_C_SOURCES = \
+       ../mesa/program/hash_table.c \
+       ../mesa/program/symbol_table.c
+GLSL2_CXX_SOURCES = \
+       main.cpp
+
+GLSL2_OBJECTS = \
+       $(GLSL2_C_SOURCES:.c=.o) \
+       $(GLSL2_CXX_SOURCES:.cpp=.o)
+
+### Basic defines ###
+
+DEFINES += \
+       $(LIBRARY_DEFINES) \
+       $(API_DEFINES)
+
+GLCPP_OBJECTS = \
+       $(GLCPP_SOURCES:.c=.o) \
+       ../mesa/program/hash_table.o
+
+OBJECTS = \
+       $(C_SOURCES:.c=.o) \
+       $(CXX_SOURCES:.cpp=.o)
+
+INCLUDES = \
+       $(TALLOC_CFLAGS) \
+       -I. \
+       -I../mesa \
+       -I../mapi \
+       -I../../include \
+       $(LIBRARY_INCLUDES)
+
+ALL_SOURCES = \
+       $(C_SOURCES) \
+       $(CXX_SOURCES) \
+       $(GLSL2_CXX_SOURCES) \
+       $(GLSL2_C_SOURCES)
+
+##### TARGETS #####
+
+default: depend lib$(LIBNAME).a $(APPS)
+
+lib$(LIBNAME).a: $(OBJECTS) Makefile $(TOP)/src/glsl/Makefile.template
+       $(MKLIB) -cplusplus -o $(LIBNAME) -static $(OBJECTS)
+
+depend: $(ALL_SOURCES) Makefile
+       rm -f depend
+       touch depend
+       $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(ALL_SOURCES) 2> /dev/null
+
+# Remove .o and backup files
+clean:
+       rm -f $(GLCPP_OBJECTS) $(GLSL2_OBJECTS) $(OBJECTS) lib$(LIBNAME).a depend depend.bak
+       -rm -f $(APPS)
+
+# Dummy target
+install:
+       @echo -n ""
+
+
+##### RULES #####
+
+glsl_compiler: $(GLSL2_OBJECTS) libglsl.a
+       $(APP_CXX) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(GLSL2_OBJECTS) $(LIBS) -o $@
+
+glcpp/glcpp: $(GLCPP_OBJECTS) libglsl.a
+       $(APP_CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(GLCPP_OBJECTS) $(LIBS) -o $@
+
+.cpp.o:
+       $(CXX) -c $(INCLUDES) $(CXXFLAGS) $(DEFINES) $< -o $@
+
+.c.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+glsl_lexer.cpp: glsl_lexer.lpp
+       flex --nounistd -o$@  $<
+
+glsl_parser.cpp: glsl_parser.ypp
+       bison -v -o "$@" -p "_mesa_glsl_" --defines=glsl_parser.h $<
+
+glcpp/glcpp-lex.c: glcpp/glcpp-lex.l
+       flex --nounistd -o$@  $<
+
+glcpp/glcpp-parse.c: glcpp/glcpp-parse.y
+       bison -v -o "$@" --defines=glcpp/glcpp-parse.h $<
+
+builtins: builtin_function.cpp builtins/profiles/* builtins/ir/* builtins/tools/generate_builtins.py builtins/tools/texture_builtins.py
+       @echo Bootstrapping the compiler...
+       cp builtins/tools/builtin_function.cpp .
+       make glsl_compiler
+       @echo Regenerating builtin_function.cpp...
+       ./builtins/tools/generate_builtins.py > builtin_function.cpp
+       @echo Rebuilding the real compiler...
+       make glsl_compiler
+
+-include depend
diff --git a/src/glsl/Makefile.am b/src/glsl/Makefile.am
new file mode 100644 (file)
index 0000000..5728a8b
--- /dev/null
@@ -0,0 +1,75 @@
+# Copyright Â© 2010 Intel Corporation
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+# AUTHORS, COPYRIGHT HOLDERS, 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.
+
+AUTOMAKE_OPTIONS = foreign
+AM_CPPFLAGS = -I mesa
+
+SUBDIRS = glcpp
+
+bin_PROGRAMS = glsl
+
+glsl_LDADD = ./glcpp/libglcpp.la
+glsl_LDFLAGS = @LDFLAGS@ $(talloc_LIBS)
+glsl_SOURCES = \
+       main.cpp \
+       builtin_types.h \
+       glsl_types.cpp \
+       glsl_parser.ypp glsl_lexer.lpp glsl_parser_extras.cpp \
+       ast_expr.cpp ast_to_hir.cpp ast_function.cpp ast_type.cpp \
+       ir.cpp hir_field_selection.cpp builtin_function.cpp \
+       ir_print_visitor.cpp ir_variable.cpp ir_function.cpp \
+       ir_basic_block.cpp \
+       ir_basic_block.h \
+       ir_clone.cpp \
+       ir_constant_expression.cpp \
+       ir_constant_folding.cpp \
+       ir_constant_variable.cpp \
+       ir_copy_propagation.cpp \
+       ir_copy_propagation.h \
+       ir_dead_code.cpp \
+       ir_dead_code.h \
+       ir_dead_code_local.cpp \
+       ir_expression_flattening.cpp \
+       ir_function_can_inline.cpp \
+       ir_function_inlining.cpp \
+       ir_if_simplification.cpp \
+       ir_optimization.h \
+       ir_reader.cpp s_expression.cpp \
+       ir_hv_accept.cpp \
+       ir_hierarchical_visitor.h \
+       ir_hierarchical_visitor.cpp \
+       ir_swizzle_swizzle.cpp \
+       ir_to_mesa.cpp \
+       ir_to_mesa.h \
+       ir_validate.cpp \
+       ir_vec_index_to_swizzle.cpp \
+       linker.cpp
+
+BUILT_SOURCES = glsl_parser.h glsl_parser.cpp glsl_lexer.cpp
+CLEANFILES = $(BUILT_SOURCES)
+
+builtin_function.cpp: builtins/*/*
+       ./builtins/tools/generate_builtins.pl > builtin_function.cpp
+glsl_parser.h: glsl_parser.cpp
+
+.lpp.cpp:
+       $(LEXCOMPILE) --outfile="$@" $<
diff --git a/src/glsl/README b/src/glsl/README
new file mode 100644 (file)
index 0000000..2e501d6
--- /dev/null
@@ -0,0 +1,191 @@
+Welcome to Mesa's GLSL compiler.  A brief overview of how things flow:
+
+1) lex and yacc-based preprocessor takes the incoming shader string
+and produces a new string containing the preprocessed shader.  This
+takes care of things like #if, #ifdef, #define, and preprocessor macro
+invocations.  Note that #version, #extension, and some others are
+passed straight through.  See glcpp/*
+
+2) lex and yacc-based parser takes the preprocessed string and
+generates the AST (abstract syntax tree).  Almost no checking is
+performed in this stage.  See glsl_lexer.lpp and glsl_parser.ypp.
+
+3) The AST is converted to "HIR".  This is the intermediate
+representation of the compiler.  Constructors are generated, function
+calls are resolved to particular function signatures, and all the
+semantic checking is performed.  See ast_*.cpp for the conversion, and
+ir.h for the IR structures.
+
+4) The driver (Mesa, or main.cpp for the standalone binary) performs
+optimizations.  These include copy propagation, dead code elimination,
+constant folding, and others.  Generally the driver will call
+optimizations in a loop, as each may open up opportunities for other
+optimizations to do additional work.  See most files called ir_*.cpp
+
+5) linking is performed.  This does checking to ensure that the
+outputs of the vertex shader match the inputs of the fragment shader,
+and assigns locations to uniforms, attributes, and varyings.  See
+linker.cpp.
+
+6) The driver may perform additional optimization at this point, as
+for example dead code elimination previously couldn't remove functions
+or global variable usage when we didn't know what other code would be
+linked in.
+
+7) The driver performs code generation out of the IR, taking a linked
+shader program and producing a compiled program for each stage.  See
+ir_to_mesa.cpp for Mesa IR code generation.
+
+FAQ:
+
+Q: What is HIR versus IR versus LIR?
+
+A: The idea behind the naming was that ast_to_hir would produce a
+high-level IR ("HIR"), with things like matrix operations, structure
+assignments, etc., present.  A series of lowering passes would occur
+that do things like break matrix multiplication into a series of dot
+products/MADs, make structure assignment be a series of assignment of
+components, flatten if statements into conditional moves, and such,
+producing a low level IR ("LIR").
+
+However, it now appears that each driver will have different
+requirements from a LIR.  A 915-generation chipset wants all functions
+inlined, all loops unrolled, all ifs flattened, no variable array
+accesses, and matrix multiplication broken down.  The Mesa IR backend
+for swrast would like matrices and structure assignment broken down,
+but it can support function calls and dynamic branching.  A 965 vertex
+shader IR backend could potentially even handle some matrix operations
+without breaking them down, but the 965 fragment shader IR backend
+would want to break to have (almost) all operations down channel-wise
+and perform optimization on that.  As a result, there's no single
+low-level IR that will make everyone happy.  So that usage has fallen
+out of favor, and each driver will perform a series of lowering passes
+to take the HIR down to whatever restrictions it wants to impose
+before doing codegen.
+
+Q: How is the IR structured?
+
+A: The best way to get started seeing it would be to run the
+standalone compiler against a shader:
+
+./glsl_compiler --dump-lir \
+       ~/src/piglit/tests/shaders/glsl-orangebook-ch06-bump.frag
+
+So for example one of the ir_instructions in main() contains:
+
+(assign (constant bool (1)) (var_ref litColor)  (expression vec3 * (var_ref Surf
+aceColor) (var_ref __retval) ) )
+
+Or more visually:
+                     (assign)
+                 /       |        \
+        (var_ref)  (expression *)  (constant bool 1)
+         /          /           \
+(litColor)      (var_ref)    (var_ref)
+                  /                  \
+           (SurfaceColor)          (__retval)
+
+which came from:
+
+litColor = SurfaceColor * max(dot(normDelta, LightDir), 0.0);
+
+(the max call is not represented in this expression tree, as it was a
+function call that got inlined but not brought into this expression
+tree)
+
+Each of those nodes is a subclass of ir_instruction.  A particular
+ir_instruction instance may only appear once in the whole IR tree with
+the exception of ir_variables, which appear once as variable
+declarations:
+
+(declare () vec3 normDelta)
+
+and multiple times as the targets of variable dereferences:
+...
+(assign (constant bool (1)) (var_ref __retval) (expression float dot
+ (var_ref normDelta) (var_ref LightDir) ) )
+...
+(assign (constant bool (1)) (var_ref __retval) (expression vec3 -
+ (var_ref LightDir) (expression vec3 * (constant float (2.000000))
+ (expression vec3 * (expression float dot (var_ref normDelta) (var_ref
+ LightDir) ) (var_ref normDelta) ) ) ) )
+...
+
+Each node has a type.  Expressions may involve several different types:
+(declare (uniform ) mat4 gl_ModelViewMatrix)
+((assign (constant bool (1)) (var_ref constructor_tmp) (expression
+ vec4 * (var_ref gl_ModelViewMatrix) (var_ref gl_Vertex) ) )
+
+An expression tree can be arbitrarily deep, and the compiler tries to
+keep them structured like that so that things like algebraic
+optimizations ((color * 1.0 == color) and ((mat1 * mat2) * vec == mat1
+* (mat2 * vec))) or recognizing operation patterns for code generation
+(vec1 * vec2 + vec3 == mad(vec1, vec2, vec3)) are easier.  This comes
+at the expense of additional trickery in implementing some
+optimizations like CSE where one must navigate an expression tree.
+
+Q: Why no SSA representation?
+
+A: Converting an IR tree to SSA form makes dead code elmimination,
+common subexpression elimination, and many other optimizations much
+easier.  However, in our primarily vector-based language, there's some
+major questions as to how it would work.  Do we do SSA on the scalar
+or vector level?  If we do it at the vector level, we're going to end
+up with many different versions of the variable when encountering code
+like:
+
+(assign (constant bool (1)) (swiz x (var_ref __retval) ) (var_ref a) ) 
+(assign (constant bool (1)) (swiz y (var_ref __retval) ) (var_ref b) ) 
+(assign (constant bool (1)) (swiz z (var_ref __retval) ) (var_ref c) ) 
+
+If every masked update of a component relies on the previous value of
+the variable, then we're probably going to be quite limited in our
+dead code elimination wins, and recognizing common expressions may
+just not happen.  On the other hand, if we operate channel-wise, then
+we'll be prone to optimizing the operation on one of the channels at
+the expense of making its instruction flow different from the other
+channels, and a vector-based GPU would end up with worse code than if
+we didn't optimize operations on that channel!
+
+Once again, it appears that our optimization requirements are driven
+significantly by the target architecture.  For now, targeting the Mesa
+IR backend, SSA does not appear to be that important to producing
+excellent code, but we do expect to do some SSA-based optimizations
+for the 965 fragment shader backend when that is developed.
+
+Q: How should I expand instructions that take multiple backend instructions?
+
+Sometimes you'll have to do the expansion in your code generation --
+see, for example, ir_to_mesa.cpp's handling of ir_binop_mul for
+matrices.  However, in many cases you'll want to do a pass over the IR
+to convert non-native instructions to a series of native instructions.
+For example, for the Mesa backend we have ir_div_to_mul_rcp.cpp because
+Mesa IR (and many hardware backends) only have a reciprocal
+instruction, not a divide.  Implementing non-native instructions this
+way gives the chance for constant folding to occur, so (a / 2.0)
+becomes (a * 0.5) after codegen instead of (a * (1.0 / 2.0))
+
+Q: How shoud I handle my special hardware instructions with respect to IR?
+
+Our current theory is that if multiple targets have an instruction for
+some operation, then we should probably be able to represent that in
+the IR.  Generally this is in the form of an ir_{bin,un}op expression
+type.  For example, we initially implemented fract() using (a -
+floor(a)), but both 945 and 965 have instructions to give that result,
+and it would also simplify the implementation of mod(), so
+ir_unop_fract was added.  The following areas need updating to add a
+new expression type:
+
+ir.h (new enum)
+ir.cpp:get_num_operands() (used for ir_reader)
+ir.cpp:operator_strs (used for ir_reader)
+ir_constant_expression.cpp (you probably want to be able to constant fold)
+ir_validate.cpp (check users have the right types)
+
+You may also need to update the backends if they will see the new expr type:
+
+../mesa/shaders/ir_to_mesa.cpp
+
+You can then use the new expression from builtins (if all backends
+would rather see it), or scan the IR and convert to use your new
+expression type (see ir_mod_to_fract, for example).
index 8e18626c4049d2b4ced0a0b31b2f7ef0a1cb9360..a808a5bc5d4dbe8a56a5618503f65431071bff8e 100644 (file)
@@ -4,23 +4,72 @@ Import('*')
 
 env = env.Clone()
 
+env.Prepend(CPPPATH = [
+    '#src/mapi',
+    '#src/mesa',
+])
+
+if env['platform'] == 'windows':
+    env.Prepend(CPPPATH = ['#src/talloc'])
+
 sources = [
-    'pp/sl_pp_context.c',
-    'pp/sl_pp_define.c',
-    'pp/sl_pp_dict.c',
-    'pp/sl_pp_error.c',
-    'pp/sl_pp_expression.c',
-    'pp/sl_pp_extension.c',
-    'pp/sl_pp_if.c',
-    'pp/sl_pp_line.c',
-    'pp/sl_pp_macro.c',
-    'pp/sl_pp_pragma.c',
-    'pp/sl_pp_process.c',
-    'pp/sl_pp_purify.c',
-    'pp/sl_pp_token.c',
-    'pp/sl_pp_token_util.c',
-    'pp/sl_pp_version.c',
-    'cl/sl_cl_parse.c',
+    'glcpp/glcpp-lex.c',
+    'glcpp/glcpp-parse.c',
+    'glcpp/pp.c',
+    'ast_expr.cpp',
+    'ast_function.cpp',
+    'ast_to_hir.cpp',
+    'ast_type.cpp',
+    'builtin_function.cpp',
+    'glsl_lexer.cpp',
+    'glsl_parser.cpp',
+    'glsl_parser_extras.cpp',
+    'glsl_types.cpp',
+    'glsl_symbol_table.cpp',
+    'hir_field_selection.cpp',
+    'ir_algebraic.cpp',
+    'ir_basic_block.cpp',
+    'ir_clone.cpp',
+    'ir_constant_expression.cpp',
+    'ir_constant_folding.cpp',
+    'ir_constant_propagation.cpp',
+    'ir_constant_variable.cpp',
+    'ir_copy_propagation.cpp',
+    'ir.cpp',
+    'ir_dead_code.cpp',
+    'ir_dead_code_local.cpp',
+    'ir_dead_functions.cpp',
+    'ir_div_to_mul_rcp.cpp',
+    'ir_explog_to_explog2.cpp',
+    'ir_expression_flattening.cpp',
+    'ir_function_can_inline.cpp',
+    'ir_function.cpp',
+    'ir_function_inlining.cpp',
+    'ir_hierarchical_visitor.cpp',
+    'ir_hv_accept.cpp',
+    'ir_if_return.cpp',
+    'ir_if_simplification.cpp',
+    'ir_if_to_cond_assign.cpp',
+    'ir_import_prototypes.cpp',
+    'ir_mat_op_to_vec.cpp',
+    'ir_mod_to_fract.cpp',
+    'ir_noop_swizzle.cpp',
+    'ir_print_visitor.cpp',
+    'ir_reader.cpp',
+    'ir_rvalue_visitor.cpp',
+    'ir_set_program_inouts.cpp',
+    'ir_structure_splitting.cpp',
+    'ir_sub_to_add_neg.cpp',
+    'ir_swizzle_swizzle.cpp',
+    'ir_tree_grafting.cpp',
+    'ir_validate.cpp',
+    'ir_variable.cpp',
+    'ir_variable_refcount.cpp',
+    'ir_vec_index_to_cond_assign.cpp',
+    'ir_vec_index_to_swizzle.cpp',
+    'linker.cpp',
+    'link_functions.cpp',
+    's_expression.cpp',
 ]
 
 glsl = env.ConvenienceLibrary(
@@ -30,6 +79,9 @@ glsl = env.ConvenienceLibrary(
 
 Export('glsl')
 
+# FIXME: We can't build the programs because there's a cyclic dependency between tis directory and src/mesa
+Return()
+
 env = env.Clone()
 
 if env['platform'] == 'windows':
@@ -37,33 +89,16 @@ if env['platform'] == 'windows':
         'user32',
     ])
 
-env.Prepend(LIBS = [glsl])
-
-env.Program(
-    target = 'purify',
-    source = ['apps/purify.c'],
-)
+env.Prepend(LIBS = [glsl, talloc])
 
 env.Program(
-    target = 'tokenise',
-    source = ['apps/tokenise.c'],
+    target = 'glsl2',
+    source = [
+        'main.cpp',
+    ]
 )
 
 env.Program(
-    target = 'version',
-    source = ['apps/version.c'],
+    target = 'glcpp',
+    source = ['glcpp/glcpp.c'],
 )
-
-env.Program(
-    target = 'process',
-    source = ['apps/process.c'],
-)
-
-glsl_compile = env.Program(
-    target = 'compile',
-    source = ['apps/compile.c'],
-)
-
-if env['platform'] == common.default_platform:
-    # Only export the GLSL compiler when building for the host platform
-    Export('glsl_compile')
diff --git a/src/glsl/TODO b/src/glsl/TODO
new file mode 100644 (file)
index 0000000..07ac5f5
--- /dev/null
@@ -0,0 +1,50 @@
+- Handle constant expressions of (struct == struct)
+
+- Handle constant expressions of (struct != struct)
+
+- Treat built-in functions with constant parameters as constant expressions.
+  - Rewrite all built-in functions return a single expression.
+  - Modify the HIR generator for functions to automatically inline built-in
+    functions durning translation.
+  - Care must be taken to handle both the 1.10 rules and the 1.20+ rules.  In
+    1.10, built-in functions cannot be constant expressions.
+
+- Detect code paths in non-void functions that don't reach a return statement
+
+- Handle over-riding built-in functions
+  - Is the overload per-compilation unit or per-linked shader?
+
+- Handle redeclaration of built-in variables
+  - Handle addition of qualifiers such as 'invariant' or 'centroid'.
+  - Handle resizing of arrays.
+  - Other?  We'll have to look at the spec.
+
+- Improve handling of constants and their initializers.  Constant initializers
+  should never generate any code.  This is trival for scalar constants.  It is
+  also trivial for arrays, matrices, and vectors that are accessed with
+  constant index values.  For others it is more complicated.  Perhaps these
+  cases should be silently converted to uniforms?
+
+1.30 features:
+
+- Implement AST-to-HIR conversion of bit-shift operators.
+
+- Implement AST-to-HIR conversion of bit-wise {&,|,^,!} operators.
+
+- Implement AST-to-HIR conversion of switch-statements
+  - switch
+  - case
+  - Update break to correcly handle mixed nexting of switch-statements
+    and loops.
+
+- Handle currently unsupported constant expression types
+  - ir_unop_bit_not
+  - ir_binop_mod
+  - ir_binop_lshift
+  - ir_binop_rshift
+  - ir_binop_bit_and
+  - ir_binop_bit_xor
+  - ir_binop_bit_or
+
+- Implement support for 1.30 style shadow compares which only return a float
+  instead of a vec4.
diff --git a/src/glsl/apps/.gitignore b/src/glsl/apps/.gitignore
deleted file mode 100644 (file)
index 7e011ce..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-compile
-process
-purify
-tokenise
-version
diff --git a/src/glsl/apps/Makefile b/src/glsl/apps/Makefile
deleted file mode 100644 (file)
index 39a0df7..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-# src/glsl/apps/Makefile
-
-TOP = ../../..
-
-include $(TOP)/configs/current
-
-LIBS = \
-       $(TOP)/src/glsl/pp/libglslpp.a \
-       $(TOP)/src/glsl/cl/libglslcl.a
-
-SOURCES = \
-       compile.c \
-       process.c \
-       purify.c \
-       tokenise.c \
-       version.c
-
-APPS = $(SOURCES:%.c=%)
-
-INCLUDES = -I.
-
-
-##### RULES #####
-
-.SUFFIXES:
-.SUFFIXES: .c
-
-.c:
-       $(APP_CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
-
-.c.o:
-       $(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
-
-
-##### TARGETS #####
-
-default: $(APPS)
-
-install:
-
-clean:
-       -rm -f $(APPS)
-       -rm -f *.o
diff --git a/src/glsl/apps/compile.c b/src/glsl/apps/compile.c
deleted file mode 100644 (file)
index 5114fc9..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include "../pp/sl_pp_public.h"
-#include "../pp/sl_pp_purify.h"
-#include "../cl/sl_cl_parse.h"
-
-
-static void
-usage(void)
-{
-   printf("Usage:\n");
-   printf("  compile fragment|vertex|geometry <source> <output>\n");
-}
-
-int
-main(int argc,
-     char *argv[])
-{
-   FILE *in;
-   long size;
-   char *inbuf;
-   struct sl_pp_purify_options options;
-   char errmsg[100] = "";
-   struct sl_pp_context *context;
-   unsigned int version;
-   FILE *out;
-   unsigned char *outbytes;
-   unsigned int cboutbytes;
-   unsigned int shader_type;
-
-   if (argc != 4) {
-      usage();
-      return 1;
-   }
-
-   if (!strcmp(argv[1], "fragment")) {
-      shader_type = 1;
-   } else if (!strcmp(argv[1], "vertex")) {
-      shader_type = 2;
-   } else if (!strcmp(argv[1], "geometry")) {
-      shader_type = 3;
-   } else {
-      usage();
-      return 1;
-   }
-
-   in = fopen(argv[2], "rb");
-   if (!in) {
-      printf("Could not open `%s' for read.\n", argv[2]);
-      usage();
-      return 1;
-   }
-
-   fseek(in, 0, SEEK_END);
-   size = ftell(in);
-   assert(size != -1);
-   if (size == -1) {
-      return 1;
-   }
-   fseek(in, 0, SEEK_SET);
-
-   out = fopen(argv[3], "w");
-   if (!out) {
-      fclose(in);
-      printf("Could not open `%s' for write.\n", argv[3]);
-      usage();
-      return 1;
-   }
-
-   inbuf = malloc(size + 1);
-   if (!inbuf) {
-      fprintf(out, "$OOMERROR\n");
-
-      fclose(out);
-      fclose(in);
-      printf("Out of memory.\n");
-      return 0;
-   }
-
-   if (fread(inbuf, 1, size, in) != size) {
-      fprintf(out, "$READERROR\n");
-
-      free(inbuf);
-      fclose(out);
-      fclose(in);
-      printf("Could not read from `%s'.\n", argv[2]);
-      return 0;
-   }
-   inbuf[size] = '\0';
-
-   fclose(in);
-
-   memset(&options, 0, sizeof(options));
-
-   context = sl_pp_context_create(inbuf, &options);
-   if (!context) {
-      fprintf(out, "$CONTEXERROR\n");
-
-      free(inbuf);
-      fclose(out);
-      printf("Could not create parse context.\n");
-      return 0;
-   }
-
-   if (sl_pp_version(context, &version)) {
-      fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context));
-
-      printf("Error: %s\n", sl_pp_context_error_message(context));
-      sl_pp_context_destroy(context);
-      free(inbuf);
-      fclose(out);
-      return 0;
-   }
-
-   if (sl_pp_context_add_extension(context, "GL_ARB_draw_buffers") ||
-       sl_pp_context_add_extension(context, "GL_ARB_texture_rectangle")) {
-      fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context));
-
-      printf("Error: %s\n", sl_pp_context_error_message(context));
-      sl_pp_context_destroy(context);
-      free(inbuf);
-      fclose(out);
-      return 0;
-   }
-
-   if (sl_cl_compile(context, shader_type, 1, &outbytes, &cboutbytes, errmsg, sizeof(errmsg)) == 0) {
-      unsigned int i;
-      unsigned int line = 0;
-
-      fprintf(out, "\n/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */");
-      fprintf(out, "\n/* %s */", argv[2]);
-      fprintf(out, "\n\n");
-
-      for (i = 0; i < cboutbytes; i++) {
-         unsigned int a;
-
-         if (outbytes[i] < 10) {
-            a = 1;
-         } else if (outbytes[i] < 100) {
-            a = 2;
-         } else {
-            a = 3;
-         }
-         if (i < cboutbytes - 1) {
-            a++;
-         }
-         if (line + a >= 100) {
-            fprintf (out, "\n");
-            line = 0;
-         }
-         line += a;
-         fprintf (out, "%u", outbytes[i]);
-         if (i < cboutbytes - 1) {
-            fprintf (out, ",");
-         }
-      }
-      fprintf (out, "\n");
-      free(outbytes);
-   } else {
-      fprintf(out, "$SYNTAXERROR: `%s'\n", errmsg);
-
-      printf("Error: %s\n", errmsg);
-   }
-
-   sl_pp_context_destroy(context);
-   free(inbuf);
-   fclose(out);
-   return 0;
-}
diff --git a/src/glsl/apps/process.c b/src/glsl/apps/process.c
deleted file mode 100644 (file)
index 6d5ce6e..0000000
+++ /dev/null
@@ -1,388 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include "../pp/sl_pp_public.h"
-#include "../pp/sl_pp_purify.h"
-#include "../pp/sl_pp_token.h"
-
-
-int
-main(int argc,
-     char *argv[])
-{
-   FILE *in;
-   long size;
-   char *inbuf;
-   struct sl_pp_purify_options options;
-   struct sl_pp_context *context;
-   unsigned int version;
-   struct sl_pp_token_info *outtokens;
-   FILE *out;
-   unsigned int i;
-
-   if (argc != 3) {
-      printf("Usage: process infile outfile\n");
-      return 1;
-   }
-
-   in = fopen(argv[1], "rb");
-   if (!in) {
-      return 1;
-   }
-
-   fseek(in, 0, SEEK_END);
-   size = ftell(in);
-   assert(size != -1);
-   if (size == -1) {
-      return 1;
-   }
-   fseek(in, 0, SEEK_SET);
-
-   out = fopen(argv[2], "wb");
-   if (!out) {
-      fclose(in);
-      return 1;
-   }
-
-   inbuf = malloc(size + 1);
-   if (!inbuf) {
-      fprintf(out, "$OOMERROR\n");
-
-      fclose(out);
-      fclose(in);
-      return 1;
-   }
-
-   if (fread(inbuf, 1, size, in) != size) {
-      fprintf(out, "$READERROR\n");
-
-      free(inbuf);
-      fclose(out);
-      fclose(in);
-      return 1;
-   }
-   inbuf[size] = '\0';
-
-   fclose(in);
-
-   memset(&options, 0, sizeof(options));
-
-   context = sl_pp_context_create(inbuf, &options);
-   if (!context) {
-      fprintf(out, "$CONTEXERROR\n");
-
-      free(inbuf);
-      fclose(out);
-      return 1;
-   }
-
-   if (sl_pp_version(context, &version)) {
-      fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context));
-
-      sl_pp_context_destroy(context);
-      free(inbuf);
-      fclose(out);
-      return -1;
-   }
-
-   if (sl_pp_context_add_extension(context, "GL_ARB_draw_buffers") ||
-       sl_pp_context_add_extension(context, "GL_ARB_texture_rectangle")) {
-      fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context));
-
-      printf("Error: %s\n", sl_pp_context_error_message(context));
-      sl_pp_context_destroy(context);
-      free(inbuf);
-      fclose(out);
-      return 0;
-   }
-
-   if (sl_pp_context_add_predefined(context, "__GLSL_PP_PREDEFINED_MACRO_TEST", "1")) {
-      fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context));
-
-      printf("Error: %s\n", sl_pp_context_error_message(context));
-      sl_pp_context_destroy(context);
-      free(inbuf);
-      fclose(out);
-      return 0;
-   }
-
-   if (sl_pp_process(context, &outtokens)) {
-      fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context));
-
-      sl_pp_context_destroy(context);
-      free(inbuf);
-      fclose(out);
-      return -1;
-   }
-
-   free(inbuf);
-
-   for (i = 0; outtokens[i].token != SL_PP_EOF; i++) {
-      switch (outtokens[i].token) {
-      case SL_PP_NEWLINE:
-         fprintf(out, "\n");
-         break;
-
-      case SL_PP_COMMA:
-         fprintf(out, ", ");
-         break;
-
-      case SL_PP_SEMICOLON:
-         fprintf(out, "; ");
-         break;
-
-      case SL_PP_LBRACE:
-         fprintf(out, "{ ");
-         break;
-
-      case SL_PP_RBRACE:
-         fprintf(out, "} ");
-         break;
-
-      case SL_PP_LPAREN:
-         fprintf(out, "( ");
-         break;
-
-      case SL_PP_RPAREN:
-         fprintf(out, ") ");
-         break;
-
-      case SL_PP_LBRACKET:
-         fprintf(out, "[ ");
-         break;
-
-      case SL_PP_RBRACKET:
-         fprintf(out, "] ");
-         break;
-
-      case SL_PP_DOT:
-         fprintf(out, ". ");
-         break;
-
-      case SL_PP_INCREMENT:
-         fprintf(out, "++ ");
-         break;
-
-      case SL_PP_ADDASSIGN:
-         fprintf(out, "+= ");
-         break;
-
-      case SL_PP_PLUS:
-         fprintf(out, "+ ");
-         break;
-
-      case SL_PP_DECREMENT:
-         fprintf(out, "-- ");
-         break;
-
-      case SL_PP_SUBASSIGN:
-         fprintf(out, "-= ");
-         break;
-
-      case SL_PP_MINUS:
-         fprintf(out, "- ");
-         break;
-
-      case SL_PP_BITNOT:
-         fprintf(out, "~ ");
-         break;
-
-      case SL_PP_NOTEQUAL:
-         fprintf(out, "!= ");
-         break;
-
-      case SL_PP_NOT:
-         fprintf(out, "! ");
-         break;
-
-      case SL_PP_MULASSIGN:
-         fprintf(out, "*= ");
-         break;
-
-      case SL_PP_STAR:
-         fprintf(out, "* ");
-         break;
-
-      case SL_PP_DIVASSIGN:
-         fprintf(out, "/= ");
-         break;
-
-      case SL_PP_SLASH:
-         fprintf(out, "/ ");
-         break;
-
-      case SL_PP_MODASSIGN:
-         fprintf(out, "%%= ");
-         break;
-
-      case SL_PP_MODULO:
-         fprintf(out, "%% ");
-         break;
-
-      case SL_PP_LSHIFTASSIGN:
-         fprintf(out, "<<= ");
-         break;
-
-      case SL_PP_LSHIFT:
-         fprintf(out, "<< ");
-         break;
-
-      case SL_PP_LESSEQUAL:
-         fprintf(out, "<= ");
-         break;
-
-      case SL_PP_LESS:
-         fprintf(out, "< ");
-         break;
-
-      case SL_PP_RSHIFTASSIGN:
-         fprintf(out, ">>= ");
-         break;
-
-      case SL_PP_RSHIFT:
-         fprintf(out, ">> ");
-         break;
-
-      case SL_PP_GREATEREQUAL:
-         fprintf(out, ">= ");
-         break;
-
-      case SL_PP_GREATER:
-         fprintf(out, "> ");
-         break;
-
-      case SL_PP_EQUAL:
-         fprintf(out, "== ");
-         break;
-
-      case SL_PP_ASSIGN:
-         fprintf(out, "= ");
-         break;
-
-      case SL_PP_AND:
-         fprintf(out, "&& ");
-         break;
-
-      case SL_PP_BITANDASSIGN:
-         fprintf(out, "&= ");
-         break;
-
-      case SL_PP_BITAND:
-         fprintf(out, "& ");
-         break;
-
-      case SL_PP_XOR:
-         fprintf(out, "^^ ");
-         break;
-
-      case SL_PP_BITXORASSIGN:
-         fprintf(out, "^= ");
-         break;
-
-      case SL_PP_BITXOR:
-         fprintf(out, "^ ");
-         break;
-
-      case SL_PP_OR:
-         fprintf(out, "|| ");
-         break;
-
-      case SL_PP_BITORASSIGN:
-         fprintf(out, "|= ");
-         break;
-
-      case SL_PP_BITOR:
-         fprintf(out, "| ");
-         break;
-
-      case SL_PP_QUESTION:
-         fprintf(out, "? ");
-         break;
-
-      case SL_PP_COLON:
-         fprintf(out, ": ");
-         break;
-
-      case SL_PP_IDENTIFIER:
-         fprintf(out, "%s ", sl_pp_context_cstr(context, outtokens[i].data.identifier));
-         break;
-
-      case SL_PP_UINT:
-         fprintf(out, "%s ", sl_pp_context_cstr(context, outtokens[i].data._uint));
-         break;
-
-      case SL_PP_FLOAT:
-         fprintf(out, "%s ", sl_pp_context_cstr(context, outtokens[i].data._float));
-         break;
-
-      case SL_PP_OTHER:
-         fprintf(out, "%c", outtokens[i].data.other);
-         break;
-
-      case SL_PP_PRAGMA_OPTIMIZE:
-         fprintf(out, "#pragma optimize(%s)", outtokens[i].data.pragma ? "on" : "off");
-         break;
-
-      case SL_PP_PRAGMA_DEBUG:
-         fprintf(out, "#pragma debug(%s)", outtokens[i].data.pragma ? "on" : "off");
-         break;
-
-      case SL_PP_EXTENSION_REQUIRE:
-         fprintf(out, "#extension %s : require", sl_pp_context_cstr(context, outtokens[i].data.extension));
-         break;
-
-      case SL_PP_EXTENSION_ENABLE:
-         fprintf(out, "#extension %s : enable", sl_pp_context_cstr(context, outtokens[i].data.extension));
-         break;
-
-      case SL_PP_EXTENSION_WARN:
-         fprintf(out, "#extension %s : warn", sl_pp_context_cstr(context, outtokens[i].data.extension));
-         break;
-
-      case SL_PP_EXTENSION_DISABLE:
-         fprintf(out, "#extension %s : disable", sl_pp_context_cstr(context, outtokens[i].data.extension));
-         break;
-
-      case SL_PP_LINE:
-         fprintf(out, "#line %u %u", outtokens[i].data.line.lineno, outtokens[i].data.line.fileno);
-         break;
-
-      default:
-         assert(0);
-      }
-   }
-
-   sl_pp_context_destroy(context);
-   free(outtokens);
-   fclose(out);
-
-   return 0;
-}
diff --git a/src/glsl/apps/purify.c b/src/glsl/apps/purify.c
deleted file mode 100644 (file)
index e3fca59..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "../pp/sl_pp_public.h"
-#include "../pp/sl_pp_purify.h"
-
-
-int
-main(int argc,
-     char *argv[])
-{
-   FILE *in;
-   long size;
-   char *inbuf;
-   struct sl_pp_purify_options options;
-   char *outbuf;
-   char errmsg[100] = "";
-   unsigned int errline = 0;
-   FILE *out;
-
-   if (argc != 3) {
-      printf("Usage: purify infile outfile\n");
-      return 1;
-   }
-
-   in = fopen(argv[1], "rb");
-   if (!in) {
-      return 1;
-   }
-
-   fseek(in, 0, SEEK_END);
-   size = ftell(in);
-   assert(size != -1);
-   if (size == -1) {
-      return 1;
-   }
-   fseek(in, 0, SEEK_SET);
-
-   out = fopen(argv[2], "wb");
-   if (!out) {
-      fclose(in);
-      return 1;
-   }
-
-   inbuf = malloc(size + 1);
-   if (!inbuf) {
-      fprintf(out, "$OOMERROR\n");
-
-      fclose(out);
-      fclose(in);
-      return 1;
-   }
-
-   if (fread(inbuf, 1, size, in) != size) {
-      fprintf(out, "$READERROR\n");
-
-      free(inbuf);
-      fclose(out);
-      fclose(in);
-      return 1;
-   }
-   inbuf[size] = '\0';
-
-   fclose(in);
-
-   memset(&options, 0, sizeof(options));
-
-   if (sl_pp_purify(inbuf, &options, &outbuf, errmsg, sizeof(errmsg), &errline)) {
-      fprintf(out, "$PURIFYERROR %u: %s\n", errline, errmsg);
-
-      free(inbuf);
-      fclose(out);
-      return 1;
-   }
-
-   free(inbuf);
-
-   fwrite(outbuf, 1, strlen(outbuf), out);
-
-   free(outbuf);
-   fclose(out);
-
-   return 0;
-}
diff --git a/src/glsl/apps/tokenise.c b/src/glsl/apps/tokenise.c
deleted file mode 100644 (file)
index 3d68334..0000000
+++ /dev/null
@@ -1,340 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include "../pp/sl_pp_public.h"
-#include "../pp/sl_pp_purify.h"
-#include "../pp/sl_pp_token.h"
-
-
-int
-main(int argc,
-     char *argv[])
-{
-   FILE *in;
-   long size;
-   char *inbuf;
-   struct sl_pp_purify_options options;
-   struct sl_pp_context *context;
-   struct sl_pp_token_info *tokens;
-   FILE *out;
-   unsigned int i;
-
-   if (argc != 3) {
-      printf("Usage: tokenize infile outfile\n");
-      return 1;
-   }
-
-   in = fopen(argv[1], "rb");
-   if (!in) {
-      return 1;
-   }
-
-   fseek(in, 0, SEEK_END);
-   size = ftell(in);
-   assert(size != -1);
-   if (size == -1) {
-      return 1;
-   }
-   fseek(in, 0, SEEK_SET);
-
-   out = fopen(argv[2], "wb");
-   if (!out) {
-      fclose(in);
-      return 1;
-   }
-
-   inbuf = malloc(size + 1);
-   if (!inbuf) {
-      fprintf(out, "$OOMERROR\n");
-
-      fclose(out);
-      fclose(in);
-      return 1;
-   }
-
-   if (fread(inbuf, 1, size, in) != size) {
-      fprintf(out, "$READERROR\n");
-
-      free(inbuf);
-      fclose(out);
-      fclose(in);
-      return 1;
-   }
-   inbuf[size] = '\0';
-
-   fclose(in);
-
-   memset(&options, 0, sizeof(options));
-
-   context = sl_pp_context_create(inbuf, &options);
-   if (!context) {
-      fprintf(out, "$CONTEXERROR\n");
-
-      free(inbuf);
-      fclose(out);
-      return 1;
-   }
-
-   if (sl_pp_tokenise(context, &tokens)) {
-      fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context));
-
-      sl_pp_context_destroy(context);
-      free(inbuf);
-      fclose(out);
-      return 1;
-   }
-
-   free(inbuf);
-
-   for (i = 0; tokens[i].token != SL_PP_EOF; i++) {
-      switch (tokens[i].token) {
-      case SL_PP_WHITESPACE:
-         break;
-
-      case SL_PP_NEWLINE:
-         fprintf(out, "\n");
-         break;
-
-      case SL_PP_HASH:
-         fprintf(out, "# ");
-         break;
-
-      case SL_PP_COMMA:
-         fprintf(out, ", ");
-         break;
-
-      case SL_PP_SEMICOLON:
-         fprintf(out, "; ");
-         break;
-
-      case SL_PP_LBRACE:
-         fprintf(out, "{ ");
-         break;
-
-      case SL_PP_RBRACE:
-         fprintf(out, "} ");
-         break;
-
-      case SL_PP_LPAREN:
-         fprintf(out, "( ");
-         break;
-
-      case SL_PP_RPAREN:
-         fprintf(out, ") ");
-         break;
-
-      case SL_PP_LBRACKET:
-         fprintf(out, "[ ");
-         break;
-
-      case SL_PP_RBRACKET:
-         fprintf(out, "] ");
-         break;
-
-      case SL_PP_DOT:
-         fprintf(out, ". ");
-         break;
-
-      case SL_PP_INCREMENT:
-         fprintf(out, "++ ");
-         break;
-
-      case SL_PP_ADDASSIGN:
-         fprintf(out, "+= ");
-         break;
-
-      case SL_PP_PLUS:
-         fprintf(out, "+ ");
-         break;
-
-      case SL_PP_DECREMENT:
-         fprintf(out, "-- ");
-         break;
-
-      case SL_PP_SUBASSIGN:
-         fprintf(out, "-= ");
-         break;
-
-      case SL_PP_MINUS:
-         fprintf(out, "- ");
-         break;
-
-      case SL_PP_BITNOT:
-         fprintf(out, "~ ");
-         break;
-
-      case SL_PP_NOTEQUAL:
-         fprintf(out, "!= ");
-         break;
-
-      case SL_PP_NOT:
-         fprintf(out, "! ");
-         break;
-
-      case SL_PP_MULASSIGN:
-         fprintf(out, "*= ");
-         break;
-
-      case SL_PP_STAR:
-         fprintf(out, "* ");
-         break;
-
-      case SL_PP_DIVASSIGN:
-         fprintf(out, "/= ");
-         break;
-
-      case SL_PP_SLASH:
-         fprintf(out, "/ ");
-         break;
-
-      case SL_PP_MODASSIGN:
-         fprintf(out, "%%= ");
-         break;
-
-      case SL_PP_MODULO:
-         fprintf(out, "%% ");
-         break;
-
-      case SL_PP_LSHIFTASSIGN:
-         fprintf(out, "<<= ");
-         break;
-
-      case SL_PP_LSHIFT:
-         fprintf(out, "<< ");
-         break;
-
-      case SL_PP_LESSEQUAL:
-         fprintf(out, "<= ");
-         break;
-
-      case SL_PP_LESS:
-         fprintf(out, "< ");
-         break;
-
-      case SL_PP_RSHIFTASSIGN:
-         fprintf(out, ">>= ");
-         break;
-
-      case SL_PP_RSHIFT:
-         fprintf(out, ">> ");
-         break;
-
-      case SL_PP_GREATEREQUAL:
-         fprintf(out, ">= ");
-         break;
-
-      case SL_PP_GREATER:
-         fprintf(out, "> ");
-         break;
-
-      case SL_PP_EQUAL:
-         fprintf(out, "== ");
-         break;
-
-      case SL_PP_ASSIGN:
-         fprintf(out, "= ");
-         break;
-
-      case SL_PP_AND:
-         fprintf(out, "&& ");
-         break;
-
-      case SL_PP_BITANDASSIGN:
-         fprintf(out, "&= ");
-         break;
-
-      case SL_PP_BITAND:
-         fprintf(out, "& ");
-         break;
-
-      case SL_PP_XOR:
-         fprintf(out, "^^ ");
-         break;
-
-      case SL_PP_BITXORASSIGN:
-         fprintf(out, "^= ");
-         break;
-
-      case SL_PP_BITXOR:
-         fprintf(out, "^ ");
-         break;
-
-      case SL_PP_OR:
-         fprintf(out, "|| ");
-         break;
-
-      case SL_PP_BITORASSIGN:
-         fprintf(out, "|= ");
-         break;
-
-      case SL_PP_BITOR:
-         fprintf(out, "| ");
-         break;
-
-      case SL_PP_QUESTION:
-         fprintf(out, "? ");
-         break;
-
-      case SL_PP_COLON:
-         fprintf(out, ": ");
-         break;
-
-      case SL_PP_IDENTIFIER:
-         fprintf(out, "%s ", sl_pp_context_cstr(context, tokens[i].data.identifier));
-         break;
-
-      case SL_PP_UINT:
-         fprintf(out, "(%s) ", sl_pp_context_cstr(context, tokens[i].data._uint));
-         break;
-
-      case SL_PP_FLOAT:
-         fprintf(out, "(%s) ", sl_pp_context_cstr(context, tokens[i].data._float));
-         break;
-
-      case SL_PP_OTHER:
-         if (tokens[i].data.other == '\'') {
-            fprintf(out, "'\\'' ");
-         } else {
-            fprintf(out, "'%c' ", tokens[i].data.other);
-         }
-         break;
-
-      default:
-         assert(0);
-      }
-   }
-
-   sl_pp_context_destroy(context);
-   free(tokens);
-   fclose(out);
-
-   return 0;
-}
diff --git a/src/glsl/apps/version.c b/src/glsl/apps/version.c
deleted file mode 100644 (file)
index 8506f35..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include "../pp/sl_pp_public.h"
-#include "../pp/sl_pp_purify.h"
-
-
-int
-main(int argc,
-     char *argv[])
-{
-   FILE *in;
-   long size;
-   char *inbuf;
-   struct sl_pp_purify_options options;
-   struct sl_pp_context *context;
-   unsigned int version;
-   FILE *out;
-
-   if (argc != 3) {
-      printf("Usage: version infile outfile\n");
-      return 1;
-   }
-
-   in = fopen(argv[1], "rb");
-   if (!in) {
-      return 1;
-   }
-
-   fseek(in, 0, SEEK_END);
-   size = ftell(in);
-   assert(size != -1);
-   if (size == -1) {
-      return 1;
-   }
-   fseek(in, 0, SEEK_SET);
-
-   out = fopen(argv[2], "wb");
-   if (!out) {
-      fclose(in);
-      return 1;
-   }
-
-   inbuf = malloc(size + 1);
-   if (!inbuf) {
-      fprintf(out, "$OOMERROR\n");
-
-      fclose(out);
-      fclose(in);
-      return 1;
-   }
-
-   if (fread(inbuf, 1, size, in) != size) {
-      fprintf(out, "$READERROR\n");
-
-      free(inbuf);
-      fclose(out);
-      fclose(in);
-      return 1;
-   }
-   inbuf[size] = '\0';
-
-   fclose(in);
-
-   memset(&options, 0, sizeof(options));
-
-   context = sl_pp_context_create(inbuf, &options);
-   if (!context) {
-      fprintf(out, "$CONTEXERROR\n");
-
-      free(inbuf);
-      fclose(out);
-      return 1;
-   }
-
-   if (sl_pp_version(context, &version)) {
-      fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context));
-
-      sl_pp_context_destroy(context);
-      free(inbuf);
-      fclose(out);
-      return -1;
-   }
-
-   sl_pp_context_destroy(context);
-   free(inbuf);
-
-   fprintf(out, "%u\n", version);
-
-   fclose(out);
-
-   return 0;
-}
diff --git a/src/glsl/ast.h b/src/glsl/ast.h
new file mode 100644 (file)
index 0000000..44c31b6
--- /dev/null
@@ -0,0 +1,664 @@
+/* -*- c++ -*- */
+/*
+ * Copyright Â© 2009 Intel Corporation
+ *
+ * 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.
+ */
+
+#pragma once
+#ifndef AST_H
+#define AST_H
+
+#include "list.h"
+#include "glsl_parser_extras.h"
+
+struct _mesa_glsl_parse_state;
+
+struct YYLTYPE;
+
+class ast_node {
+public:
+   /* Callers of this talloc-based new need not call delete. It's
+    * easier to just talloc_free 'ctx' (or any of its ancestors). */
+   static void* operator new(size_t size, void *ctx)
+   {
+      void *node;
+
+      node = talloc_zero_size(ctx, size);
+      assert(node != NULL);
+
+      return node;
+   }
+
+   /* If the user *does* call delete, that's OK, we will just
+    * talloc_free in that case. */
+   static void operator delete(void *table)
+   {
+      talloc_free(table);
+   }
+
+   virtual void print(void) const;
+   virtual ir_rvalue *hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state);
+
+   /**
+    * Retrieve the source location of an AST node
+    *
+    * This function is primarily used to get the source position of an AST node
+    * into a form that can be passed to \c _mesa_glsl_error.
+    *
+    * \sa _mesa_glsl_error, ast_node::set_location
+    */
+   struct YYLTYPE get_location(void) const
+   {
+      struct YYLTYPE locp;
+
+      locp.source = this->location.source;
+      locp.first_line = this->location.line;
+      locp.first_column = this->location.column;
+      locp.last_line = locp.first_line;
+      locp.last_column = locp.first_column;
+
+      return locp;
+   }
+
+   /**
+    * Set the source location of an AST node from a parser location
+    *
+    * \sa ast_node::get_location
+    */
+   void set_location(const struct YYLTYPE &locp)
+   {
+      this->location.source = locp.source;
+      this->location.line = locp.first_line;
+      this->location.column = locp.first_column;
+   }
+
+   struct {
+      unsigned source;
+      unsigned line;
+      unsigned column;
+   } location;
+
+   exec_node link;
+
+protected:
+   ast_node(void);
+};
+
+
+enum ast_operators {
+   ast_assign,
+   ast_plus,        /**< Unary + operator. */
+   ast_neg,
+   ast_add,
+   ast_sub,
+   ast_mul,
+   ast_div,
+   ast_mod,
+   ast_lshift,
+   ast_rshift,
+   ast_less,
+   ast_greater,
+   ast_lequal,
+   ast_gequal,
+   ast_equal,
+   ast_nequal,
+   ast_bit_and,
+   ast_bit_xor,
+   ast_bit_or,
+   ast_bit_not,
+   ast_logic_and,
+   ast_logic_xor,
+   ast_logic_or,
+   ast_logic_not,
+
+   ast_mul_assign,
+   ast_div_assign,
+   ast_mod_assign,
+   ast_add_assign,
+   ast_sub_assign,
+   ast_ls_assign,
+   ast_rs_assign,
+   ast_and_assign,
+   ast_xor_assign,
+   ast_or_assign,
+
+   ast_conditional,
+
+   ast_pre_inc,
+   ast_pre_dec,
+   ast_post_inc,
+   ast_post_dec,
+   ast_field_selection,
+   ast_array_index,
+
+   ast_function_call,
+
+   ast_identifier,
+   ast_int_constant,
+   ast_uint_constant,
+   ast_float_constant,
+   ast_bool_constant,
+
+   ast_sequence
+};
+
+class ast_expression : public ast_node {
+public:
+   ast_expression(int oper, ast_expression *,
+                 ast_expression *, ast_expression *);
+
+   ast_expression(const char *identifier) :
+      oper(ast_identifier)
+   {
+      subexpressions[0] = NULL;
+      subexpressions[1] = NULL;
+      subexpressions[2] = NULL;
+      primary_expression.identifier = (char *) identifier;
+   }
+
+   static const char *operator_string(enum ast_operators op);
+
+   virtual ir_rvalue *hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state);
+
+   virtual void print(void) const;
+
+   enum ast_operators oper;
+
+   ast_expression *subexpressions[3];
+
+   union {
+      char *identifier;
+      int int_constant;
+      float float_constant;
+      unsigned uint_constant;
+      int bool_constant;
+   } primary_expression;
+
+
+   /**
+    * List of expressions for an \c ast_sequence or parameters for an
+    * \c ast_function_call
+    */
+   exec_list expressions;
+};
+
+class ast_expression_bin : public ast_expression {
+public:
+   ast_expression_bin(int oper, ast_expression *, ast_expression *);
+
+   virtual void print(void) const;
+};
+
+/**
+ * Subclass of expressions for function calls
+ */
+class ast_function_expression : public ast_expression {
+public:
+   ast_function_expression(ast_expression *callee)
+      : ast_expression(ast_function_call, callee,
+                      NULL, NULL),
+       cons(false)
+   {
+      /* empty */
+   }
+
+   ast_function_expression(class ast_type_specifier *type)
+      : ast_expression(ast_function_call, (ast_expression *) type,
+                      NULL, NULL),
+       cons(true)
+   {
+      /* empty */
+   }
+
+   bool is_constructor() const
+   {
+      return cons;
+   }
+
+   virtual ir_rvalue *hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state);
+
+private:
+   /**
+    * Is this function call actually a constructor?
+    */
+   bool cons;
+};
+
+
+/**
+ * Number of possible operators for an ast_expression
+ *
+ * This is done as a define instead of as an additional value in the enum so
+ * that the compiler won't generate spurious messages like "warning:
+ * enumeration value â€˜ast_num_operators’ not handled in switch"
+ */
+#define AST_NUM_OPERATORS (ast_sequence + 1)
+
+
+class ast_compound_statement : public ast_node {
+public:
+   ast_compound_statement(int new_scope, ast_node *statements);
+   virtual void print(void) const;
+
+   virtual ir_rvalue *hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state);
+
+   int new_scope;
+   exec_list statements;
+};
+
+class ast_declaration : public ast_node {
+public:
+   ast_declaration(char *identifier, int is_array, ast_expression *array_size,
+                  ast_expression *initializer);
+   virtual void print(void) const;
+
+   char *identifier;
+   
+   int is_array;
+   ast_expression *array_size;
+
+   ast_expression *initializer;
+};
+
+
+enum {
+   ast_precision_high = 0, /**< Default precision. */
+   ast_precision_medium,
+   ast_precision_low
+};
+
+struct ast_type_qualifier {
+   unsigned invariant:1;
+   unsigned constant:1;
+   unsigned attribute:1;
+   unsigned varying:1;
+   unsigned in:1;
+   unsigned out:1;
+   unsigned centroid:1;
+   unsigned uniform:1;
+   unsigned smooth:1;
+   unsigned flat:1;
+   unsigned noperspective:1;
+
+   /** \name Layout qualifiers for GL_ARB_fragment_coord_conventions */
+   /*@{*/
+   unsigned origin_upper_left:1;
+   unsigned pixel_center_integer:1;
+   /*@}*/
+};
+
+class ast_struct_specifier : public ast_node {
+public:
+   ast_struct_specifier(char *identifier, ast_node *declarator_list);
+   virtual void print(void) const;
+
+   virtual ir_rvalue *hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state);
+
+   char *name;
+   exec_list declarations;
+};
+
+
+enum ast_types {
+   ast_void,
+   ast_float,
+   ast_int,
+   ast_uint,
+   ast_bool,
+   ast_vec2,
+   ast_vec3,
+   ast_vec4,
+   ast_bvec2,
+   ast_bvec3,
+   ast_bvec4,
+   ast_ivec2,
+   ast_ivec3,
+   ast_ivec4,
+   ast_uvec2,
+   ast_uvec3,
+   ast_uvec4,
+   ast_mat2,
+   ast_mat2x3,
+   ast_mat2x4,
+   ast_mat3x2,
+   ast_mat3,
+   ast_mat3x4,
+   ast_mat4x2,
+   ast_mat4x3,
+   ast_mat4,
+   ast_sampler1d,
+   ast_sampler2d,
+   ast_sampler2drect,
+   ast_sampler3d,
+   ast_samplercube,
+   ast_sampler1dshadow,
+   ast_sampler2dshadow,
+   ast_sampler2drectshadow,
+   ast_samplercubeshadow,
+   ast_sampler1darray,
+   ast_sampler2darray,
+   ast_sampler1darrayshadow,
+   ast_sampler2darrayshadow,
+   ast_isampler1d,
+   ast_isampler2d,
+   ast_isampler3d,
+   ast_isamplercube,
+   ast_isampler1darray,
+   ast_isampler2darray,
+   ast_usampler1d,
+   ast_usampler2d,
+   ast_usampler3d,
+   ast_usamplercube,
+   ast_usampler1darray,
+   ast_usampler2darray,
+
+   ast_struct,
+   ast_type_name
+};
+
+
+class ast_type_specifier : public ast_node {
+public:
+   ast_type_specifier(int specifier);
+
+   /** Construct a type specifier from a type name */
+   ast_type_specifier(const char *name) 
+      : type_specifier(ast_type_name), type_name(name), structure(NULL),
+       is_array(false), array_size(NULL), precision(ast_precision_high)
+   {
+      /* empty */
+   }
+
+   /** Construct a type specifier from a structure definition */
+   ast_type_specifier(ast_struct_specifier *s)
+      : type_specifier(ast_struct), type_name(s->name), structure(s),
+       is_array(false), array_size(NULL), precision(ast_precision_high)
+   {
+      /* empty */
+   }
+
+   const struct glsl_type *glsl_type(const char **name,
+                                    struct _mesa_glsl_parse_state *state)
+      const;
+
+   virtual void print(void) const;
+
+   ir_rvalue *hir(exec_list *, struct _mesa_glsl_parse_state *);
+
+   enum ast_types type_specifier;
+
+   const char *type_name;
+   ast_struct_specifier *structure;
+
+   int is_array;
+   ast_expression *array_size;
+
+   unsigned precision:2;
+};
+
+
+class ast_fully_specified_type : public ast_node {
+public:
+   virtual void print(void) const;
+   bool has_qualifiers() const;
+
+   ast_type_qualifier qualifier;
+   ast_type_specifier *specifier;
+};
+
+
+class ast_declarator_list : public ast_node {
+public:
+   ast_declarator_list(ast_fully_specified_type *);
+   virtual void print(void) const;
+
+   virtual ir_rvalue *hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state);
+
+   ast_fully_specified_type *type;
+   exec_list declarations;
+
+   /**
+    * Special flag for vertex shader "invariant" declarations.
+    *
+    * Vertex shaders can contain "invariant" variable redeclarations that do
+    * not include a type.  For example, "invariant gl_Position;".  This flag
+    * is used to note these cases when no type is specified.
+    */
+   int invariant;
+};
+
+
+class ast_parameter_declarator : public ast_node {
+public:
+   ast_parameter_declarator()
+   {
+      this->identifier = NULL;
+      this->is_array = false;
+      this->array_size = 0;
+   }
+
+   virtual void print(void) const;
+
+   virtual ir_rvalue *hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state);
+
+   ast_fully_specified_type *type;
+   char *identifier;
+   int is_array;
+   ast_expression *array_size;
+
+   static void parameters_to_hir(exec_list *ast_parameters,
+                                bool formal, exec_list *ir_parameters,
+                                struct _mesa_glsl_parse_state *state);
+
+private:
+   /** Is this parameter declaration part of a formal parameter list? */
+   bool formal_parameter;
+
+   /**
+    * Is this parameter 'void' type?
+    *
+    * This field is set by \c ::hir.
+    */
+   bool is_void;
+};
+
+
+class ast_function : public ast_node {
+public:
+   ast_function(void);
+
+   virtual void print(void) const;
+
+   virtual ir_rvalue *hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state);
+
+   ast_fully_specified_type *return_type;
+   char *identifier;
+
+   exec_list parameters;
+
+private:
+   /**
+    * Is this prototype part of the function definition?
+    *
+    * Used by ast_function_definition::hir to process the parameters, etc.
+    * of the function.
+    *
+    * \sa ::hir
+    */
+   bool is_definition;
+
+   /**
+    * Function signature corresponding to this function prototype instance
+    *
+    * Used by ast_function_definition::hir to process the parameters, etc.
+    * of the function.
+    *
+    * \sa ::hir
+    */
+   class ir_function_signature *signature;
+
+   friend class ast_function_definition;
+};
+
+
+class ast_declaration_statement : public ast_node {
+public:
+   ast_declaration_statement(void);
+
+   enum {
+      ast_function,
+      ast_declaration,
+      ast_precision
+   } mode;
+
+   union {
+      class ast_function *function;
+      ast_declarator_list *declarator;
+      ast_type_specifier *type;
+      ast_node *node;
+   } declaration;
+};
+
+
+class ast_expression_statement : public ast_node {
+public:
+   ast_expression_statement(ast_expression *);
+   virtual void print(void) const;
+
+   virtual ir_rvalue *hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state);
+
+   ast_expression *expression;
+};
+
+
+class ast_case_label : public ast_node {
+public:
+
+   /**
+    * An expression of NULL means 'default'.
+    */
+   ast_expression *expression;
+};
+
+class ast_selection_statement : public ast_node {
+public:
+   ast_selection_statement(ast_expression *condition,
+                          ast_node *then_statement,
+                          ast_node *else_statement);
+   virtual void print(void) const;
+
+   virtual ir_rvalue *hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state);
+
+   ast_expression *condition;
+   ast_node *then_statement;
+   ast_node *else_statement;
+};
+
+
+class ast_switch_statement : public ast_node {
+public:
+   ast_expression *expression;
+   exec_list statements;
+};
+
+class ast_iteration_statement : public ast_node {
+public:
+   ast_iteration_statement(int mode, ast_node *init, ast_node *condition,
+                          ast_expression *rest_expression, ast_node *body);
+
+   virtual void print(void) const;
+
+   virtual ir_rvalue *hir(exec_list *, struct _mesa_glsl_parse_state *);
+
+   enum ast_iteration_modes {
+      ast_for,
+      ast_while,
+      ast_do_while
+   } mode;
+   
+
+   ast_node *init_statement;
+   ast_node *condition;
+   ast_expression *rest_expression;
+
+   ast_node *body;
+
+private:
+   /**
+    * Generate IR from the condition of a loop
+    *
+    * This is factored out of ::hir because some loops have the condition
+    * test at the top (for and while), and others have it at the end (do-while).
+    */
+   void condition_to_hir(class ir_loop *, struct _mesa_glsl_parse_state *);
+};
+
+
+class ast_jump_statement : public ast_node {
+public:
+   ast_jump_statement(int mode, ast_expression *return_value);
+   virtual void print(void) const;
+
+   virtual ir_rvalue *hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state);
+
+   enum ast_jump_modes {
+      ast_continue,
+      ast_break,
+      ast_return,
+      ast_discard
+   } mode;
+
+   ast_expression *opt_return_value;
+};
+
+
+class ast_function_definition : public ast_node {
+public:
+   virtual void print(void) const;
+
+   virtual ir_rvalue *hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state);
+
+   ast_function *prototype;
+   ast_compound_statement *body;
+};
+
+
+extern void
+_mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state);
+
+extern ir_rvalue *
+_mesa_ast_field_selection_to_hir(const ast_expression *expr,
+                                exec_list *instructions,
+                                struct _mesa_glsl_parse_state *state);
+
+#endif /* AST_H */
diff --git a/src/glsl/ast_expr.cpp b/src/glsl/ast_expr.cpp
new file mode 100644 (file)
index 0000000..4e83dec
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 <cstdio>
+#include <cassert>
+#include "ast.h"
+
+const char *
+ast_expression::operator_string(enum ast_operators op)
+{
+   static const char *const operators[] = {
+      "=",
+      "+",
+      "-",
+      "+",
+      "-",
+      "*",
+      "/",
+      "%",
+      "<<",
+      ">>",
+      "<",
+      ">",
+      "<=",
+      ">=",
+      "==",
+      "!=",
+      "&",
+      "^",
+      "|",
+      "~",
+      "&&",
+      "^^",
+      "||",
+      "!",
+
+      "*=",
+      "/=",
+      "%=",
+      "+=",
+      "-=",
+      "<<=",
+      ">>=",
+      "&=",
+      "^=",
+      "|=",
+
+      "?:",
+
+      "++",
+      "--",
+      "++",
+      "--",
+      ".",
+   };
+
+   assert((unsigned int)op < sizeof(operators) / sizeof(operators[0]));
+
+   return operators[op];
+}
+
+
+ast_expression_bin::ast_expression_bin(int oper, ast_expression *ex0,
+                                      ast_expression *ex1) :
+   ast_expression(oper, ex0, ex1, NULL)
+{
+   assert((oper >= ast_plus) && (oper <= ast_logic_not));
+}
+
+
+void
+ast_expression_bin::print(void) const
+{
+   subexpressions[0]->print();
+   printf("%s ", operator_string(oper));
+   subexpressions[1]->print();
+}
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
new file mode 100644 (file)
index 0000000..61012b8
--- /dev/null
@@ -0,0 +1,1240 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 "glsl_symbol_table.h"
+#include "ast.h"
+#include "glsl_types.h"
+#include "ir.h"
+#include "main/core.h" /* for MIN2 */
+
+static ir_rvalue *
+convert_component(ir_rvalue *src, const glsl_type *desired_type);
+
+bool
+apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from,
+                          struct _mesa_glsl_parse_state *state);
+
+static unsigned
+process_parameters(exec_list *instructions, exec_list *actual_parameters,
+                  exec_list *parameters,
+                  struct _mesa_glsl_parse_state *state)
+{
+   unsigned count = 0;
+
+   foreach_list (n, parameters) {
+      ast_node *const ast = exec_node_data(ast_node, n, link);
+      ir_rvalue *result = ast->hir(instructions, state);
+
+      ir_constant *const constant = result->constant_expression_value();
+      if (constant != NULL)
+        result = constant;
+
+      actual_parameters->push_tail(result);
+      count++;
+   }
+
+   return count;
+}
+
+
+/**
+ * Generate a source prototype for a function signature
+ *
+ * \param return_type Return type of the function.  May be \c NULL.
+ * \param name        Name of the function.
+ * \param parameters  Parameter list for the function.  This may be either a
+ *                    formal or actual parameter list.  Only the type is used.
+ *
+ * \return
+ * A talloced string representing the prototype of the function.
+ */
+char *
+prototype_string(const glsl_type *return_type, const char *name,
+                exec_list *parameters)
+{
+   char *str = NULL;
+
+   if (return_type != NULL)
+      str = talloc_asprintf(str, "%s ", return_type->name);
+
+   str = talloc_asprintf_append(str, "%s(", name);
+
+   const char *comma = "";
+   foreach_list(node, parameters) {
+      const ir_instruction *const param = (ir_instruction *) node;
+
+      str = talloc_asprintf_append(str, "%s%s", comma, param->type->name);
+      comma = ", ";
+   }
+
+   str = talloc_strdup_append(str, ")");
+   return str;
+}
+
+
+static ir_rvalue *
+process_call(exec_list *instructions, ir_function *f,
+            YYLTYPE *loc, exec_list *actual_parameters,
+            struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+
+   ir_function_signature *sig = f->matching_signature(actual_parameters);
+
+   /* The instructions param will be used when the FINISHMEs below are done */
+   (void) instructions;
+
+   if (sig != NULL) {
+      /* Verify that 'out' and 'inout' actual parameters are lvalues.  This
+       * isn't done in ir_function::matching_signature because that function
+       * cannot generate the necessary diagnostics.
+       */
+      exec_list_iterator actual_iter = actual_parameters->iterator();
+      exec_list_iterator formal_iter = sig->parameters.iterator();
+
+      while (actual_iter.has_next()) {
+        ir_rvalue *actual = (ir_rvalue *) actual_iter.get();
+        ir_variable *formal = (ir_variable *) formal_iter.get();
+
+        assert(actual != NULL);
+        assert(formal != NULL);
+
+        if ((formal->mode == ir_var_out)
+            || (formal->mode == ir_var_inout)) {
+           if (! actual->is_lvalue()) {
+              /* FINISHME: Log a better diagnostic here.  There is no way
+               * FINISHME: to tell the user which parameter is invalid.
+               */
+              _mesa_glsl_error(loc, state, "`%s' parameter is not lvalue",
+                               (formal->mode == ir_var_out) ? "out" : "inout");
+           }
+        }
+
+        if (formal->type->is_numeric() || formal->type->is_boolean()) {
+           ir_rvalue *converted = convert_component(actual, formal->type);
+           actual->replace_with(converted);
+        }
+
+        actual_iter.next();
+        formal_iter.next();
+      }
+
+      /* Always insert the call in the instruction stream, and return a deref
+       * of its return val if it returns a value, since we don't know if
+       * the rvalue is going to be assigned to anything or not.
+       */
+      ir_call *call = new(ctx) ir_call(sig, actual_parameters);
+      if (!sig->return_type->is_void()) {
+        ir_variable *var;
+        ir_dereference_variable *deref;
+
+        var = new(ctx) ir_variable(sig->return_type,
+                                   talloc_asprintf(ctx, "%s_retval",
+                                                   sig->function_name()),
+                                   ir_var_temporary);
+        instructions->push_tail(var);
+
+        deref = new(ctx) ir_dereference_variable(var);
+        ir_assignment *assign = new(ctx) ir_assignment(deref, call, NULL);
+        instructions->push_tail(assign);
+        if (state->language_version >= 120)
+           var->constant_value = call->constant_expression_value();
+
+        deref = new(ctx) ir_dereference_variable(var);
+        return deref;
+      } else {
+        instructions->push_tail(call);
+        return NULL;
+      }
+   } else {
+      char *str = prototype_string(NULL, f->name, actual_parameters);
+
+      _mesa_glsl_error(loc, state, "no matching function for call to `%s'",
+                      str);
+      talloc_free(str);
+
+      const char *prefix = "candidates are: ";
+      foreach_list (node, &f->signatures) {
+        ir_function_signature *sig = (ir_function_signature *) node;
+
+        str = prototype_string(sig->return_type, f->name, &sig->parameters);
+        _mesa_glsl_error(loc, state, "%s%s\n", prefix, str);
+        talloc_free(str);
+
+        prefix = "                ";
+      }
+
+      return ir_call::get_error_instruction(ctx);
+   }
+}
+
+
+static ir_rvalue *
+match_function_by_name(exec_list *instructions, const char *name,
+                      YYLTYPE *loc, exec_list *actual_parameters,
+                      struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+   ir_function *f = state->symbols->get_function(name);
+
+   if (f == NULL) {
+      _mesa_glsl_error(loc, state, "function `%s' undeclared", name);
+      return ir_call::get_error_instruction(ctx);
+   }
+
+   /* Once we've determined that the function being called might exist, try
+    * to find an overload of the function that matches the parameters.
+    */
+   return process_call(instructions, f, loc, actual_parameters, state);
+}
+
+
+/**
+ * Perform automatic type conversion of constructor parameters
+ *
+ * This implements the rules in the "Conversion and Scalar Constructors"
+ * section (GLSL 1.10 section 5.4.1), not the "Implicit Conversions" rules.
+ */
+static ir_rvalue *
+convert_component(ir_rvalue *src, const glsl_type *desired_type)
+{
+   void *ctx = talloc_parent(src);
+   const unsigned a = desired_type->base_type;
+   const unsigned b = src->type->base_type;
+   ir_expression *result = NULL;
+
+   if (src->type->is_error())
+      return src;
+
+   assert(a <= GLSL_TYPE_BOOL);
+   assert(b <= GLSL_TYPE_BOOL);
+
+   if ((a == b) || (src->type->is_integer() && desired_type->is_integer()))
+      return src;
+
+   switch (a) {
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+      if (b == GLSL_TYPE_FLOAT)
+        result = new(ctx) ir_expression(ir_unop_f2i, desired_type, src, NULL);
+      else {
+        assert(b == GLSL_TYPE_BOOL);
+        result = new(ctx) ir_expression(ir_unop_b2i, desired_type, src, NULL);
+      }
+      break;
+   case GLSL_TYPE_FLOAT:
+      switch (b) {
+      case GLSL_TYPE_UINT:
+        result = new(ctx) ir_expression(ir_unop_u2f, desired_type, src, NULL);
+        break;
+      case GLSL_TYPE_INT:
+        result = new(ctx) ir_expression(ir_unop_i2f, desired_type, src, NULL);
+        break;
+      case GLSL_TYPE_BOOL:
+        result = new(ctx) ir_expression(ir_unop_b2f, desired_type, src, NULL);
+        break;
+      }
+      break;
+   case GLSL_TYPE_BOOL:
+      switch (b) {
+      case GLSL_TYPE_UINT:
+      case GLSL_TYPE_INT:
+        result = new(ctx) ir_expression(ir_unop_i2b, desired_type, src, NULL);
+        break;
+      case GLSL_TYPE_FLOAT:
+        result = new(ctx) ir_expression(ir_unop_f2b, desired_type, src, NULL);
+        break;
+      }
+      break;
+   }
+
+   assert(result != NULL);
+
+   /* Try constant folding; it may fold in the conversion we just added. */
+   ir_constant *const constant = result->constant_expression_value();
+   return (constant != NULL) ? (ir_rvalue *) constant : (ir_rvalue *) result;
+}
+
+/**
+ * Dereference a specific component from a scalar, vector, or matrix
+ */
+static ir_rvalue *
+dereference_component(ir_rvalue *src, unsigned component)
+{
+   void *ctx = talloc_parent(src);
+   assert(component < src->type->components());
+
+   /* If the source is a constant, just create a new constant instead of a
+    * dereference of the existing constant.
+    */
+   ir_constant *constant = src->as_constant();
+   if (constant)
+      return new(ctx) ir_constant(constant, component);
+
+   if (src->type->is_scalar()) {
+      return src;
+   } else if (src->type->is_vector()) {
+      return new(ctx) ir_swizzle(src, component, 0, 0, 0, 1);
+   } else {
+      assert(src->type->is_matrix());
+
+      /* Dereference a row of the matrix, then call this function again to get
+       * a specific element from that row.
+       */
+      const int c = component / src->type->column_type()->vector_elements;
+      const int r = component % src->type->column_type()->vector_elements;
+      ir_constant *const col_index = new(ctx) ir_constant(c);
+      ir_dereference *const col = new(ctx) ir_dereference_array(src, col_index);
+
+      col->type = src->type->column_type();
+
+      return dereference_component(col, r);
+   }
+
+   assert(!"Should not get here.");
+   return NULL;
+}
+
+
+static ir_rvalue *
+process_array_constructor(exec_list *instructions,
+                         const glsl_type *constructor_type,
+                         YYLTYPE *loc, exec_list *parameters,
+                         struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+   /* Array constructors come in two forms: sized and unsized.  Sized array
+    * constructors look like 'vec4[2](a, b)', where 'a' and 'b' are vec4
+    * variables.  In this case the number of parameters must exactly match the
+    * specified size of the array.
+    *
+    * Unsized array constructors look like 'vec4[](a, b)', where 'a' and 'b'
+    * are vec4 variables.  In this case the size of the array being constructed
+    * is determined by the number of parameters.
+    *
+    * From page 52 (page 58 of the PDF) of the GLSL 1.50 spec:
+    *
+    *    "There must be exactly the same number of arguments as the size of
+    *    the array being constructed. If no size is present in the
+    *    constructor, then the array is explicitly sized to the number of
+    *    arguments provided. The arguments are assigned in order, starting at
+    *    element 0, to the elements of the constructed array. Each argument
+    *    must be the same type as the element type of the array, or be a type
+    *    that can be converted to the element type of the array according to
+    *    Section 4.1.10 "Implicit Conversions.""
+    */
+   exec_list actual_parameters;
+   const unsigned parameter_count =
+      process_parameters(instructions, &actual_parameters, parameters, state);
+
+   if ((parameter_count == 0)
+       || ((constructor_type->length != 0)
+          && (constructor_type->length != parameter_count))) {
+      const unsigned min_param = (constructor_type->length == 0)
+        ? 1 : constructor_type->length;
+
+      _mesa_glsl_error(loc, state, "array constructor must have %s %u "
+                      "parameter%s",
+                      (constructor_type->length != 0) ? "at least" : "exactly",
+                      min_param, (min_param <= 1) ? "" : "s");
+      return ir_call::get_error_instruction(ctx);
+   }
+
+   if (constructor_type->length == 0) {
+      constructor_type =
+        glsl_type::get_array_instance(constructor_type->element_type(),
+                                      parameter_count);
+      assert(constructor_type != NULL);
+      assert(constructor_type->length == parameter_count);
+   }
+
+   bool all_parameters_are_constant = true;
+
+   /* Type cast each parameter and, if possible, fold constants. */
+   foreach_list_safe(n, &actual_parameters) {
+      ir_rvalue *ir = (ir_rvalue *) n;
+      ir_rvalue *result = ir;
+
+      /* Apply implicit conversions (not the scalar constructor rules!) */
+      if (constructor_type->element_type()->is_float()) {
+        const glsl_type *desired_type =
+           glsl_type::get_instance(GLSL_TYPE_FLOAT,
+                                   ir->type->vector_elements,
+                                   ir->type->matrix_columns);
+        result = convert_component(ir, desired_type);
+      }
+
+      if (result->type != constructor_type->element_type()) {
+        _mesa_glsl_error(loc, state, "type error in array constructor: "
+                         "expected: %s, found %s",
+                         constructor_type->element_type()->name,
+                         result->type->name);
+      }
+
+      /* Attempt to convert the parameter to a constant valued expression.
+       * After doing so, track whether or not all the parameters to the
+       * constructor are trivially constant valued expressions.
+       */
+      ir_rvalue *const constant = result->constant_expression_value();
+
+      if (constant != NULL)
+         result = constant;
+      else
+         all_parameters_are_constant = false;
+
+      ir->replace_with(result);
+   }
+
+   if (all_parameters_are_constant)
+      return new(ctx) ir_constant(constructor_type, &actual_parameters);
+
+   ir_variable *var = new(ctx) ir_variable(constructor_type, "array_ctor",
+                                          ir_var_temporary);
+   instructions->push_tail(var);
+
+   int i = 0;
+   foreach_list(node, &actual_parameters) {
+      ir_rvalue *rhs = (ir_rvalue *) node;
+      ir_rvalue *lhs = new(ctx) ir_dereference_array(var,
+                                                    new(ctx) ir_constant(i));
+
+      ir_instruction *assignment = new(ctx) ir_assignment(lhs, rhs, NULL);
+      instructions->push_tail(assignment);
+
+      i++;
+   }
+
+   return new(ctx) ir_dereference_variable(var);
+}
+
+
+/**
+ * Try to convert a record constructor to a constant expression
+ */
+static ir_constant *
+constant_record_constructor(const glsl_type *constructor_type,
+                           exec_list *parameters, void *mem_ctx)
+{
+   foreach_list(node, parameters) {
+      ir_constant *constant = ((ir_instruction *) node)->as_constant();
+      if (constant == NULL)
+        return NULL;
+      node->replace_with(constant);
+   }
+
+   return new(mem_ctx) ir_constant(constructor_type, parameters);
+}
+
+
+/**
+ * Determine if a list consists of a single scalar r-value
+ */
+bool
+single_scalar_parameter(exec_list *parameters)
+{
+   const ir_rvalue *const p = (ir_rvalue *) parameters->head;
+   assert(((ir_rvalue *)p)->as_rvalue() != NULL);
+
+   return (p->type->is_scalar() && p->next->is_tail_sentinel());
+}
+
+
+/**
+ * Generate inline code for a vector constructor
+ *
+ * The generated constructor code will consist of a temporary variable
+ * declaration of the same type as the constructor.  A sequence of assignments
+ * from constructor parameters to the temporary will follow.
+ *
+ * \return
+ * An \c ir_dereference_variable of the temprorary generated in the constructor
+ * body.
+ */
+ir_rvalue *
+emit_inline_vector_constructor(const glsl_type *type,
+                              exec_list *instructions,
+                              exec_list *parameters,
+                              void *ctx)
+{
+   assert(!parameters->is_empty());
+
+   ir_variable *var = new(ctx) ir_variable(type, "vec_ctor", ir_var_temporary);
+   instructions->push_tail(var);
+
+   /* There are two kinds of vector constructors.
+    *
+    *  - Construct a vector from a single scalar by replicating that scalar to
+    *    all components of the vector.
+    *
+    *  - Construct a vector from an arbirary combination of vectors and
+    *    scalars.  The components of the constructor parameters are assigned
+    *    to the vector in order until the vector is full.
+    */
+   const unsigned lhs_components = type->components();
+   if (single_scalar_parameter(parameters)) {
+      ir_rvalue *first_param = (ir_rvalue *)parameters->head;
+      ir_rvalue *rhs = new(ctx) ir_swizzle(first_param, 0, 0, 0, 0,
+                                          lhs_components);
+      ir_dereference_variable *lhs = new(ctx) ir_dereference_variable(var);
+      const unsigned mask = (1U << lhs_components) - 1;
+
+      assert(rhs->type == lhs->type);
+
+      ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL, mask);
+      instructions->push_tail(inst);
+   } else {
+      unsigned base_component = 0;
+      ir_constant_data data;
+      unsigned constant_mask = 0;
+
+      memset(&data, 0, sizeof(data));
+
+      foreach_list(node, parameters) {
+        ir_rvalue *param = (ir_rvalue *) node;
+        unsigned rhs_components = param->type->components();
+
+        /* Do not try to assign more components to the vector than it has!
+         */
+        if ((rhs_components + base_component) > lhs_components) {
+           rhs_components = lhs_components - base_component;
+        }
+
+        const ir_constant *const c = param->as_constant();
+        if (c != NULL) {
+           for (unsigned i = 0; i < rhs_components; i++) {
+              switch (c->type->base_type) {
+              case GLSL_TYPE_UINT:
+                 data.u[i + base_component] = c->get_uint_component(i);
+                 break;
+              case GLSL_TYPE_INT:
+                 data.i[i + base_component] = c->get_int_component(i);
+                 break;
+              case GLSL_TYPE_FLOAT:
+                 data.f[i + base_component] = c->get_float_component(i);
+                 break;
+              case GLSL_TYPE_BOOL:
+                 data.b[i + base_component] = c->get_bool_component(i);
+                 break;
+              default:
+                 assert(!"Should not get here.");
+                 break;
+              }
+           }
+
+           /* Mask of fields to be written in the assignment.
+            */
+           constant_mask |= ((1U << rhs_components) - 1) << base_component;
+        }
+
+        /* Advance the component index by the number of components that were
+         * just assigned.
+         */
+        base_component += rhs_components;
+      }
+
+      if (constant_mask != 0) {
+        ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
+        ir_rvalue *rhs = new(ctx) ir_constant(var->type, &data);
+
+        ir_instruction *inst =
+           new(ctx) ir_assignment(lhs, rhs, NULL, constant_mask);
+        instructions->push_tail(inst);
+      }
+
+      base_component = 0;
+      foreach_list(node, parameters) {
+        ir_rvalue *param = (ir_rvalue *) node;
+        unsigned rhs_components = param->type->components();
+
+        /* Do not try to assign more components to the vector than it has!
+         */
+        if ((rhs_components + base_component) > lhs_components) {
+           rhs_components = lhs_components - base_component;
+        }
+
+        const ir_constant *const c = param->as_constant();
+        if (c == NULL) {
+           /* Generate a swizzle that puts the first element of the source at
+            * the location of the first element of the destination.
+            */
+           unsigned swiz[4] = { 0, 0, 0, 0 };
+           for (unsigned i = 0; i < rhs_components; i++)
+              swiz[i + base_component] = i;
+
+           /* Mask of fields to be written in the assignment.
+            */
+           const unsigned write_mask = ((1U << rhs_components) - 1)
+              << base_component;
+
+           ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
+           ir_rvalue *rhs = new(ctx) ir_swizzle(param, swiz, lhs_components);
+
+           ir_instruction *inst =
+              new(ctx) ir_assignment(lhs, rhs, NULL, write_mask);
+           instructions->push_tail(inst);
+        }
+
+        /* Advance the component index by the number of components that were
+         * just assigned.
+         */
+        base_component += rhs_components;
+      }
+   }
+   return new(ctx) ir_dereference_variable(var);
+}
+
+
+/**
+ * Generate assignment of a portion of a vector to a portion of a matrix column
+ *
+ * \param src_base  First component of the source to be used in assignment
+ * \param column    Column of destination to be assiged
+ * \param row_base  First component of the destination column to be assigned
+ * \param count     Number of components to be assigned
+ *
+ * \note
+ * \c src_base + \c count must be less than or equal to the number of components
+ * in the source vector.
+ */
+ir_instruction *
+assign_to_matrix_column(ir_variable *var, unsigned column, unsigned row_base,
+                       ir_rvalue *src, unsigned src_base, unsigned count,
+                       void *mem_ctx)
+{
+   ir_constant *col_idx = new(mem_ctx) ir_constant(column);
+   ir_dereference *column_ref = new(mem_ctx) ir_dereference_array(var, col_idx);
+
+   assert(column_ref->type->components() >= (row_base + count));
+   assert(src->type->components() >= (src_base + count));
+
+   /* Generate a swizzle that puts the first element of the source at the
+    * location of the first element of the destination.
+    */
+   unsigned swiz[4] = { src_base, src_base, src_base, src_base };
+   for (unsigned i = 0; i < count; i++)
+      swiz[i + row_base] = src_base + i;
+
+   ir_rvalue *const rhs =
+      new(mem_ctx) ir_swizzle(src, swiz, column_ref->type->components());
+
+   /* Mask of fields to be written in the assignment.
+    */
+   const unsigned write_mask = ((1U << count) - 1) << row_base;
+
+   return new(mem_ctx) ir_assignment(column_ref, rhs, NULL, write_mask);
+}
+
+
+/**
+ * Generate inline code for a matrix constructor
+ *
+ * The generated constructor code will consist of a temporary variable
+ * declaration of the same type as the constructor.  A sequence of assignments
+ * from constructor parameters to the temporary will follow.
+ *
+ * \return
+ * An \c ir_dereference_variable of the temprorary generated in the constructor
+ * body.
+ */
+ir_rvalue *
+emit_inline_matrix_constructor(const glsl_type *type,
+                              exec_list *instructions,
+                              exec_list *parameters,
+                              void *ctx)
+{
+   assert(!parameters->is_empty());
+
+   ir_variable *var = new(ctx) ir_variable(type, "mat_ctor", ir_var_temporary);
+   instructions->push_tail(var);
+
+   /* There are three kinds of matrix constructors.
+    *
+    *  - Construct a matrix from a single scalar by replicating that scalar to
+    *    along the diagonal of the matrix and setting all other components to
+    *    zero.
+    *
+    *  - Construct a matrix from an arbirary combination of vectors and
+    *    scalars.  The components of the constructor parameters are assigned
+    *    to the matrix in colum-major order until the matrix is full.
+    *
+    *  - Construct a matrix from a single matrix.  The source matrix is copied
+    *    to the upper left portion of the constructed matrix, and the remaining
+    *    elements take values from the identity matrix.
+    */
+   ir_rvalue *const first_param = (ir_rvalue *) parameters->head;
+   if (single_scalar_parameter(parameters)) {
+      /* Assign the scalar to the X component of a vec4, and fill the remaining
+       * components with zero.
+       */
+      ir_variable *rhs_var =
+        new(ctx) ir_variable(glsl_type::vec4_type, "mat_ctor_vec",
+                             ir_var_temporary);
+      instructions->push_tail(rhs_var);
+
+      ir_constant_data zero;
+      zero.f[0] = 0.0;
+      zero.f[1] = 0.0;
+      zero.f[2] = 0.0;
+      zero.f[3] = 0.0;
+
+      ir_instruction *inst =
+        new(ctx) ir_assignment(new(ctx) ir_dereference_variable(rhs_var),
+                               new(ctx) ir_constant(rhs_var->type, &zero),
+                               NULL);
+      instructions->push_tail(inst);
+
+      ir_dereference *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var);
+
+      inst = new(ctx) ir_assignment(rhs_ref, first_param, NULL, 0x01);
+      instructions->push_tail(inst);
+
+      /* Assign the temporary vector to each column of the destination matrix
+       * with a swizzle that puts the X component on the diagonal of the
+       * matrix.  In some cases this may mean that the X component does not
+       * get assigned into the column at all (i.e., when the matrix has more
+       * columns than rows).
+       */
+      static const unsigned rhs_swiz[4][4] = {
+        { 0, 1, 1, 1 },
+        { 1, 0, 1, 1 },
+        { 1, 1, 0, 1 },
+        { 1, 1, 1, 0 }
+      };
+
+      const unsigned cols_to_init = MIN2(type->matrix_columns,
+                                        type->vector_elements);
+      for (unsigned i = 0; i < cols_to_init; i++) {
+        ir_constant *const col_idx = new(ctx) ir_constant(i);
+        ir_rvalue *const col_ref = new(ctx) ir_dereference_array(var, col_idx);
+
+        ir_rvalue *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var);
+        ir_rvalue *const rhs = new(ctx) ir_swizzle(rhs_ref, rhs_swiz[i],
+                                                   type->vector_elements);
+
+        inst = new(ctx) ir_assignment(col_ref, rhs, NULL);
+        instructions->push_tail(inst);
+      }
+
+      for (unsigned i = cols_to_init; i < type->matrix_columns; i++) {
+        ir_constant *const col_idx = new(ctx) ir_constant(i);
+        ir_rvalue *const col_ref = new(ctx) ir_dereference_array(var, col_idx);
+
+        ir_rvalue *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var);
+        ir_rvalue *const rhs = new(ctx) ir_swizzle(rhs_ref, 1, 1, 1, 1,
+                                                   type->vector_elements);
+
+        inst = new(ctx) ir_assignment(col_ref, rhs, NULL);
+        instructions->push_tail(inst);
+      }
+   } else if (first_param->type->is_matrix()) {
+      /* From page 50 (56 of the PDF) of the GLSL 1.50 spec:
+       *
+       *     "If a matrix is constructed from a matrix, then each component
+       *     (column i, row j) in the result that has a corresponding
+       *     component (column i, row j) in the argument will be initialized
+       *     from there. All other components will be initialized to the
+       *     identity matrix. If a matrix argument is given to a matrix
+       *     constructor, it is an error to have any other arguments."
+       */
+      assert(first_param->next->is_tail_sentinel());
+      ir_rvalue *const src_matrix = first_param;
+
+      /* If the source matrix is smaller, pre-initialize the relavent parts of
+       * the destination matrix to the identity matrix.
+       */
+      if ((src_matrix->type->matrix_columns < var->type->matrix_columns)
+         || (src_matrix->type->vector_elements < var->type->vector_elements)) {
+
+        /* If the source matrix has fewer rows, every column of the destination
+         * must be initialized.  Otherwise only the columns in the destination
+         * that do not exist in the source must be initialized.
+         */
+        unsigned col =
+           (src_matrix->type->vector_elements < var->type->vector_elements)
+           ? 0 : src_matrix->type->matrix_columns;
+
+        const glsl_type *const col_type = var->type->column_type();
+        for (/* empty */; col < var->type->matrix_columns; col++) {
+           ir_constant_data ident;
+
+           ident.f[0] = 0.0;
+           ident.f[1] = 0.0;
+           ident.f[2] = 0.0;
+           ident.f[3] = 0.0;
+
+           ident.f[col] = 1.0;
+
+           ir_rvalue *const rhs = new(ctx) ir_constant(col_type, &ident);
+
+           ir_rvalue *const lhs =
+              new(ctx) ir_dereference_array(var, new(ctx) ir_constant(col));
+
+           ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL);
+           instructions->push_tail(inst);
+        }
+      }
+
+      /* Assign columns from the source matrix to the destination matrix.
+       *
+       * Since the parameter will be used in the RHS of multiple assignments,
+       * generate a temporary and copy the paramter there.
+       */
+      ir_variable *const rhs_var =
+        new(ctx) ir_variable(first_param->type, "mat_ctor_mat",
+                             ir_var_temporary);
+      instructions->push_tail(rhs_var);
+
+      ir_dereference *const rhs_var_ref =
+        new(ctx) ir_dereference_variable(rhs_var);
+      ir_instruction *const inst =
+        new(ctx) ir_assignment(rhs_var_ref, first_param, NULL);
+      instructions->push_tail(inst);
+
+      const unsigned last_row = MIN2(src_matrix->type->vector_elements,
+                                    var->type->vector_elements);
+      const unsigned last_col = MIN2(src_matrix->type->matrix_columns,
+                                    var->type->matrix_columns);
+
+      unsigned swiz[4] = { 0, 0, 0, 0 };
+      for (unsigned i = 1; i < src_matrix->type->vector_elements; i++)
+        swiz[i] = i;
+
+      const unsigned write_mask = (1U << last_row) - 1;
+
+      for (unsigned i = 0; i < last_col; i++) {
+        ir_dereference *const lhs =
+           new(ctx) ir_dereference_array(var, new(ctx) ir_constant(i));
+        ir_rvalue *const rhs_col =
+           new(ctx) ir_dereference_array(rhs_var, new(ctx) ir_constant(i));
+
+        /* If one matrix has columns that are smaller than the columns of the
+         * other matrix, wrap the column access of the larger with a swizzle
+         * so that the LHS and RHS of the assignment have the same size (and
+         * therefore have the same type).
+         *
+         * It would be perfectly valid to unconditionally generate the
+         * swizzles, this this will typically result in a more compact IR tree.
+         */
+        ir_rvalue *rhs;
+        if (lhs->type->vector_elements != rhs_col->type->vector_elements) {
+           rhs = new(ctx) ir_swizzle(rhs_col, swiz,
+                                     lhs->type->vector_elements);
+        } else {
+           rhs = rhs_col;
+        }
+
+        assert(lhs->type == rhs->type);
+
+        ir_instruction *inst =
+           new(ctx) ir_assignment(lhs, rhs, NULL, write_mask);
+        instructions->push_tail(inst);
+      }
+   } else {
+      const unsigned cols = type->matrix_columns;
+      const unsigned rows = type->vector_elements;
+      unsigned col_idx = 0;
+      unsigned row_idx = 0;
+
+      foreach_list (node, parameters) {
+        ir_rvalue *const rhs = (ir_rvalue *) node;
+        const unsigned components_remaining_this_column = rows - row_idx;
+        unsigned rhs_components = rhs->type->components();
+        unsigned rhs_base = 0;
+
+        /* Since the parameter might be used in the RHS of two assignments,
+         * generate a temporary and copy the paramter there.
+         */
+        ir_variable *rhs_var =
+           new(ctx) ir_variable(rhs->type, "mat_ctor_vec", ir_var_temporary);
+        instructions->push_tail(rhs_var);
+
+        ir_dereference *rhs_var_ref =
+           new(ctx) ir_dereference_variable(rhs_var);
+        ir_instruction *inst = new(ctx) ir_assignment(rhs_var_ref, rhs, NULL);
+        instructions->push_tail(inst);
+
+        /* Assign the current parameter to as many components of the matrix
+         * as it will fill.
+         *
+         * NOTE: A single vector parameter can span two matrix columns.  A
+         * single vec4, for example, can completely fill a mat2.
+         */
+        if (rhs_components >= components_remaining_this_column) {
+           const unsigned count = MIN2(rhs_components,
+                                       components_remaining_this_column);
+
+           rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var);
+
+           ir_instruction *inst = assign_to_matrix_column(var, col_idx,
+                                                          row_idx,
+                                                          rhs_var_ref, 0,
+                                                          count, ctx);
+           instructions->push_tail(inst);
+
+           rhs_base = count;
+
+           col_idx++;
+           row_idx = 0;
+        }
+
+        /* If there is data left in the parameter and components left to be
+         * set in the destination, emit another assignment.  It is possible
+         * that the assignment could be of a vec4 to the last element of the
+         * matrix.  In this case col_idx==cols, but there is still data
+         * left in the source parameter.  Obviously, don't emit an assignment
+         * to data outside the destination matrix.
+         */
+        if ((col_idx < cols) && (rhs_base < rhs_components)) {
+           const unsigned count = rhs_components - rhs_base;
+
+           rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var);
+
+           ir_instruction *inst = assign_to_matrix_column(var, col_idx,
+                                                          row_idx,
+                                                          rhs_var_ref,
+                                                          rhs_base,
+                                                          count, ctx);
+           instructions->push_tail(inst);
+
+           row_idx += count;
+        }
+      }
+   }
+
+   return new(ctx) ir_dereference_variable(var);
+}
+
+
+ir_rvalue *
+emit_inline_record_constructor(const glsl_type *type,
+                              exec_list *instructions,
+                              exec_list *parameters,
+                              void *mem_ctx)
+{
+   ir_variable *const var =
+      new(mem_ctx) ir_variable(type, "record_ctor", ir_var_temporary);
+   ir_dereference_variable *const d = new(mem_ctx) ir_dereference_variable(var);
+
+   instructions->push_tail(var);
+
+   exec_node *node = parameters->head;
+   for (unsigned i = 0; i < type->length; i++) {
+      assert(!node->is_tail_sentinel());
+
+      ir_dereference *const lhs =
+        new(mem_ctx) ir_dereference_record(d->clone(mem_ctx, NULL),
+                                           type->fields.structure[i].name);
+
+      ir_rvalue *const rhs = ((ir_instruction *) node)->as_rvalue();
+      assert(rhs != NULL);
+
+      ir_instruction *const assign = new(mem_ctx) ir_assignment(lhs, rhs, NULL);
+
+      instructions->push_tail(assign);
+      node = node->next;
+   }
+
+   return d;
+}
+
+
+ir_rvalue *
+ast_function_expression::hir(exec_list *instructions,
+                            struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+   /* There are three sorts of function calls.
+    *
+    * 1. constructors - The first subexpression is an ast_type_specifier.
+    * 2. methods - Only the .length() method of array types.
+    * 3. functions - Calls to regular old functions.
+    *
+    * Method calls are actually detected when the ast_field_selection
+    * expression is handled.
+    */
+   if (is_constructor()) {
+      const ast_type_specifier *type = (ast_type_specifier *) subexpressions[0];
+      YYLTYPE loc = type->get_location();
+      const char *name;
+
+      const glsl_type *const constructor_type = type->glsl_type(& name, state);
+
+
+      /* Constructors for samplers are illegal.
+       */
+      if (constructor_type->is_sampler()) {
+        _mesa_glsl_error(& loc, state, "cannot construct sampler type `%s'",
+                         constructor_type->name);
+        return ir_call::get_error_instruction(ctx);
+      }
+
+      if (constructor_type->is_array()) {
+        if (state->language_version <= 110) {
+           _mesa_glsl_error(& loc, state,
+                            "array constructors forbidden in GLSL 1.10");
+           return ir_call::get_error_instruction(ctx);
+        }
+
+        return process_array_constructor(instructions, constructor_type,
+                                         & loc, &this->expressions, state);
+      }
+
+
+      /* There are two kinds of constructor call.  Constructors for built-in
+       * language types, such as mat4 and vec2, are free form.  The only
+       * requirement is that the parameters must provide enough values of the
+       * correct scalar type.  Constructors for arrays and structures must
+       * have the exact number of parameters with matching types in the
+       * correct order.  These constructors follow essentially the same type
+       * matching rules as functions.
+       */
+      if (!constructor_type->is_numeric() && !constructor_type->is_boolean())
+        return ir_call::get_error_instruction(ctx);
+
+      /* Total number of components of the type being constructed. */
+      const unsigned type_components = constructor_type->components();
+
+      /* Number of components from parameters that have actually been
+       * consumed.  This is used to perform several kinds of error checking.
+       */
+      unsigned components_used = 0;
+
+      unsigned matrix_parameters = 0;
+      unsigned nonmatrix_parameters = 0;
+      exec_list actual_parameters;
+
+      foreach_list (n, &this->expressions) {
+        ast_node *ast = exec_node_data(ast_node, n, link);
+        ir_rvalue *result = ast->hir(instructions, state)->as_rvalue();
+
+        /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec:
+         *
+         *    "It is an error to provide extra arguments beyond this
+         *    last used argument."
+         */
+        if (components_used >= type_components) {
+           _mesa_glsl_error(& loc, state, "too many parameters to `%s' "
+                            "constructor",
+                            constructor_type->name);
+           return ir_call::get_error_instruction(ctx);
+        }
+
+        if (!result->type->is_numeric() && !result->type->is_boolean()) {
+           _mesa_glsl_error(& loc, state, "cannot construct `%s' from a "
+                            "non-numeric data type",
+                            constructor_type->name);
+           return ir_call::get_error_instruction(ctx);
+        }
+
+        /* Count the number of matrix and nonmatrix parameters.  This
+         * is used below to enforce some of the constructor rules.
+         */
+        if (result->type->is_matrix())
+           matrix_parameters++;
+        else
+           nonmatrix_parameters++;
+
+        actual_parameters.push_tail(result);
+        components_used += result->type->components();
+      }
+
+      /* From page 28 (page 34 of the PDF) of the GLSL 1.10 spec:
+       *
+       *    "It is an error to construct matrices from other matrices. This
+       *    is reserved for future use."
+       */
+      if ((state->language_version <= 110) && (matrix_parameters > 0)
+         && constructor_type->is_matrix()) {
+        _mesa_glsl_error(& loc, state, "cannot construct `%s' from a "
+                         "matrix in GLSL 1.10",
+                         constructor_type->name);
+        return ir_call::get_error_instruction(ctx);
+      }
+
+      /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec:
+       *
+       *    "If a matrix argument is given to a matrix constructor, it is
+       *    an error to have any other arguments."
+       */
+      if ((matrix_parameters > 0)
+         && ((matrix_parameters + nonmatrix_parameters) > 1)
+         && constructor_type->is_matrix()) {
+        _mesa_glsl_error(& loc, state, "for matrix `%s' constructor, "
+                         "matrix must be only parameter",
+                         constructor_type->name);
+        return ir_call::get_error_instruction(ctx);
+      }
+
+      /* From page 28 (page 34 of the PDF) of the GLSL 1.10 spec:
+       *
+       *    "In these cases, there must be enough components provided in the
+       *    arguments to provide an initializer for every component in the
+       *    constructed value."
+       */
+      if (components_used < type_components && components_used != 1
+         && matrix_parameters == 0) {
+        _mesa_glsl_error(& loc, state, "too few components to construct "
+                         "`%s'",
+                         constructor_type->name);
+        return ir_call::get_error_instruction(ctx);
+      }
+
+      /* Later, we cast each parameter to the same base type as the
+       * constructor.  Since there are no non-floating point matrices, we
+       * need to break them up into a series of column vectors.
+       */
+      if (constructor_type->base_type != GLSL_TYPE_FLOAT) {
+        foreach_list_safe(n, &actual_parameters) {
+           ir_rvalue *matrix = (ir_rvalue *) n;
+
+           if (!matrix->type->is_matrix())
+              continue;
+
+           /* Create a temporary containing the matrix. */
+           ir_variable *var = new(ctx) ir_variable(matrix->type, "matrix_tmp",
+                                                   ir_var_temporary);
+           instructions->push_tail(var);
+           instructions->push_tail(new(ctx) ir_assignment(new(ctx)
+              ir_dereference_variable(var), matrix, NULL));
+           var->constant_value = matrix->constant_expression_value();
+
+           /* Replace the matrix with dereferences of its columns. */
+           for (int i = 0; i < matrix->type->matrix_columns; i++) {
+              matrix->insert_before(new (ctx) ir_dereference_array(var,
+                 new(ctx) ir_constant(i)));
+           }
+           matrix->remove();
+        }
+      }
+
+      bool all_parameters_are_constant = true;
+
+      /* Type cast each parameter and, if possible, fold constants.*/
+      foreach_list_safe(n, &actual_parameters) {
+        ir_rvalue *ir = (ir_rvalue *) n;
+
+        const glsl_type *desired_type =
+           glsl_type::get_instance(constructor_type->base_type,
+                                   ir->type->vector_elements,
+                                   ir->type->matrix_columns);
+        ir_rvalue *result = convert_component(ir, desired_type);
+
+        /* Attempt to convert the parameter to a constant valued expression.
+         * After doing so, track whether or not all the parameters to the
+         * constructor are trivially constant valued expressions.
+         */
+        ir_rvalue *const constant = result->constant_expression_value();
+
+        if (constant != NULL)
+           result = constant;
+        else
+           all_parameters_are_constant = false;
+
+        if (result != ir) {
+           ir->replace_with(result);
+        }
+      }
+
+      /* If all of the parameters are trivially constant, create a
+       * constant representing the complete collection of parameters.
+       */
+      if (all_parameters_are_constant) {
+        return new(ctx) ir_constant(constructor_type, &actual_parameters);
+      } else if (constructor_type->is_scalar()) {
+        return dereference_component((ir_rvalue *) actual_parameters.head,
+                                     0);
+      } else if (constructor_type->is_vector()) {
+        return emit_inline_vector_constructor(constructor_type,
+                                              instructions,
+                                              &actual_parameters,
+                                              ctx);
+      } else {
+        assert(constructor_type->is_matrix());
+        return emit_inline_matrix_constructor(constructor_type,
+                                              instructions,
+                                              &actual_parameters,
+                                              ctx);
+      }
+   } else {
+      const ast_expression *id = subexpressions[0];
+      YYLTYPE loc = id->get_location();
+      exec_list actual_parameters;
+
+      process_parameters(instructions, &actual_parameters, &this->expressions,
+                        state);
+
+      const glsl_type *const type =
+        state->symbols->get_type(id->primary_expression.identifier);
+
+      if ((type != NULL) && type->is_record()) {
+        exec_node *node = actual_parameters.head;
+        for (unsigned i = 0; i < type->length; i++) {
+           ir_rvalue *ir = (ir_rvalue *) node;
+
+           if (node->is_tail_sentinel()) {
+              _mesa_glsl_error(&loc, state,
+                               "insufficient parameters to constructor "
+                               "for `%s'",
+                               type->name);
+              return ir_call::get_error_instruction(ctx);
+           }
+
+           if (apply_implicit_conversion(type->fields.structure[i].type, ir,
+                                         state)) {
+              node->replace_with(ir);
+           } else {
+              _mesa_glsl_error(&loc, state,
+                               "parameter type mismatch in constructor "
+                               "for `%s.%s' (%s vs %s)",
+                               type->name,
+                               type->fields.structure[i].name,
+                               ir->type->name,
+                               type->fields.structure[i].type->name);
+              return ir_call::get_error_instruction(ctx);;
+           }
+
+           node = node->next;
+        }
+
+        if (!node->is_tail_sentinel()) {
+           _mesa_glsl_error(&loc, state, "too many parameters in constructor "
+                            "for `%s'", type->name);
+           return ir_call::get_error_instruction(ctx);
+        }
+
+        ir_rvalue *const constant =
+           constant_record_constructor(type, &actual_parameters, state);
+
+        return (constant != NULL)
+           ? constant
+           : emit_inline_record_constructor(type, instructions,
+                                            &actual_parameters, state);
+      }
+
+      return match_function_by_name(instructions, 
+                                   id->primary_expression.identifier, & loc,
+                                   &actual_parameters, state);
+   }
+
+   return ir_call::get_error_instruction(ctx);
+}
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
new file mode 100644 (file)
index 0000000..762f802
--- /dev/null
@@ -0,0 +1,2751 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ast_to_hir.c
+ * Convert abstract syntax to to high-level intermediate reprensentation (HIR).
+ *
+ * During the conversion to HIR, the majority of the symantic checking is
+ * preformed on the program.  This includes:
+ *
+ *    * Symbol table management
+ *    * Type checking
+ *    * Function binding
+ *
+ * The majority of this work could be done during parsing, and the parser could
+ * probably generate HIR directly.  However, this results in frequent changes
+ * to the parser code.  Since we do not assume that every system this complier
+ * is built on will have Flex and Bison installed, we have to store the code
+ * generated by these tools in our version control system.  In other parts of
+ * the system we've seen problems where a parser was changed but the generated
+ * code was not committed, merge conflicts where created because two developers
+ * had slightly different versions of Bison installed, etc.
+ *
+ * I have also noticed that running Bison generated parsers in GDB is very
+ * irritating.  When you get a segfault on '$$ = $1->foo', you can't very
+ * well 'print $1' in GDB.
+ *
+ * As a result, my preference is to put as little C code as possible in the
+ * parser (and lexer) sources.
+ */
+
+#include "main/core.h" /* for struct gl_extensions */
+#include "glsl_symbol_table.h"
+#include "glsl_parser_extras.h"
+#include "ast.h"
+#include "glsl_types.h"
+#include "ir.h"
+
+void
+_mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
+{
+   _mesa_glsl_initialize_variables(instructions, state);
+   _mesa_glsl_initialize_functions(instructions, state);
+
+   state->current_function = NULL;
+
+   /* Section 4.2 of the GLSL 1.20 specification states:
+    * "The built-in functions are scoped in a scope outside the global scope
+    *  users declare global variables in.  That is, a shader's global scope,
+    *  available for user-defined functions and global variables, is nested
+    *  inside the scope containing the built-in functions."
+    *
+    * Since built-in functions like ftransform() access built-in variables,
+    * it follows that those must be in the outer scope as well.
+    *
+    * We push scope here to create this nesting effect...but don't pop.
+    * This way, a shader's globals are still in the symbol table for use
+    * by the linker.
+    */
+   state->symbols->push_scope();
+
+   foreach_list_typed (ast_node, ast, link, & state->translation_unit)
+      ast->hir(instructions, state);
+}
+
+
+/**
+ * If a conversion is available, convert one operand to a different type
+ *
+ * The \c from \c ir_rvalue is converted "in place".
+ *
+ * \param to     Type that the operand it to be converted to
+ * \param from   Operand that is being converted
+ * \param state  GLSL compiler state
+ *
+ * \return
+ * If a conversion is possible (or unnecessary), \c true is returned.
+ * Otherwise \c false is returned.
+ */
+bool
+apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from,
+                         struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+   if (to->base_type == from->type->base_type)
+      return true;
+
+   /* This conversion was added in GLSL 1.20.  If the compilation mode is
+    * GLSL 1.10, the conversion is skipped.
+    */
+   if (state->language_version < 120)
+      return false;
+
+   /* From page 27 (page 33 of the PDF) of the GLSL 1.50 spec:
+    *
+    *    "There are no implicit array or structure conversions. For
+    *    example, an array of int cannot be implicitly converted to an
+    *    array of float. There are no implicit conversions between
+    *    signed and unsigned integers."
+    */
+   /* FINISHME: The above comment is partially a lie.  There is int/uint
+    * FINISHME: conversion for immediate constants.
+    */
+   if (!to->is_float() || !from->type->is_numeric())
+      return false;
+
+   /* Convert to a floating point type with the same number of components
+    * as the original type - i.e. int to float, not int to vec4.
+    */
+   to = glsl_type::get_instance(GLSL_TYPE_FLOAT, from->type->vector_elements,
+                               from->type->matrix_columns);
+
+   switch (from->type->base_type) {
+   case GLSL_TYPE_INT:
+      from = new(ctx) ir_expression(ir_unop_i2f, to, from, NULL);
+      break;
+   case GLSL_TYPE_UINT:
+      from = new(ctx) ir_expression(ir_unop_u2f, to, from, NULL);
+      break;
+   case GLSL_TYPE_BOOL:
+      from = new(ctx) ir_expression(ir_unop_b2f, to, from, NULL);
+      break;
+   default:
+      assert(0);
+   }
+
+   return true;
+}
+
+
+static const struct glsl_type *
+arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
+                      bool multiply,
+                      struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
+{
+   const glsl_type *type_a = value_a->type;
+   const glsl_type *type_b = value_b->type;
+
+   /* From GLSL 1.50 spec, page 56:
+    *
+    *    "The arithmetic binary operators add (+), subtract (-),
+    *    multiply (*), and divide (/) operate on integer and
+    *    floating-point scalars, vectors, and matrices."
+    */
+   if (!type_a->is_numeric() || !type_b->is_numeric()) {
+      _mesa_glsl_error(loc, state,
+                      "Operands to arithmetic operators must be numeric");
+      return glsl_type::error_type;
+   }
+
+
+   /*    "If one operand is floating-point based and the other is
+    *    not, then the conversions from Section 4.1.10 "Implicit
+    *    Conversions" are applied to the non-floating-point-based operand."
+    */
+   if (!apply_implicit_conversion(type_a, value_b, state)
+       && !apply_implicit_conversion(type_b, value_a, state)) {
+      _mesa_glsl_error(loc, state,
+                      "Could not implicitly convert operands to "
+                      "arithmetic operator");
+      return glsl_type::error_type;
+   }
+   type_a = value_a->type;
+   type_b = value_b->type;
+
+   /*    "If the operands are integer types, they must both be signed or
+    *    both be unsigned."
+    *
+    * From this rule and the preceeding conversion it can be inferred that
+    * both types must be GLSL_TYPE_FLOAT, or GLSL_TYPE_UINT, or GLSL_TYPE_INT.
+    * The is_numeric check above already filtered out the case where either
+    * type is not one of these, so now the base types need only be tested for
+    * equality.
+    */
+   if (type_a->base_type != type_b->base_type) {
+      _mesa_glsl_error(loc, state,
+                      "base type mismatch for arithmetic operator");
+      return glsl_type::error_type;
+   }
+
+   /*    "All arithmetic binary operators result in the same fundamental type
+    *    (signed integer, unsigned integer, or floating-point) as the
+    *    operands they operate on, after operand type conversion. After
+    *    conversion, the following cases are valid
+    *
+    *    * The two operands are scalars. In this case the operation is
+    *      applied, resulting in a scalar."
+    */
+   if (type_a->is_scalar() && type_b->is_scalar())
+      return type_a;
+
+   /*   "* One operand is a scalar, and the other is a vector or matrix.
+    *      In this case, the scalar operation is applied independently to each
+    *      component of the vector or matrix, resulting in the same size
+    *      vector or matrix."
+    */
+   if (type_a->is_scalar()) {
+      if (!type_b->is_scalar())
+        return type_b;
+   } else if (type_b->is_scalar()) {
+      return type_a;
+   }
+
+   /* All of the combinations of <scalar, scalar>, <vector, scalar>,
+    * <scalar, vector>, <scalar, matrix>, and <matrix, scalar> have been
+    * handled.
+    */
+   assert(!type_a->is_scalar());
+   assert(!type_b->is_scalar());
+
+   /*   "* The two operands are vectors of the same size. In this case, the
+    *      operation is done component-wise resulting in the same size
+    *      vector."
+    */
+   if (type_a->is_vector() && type_b->is_vector()) {
+      if (type_a == type_b) {
+        return type_a;
+      } else {
+        _mesa_glsl_error(loc, state,
+                         "vector size mismatch for arithmetic operator");
+        return glsl_type::error_type;
+      }
+   }
+
+   /* All of the combinations of <scalar, scalar>, <vector, scalar>,
+    * <scalar, vector>, <scalar, matrix>, <matrix, scalar>, and
+    * <vector, vector> have been handled.  At least one of the operands must
+    * be matrix.  Further, since there are no integer matrix types, the base
+    * type of both operands must be float.
+    */
+   assert(type_a->is_matrix() || type_b->is_matrix());
+   assert(type_a->base_type == GLSL_TYPE_FLOAT);
+   assert(type_b->base_type == GLSL_TYPE_FLOAT);
+
+   /*   "* The operator is add (+), subtract (-), or divide (/), and the
+    *      operands are matrices with the same number of rows and the same
+    *      number of columns. In this case, the operation is done component-
+    *      wise resulting in the same size matrix."
+    *    * The operator is multiply (*), where both operands are matrices or
+    *      one operand is a vector and the other a matrix. A right vector
+    *      operand is treated as a column vector and a left vector operand as a
+    *      row vector. In all these cases, it is required that the number of
+    *      columns of the left operand is equal to the number of rows of the
+    *      right operand. Then, the multiply (*) operation does a linear
+    *      algebraic multiply, yielding an object that has the same number of
+    *      rows as the left operand and the same number of columns as the right
+    *      operand. Section 5.10 "Vector and Matrix Operations" explains in
+    *      more detail how vectors and matrices are operated on."
+    */
+   if (! multiply) {
+      if (type_a == type_b)
+        return type_a;
+   } else {
+      if (type_a->is_matrix() && type_b->is_matrix()) {
+        /* Matrix multiply.  The columns of A must match the rows of B.  Given
+         * the other previously tested constraints, this means the vector type
+         * of a row from A must be the same as the vector type of a column from
+         * B.
+         */
+        if (type_a->row_type() == type_b->column_type()) {
+           /* The resulting matrix has the number of columns of matrix B and
+            * the number of rows of matrix A.  We get the row count of A by
+            * looking at the size of a vector that makes up a column.  The
+            * transpose (size of a row) is done for B.
+            */
+           const glsl_type *const type =
+              glsl_type::get_instance(type_a->base_type,
+                                      type_a->column_type()->vector_elements,
+                                      type_b->row_type()->vector_elements);
+           assert(type != glsl_type::error_type);
+
+           return type;
+        }
+      } else if (type_a->is_matrix()) {
+        /* A is a matrix and B is a column vector.  Columns of A must match
+         * rows of B.  Given the other previously tested constraints, this
+         * means the vector type of a row from A must be the same as the
+         * vector the type of B.
+         */
+        if (type_a->row_type() == type_b) {
+           /* The resulting vector has a number of elements equal to
+            * the number of rows of matrix A. */
+           const glsl_type *const type =
+              glsl_type::get_instance(type_a->base_type,
+                                      type_a->column_type()->vector_elements,
+                                      1);
+           assert(type != glsl_type::error_type);
+
+           return type;
+        }
+      } else {
+        assert(type_b->is_matrix());
+
+        /* A is a row vector and B is a matrix.  Columns of A must match rows
+         * of B.  Given the other previously tested constraints, this means
+         * the type of A must be the same as the vector type of a column from
+         * B.
+         */
+        if (type_a == type_b->column_type()) {
+           /* The resulting vector has a number of elements equal to
+            * the number of columns of matrix B. */
+           const glsl_type *const type =
+              glsl_type::get_instance(type_a->base_type,
+                                      type_b->row_type()->vector_elements,
+                                      1);
+           assert(type != glsl_type::error_type);
+
+           return type;
+        }
+      }
+
+      _mesa_glsl_error(loc, state, "size mismatch for matrix multiplication");
+      return glsl_type::error_type;
+   }
+
+
+   /*    "All other cases are illegal."
+    */
+   _mesa_glsl_error(loc, state, "type mismatch");
+   return glsl_type::error_type;
+}
+
+
+static const struct glsl_type *
+unary_arithmetic_result_type(const struct glsl_type *type,
+                            struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
+{
+   /* From GLSL 1.50 spec, page 57:
+    *
+    *    "The arithmetic unary operators negate (-), post- and pre-increment
+    *     and decrement (-- and ++) operate on integer or floating-point
+    *     values (including vectors and matrices). All unary operators work
+    *     component-wise on their operands. These result with the same type
+    *     they operated on."
+    */
+   if (!type->is_numeric()) {
+      _mesa_glsl_error(loc, state,
+                      "Operands to arithmetic operators must be numeric");
+      return glsl_type::error_type;
+   }
+
+   return type;
+}
+
+
+static const struct glsl_type *
+modulus_result_type(const struct glsl_type *type_a,
+                   const struct glsl_type *type_b,
+                   struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
+{
+   /* From GLSL 1.50 spec, page 56:
+    *    "The operator modulus (%) operates on signed or unsigned integers or
+    *    integer vectors. The operand types must both be signed or both be
+    *    unsigned."
+    */
+   if (!type_a->is_integer() || !type_b->is_integer()
+       || (type_a->base_type != type_b->base_type)) {
+      _mesa_glsl_error(loc, state, "type mismatch");
+      return glsl_type::error_type;
+   }
+
+   /*    "The operands cannot be vectors of differing size. If one operand is
+    *    a scalar and the other vector, then the scalar is applied component-
+    *    wise to the vector, resulting in the same type as the vector. If both
+    *    are vectors of the same size, the result is computed component-wise."
+    */
+   if (type_a->is_vector()) {
+      if (!type_b->is_vector()
+         || (type_a->vector_elements == type_b->vector_elements))
+        return type_a;
+   } else
+      return type_b;
+
+   /*    "The operator modulus (%) is not defined for any other data types
+    *    (non-integer types)."
+    */
+   _mesa_glsl_error(loc, state, "type mismatch");
+   return glsl_type::error_type;
+}
+
+
+static const struct glsl_type *
+relational_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
+                      struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
+{
+   const glsl_type *type_a = value_a->type;
+   const glsl_type *type_b = value_b->type;
+
+   /* From GLSL 1.50 spec, page 56:
+    *    "The relational operators greater than (>), less than (<), greater
+    *    than or equal (>=), and less than or equal (<=) operate only on
+    *    scalar integer and scalar floating-point expressions."
+    */
+   if (!type_a->is_numeric()
+       || !type_b->is_numeric()
+       || !type_a->is_scalar()
+       || !type_b->is_scalar()) {
+      _mesa_glsl_error(loc, state,
+                      "Operands to relational operators must be scalar and "
+                      "numeric");
+      return glsl_type::error_type;
+   }
+
+   /*    "Either the operands' types must match, or the conversions from
+    *    Section 4.1.10 "Implicit Conversions" will be applied to the integer
+    *    operand, after which the types must match."
+    */
+   if (!apply_implicit_conversion(type_a, value_b, state)
+       && !apply_implicit_conversion(type_b, value_a, state)) {
+      _mesa_glsl_error(loc, state,
+                      "Could not implicitly convert operands to "
+                      "relational operator");
+      return glsl_type::error_type;
+   }
+   type_a = value_a->type;
+   type_b = value_b->type;
+
+   if (type_a->base_type != type_b->base_type) {
+      _mesa_glsl_error(loc, state, "base type mismatch");
+      return glsl_type::error_type;
+   }
+
+   /*    "The result is scalar Boolean."
+    */
+   return glsl_type::bool_type;
+}
+
+
+/**
+ * Validates that a value can be assigned to a location with a specified type
+ *
+ * Validates that \c rhs can be assigned to some location.  If the types are
+ * not an exact match but an automatic conversion is possible, \c rhs will be
+ * converted.
+ *
+ * \return
+ * \c NULL if \c rhs cannot be assigned to a location with type \c lhs_type.
+ * Otherwise the actual RHS to be assigned will be returned.  This may be
+ * \c rhs, or it may be \c rhs after some type conversion.
+ *
+ * \note
+ * In addition to being used for assignments, this function is used to
+ * type-check return values.
+ */
+ir_rvalue *
+validate_assignment(struct _mesa_glsl_parse_state *state,
+                   const glsl_type *lhs_type, ir_rvalue *rhs)
+{
+   const glsl_type *rhs_type = rhs->type;
+
+   /* If there is already some error in the RHS, just return it.  Anything
+    * else will lead to an avalanche of error message back to the user.
+    */
+   if (rhs_type->is_error())
+      return rhs;
+
+   /* If the types are identical, the assignment can trivially proceed.
+    */
+   if (rhs_type == lhs_type)
+      return rhs;
+
+   /* If the array element types are the same and the size of the LHS is zero,
+    * the assignment is okay.
+    *
+    * Note: Whole-array assignments are not permitted in GLSL 1.10, but this
+    * is handled by ir_dereference::is_lvalue.
+    */
+   if (lhs_type->is_array() && rhs->type->is_array()
+       && (lhs_type->element_type() == rhs->type->element_type())
+       && (lhs_type->array_size() == 0)) {
+      return rhs;
+   }
+
+   /* Check for implicit conversion in GLSL 1.20 */
+   if (apply_implicit_conversion(lhs_type, rhs, state)) {
+      rhs_type = rhs->type;
+      if (rhs_type == lhs_type)
+        return rhs;
+   }
+
+   return NULL;
+}
+
+ir_rvalue *
+do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
+             ir_rvalue *lhs, ir_rvalue *rhs,
+             YYLTYPE lhs_loc)
+{
+   void *ctx = state;
+   bool error_emitted = (lhs->type->is_error() || rhs->type->is_error());
+
+   if (!error_emitted) {
+      if (!lhs->is_lvalue()) {
+        _mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment");
+        error_emitted = true;
+      }
+   }
+
+   ir_rvalue *new_rhs = validate_assignment(state, lhs->type, rhs);
+   if (new_rhs == NULL) {
+      _mesa_glsl_error(& lhs_loc, state, "type mismatch");
+   } else {
+      rhs = new_rhs;
+
+      /* If the LHS array was not declared with a size, it takes it size from
+       * the RHS.  If the LHS is an l-value and a whole array, it must be a
+       * dereference of a variable.  Any other case would require that the LHS
+       * is either not an l-value or not a whole array.
+       */
+      if (lhs->type->array_size() == 0) {
+        ir_dereference *const d = lhs->as_dereference();
+
+        assert(d != NULL);
+
+        ir_variable *const var = d->variable_referenced();
+
+        assert(var != NULL);
+
+        if (var->max_array_access >= unsigned(rhs->type->array_size())) {
+           /* FINISHME: This should actually log the location of the RHS. */
+           _mesa_glsl_error(& lhs_loc, state, "array size must be > %u due to "
+                            "previous access",
+                            var->max_array_access);
+        }
+
+        var->type = glsl_type::get_array_instance(lhs->type->element_type(),
+                                                  rhs->type->array_size());
+        d->type = var->type;
+      }
+   }
+
+   /* Most callers of do_assignment (assign, add_assign, pre_inc/dec,
+    * but not post_inc) need the converted assigned value as an rvalue
+    * to handle things like:
+    *
+    * i = j += 1;
+    *
+    * So we always just store the computed value being assigned to a
+    * temporary and return a deref of that temporary.  If the rvalue
+    * ends up not being used, the temp will get copy-propagated out.
+    */
+   ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp",
+                                          ir_var_temporary);
+   ir_dereference_variable *deref_var = new(ctx) ir_dereference_variable(var);
+   instructions->push_tail(var);
+   instructions->push_tail(new(ctx) ir_assignment(deref_var,
+                                                 rhs,
+                                                 NULL));
+   deref_var = new(ctx) ir_dereference_variable(var);
+
+   if (!error_emitted)
+      instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var, NULL));
+
+   return new(ctx) ir_dereference_variable(var);
+}
+
+static ir_rvalue *
+get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue)
+{
+   void *ctx = talloc_parent(lvalue);
+   ir_variable *var;
+
+   var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp",
+                             ir_var_temporary);
+   instructions->push_tail(var);
+   var->mode = ir_var_auto;
+
+   instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
+                                                 lvalue, NULL));
+
+   /* Once we've created this temporary, mark it read only so it's no
+    * longer considered an lvalue.
+    */
+   var->read_only = true;
+
+   return new(ctx) ir_dereference_variable(var);
+}
+
+
+ir_rvalue *
+ast_node::hir(exec_list *instructions,
+             struct _mesa_glsl_parse_state *state)
+{
+   (void) instructions;
+   (void) state;
+
+   return NULL;
+}
+
+
+ir_rvalue *
+ast_expression::hir(exec_list *instructions,
+                   struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+   static const int operations[AST_NUM_OPERATORS] = {
+      -1,               /* ast_assign doesn't convert to ir_expression. */
+      -1,               /* ast_plus doesn't convert to ir_expression. */
+      ir_unop_neg,
+      ir_binop_add,
+      ir_binop_sub,
+      ir_binop_mul,
+      ir_binop_div,
+      ir_binop_mod,
+      ir_binop_lshift,
+      ir_binop_rshift,
+      ir_binop_less,
+      ir_binop_greater,
+      ir_binop_lequal,
+      ir_binop_gequal,
+      ir_binop_equal,
+      ir_binop_nequal,
+      ir_binop_bit_and,
+      ir_binop_bit_xor,
+      ir_binop_bit_or,
+      ir_unop_bit_not,
+      ir_binop_logic_and,
+      ir_binop_logic_xor,
+      ir_binop_logic_or,
+      ir_unop_logic_not,
+
+      /* Note: The following block of expression types actually convert
+       * to multiple IR instructions.
+       */
+      ir_binop_mul,     /* ast_mul_assign */
+      ir_binop_div,     /* ast_div_assign */
+      ir_binop_mod,     /* ast_mod_assign */
+      ir_binop_add,     /* ast_add_assign */
+      ir_binop_sub,     /* ast_sub_assign */
+      ir_binop_lshift,  /* ast_ls_assign */
+      ir_binop_rshift,  /* ast_rs_assign */
+      ir_binop_bit_and, /* ast_and_assign */
+      ir_binop_bit_xor, /* ast_xor_assign */
+      ir_binop_bit_or,  /* ast_or_assign */
+
+      -1,               /* ast_conditional doesn't convert to ir_expression. */
+      ir_binop_add,     /* ast_pre_inc. */
+      ir_binop_sub,     /* ast_pre_dec. */
+      ir_binop_add,     /* ast_post_inc. */
+      ir_binop_sub,     /* ast_post_dec. */
+      -1,               /* ast_field_selection doesn't conv to ir_expression. */
+      -1,               /* ast_array_index doesn't convert to ir_expression. */
+      -1,               /* ast_function_call doesn't conv to ir_expression. */
+      -1,               /* ast_identifier doesn't convert to ir_expression. */
+      -1,               /* ast_int_constant doesn't convert to ir_expression. */
+      -1,               /* ast_uint_constant doesn't conv to ir_expression. */
+      -1,               /* ast_float_constant doesn't conv to ir_expression. */
+      -1,               /* ast_bool_constant doesn't conv to ir_expression. */
+      -1,               /* ast_sequence doesn't convert to ir_expression. */
+   };
+   ir_rvalue *result = NULL;
+   ir_rvalue *op[3];
+   const struct glsl_type *type = glsl_type::error_type;
+   bool error_emitted = false;
+   YYLTYPE loc;
+
+   loc = this->get_location();
+
+   switch (this->oper) {
+   case ast_assign: {
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+      op[1] = this->subexpressions[1]->hir(instructions, state);
+
+      result = do_assignment(instructions, state, op[0], op[1],
+                            this->subexpressions[0]->get_location());
+      error_emitted = result->type->is_error();
+      type = result->type;
+      break;
+   }
+
+   case ast_plus:
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+
+      type = unary_arithmetic_result_type(op[0]->type, state, & loc);
+
+      error_emitted = type->is_error();
+
+      result = op[0];
+      break;
+
+   case ast_neg:
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+
+      type = unary_arithmetic_result_type(op[0]->type, state, & loc);
+
+      error_emitted = type->is_error();
+
+      result = new(ctx) ir_expression(operations[this->oper], type,
+                                     op[0], NULL);
+      break;
+
+   case ast_add:
+   case ast_sub:
+   case ast_mul:
+   case ast_div:
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+      op[1] = this->subexpressions[1]->hir(instructions, state);
+
+      type = arithmetic_result_type(op[0], op[1],
+                                   (this->oper == ast_mul),
+                                   state, & loc);
+      error_emitted = type->is_error();
+
+      result = new(ctx) ir_expression(operations[this->oper], type,
+                                     op[0], op[1]);
+      break;
+
+   case ast_mod:
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+      op[1] = this->subexpressions[1]->hir(instructions, state);
+
+      type = modulus_result_type(op[0]->type, op[1]->type, state, & loc);
+
+      assert(operations[this->oper] == ir_binop_mod);
+
+      result = new(ctx) ir_expression(operations[this->oper], type,
+                                     op[0], op[1]);
+      error_emitted = type->is_error();
+      break;
+
+   case ast_lshift:
+   case ast_rshift:
+      _mesa_glsl_error(& loc, state, "FINISHME: implement bit-shift operators");
+      error_emitted = true;
+      break;
+
+   case ast_less:
+   case ast_greater:
+   case ast_lequal:
+   case ast_gequal:
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+      op[1] = this->subexpressions[1]->hir(instructions, state);
+
+      type = relational_result_type(op[0], op[1], state, & loc);
+
+      /* The relational operators must either generate an error or result
+       * in a scalar boolean.  See page 57 of the GLSL 1.50 spec.
+       */
+      assert(type->is_error()
+            || ((type->base_type == GLSL_TYPE_BOOL)
+                && type->is_scalar()));
+
+      result = new(ctx) ir_expression(operations[this->oper], type,
+                                     op[0], op[1]);
+      error_emitted = type->is_error();
+      break;
+
+   case ast_nequal:
+   case ast_equal:
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+      op[1] = this->subexpressions[1]->hir(instructions, state);
+
+      /* From page 58 (page 64 of the PDF) of the GLSL 1.50 spec:
+       *
+       *    "The equality operators equal (==), and not equal (!=)
+       *    operate on all types. They result in a scalar Boolean. If
+       *    the operand types do not match, then there must be a
+       *    conversion from Section 4.1.10 "Implicit Conversions"
+       *    applied to one operand that can make them match, in which
+       *    case this conversion is done."
+       */
+      if ((!apply_implicit_conversion(op[0]->type, op[1], state)
+          && !apply_implicit_conversion(op[1]->type, op[0], state))
+         || (op[0]->type != op[1]->type)) {
+        _mesa_glsl_error(& loc, state, "operands of `%s' must have the same "
+                         "type", (this->oper == ast_equal) ? "==" : "!=");
+        error_emitted = true;
+      } else if ((state->language_version <= 110)
+                && (op[0]->type->is_array() || op[1]->type->is_array())) {
+        _mesa_glsl_error(& loc, state, "array comparisons forbidden in "
+                         "GLSL 1.10");
+        error_emitted = true;
+      }
+
+      result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type,
+                                     op[0], op[1]);
+      type = glsl_type::bool_type;
+
+      assert(result->type == glsl_type::bool_type);
+      break;
+
+   case ast_bit_and:
+   case ast_bit_xor:
+   case ast_bit_or:
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+      op[1] = this->subexpressions[1]->hir(instructions, state);
+
+      if (state->language_version < 130) {
+        _mesa_glsl_error(&loc, state, "bit-wise operations require GLSL 1.30");
+        error_emitted = true;
+      }
+
+      if (!op[0]->type->is_integer()) {
+        _mesa_glsl_error(&loc, state, "LHS of `%s' must be an integer",
+                         operator_string(this->oper));
+        error_emitted = true;
+      }
+
+      if (!op[1]->type->is_integer()) {
+        _mesa_glsl_error(&loc, state, "RHS of `%s' must be an integer",
+                         operator_string(this->oper));
+        error_emitted = true;
+      }
+
+      if (op[0]->type->base_type != op[1]->type->base_type) {
+        _mesa_glsl_error(&loc, state, "operands of `%s' must have the same "
+                         "base type", operator_string(this->oper));
+        error_emitted = true;
+      }
+
+      if (op[0]->type->is_vector() && op[1]->type->is_vector()
+         && op[0]->type->vector_elements != op[1]->type->vector_elements) {
+        _mesa_glsl_error(&loc, state, "operands of `%s' cannot be vectors of "
+                         "different sizes", operator_string(this->oper));
+        error_emitted = true;
+      }
+
+      type = op[0]->type->is_scalar() ? op[1]->type : op[0]->type;
+      result = new(ctx) ir_expression(operations[this->oper], type,
+                                     op[0], op[1]);
+      error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
+      break;
+
+   case ast_bit_not:
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+
+      if (state->language_version < 130) {
+        _mesa_glsl_error(&loc, state, "bit-wise operations require GLSL 1.30");
+        error_emitted = true;
+      }
+
+      if (!op[0]->type->is_integer()) {
+        _mesa_glsl_error(&loc, state, "operand of `~' must be an integer");
+        error_emitted = true;
+      }
+
+      type = op[0]->type;
+      result = new(ctx) ir_expression(ir_unop_bit_not, type, op[0], NULL);
+      break;
+
+   case ast_logic_and: {
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+
+      if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
+        YYLTYPE loc = this->subexpressions[0]->get_location();
+
+        _mesa_glsl_error(& loc, state, "LHS of `%s' must be scalar boolean",
+                         operator_string(this->oper));
+        error_emitted = true;
+      }
+
+      ir_constant *op0_const = op[0]->constant_expression_value();
+      if (op0_const) {
+        if (op0_const->value.b[0]) {
+           op[1] = this->subexpressions[1]->hir(instructions, state);
+
+           if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+              YYLTYPE loc = this->subexpressions[1]->get_location();
+
+              _mesa_glsl_error(& loc, state,
+                               "RHS of `%s' must be scalar boolean",
+                               operator_string(this->oper));
+              error_emitted = true;
+           }
+           result = op[1];
+        } else {
+           result = op0_const;
+        }
+        type = glsl_type::bool_type;
+      } else {
+        ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type,
+                                                      "and_tmp",
+                                                      ir_var_temporary);
+        instructions->push_tail(tmp);
+
+        ir_if *const stmt = new(ctx) ir_if(op[0]);
+        instructions->push_tail(stmt);
+
+        op[1] = this->subexpressions[1]->hir(&stmt->then_instructions, state);
+
+        if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+           YYLTYPE loc = this->subexpressions[1]->get_location();
+
+           _mesa_glsl_error(& loc, state,
+                            "RHS of `%s' must be scalar boolean",
+                            operator_string(this->oper));
+           error_emitted = true;
+        }
+
+        ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp);
+        ir_assignment *const then_assign =
+           new(ctx) ir_assignment(then_deref, op[1], NULL);
+        stmt->then_instructions.push_tail(then_assign);
+
+        ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp);
+        ir_assignment *const else_assign =
+           new(ctx) ir_assignment(else_deref, new(ctx) ir_constant(false), NULL);
+        stmt->else_instructions.push_tail(else_assign);
+
+        result = new(ctx) ir_dereference_variable(tmp);
+        type = tmp->type;
+      }
+      break;
+   }
+
+   case ast_logic_or: {
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+
+      if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
+        YYLTYPE loc = this->subexpressions[0]->get_location();
+
+        _mesa_glsl_error(& loc, state, "LHS of `%s' must be scalar boolean",
+                         operator_string(this->oper));
+        error_emitted = true;
+      }
+
+      ir_constant *op0_const = op[0]->constant_expression_value();
+      if (op0_const) {
+        if (op0_const->value.b[0]) {
+           result = op0_const;
+        } else {
+           op[1] = this->subexpressions[1]->hir(instructions, state);
+
+           if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+              YYLTYPE loc = this->subexpressions[1]->get_location();
+
+              _mesa_glsl_error(& loc, state,
+                               "RHS of `%s' must be scalar boolean",
+                               operator_string(this->oper));
+              error_emitted = true;
+           }
+           result = op[1];
+        }
+        type = glsl_type::bool_type;
+      } else {
+        ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type,
+                                                      "or_tmp",
+                                                      ir_var_temporary);
+        instructions->push_tail(tmp);
+
+        ir_if *const stmt = new(ctx) ir_if(op[0]);
+        instructions->push_tail(stmt);
+
+        op[1] = this->subexpressions[1]->hir(&stmt->else_instructions, state);
+
+        if (!op[1]->type->is_boolean() || !op[1]->type->is_scalar()) {
+           YYLTYPE loc = this->subexpressions[1]->get_location();
+
+           _mesa_glsl_error(& loc, state, "RHS of `%s' must be scalar boolean",
+                            operator_string(this->oper));
+           error_emitted = true;
+        }
+
+        ir_dereference *const then_deref = new(ctx) ir_dereference_variable(tmp);
+        ir_assignment *const then_assign =
+           new(ctx) ir_assignment(then_deref, new(ctx) ir_constant(true), NULL);
+        stmt->then_instructions.push_tail(then_assign);
+
+        ir_dereference *const else_deref = new(ctx) ir_dereference_variable(tmp);
+        ir_assignment *const else_assign =
+           new(ctx) ir_assignment(else_deref, op[1], NULL);
+        stmt->else_instructions.push_tail(else_assign);
+
+        result = new(ctx) ir_dereference_variable(tmp);
+        type = tmp->type;
+      }
+      break;
+   }
+
+   case ast_logic_xor:
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+      op[1] = this->subexpressions[1]->hir(instructions, state);
+
+
+      result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type,
+                                     op[0], op[1]);
+      type = glsl_type::bool_type;
+      break;
+
+   case ast_logic_not:
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+
+      if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
+        YYLTYPE loc = this->subexpressions[0]->get_location();
+
+        _mesa_glsl_error(& loc, state,
+                         "operand of `!' must be scalar boolean");
+        error_emitted = true;
+      }
+
+      result = new(ctx) ir_expression(operations[this->oper], glsl_type::bool_type,
+                                     op[0], NULL);
+      type = glsl_type::bool_type;
+      break;
+
+   case ast_mul_assign:
+   case ast_div_assign:
+   case ast_add_assign:
+   case ast_sub_assign: {
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+      op[1] = this->subexpressions[1]->hir(instructions, state);
+
+      type = arithmetic_result_type(op[0], op[1],
+                                   (this->oper == ast_mul_assign),
+                                   state, & loc);
+
+      ir_rvalue *temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
+                                                  op[0], op[1]);
+
+      result = do_assignment(instructions, state,
+                            op[0]->clone(ctx, NULL), temp_rhs,
+                            this->subexpressions[0]->get_location());
+      type = result->type;
+      error_emitted = (op[0]->type->is_error());
+
+      /* GLSL 1.10 does not allow array assignment.  However, we don't have to
+       * explicitly test for this because none of the binary expression
+       * operators allow array operands either.
+       */
+
+      break;
+   }
+
+   case ast_mod_assign: {
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+      op[1] = this->subexpressions[1]->hir(instructions, state);
+
+      type = modulus_result_type(op[0]->type, op[1]->type, state, & loc);
+
+      assert(operations[this->oper] == ir_binop_mod);
+
+      ir_rvalue *temp_rhs;
+      temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
+                                       op[0], op[1]);
+
+      result = do_assignment(instructions, state,
+                            op[0]->clone(ctx, NULL), temp_rhs,
+                            this->subexpressions[0]->get_location());
+      type = result->type;
+      error_emitted = type->is_error();
+      break;
+   }
+
+   case ast_ls_assign:
+   case ast_rs_assign:
+      _mesa_glsl_error(& loc, state,
+                      "FINISHME: implement bit-shift assignment operators");
+      error_emitted = true;
+      break;
+
+   case ast_and_assign:
+   case ast_xor_assign:
+   case ast_or_assign:
+      _mesa_glsl_error(& loc, state,
+                      "FINISHME: implement logic assignment operators");
+      error_emitted = true;
+      break;
+
+   case ast_conditional: {
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+
+      /* From page 59 (page 65 of the PDF) of the GLSL 1.50 spec:
+       *
+       *    "The ternary selection operator (?:). It operates on three
+       *    expressions (exp1 ? exp2 : exp3). This operator evaluates the
+       *    first expression, which must result in a scalar Boolean."
+       */
+      if (!op[0]->type->is_boolean() || !op[0]->type->is_scalar()) {
+        YYLTYPE loc = this->subexpressions[0]->get_location();
+
+        _mesa_glsl_error(& loc, state, "?: condition must be scalar boolean");
+        error_emitted = true;
+      }
+
+      /* The :? operator is implemented by generating an anonymous temporary
+       * followed by an if-statement.  The last instruction in each branch of
+       * the if-statement assigns a value to the anonymous temporary.  This
+       * temporary is the r-value of the expression.
+       */
+      exec_list then_instructions;
+      exec_list else_instructions;
+
+      op[1] = this->subexpressions[1]->hir(&then_instructions, state);
+      op[2] = this->subexpressions[2]->hir(&else_instructions, state);
+
+      /* From page 59 (page 65 of the PDF) of the GLSL 1.50 spec:
+       *
+       *     "The second and third expressions can be any type, as
+       *     long their types match, or there is a conversion in
+       *     Section 4.1.10 "Implicit Conversions" that can be applied
+       *     to one of the expressions to make their types match. This
+       *     resulting matching type is the type of the entire
+       *     expression."
+       */
+      if ((!apply_implicit_conversion(op[1]->type, op[2], state)
+          && !apply_implicit_conversion(op[2]->type, op[1], state))
+         || (op[1]->type != op[2]->type)) {
+        YYLTYPE loc = this->subexpressions[1]->get_location();
+
+        _mesa_glsl_error(& loc, state, "Second and third operands of ?: "
+                         "operator must have matching types.");
+        error_emitted = true;
+        type = glsl_type::error_type;
+      } else {
+        type = op[1]->type;
+      }
+
+      ir_constant *cond_val = op[0]->constant_expression_value();
+      ir_constant *then_val = op[1]->constant_expression_value();
+      ir_constant *else_val = op[2]->constant_expression_value();
+
+      if (then_instructions.is_empty()
+         && else_instructions.is_empty()
+         && (cond_val != NULL) && (then_val != NULL) && (else_val != NULL)) {
+        result = (cond_val->value.b[0]) ? then_val : else_val;
+      } else {
+        ir_variable *const tmp =
+           new(ctx) ir_variable(type, "conditional_tmp", ir_var_temporary);
+        instructions->push_tail(tmp);
+
+        ir_if *const stmt = new(ctx) ir_if(op[0]);
+        instructions->push_tail(stmt);
+
+        then_instructions.move_nodes_to(& stmt->then_instructions);
+        ir_dereference *const then_deref =
+           new(ctx) ir_dereference_variable(tmp);
+        ir_assignment *const then_assign =
+           new(ctx) ir_assignment(then_deref, op[1], NULL);
+        stmt->then_instructions.push_tail(then_assign);
+
+        else_instructions.move_nodes_to(& stmt->else_instructions);
+        ir_dereference *const else_deref =
+           new(ctx) ir_dereference_variable(tmp);
+        ir_assignment *const else_assign =
+           new(ctx) ir_assignment(else_deref, op[2], NULL);
+        stmt->else_instructions.push_tail(else_assign);
+
+        result = new(ctx) ir_dereference_variable(tmp);
+      }
+      break;
+   }
+
+   case ast_pre_inc:
+   case ast_pre_dec: {
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+      if (op[0]->type->base_type == GLSL_TYPE_FLOAT)
+        op[1] = new(ctx) ir_constant(1.0f);
+      else
+        op[1] = new(ctx) ir_constant(1);
+
+      type = arithmetic_result_type(op[0], op[1], false, state, & loc);
+
+      ir_rvalue *temp_rhs;
+      temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
+                                       op[0], op[1]);
+
+      result = do_assignment(instructions, state,
+                            op[0]->clone(ctx, NULL), temp_rhs,
+                            this->subexpressions[0]->get_location());
+      type = result->type;
+      error_emitted = op[0]->type->is_error();
+      break;
+   }
+
+   case ast_post_inc:
+   case ast_post_dec: {
+      op[0] = this->subexpressions[0]->hir(instructions, state);
+      if (op[0]->type->base_type == GLSL_TYPE_FLOAT)
+        op[1] = new(ctx) ir_constant(1.0f);
+      else
+        op[1] = new(ctx) ir_constant(1);
+
+      error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
+
+      type = arithmetic_result_type(op[0], op[1], false, state, & loc);
+
+      ir_rvalue *temp_rhs;
+      temp_rhs = new(ctx) ir_expression(operations[this->oper], type,
+                                       op[0], op[1]);
+
+      /* Get a temporary of a copy of the lvalue before it's modified.
+       * This may get thrown away later.
+       */
+      result = get_lvalue_copy(instructions, op[0]->clone(ctx, NULL));
+
+      (void)do_assignment(instructions, state,
+                         op[0]->clone(ctx, NULL), temp_rhs,
+                         this->subexpressions[0]->get_location());
+
+      type = result->type;
+      error_emitted = op[0]->type->is_error();
+      break;
+   }
+
+   case ast_field_selection:
+      result = _mesa_ast_field_selection_to_hir(this, instructions, state);
+      type = result->type;
+      break;
+
+   case ast_array_index: {
+      YYLTYPE index_loc = subexpressions[1]->get_location();
+
+      op[0] = subexpressions[0]->hir(instructions, state);
+      op[1] = subexpressions[1]->hir(instructions, state);
+
+      error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
+
+      ir_rvalue *const array = op[0];
+
+      result = new(ctx) ir_dereference_array(op[0], op[1]);
+
+      /* Do not use op[0] after this point.  Use array.
+       */
+      op[0] = NULL;
+
+
+      if (error_emitted)
+        break;
+
+      if (!array->type->is_array()
+         && !array->type->is_matrix()
+         && !array->type->is_vector()) {
+        _mesa_glsl_error(& index_loc, state,
+                         "cannot dereference non-array / non-matrix / "
+                         "non-vector");
+        error_emitted = true;
+      }
+
+      if (!op[1]->type->is_integer()) {
+        _mesa_glsl_error(& index_loc, state,
+                         "array index must be integer type");
+        error_emitted = true;
+      } else if (!op[1]->type->is_scalar()) {
+        _mesa_glsl_error(& index_loc, state,
+                         "array index must be scalar");
+        error_emitted = true;
+      }
+
+      /* If the array index is a constant expression and the array has a
+       * declared size, ensure that the access is in-bounds.  If the array
+       * index is not a constant expression, ensure that the array has a
+       * declared size.
+       */
+      ir_constant *const const_index = op[1]->constant_expression_value();
+      if (const_index != NULL) {
+        const int idx = const_index->value.i[0];
+        const char *type_name;
+        unsigned bound = 0;
+
+        if (array->type->is_matrix()) {
+           type_name = "matrix";
+        } else if (array->type->is_vector()) {
+           type_name = "vector";
+        } else {
+           type_name = "array";
+        }
+
+        /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec:
+         *
+         *    "It is illegal to declare an array with a size, and then
+         *    later (in the same shader) index the same array with an
+         *    integral constant expression greater than or equal to the
+         *    declared size. It is also illegal to index an array with a
+         *    negative constant expression."
+         */
+        if (array->type->is_matrix()) {
+           if (array->type->row_type()->vector_elements <= idx) {
+              bound = array->type->row_type()->vector_elements;
+           }
+        } else if (array->type->is_vector()) {
+           if (array->type->vector_elements <= idx) {
+              bound = array->type->vector_elements;
+           }
+        } else {
+           if ((array->type->array_size() > 0)
+               && (array->type->array_size() <= idx)) {
+              bound = array->type->array_size();
+           }
+        }
+
+        if (bound > 0) {
+           _mesa_glsl_error(& loc, state, "%s index must be < %u",
+                            type_name, bound);
+           error_emitted = true;
+        } else if (idx < 0) {
+           _mesa_glsl_error(& loc, state, "%s index must be >= 0",
+                            type_name);
+           error_emitted = true;
+        }
+
+        if (array->type->is_array()) {
+           /* If the array is a variable dereference, it dereferences the
+            * whole array, by definition.  Use this to get the variable.
+            *
+            * FINISHME: Should some methods for getting / setting / testing
+            * FINISHME: array access limits be added to ir_dereference?
+            */
+           ir_variable *const v = array->whole_variable_referenced();
+           if ((v != NULL) && (unsigned(idx) > v->max_array_access))
+              v->max_array_access = idx;
+        }
+      } else if (array->type->array_size() == 0) {
+        _mesa_glsl_error(&loc, state, "unsized array index must be constant");
+      } else {
+        if (array->type->is_array()) {
+           /* whole_variable_referenced can return NULL if the array is a
+            * member of a structure.  In this case it is safe to not update
+            * the max_array_access field because it is never used for fields
+            * of structures.
+            */
+           ir_variable *v = array->whole_variable_referenced();
+           if (v != NULL)
+              v->max_array_access = array->type->array_size();
+        }
+      }
+
+      if (error_emitted)
+        result->type = glsl_type::error_type;
+
+      type = result->type;
+      break;
+   }
+
+   case ast_function_call:
+      /* Should *NEVER* get here.  ast_function_call should always be handled
+       * by ast_function_expression::hir.
+       */
+      assert(0);
+      break;
+
+   case ast_identifier: {
+      /* ast_identifier can appear several places in a full abstract syntax
+       * tree.  This particular use must be at location specified in the grammar
+       * as 'variable_identifier'.
+       */
+      ir_variable *var = 
+        state->symbols->get_variable(this->primary_expression.identifier);
+
+      result = new(ctx) ir_dereference_variable(var);
+
+      if (var != NULL) {
+        type = result->type;
+      } else {
+        _mesa_glsl_error(& loc, state, "`%s' undeclared",
+                         this->primary_expression.identifier);
+
+        error_emitted = true;
+      }
+      break;
+   }
+
+   case ast_int_constant:
+      type = glsl_type::int_type;
+      result = new(ctx) ir_constant(this->primary_expression.int_constant);
+      break;
+
+   case ast_uint_constant:
+      type = glsl_type::uint_type;
+      result = new(ctx) ir_constant(this->primary_expression.uint_constant);
+      break;
+
+   case ast_float_constant:
+      type = glsl_type::float_type;
+      result = new(ctx) ir_constant(this->primary_expression.float_constant);
+      break;
+
+   case ast_bool_constant:
+      type = glsl_type::bool_type;
+      result = new(ctx) ir_constant(bool(this->primary_expression.bool_constant));
+      break;
+
+   case ast_sequence: {
+      /* It should not be possible to generate a sequence in the AST without
+       * any expressions in it.
+       */
+      assert(!this->expressions.is_empty());
+
+      /* The r-value of a sequence is the last expression in the sequence.  If
+       * the other expressions in the sequence do not have side-effects (and
+       * therefore add instructions to the instruction list), they get dropped
+       * on the floor.
+       */
+      foreach_list_typed (ast_node, ast, link, &this->expressions)
+        result = ast->hir(instructions, state);
+
+      type = result->type;
+
+      /* Any errors should have already been emitted in the loop above.
+       */
+      error_emitted = true;
+      break;
+   }
+   }
+
+   if (type->is_error() && !error_emitted)
+      _mesa_glsl_error(& loc, state, "type mismatch");
+
+   return result;
+}
+
+
+ir_rvalue *
+ast_expression_statement::hir(exec_list *instructions,
+                             struct _mesa_glsl_parse_state *state)
+{
+   /* It is possible to have expression statements that don't have an
+    * expression.  This is the solitary semicolon:
+    *
+    * for (i = 0; i < 5; i++)
+    *     ;
+    *
+    * In this case the expression will be NULL.  Test for NULL and don't do
+    * anything in that case.
+    */
+   if (expression != NULL)
+      expression->hir(instructions, state);
+
+   /* Statements do not have r-values.
+    */
+   return NULL;
+}
+
+
+ir_rvalue *
+ast_compound_statement::hir(exec_list *instructions,
+                           struct _mesa_glsl_parse_state *state)
+{
+   if (new_scope)
+      state->symbols->push_scope();
+
+   foreach_list_typed (ast_node, ast, link, &this->statements)
+      ast->hir(instructions, state);
+
+   if (new_scope)
+      state->symbols->pop_scope();
+
+   /* Compound statements do not have r-values.
+    */
+   return NULL;
+}
+
+
+static const glsl_type *
+process_array_type(const glsl_type *base, ast_node *array_size,
+                  struct _mesa_glsl_parse_state *state)
+{
+   unsigned length = 0;
+
+   /* FINISHME: Reject delcarations of multidimensional arrays. */
+
+   if (array_size != NULL) {
+      exec_list dummy_instructions;
+      ir_rvalue *const ir = array_size->hir(& dummy_instructions, state);
+      YYLTYPE loc = array_size->get_location();
+
+      /* FINISHME: Verify that the grammar forbids side-effects in array
+       * FINISHME: sizes.   i.e., 'vec4 [x = 12] data'
+       */
+      assert(dummy_instructions.is_empty());
+
+      if (ir != NULL) {
+        if (!ir->type->is_integer()) {
+           _mesa_glsl_error(& loc, state, "array size must be integer type");
+        } else if (!ir->type->is_scalar()) {
+           _mesa_glsl_error(& loc, state, "array size must be scalar type");
+        } else {
+           ir_constant *const size = ir->constant_expression_value();
+
+           if (size == NULL) {
+              _mesa_glsl_error(& loc, state, "array size must be a "
+                               "constant valued expression");
+           } else if (size->value.i[0] <= 0) {
+              _mesa_glsl_error(& loc, state, "array size must be > 0");
+           } else {
+              assert(size->type == ir->type);
+              length = size->value.u[0];
+           }
+        }
+      }
+   }
+
+   return glsl_type::get_array_instance(base, length);
+}
+
+
+const glsl_type *
+ast_type_specifier::glsl_type(const char **name,
+                             struct _mesa_glsl_parse_state *state) const
+{
+   const struct glsl_type *type;
+
+   if ((this->type_specifier == ast_struct) && (this->type_name == NULL)) {
+      /* FINISHME: Handle annonymous structures. */
+      type = NULL;
+   } else {
+      type = state->symbols->get_type(this->type_name);
+      *name = this->type_name;
+
+      if (this->is_array) {
+        type = process_array_type(type, this->array_size, state);
+      }
+   }
+
+   return type;
+}
+
+
+static void
+apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
+                                ir_variable *var,
+                                struct _mesa_glsl_parse_state *state,
+                                YYLTYPE *loc)
+{
+   if (qual->invariant)
+      var->invariant = 1;
+
+   /* FINISHME: Mark 'in' variables at global scope as read-only. */
+   if (qual->constant || qual->attribute || qual->uniform
+       || (qual->varying && (state->target == fragment_shader)))
+      var->read_only = 1;
+
+   if (qual->centroid)
+      var->centroid = 1;
+
+   if (qual->attribute && state->target != vertex_shader) {
+      var->type = glsl_type::error_type;
+      _mesa_glsl_error(loc, state,
+                      "`attribute' variables may not be declared in the "
+                      "%s shader",
+                      _mesa_glsl_shader_target_name(state->target));
+   }
+
+   /* From page 25 (page 31 of the PDF) of the GLSL 1.10 spec:
+    *
+    *     "The varying qualifier can be used only with the data types
+    *     float, vec2, vec3, vec4, mat2, mat3, and mat4, or arrays of
+    *     these."
+    */
+   if (qual->varying) {
+      const glsl_type *non_array_type;
+
+      if (var->type && var->type->is_array())
+        non_array_type = var->type->fields.array;
+      else
+        non_array_type = var->type;
+
+      if (non_array_type && non_array_type->base_type != GLSL_TYPE_FLOAT) {
+        var->type = glsl_type::error_type;
+        _mesa_glsl_error(loc, state,
+                         "varying variables must be of base type float");
+      }
+   }
+
+   /* If there is no qualifier that changes the mode of the variable, leave
+    * the setting alone.
+    */
+   if (qual->in && qual->out)
+      var->mode = ir_var_inout;
+   else if (qual->attribute || qual->in
+           || (qual->varying && (state->target == fragment_shader)))
+      var->mode = ir_var_in;
+   else if (qual->out || (qual->varying && (state->target == vertex_shader)))
+      var->mode = ir_var_out;
+   else if (qual->uniform)
+      var->mode = ir_var_uniform;
+
+   if (qual->flat)
+      var->interpolation = ir_var_flat;
+   else if (qual->noperspective)
+      var->interpolation = ir_var_noperspective;
+   else
+      var->interpolation = ir_var_smooth;
+
+   var->pixel_center_integer = qual->pixel_center_integer;
+   var->origin_upper_left = qual->origin_upper_left;
+   if ((qual->origin_upper_left || qual->pixel_center_integer)
+       && (strcmp(var->name, "gl_FragCoord") != 0)) {
+      const char *const qual_string = (qual->origin_upper_left)
+        ? "origin_upper_left" : "pixel_center_integer";
+
+      _mesa_glsl_error(loc, state,
+                      "layout qualifier `%s' can only be applied to "
+                      "fragment shader input `gl_FragCoord'",
+                      qual_string);
+   }
+
+   if (var->type->is_array() && (state->language_version >= 120)) {
+      var->array_lvalue = true;
+   }
+}
+
+
+ir_rvalue *
+ast_declarator_list::hir(exec_list *instructions,
+                        struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+   const struct glsl_type *decl_type;
+   const char *type_name = NULL;
+   ir_rvalue *result = NULL;
+   YYLTYPE loc = this->get_location();
+
+   /* From page 46 (page 52 of the PDF) of the GLSL 1.50 spec:
+    *
+    *     "To ensure that a particular output variable is invariant, it is
+    *     necessary to use the invariant qualifier. It can either be used to
+    *     qualify a previously declared variable as being invariant
+    *
+    *         invariant gl_Position; // make existing gl_Position be invariant"
+    *
+    * In these cases the parser will set the 'invariant' flag in the declarator
+    * list, and the type will be NULL.
+    */
+   if (this->invariant) {
+      assert(this->type == NULL);
+
+      if (state->current_function != NULL) {
+        _mesa_glsl_error(& loc, state,
+                         "All uses of `invariant' keyword must be at global "
+                         "scope\n");
+      }
+
+      foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
+        assert(!decl->is_array);
+        assert(decl->array_size == NULL);
+        assert(decl->initializer == NULL);
+
+        ir_variable *const earlier =
+           state->symbols->get_variable(decl->identifier);
+        if (earlier == NULL) {
+           _mesa_glsl_error(& loc, state,
+                            "Undeclared variable `%s' cannot be marked "
+                            "invariant\n", decl->identifier);
+        } else if ((state->target == vertex_shader)
+              && (earlier->mode != ir_var_out)) {
+           _mesa_glsl_error(& loc, state,
+                            "`%s' cannot be marked invariant, vertex shader "
+                            "outputs only\n", decl->identifier);
+        } else if ((state->target == fragment_shader)
+              && (earlier->mode != ir_var_in)) {
+           _mesa_glsl_error(& loc, state,
+                            "`%s' cannot be marked invariant, fragment shader "
+                            "inputs only\n", decl->identifier);
+        } else {
+           earlier->invariant = true;
+        }
+      }
+
+      /* Invariant redeclarations do not have r-values.
+       */
+      return NULL;
+   }
+
+   assert(this->type != NULL);
+   assert(!this->invariant);
+
+   /* The type specifier may contain a structure definition.  Process that
+    * before any of the variable declarations.
+    */
+   (void) this->type->specifier->hir(instructions, state);
+
+   decl_type = this->type->specifier->glsl_type(& type_name, state);
+   if (this->declarations.is_empty()) {
+      /* The only valid case where the declaration list can be empty is when
+       * the declaration is setting the default precision of a built-in type
+       * (e.g., 'precision highp vec4;').
+       */
+
+      if (decl_type != NULL) {
+      } else {
+           _mesa_glsl_error(& loc, state, "incomplete declaration");
+      }
+   }
+
+   foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
+      const struct glsl_type *var_type;
+      ir_variable *var;
+
+      /* FINISHME: Emit a warning if a variable declaration shadows a
+       * FINISHME: declaration at a higher scope.
+       */
+
+      if ((decl_type == NULL) || decl_type->is_void()) {
+        if (type_name != NULL) {
+           _mesa_glsl_error(& loc, state,
+                            "invalid type `%s' in declaration of `%s'",
+                            type_name, decl->identifier);
+        } else {
+           _mesa_glsl_error(& loc, state,
+                            "invalid type in declaration of `%s'",
+                            decl->identifier);
+        }
+        continue;
+      }
+
+      if (decl->is_array) {
+        var_type = process_array_type(decl_type, decl->array_size, state);
+      } else {
+        var_type = decl_type;
+      }
+
+      var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto);
+
+      /* From page 22 (page 28 of the PDF) of the GLSL 1.10 specification;
+       *
+       *     "Global variables can only use the qualifiers const,
+       *     attribute, uni form, or varying. Only one may be
+       *     specified.
+       *
+       *     Local variables can only use the qualifier const."
+       *
+       * This is relaxed in GLSL 1.30.
+       */
+      if (state->language_version < 120) {
+        if (this->type->qualifier.out) {
+           _mesa_glsl_error(& loc, state,
+                            "`out' qualifier in declaration of `%s' "
+                            "only valid for function parameters in GLSL 1.10.",
+                            decl->identifier);
+        }
+        if (this->type->qualifier.in) {
+           _mesa_glsl_error(& loc, state,
+                            "`in' qualifier in declaration of `%s' "
+                            "only valid for function parameters in GLSL 1.10.",
+                            decl->identifier);
+        }
+        /* FINISHME: Test for other invalid qualifiers. */
+      }
+
+      apply_type_qualifier_to_variable(& this->type->qualifier, var, state,
+                                      & loc);
+
+      if (this->type->qualifier.invariant) {
+        if ((state->target == vertex_shader) && !(var->mode == ir_var_out ||
+                                                  var->mode == ir_var_inout)) {
+           /* FINISHME: Note that this doesn't work for invariant on
+            * a function signature outval
+            */
+           _mesa_glsl_error(& loc, state,
+                            "`%s' cannot be marked invariant, vertex shader "
+                            "outputs only\n", var->name);
+        } else if ((state->target == fragment_shader) &&
+                   !(var->mode == ir_var_in || var->mode == ir_var_inout)) {
+           /* FINISHME: Note that this doesn't work for invariant on
+            * a function signature inval
+            */
+           _mesa_glsl_error(& loc, state,
+                            "`%s' cannot be marked invariant, fragment shader "
+                            "inputs only\n", var->name);
+        }
+      }
+
+      if (state->current_function != NULL) {
+        const char *mode = NULL;
+        const char *extra = "";
+
+        /* There is no need to check for 'inout' here because the parser will
+         * only allow that in function parameter lists.
+         */
+        if (this->type->qualifier.attribute) {
+           mode = "attribute";
+        } else if (this->type->qualifier.uniform) {
+           mode = "uniform";
+        } else if (this->type->qualifier.varying) {
+           mode = "varying";
+        } else if (this->type->qualifier.in) {
+           mode = "in";
+           extra = " or in function parameter list";
+        } else if (this->type->qualifier.out) {
+           mode = "out";
+           extra = " or in function parameter list";
+        }
+
+        if (mode) {
+           _mesa_glsl_error(& loc, state,
+                            "%s variable `%s' must be declared at "
+                            "global scope%s",
+                            mode, var->name, extra);
+        }
+      } else if (var->mode == ir_var_in) {
+        if (state->target == vertex_shader) {
+           bool error_emitted = false;
+
+           /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec:
+            *
+            *    "Vertex shader inputs can only be float, floating-point
+            *    vectors, matrices, signed and unsigned integers and integer
+            *    vectors. Vertex shader inputs can also form arrays of these
+            *    types, but not structures."
+            *
+            * From page 31 (page 27 of the PDF) of the GLSL 1.30 spec:
+            *
+            *    "Vertex shader inputs can only be float, floating-point
+            *    vectors, matrices, signed and unsigned integers and integer
+            *    vectors. They cannot be arrays or structures."
+            *
+            * From page 23 (page 29 of the PDF) of the GLSL 1.20 spec:
+            *
+            *    "The attribute qualifier can be used only with float,
+            *    floating-point vectors, and matrices. Attribute variables
+            *    cannot be declared as arrays or structures."
+            */
+           const glsl_type *check_type = var->type->is_array()
+              ? var->type->fields.array : var->type;
+
+           switch (check_type->base_type) {
+           case GLSL_TYPE_FLOAT:
+              break;
+           case GLSL_TYPE_UINT:
+           case GLSL_TYPE_INT:
+              if (state->language_version > 120)
+                 break;
+              /* FALLTHROUGH */
+           default:
+              _mesa_glsl_error(& loc, state,
+                               "vertex shader input / attribute cannot have "
+                               "type %s`%s'",
+                               var->type->is_array() ? "array of " : "",
+                               check_type->name);
+              error_emitted = true;
+           }
+
+           if (!error_emitted && (state->language_version <= 130)
+               && var->type->is_array()) {
+              _mesa_glsl_error(& loc, state,
+                               "vertex shader input / attribute cannot have "
+                               "array type");
+              error_emitted = true;
+           }
+        }
+      }
+
+      /* Process the initializer and add its instructions to a temporary
+       * list.  This list will be added to the instruction stream (below) after
+       * the declaration is added.  This is done because in some cases (such as
+       * redeclarations) the declaration may not actually be added to the
+       * instruction stream.
+       */
+      exec_list initializer_instructions;
+      if (decl->initializer != NULL) {
+        YYLTYPE initializer_loc = decl->initializer->get_location();
+
+        /* From page 24 (page 30 of the PDF) of the GLSL 1.10 spec:
+         *
+         *    "All uniform variables are read-only and are initialized either
+         *    directly by an application via API commands, or indirectly by
+         *    OpenGL."
+         */
+        if ((state->language_version <= 110)
+            && (var->mode == ir_var_uniform)) {
+           _mesa_glsl_error(& initializer_loc, state,
+                            "cannot initialize uniforms in GLSL 1.10");
+        }
+
+        if (var->type->is_sampler()) {
+           _mesa_glsl_error(& initializer_loc, state,
+                            "cannot initialize samplers");
+        }
+
+        if ((var->mode == ir_var_in) && (state->current_function == NULL)) {
+           _mesa_glsl_error(& initializer_loc, state,
+                            "cannot initialize %s shader input / %s",
+                            _mesa_glsl_shader_target_name(state->target),
+                            (state->target == vertex_shader)
+                            ? "attribute" : "varying");
+        }
+
+        ir_dereference *const lhs = new(ctx) ir_dereference_variable(var);
+        ir_rvalue *rhs = decl->initializer->hir(&initializer_instructions,
+                                                state);
+
+        /* Calculate the constant value if this is a const or uniform
+         * declaration.
+         */
+        if (this->type->qualifier.constant || this->type->qualifier.uniform) {
+           ir_rvalue *new_rhs = validate_assignment(state, var->type, rhs);
+           if (new_rhs != NULL) {
+              rhs = new_rhs;
+
+              ir_constant *constant_value = rhs->constant_expression_value();
+              if (!constant_value) {
+                 _mesa_glsl_error(& initializer_loc, state,
+                                  "initializer of %s variable `%s' must be a "
+                                  "constant expression",
+                                  (this->type->qualifier.constant)
+                                  ? "const" : "uniform",
+                                  decl->identifier);
+                 if (var->type->is_numeric()) {
+                    /* Reduce cascading errors. */
+                    var->constant_value = ir_constant::zero(ctx, var->type);
+                 }
+              } else {
+                 rhs = constant_value;
+                 var->constant_value = constant_value;
+              }
+           } else {
+              _mesa_glsl_error(&initializer_loc, state,
+                               "initializer of type %s cannot be assigned to "
+                               "variable of type %s",
+                               rhs->type->name, var->type->name);
+              if (var->type->is_numeric()) {
+                 /* Reduce cascading errors. */
+                 var->constant_value = ir_constant::zero(ctx, var->type);
+              }
+           }
+        }
+
+        if (rhs && !rhs->type->is_error()) {
+           bool temp = var->read_only;
+           if (this->type->qualifier.constant)
+              var->read_only = false;
+
+           /* Never emit code to initialize a uniform.
+            */
+           if (!this->type->qualifier.uniform)
+              result = do_assignment(&initializer_instructions, state,
+                                     lhs, rhs,
+                                     this->get_location());
+           var->read_only = temp;
+        }
+      }
+
+      /* From page 23 (page 29 of the PDF) of the GLSL 1.10 spec:
+       *
+       *     "It is an error to write to a const variable outside of
+       *      its declaration, so they must be initialized when
+       *      declared."
+       */
+      if (this->type->qualifier.constant && decl->initializer == NULL) {
+        _mesa_glsl_error(& loc, state,
+                         "const declaration of `%s' must be initialized");
+      }
+
+      /* Check if this declaration is actually a re-declaration, either to
+       * resize an array or add qualifiers to an existing variable.
+       *
+       * This is allowed for variables in the current scope, or when at
+       * global scope (for built-ins in the implicit outer scope).
+       */
+      ir_variable *earlier = state->symbols->get_variable(decl->identifier);
+      if (earlier != NULL && (state->current_function == NULL ||
+         state->symbols->name_declared_this_scope(decl->identifier))) {
+
+        /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec,
+         *
+         * "It is legal to declare an array without a size and then
+         *  later re-declare the same name as an array of the same
+         *  type and specify a size."
+         */
+        if ((earlier->type->array_size() == 0)
+            && var->type->is_array()
+            && (var->type->element_type() == earlier->type->element_type())) {
+           /* FINISHME: This doesn't match the qualifiers on the two
+            * FINISHME: declarations.  It's not 100% clear whether this is
+            * FINISHME: required or not.
+            */
+
+           /* From page 54 (page 60 of the PDF) of the GLSL 1.20 spec:
+            *
+            *     "The size [of gl_TexCoord] can be at most
+            *     gl_MaxTextureCoords."
+            */
+           const unsigned size = unsigned(var->type->array_size());
+           if ((strcmp("gl_TexCoord", var->name) == 0)
+               && (size > state->Const.MaxTextureCoords)) {
+              YYLTYPE loc = this->get_location();
+
+              _mesa_glsl_error(& loc, state, "`gl_TexCoord' array size cannot "
+                               "be larger than gl_MaxTextureCoords (%u)\n",
+                               state->Const.MaxTextureCoords);
+           } else if ((size > 0) && (size <= earlier->max_array_access)) {
+              YYLTYPE loc = this->get_location();
+
+              _mesa_glsl_error(& loc, state, "array size must be > %u due to "
+                               "previous access",
+                               earlier->max_array_access);
+           }
+
+           earlier->type = var->type;
+           delete var;
+           var = NULL;
+        } else if (state->extensions->ARB_fragment_coord_conventions
+                   && strcmp(var->name, "gl_FragCoord") == 0
+                   && earlier->type == var->type
+                   && earlier->mode == var->mode) {
+           /* Allow redeclaration of gl_FragCoord for ARB_fcc layout
+            * qualifiers.
+            */
+           earlier->origin_upper_left = var->origin_upper_left;
+           earlier->pixel_center_integer = var->pixel_center_integer;
+        } else {
+           YYLTYPE loc = this->get_location();
+           _mesa_glsl_error(&loc, state, "`%s' redeclared", decl->identifier);
+        }
+
+        continue;
+      }
+
+      /* By now, we know it's a new variable declaration (we didn't hit the
+       * above "continue").
+       *
+       * From page 15 (page 21 of the PDF) of the GLSL 1.10 spec,
+       *
+       *   "Identifiers starting with "gl_" are reserved for use by
+       *   OpenGL, and may not be declared in a shader as either a
+       *   variable or a function."
+       */
+      if (strncmp(decl->identifier, "gl_", 3) == 0)
+        _mesa_glsl_error(& loc, state,
+                         "identifier `%s' uses reserved `gl_' prefix",
+                         decl->identifier);
+
+      /* Add the variable to the symbol table.  Note that the initializer's
+       * IR was already processed earlier (though it hasn't been emitted yet),
+       * without the variable in scope.
+       *
+       * This differs from most C-like languages, but it follows the GLSL
+       * specification.  From page 28 (page 34 of the PDF) of the GLSL 1.50
+       * spec:
+       *
+       *     "Within a declaration, the scope of a name starts immediately
+       *     after the initializer if present or immediately after the name
+       *     being declared if not."
+       */
+      if (!state->symbols->add_variable(var->name, var)) {
+        YYLTYPE loc = this->get_location();
+        _mesa_glsl_error(&loc, state, "name `%s' already taken in the "
+                         "current scope", decl->identifier);
+        continue;
+      }
+
+      /* Push the variable declaration to the top.  It means that all
+       * the variable declarations will appear in a funny
+       * last-to-first order, but otherwise we run into trouble if a
+       * function is prototyped, a global var is decled, then the
+       * function is defined with usage of the global var.  See
+       * glslparsertest's CorrectModule.frag.
+       */
+      instructions->push_head(var);
+      instructions->append_list(&initializer_instructions);
+   }
+
+
+   /* Generally, variable declarations do not have r-values.  However,
+    * one is used for the declaration in
+    *
+    * while (bool b = some_condition()) {
+    *   ...
+    * }
+    *
+    * so we return the rvalue from the last seen declaration here.
+    */
+   return result;
+}
+
+
+ir_rvalue *
+ast_parameter_declarator::hir(exec_list *instructions,
+                             struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+   const struct glsl_type *type;
+   const char *name = NULL;
+   YYLTYPE loc = this->get_location();
+
+   type = this->type->specifier->glsl_type(& name, state);
+
+   if (type == NULL) {
+      if (name != NULL) {
+        _mesa_glsl_error(& loc, state,
+                         "invalid type `%s' in declaration of `%s'",
+                         name, this->identifier);
+      } else {
+        _mesa_glsl_error(& loc, state,
+                         "invalid type in declaration of `%s'",
+                         this->identifier);
+      }
+
+      type = glsl_type::error_type;
+   }
+
+   /* From page 62 (page 68 of the PDF) of the GLSL 1.50 spec:
+    *
+    *    "Functions that accept no input arguments need not use void in the
+    *    argument list because prototypes (or definitions) are required and
+    *    therefore there is no ambiguity when an empty argument list "( )" is
+    *    declared. The idiom "(void)" as a parameter list is provided for
+    *    convenience."
+    *
+    * Placing this check here prevents a void parameter being set up
+    * for a function, which avoids tripping up checks for main taking
+    * parameters and lookups of an unnamed symbol.
+    */
+   if (type->is_void()) {
+      if (this->identifier != NULL)
+        _mesa_glsl_error(& loc, state,
+                         "named parameter cannot have type `void'");
+
+      is_void = true;
+      return NULL;
+   }
+
+   if (formal_parameter && (this->identifier == NULL)) {
+      _mesa_glsl_error(& loc, state, "formal parameter lacks a name");
+      return NULL;
+   }
+
+   /* This only handles "vec4 foo[..]".  The earlier specifier->glsl_type(...)
+    * call already handled the "vec4[..] foo" case.
+    */
+   if (this->is_array) {
+      type = process_array_type(type, this->array_size, state);
+   }
+
+   if (type->array_size() == 0) {
+      _mesa_glsl_error(&loc, state, "arrays passed as parameters must have "
+                      "a declared size.");
+      type = glsl_type::error_type;
+   }
+
+   is_void = false;
+   ir_variable *var = new(ctx) ir_variable(type, this->identifier, ir_var_in);
+
+   /* Apply any specified qualifiers to the parameter declaration.  Note that
+    * for function parameters the default mode is 'in'.
+    */
+   apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc);
+
+   instructions->push_tail(var);
+
+   /* Parameter declarations do not have r-values.
+    */
+   return NULL;
+}
+
+
+void
+ast_parameter_declarator::parameters_to_hir(exec_list *ast_parameters,
+                                           bool formal,
+                                           exec_list *ir_parameters,
+                                           _mesa_glsl_parse_state *state)
+{
+   ast_parameter_declarator *void_param = NULL;
+   unsigned count = 0;
+
+   foreach_list_typed (ast_parameter_declarator, param, link, ast_parameters) {
+      param->formal_parameter = formal;
+      param->hir(ir_parameters, state);
+
+      if (param->is_void)
+        void_param = param;
+
+      count++;
+   }
+
+   if ((void_param != NULL) && (count > 1)) {
+      YYLTYPE loc = void_param->get_location();
+
+      _mesa_glsl_error(& loc, state,
+                      "`void' parameter must be only parameter");
+   }
+}
+
+
+ir_rvalue *
+ast_function::hir(exec_list *instructions,
+                 struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+   ir_function *f = NULL;
+   ir_function_signature *sig = NULL;
+   exec_list hir_parameters;
+
+   const char *const name = identifier;
+
+   /* From page 21 (page 27 of the PDF) of the GLSL 1.20 spec,
+    *
+    *   "Function declarations (prototypes) cannot occur inside of functions;
+    *   they must be at global scope, or for the built-in functions, outside
+    *   the global scope."
+    *
+    * From page 27 (page 33 of the PDF) of the GLSL ES 1.00.16 spec,
+    *
+    *   "User defined functions may only be defined within the global scope."
+    *
+    * Note that this language does not appear in GLSL 1.10.
+    */
+   if ((state->current_function != NULL) && (state->language_version != 110)) {
+      YYLTYPE loc = this->get_location();
+      _mesa_glsl_error(&loc, state,
+                      "declaration of function `%s' not allowed within "
+                      "function body", name);
+   }
+
+   /* From page 15 (page 21 of the PDF) of the GLSL 1.10 spec,
+    *
+    *   "Identifiers starting with "gl_" are reserved for use by
+    *   OpenGL, and may not be declared in a shader as either a
+    *   variable or a function."
+    */
+   if (strncmp(name, "gl_", 3) == 0) {
+      YYLTYPE loc = this->get_location();
+      _mesa_glsl_error(&loc, state,
+                      "identifier `%s' uses reserved `gl_' prefix", name);
+   }
+
+   /* Convert the list of function parameters to HIR now so that they can be
+    * used below to compare this function's signature with previously seen
+    * signatures for functions with the same name.
+    */
+   ast_parameter_declarator::parameters_to_hir(& this->parameters,
+                                              is_definition,
+                                              & hir_parameters, state);
+
+   const char *return_type_name;
+   const glsl_type *return_type =
+      this->return_type->specifier->glsl_type(& return_type_name, state);
+
+   if (!return_type) {
+      YYLTYPE loc = this->get_location();
+      _mesa_glsl_error(&loc, state,
+                      "function `%s' has undeclared return type `%s'",
+                      name, return_type_name);
+      return_type = glsl_type::error_type;
+   }
+
+   /* From page 56 (page 62 of the PDF) of the GLSL 1.30 spec:
+    * "No qualifier is allowed on the return type of a function."
+    */
+   if (this->return_type->has_qualifiers()) {
+      YYLTYPE loc = this->get_location();
+      _mesa_glsl_error(& loc, state,
+                      "function `%s' return type has qualifiers", name);
+   }
+
+   /* Verify that this function's signature either doesn't match a previously
+    * seen signature for a function with the same name, or, if a match is found,
+    * that the previously seen signature does not have an associated definition.
+    */
+   f = state->symbols->get_function(name);
+   if (f != NULL && !f->is_builtin) {
+      sig = f->exact_matching_signature(&hir_parameters);
+      if (sig != NULL) {
+        const char *badvar = sig->qualifiers_match(&hir_parameters);
+        if (badvar != NULL) {
+           YYLTYPE loc = this->get_location();
+
+           _mesa_glsl_error(&loc, state, "function `%s' parameter `%s' "
+                            "qualifiers don't match prototype", name, badvar);
+        }
+
+        if (sig->return_type != return_type) {
+           YYLTYPE loc = this->get_location();
+
+           _mesa_glsl_error(&loc, state, "function `%s' return type doesn't "
+                            "match prototype", name);
+        }
+
+        if (is_definition && sig->is_defined) {
+           YYLTYPE loc = this->get_location();
+
+           _mesa_glsl_error(& loc, state, "function `%s' redefined", name);
+        }
+      }
+   } else {
+      f = new(ctx) ir_function(name);
+      if (!state->symbols->add_function(f->name, f)) {
+        /* This function name shadows a non-function use of the same name. */
+        YYLTYPE loc = this->get_location();
+
+        _mesa_glsl_error(&loc, state, "function name `%s' conflicts with "
+                         "non-function", name);
+        return NULL;
+      }
+
+      /* Emit the new function header */
+      if (state->current_function == NULL)
+        instructions->push_tail(f);
+      else {
+        /* IR invariants disallow function declarations or definitions nested
+         * within other function definitions.  Insert the new ir_function
+         * block in the instruction sequence before the ir_function block
+         * containing the current ir_function_signature.
+         *
+         * This can only happen in a GLSL 1.10 shader.  In all other GLSL
+         * versions this nesting is disallowed.  There is a check for this at
+         * the top of this function.
+         */
+        ir_function *const curr =
+           const_cast<ir_function *>(state->current_function->function());
+
+        curr->insert_before(f);
+      }
+   }
+
+   /* Verify the return type of main() */
+   if (strcmp(name, "main") == 0) {
+      if (! return_type->is_void()) {
+        YYLTYPE loc = this->get_location();
+
+        _mesa_glsl_error(& loc, state, "main() must return void");
+      }
+
+      if (!hir_parameters.is_empty()) {
+        YYLTYPE loc = this->get_location();
+
+        _mesa_glsl_error(& loc, state, "main() must not take any parameters");
+      }
+   }
+
+   /* Finish storing the information about this new function in its signature.
+    */
+   if (sig == NULL) {
+      sig = new(ctx) ir_function_signature(return_type);
+      f->add_signature(sig);
+   }
+
+   sig->replace_parameters(&hir_parameters);
+   signature = sig;
+
+   /* Function declarations (prototypes) do not have r-values.
+    */
+   return NULL;
+}
+
+
+ir_rvalue *
+ast_function_definition::hir(exec_list *instructions,
+                            struct _mesa_glsl_parse_state *state)
+{
+   prototype->is_definition = true;
+   prototype->hir(instructions, state);
+
+   ir_function_signature *signature = prototype->signature;
+   if (signature == NULL)
+      return NULL;
+
+   assert(state->current_function == NULL);
+   state->current_function = signature;
+   state->found_return = false;
+
+   /* Duplicate parameters declared in the prototype as concrete variables.
+    * Add these to the symbol table.
+    */
+   state->symbols->push_scope();
+   foreach_iter(exec_list_iterator, iter, signature->parameters) {
+      ir_variable *const var = ((ir_instruction *) iter.get())->as_variable();
+
+      assert(var != NULL);
+
+      /* The only way a parameter would "exist" is if two parameters have
+       * the same name.
+       */
+      if (state->symbols->name_declared_this_scope(var->name)) {
+        YYLTYPE loc = this->get_location();
+
+        _mesa_glsl_error(& loc, state, "parameter `%s' redeclared", var->name);
+      } else {
+        state->symbols->add_variable(var->name, var);
+      }
+   }
+
+   /* Convert the body of the function to HIR. */
+   this->body->hir(&signature->body, state);
+   signature->is_defined = true;
+
+   state->symbols->pop_scope();
+
+   assert(state->current_function == signature);
+   state->current_function = NULL;
+
+   if (!signature->return_type->is_void() && !state->found_return) {
+      YYLTYPE loc = this->get_location();
+      _mesa_glsl_error(& loc, state, "function `%s' has non-void return type "
+                      "%s, but no return statement",
+                      signature->function_name(),
+                      signature->return_type->name);
+   }
+
+   /* Function definitions do not have r-values.
+    */
+   return NULL;
+}
+
+
+ir_rvalue *
+ast_jump_statement::hir(exec_list *instructions,
+                       struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+
+   switch (mode) {
+   case ast_return: {
+      ir_return *inst;
+      assert(state->current_function);
+
+      if (opt_return_value) {
+        if (state->current_function->return_type->base_type ==
+            GLSL_TYPE_VOID) {
+           YYLTYPE loc = this->get_location();
+
+           _mesa_glsl_error(& loc, state,
+                            "`return` with a value, in function `%s' "
+                            "returning void",
+                            state->current_function->function_name());
+        }
+
+        ir_expression *const ret = (ir_expression *)
+           opt_return_value->hir(instructions, state);
+        assert(ret != NULL);
+
+        /* Implicit conversions are not allowed for return values. */
+        if (state->current_function->return_type != ret->type) {
+           YYLTYPE loc = this->get_location();
+
+           _mesa_glsl_error(& loc, state,
+                            "`return' with wrong type %s, in function `%s' "
+                            "returning %s",
+                            ret->type->name,
+                            state->current_function->function_name(),
+                            state->current_function->return_type->name);
+        }
+
+        inst = new(ctx) ir_return(ret);
+      } else {
+        if (state->current_function->return_type->base_type !=
+            GLSL_TYPE_VOID) {
+           YYLTYPE loc = this->get_location();
+
+           _mesa_glsl_error(& loc, state,
+                            "`return' with no value, in function %s returning "
+                            "non-void",
+                            state->current_function->function_name());
+        }
+        inst = new(ctx) ir_return;
+      }
+
+      state->found_return = true;
+      instructions->push_tail(inst);
+      break;
+   }
+
+   case ast_discard:
+      if (state->target != fragment_shader) {
+        YYLTYPE loc = this->get_location();
+
+        _mesa_glsl_error(& loc, state,
+                         "`discard' may only appear in a fragment shader");
+      }
+      instructions->push_tail(new(ctx) ir_discard);
+      break;
+
+   case ast_break:
+   case ast_continue:
+      /* FINISHME: Handle switch-statements.  They cannot contain 'continue',
+       * FINISHME: and they use a different IR instruction for 'break'.
+       */
+      /* FINISHME: Correctly handle the nesting.  If a switch-statement is
+       * FINISHME: inside a loop, a 'continue' is valid and will bind to the
+       * FINISHME: loop.
+       */
+      if (state->loop_or_switch_nesting == NULL) {
+        YYLTYPE loc = this->get_location();
+
+        _mesa_glsl_error(& loc, state,
+                         "`%s' may only appear in a loop",
+                         (mode == ast_break) ? "break" : "continue");
+      } else {
+        ir_loop *const loop = state->loop_or_switch_nesting->as_loop();
+
+        /* Inline the for loop expression again, since we don't know
+         * where near the end of the loop body the normal copy of it
+         * is going to be placed.
+         */
+        if (mode == ast_continue &&
+            state->loop_or_switch_nesting_ast->rest_expression) {
+           state->loop_or_switch_nesting_ast->rest_expression->hir(instructions,
+                                                                   state);
+        }
+
+        if (loop != NULL) {
+           ir_loop_jump *const jump =
+              new(ctx) ir_loop_jump((mode == ast_break)
+                                    ? ir_loop_jump::jump_break
+                                    : ir_loop_jump::jump_continue);
+           instructions->push_tail(jump);
+        }
+      }
+
+      break;
+   }
+
+   /* Jump instructions do not have r-values.
+    */
+   return NULL;
+}
+
+
+ir_rvalue *
+ast_selection_statement::hir(exec_list *instructions,
+                            struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+
+   ir_rvalue *const condition = this->condition->hir(instructions, state);
+
+   /* From page 66 (page 72 of the PDF) of the GLSL 1.50 spec:
+    *
+    *    "Any expression whose type evaluates to a Boolean can be used as the
+    *    conditional expression bool-expression. Vector types are not accepted
+    *    as the expression to if."
+    *
+    * The checks are separated so that higher quality diagnostics can be
+    * generated for cases where both rules are violated.
+    */
+   if (!condition->type->is_boolean() || !condition->type->is_scalar()) {
+      YYLTYPE loc = this->condition->get_location();
+
+      _mesa_glsl_error(& loc, state, "if-statement condition must be scalar "
+                      "boolean");
+   }
+
+   ir_if *const stmt = new(ctx) ir_if(condition);
+
+   if (then_statement != NULL) {
+      state->symbols->push_scope();
+      then_statement->hir(& stmt->then_instructions, state);
+      state->symbols->pop_scope();
+   }
+
+   if (else_statement != NULL) {
+      state->symbols->push_scope();
+      else_statement->hir(& stmt->else_instructions, state);
+      state->symbols->pop_scope();
+   }
+
+   instructions->push_tail(stmt);
+
+   /* if-statements do not have r-values.
+    */
+   return NULL;
+}
+
+
+void
+ast_iteration_statement::condition_to_hir(ir_loop *stmt,
+                                         struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+
+   if (condition != NULL) {
+      ir_rvalue *const cond =
+        condition->hir(& stmt->body_instructions, state);
+
+      if ((cond == NULL)
+         || !cond->type->is_boolean() || !cond->type->is_scalar()) {
+        YYLTYPE loc = condition->get_location();
+
+        _mesa_glsl_error(& loc, state,
+                         "loop condition must be scalar boolean");
+      } else {
+        /* As the first code in the loop body, generate a block that looks
+         * like 'if (!condition) break;' as the loop termination condition.
+         */
+        ir_rvalue *const not_cond =
+           new(ctx) ir_expression(ir_unop_logic_not, glsl_type::bool_type, cond,
+                                  NULL);
+
+        ir_if *const if_stmt = new(ctx) ir_if(not_cond);
+
+        ir_jump *const break_stmt =
+           new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
+
+        if_stmt->then_instructions.push_tail(break_stmt);
+        stmt->body_instructions.push_tail(if_stmt);
+      }
+   }
+}
+
+
+ir_rvalue *
+ast_iteration_statement::hir(exec_list *instructions,
+                            struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+
+   /* For-loops and while-loops start a new scope, but do-while loops do not.
+    */
+   if (mode != ast_do_while)
+      state->symbols->push_scope();
+
+   if (init_statement != NULL)
+      init_statement->hir(instructions, state);
+
+   ir_loop *const stmt = new(ctx) ir_loop();
+   instructions->push_tail(stmt);
+
+   /* Track the current loop and / or switch-statement nesting.
+    */
+   ir_instruction *const nesting = state->loop_or_switch_nesting;
+   ast_iteration_statement *nesting_ast = state->loop_or_switch_nesting_ast;
+
+   state->loop_or_switch_nesting = stmt;
+   state->loop_or_switch_nesting_ast = this;
+
+   if (mode != ast_do_while)
+      condition_to_hir(stmt, state);
+
+   if (body != NULL)
+      body->hir(& stmt->body_instructions, state);
+
+   if (rest_expression != NULL)
+      rest_expression->hir(& stmt->body_instructions, state);
+
+   if (mode == ast_do_while)
+      condition_to_hir(stmt, state);
+
+   if (mode != ast_do_while)
+      state->symbols->pop_scope();
+
+   /* Restore previous nesting before returning.
+    */
+   state->loop_or_switch_nesting = nesting;
+   state->loop_or_switch_nesting_ast = nesting_ast;
+
+   /* Loops do not have r-values.
+    */
+   return NULL;
+}
+
+
+ir_rvalue *
+ast_type_specifier::hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state)
+{
+   if (this->structure != NULL)
+      return this->structure->hir(instructions, state);
+
+   return NULL;
+}
+
+
+ir_rvalue *
+ast_struct_specifier::hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state)
+{
+   unsigned decl_count = 0;
+
+   /* Make an initial pass over the list of structure fields to determine how
+    * many there are.  Each element in this list is an ast_declarator_list.
+    * This means that we actually need to count the number of elements in the
+    * 'declarations' list in each of the elements.
+    */
+   foreach_list_typed (ast_declarator_list, decl_list, link,
+                      &this->declarations) {
+      foreach_list_const (decl_ptr, & decl_list->declarations) {
+        decl_count++;
+      }
+   }
+
+
+   /* Allocate storage for the structure fields and process the field
+    * declarations.  As the declarations are processed, try to also convert
+    * the types to HIR.  This ensures that structure definitions embedded in
+    * other structure definitions are processed.
+    */
+   glsl_struct_field *const fields = talloc_array(state, glsl_struct_field,
+                                                 decl_count);
+
+   unsigned i = 0;
+   foreach_list_typed (ast_declarator_list, decl_list, link,
+                      &this->declarations) {
+      const char *type_name;
+
+      decl_list->type->specifier->hir(instructions, state);
+
+      const glsl_type *decl_type =
+        decl_list->type->specifier->glsl_type(& type_name, state);
+
+      foreach_list_typed (ast_declaration, decl, link,
+                         &decl_list->declarations) {
+        const struct glsl_type *const field_type =
+           (decl->is_array)
+           ? process_array_type(decl_type, decl->array_size, state)
+           : decl_type;
+
+        fields[i].type = (field_type != NULL)
+           ? field_type : glsl_type::error_type;
+        fields[i].name = decl->identifier;
+        i++;
+      }
+   }
+
+   assert(i == decl_count);
+
+   const char *name;
+   if (this->name == NULL) {
+      static unsigned anon_count = 1;
+      char buf[32];
+
+      snprintf(buf, sizeof(buf), "#anon_struct_%04x", anon_count);
+      anon_count++;
+
+      name = strdup(buf);
+   } else {
+      name = this->name;
+   }
+
+   const glsl_type *t =
+      glsl_type::get_record_instance(fields, decl_count, name);
+
+   YYLTYPE loc = this->get_location();
+   if (!state->symbols->add_type(name, t)) {
+      _mesa_glsl_error(& loc, state, "struct `%s' previously defined", name);
+   } else {
+
+      const glsl_type **s = (const glsl_type **)
+        realloc(state->user_structures,
+                sizeof(state->user_structures[0]) *
+                (state->num_user_structures + 1));
+      if (s != NULL) {
+        s[state->num_user_structures] = t;
+        state->user_structures = s;
+        state->num_user_structures++;
+      }
+   }
+
+   /* Structure type definitions do not have r-values.
+    */
+   return NULL;
+}
diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp
new file mode 100644 (file)
index 0000000..9a95704
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 <cstdio>
+#include "ast.h"
+extern "C" {
+#include "program/symbol_table.h"
+}
+
+void
+ast_type_specifier::print(void) const
+{
+   if (type_specifier == ast_struct) {
+      structure->print();
+   } else {
+      printf("%s ", type_name);
+   }
+
+   if (is_array) {
+      printf("[ ");
+
+      if (array_size) {
+        array_size->print();
+      }
+
+      printf("] ");
+   }
+}
+
+ast_type_specifier::ast_type_specifier(int specifier)
+      : type_specifier(ast_types(specifier)), type_name(NULL), structure(NULL),
+       is_array(false), array_size(NULL), precision(ast_precision_high)
+{
+   static const char *const names[] = {
+      "void",
+      "float",
+      "int",
+      "uint",
+      "bool",
+      "vec2",
+      "vec3",
+      "vec4",
+      "bvec2",
+      "bvec3",
+      "bvec4",
+      "ivec2",
+      "ivec3",
+      "ivec4",
+      "uvec2",
+      "uvec3",
+      "uvec4",
+      "mat2",
+      "mat2x3",
+      "mat2x4",
+      "mat3x2",
+      "mat3",
+      "mat3x4",
+      "mat4x2",
+      "mat4x3",
+      "mat4",
+      "sampler1D",
+      "sampler2D",
+      "sampler2DRect",
+      "sampler3D",
+      "samplerCube",
+      "sampler1DShadow",
+      "sampler2DShadow",
+      "sampler2DRectShadow",
+      "samplerCubeShadow",
+      "sampler1DArray",
+      "sampler2DArray",
+      "sampler1DArrayShadow",
+      "sampler2DArrayShadow",
+      "isampler1D",
+      "isampler2D",
+      "isampler3D",
+      "isamplerCube",
+      "isampler1DArray",
+      "isampler2DArray",
+      "usampler1D",
+      "usampler2D",
+      "usampler3D",
+      "usamplerCube",
+      "usampler1DArray",
+      "usampler2DArray",
+
+      NULL, /* ast_struct */
+      NULL  /* ast_type_name */
+   };
+
+   type_name = names[specifier];
+}
+
+bool
+ast_fully_specified_type::has_qualifiers() const
+{
+   return qualifier.invariant || qualifier.constant || qualifier.attribute
+                             || qualifier.varying || qualifier.in
+                             || qualifier.out || qualifier.centroid
+                             || qualifier.uniform || qualifier.smooth
+                             || qualifier.flat || qualifier.noperspective;
+}
diff --git a/src/glsl/autogen.sh b/src/glsl/autogen.sh
new file mode 100755 (executable)
index 0000000..904cd67
--- /dev/null
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+$srcdir/configure --enable-maintainer-mode "$@"
diff --git a/src/glsl/builtin_function.cpp b/src/glsl/builtin_function.cpp
new file mode 100644 (file)
index 0000000..892b5aa
--- /dev/null
@@ -0,0 +1,16935 @@
+/* DO NOT MODIFY - automatically generated by generate_builtins.py */
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 "main/core.h" /* for struct gl_shader */
+#include "glsl_parser_extras.h"
+#include "ir_reader.h"
+#include "program.h"
+#include "ast.h"
+
+extern "C" struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
+
+gl_shader *
+read_builtins(GLenum target, const char *protos, const char **functions, unsigned count)
+{
+   gl_shader *sh = _mesa_new_shader(NULL, 0, target);
+   struct _mesa_glsl_parse_state *st =
+      new(sh) _mesa_glsl_parse_state(NULL, target, sh);
+
+   st->language_version = 130;
+   st->symbols->language_version = 130;
+   st->ARB_texture_rectangle_enable = true;
+   st->EXT_texture_array_enable = true;
+   _mesa_glsl_initialize_types(st);
+
+   sh->ir = new(sh) exec_list;
+   sh->symbols = st->symbols;
+
+   /* Read the IR containing the prototypes */
+   _mesa_glsl_read_ir(st, sh->ir, protos, true);
+
+   /* Read ALL the function bodies, telling the IR reader not to scan for
+    * prototypes (we've already created them).  The IR reader will skip any
+    * signature that does not already exist as a prototype.
+    */
+   for (unsigned i = 0; i < count; i++) {
+      _mesa_glsl_read_ir(st, sh->ir, functions[i], false);
+
+      if (st->error) {
+         printf("error reading builtin: %.35s ...\n", functions[i]);
+         talloc_free(sh);
+         return NULL;
+      }
+   }
+
+   reparent_ir(sh->ir, sh);
+   delete st;
+
+   return sh;
+}
+
+static const char *builtin_abs =
+   "((function abs\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0))\n"
+   "     ((return (expression float abs (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0))\n"
+   "     ((return (expression vec2 abs (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0))\n"
+   "     ((return (expression vec3 abs (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0))\n"
+   "     ((return (expression vec4 abs (var_ref arg0)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_acos =
+   "((function acos\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float x))\n"
+   "     ((return (expression float - (constant float (1.5707963))\n"
+   "                                  (call asin ((var_ref x)))))))\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((return (expression vec2 - (constant float (1.5707963))\n"
+   "                                 (call asin ((var_ref x)))))))\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((return (expression vec3 - (constant float (1.5707963))\n"
+   "                                 (call asin ((var_ref x)))))))\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((return (expression vec4 - (constant float (1.5707963))\n"
+   "                                 (call asin ((var_ref x)))))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_all =
+   "((function all\n"
+   "   (signature bool\n"
+   "     (parameters\n"
+   "       (declare (in) bvec2 arg0))\n"
+   "     ((return (expression bool && (swiz x (var_ref arg0))(swiz y (var_ref arg0))))))\n"
+   "\n"
+   "   (signature bool\n"
+   "     (parameters\n"
+   "       (declare (in) bvec3 arg0))\n"
+   "     ((return (expression bool && (expression bool && (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0))))))\n"
+   "\n"
+   "   (signature bool\n"
+   "     (parameters\n"
+   "       (declare (in) bvec4 arg0))\n"
+   "     ((return (expression bool && (expression bool && (expression bool && (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0))) (swiz w (var_ref arg0))))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_any =
+   "((function any\n"
+   "   (signature bool\n"
+   "     (parameters\n"
+   "       (declare (in) bvec2 arg0))\n"
+   "     ((return (expression bool any (var_ref arg0)))))\n"
+   "\n"
+   "   (signature bool\n"
+   "     (parameters\n"
+   "       (declare (in) bvec3 arg0))\n"
+   "     ((return (expression bool any (var_ref arg0)))))\n"
+   "\n"
+   "   (signature bool\n"
+   "     (parameters\n"
+   "       (declare (in) bvec4 arg0))\n"
+   "     ((return (expression bool any (var_ref arg0)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_asin =
+   "((function asin\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float x))\n"
+   "     ((return (expression float *\n"
+   "          (expression float sign (var_ref x))\n"
+   "          (expression float -\n"
+   "           (expression float *\n"
+   "            (constant float (3.1415926))\n"
+   "            (constant float (0.5)))\n"
+   "           (expression float *\n"
+   "            (expression float sqrt\n"
+   "             (expression float -\n"
+   "              (constant float (1.0))\n"
+   "              (expression float abs (var_ref x))))\n"
+   "            (expression float +\n"
+   "             (constant float (1.5707288))\n"
+   "             (expression float *\n"
+   "              (expression float abs (var_ref x))\n"
+   "              (expression float +\n"
+   "               (constant float (-0.2121144))\n"
+   "               (expression float *\n"
+   "                (constant float (0.0742610))\n"
+   "                (expression float abs (var_ref x))))))))))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((return (expression vec2 *\n"
+   "          (expression vec2 sign (var_ref x))\n"
+   "          (expression vec2 -\n"
+   "           (expression float *\n"
+   "            (constant float (3.1415926))\n"
+   "            (constant float (0.5)))\n"
+   "           (expression vec2 *\n"
+   "            (expression vec2 sqrt\n"
+   "             (expression vec2 -\n"
+   "              (constant float (1.0))\n"
+   "              (expression vec2 abs (var_ref x))))\n"
+   "            (expression vec2 +\n"
+   "             (constant float (1.5707288))\n"
+   "             (expression vec2 *\n"
+   "              (expression vec2 abs (var_ref x))\n"
+   "              (expression vec2 +\n"
+   "               (constant float (-0.2121144))\n"
+   "               (expression vec2 *\n"
+   "                (constant float (0.0742610))\n"
+   "                (expression vec2 abs (var_ref x))))))))))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((return (expression vec3 *\n"
+   "          (expression vec3 sign (var_ref x))\n"
+   "          (expression vec3 -\n"
+   "           (expression float *\n"
+   "            (constant float (3.1415926))\n"
+   "            (constant float (0.5)))\n"
+   "           (expression vec3 *\n"
+   "            (expression vec3 sqrt\n"
+   "             (expression vec3 -\n"
+   "              (constant float (1.0))\n"
+   "              (expression vec3 abs (var_ref x))))\n"
+   "            (expression vec3 +\n"
+   "             (constant float (1.5707288))\n"
+   "             (expression vec3 *\n"
+   "              (expression vec3 abs (var_ref x))\n"
+   "              (expression vec3 +\n"
+   "               (constant float (-0.2121144))\n"
+   "               (expression vec3 *\n"
+   "                (constant float (0.0742610))\n"
+   "                (expression vec3 abs (var_ref x))))))))))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((return (expression vec4 *\n"
+   "          (expression vec4 sign (var_ref x))\n"
+   "          (expression vec4 -\n"
+   "           (expression float *\n"
+   "            (constant float (3.1415926))\n"
+   "            (constant float (0.5)))\n"
+   "           (expression vec4 *\n"
+   "            (expression vec4 sqrt\n"
+   "             (expression vec4 -\n"
+   "              (constant float (1.0))\n"
+   "              (expression vec4 abs (var_ref x))))\n"
+   "            (expression vec4 +\n"
+   "             (constant float (1.5707288))\n"
+   "             (expression vec4 *\n"
+   "              (expression vec4 abs (var_ref x))\n"
+   "              (expression vec4 +\n"
+   "               (constant float (-0.2121144))\n"
+   "               (expression vec4 *\n"
+   "                (constant float (0.0742610))\n"
+   "                (expression vec4 abs (var_ref x))))))))))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_atan =
+   "((function atan\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float x))\n"
+   "     ((return (call asin ((expression float *\n"
+   "                      (var_ref x)\n"
+   "                      (expression float rsq\n"
+   "                       (expression float +\n"
+   "                        (expression float *\n"
+   "                         (var_ref x)\n"
+   "                         (var_ref x))\n"
+   "                        (constant float (1.0))))))))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 y_over_x))\n"
+   "     ((return (call asin ((expression vec2 *\n"
+   "                      (var_ref y_over_x)\n"
+   "                      (expression vec2 rsq\n"
+   "                       (expression vec2 +\n"
+   "                        (expression vec2 *\n"
+   "                         (var_ref y_over_x)\n"
+   "                         (var_ref y_over_x))\n"
+   "                        (constant float (1.0))))))))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 y_over_x))\n"
+   "     ((return (call asin ((expression vec3 *\n"
+   "                      (var_ref y_over_x)\n"
+   "                      (expression vec3 rsq\n"
+   "                       (expression vec3 +\n"
+   "                        (expression vec3 *\n"
+   "                         (var_ref y_over_x)\n"
+   "                         (var_ref y_over_x))\n"
+   "                        (constant float (1.0))))))))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 y_over_x))\n"
+   "     ((return (call asin ((expression vec4 *\n"
+   "                      (var_ref y_over_x)\n"
+   "                      (expression vec4 rsq\n"
+   "                       (expression vec4 +\n"
+   "                        (expression vec4 *\n"
+   "                         (var_ref y_over_x)\n"
+   "                         (var_ref y_over_x))\n"
+   "                        (constant float (1.0))))))))))\n"
+   "\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in ) float y)\n"
+   "      (declare (in ) float x)\n"
+   "    )\n"
+   "    (\n"
+   "      (declare () float r)\n"
+   "      (declare ( ) float abs_retval)\n"
+   "      (assign (constant bool (1)) (var_ref abs_retval)  (call abs ((var_ref x) ))\n"
+   ") \n"
+   "      (if (expression bool > (var_ref abs_retval) (constant float (0.000100)) ) (\n"
+   "        (declare ( ) float atan_retval)\n"
+   "        (assign (constant bool (1)) (var_ref atan_retval)  (call atan ((expression float / (var_ref y) (var_ref x) ) ))\n"
+   ") \n"
+   "        (assign (constant bool (1)) (var_ref r)  (var_ref atan_retval) ) \n"
+   "        (if (expression bool < (var_ref x) (constant float (0.000000)) ) (\n"
+   "\n"
+   "\n"
+   "          (if (expression bool >= (var_ref y) (constant float (0.000000)) ) (\n"
+   "            (declare ( ) float assignment_tmp)\n"
+   "            (assign (constant bool (1)) (var_ref assignment_tmp)  (expression float + (var_ref r) (constant float (3.141593)) ) ) \n"
+   "            (assign (constant bool (1)) (var_ref r)  (var_ref assignment_tmp) ) \n"
+   "          )\n"
+   "          (\n"
+   "            (declare ( ) float assignment_tmp)\n"
+   "            (assign (constant bool (1)) (var_ref assignment_tmp)  (expression float - (var_ref r) (constant float (3.141593)) ) ) \n"
+   "            (assign (constant bool (1)) (var_ref r)  (var_ref assignment_tmp) ) \n"
+   "          ))\n"
+   "\n"
+   "        )\n"
+   "        (\n"
+   "        ))\n"
+   "\n"
+   "      )\n"
+   "      (\n"
+   "\n"
+   "        (declare () float sgn)\n"
+   "        (assign (constant bool (1)) (var_ref sgn) (expression float sign (var_ref y)))\n"
+   "        (assign (constant bool (1)) (var_ref r) (expression float * (var_ref sgn) (constant float (1.5707965))))\n"
+   "\n"
+   "      ))\n"
+   "\n"
+   "      (return (var_ref r) )\n"
+   "    ))\n"
+   "\n"
+   "\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 y)\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((declare () vec2 r)\n"
+   "      (assign (constant bool (1))\n"
+   "         (swiz x (var_ref r))\n"
+   "         (call atan ((swiz x (var_ref y))\n"
+   "                     (swiz x (var_ref x)))))\n"
+   "      (assign (constant bool (1))\n"
+   "         (swiz y (var_ref r))\n"
+   "         (call atan ((swiz y (var_ref y))\n"
+   "                     (swiz y (var_ref x)))))\n"
+   "      (return (var_ref r))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 y)\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((declare () vec3 r)\n"
+   "      (assign (constant bool (1))\n"
+   "         (swiz x (var_ref r))\n"
+   "         (call atan ((swiz x (var_ref y))\n"
+   "                     (swiz x (var_ref x)))))\n"
+   "      (assign (constant bool (1))\n"
+   "         (swiz y (var_ref r))\n"
+   "         (call atan ((swiz y (var_ref y))\n"
+   "                     (swiz y (var_ref x)))))\n"
+   "      (assign (constant bool (1))\n"
+   "         (swiz z (var_ref r))\n"
+   "         (call atan ((swiz z (var_ref y))\n"
+   "                     (swiz z (var_ref x)))))\n"
+   "      (return (var_ref r))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 y)\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((declare () vec4 r)\n"
+   "      (assign (constant bool (1))\n"
+   "         (swiz x (var_ref r))\n"
+   "         (call atan ((swiz x (var_ref y))\n"
+   "                     (swiz x (var_ref x)))))\n"
+   "      (assign (constant bool (1))\n"
+   "         (swiz y (var_ref r))\n"
+   "         (call atan ((swiz y (var_ref y))\n"
+   "                     (swiz y (var_ref x)))))\n"
+   "      (assign (constant bool (1))\n"
+   "         (swiz z (var_ref r))\n"
+   "         (call atan ((swiz z (var_ref y))\n"
+   "                     (swiz z (var_ref x)))))\n"
+   "      (assign (constant bool (1))\n"
+   "         (swiz w (var_ref r))\n"
+   "         (call atan ((swiz w (var_ref y))\n"
+   "                     (swiz w (var_ref x)))))\n"
+   "      (return (var_ref r)))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_ceil =
+   "((function ceil\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0))\n"
+   "     ((return (expression float ceil (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0))\n"
+   "     ((return (expression vec2 ceil (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0))\n"
+   "     ((return (expression vec3 ceil (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0))\n"
+   "     ((return (expression vec4 ceil (var_ref arg0)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_clamp =
+   "((function clamp\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0)\n"
+   "       (declare (in) float arg1)\n"
+   "       (declare (in) float arg2))\n"
+   "     ((return (expression float max (expression float min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0)\n"
+   "       (declare (in) vec2 arg1)\n"
+   "       (declare (in) vec2 arg2))\n"
+   "     ((return (expression vec2 max (expression vec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0)\n"
+   "       (declare (in) vec3 arg1)\n"
+   "       (declare (in) vec3 arg2))\n"
+   "     ((return (expression vec3 max (expression vec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0)\n"
+   "       (declare (in) vec4 arg1)\n"
+   "       (declare (in) vec4 arg2))\n"
+   "     ((return (expression vec4 max (expression vec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2  arg0)\n"
+   "       (declare (in) float arg1)\n"
+   "       (declare (in) float arg2))\n"
+   "     ((return (expression vec2 max (expression vec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3  arg0)\n"
+   "       (declare (in) float arg1)\n"
+   "       (declare (in) float arg2))\n"
+   "     ((return (expression vec3 max (expression vec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4  arg0)\n"
+   "       (declare (in) float arg1)\n"
+   "       (declare (in) float arg2))\n"
+   "     ((return (expression vec4 max (expression vec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature int\n"
+   "     (parameters\n"
+   "       (declare (in) int arg0)\n"
+   "       (declare (in) int arg1)\n"
+   "       (declare (in) int arg2))\n"
+   "     ((return (expression int max (expression int min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec2\n"
+   "     (parameters\n"
+   "       (declare (in) ivec2 arg0)\n"
+   "       (declare (in) ivec2 arg1)\n"
+   "       (declare (in) ivec2 arg2))\n"
+   "     ((return (expression ivec2 max (expression ivec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec3\n"
+   "     (parameters\n"
+   "       (declare (in) ivec3 arg0)\n"
+   "       (declare (in) ivec3 arg1)\n"
+   "       (declare (in) ivec3 arg2))\n"
+   "     ((return (expression ivec3 max (expression ivec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) ivec4 arg0)\n"
+   "       (declare (in) ivec4 arg1)\n"
+   "       (declare (in) ivec4 arg2))\n"
+   "     ((return (expression ivec4 max (expression ivec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec2\n"
+   "     (parameters\n"
+   "       (declare (in) ivec2 arg0)\n"
+   "       (declare (in) int arg1)\n"
+   "       (declare (in) int arg2))\n"
+   "     ((return (expression ivec2 max (expression ivec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec3\n"
+   "     (parameters\n"
+   "       (declare (in) ivec3 arg0)\n"
+   "       (declare (in) int arg1)\n"
+   "       (declare (in) int arg2))\n"
+   "     ((return (expression ivec3 max (expression ivec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) ivec4 arg0)\n"
+   "       (declare (in) int arg1)\n"
+   "       (declare (in) int arg2))\n"
+   "     ((return (expression ivec4 max (expression ivec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uint\n"
+   "     (parameters\n"
+   "       (declare (in) uint arg0)\n"
+   "       (declare (in) uint arg1)\n"
+   "       (declare (in) uint arg2))\n"
+   "     ((return (expression uint max (expression uint min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec2\n"
+   "     (parameters\n"
+   "       (declare (in) uvec2 arg0)\n"
+   "       (declare (in) uvec2 arg1)\n"
+   "       (declare (in) uvec2 arg2))\n"
+   "     ((return (expression uvec2 max (expression uvec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec3\n"
+   "     (parameters\n"
+   "       (declare (in) uvec3 arg0)\n"
+   "       (declare (in) uvec3 arg1)\n"
+   "       (declare (in) uvec3 arg2))\n"
+   "     ((return (expression uvec3 max (expression uvec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) uvec4 arg0)\n"
+   "       (declare (in) uvec4 arg1)\n"
+   "       (declare (in) uvec4 arg2))\n"
+   "     ((return (expression uvec4 max (expression uvec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec2\n"
+   "     (parameters\n"
+   "       (declare (in) uvec2 arg0)\n"
+   "       (declare (in) uint arg1)\n"
+   "       (declare (in) uint arg2))\n"
+   "     ((return (expression uvec2 max (expression uvec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec3\n"
+   "     (parameters\n"
+   "       (declare (in) uvec3 arg0)\n"
+   "       (declare (in) uint arg1)\n"
+   "       (declare (in) uint arg2))\n"
+   "     ((return (expression uvec3 max (expression uvec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) uvec4 arg0)\n"
+   "       (declare (in) uint arg1)\n"
+   "       (declare (in) uint arg2))\n"
+   "     ((return (expression uvec4 max (expression uvec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_cos =
+   "((function cos\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float angle))\n"
+   "     ((return (expression float cos (var_ref angle)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 angle))\n"
+   "     ((return (expression vec2 cos (var_ref angle)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 angle))\n"
+   "     ((return (expression vec3 cos (var_ref angle)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 angle))\n"
+   "     ((return (expression vec4 cos (var_ref angle)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_cosh =
+   "((function cosh\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float x))\n"
+   "     ((return (expression float * (constant float (0.5))\n"
+   "                (expression float +\n"
+   "             (expression float exp (var_ref x))\n"
+   "             (expression float exp (expression float neg (var_ref x))))))))\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((return (expression vec2 * (constant vec2 (0.5))\n"
+   "                (expression vec2 +\n"
+   "             (expression vec2 exp (var_ref x))\n"
+   "             (expression vec2 exp (expression vec2 neg (var_ref x))))))))\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((return (expression vec3 * (constant vec3 (0.5))\n"
+   "                (expression vec3 +\n"
+   "             (expression vec3 exp (var_ref x))\n"
+   "             (expression vec3 exp (expression vec3 neg (var_ref x))))))))\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((return (expression vec4 * (constant vec4 (0.5))\n"
+   "                (expression vec4 +\n"
+   "             (expression vec4 exp (var_ref x))\n"
+   "             (expression vec4 exp (expression vec4 neg (var_ref x))))))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_cross =
+   "((function cross\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0)\n"
+   "       (declare (in) vec3 arg1))\n"
+   "     ((return (expression vec3 cross (var_ref arg0) (var_ref arg1)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_dFdx =
+   "((function dFdx\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float p))\n"
+   "     ((return (expression float dFdx (var_ref p)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 p))\n"
+   "     ((return (expression vec2 dFdx (var_ref p)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 p))\n"
+   "     ((return (expression vec3 dFdx (var_ref p)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 p))\n"
+   "     ((return (expression vec4 dFdx (var_ref p)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_dFdy =
+   "((function dFdy\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float p))\n"
+   "     ((return (expression float dFdy (var_ref p)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 p))\n"
+   "     ((return (expression vec2 dFdy (var_ref p)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 p))\n"
+   "     ((return (expression vec3 dFdy (var_ref p)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 p))\n"
+   "     ((return (expression vec4 dFdy (var_ref p)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_degrees =
+   "((function degrees\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0))\n"
+   "     ((return (expression float * (var_ref arg0) (constant float (57.295780))))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0))\n"
+   "     ((return (expression vec2 * (var_ref arg0) (constant float (57.295780))))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0))\n"
+   "     ((return (expression vec3 * (var_ref arg0) (constant float (57.295780))))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0))\n"
+   "     ((return (expression vec4 * (var_ref arg0) (constant float (57.295780))))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_distance =
+   "((function distance\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float p0)\n"
+   "       (declare (in) float p1))\n"
+   "     ((declare () float p)\n"
+   "      (assign (constant bool (1)) (var_ref p) (expression float - (var_ref p0) (var_ref p1)))\n"
+   "      (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))\n"
+   "\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 p0)\n"
+   "       (declare (in) vec2 p1))\n"
+   "     ((declare () vec2 p)\n"
+   "      (assign (constant bool (1)) (var_ref p) (expression vec2 - (var_ref p0) (var_ref p1)))\n"
+   "      (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))\n"
+   "\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 p0)\n"
+   "       (declare (in) vec3 p1))\n"
+   "     ((declare () vec3 p)\n"
+   "      (assign (constant bool (1)) (var_ref p) (expression vec3 - (var_ref p0) (var_ref p1)))\n"
+   "      (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))\n"
+   "\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 p0)\n"
+   "       (declare (in) vec4 p1))\n"
+   "     ((declare () vec4 p)\n"
+   "      (assign (constant bool (1)) (var_ref p) (expression vec4 - (var_ref p0) (var_ref p1)))\n"
+   "      (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_dot =
+   "((function dot\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0)\n"
+   "       (declare (in) float arg1))\n"
+   "     ((return (expression float dot (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0)\n"
+   "       (declare (in) vec2 arg1))\n"
+   "     ((return (expression float dot (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0)\n"
+   "       (declare (in) vec3 arg1))\n"
+   "     ((return (expression float dot (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0)\n"
+   "       (declare (in) vec4 arg1))\n"
+   "     ((return (expression float dot (var_ref arg0) (var_ref arg1)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_equal =
+   "((function equal\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0)\n"
+   "       (declare (in) vec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0)\n"
+   "       (declare (in) vec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0)\n"
+   "       (declare (in) vec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool == (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) bvec2 arg0)\n"
+   "       (declare (in) bvec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) bvec3 arg0)\n"
+   "       (declare (in) bvec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1))))\n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) bvec4 arg0)\n"
+   "       (declare (in) bvec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool == (swiz w (var_ref arg0))(swiz w (var_ref arg1))))\n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) ivec2 arg0)\n"
+   "       (declare (in) ivec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) ivec3 arg0)\n"
+   "       (declare (in) ivec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) ivec4 arg0)\n"
+   "       (declare (in) ivec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool == (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) uvec2 arg0)\n"
+   "       (declare (in) uvec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) uvec3 arg0)\n"
+   "       (declare (in) uvec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) uvec4 arg0)\n"
+   "       (declare (in) uvec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool == (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_exp =
+   "((function exp\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0))\n"
+   "     ((return (expression float exp (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0))\n"
+   "     ((return (expression vec2 exp (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0))\n"
+   "     ((return (expression vec3 exp (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0))\n"
+   "     ((return (expression vec4 exp (var_ref arg0)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_exp2 =
+   "((function exp2\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0))\n"
+   "     ((return (expression float exp2 (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0))\n"
+   "     ((return (expression vec2 exp2 (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0))\n"
+   "     ((return (expression vec3 exp2 (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0))\n"
+   "     ((return (expression vec4 exp2 (var_ref arg0)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_faceforward =
+   "((function faceforward\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float N)\n"
+   "       (declare (in) float I)\n"
+   "       (declare (in) float Nref))\n"
+   "     ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))\n"
+   "          ((return (var_ref N)))\n"
+   "     ((return (expression float neg (var_ref N)))))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 N)\n"
+   "       (declare (in) vec2 I)\n"
+   "       (declare (in) vec2 Nref))\n"
+   "     ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))\n"
+   "          ((return (var_ref N)))\n"
+   "     ((return (expression vec2 neg (var_ref N)))))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 N)\n"
+   "       (declare (in) vec3 I)\n"
+   "       (declare (in) vec3 Nref))\n"
+   "     ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))\n"
+   "          ((return (var_ref N)))\n"
+   "     ((return (expression vec3 neg (var_ref N)))))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 N)\n"
+   "       (declare (in) vec4 I)\n"
+   "       (declare (in) vec4 Nref))\n"
+   "     ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))\n"
+   "          ((return (var_ref N)))\n"
+   "     ((return (expression vec4 neg (var_ref N)))))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_floor =
+   "((function floor\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0))\n"
+   "     ((return (expression float floor (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0))\n"
+   "     ((return (expression vec2 floor (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0))\n"
+   "     ((return (expression vec3 floor (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0))\n"
+   "     ((return (expression vec4 floor (var_ref arg0)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_fract =
+   "((function fract\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float x))\n"
+   "     ((return (expression float fract (var_ref x)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((return (expression vec2 fract (var_ref x)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((return (expression vec3 fract (var_ref x)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((return (expression vec4 fract (var_ref x)))))\n"
+   "))\n"
+   "\n"
+   ""
+;
+static const char *builtin_ftransform =
+   "((declare (uniform) mat4 gl_ModelViewProjectionMatrix)\n"
+   " (declare (in) vec4 gl_Vertex)\n"
+   " (function ftransform\n"
+   "   (signature vec4\n"
+   "     (parameters)\n"
+   "    ((return (expression vec4 *\n"
+   "         (var_ref gl_ModelViewProjectionMatrix)\n"
+   "         (var_ref gl_Vertex)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_fwidth =
+   "((function fwidth\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float p))\n"
+   "     ((return (expression float +\n"
+   "                (expression float abs (expression float dFdx (var_ref p)))\n"
+   "                (expression float abs (expression float dFdy (var_ref p)))))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 p))\n"
+   "     ((return (expression vec2 +\n"
+   "                (expression vec2 abs (expression vec2 dFdx (var_ref p)))\n"
+   "                (expression vec2 abs (expression vec2 dFdy (var_ref p)))))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 p))\n"
+   "     ((return (expression vec3 +\n"
+   "                (expression vec3 abs (expression vec3 dFdx (var_ref p)))\n"
+   "                (expression vec3 abs (expression vec3 dFdy (var_ref p)))))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 p))\n"
+   "     ((return (expression vec4 +\n"
+   "                (expression vec4 abs (expression vec4 dFdx (var_ref p)))\n"
+   "                (expression vec4 abs (expression vec4 dFdy (var_ref p)))))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_greaterThan =
+   "((function greaterThan\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0)\n"
+   "       (declare (in) vec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0)\n"
+   "       (declare (in) vec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0)\n"
+   "       (declare (in) vec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool > (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) ivec2 arg0)\n"
+   "       (declare (in) ivec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) ivec3 arg0)\n"
+   "       (declare (in) ivec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) ivec4 arg0)\n"
+   "       (declare (in) ivec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool > (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) uvec2 arg0)\n"
+   "       (declare (in) uvec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) uvec3 arg0)\n"
+   "       (declare (in) uvec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) uvec4 arg0)\n"
+   "       (declare (in) uvec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool > (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_greaterThanEqual =
+   "((function greaterThanEqual\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0)\n"
+   "       (declare (in) vec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0)\n"
+   "       (declare (in) vec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0)\n"
+   "       (declare (in) vec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool >= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) ivec2 arg0)\n"
+   "       (declare (in) ivec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) ivec3 arg0)\n"
+   "       (declare (in) ivec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) ivec4 arg0)\n"
+   "       (declare (in) ivec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool >= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) uvec2 arg0)\n"
+   "       (declare (in) uvec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) uvec3 arg0)\n"
+   "       (declare (in) uvec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) uvec4 arg0)\n"
+   "       (declare (in) uvec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool >= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_inversesqrt =
+   "((function inversesqrt\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0))\n"
+   "     ((return (expression float rsq (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0))\n"
+   "     ((return (expression vec2 rsq (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0))\n"
+   "     ((return (expression vec3 rsq (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0))\n"
+   "     ((return (expression vec4 rsq (var_ref arg0)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_length =
+   "((function length\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0))\n"
+   "     ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))\n"
+   "\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0))\n"
+   "     ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))\n"
+   "\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0))\n"
+   "     ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))\n"
+   "\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0))\n"
+   "     ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_lessThan =
+   "((function lessThan\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0)\n"
+   "       (declare (in) vec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0)\n"
+   "       (declare (in) vec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0)\n"
+   "       (declare (in) vec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool < (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) ivec2 arg0)\n"
+   "       (declare (in) ivec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) ivec3 arg0)\n"
+   "       (declare (in) ivec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) ivec4 arg0)\n"
+   "       (declare (in) ivec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool < (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) uvec2 arg0)\n"
+   "       (declare (in) uvec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) uvec3 arg0)\n"
+   "       (declare (in) uvec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) uvec4 arg0)\n"
+   "       (declare (in) uvec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool < (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_lessThanEqual =
+   "((function lessThanEqual\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0)\n"
+   "       (declare (in) vec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0)\n"
+   "       (declare (in) vec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0)\n"
+   "       (declare (in) vec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool <= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) ivec2 arg0)\n"
+   "       (declare (in) ivec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) ivec3 arg0)\n"
+   "       (declare (in) ivec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) ivec4 arg0)\n"
+   "       (declare (in) ivec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool <= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) uvec2 arg0)\n"
+   "       (declare (in) uvec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) uvec3 arg0)\n"
+   "       (declare (in) uvec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) uvec4 arg0)\n"
+   "       (declare (in) uvec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool <= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_log =
+   "((function log\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0))\n"
+   "     ((return (expression float log (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0))\n"
+   "     ((return (expression vec2 log (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0))\n"
+   "     ((return (expression vec3 log (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0))\n"
+   "     ((return (expression vec4 log (var_ref arg0)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_log2 =
+   "((function log2\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0))\n"
+   "     ((return (expression float log2 (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0))\n"
+   "     ((return (expression vec2 log2 (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0))\n"
+   "     ((return (expression vec3 log2 (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0))\n"
+   "     ((return (expression vec4 log2 (var_ref arg0)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_matrixCompMult =
+   "((function matrixCompMult\n"
+   "   (signature mat2\n"
+   "     (parameters\n"
+   "       (declare (in) mat2 x)\n"
+   "       (declare (in) mat2 y))\n"
+   "     ((declare () mat2 z)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec2 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec2 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+   "(return (var_ref z))))\n"
+   "\n"
+   "   (signature mat3\n"
+   "     (parameters\n"
+   "       (declare (in) mat3 x)\n"
+   "       (declare (in) mat3 y))\n"
+   "     ((declare () mat3 z)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec3 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec3 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2)))  (expression vec3 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) \n"
+   "(return (var_ref z))))\n"
+   "\n"
+   "   (signature mat4\n"
+   "     (parameters\n"
+   "       (declare (in) mat4 x)\n"
+   "       (declare (in) mat4 y))\n"
+   "     ((declare () mat4 z)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec4 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec4 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2)))  (expression vec4 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (3)))  (expression vec4 * (array_ref (var_ref x) (constant int (3))) (array_ref (var_ref y) (constant int (3))))) \n"
+   "(return (var_ref z))))\n"
+   "\n"
+   "   (signature mat2x3\n"
+   "     (parameters\n"
+   "       (declare (in) mat2x3 x)\n"
+   "       (declare (in) mat2x3 y))\n"
+   "     ((declare () mat2x3 z)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec3 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec3 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+   "(return (var_ref z))))\n"
+   "\n"
+   "   (signature mat3x2\n"
+   "     (parameters\n"
+   "       (declare (in) mat3x2 x)\n"
+   "       (declare (in) mat3x2 y))\n"
+   "     ((declare () mat3x2 z)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec2 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec2 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2)))  (expression vec2 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) \n"
+   "(return (var_ref z))))\n"
+   "\n"
+   "   (signature mat2x4\n"
+   "     (parameters\n"
+   "       (declare (in) mat2x4 x)\n"
+   "       (declare (in) mat2x4 y))\n"
+   "     ((declare () mat2x4 z)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec4 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec4 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+   "(return (var_ref z))))\n"
+   "\n"
+   "   (signature mat4x2\n"
+   "     (parameters\n"
+   "       (declare (in) mat4x2 x)\n"
+   "       (declare (in) mat4x2 y))\n"
+   "     ((declare () mat4x2 z)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec2 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec2 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2)))  (expression vec2 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (3)))  (expression vec2 * (array_ref (var_ref x) (constant int (3))) (array_ref (var_ref y) (constant int (3))))) \n"
+   "(return (var_ref z))))\n"
+   "\n"
+   "   (signature mat3x4\n"
+   "     (parameters\n"
+   "       (declare (in) mat3x4 x)\n"
+   "       (declare (in) mat3x4 y))\n"
+   "     ((declare () mat3x4 z)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec4 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec4 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2)))  (expression vec4 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) \n"
+   "(return (var_ref z))))\n"
+   "\n"
+   "   (signature mat4x3\n"
+   "     (parameters\n"
+   "       (declare (in) mat4x3 x)\n"
+   "       (declare (in) mat4x3 y))\n"
+   "     ((declare () mat4x3 z)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec3 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec3 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2)))  (expression vec3 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (3)))  (expression vec3 * (array_ref (var_ref x) (constant int (3))) (array_ref (var_ref y) (constant int (3))))) \n"
+   "(return (var_ref z))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_max =
+   "((function max\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0)\n"
+   "       (declare (in) float arg1))\n"
+   "     ((return (expression float max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0)\n"
+   "       (declare (in) vec2 arg1))\n"
+   "     ((return (expression vec2 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0)\n"
+   "       (declare (in) vec3 arg1))\n"
+   "     ((return (expression vec3 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0)\n"
+   "       (declare (in) vec4 arg1))\n"
+   "     ((return (expression vec4 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2  arg0)\n"
+   "       (declare (in) float arg1))\n"
+   "     ((return (expression vec2 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3  arg0)\n"
+   "       (declare (in) float arg1))\n"
+   "     ((return (expression vec3 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4  arg0)\n"
+   "       (declare (in) float arg1))\n"
+   "     ((return (expression vec4 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature int\n"
+   "     (parameters\n"
+   "       (declare (in) int arg0)\n"
+   "       (declare (in) int arg1))\n"
+   "     ((return (expression int max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec2\n"
+   "     (parameters\n"
+   "       (declare (in) ivec2 arg0)\n"
+   "       (declare (in) ivec2 arg1))\n"
+   "     ((return (expression ivec2 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec3\n"
+   "     (parameters\n"
+   "       (declare (in) ivec3 arg0)\n"
+   "       (declare (in) ivec3 arg1))\n"
+   "     ((return (expression ivec3 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) ivec4 arg0)\n"
+   "       (declare (in) ivec4 arg1))\n"
+   "     ((return (expression ivec4 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec2\n"
+   "     (parameters\n"
+   "       (declare (in) ivec2  arg0)\n"
+   "       (declare (in) int arg1))\n"
+   "     ((return (expression ivec2 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec3\n"
+   "     (parameters\n"
+   "       (declare (in) ivec3  arg0)\n"
+   "       (declare (in) int arg1))\n"
+   "     ((return (expression ivec3 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) ivec4  arg0)\n"
+   "       (declare (in) int arg1))\n"
+   "     ((return (expression ivec4 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uint\n"
+   "     (parameters\n"
+   "       (declare (in) uint arg0)\n"
+   "       (declare (in) uint arg1))\n"
+   "     ((return (expression uint max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec2\n"
+   "     (parameters\n"
+   "       (declare (in) uvec2 arg0)\n"
+   "       (declare (in) uvec2 arg1))\n"
+   "     ((return (expression uvec2 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec3\n"
+   "     (parameters\n"
+   "       (declare (in) uvec3 arg0)\n"
+   "       (declare (in) uvec3 arg1))\n"
+   "     ((return (expression uvec3 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) uvec4 arg0)\n"
+   "       (declare (in) uvec4 arg1))\n"
+   "     ((return (expression uvec4 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec2\n"
+   "     (parameters\n"
+   "       (declare (in) uvec2  arg0)\n"
+   "       (declare (in) uint arg1))\n"
+   "     ((return (expression uvec2 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec3\n"
+   "     (parameters\n"
+   "       (declare (in) uvec3  arg0)\n"
+   "       (declare (in) uint arg1))\n"
+   "     ((return (expression uvec3 max (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) uvec4  arg0)\n"
+   "       (declare (in) uint arg1))\n"
+   "     ((return (expression uvec4 max (var_ref arg0) (var_ref arg1)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_min =
+   "((function min\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0)\n"
+   "       (declare (in) float arg1))\n"
+   "     ((return (expression float min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0)\n"
+   "       (declare (in) vec2 arg1))\n"
+   "     ((return (expression vec2 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0)\n"
+   "       (declare (in) vec3 arg1))\n"
+   "     ((return (expression vec3 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0)\n"
+   "       (declare (in) vec4 arg1))\n"
+   "     ((return (expression vec4 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2  arg0)\n"
+   "       (declare (in) float arg1))\n"
+   "     ((return (expression vec2 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3  arg0)\n"
+   "       (declare (in) float arg1))\n"
+   "     ((return (expression vec3 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4  arg0)\n"
+   "       (declare (in) float arg1))\n"
+   "     ((return (expression vec4 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature int\n"
+   "     (parameters\n"
+   "       (declare (in) int arg0)\n"
+   "       (declare (in) int arg1))\n"
+   "     ((return (expression int min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec2\n"
+   "     (parameters\n"
+   "       (declare (in) ivec2 arg0)\n"
+   "       (declare (in) ivec2 arg1))\n"
+   "     ((return (expression ivec2 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec3\n"
+   "     (parameters\n"
+   "       (declare (in) ivec3 arg0)\n"
+   "       (declare (in) ivec3 arg1))\n"
+   "     ((return (expression ivec3 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) ivec4 arg0)\n"
+   "       (declare (in) ivec4 arg1))\n"
+   "     ((return (expression ivec4 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec2\n"
+   "     (parameters\n"
+   "       (declare (in) ivec2  arg0)\n"
+   "       (declare (in) int arg1))\n"
+   "     ((return (expression ivec2 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec3\n"
+   "     (parameters\n"
+   "       (declare (in) ivec3  arg0)\n"
+   "       (declare (in) int arg1))\n"
+   "     ((return (expression ivec3 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) ivec4  arg0)\n"
+   "       (declare (in) int arg1))\n"
+   "     ((return (expression ivec4 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uint\n"
+   "     (parameters\n"
+   "       (declare (in) uint arg0)\n"
+   "       (declare (in) uint arg1))\n"
+   "     ((return (expression uint min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec2\n"
+   "     (parameters\n"
+   "       (declare (in) uvec2 arg0)\n"
+   "       (declare (in) uvec2 arg1))\n"
+   "     ((return (expression uvec2 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec3\n"
+   "     (parameters\n"
+   "       (declare (in) uvec3 arg0)\n"
+   "       (declare (in) uvec3 arg1))\n"
+   "     ((return (expression uvec3 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) uvec4 arg0)\n"
+   "       (declare (in) uvec4 arg1))\n"
+   "     ((return (expression uvec4 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec2\n"
+   "     (parameters\n"
+   "       (declare (in) uvec2  arg0)\n"
+   "       (declare (in) uint arg1))\n"
+   "     ((return (expression uvec2 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec3\n"
+   "     (parameters\n"
+   "       (declare (in) uvec3  arg0)\n"
+   "       (declare (in) uint arg1))\n"
+   "     ((return (expression uvec3 min (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) uvec4  arg0)\n"
+   "       (declare (in) uint arg1))\n"
+   "     ((return (expression uvec4 min (var_ref arg0) (var_ref arg1)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_mix =
+   "((function mix\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0)\n"
+   "       (declare (in) float arg1)\n"
+   "       (declare (in) float arg2))\n"
+   "     ((return (expression float + (expression float * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression float * (var_ref arg1) (var_ref arg2))))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0)\n"
+   "       (declare (in) vec2 arg1)\n"
+   "       (declare (in) vec2 arg2))\n"
+   "     ((return (expression vec2 + (expression vec2 * (var_ref arg0) (expression vec2 - (constant float (1.000000)) (var_ref arg2))) (expression vec2 * (var_ref arg1) (var_ref arg2))))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0)\n"
+   "       (declare (in) vec3 arg1)\n"
+   "       (declare (in) vec3 arg2))\n"
+   "     ((return (expression vec3 + (expression vec3 * (var_ref arg0) (expression vec3 - (constant float (1.000000)) (var_ref arg2))) (expression vec3 * (var_ref arg1) (var_ref arg2))))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0)\n"
+   "       (declare (in) vec4 arg1)\n"
+   "       (declare (in) vec4 arg2))\n"
+   "     ((return (expression vec4 + (expression vec4 * (var_ref arg0) (expression vec4 - (constant float (1.000000)) (var_ref arg2))) (expression vec4 * (var_ref arg1) (var_ref arg2))))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0)\n"
+   "       (declare (in) vec2 arg1)\n"
+   "       (declare (in) float arg2))\n"
+   "     ((return (expression vec2 + (expression vec2 * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression vec2 * (var_ref arg1) (var_ref arg2))))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0)\n"
+   "       (declare (in) vec3 arg1)\n"
+   "       (declare (in) float arg2))\n"
+   "     ((return (expression vec3 + (expression vec3 * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression vec3 * (var_ref arg1) (var_ref arg2))))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0)\n"
+   "       (declare (in) vec4 arg1)\n"
+   "       (declare (in) float arg2))\n"
+   "     ((return (expression vec4 + (expression vec4 * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression vec4 * (var_ref arg1) (var_ref arg2))))))\n"
+   "\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float v1)\n"
+   "       (declare (in) float v2)\n"
+   "       (declare (in) bool  a))\n"
+   "     ((assign (var_ref a) (var_ref v1) (var_ref v2))\n"
+   "      (return (var_ref v1))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 v1)\n"
+   "       (declare (in) vec2 v2)\n"
+   "       (declare (in) bvec2 a))\n"
+   "     ((assign (swiz x (var_ref a)) (swiz x (var_ref v1)) (swiz x (var_ref v2)))\n"
+   "      (assign (swiz y (var_ref a)) (swiz y (var_ref v1)) (swiz y (var_ref v2)))\n"
+   "      (return (var_ref v1))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 v1)\n"
+   "       (declare (in) vec3 v2)\n"
+   "       (declare (in) bvec3 a))\n"
+   "     ((assign (swiz x (var_ref a)) (swiz x (var_ref v1)) (swiz x (var_ref v2)))\n"
+   "      (assign (swiz y (var_ref a)) (swiz y (var_ref v1)) (swiz y (var_ref v2)))\n"
+   "      (assign (swiz z (var_ref a)) (swiz z (var_ref v1)) (swiz z (var_ref v2)))\n"
+   "      (return (var_ref v1))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 v1)\n"
+   "       (declare (in) vec4 v2)\n"
+   "       (declare (in) bvec4 a))\n"
+   "     ((assign (swiz x (var_ref a)) (swiz x (var_ref v1)) (swiz x (var_ref v2)))\n"
+   "      (assign (swiz y (var_ref a)) (swiz y (var_ref v1)) (swiz y (var_ref v2)))\n"
+   "      (assign (swiz z (var_ref a)) (swiz z (var_ref v1)) (swiz z (var_ref v2)))\n"
+   "      (assign (swiz w (var_ref a)) (swiz w (var_ref v1)) (swiz w (var_ref v2)))\n"
+   "      (return (var_ref v1))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_mod =
+   "((function mod\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0)\n"
+   "       (declare (in) float arg1))\n"
+   "     ((return (expression float % (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0)\n"
+   "       (declare (in) vec2 arg1))\n"
+   "     ((return (expression vec2 % (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0)\n"
+   "       (declare (in) vec3 arg1))\n"
+   "     ((return (expression vec3 % (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0)\n"
+   "       (declare (in) vec4 arg1))\n"
+   "     ((return (expression vec4 % (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2  arg0)\n"
+   "       (declare (in) float arg1))\n"
+   "     ((return (expression vec2 % (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3  arg0)\n"
+   "       (declare (in) float arg1))\n"
+   "     ((return (expression vec3 % (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4  arg0)\n"
+   "       (declare (in) float arg1))\n"
+   "     ((return (expression vec4 % (var_ref arg0) (var_ref arg1)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_noise1 =
+   "((function noise1\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float x))\n"
+   "     ((return (constant float (0)))))\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((return (constant float (0)))))\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((return (constant float (0)))))\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((return (constant float (0)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_noise2 =
+   "((function noise2\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) float x))\n"
+   "     ((return (constant vec2 (0 0)))))\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((return (constant vec2 (0 0)))))\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((return (constant vec2 (0 0)))))\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((return (constant vec2 (0 0)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_noise3 =
+   "((function noise3\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) float x))\n"
+   "     ((return (constant vec3 (0 0 0)))))\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((return (constant vec3 (0 0 0)))))\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((return (constant vec3 (0 0 0)))))\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((return (constant vec3 (0 0 0)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_noise4 =
+   "((function noise4\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) float x))\n"
+   "     ((return (constant vec4 (0 0 0 0)))))\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((return (constant vec4 (0 0 0 0)))))\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((return (constant vec4 (0 0 0 0)))))\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((return (constant vec4 (0 0 0 0)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_normalize =
+   "((function normalize\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0))\n"
+   "     ((return (expression float * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0))\n"
+   "     ((return (expression vec2 * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0))\n"
+   "     ((return (expression vec3 * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0))\n"
+   "     ((return (expression vec4 * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_not =
+   "((function not\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) bvec2 arg0))\n"
+   "     ((return (expression bvec2 ! (var_ref arg0)))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) bvec3 arg0))\n"
+   "     ((return (expression bvec3 ! (var_ref arg0)))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) bvec4 arg0))\n"
+   "     ((return (expression bvec4 ! (var_ref arg0)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_notEqual =
+   "((function notEqual\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0)\n"
+   "       (declare (in) vec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0)\n"
+   "       (declare (in) vec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))\n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0)\n"
+   "       (declare (in) vec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool != (swiz w (var_ref arg0))(swiz w (var_ref arg1))))\n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) bvec2 arg0)\n"
+   "       (declare (in) bvec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) bvec3 arg0)\n"
+   "       (declare (in) bvec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))\n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) bvec4 arg0)\n"
+   "       (declare (in) bvec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool != (swiz w (var_ref arg0))(swiz w (var_ref arg1))))\n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) ivec2 arg0)\n"
+   "       (declare (in) ivec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) ivec3 arg0)\n"
+   "       (declare (in) ivec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))\n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) ivec4 arg0)\n"
+   "       (declare (in) ivec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))\n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool != (swiz w (var_ref arg0))(swiz w (var_ref arg1))))\n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec2\n"
+   "     (parameters\n"
+   "       (declare (in) uvec2 arg0)\n"
+   "       (declare (in) uvec2 arg1))\n"
+   "     ((declare () bvec2 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec3\n"
+   "     (parameters\n"
+   "       (declare (in) uvec3 arg0)\n"
+   "       (declare (in) uvec3 arg1))\n"
+   "     ((declare () bvec3 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "\n"
+   "   (signature bvec4\n"
+   "     (parameters\n"
+   "       (declare (in) uvec4 arg0)\n"
+   "       (declare (in) uvec4 arg1))\n"
+   "     ((declare () bvec4 temp)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) \n"
+   "      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool != (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) \n"
+   "      (return (var_ref temp))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_outerProduct =
+   "((function outerProduct\n"
+   "   (signature mat2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 u)\n"
+   "       (declare (in) vec2 v))\n"
+   "     ((declare () mat2 m)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref u) (swiz x (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref u) (swiz y (var_ref v))))\n"
+   "      (return (var_ref m))))\n"
+   "\n"
+   "   (signature mat2x3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 u)\n"
+   "       (declare (in) vec2 v))\n"
+   "     ((declare () mat2x3 m)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref u) (swiz x (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref u) (swiz y (var_ref v))))\n"
+   "      (return (var_ref m))))\n"
+   "\n"
+   "   (signature mat2x4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 u)\n"
+   "       (declare (in) vec2 v))\n"
+   "     ((declare () mat2x4 m)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref u) (swiz x (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref u) (swiz y (var_ref v))))\n"
+   "      (return (var_ref m))))\n"
+   "\n"
+   "   (signature mat3x2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 u)\n"
+   "       (declare (in) vec3 v))\n"
+   "     ((declare () mat3x2 m)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref u) (swiz x (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref u) (swiz y (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec2 * (var_ref u) (swiz z (var_ref v))))\n"
+   "      (return (var_ref m))\n"
+   " ))\n"
+   "\n"
+   "   (signature mat3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 u)\n"
+   "       (declare (in) vec3 v))\n"
+   "     ((declare () mat3 m)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref u) (swiz x (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref u) (swiz y (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec3 * (var_ref u) (swiz z (var_ref v))))\n"
+   "      (return (var_ref m))))\n"
+   "\n"
+   "   (signature mat3x4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 u)\n"
+   "       (declare (in) vec3 v))\n"
+   "     ((declare () mat3x4 m)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref u) (swiz x (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref u) (swiz y (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec4 * (var_ref u) (swiz z (var_ref v))))\n"
+   "      (return (var_ref m))))\n"
+   "\n"
+   "   (signature mat4x2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 u)\n"
+   "       (declare (in) vec4 v))\n"
+   "     ((declare () mat4x2 m)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref u) (swiz x (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref u) (swiz y (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec2 * (var_ref u) (swiz z (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec2 * (var_ref u) (swiz w (var_ref v))))\n"
+   "      (return (var_ref m))))\n"
+   "\n"
+   "   (signature mat4x3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 u)\n"
+   "       (declare (in) vec4 v))\n"
+   "     ((declare () mat4x3 m)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref u) (swiz x (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref u) (swiz y (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec3 * (var_ref u) (swiz z (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec3 * (var_ref u) (swiz w (var_ref v))))\n"
+   "      (return (var_ref m))))\n"
+   "\n"
+   "   (signature mat4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 u)\n"
+   "       (declare (in) vec4 v))\n"
+   "     ((declare () mat4 m)\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref u) (swiz x (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref u) (swiz y (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec4 * (var_ref u) (swiz z (var_ref v))))\n"
+   "      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec4 * (var_ref u) (swiz w (var_ref v))))\n"
+   "      (return (var_ref m))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_pow =
+   "((function pow\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0)\n"
+   "       (declare (in) float arg1))\n"
+   "     ((return (expression float pow (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0)\n"
+   "       (declare (in) vec2 arg1))\n"
+   "     ((return (expression vec2 pow (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0)\n"
+   "       (declare (in) vec3 arg1))\n"
+   "     ((return (expression vec3 pow (var_ref arg0) (var_ref arg1)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0)\n"
+   "       (declare (in) vec4 arg1))\n"
+   "     ((return (expression vec4 pow (var_ref arg0) (var_ref arg1)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_radians =
+   "((function radians\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0))\n"
+   "     ((return (expression float * (var_ref arg0) (constant float (0.017453))))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0))\n"
+   "     ((return (expression vec2 * (var_ref arg0) (constant float (0.017453))))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0))\n"
+   "     ((return (expression vec3 * (var_ref arg0) (constant float (0.017453))))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0))\n"
+   "     ((return (expression vec4 * (var_ref arg0) (constant float (0.017453))))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_reflect =
+   "((function reflect\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float i)\n"
+   "       (declare (in) float n))\n"
+   "     ((return (expression float -\n"
+   "          (var_ref i)\n"
+   "          (expression float *\n"
+   "           (constant float (2.0))\n"
+   "           (expression float *\n"
+   "            (expression float dot\n"
+   "             (var_ref n)\n"
+   "             (var_ref i))\n"
+   "            (var_ref n)))))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 i)\n"
+   "       (declare (in) vec2 n))\n"
+   "     ((return (expression vec2 -\n"
+   "          (var_ref i)\n"
+   "          (expression vec2 *\n"
+   "           (constant float (2.0))\n"
+   "           (expression vec2 *\n"
+   "            (expression float dot\n"
+   "             (var_ref n)\n"
+   "             (var_ref i))\n"
+   "            (var_ref n)))))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 i)\n"
+   "       (declare (in) vec3 n))\n"
+   "     ((return (expression vec3 -\n"
+   "          (var_ref i)\n"
+   "          (expression vec3 *\n"
+   "           (constant float (2.0))\n"
+   "           (expression vec3 *\n"
+   "            (expression float dot\n"
+   "             (var_ref n)\n"
+   "             (var_ref i))\n"
+   "            (var_ref n)))))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 i)\n"
+   "       (declare (in) vec4 n))\n"
+   "     ((return (expression vec4 -\n"
+   "          (var_ref i)\n"
+   "          (expression vec4 *\n"
+   "           (constant float (2.0))\n"
+   "           (expression vec4 *\n"
+   "            (expression float dot\n"
+   "             (var_ref n)\n"
+   "             (var_ref i))\n"
+   "            (var_ref n)))))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_refract =
+   "((function refract\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float i)\n"
+   "       (declare (in) float n)\n"
+   "       (declare (in) float eta))\n"
+   "     ((declare () float k)\n"
+   "      (assign (constant bool (1)) (var_ref k)\n"
+   "              (expression float - (constant float (1.0))\n"
+   "           (expression float * (var_ref eta)\n"
+   "             (expression float * (var_ref eta)\n"
+   "               (expression float - (constant float (1.0))\n"
+   "                 (expression float * \n"
+   "                   (expression float dot (var_ref n) (var_ref i))\n"
+   "                   (expression float dot (var_ref n) (var_ref i))))))))\n"
+   "      (if (expression bool < (var_ref k) (constant float (0.0)))\n"
+   "          ((return (constant float (0.0))))\n"
+   "     ((return (expression float -\n"
+   "                (expression float * (var_ref eta) (var_ref i))\n"
+   "                (expression float *\n"
+   "                  (expression float +\n"
+   "                    (expression float * (var_ref eta)\n"
+   "                      (expression float dot (var_ref n) (var_ref i)))\n"
+   "                    (expression float sqrt (var_ref k)))\n"
+   "                  (var_ref n))))))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 i)\n"
+   "       (declare (in) vec2 n)\n"
+   "       (declare (in) float eta))\n"
+   "     ((declare () float k)\n"
+   "      (assign (constant bool (1)) (var_ref k)\n"
+   "              (expression float - (constant float (1.0))\n"
+   "           (expression float * (var_ref eta)\n"
+   "             (expression float * (var_ref eta)\n"
+   "               (expression float - (constant float (1.0))\n"
+   "                 (expression float * \n"
+   "                   (expression float dot (var_ref n) (var_ref i))\n"
+   "                   (expression float dot (var_ref n) (var_ref i))))))))\n"
+   "      (if (expression bool < (var_ref k) (constant float (0.0)))\n"
+   "          ((return (constant vec2 (0.0 0.0))))\n"
+   "     ((return (expression vec2 -\n"
+   "                (expression vec2 * (var_ref eta) (var_ref i))\n"
+   "                (expression vec2 *\n"
+   "                  (expression float +\n"
+   "                    (expression float * (var_ref eta)\n"
+   "                      (expression float dot (var_ref n) (var_ref i)))\n"
+   "                    (expression float sqrt (var_ref k)))\n"
+   "                  (var_ref n))))))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 i)\n"
+   "       (declare (in) vec3 n)\n"
+   "       (declare (in) float eta))\n"
+   "     ((declare () float k)\n"
+   "      (assign (constant bool (1)) (var_ref k)\n"
+   "              (expression float - (constant float (1.0))\n"
+   "           (expression float * (var_ref eta)\n"
+   "             (expression float * (var_ref eta)\n"
+   "               (expression float - (constant float (1.0))\n"
+   "                 (expression float * \n"
+   "                   (expression float dot (var_ref n) (var_ref i))\n"
+   "                   (expression float dot (var_ref n) (var_ref i))))))))\n"
+   "      (if (expression bool < (var_ref k) (constant float (0.0)))\n"
+   "          ((return (constant vec3 (0.0 0.0 0.0))))\n"
+   "     ((return (expression vec3 -\n"
+   "                (expression vec3 * (var_ref eta) (var_ref i))\n"
+   "                (expression vec3 *\n"
+   "                  (expression float +\n"
+   "                    (expression float * (var_ref eta)\n"
+   "                      (expression float dot (var_ref n) (var_ref i)))\n"
+   "                    (expression float sqrt (var_ref k)))\n"
+   "                  (var_ref n))))))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 i)\n"
+   "       (declare (in) vec4 n)\n"
+   "       (declare (in) float eta))\n"
+   "     ((declare () float k)\n"
+   "      (assign (constant bool (1)) (var_ref k)\n"
+   "              (expression float - (constant float (1.0))\n"
+   "           (expression float * (var_ref eta)\n"
+   "             (expression float * (var_ref eta)\n"
+   "               (expression float - (constant float (1.0))\n"
+   "                 (expression float * \n"
+   "                   (expression float dot (var_ref n) (var_ref i))\n"
+   "                   (expression float dot (var_ref n) (var_ref i))))))))\n"
+   "      (if (expression bool < (var_ref k) (constant float (0.0)))\n"
+   "          ((return (constant vec4 (0.0 0.0 0.0 0.0))))\n"
+   "     ((return (expression vec4 -\n"
+   "                (expression vec4 * (var_ref eta) (var_ref i))\n"
+   "                (expression vec4 *\n"
+   "                  (expression float +\n"
+   "                    (expression float * (var_ref eta)\n"
+   "                      (expression float dot (var_ref n) (var_ref i)))\n"
+   "                    (expression float sqrt (var_ref k)))\n"
+   "                  (var_ref n))))))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_shadow1D =
+   "((function shadow1D\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DShadow sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DShadow sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_shadow1DArray =
+   "((function shadow1DArray\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DArrayShadow sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DArrayShadow sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_shadow1DArrayLod =
+   "((function shadow1DArrayLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DArrayShadow sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_shadow1DLod =
+   "((function shadow1DLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DShadow sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_shadow1DProj =
+   "((function shadow1DProj\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DShadow sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DShadow sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_shadow1DProjLod =
+   "((function shadow1DProjLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DShadow sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_shadow2D =
+   "((function shadow2D\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DShadow sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DShadow sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_shadow2DArray =
+   "((function shadow2DArray\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DArrayShadow sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) 1 (swiz w (var_ref P)) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_shadow2DLod =
+   "((function shadow2DLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DShadow sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_shadow2DProj =
+   "((function shadow2DProj\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DShadow sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DShadow sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_shadow2DProjLod =
+   "((function shadow2DProjLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DShadow sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_shadow2DRect =
+   "((function shadow2DRect\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DRectShadow sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) 1 (swiz z (var_ref P)) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_shadow2DRectProj =
+   "((function shadow2DRectProj\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DRectShadow sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) (swiz z (var_ref P)) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_sign =
+   "((function sign\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float x))\n"
+   "     ((return (expression float sign (var_ref x)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((return (expression vec2 sign (var_ref x)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((return (expression vec3 sign (var_ref x)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((return (expression vec4 sign (var_ref x)))))\n"
+   "\n"
+   "   (signature int\n"
+   "     (parameters\n"
+   "       (declare (in) int x))\n"
+   "     ((return (expression int sign (var_ref x)))))\n"
+   "\n"
+   "   (signature ivec2\n"
+   "     (parameters\n"
+   "       (declare (in) ivec2 x))\n"
+   "     ((return (expression ivec2 sign (var_ref x)))))\n"
+   "\n"
+   "   (signature ivec3\n"
+   "     (parameters\n"
+   "       (declare (in) ivec3 x))\n"
+   "     ((return (expression ivec3 sign (var_ref x)))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) ivec4 x))\n"
+   "     ((return (expression ivec4 sign (var_ref x)))))\n"
+   "))\n"
+   "\n"
+   ""
+;
+static const char *builtin_sin =
+   "((function sin\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float angle))\n"
+   "     ((return (expression float sin (var_ref angle)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 angle))\n"
+   "     ((return (expression vec2 sin (var_ref angle)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 angle))\n"
+   "     ((return (expression vec3 sin (var_ref angle)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 angle))\n"
+   "     ((return (expression vec4 sin (var_ref angle)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_sinh =
+   "((function sinh\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float x))\n"
+   "     ((return (expression float * (constant float (0.5))\n"
+   "                (expression float -\n"
+   "             (expression float exp (var_ref x))\n"
+   "             (expression float exp (expression float neg (var_ref x))))))))\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((return (expression vec2 * (constant vec2 (0.5))\n"
+   "                (expression vec2 -\n"
+   "             (expression vec2 exp (var_ref x))\n"
+   "             (expression vec2 exp (expression vec2 neg (var_ref x))))))))\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((return (expression vec3 * (constant vec3 (0.5))\n"
+   "                (expression vec3 -\n"
+   "             (expression vec3 exp (var_ref x))\n"
+   "             (expression vec3 exp (expression vec3 neg (var_ref x))))))))\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((return (expression vec4 * (constant vec4 (0.5))\n"
+   "                (expression vec4 -\n"
+   "             (expression vec4 exp (var_ref x))\n"
+   "             (expression vec4 exp (expression vec4 neg (var_ref x))))))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_smoothstep =
+   "((function smoothstep\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float edge0)\n"
+   "       (declare (in) float edge1)\n"
+   "       (declare (in) float x))\n"
+   "     ((declare () float t)\n"
+   "\n"
+   "      (assign (constant bool (1)) (var_ref t)\n"
+   "              (expression float max\n"
+   "                     (expression float min\n"
+   "                                 (expression float / (expression float - (var_ref x) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+   "                                 (constant float (1.0)))\n"
+   "                     (constant float (0.0))))\n"
+   "      (return (expression float * (var_ref t) (expression float * (var_ref t) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (var_ref t))))))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) float edge0)\n"
+   "       (declare (in) float edge1)\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((declare () vec2 t)\n"
+   "      (declare () vec2 retval)\n"
+   "\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref t))\n"
+   "              (expression float max\n"
+   "                     (expression float min\n"
+   "                                 (expression float / (expression float - (swiz x (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+   "                                 (constant float (1.0)))\n"
+   "                     (constant float (0.0))))\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref retval)) (expression float * (swiz x (var_ref t)) (expression float * (swiz x (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz x (var_ref t)))))))\n"
+   "\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref t))\n"
+   "              (expression float max\n"
+   "                     (expression float min\n"
+   "                                 (expression float / (expression float - (swiz y (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+   "                                 (constant float (1.0)))\n"
+   "                     (constant float (0.0))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref retval)) (expression float * (swiz y (var_ref t)) (expression float * (swiz y (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz y (var_ref t)))))))\n"
+   "      (return (var_ref retval))\n"
+   "      ))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) float edge0)\n"
+   "       (declare (in) float edge1)\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((declare () vec3 t)\n"
+   "      (declare () vec3 retval)\n"
+   "\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref t))\n"
+   "              (expression float max\n"
+   "                     (expression float min\n"
+   "                                 (expression float / (expression float - (swiz x (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+   "                                 (constant float (1.0)))\n"
+   "                     (constant float (0.0))))\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref retval)) (expression float * (swiz x (var_ref t)) (expression float * (swiz x (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz x (var_ref t)))))))\n"
+   "\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref t))\n"
+   "              (expression float max\n"
+   "                     (expression float min\n"
+   "                                 (expression float / (expression float - (swiz y (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+   "                                 (constant float (1.0)))\n"
+   "                     (constant float (0.0))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref retval)) (expression float * (swiz y (var_ref t)) (expression float * (swiz y (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz y (var_ref t)))))))\n"
+   "\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref t))\n"
+   "              (expression float max\n"
+   "                     (expression float min\n"
+   "                                 (expression float / (expression float - (swiz z (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+   "                                 (constant float (1.0)))\n"
+   "                     (constant float (0.0))))\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref retval)) (expression float * (swiz z (var_ref t)) (expression float * (swiz z (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz z (var_ref t)))))))\n"
+   "      (return (var_ref retval))\n"
+   "      ))\n"
+   "\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) float edge0)\n"
+   "       (declare (in) float edge1)\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((declare () vec4 t)\n"
+   "      (declare () vec4 retval)\n"
+   "\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref t))\n"
+   "              (expression float max\n"
+   "                     (expression float min\n"
+   "                                 (expression float / (expression float - (swiz x (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+   "                                 (constant float (1.0)))\n"
+   "                     (constant float (0.0))))\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref retval)) (expression float * (swiz x (var_ref t)) (expression float * (swiz x (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz x (var_ref t)))))))\n"
+   "\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref t))\n"
+   "              (expression float max\n"
+   "                     (expression float min\n"
+   "                                 (expression float / (expression float - (swiz y (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+   "                                 (constant float (1.0)))\n"
+   "                     (constant float (0.0))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref retval)) (expression float * (swiz y (var_ref t)) (expression float * (swiz y (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz y (var_ref t)))))))\n"
+   "\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref t))\n"
+   "              (expression float max\n"
+   "                     (expression float min\n"
+   "                                 (expression float / (expression float - (swiz z (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+   "                                 (constant float (1.0)))\n"
+   "                     (constant float (0.0))))\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref retval)) (expression float * (swiz z (var_ref t)) (expression float * (swiz z (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz z (var_ref t)))))))\n"
+   "\n"
+   "      (assign (constant bool (1)) (swiz w (var_ref t))\n"
+   "              (expression float max\n"
+   "                     (expression float min\n"
+   "                                 (expression float / (expression float - (swiz w (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))\n"
+   "                                 (constant float (1.0)))\n"
+   "                     (constant float (0.0))))\n"
+   "      (assign (constant bool (1)) (swiz w (var_ref retval)) (expression float * (swiz w (var_ref t)) (expression float * (swiz w (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz w (var_ref t)))))))\n"
+   "      (return (var_ref retval))\n"
+   "      ))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 edge0)\n"
+   "       (declare (in) vec2 edge1)\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((return (expression vec2 max\n"
+   "                          (expression vec2 min\n"
+   "                                      (expression vec2 / (expression vec2 - (var_ref x) (var_ref edge0)) (expression vec2 - (var_ref edge1) (var_ref edge0)))\n"
+   "                                      (constant vec2 (1.0 1.0)))\n"
+   "                          (constant vec2 (0.0 0.0))))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 edge0)\n"
+   "       (declare (in) vec3 edge1)\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((return (expression vec3 max\n"
+   "                          (expression vec3 min\n"
+   "                                      (expression vec3 / (expression vec3 - (var_ref x) (var_ref edge0)) (expression vec3 - (var_ref edge1) (var_ref edge0)))\n"
+   "                                      (constant vec3 (1.0 1.0 1.0)))\n"
+   "                          (constant vec3 (0.0 0.0 0.0))))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 edge0)\n"
+   "       (declare (in) vec4 edge1)\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((return (expression vec4 max\n"
+   "                          (expression vec4 min\n"
+   "                                      (expression vec4 / (expression vec4 - (var_ref x) (var_ref edge0)) (expression vec4 - (var_ref edge1) (var_ref edge0)))\n"
+   "                                      (constant vec4 (1.0 1.0 1.0 1.0)))\n"
+   "                          (constant vec4 (0.0 0.0 0.0 0.0))))))\n"
+   "))\n"
+   "\n"
+   ""
+;
+static const char *builtin_sqrt =
+   "((function sqrt\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float arg0))\n"
+   "     ((return (expression float sqrt (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 arg0))\n"
+   "     ((return (expression vec2 sqrt (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 arg0))\n"
+   "     ((return (expression vec3 sqrt (var_ref arg0)))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 arg0))\n"
+   "     ((return (expression vec4 sqrt (var_ref arg0)))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_step =
+   "((function step\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float edge)\n"
+   "       (declare (in) float x))\n"
+   "     ((return (expression float b2f (expression bool >= (var_ref x) (var_ref edge))))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) float edge)\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((declare () vec2 t)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(var_ref edge))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(var_ref edge))))\n"
+   "      (return (var_ref t))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) float edge)\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((declare () vec3 t)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(var_ref edge))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(var_ref edge))))\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz z (var_ref x))(var_ref edge))))\n"
+   "      (return (var_ref t))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) float edge)\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((declare () vec4 t)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(var_ref edge))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(var_ref edge))))\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz z (var_ref x))(var_ref edge))))\n"
+   "      (assign (constant bool (1)) (swiz w (var_ref t)) (expression float b2f (expression bool >= (swiz w (var_ref x))(var_ref edge))))\n"
+   "      (return (var_ref t))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 edge)\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((declare () vec2 t)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(swiz x (var_ref edge)))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz y (var_ref edge)))))\n"
+   "      (return (var_ref t))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 edge)\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((declare () vec3 t)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(swiz x (var_ref edge)))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz y (var_ref edge)))))\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz z (var_ref x))(swiz z (var_ref edge)))))\n"
+   "      (return (var_ref t))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 edge)\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((declare () vec4 t)\n"
+   "      (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(swiz x (var_ref edge)))))\n"
+   "      (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz y (var_ref edge)))))\n"
+   "      (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz z (var_ref edge)))))\n"
+   "      (assign (constant bool (1)) (swiz w (var_ref t)) (expression float b2f (expression bool >= (swiz w (var_ref x))(swiz w (var_ref edge)))))\n"
+   "      (return (var_ref t))))\n"
+   "))\n"
+   "\n"
+   ""
+;
+static const char *builtin_tan =
+   "((function tan\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float angle))\n"
+   "     ((return (expression float / (expression float sin (var_ref angle)) (expression float cos (var_ref angle))))))\n"
+   "\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 angle))\n"
+   "     ((return (expression vec2 / (expression vec2 sin (var_ref angle)) (expression vec2 cos (var_ref angle))))))\n"
+   "\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 angle))\n"
+   "     ((return (expression vec3 / (expression vec3 sin (var_ref angle)) (expression vec3 cos (var_ref angle))))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 angle))\n"
+   "     ((return (expression vec4 / (expression vec4 sin (var_ref angle)) (expression vec4 cos (var_ref angle))))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_tanh =
+   "((function tanh\n"
+   "   (signature float\n"
+   "     (parameters\n"
+   "       (declare (in) float x))\n"
+   "     ((return (expression float /\n"
+   "                (expression float -\n"
+   "             (expression float exp (var_ref x))\n"
+   "             (expression float exp (expression float neg (var_ref x))))\n"
+   "                (expression float +\n"
+   "             (expression float exp (var_ref x))\n"
+   "             (expression float exp (expression float neg (var_ref x))))))))\n"
+   "   (signature vec2\n"
+   "     (parameters\n"
+   "       (declare (in) vec2 x))\n"
+   "     ((return (expression vec2 /\n"
+   "                (expression vec2 -\n"
+   "             (expression vec2 exp (var_ref x))\n"
+   "             (expression vec2 exp (expression vec2 neg (var_ref x))))\n"
+   "                (expression vec2 +\n"
+   "             (expression vec2 exp (var_ref x))\n"
+   "             (expression vec2 exp (expression vec2 neg (var_ref x))))))))\n"
+   "   (signature vec3\n"
+   "     (parameters\n"
+   "       (declare (in) vec3 x))\n"
+   "     ((return (expression vec3 /\n"
+   "                (expression vec3 -\n"
+   "             (expression vec3 exp (var_ref x))\n"
+   "             (expression vec3 exp (expression vec3 neg (var_ref x))))\n"
+   "                (expression vec3 +\n"
+   "             (expression vec3 exp (var_ref x))\n"
+   "             (expression vec3 exp (expression vec3 neg (var_ref x))))))))\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) vec4 x))\n"
+   "     ((return (expression vec4 /\n"
+   "                (expression vec4 -\n"
+   "             (expression vec4 exp (var_ref x))\n"
+   "             (expression vec4 exp (expression vec4 neg (var_ref x))))\n"
+   "                (expression vec4 +\n"
+   "             (expression vec4 exp (var_ref x))\n"
+   "             (expression vec4 exp (expression vec4 neg (var_ref x))))))))\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texelFetch =
+   "((function texelFetch\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) int P) \n"
+   "       (declare (in) int lod) )\n"
+   "     ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1D sampler)\n"
+   "       (declare (in) int P) \n"
+   "       (declare (in) int lod) )\n"
+   "     ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1D sampler)\n"
+   "       (declare (in) int P) \n"
+   "       (declare (in) int lod) )\n"
+   "     ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) ivec2 P) \n"
+   "       (declare (in) int lod) )\n"
+   "     ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2D sampler)\n"
+   "       (declare (in) ivec2 P) \n"
+   "       (declare (in) int lod) )\n"
+   "     ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2D sampler)\n"
+   "       (declare (in) ivec2 P) \n"
+   "       (declare (in) int lod) )\n"
+   "     ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler3D sampler)\n"
+   "       (declare (in) ivec3 P) \n"
+   "       (declare (in) int lod) )\n"
+   "     ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler3D sampler)\n"
+   "       (declare (in) ivec3 P) \n"
+   "       (declare (in) int lod) )\n"
+   "     ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler3D sampler)\n"
+   "       (declare (in) ivec3 P) \n"
+   "       (declare (in) int lod) )\n"
+   "     ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DArray sampler)\n"
+   "       (declare (in) ivec2 P) \n"
+   "       (declare (in) int lod) )\n"
+   "     ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1DArray sampler)\n"
+   "       (declare (in) ivec2 P) \n"
+   "       (declare (in) int lod) )\n"
+   "     ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1DArray sampler)\n"
+   "       (declare (in) ivec2 P) \n"
+   "       (declare (in) int lod) )\n"
+   "     ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DArray sampler)\n"
+   "       (declare (in) ivec3 P) \n"
+   "       (declare (in) int lod) )\n"
+   "     ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2DArray sampler)\n"
+   "       (declare (in) ivec3 P) \n"
+   "       (declare (in) int lod) )\n"
+   "     ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2DArray sampler)\n"
+   "       (declare (in) ivec3 P) \n"
+   "       (declare (in) int lod) )\n"
+   "     ((return (txf (var_ref sampler) (var_ref P) (0 0 0) (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture =
+   "((function texture\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) float P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1D sampler)\n"
+   "       (declare (in) float P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1D sampler)\n"
+   "       (declare (in) float P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec2 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2D sampler)\n"
+   "       (declare (in) vec2 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2D sampler)\n"
+   "       (declare (in) vec2 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler3D sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler3D sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler3D sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) samplerCube sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isamplerCube sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usamplerCube sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DArray sampler)\n"
+   "       (declare (in) vec2 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1DArray sampler)\n"
+   "       (declare (in) vec2 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1DArray sampler)\n"
+   "       (declare (in) vec2 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DArray sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2DArray sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2DArray sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) float P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1D sampler)\n"
+   "       (declare (in) float P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1D sampler)\n"
+   "       (declare (in) float P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler3D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler3D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler3D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) samplerCube sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isamplerCube sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usamplerCube sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DArray sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1DArray sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1DArray sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DArray sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2DArray sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2DArray sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture1D =
+   "((function texture1D\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) float P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) float P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture1DArray =
+   "((function texture1DArray\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DArray sampler)\n"
+   "       (declare (in) vec2 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DArray sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture1DArrayLod =
+   "((function texture1DArrayLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DArray sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture1DLod =
+   "((function texture1DLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) float P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture1DProj =
+   "((function texture1DProj\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) vec2 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture1DProjLod =
+   "((function texture1DProjLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture2D =
+   "((function texture2D\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec2 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture2DArray =
+   "((function texture2DArray\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DArray sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DArray sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture2DArrayLod =
+   "((function texture2DArrayLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DArray sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture2DLod =
+   "((function texture2DLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture2DProj =
+   "((function texture2DProj\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture2DProjLod =
+   "((function texture2DProjLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture2DRect =
+   "((function texture2DRect\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DRect sampler)\n"
+   "       (declare (in) vec2 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture2DRectProj =
+   "((function texture2DRectProj\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DRect sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DRect sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture3D =
+   "((function texture3D\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler3D sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler3D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture3DLod =
+   "((function texture3DLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler3D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture3DProj =
+   "((function texture3DProj\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler3D sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler3D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_texture3DProjLod =
+   "((function texture3DProjLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler3D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_textureCube =
+   "((function textureCube\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) samplerCube sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (var_ref P) (0 0 0) 1 () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) samplerCube sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_textureCubeLod =
+   "((function textureCubeLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) samplerCube sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_textureGrad =
+   "((function textureGrad\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) float P) \n"
+   "       (declare (in) float dPdx) \n"
+   "       (declare (in) float dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1D sampler)\n"
+   "       (declare (in) float P) \n"
+   "       (declare (in) float dPdx) \n"
+   "       (declare (in) float dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1D sampler)\n"
+   "       (declare (in) float P) \n"
+   "       (declare (in) float dPdx) \n"
+   "       (declare (in) float dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) vec2 dPdx) \n"
+   "       (declare (in) vec2 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) vec2 dPdx) \n"
+   "       (declare (in) vec2 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) vec2 dPdx) \n"
+   "       (declare (in) vec2 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler3D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) vec3 dPdx) \n"
+   "       (declare (in) vec3 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler3D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) vec3 dPdx) \n"
+   "       (declare (in) vec3 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler3D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) vec3 dPdx) \n"
+   "       (declare (in) vec3 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) samplerCube sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) vec3 dPdx) \n"
+   "       (declare (in) vec3 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isamplerCube sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) vec3 dPdx) \n"
+   "       (declare (in) vec3 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usamplerCube sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) vec3 dPdx) \n"
+   "       (declare (in) vec3 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DArray sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) vec2 dPdx) \n"
+   "       (declare (in) vec2 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1DArray sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) vec2 dPdx) \n"
+   "       (declare (in) vec2 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1DArray sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) vec2 dPdx) \n"
+   "       (declare (in) vec2 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DArray sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) vec3 dPdx) \n"
+   "       (declare (in) vec3 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2DArray sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) vec3 dPdx) \n"
+   "       (declare (in) vec3 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2DArray sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) vec3 dPdx) \n"
+   "       (declare (in) vec3 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (var_ref P) (0 0 0) 1 () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_textureLod =
+   "((function textureLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) float P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1D sampler)\n"
+   "       (declare (in) float P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1D sampler)\n"
+   "       (declare (in) float P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler3D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler3D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler3D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) samplerCube sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isamplerCube sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usamplerCube sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1DArray sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1DArray sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1DArray sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2DArray sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2DArray sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2DArray sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (var_ref P) (0 0 0) 1 () (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_textureProj =
+   "((function textureProj\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) vec2 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1D sampler)\n"
+   "       (declare (in) vec2 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1D sampler)\n"
+   "       (declare (in) vec2 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1D sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1D sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2D sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2D sampler)\n"
+   "       (declare (in) vec3 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2D sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2D sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler3D sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler3D sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler3D sampler)\n"
+   "       (declare (in) vec4 P) )\n"
+   "     ((return (tex (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler3D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler3D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler3D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float bias) )\n"
+   "     ((return (txb (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref bias) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_textureProjGrad =
+   "((function textureProjGrad\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float dPdx) \n"
+   "       (declare (in) float dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float dPdx) \n"
+   "       (declare (in) float dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float dPdx) \n"
+   "       (declare (in) float dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float dPdx) \n"
+   "       (declare (in) float dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float dPdx) \n"
+   "       (declare (in) float dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float dPdx) \n"
+   "       (declare (in) float dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) vec2 dPdx) \n"
+   "       (declare (in) vec2 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) vec2 dPdx) \n"
+   "       (declare (in) vec2 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) vec2 dPdx) \n"
+   "       (declare (in) vec2 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) vec2 dPdx) \n"
+   "       (declare (in) vec2 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) vec2 dPdx) \n"
+   "       (declare (in) vec2 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) vec2 dPdx) \n"
+   "       (declare (in) vec2 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler3D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) vec3 dPdx) \n"
+   "       (declare (in) vec3 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler3D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) vec3 dPdx) \n"
+   "       (declare (in) vec3 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler3D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) vec3 dPdx) \n"
+   "       (declare (in) vec3 dPdy) )\n"
+   "     ((return (txd (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () ((var_ref dPdx) (var_ref dPdy)) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_textureProjLod =
+   "((function textureProjLod\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1D sampler)\n"
+   "       (declare (in) vec2 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz y (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler1D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler1D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler1D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz x (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2D sampler)\n"
+   "       (declare (in) vec3 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz z (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler2D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler2D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler2D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz xy (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature vec4\n"
+   "     (parameters\n"
+   "       (declare (in) sampler3D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature ivec4\n"
+   "     (parameters\n"
+   "       (declare (in) isampler3D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "   (signature uvec4\n"
+   "     (parameters\n"
+   "       (declare (in) usampler3D sampler)\n"
+   "       (declare (in) vec4 P) \n"
+   "       (declare (in) float lod) )\n"
+   "     ((return (txl (var_ref sampler) (swiz xyz (var_ref P)) (0 0 0) (swiz w (var_ref P)) () (var_ref lod) ))))\n"
+   "\n"
+   "))\n"
+   ""
+;
+static const char *builtin_transpose =
+   "((function transpose\n"
+   "   (signature mat2\n"
+   "     (parameters\n"
+   "       (declare (in) mat2 m))\n"
+   "     ((declare () mat2 t)\n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+   "(return (var_ref t))))\n"
+   "\n"
+   "   (signature mat3x2\n"
+   "     (parameters\n"
+   "       (declare (in) mat2x3 m))\n"
+   "     ((declare () mat3x2 t)\n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) \n"
+   "(return (var_ref t))))\n"
+   "\n"
+   "   (signature mat4x2\n"
+   "     (parameters\n"
+   "       (declare (in) mat2x4 m))\n"
+   "     ((declare () mat4x2 t)\n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (1))))) \n"
+   "(return (var_ref t))))\n"
+   "\n"
+   "   (signature mat2x3\n"
+   "     (parameters\n"
+   "       (declare (in) mat3x2 m))\n"
+   "     ((declare () mat2x3 t)\n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) \n"
+   "(return (var_ref t))))\n"
+   "\n"
+   "   (signature mat3\n"
+   "     (parameters\n"
+   "       (declare (in) mat3 m))\n"
+   "     ((declare () mat3 t)\n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2))))) \n"
+   "(return (var_ref t))))\n"
+   "\n"
+   "   (signature mat4x3\n"
+   "     (parameters\n"
+   "       (declare (in) mat3x4 m))\n"
+   "     ((declare () mat4x3 t)\n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (2))))) \n"
+   "(return (var_ref t))))\n"
+   "\n"
+   "   (signature mat2x4\n"
+   "     (parameters\n"
+   "       (declare (in) mat4x2 m))\n"
+   "     ((declare () mat2x4 t)\n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (3))))) \n"
+   "      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (3))))) \n"
+   "(return (var_ref t))))\n"
+   "\n"
+   "   (signature mat3x4\n"
+   "     (parameters\n"
+   "       (declare (in) mat4x3 m))\n"
+   "     ((declare () mat3x4 t)\n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (3))))) \n"
+   "      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (3))))) \n"
+   "      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (3))))) \n"
+   "(return (var_ref t))))\n"
+   "\n"
+   "   (signature mat4\n"
+   "     (parameters\n"
+   "       (declare (in) mat4 m))\n"
+   "     ((declare () mat4 t)\n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (0))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (1))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (2))))) \n"
+   "      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (3))))) \n"
+   "      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (3))))) \n"
+   "      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (3))))) \n"
+   "      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (3))))) \n"
+   "(return (var_ref t))))\n"
+   ")\n"
+   "\n"
+   ")\n"
+   "\n"
+   ""
+;
+static const char *prototypes_for_110_frag =
+   "(\n"
+   "(function radians\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float degrees))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 degrees))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 degrees))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 degrees))\n"
+   "    ()))\n"
+   "(function degrees\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float radians))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 radians))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 radians))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 radians))\n"
+   "    ()))\n"
+   "(function sin\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function cos\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function tan\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function asin\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function acos\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function atan\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float y)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float y_over_x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 y_over_x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 y_over_x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 y_over_x))\n"
+   "    ()))\n"
+   "(function pow\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function exp\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function log\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function exp2\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function log2\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function sqrt\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function inversesqrt\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function abs\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function sign\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function floor\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function ceil\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function fract\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function mod\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function min\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ()))\n"
+   "(function max\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ()))\n"
+   "(function clamp\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 minVal)\n"
+   "      (declare (in) vec2 maxVal))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 minVal)\n"
+   "      (declare (in) vec3 maxVal))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 minVal)\n"
+   "      (declare (in) vec4 maxVal))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ()))\n"
+   "(function mix\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) vec2 a))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) vec3 a))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) vec4 a))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) float a))\n"
+   "    ()))\n"
+   "(function step\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 edge)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 edge)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 edge)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function smoothstep\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 edge0)\n"
+   "      (declare (in) vec2 edge1)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 edge0)\n"
+   "      (declare (in) vec3 edge1)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 edge0)\n"
+   "      (declare (in) vec4 edge1)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function length\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function distance\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float p0)\n"
+   "      (declare (in) float p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 p0)\n"
+   "      (declare (in) vec2 p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 p0)\n"
+   "      (declare (in) vec3 p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 p0)\n"
+   "      (declare (in) vec4 p1))\n"
+   "    ()))\n"
+   "(function dot\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function cross\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ()))\n"
+   "(function normalize\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function faceforward\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float N)\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float Nref))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 N)\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 Nref))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 N)\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 Nref))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 N)\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 Nref))\n"
+   "    ()))\n"
+   "(function reflect\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float N))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 N))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 N))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 N))\n"
+   "    ()))\n"
+   "(function refract\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ()))\n"
+   "(function matrixCompMult\n"
+   "  (signature mat2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2 x)\n"
+   "      (declare (in) mat2 y))\n"
+   "    ())\n"
+   "  (signature mat3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3 x)\n"
+   "      (declare (in) mat3 y))\n"
+   "    ())\n"
+   "  (signature mat4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4 x)\n"
+   "      (declare (in) mat4 y))\n"
+   "    ()))\n"
+   "(function lessThan\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function lessThanEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function greaterThan\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function greaterThanEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function equal\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x)\n"
+   "      (declare (in) bvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x)\n"
+   "      (declare (in) bvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x)\n"
+   "      (declare (in) bvec4 y))\n"
+   "    ()))\n"
+   "(function notEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x)\n"
+   "      (declare (in) bvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x)\n"
+   "      (declare (in) bvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x)\n"
+   "      (declare (in) bvec4 y))\n"
+   "    ()))\n"
+   "(function any\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function all\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function not\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function texture1D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture1DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture2D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture2DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture3D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture3DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function textureCube\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow1D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow2D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow1DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow2DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function dFdx\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float p))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 p))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 p))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 p))\n"
+   "    ()))\n"
+   "(function dFdy\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float p))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 p))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 p))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 p))\n"
+   "    ()))\n"
+   "(function fwidth\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float p))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 p))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 p))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 p))\n"
+   "    ()))\n"
+   "(function noise1\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise2\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise3\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise4\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())))"
+;
+static const char *functions_for_110_frag [] = {
+   builtin_abs,
+   builtin_acos,
+   builtin_all,
+   builtin_any,
+   builtin_asin,
+   builtin_atan,
+   builtin_ceil,
+   builtin_clamp,
+   builtin_cos,
+   builtin_cross,
+   builtin_dFdx,
+   builtin_dFdy,
+   builtin_degrees,
+   builtin_distance,
+   builtin_dot,
+   builtin_equal,
+   builtin_exp,
+   builtin_exp2,
+   builtin_faceforward,
+   builtin_floor,
+   builtin_fract,
+   builtin_fwidth,
+   builtin_greaterThan,
+   builtin_greaterThanEqual,
+   builtin_inversesqrt,
+   builtin_length,
+   builtin_lessThan,
+   builtin_lessThanEqual,
+   builtin_log,
+   builtin_log2,
+   builtin_matrixCompMult,
+   builtin_max,
+   builtin_min,
+   builtin_mix,
+   builtin_mod,
+   builtin_noise1,
+   builtin_noise2,
+   builtin_noise3,
+   builtin_noise4,
+   builtin_normalize,
+   builtin_not,
+   builtin_notEqual,
+   builtin_pow,
+   builtin_radians,
+   builtin_reflect,
+   builtin_refract,
+   builtin_shadow1D,
+   builtin_shadow1DProj,
+   builtin_shadow2D,
+   builtin_shadow2DProj,
+   builtin_sign,
+   builtin_sin,
+   builtin_smoothstep,
+   builtin_sqrt,
+   builtin_step,
+   builtin_tan,
+   builtin_texture1D,
+   builtin_texture1DProj,
+   builtin_texture2D,
+   builtin_texture2DProj,
+   builtin_texture3D,
+   builtin_texture3DProj,
+   builtin_textureCube,
+};
+static const char *prototypes_for_110_vert =
+   "(\n"
+   "(function radians\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float degrees))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 degrees))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 degrees))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 degrees))\n"
+   "    ()))\n"
+   "(function degrees\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float radians))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 radians))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 radians))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 radians))\n"
+   "    ()))\n"
+   "(function sin\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function cos\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function tan\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function asin\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function acos\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function atan\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float y)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float y_over_x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 y_over_x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 y_over_x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 y_over_x))\n"
+   "    ()))\n"
+   "(function pow\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function exp\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function log\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function exp2\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function log2\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function sqrt\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function inversesqrt\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function abs\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function sign\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function floor\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function ceil\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function fract\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function mod\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function min\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ()))\n"
+   "(function max\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ()))\n"
+   "(function clamp\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 minVal)\n"
+   "      (declare (in) vec2 maxVal))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 minVal)\n"
+   "      (declare (in) vec3 maxVal))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 minVal)\n"
+   "      (declare (in) vec4 maxVal))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ()))\n"
+   "(function mix\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) vec2 a))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) vec3 a))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) vec4 a))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) float a))\n"
+   "    ()))\n"
+   "(function step\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 edge)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 edge)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 edge)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function smoothstep\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 edge0)\n"
+   "      (declare (in) vec2 edge1)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 edge0)\n"
+   "      (declare (in) vec3 edge1)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 edge0)\n"
+   "      (declare (in) vec4 edge1)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function length\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function distance\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float p0)\n"
+   "      (declare (in) float p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 p0)\n"
+   "      (declare (in) vec2 p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 p0)\n"
+   "      (declare (in) vec3 p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 p0)\n"
+   "      (declare (in) vec4 p1))\n"
+   "    ()))\n"
+   "(function dot\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function cross\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ()))\n"
+   "(function normalize\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function ftransform\n"
+   "  (signature vec4\n"
+   "    (parameters)\n"
+   "    ()))\n"
+   "(function faceforward\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float N)\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float Nref))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 N)\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 Nref))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 N)\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 Nref))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 N)\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 Nref))\n"
+   "    ()))\n"
+   "(function reflect\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float N))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 N))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 N))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 N))\n"
+   "    ()))\n"
+   "(function refract\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ()))\n"
+   "(function matrixCompMult\n"
+   "  (signature mat2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2 x)\n"
+   "      (declare (in) mat2 y))\n"
+   "    ())\n"
+   "  (signature mat3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3 x)\n"
+   "      (declare (in) mat3 y))\n"
+   "    ())\n"
+   "  (signature mat4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4 x)\n"
+   "      (declare (in) mat4 y))\n"
+   "    ()))\n"
+   "(function lessThan\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function lessThanEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function greaterThan\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function greaterThanEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function equal\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x)\n"
+   "      (declare (in) bvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x)\n"
+   "      (declare (in) bvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x)\n"
+   "      (declare (in) bvec4 y))\n"
+   "    ()))\n"
+   "(function notEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x)\n"
+   "      (declare (in) bvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x)\n"
+   "      (declare (in) bvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x)\n"
+   "      (declare (in) bvec4 y))\n"
+   "    ()))\n"
+   "(function any\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function all\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function not\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function texture1D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float coord))\n"
+   "    ()))\n"
+   "(function texture1DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ()))\n"
+   "(function texture1DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture1DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture2D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ()))\n"
+   "(function texture2DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ()))\n"
+   "(function texture2DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture2DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture3D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ()))\n"
+   "(function texture3DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ()))\n"
+   "(function texture3DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture3DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function textureCube\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ()))\n"
+   "(function textureCubeLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow1D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ()))\n"
+   "(function shadow2D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ()))\n"
+   "(function shadow1DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ()))\n"
+   "(function shadow2DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ()))\n"
+   "(function shadow1DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow2DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow1DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow2DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function noise1\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise2\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise3\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise4\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())))"
+;
+static const char *functions_for_110_vert [] = {
+   builtin_abs,
+   builtin_acos,
+   builtin_all,
+   builtin_any,
+   builtin_asin,
+   builtin_atan,
+   builtin_ceil,
+   builtin_clamp,
+   builtin_cos,
+   builtin_cross,
+   builtin_degrees,
+   builtin_distance,
+   builtin_dot,
+   builtin_equal,
+   builtin_exp,
+   builtin_exp2,
+   builtin_faceforward,
+   builtin_floor,
+   builtin_fract,
+   builtin_ftransform,
+   builtin_greaterThan,
+   builtin_greaterThanEqual,
+   builtin_inversesqrt,
+   builtin_length,
+   builtin_lessThan,
+   builtin_lessThanEqual,
+   builtin_log,
+   builtin_log2,
+   builtin_matrixCompMult,
+   builtin_max,
+   builtin_min,
+   builtin_mix,
+   builtin_mod,
+   builtin_noise1,
+   builtin_noise2,
+   builtin_noise3,
+   builtin_noise4,
+   builtin_normalize,
+   builtin_not,
+   builtin_notEqual,
+   builtin_pow,
+   builtin_radians,
+   builtin_reflect,
+   builtin_refract,
+   builtin_shadow1D,
+   builtin_shadow1DLod,
+   builtin_shadow1DProj,
+   builtin_shadow1DProjLod,
+   builtin_shadow2D,
+   builtin_shadow2DLod,
+   builtin_shadow2DProj,
+   builtin_shadow2DProjLod,
+   builtin_sign,
+   builtin_sin,
+   builtin_smoothstep,
+   builtin_sqrt,
+   builtin_step,
+   builtin_tan,
+   builtin_texture1D,
+   builtin_texture1DLod,
+   builtin_texture1DProj,
+   builtin_texture1DProjLod,
+   builtin_texture2D,
+   builtin_texture2DLod,
+   builtin_texture2DProj,
+   builtin_texture2DProjLod,
+   builtin_texture3D,
+   builtin_texture3DLod,
+   builtin_texture3DProj,
+   builtin_texture3DProjLod,
+   builtin_textureCube,
+   builtin_textureCubeLod,
+};
+static const char *prototypes_for_120_frag =
+   "(\n"
+   "(function radians\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float degrees))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 degrees))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 degrees))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 degrees))\n"
+   "    ()))\n"
+   "(function degrees\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float radians))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 radians))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 radians))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 radians))\n"
+   "    ()))\n"
+   "(function sin\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function cos\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function tan\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function asin\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function acos\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function atan\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float y)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float y_over_x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 y_over_x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 y_over_x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 y_over_x))\n"
+   "    ()))\n"
+   "(function pow\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function exp\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function log\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function exp2\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function log2\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function sqrt\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function inversesqrt\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function abs\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function sign\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function floor\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function ceil\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function fract\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function mod\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function min\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ()))\n"
+   "(function max\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ()))\n"
+   "(function clamp\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 minVal)\n"
+   "      (declare (in) vec2 maxVal))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 minVal)\n"
+   "      (declare (in) vec3 maxVal))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 minVal)\n"
+   "      (declare (in) vec4 maxVal))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ()))\n"
+   "(function mix\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) vec2 a))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) vec3 a))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) vec4 a))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) float a))\n"
+   "    ()))\n"
+   "(function step\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 edge)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 edge)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 edge)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function smoothstep\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 edge0)\n"
+   "      (declare (in) vec2 edge1)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 edge0)\n"
+   "      (declare (in) vec3 edge1)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 edge0)\n"
+   "      (declare (in) vec4 edge1)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function length\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function distance\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float p0)\n"
+   "      (declare (in) float p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 p0)\n"
+   "      (declare (in) vec2 p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 p0)\n"
+   "      (declare (in) vec3 p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 p0)\n"
+   "      (declare (in) vec4 p1))\n"
+   "    ()))\n"
+   "(function dot\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function cross\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ()))\n"
+   "(function normalize\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function faceforward\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float N)\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float Nref))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 N)\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 Nref))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 N)\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 Nref))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 N)\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 Nref))\n"
+   "    ()))\n"
+   "(function reflect\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float N))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 N))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 N))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 N))\n"
+   "    ()))\n"
+   "(function refract\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ()))\n"
+   "(function matrixCompMult\n"
+   "  (signature mat2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2 x)\n"
+   "      (declare (in) mat2 y))\n"
+   "    ())\n"
+   "  (signature mat3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3 x)\n"
+   "      (declare (in) mat3 y))\n"
+   "    ())\n"
+   "  (signature mat4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4 x)\n"
+   "      (declare (in) mat4 y))\n"
+   "    ())\n"
+   "  (signature mat2x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x3 x)\n"
+   "      (declare (in) mat2x3 y))\n"
+   "    ())\n"
+   "  (signature mat2x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x4 x)\n"
+   "      (declare (in) mat2x4 y))\n"
+   "    ())\n"
+   "  (signature mat3x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x2 x)\n"
+   "      (declare (in) mat3x2 y))\n"
+   "    ())\n"
+   "  (signature mat3x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x4 x)\n"
+   "      (declare (in) mat3x4 y))\n"
+   "    ())\n"
+   "  (signature mat4x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x2 x)\n"
+   "      (declare (in) mat4x2 y))\n"
+   "    ())\n"
+   "  (signature mat4x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x3 x)\n"
+   "      (declare (in) mat4x3 y))\n"
+   "    ()))\n"
+   "(function outerProduct\n"
+   "  (signature mat2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 c)\n"
+   "      (declare (in) vec2 r))\n"
+   "    ())\n"
+   "  (signature mat3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 c)\n"
+   "      (declare (in) vec3 r))\n"
+   "    ())\n"
+   "  (signature mat4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 c)\n"
+   "      (declare (in) vec4 r))\n"
+   "    ())\n"
+   "  (signature mat2x3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 c)\n"
+   "      (declare (in) vec2 r))\n"
+   "    ())\n"
+   "  (signature mat3x2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 c)\n"
+   "      (declare (in) vec3 r))\n"
+   "    ())\n"
+   "  (signature mat2x4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 c)\n"
+   "      (declare (in) vec2 r))\n"
+   "    ())\n"
+   "  (signature mat4x2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 c)\n"
+   "      (declare (in) vec4 r))\n"
+   "    ())\n"
+   "  (signature mat3x4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 c)\n"
+   "      (declare (in) vec3 r))\n"
+   "    ())\n"
+   "  (signature mat4x3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 c)\n"
+   "      (declare (in) vec4 r))\n"
+   "    ()))\n"
+   "(function transpose\n"
+   "  (signature mat2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2 m))\n"
+   "    ())\n"
+   "  (signature mat3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3 m))\n"
+   "    ())\n"
+   "  (signature mat4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4 m))\n"
+   "    ())\n"
+   "  (signature mat2x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x2 m))\n"
+   "    ())\n"
+   "  (signature mat3x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x3 m))\n"
+   "    ())\n"
+   "  (signature mat2x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x2 m))\n"
+   "    ())\n"
+   "  (signature mat4x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x4 m))\n"
+   "    ())\n"
+   "  (signature mat3x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x3 m))\n"
+   "    ())\n"
+   "  (signature mat4x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x4 m))\n"
+   "    ()))\n"
+   "(function lessThan\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function lessThanEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function greaterThan\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function greaterThanEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function equal\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x)\n"
+   "      (declare (in) bvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x)\n"
+   "      (declare (in) bvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x)\n"
+   "      (declare (in) bvec4 y))\n"
+   "    ()))\n"
+   "(function notEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x)\n"
+   "      (declare (in) bvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x)\n"
+   "      (declare (in) bvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x)\n"
+   "      (declare (in) bvec4 y))\n"
+   "    ()))\n"
+   "(function any\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function all\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function not\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function texture1D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture1DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture2D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture2DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture3D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture3DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function textureCube\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow1D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow2D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow1DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow2DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function dFdx\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float p))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 p))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 p))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 p))\n"
+   "    ()))\n"
+   "(function dFdy\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float p))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 p))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 p))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 p))\n"
+   "    ()))\n"
+   "(function fwidth\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float p))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 p))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 p))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 p))\n"
+   "    ()))\n"
+   "(function noise1\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise2\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise3\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise4\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())))"
+;
+static const char *functions_for_120_frag [] = {
+   builtin_abs,
+   builtin_acos,
+   builtin_all,
+   builtin_any,
+   builtin_asin,
+   builtin_atan,
+   builtin_ceil,
+   builtin_clamp,
+   builtin_cos,
+   builtin_cross,
+   builtin_dFdx,
+   builtin_dFdy,
+   builtin_degrees,
+   builtin_distance,
+   builtin_dot,
+   builtin_equal,
+   builtin_exp,
+   builtin_exp2,
+   builtin_faceforward,
+   builtin_floor,
+   builtin_fract,
+   builtin_fwidth,
+   builtin_greaterThan,
+   builtin_greaterThanEqual,
+   builtin_inversesqrt,
+   builtin_length,
+   builtin_lessThan,
+   builtin_lessThanEqual,
+   builtin_log,
+   builtin_log2,
+   builtin_matrixCompMult,
+   builtin_max,
+   builtin_min,
+   builtin_mix,
+   builtin_mod,
+   builtin_noise1,
+   builtin_noise2,
+   builtin_noise3,
+   builtin_noise4,
+   builtin_normalize,
+   builtin_not,
+   builtin_notEqual,
+   builtin_outerProduct,
+   builtin_pow,
+   builtin_radians,
+   builtin_reflect,
+   builtin_refract,
+   builtin_shadow1D,
+   builtin_shadow1DProj,
+   builtin_shadow2D,
+   builtin_shadow2DProj,
+   builtin_sign,
+   builtin_sin,
+   builtin_smoothstep,
+   builtin_sqrt,
+   builtin_step,
+   builtin_tan,
+   builtin_texture1D,
+   builtin_texture1DProj,
+   builtin_texture2D,
+   builtin_texture2DProj,
+   builtin_texture3D,
+   builtin_texture3DProj,
+   builtin_textureCube,
+   builtin_transpose,
+};
+static const char *prototypes_for_120_vert =
+   "(\n"
+   "(function radians\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float degrees))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 degrees))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 degrees))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 degrees))\n"
+   "    ()))\n"
+   "(function degrees\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float radians))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 radians))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 radians))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 radians))\n"
+   "    ()))\n"
+   "(function sin\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function cos\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function tan\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function asin\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function acos\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function atan\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float y)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float y_over_x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 y_over_x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 y_over_x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 y_over_x))\n"
+   "    ()))\n"
+   "(function pow\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function exp\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function log\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function exp2\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function log2\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function sqrt\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function inversesqrt\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function abs\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function sign\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function floor\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function ceil\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function fract\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function mod\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function min\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ()))\n"
+   "(function max\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ()))\n"
+   "(function clamp\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 minVal)\n"
+   "      (declare (in) vec2 maxVal))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 minVal)\n"
+   "      (declare (in) vec3 maxVal))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 minVal)\n"
+   "      (declare (in) vec4 maxVal))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ()))\n"
+   "(function mix\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) vec2 a))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) vec3 a))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) vec4 a))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) float a))\n"
+   "    ()))\n"
+   "(function step\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 edge)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 edge)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 edge)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function smoothstep\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 edge0)\n"
+   "      (declare (in) vec2 edge1)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 edge0)\n"
+   "      (declare (in) vec3 edge1)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 edge0)\n"
+   "      (declare (in) vec4 edge1)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function length\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function distance\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float p0)\n"
+   "      (declare (in) float p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 p0)\n"
+   "      (declare (in) vec2 p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 p0)\n"
+   "      (declare (in) vec3 p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 p0)\n"
+   "      (declare (in) vec4 p1))\n"
+   "    ()))\n"
+   "(function dot\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function cross\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ()))\n"
+   "(function normalize\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function ftransform\n"
+   "  (signature vec4\n"
+   "    (parameters)\n"
+   "    ()))\n"
+   "(function faceforward\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float N)\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float Nref))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 N)\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 Nref))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 N)\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 Nref))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 N)\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 Nref))\n"
+   "    ()))\n"
+   "(function reflect\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float N))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 N))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 N))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 N))\n"
+   "    ()))\n"
+   "(function refract\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ()))\n"
+   "(function matrixCompMult\n"
+   "  (signature mat2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2 x)\n"
+   "      (declare (in) mat2 y))\n"
+   "    ())\n"
+   "  (signature mat3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3 x)\n"
+   "      (declare (in) mat3 y))\n"
+   "    ())\n"
+   "  (signature mat4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4 x)\n"
+   "      (declare (in) mat4 y))\n"
+   "    ())\n"
+   "  (signature mat2x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x3 x)\n"
+   "      (declare (in) mat2x3 y))\n"
+   "    ())\n"
+   "  (signature mat2x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x4 x)\n"
+   "      (declare (in) mat2x4 y))\n"
+   "    ())\n"
+   "  (signature mat3x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x2 x)\n"
+   "      (declare (in) mat3x2 y))\n"
+   "    ())\n"
+   "  (signature mat3x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x4 x)\n"
+   "      (declare (in) mat3x4 y))\n"
+   "    ())\n"
+   "  (signature mat4x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x2 x)\n"
+   "      (declare (in) mat4x2 y))\n"
+   "    ())\n"
+   "  (signature mat4x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x3 x)\n"
+   "      (declare (in) mat4x3 y))\n"
+   "    ()))\n"
+   "(function outerProduct\n"
+   "  (signature mat2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 c)\n"
+   "      (declare (in) vec2 r))\n"
+   "    ())\n"
+   "  (signature mat3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 c)\n"
+   "      (declare (in) vec3 r))\n"
+   "    ())\n"
+   "  (signature mat4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 c)\n"
+   "      (declare (in) vec4 r))\n"
+   "    ())\n"
+   "  (signature mat2x3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 c)\n"
+   "      (declare (in) vec2 r))\n"
+   "    ())\n"
+   "  (signature mat3x2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 c)\n"
+   "      (declare (in) vec3 r))\n"
+   "    ())\n"
+   "  (signature mat2x4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 c)\n"
+   "      (declare (in) vec2 r))\n"
+   "    ())\n"
+   "  (signature mat4x2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 c)\n"
+   "      (declare (in) vec4 r))\n"
+   "    ())\n"
+   "  (signature mat3x4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 c)\n"
+   "      (declare (in) vec3 r))\n"
+   "    ())\n"
+   "  (signature mat4x3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 c)\n"
+   "      (declare (in) vec4 r))\n"
+   "    ()))\n"
+   "(function transpose\n"
+   "  (signature mat2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2 m))\n"
+   "    ())\n"
+   "  (signature mat3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3 m))\n"
+   "    ())\n"
+   "  (signature mat4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4 m))\n"
+   "    ())\n"
+   "  (signature mat2x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x2 m))\n"
+   "    ())\n"
+   "  (signature mat3x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x3 m))\n"
+   "    ())\n"
+   "  (signature mat2x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x2 m))\n"
+   "    ())\n"
+   "  (signature mat4x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x4 m))\n"
+   "    ())\n"
+   "  (signature mat3x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x3 m))\n"
+   "    ())\n"
+   "  (signature mat4x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x4 m))\n"
+   "    ()))\n"
+   "(function lessThan\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function lessThanEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function greaterThan\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function greaterThanEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ()))\n"
+   "(function equal\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x)\n"
+   "      (declare (in) bvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x)\n"
+   "      (declare (in) bvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x)\n"
+   "      (declare (in) bvec4 y))\n"
+   "    ()))\n"
+   "(function notEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x)\n"
+   "      (declare (in) bvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x)\n"
+   "      (declare (in) bvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x)\n"
+   "      (declare (in) bvec4 y))\n"
+   "    ()))\n"
+   "(function any\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function all\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function not\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function texture1D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float coord))\n"
+   "    ()))\n"
+   "(function texture1DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ()))\n"
+   "(function texture1DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture1DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture2D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ()))\n"
+   "(function texture2DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ()))\n"
+   "(function texture2DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture2DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture3D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ()))\n"
+   "(function texture3DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ()))\n"
+   "(function texture3DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture3DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function textureCube\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ()))\n"
+   "(function textureCubeLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow1D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ()))\n"
+   "(function shadow2D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ()))\n"
+   "(function shadow1DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ()))\n"
+   "(function shadow2DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ()))\n"
+   "(function shadow1DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow2DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow1DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow2DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function noise1\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise2\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise3\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise4\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())))"
+;
+static const char *functions_for_120_vert [] = {
+   builtin_abs,
+   builtin_acos,
+   builtin_all,
+   builtin_any,
+   builtin_asin,
+   builtin_atan,
+   builtin_ceil,
+   builtin_clamp,
+   builtin_cos,
+   builtin_cross,
+   builtin_degrees,
+   builtin_distance,
+   builtin_dot,
+   builtin_equal,
+   builtin_exp,
+   builtin_exp2,
+   builtin_faceforward,
+   builtin_floor,
+   builtin_fract,
+   builtin_ftransform,
+   builtin_greaterThan,
+   builtin_greaterThanEqual,
+   builtin_inversesqrt,
+   builtin_length,
+   builtin_lessThan,
+   builtin_lessThanEqual,
+   builtin_log,
+   builtin_log2,
+   builtin_matrixCompMult,
+   builtin_max,
+   builtin_min,
+   builtin_mix,
+   builtin_mod,
+   builtin_noise1,
+   builtin_noise2,
+   builtin_noise3,
+   builtin_noise4,
+   builtin_normalize,
+   builtin_not,
+   builtin_notEqual,
+   builtin_outerProduct,
+   builtin_pow,
+   builtin_radians,
+   builtin_reflect,
+   builtin_refract,
+   builtin_shadow1D,
+   builtin_shadow1DLod,
+   builtin_shadow1DProj,
+   builtin_shadow1DProjLod,
+   builtin_shadow2D,
+   builtin_shadow2DLod,
+   builtin_shadow2DProj,
+   builtin_shadow2DProjLod,
+   builtin_sign,
+   builtin_sin,
+   builtin_smoothstep,
+   builtin_sqrt,
+   builtin_step,
+   builtin_tan,
+   builtin_texture1D,
+   builtin_texture1DLod,
+   builtin_texture1DProj,
+   builtin_texture1DProjLod,
+   builtin_texture2D,
+   builtin_texture2DLod,
+   builtin_texture2DProj,
+   builtin_texture2DProjLod,
+   builtin_texture3D,
+   builtin_texture3DLod,
+   builtin_texture3DProj,
+   builtin_texture3DProjLod,
+   builtin_textureCube,
+   builtin_textureCubeLod,
+   builtin_transpose,
+};
+static const char *prototypes_for_130_frag =
+   "(\n"
+   "(function radians\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float degrees))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 degrees))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 degrees))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 degrees))\n"
+   "    ()))\n"
+   "(function degrees\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float radians))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 radians))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 radians))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 radians))\n"
+   "    ()))\n"
+   "(function sin\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function cos\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function tan\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function asin\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function acos\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function atan\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float y)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float y_over_x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 y_over_x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 y_over_x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 y_over_x))\n"
+   "    ()))\n"
+   "(function sinh\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function cosh\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function tanh\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function pow\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function exp\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function log\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function exp2\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function log2\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function sqrt\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function inversesqrt\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function abs\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature int\n"
+   "    (parameters\n"
+   "      (declare (in) int x))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x))\n"
+   "    ()))\n"
+   "(function sign\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature int\n"
+   "    (parameters\n"
+   "      (declare (in) int x))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x))\n"
+   "    ()))\n"
+   "(function floor\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function ceil\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function fract\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function mod\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function min\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature int\n"
+   "    (parameters\n"
+   "      (declare (in) int x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature uint\n"
+   "    (parameters\n"
+   "      (declare (in) uint x)\n"
+   "      (declare (in) uint y))\n"
+   "    ())\n"
+   "  (signature uvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature uvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ())\n"
+   "  (signature uvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uint y))\n"
+   "    ())\n"
+   "  (signature uvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uint y))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uint y))\n"
+   "    ()))\n"
+   "(function max\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature int\n"
+   "    (parameters\n"
+   "      (declare (in) int x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature uint\n"
+   "    (parameters\n"
+   "      (declare (in) uint x)\n"
+   "      (declare (in) uint y))\n"
+   "    ())\n"
+   "  (signature uvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature uvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ())\n"
+   "  (signature uvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uint y))\n"
+   "    ())\n"
+   "  (signature uvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uint y))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uint y))\n"
+   "    ()))\n"
+   "(function clamp\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 minVal)\n"
+   "      (declare (in) vec2 maxVal))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 minVal)\n"
+   "      (declare (in) vec3 maxVal))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 minVal)\n"
+   "      (declare (in) vec4 maxVal))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature int\n"
+   "    (parameters\n"
+   "      (declare (in) int x)\n"
+   "      (declare (in) int minVal)\n"
+   "      (declare (in) int maxVal))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 minVal)\n"
+   "      (declare (in) ivec2 maxVal))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 minVal)\n"
+   "      (declare (in) ivec3 maxVal))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 minVal)\n"
+   "      (declare (in) ivec4 maxVal))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) int minVal)\n"
+   "      (declare (in) int maxVal))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) int minVal)\n"
+   "      (declare (in) int maxVal))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) int minVal)\n"
+   "      (declare (in) int maxVal))\n"
+   "    ())\n"
+   "  (signature uint\n"
+   "    (parameters\n"
+   "      (declare (in) uint x)\n"
+   "      (declare (in) uint minVal)\n"
+   "      (declare (in) uint maxVal))\n"
+   "    ())\n"
+   "  (signature uvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 minVal)\n"
+   "      (declare (in) uvec2 maxVal))\n"
+   "    ())\n"
+   "  (signature uvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 minVal)\n"
+   "      (declare (in) uvec3 maxVal))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 minVal)\n"
+   "      (declare (in) uvec4 maxVal))\n"
+   "    ())\n"
+   "  (signature uvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uint minVal)\n"
+   "      (declare (in) uint maxVal))\n"
+   "    ())\n"
+   "  (signature uvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uint minVal)\n"
+   "      (declare (in) uint maxVal))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uint minVal)\n"
+   "      (declare (in) uint maxVal))\n"
+   "    ()))\n"
+   "(function mix\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) vec2 a))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) vec3 a))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) vec4 a))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) float a))\n"
+   "    ()))\n"
+   "(function step\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 edge)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 edge)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 edge)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function smoothstep\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 edge0)\n"
+   "      (declare (in) vec2 edge1)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 edge0)\n"
+   "      (declare (in) vec3 edge1)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 edge0)\n"
+   "      (declare (in) vec4 edge1)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function length\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function distance\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float p0)\n"
+   "      (declare (in) float p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 p0)\n"
+   "      (declare (in) vec2 p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 p0)\n"
+   "      (declare (in) vec3 p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 p0)\n"
+   "      (declare (in) vec4 p1))\n"
+   "    ()))\n"
+   "(function dot\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function cross\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ()))\n"
+   "(function normalize\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function faceforward\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float N)\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float Nref))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 N)\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 Nref))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 N)\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 Nref))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 N)\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 Nref))\n"
+   "    ()))\n"
+   "(function reflect\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float N))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 N))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 N))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 N))\n"
+   "    ()))\n"
+   "(function refract\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ()))\n"
+   "(function matrixCompMult\n"
+   "  (signature mat2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2 x)\n"
+   "      (declare (in) mat2 y))\n"
+   "    ())\n"
+   "  (signature mat3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3 x)\n"
+   "      (declare (in) mat3 y))\n"
+   "    ())\n"
+   "  (signature mat4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4 x)\n"
+   "      (declare (in) mat4 y))\n"
+   "    ())\n"
+   "  (signature mat2x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x3 x)\n"
+   "      (declare (in) mat2x3 y))\n"
+   "    ())\n"
+   "  (signature mat2x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x4 x)\n"
+   "      (declare (in) mat2x4 y))\n"
+   "    ())\n"
+   "  (signature mat3x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x2 x)\n"
+   "      (declare (in) mat3x2 y))\n"
+   "    ())\n"
+   "  (signature mat3x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x4 x)\n"
+   "      (declare (in) mat3x4 y))\n"
+   "    ())\n"
+   "  (signature mat4x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x2 x)\n"
+   "      (declare (in) mat4x2 y))\n"
+   "    ())\n"
+   "  (signature mat4x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x3 x)\n"
+   "      (declare (in) mat4x3 y))\n"
+   "    ()))\n"
+   "(function outerProduct\n"
+   "  (signature mat2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 c)\n"
+   "      (declare (in) vec2 r))\n"
+   "    ())\n"
+   "  (signature mat3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 c)\n"
+   "      (declare (in) vec3 r))\n"
+   "    ())\n"
+   "  (signature mat4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 c)\n"
+   "      (declare (in) vec4 r))\n"
+   "    ())\n"
+   "  (signature mat2x3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 c)\n"
+   "      (declare (in) vec2 r))\n"
+   "    ())\n"
+   "  (signature mat3x2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 c)\n"
+   "      (declare (in) vec3 r))\n"
+   "    ())\n"
+   "  (signature mat2x4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 c)\n"
+   "      (declare (in) vec2 r))\n"
+   "    ())\n"
+   "  (signature mat4x2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 c)\n"
+   "      (declare (in) vec4 r))\n"
+   "    ())\n"
+   "  (signature mat3x4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 c)\n"
+   "      (declare (in) vec3 r))\n"
+   "    ())\n"
+   "  (signature mat4x3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 c)\n"
+   "      (declare (in) vec4 r))\n"
+   "    ()))\n"
+   "(function transpose\n"
+   "  (signature mat2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2 m))\n"
+   "    ())\n"
+   "  (signature mat3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3 m))\n"
+   "    ())\n"
+   "  (signature mat4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4 m))\n"
+   "    ())\n"
+   "  (signature mat2x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x2 m))\n"
+   "    ())\n"
+   "  (signature mat3x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x3 m))\n"
+   "    ())\n"
+   "  (signature mat2x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x2 m))\n"
+   "    ())\n"
+   "  (signature mat4x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x4 m))\n"
+   "    ())\n"
+   "  (signature mat3x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x3 m))\n"
+   "    ())\n"
+   "  (signature mat4x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x4 m))\n"
+   "    ()))\n"
+   "(function lessThan\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ()))\n"
+   "(function lessThanEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ()))\n"
+   "(function greaterThan\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ()))\n"
+   "(function greaterThanEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ()))\n"
+   "(function equal\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x)\n"
+   "      (declare (in) bvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x)\n"
+   "      (declare (in) bvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x)\n"
+   "      (declare (in) bvec4 y))\n"
+   "    ()))\n"
+   "(function notEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x)\n"
+   "      (declare (in) bvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x)\n"
+   "      (declare (in) bvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x)\n"
+   "      (declare (in) bvec4 y))\n"
+   "    ()))\n"
+   "(function any\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function all\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function not\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function texture\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) float P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) float P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isamplerCube sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usamplerCube sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCubeShadow sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArray sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1DArray sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1DArray sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArray sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2DArray sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2DArray sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArrayShadow sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArrayShadow sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isamplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usamplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCubeShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArrayShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function textureProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function textureLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isamplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usamplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArrayShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texelFetch\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) int P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) int P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) int P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) ivec2 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) ivec2 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) ivec2 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) ivec3 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) ivec3 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) ivec3 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArray sampler)\n"
+   "      (declare (in) ivec2 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1DArray sampler)\n"
+   "      (declare (in) ivec2 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1DArray sampler)\n"
+   "      (declare (in) ivec2 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArray sampler)\n"
+   "      (declare (in) ivec3 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2DArray sampler)\n"
+   "      (declare (in) ivec3 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2DArray sampler)\n"
+   "      (declare (in) ivec3 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ()))\n"
+   "(function textureProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function textureGrad\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isamplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usamplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCubeShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArrayShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArrayShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ()))\n"
+   "(function textureProjGrad\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ()))\n"
+   "(function texture1D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture1DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture1DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture1DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture2D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture2DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture2DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture2DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture3D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture3DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture3DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture3DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function textureCube\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function textureCubeLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow1D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow2D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow1DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow2DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow1DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow2DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow1DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow2DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function dFdx\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float p))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 p))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 p))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 p))\n"
+   "    ()))\n"
+   "(function dFdy\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float p))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 p))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 p))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 p))\n"
+   "    ()))\n"
+   "(function fwidth\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float p))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 p))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 p))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 p))\n"
+   "    ()))\n"
+   "(function noise1\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise2\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise3\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise4\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())))"
+;
+static const char *functions_for_130_frag [] = {
+   builtin_abs,
+   builtin_acos,
+   builtin_all,
+   builtin_any,
+   builtin_asin,
+   builtin_atan,
+   builtin_ceil,
+   builtin_clamp,
+   builtin_cos,
+   builtin_cosh,
+   builtin_cross,
+   builtin_dFdx,
+   builtin_dFdy,
+   builtin_degrees,
+   builtin_distance,
+   builtin_dot,
+   builtin_equal,
+   builtin_exp,
+   builtin_exp2,
+   builtin_faceforward,
+   builtin_floor,
+   builtin_fract,
+   builtin_fwidth,
+   builtin_greaterThan,
+   builtin_greaterThanEqual,
+   builtin_inversesqrt,
+   builtin_length,
+   builtin_lessThan,
+   builtin_lessThanEqual,
+   builtin_log,
+   builtin_log2,
+   builtin_matrixCompMult,
+   builtin_max,
+   builtin_min,
+   builtin_mix,
+   builtin_mod,
+   builtin_noise1,
+   builtin_noise2,
+   builtin_noise3,
+   builtin_noise4,
+   builtin_normalize,
+   builtin_not,
+   builtin_notEqual,
+   builtin_outerProduct,
+   builtin_pow,
+   builtin_radians,
+   builtin_reflect,
+   builtin_refract,
+   builtin_shadow1D,
+   builtin_shadow1DLod,
+   builtin_shadow1DProj,
+   builtin_shadow1DProjLod,
+   builtin_shadow2D,
+   builtin_shadow2DLod,
+   builtin_shadow2DProj,
+   builtin_shadow2DProjLod,
+   builtin_sign,
+   builtin_sin,
+   builtin_sinh,
+   builtin_smoothstep,
+   builtin_sqrt,
+   builtin_step,
+   builtin_tan,
+   builtin_tanh,
+   builtin_texelFetch,
+   builtin_texture,
+   builtin_texture1D,
+   builtin_texture1DLod,
+   builtin_texture1DProj,
+   builtin_texture1DProjLod,
+   builtin_texture2D,
+   builtin_texture2DLod,
+   builtin_texture2DProj,
+   builtin_texture2DProjLod,
+   builtin_texture3D,
+   builtin_texture3DLod,
+   builtin_texture3DProj,
+   builtin_texture3DProjLod,
+   builtin_textureCube,
+   builtin_textureCubeLod,
+   builtin_textureGrad,
+   builtin_textureLod,
+   builtin_textureProj,
+   builtin_textureProjGrad,
+   builtin_textureProjLod,
+   builtin_transpose,
+};
+static const char *prototypes_for_130_vert =
+   "(\n"
+   "(function radians\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float degrees))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 degrees))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 degrees))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 degrees))\n"
+   "    ()))\n"
+   "(function degrees\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float radians))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 radians))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 radians))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 radians))\n"
+   "    ()))\n"
+   "(function sin\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function cos\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function tan\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function asin\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function acos\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float angle))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 angle))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 angle))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 angle))\n"
+   "    ()))\n"
+   "(function atan\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float y)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float y_over_x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 y_over_x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 y_over_x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 y_over_x))\n"
+   "    ()))\n"
+   "(function sinh\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function cosh\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function tanh\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function pow\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function exp\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function log\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function exp2\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function log2\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function sqrt\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function inversesqrt\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function abs\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature int\n"
+   "    (parameters\n"
+   "      (declare (in) int x))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x))\n"
+   "    ()))\n"
+   "(function sign\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature int\n"
+   "    (parameters\n"
+   "      (declare (in) int x))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x))\n"
+   "    ()))\n"
+   "(function floor\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function ceil\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function fract\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function mod\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function min\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature int\n"
+   "    (parameters\n"
+   "      (declare (in) int x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature uint\n"
+   "    (parameters\n"
+   "      (declare (in) uint x)\n"
+   "      (declare (in) uint y))\n"
+   "    ())\n"
+   "  (signature uvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature uvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ())\n"
+   "  (signature uvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uint y))\n"
+   "    ())\n"
+   "  (signature uvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uint y))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uint y))\n"
+   "    ()))\n"
+   "(function max\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature int\n"
+   "    (parameters\n"
+   "      (declare (in) int x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) int y))\n"
+   "    ())\n"
+   "  (signature uint\n"
+   "    (parameters\n"
+   "      (declare (in) uint x)\n"
+   "      (declare (in) uint y))\n"
+   "    ())\n"
+   "  (signature uvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature uvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ())\n"
+   "  (signature uvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uint y))\n"
+   "    ())\n"
+   "  (signature uvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uint y))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uint y))\n"
+   "    ()))\n"
+   "(function clamp\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 minVal)\n"
+   "      (declare (in) vec2 maxVal))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 minVal)\n"
+   "      (declare (in) vec3 maxVal))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 minVal)\n"
+   "      (declare (in) vec4 maxVal))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) float minVal)\n"
+   "      (declare (in) float maxVal))\n"
+   "    ())\n"
+   "  (signature int\n"
+   "    (parameters\n"
+   "      (declare (in) int x)\n"
+   "      (declare (in) int minVal)\n"
+   "      (declare (in) int maxVal))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 minVal)\n"
+   "      (declare (in) ivec2 maxVal))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 minVal)\n"
+   "      (declare (in) ivec3 maxVal))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 minVal)\n"
+   "      (declare (in) ivec4 maxVal))\n"
+   "    ())\n"
+   "  (signature ivec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) int minVal)\n"
+   "      (declare (in) int maxVal))\n"
+   "    ())\n"
+   "  (signature ivec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) int minVal)\n"
+   "      (declare (in) int maxVal))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) int minVal)\n"
+   "      (declare (in) int maxVal))\n"
+   "    ())\n"
+   "  (signature uint\n"
+   "    (parameters\n"
+   "      (declare (in) uint x)\n"
+   "      (declare (in) uint minVal)\n"
+   "      (declare (in) uint maxVal))\n"
+   "    ())\n"
+   "  (signature uvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 minVal)\n"
+   "      (declare (in) uvec2 maxVal))\n"
+   "    ())\n"
+   "  (signature uvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 minVal)\n"
+   "      (declare (in) uvec3 maxVal))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 minVal)\n"
+   "      (declare (in) uvec4 maxVal))\n"
+   "    ())\n"
+   "  (signature uvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uint minVal)\n"
+   "      (declare (in) uint maxVal))\n"
+   "    ())\n"
+   "  (signature uvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uint minVal)\n"
+   "      (declare (in) uint maxVal))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uint minVal)\n"
+   "      (declare (in) uint maxVal))\n"
+   "    ()))\n"
+   "(function mix\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) vec2 a))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) vec3 a))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) vec4 a))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y)\n"
+   "      (declare (in) float a))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y)\n"
+   "      (declare (in) float a))\n"
+   "    ()))\n"
+   "(function step\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 edge)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 edge)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 edge)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float edge)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function smoothstep\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 edge0)\n"
+   "      (declare (in) vec2 edge1)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 edge0)\n"
+   "      (declare (in) vec3 edge1)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 edge0)\n"
+   "      (declare (in) vec4 edge1)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float edge0)\n"
+   "      (declare (in) float edge1)\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function length\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function distance\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float p0)\n"
+   "      (declare (in) float p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 p0)\n"
+   "      (declare (in) vec2 p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 p0)\n"
+   "      (declare (in) vec3 p1))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 p0)\n"
+   "      (declare (in) vec4 p1))\n"
+   "    ()))\n"
+   "(function dot\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x)\n"
+   "      (declare (in) float y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ()))\n"
+   "(function cross\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ()))\n"
+   "(function normalize\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function ftransform\n"
+   "  (signature vec4\n"
+   "    (parameters)\n"
+   "    ()))\n"
+   "(function faceforward\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float N)\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float Nref))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 N)\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 Nref))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 N)\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 Nref))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 N)\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 Nref))\n"
+   "    ()))\n"
+   "(function reflect\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float N))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 N))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 N))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 N))\n"
+   "    ()))\n"
+   "(function refract\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float I)\n"
+   "      (declare (in) float N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 I)\n"
+   "      (declare (in) vec2 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 I)\n"
+   "      (declare (in) vec3 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 I)\n"
+   "      (declare (in) vec4 N)\n"
+   "      (declare (in) float eta))\n"
+   "    ()))\n"
+   "(function matrixCompMult\n"
+   "  (signature mat2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2 x)\n"
+   "      (declare (in) mat2 y))\n"
+   "    ())\n"
+   "  (signature mat3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3 x)\n"
+   "      (declare (in) mat3 y))\n"
+   "    ())\n"
+   "  (signature mat4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4 x)\n"
+   "      (declare (in) mat4 y))\n"
+   "    ())\n"
+   "  (signature mat2x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x3 x)\n"
+   "      (declare (in) mat2x3 y))\n"
+   "    ())\n"
+   "  (signature mat2x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x4 x)\n"
+   "      (declare (in) mat2x4 y))\n"
+   "    ())\n"
+   "  (signature mat3x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x2 x)\n"
+   "      (declare (in) mat3x2 y))\n"
+   "    ())\n"
+   "  (signature mat3x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x4 x)\n"
+   "      (declare (in) mat3x4 y))\n"
+   "    ())\n"
+   "  (signature mat4x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x2 x)\n"
+   "      (declare (in) mat4x2 y))\n"
+   "    ())\n"
+   "  (signature mat4x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x3 x)\n"
+   "      (declare (in) mat4x3 y))\n"
+   "    ()))\n"
+   "(function outerProduct\n"
+   "  (signature mat2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 c)\n"
+   "      (declare (in) vec2 r))\n"
+   "    ())\n"
+   "  (signature mat3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 c)\n"
+   "      (declare (in) vec3 r))\n"
+   "    ())\n"
+   "  (signature mat4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 c)\n"
+   "      (declare (in) vec4 r))\n"
+   "    ())\n"
+   "  (signature mat2x3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 c)\n"
+   "      (declare (in) vec2 r))\n"
+   "    ())\n"
+   "  (signature mat3x2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 c)\n"
+   "      (declare (in) vec3 r))\n"
+   "    ())\n"
+   "  (signature mat2x4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 c)\n"
+   "      (declare (in) vec2 r))\n"
+   "    ())\n"
+   "  (signature mat4x2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 c)\n"
+   "      (declare (in) vec4 r))\n"
+   "    ())\n"
+   "  (signature mat3x4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 c)\n"
+   "      (declare (in) vec3 r))\n"
+   "    ())\n"
+   "  (signature mat4x3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 c)\n"
+   "      (declare (in) vec4 r))\n"
+   "    ()))\n"
+   "(function transpose\n"
+   "  (signature mat2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2 m))\n"
+   "    ())\n"
+   "  (signature mat3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3 m))\n"
+   "    ())\n"
+   "  (signature mat4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4 m))\n"
+   "    ())\n"
+   "  (signature mat2x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x2 m))\n"
+   "    ())\n"
+   "  (signature mat3x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x3 m))\n"
+   "    ())\n"
+   "  (signature mat2x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x2 m))\n"
+   "    ())\n"
+   "  (signature mat4x2\n"
+   "    (parameters\n"
+   "      (declare (in) mat2x4 m))\n"
+   "    ())\n"
+   "  (signature mat3x4\n"
+   "    (parameters\n"
+   "      (declare (in) mat4x3 m))\n"
+   "    ())\n"
+   "  (signature mat4x3\n"
+   "    (parameters\n"
+   "      (declare (in) mat3x4 m))\n"
+   "    ()))\n"
+   "(function lessThan\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ()))\n"
+   "(function lessThanEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ()))\n"
+   "(function greaterThan\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ()))\n"
+   "(function greaterThanEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ()))\n"
+   "(function equal\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x)\n"
+   "      (declare (in) bvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x)\n"
+   "      (declare (in) bvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x)\n"
+   "      (declare (in) bvec4 y))\n"
+   "    ()))\n"
+   "(function notEqual\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x)\n"
+   "      (declare (in) vec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x)\n"
+   "      (declare (in) vec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x)\n"
+   "      (declare (in) vec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) ivec2 x)\n"
+   "      (declare (in) ivec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) ivec3 x)\n"
+   "      (declare (in) ivec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) ivec4 x)\n"
+   "      (declare (in) ivec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) uvec2 x)\n"
+   "      (declare (in) uvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) uvec3 x)\n"
+   "      (declare (in) uvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) uvec4 x)\n"
+   "      (declare (in) uvec4 y))\n"
+   "    ())\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x)\n"
+   "      (declare (in) bvec2 y))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x)\n"
+   "      (declare (in) bvec3 y))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x)\n"
+   "      (declare (in) bvec4 y))\n"
+   "    ()))\n"
+   "(function any\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function all\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bool\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function not\n"
+   "  (signature bvec2\n"
+   "    (parameters\n"
+   "      (declare (in) bvec2 x))\n"
+   "    ())\n"
+   "  (signature bvec3\n"
+   "    (parameters\n"
+   "      (declare (in) bvec3 x))\n"
+   "    ())\n"
+   "  (signature bvec4\n"
+   "    (parameters\n"
+   "      (declare (in) bvec4 x))\n"
+   "    ()))\n"
+   "(function texture\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) float P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) float P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isamplerCube sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usamplerCube sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCubeShadow sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArray sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1DArray sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1DArray sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArray sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2DArray sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2DArray sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArrayShadow sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArrayShadow sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isamplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usamplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCubeShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArrayShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function textureProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec2 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec3 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 P))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function textureLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isamplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usamplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArrayShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texelFetch\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) int P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) int P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) int P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) ivec2 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) ivec2 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) ivec2 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) ivec3 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) ivec3 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) ivec3 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArray sampler)\n"
+   "      (declare (in) ivec2 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1DArray sampler)\n"
+   "      (declare (in) ivec2 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1DArray sampler)\n"
+   "      (declare (in) ivec2 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArray sampler)\n"
+   "      (declare (in) ivec3 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2DArray sampler)\n"
+   "      (declare (in) ivec3 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2DArray sampler)\n"
+   "      (declare (in) ivec3 P)\n"
+   "      (declare (in) int lod))\n"
+   "    ()))\n"
+   "(function textureProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function textureGrad\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) float P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isamplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usamplerCube sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCubeShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1DArray sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2DArray sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArrayShadow sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArrayShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ()))\n"
+   "(function textureProjGrad\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec2 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler1D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec3 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler2D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature ivec4\n"
+   "    (parameters\n"
+   "      (declare (in) isampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature uvec4\n"
+   "    (parameters\n"
+   "      (declare (in) usampler3D sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec3 dPdx)\n"
+   "      (declare (in) vec3 dPdy))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) float dPdx)\n"
+   "      (declare (in) float dPdy))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 P)\n"
+   "      (declare (in) vec2 dPdx)\n"
+   "      (declare (in) vec2 dPdy))\n"
+   "    ()))\n"
+   "(function texture1D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture1DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture1DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) float coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture1DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture2D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture2DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture2DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture2DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture3D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture3DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture3DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture3DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler3D sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function textureCube\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function textureCubeLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) samplerCube sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow1D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow2D\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow1DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow2DProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow1DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow2DLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow1DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow2DProjLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DShadow sampler)\n"
+   "      (declare (in) vec4 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function noise1\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature float\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise2\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec2\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise3\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec3\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ()))\n"
+   "(function noise4\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) float x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec2 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec3 x))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) vec4 x))\n"
+   "    ())))"
+;
+static const char *functions_for_130_vert [] = {
+   builtin_abs,
+   builtin_acos,
+   builtin_all,
+   builtin_any,
+   builtin_asin,
+   builtin_atan,
+   builtin_ceil,
+   builtin_clamp,
+   builtin_cos,
+   builtin_cosh,
+   builtin_cross,
+   builtin_degrees,
+   builtin_distance,
+   builtin_dot,
+   builtin_equal,
+   builtin_exp,
+   builtin_exp2,
+   builtin_faceforward,
+   builtin_floor,
+   builtin_fract,
+   builtin_ftransform,
+   builtin_greaterThan,
+   builtin_greaterThanEqual,
+   builtin_inversesqrt,
+   builtin_length,
+   builtin_lessThan,
+   builtin_lessThanEqual,
+   builtin_log,
+   builtin_log2,
+   builtin_matrixCompMult,
+   builtin_max,
+   builtin_min,
+   builtin_mix,
+   builtin_mod,
+   builtin_noise1,
+   builtin_noise2,
+   builtin_noise3,
+   builtin_noise4,
+   builtin_normalize,
+   builtin_not,
+   builtin_notEqual,
+   builtin_outerProduct,
+   builtin_pow,
+   builtin_radians,
+   builtin_reflect,
+   builtin_refract,
+   builtin_shadow1D,
+   builtin_shadow1DLod,
+   builtin_shadow1DProj,
+   builtin_shadow1DProjLod,
+   builtin_shadow2D,
+   builtin_shadow2DLod,
+   builtin_shadow2DProj,
+   builtin_shadow2DProjLod,
+   builtin_sign,
+   builtin_sin,
+   builtin_sinh,
+   builtin_smoothstep,
+   builtin_sqrt,
+   builtin_step,
+   builtin_tan,
+   builtin_tanh,
+   builtin_texelFetch,
+   builtin_texture,
+   builtin_texture1D,
+   builtin_texture1DLod,
+   builtin_texture1DProj,
+   builtin_texture1DProjLod,
+   builtin_texture2D,
+   builtin_texture2DLod,
+   builtin_texture2DProj,
+   builtin_texture2DProjLod,
+   builtin_texture3D,
+   builtin_texture3DLod,
+   builtin_texture3DProj,
+   builtin_texture3DProjLod,
+   builtin_textureCube,
+   builtin_textureCubeLod,
+   builtin_textureGrad,
+   builtin_textureLod,
+   builtin_textureProj,
+   builtin_textureProjGrad,
+   builtin_textureProjLod,
+   builtin_transpose,
+};
+static const char *prototypes_for_ARB_texture_rectangle_frag =
+   "(\n"
+   "(function texture2DRect\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DRect sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ()))\n"
+   "(function texture2DRectProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DRect sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DRect sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ()))\n"
+   "(function shadow2DRect\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DRectShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ()))\n"
+   "(function shadow2DRectProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DRectShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())))"
+;
+static const char *functions_for_ARB_texture_rectangle_frag [] = {
+   builtin_shadow2DRect,
+   builtin_shadow2DRectProj,
+   builtin_texture2DRect,
+   builtin_texture2DRectProj,
+};
+static const char *prototypes_for_ARB_texture_rectangle_vert =
+   "(\n"
+   "(function texture2DRect\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DRect sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ()))\n"
+   "(function texture2DRectProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DRect sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DRect sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ()))\n"
+   "(function shadow2DRect\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DRectShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ()))\n"
+   "(function shadow2DRectProj\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DRectShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())))"
+;
+static const char *functions_for_ARB_texture_rectangle_vert [] = {
+   builtin_shadow2DRect,
+   builtin_shadow2DRectProj,
+   builtin_texture2DRect,
+   builtin_texture2DRectProj,
+};
+static const char *prototypes_for_EXT_texture_array_frag =
+   "(\n"
+   "(function texture1DArray\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArray sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArray sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function texture2DArray\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArray sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArray sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow1DArray\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArrayShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ())\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArrayShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float bias))\n"
+   "    ()))\n"
+   "(function shadow2DArray\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArrayShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())))"
+;
+static const char *functions_for_EXT_texture_array_frag [] = {
+   builtin_shadow1DArray,
+   builtin_shadow2DArray,
+   builtin_texture1DArray,
+   builtin_texture2DArray,
+};
+static const char *prototypes_for_EXT_texture_array_vert =
+   "(\n"
+   "(function texture1DArray\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArray sampler)\n"
+   "      (declare (in) vec2 coord))\n"
+   "    ()))\n"
+   "(function texture1DArrayLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArray sampler)\n"
+   "      (declare (in) vec2 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function texture2DArray\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArray sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ()))\n"
+   "(function texture2DArrayLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArray sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow1DArray\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArrayShadow sampler)\n"
+   "      (declare (in) vec3 coord))\n"
+   "    ()))\n"
+   "(function shadow1DArrayLod\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler1DArrayShadow sampler)\n"
+   "      (declare (in) vec3 coord)\n"
+   "      (declare (in) float lod))\n"
+   "    ()))\n"
+   "(function shadow2DArray\n"
+   "  (signature vec4\n"
+   "    (parameters\n"
+   "      (declare (in) sampler2DArrayShadow sampler)\n"
+   "      (declare (in) vec4 coord))\n"
+   "    ())))"
+;
+static const char *functions_for_EXT_texture_array_vert [] = {
+   builtin_shadow1DArray,
+   builtin_shadow1DArrayLod,
+   builtin_shadow2DArray,
+   builtin_texture1DArray,
+   builtin_texture1DArrayLod,
+   builtin_texture2DArray,
+   builtin_texture2DArrayLod,
+};
+static gl_shader *builtin_profiles[10];
+
+void *builtin_mem_ctx = NULL;
+
+void
+_mesa_glsl_release_functions(void)
+{
+   talloc_free(builtin_mem_ctx);
+   builtin_mem_ctx = NULL;
+}
+
+static void
+_mesa_read_profile(struct _mesa_glsl_parse_state *state,
+                  exec_list *instructions,
+                   int profile_index,
+                  const char *prototypes,
+                  const char **functions,
+                   int count)
+{
+   gl_shader *sh = builtin_profiles[profile_index];
+
+   if (sh == NULL) {
+      sh = read_builtins(GL_VERTEX_SHADER, prototypes, functions, count);
+      talloc_steal(builtin_mem_ctx, sh);
+      builtin_profiles[profile_index] = sh;
+   }
+
+   import_prototypes(sh->ir, instructions, state->symbols, state);
+   state->builtins_to_link[state->num_builtins_to_link] = sh;
+   state->num_builtins_to_link++;
+}
+
+void
+_mesa_glsl_initialize_functions(exec_list *instructions,
+                                struct _mesa_glsl_parse_state *state)
+{
+   if (builtin_mem_ctx == NULL) {
+      builtin_mem_ctx = talloc_init("GLSL built-in functions");
+      memset(&builtin_profiles, 0, sizeof(builtin_profiles));
+   }
+
+   state->num_builtins_to_link = 0;
+
+   if (state->target == fragment_shader && state->language_version == 110) {
+      _mesa_read_profile(state, instructions, 0,
+                         prototypes_for_110_frag,
+                         functions_for_110_frag,
+                         Elements(functions_for_110_frag));
+   }
+
+   if (state->target == vertex_shader && state->language_version == 110) {
+      _mesa_read_profile(state, instructions, 1,
+                         prototypes_for_110_vert,
+                         functions_for_110_vert,
+                         Elements(functions_for_110_vert));
+   }
+
+   if (state->target == fragment_shader && state->language_version == 120) {
+      _mesa_read_profile(state, instructions, 2,
+                         prototypes_for_120_frag,
+                         functions_for_120_frag,
+                         Elements(functions_for_120_frag));
+   }
+
+   if (state->target == vertex_shader && state->language_version == 120) {
+      _mesa_read_profile(state, instructions, 3,
+                         prototypes_for_120_vert,
+                         functions_for_120_vert,
+                         Elements(functions_for_120_vert));
+   }
+
+   if (state->target == fragment_shader && state->language_version == 130) {
+      _mesa_read_profile(state, instructions, 4,
+                         prototypes_for_130_frag,
+                         functions_for_130_frag,
+                         Elements(functions_for_130_frag));
+   }
+
+   if (state->target == vertex_shader && state->language_version == 130) {
+      _mesa_read_profile(state, instructions, 5,
+                         prototypes_for_130_vert,
+                         functions_for_130_vert,
+                         Elements(functions_for_130_vert));
+   }
+
+   if (state->target == fragment_shader && state->ARB_texture_rectangle_enable) {
+      _mesa_read_profile(state, instructions, 6,
+                         prototypes_for_ARB_texture_rectangle_frag,
+                         functions_for_ARB_texture_rectangle_frag,
+                         Elements(functions_for_ARB_texture_rectangle_frag));
+   }
+
+   if (state->target == vertex_shader && state->ARB_texture_rectangle_enable) {
+      _mesa_read_profile(state, instructions, 7,
+                         prototypes_for_ARB_texture_rectangle_vert,
+                         functions_for_ARB_texture_rectangle_vert,
+                         Elements(functions_for_ARB_texture_rectangle_vert));
+   }
+
+   if (state->target == fragment_shader && state->EXT_texture_array_enable) {
+      _mesa_read_profile(state, instructions, 8,
+                         prototypes_for_EXT_texture_array_frag,
+                         functions_for_EXT_texture_array_frag,
+                         Elements(functions_for_EXT_texture_array_frag));
+   }
+
+   if (state->target == vertex_shader && state->EXT_texture_array_enable) {
+      _mesa_read_profile(state, instructions, 9,
+                         prototypes_for_EXT_texture_array_vert,
+                         functions_for_EXT_texture_array_vert,
+                         Elements(functions_for_EXT_texture_array_vert));
+   }
+
+}
diff --git a/src/glsl/builtin_types.h b/src/glsl/builtin_types.h
new file mode 100644 (file)
index 0000000..7b94aac
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * Copyright Â© 2009 Intel Corporation
+ *
+ * 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.
+ */
+
+const glsl_type glsl_type::_error_type =
+   glsl_type(GL_INVALID_ENUM, GLSL_TYPE_ERROR, 0, 0, "");
+
+const glsl_type glsl_type::void_type =
+   glsl_type(GL_INVALID_ENUM, GLSL_TYPE_VOID, 0, 0, "void");
+
+const glsl_type *const glsl_type::error_type = & glsl_type::_error_type;
+
+/** \name Core built-in types
+ *
+ * These types exist in all versions of GLSL.
+ */
+/*@{*/
+
+const glsl_type glsl_type::builtin_core_types[] = {
+   glsl_type(GL_BOOL,         GLSL_TYPE_BOOL, 1, 1, "bool"),
+   glsl_type(GL_BOOL_VEC2,    GLSL_TYPE_BOOL, 2, 1, "bvec2"),
+   glsl_type(GL_BOOL_VEC3,    GLSL_TYPE_BOOL, 3, 1, "bvec3"),
+   glsl_type(GL_BOOL_VEC4,    GLSL_TYPE_BOOL, 4, 1, "bvec4"),
+   glsl_type(GL_INT,          GLSL_TYPE_INT, 1, 1, "int"),
+   glsl_type(GL_INT_VEC2,     GLSL_TYPE_INT, 2, 1, "ivec2"),
+   glsl_type(GL_INT_VEC3,     GLSL_TYPE_INT, 3, 1, "ivec3"),
+   glsl_type(GL_INT_VEC4,     GLSL_TYPE_INT, 4, 1, "ivec4"),
+   glsl_type(GL_FLOAT,        GLSL_TYPE_FLOAT, 1, 1, "float"),
+   glsl_type(GL_FLOAT_VEC2,   GLSL_TYPE_FLOAT, 2, 1, "vec2"),
+   glsl_type(GL_FLOAT_VEC3,   GLSL_TYPE_FLOAT, 3, 1, "vec3"),
+   glsl_type(GL_FLOAT_VEC4,   GLSL_TYPE_FLOAT, 4, 1, "vec4"),
+   glsl_type(GL_FLOAT_MAT2,   GLSL_TYPE_FLOAT, 2, 2, "mat2"),
+   glsl_type(GL_FLOAT_MAT3,   GLSL_TYPE_FLOAT, 3, 3, "mat3"),
+   glsl_type(GL_FLOAT_MAT4,   GLSL_TYPE_FLOAT, 4, 4, "mat4"),
+   glsl_type(GL_SAMPLER_1D,   GLSL_SAMPLER_DIM_1D, 0, 0, GLSL_TYPE_FLOAT,
+            "sampler1D"),
+   glsl_type(GL_SAMPLER_1D_SHADOW, GLSL_SAMPLER_DIM_1D, 1, 0, GLSL_TYPE_FLOAT,
+            "sampler1DShadow"),
+   glsl_type(GL_SAMPLER_2D,   GLSL_SAMPLER_DIM_2D, 0, 0, GLSL_TYPE_FLOAT,
+            "sampler2D"),
+   glsl_type(GL_SAMPLER_2D_SHADOW, GLSL_SAMPLER_DIM_2D, 1, 0, GLSL_TYPE_FLOAT,
+            "sampler2DShadow"),
+   glsl_type(GL_SAMPLER_3D,   GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_FLOAT,
+            "sampler3D"),
+   glsl_type(GL_SAMPLER_CUBE, GLSL_SAMPLER_DIM_CUBE, 0, 0, GLSL_TYPE_FLOAT,
+            "samplerCube"),
+};
+
+const glsl_type *const glsl_type::bool_type  = & builtin_core_types[0];
+const glsl_type *const glsl_type::int_type   = & builtin_core_types[4];
+const glsl_type *const glsl_type::ivec4_type = & builtin_core_types[7];
+const glsl_type *const glsl_type::float_type = & builtin_core_types[8];
+const glsl_type *const glsl_type::vec2_type = & builtin_core_types[9];
+const glsl_type *const glsl_type::vec3_type = & builtin_core_types[10];
+const glsl_type *const glsl_type::vec4_type = & builtin_core_types[11];
+const glsl_type *const glsl_type::mat2_type = & builtin_core_types[12];
+const glsl_type *const glsl_type::mat3_type = & builtin_core_types[13];
+const glsl_type *const glsl_type::mat4_type = & builtin_core_types[14];
+/*@}*/
+
+/** \name GLSL structures that have not been deprecated.
+ */
+/*@{*/
+
+static const struct glsl_struct_field gl_DepthRangeParameters_fields[] = {
+   { glsl_type::float_type, "near" },
+   { glsl_type::float_type, "far" },
+   { glsl_type::float_type, "diff" },
+};
+
+const glsl_type glsl_type::builtin_structure_types[] = {
+   glsl_type(gl_DepthRangeParameters_fields,
+             Elements(gl_DepthRangeParameters_fields),
+             "gl_DepthRangeParameters"),
+};
+/*@}*/
+
+/** \name GLSL 1.00 / 1.10 structures that are deprecated in GLSL 1.30
+ */
+/*@{*/
+
+static const struct glsl_struct_field gl_PointParameters_fields[] = {
+   { glsl_type::float_type, "size" },
+   { glsl_type::float_type, "sizeMin" },
+   { glsl_type::float_type, "sizeMax" },
+   { glsl_type::float_type, "fadeThresholdSize" },
+   { glsl_type::float_type, "distanceConstantAttenuation" },
+   { glsl_type::float_type, "distanceLinearAttenuation" },
+   { glsl_type::float_type, "distanceQuadraticAttenuation" },
+};
+
+static const struct glsl_struct_field gl_MaterialParameters_fields[] = {
+   { glsl_type::vec4_type, "emission" },
+   { glsl_type::vec4_type, "ambient" },
+   { glsl_type::vec4_type, "diffuse" },
+   { glsl_type::vec4_type, "specular" },
+   { glsl_type::float_type, "shininess" },
+};
+
+static const struct glsl_struct_field gl_LightSourceParameters_fields[] = {
+   { glsl_type::vec4_type, "ambient" },
+   { glsl_type::vec4_type, "diffuse" },
+   { glsl_type::vec4_type, "specular" },
+   { glsl_type::vec4_type, "position" },
+   { glsl_type::vec4_type, "halfVector" },
+   { glsl_type::vec3_type, "spotDirection" },
+   { glsl_type::float_type, "spotExponent" },
+   { glsl_type::float_type, "spotCutoff" },
+   { glsl_type::float_type, "spotCosCutoff" },
+   { glsl_type::float_type, "constantAttenuation" },
+   { glsl_type::float_type, "linearAttenuation" },
+   { glsl_type::float_type, "quadraticAttenuation" },
+};
+
+static const struct glsl_struct_field gl_LightModelParameters_fields[] = {
+   { glsl_type::vec4_type, "ambient" },
+};
+
+static const struct glsl_struct_field gl_LightModelProducts_fields[] = {
+   { glsl_type::vec4_type, "sceneColor" },
+};
+
+static const struct glsl_struct_field gl_LightProducts_fields[] = {
+   { glsl_type::vec4_type, "ambient" },
+   { glsl_type::vec4_type, "diffuse" },
+   { glsl_type::vec4_type, "specular" },
+};
+
+static const struct glsl_struct_field gl_FogParameters_fields[] = {
+   { glsl_type::vec4_type, "color" },
+   { glsl_type::float_type, "density" },
+   { glsl_type::float_type, "start" },
+   { glsl_type::float_type, "end" },
+   { glsl_type::float_type, "scale" },
+};
+
+const glsl_type glsl_type::builtin_110_deprecated_structure_types[] = {
+   glsl_type(gl_PointParameters_fields,
+             Elements(gl_PointParameters_fields),
+             "gl_PointParameters"),
+   glsl_type(gl_MaterialParameters_fields,
+             Elements(gl_MaterialParameters_fields),
+             "gl_MaterialParameters"),
+   glsl_type(gl_LightSourceParameters_fields,
+             Elements(gl_LightSourceParameters_fields),
+             "gl_LightSourceParameters"),
+   glsl_type(gl_LightModelParameters_fields,
+             Elements(gl_LightModelParameters_fields),
+             "gl_LightModelParameters"),
+   glsl_type(gl_LightModelProducts_fields,
+             Elements(gl_LightModelProducts_fields),
+             "gl_LightModelProducts"),
+   glsl_type(gl_LightProducts_fields,
+             Elements(gl_LightProducts_fields),
+             "gl_LightProducts"),
+   glsl_type(gl_FogParameters_fields,
+             Elements(gl_FogParameters_fields),
+             "gl_FogParameters"),
+};
+/*@}*/
+
+/** \name Types added in GLSL 1.20
+ */
+/*@{*/
+
+const glsl_type glsl_type::builtin_120_types[] = {
+   glsl_type(GL_FLOAT_MAT2x3, GLSL_TYPE_FLOAT, 3, 2, "mat2x3"),
+   glsl_type(GL_FLOAT_MAT2x4, GLSL_TYPE_FLOAT, 4, 2, "mat2x4"),
+   glsl_type(GL_FLOAT_MAT3x2, GLSL_TYPE_FLOAT, 2, 3, "mat3x2"),
+   glsl_type(GL_FLOAT_MAT3x4, GLSL_TYPE_FLOAT, 4, 3, "mat3x4"),
+   glsl_type(GL_FLOAT_MAT4x2, GLSL_TYPE_FLOAT, 2, 4, "mat4x2"),
+   glsl_type(GL_FLOAT_MAT4x3, GLSL_TYPE_FLOAT, 3, 4, "mat4x3"),
+};
+const glsl_type *const glsl_type::mat2x3_type = & builtin_120_types[0];
+const glsl_type *const glsl_type::mat2x4_type = & builtin_120_types[1];
+const glsl_type *const glsl_type::mat3x2_type = & builtin_120_types[2];
+const glsl_type *const glsl_type::mat3x4_type = & builtin_120_types[3];
+const glsl_type *const glsl_type::mat4x2_type = & builtin_120_types[4];
+const glsl_type *const glsl_type::mat4x3_type = & builtin_120_types[5];
+/*@}*/
+
+/** \name Types added in GLSL 1.30
+ */
+/*@{*/
+
+const glsl_type glsl_type::builtin_130_types[] = {
+   glsl_type(GL_UNSIGNED_INT,      GLSL_TYPE_UINT, 1, 1, "uint"),
+   glsl_type(GL_UNSIGNED_INT_VEC2, GLSL_TYPE_UINT, 2, 1, "uvec2"),
+   glsl_type(GL_UNSIGNED_INT_VEC3, GLSL_TYPE_UINT, 3, 1, "uvec3"),
+   glsl_type(GL_UNSIGNED_INT_VEC4, GLSL_TYPE_UINT, 4, 1, "uvec4"),
+
+   /* 1D and 2D texture arrays - several of these are included only in
+    * builtin_EXT_texture_array_types.
+    */
+   glsl_type(GL_INT_SAMPLER_1D_ARRAY,
+            GLSL_SAMPLER_DIM_1D, 0, 1,   GLSL_TYPE_INT, "isampler1DArray"),
+   glsl_type(GL_UNSIGNED_INT_SAMPLER_1D_ARRAY,
+            GLSL_SAMPLER_DIM_1D, 0, 1,  GLSL_TYPE_UINT, "usampler1DArray"),
+   glsl_type(GL_INT_SAMPLER_2D_ARRAY,
+            GLSL_SAMPLER_DIM_2D, 0, 1,   GLSL_TYPE_INT, "isampler2DArray"),
+   glsl_type(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY,
+            GLSL_SAMPLER_DIM_2D, 0, 1,  GLSL_TYPE_UINT, "usampler2DArray"),
+
+   /* cube shadow samplers */
+   glsl_type(GL_SAMPLER_CUBE_SHADOW,
+            GLSL_SAMPLER_DIM_CUBE, 1, 0, GLSL_TYPE_FLOAT, "samplerCubeShadow"),
+
+   /* signed and unsigned integer samplers */
+   glsl_type(GL_INT_SAMPLER_1D,
+            GLSL_SAMPLER_DIM_1D, 0, 0,   GLSL_TYPE_INT, "isampler1D"),
+   glsl_type(GL_UNSIGNED_INT_SAMPLER_1D,
+            GLSL_SAMPLER_DIM_1D, 0, 0,  GLSL_TYPE_UINT, "usampler1D"),
+   glsl_type(GL_INT_SAMPLER_2D,
+            GLSL_SAMPLER_DIM_2D, 0, 0,   GLSL_TYPE_INT, "isampler2D"),
+   glsl_type(GL_UNSIGNED_INT_SAMPLER_2D,
+            GLSL_SAMPLER_DIM_2D, 0, 0,  GLSL_TYPE_UINT, "usampler2D"),
+   glsl_type(GL_INT_SAMPLER_3D,
+            GLSL_SAMPLER_DIM_3D, 0, 0,   GLSL_TYPE_INT, "isampler3D"),
+   glsl_type(GL_UNSIGNED_INT_SAMPLER_3D,
+            GLSL_SAMPLER_DIM_3D, 0, 0,  GLSL_TYPE_UINT, "usampler3D"),
+   glsl_type(GL_INT_SAMPLER_CUBE,
+            GLSL_SAMPLER_DIM_CUBE, 0, 0,   GLSL_TYPE_INT, "isamplerCube"),
+   glsl_type(GL_INT_SAMPLER_CUBE,
+            GLSL_SAMPLER_DIM_CUBE, 0, 0,  GLSL_TYPE_UINT, "usamplerCube"),
+};
+
+const glsl_type *const glsl_type::uint_type = & builtin_130_types[0];
+const glsl_type *const glsl_type::uvec4_type = & builtin_130_types[3];
+/*@}*/
+
+/** \name Sampler types added by GL_ARB_texture_rectangle
+ */
+/*@{*/
+
+const glsl_type glsl_type::builtin_ARB_texture_rectangle_types[] = {
+   glsl_type(GL_SAMPLER_2D_RECT,
+            GLSL_SAMPLER_DIM_RECT, 0, 0, GLSL_TYPE_FLOAT, "sampler2DRect"),
+   glsl_type(GL_SAMPLER_2D_RECT_SHADOW,
+            GLSL_SAMPLER_DIM_RECT, 1, 0, GLSL_TYPE_FLOAT, "sampler2DRectShadow"),
+};
+/*@}*/
+
+/** \name Sampler types added by GL_EXT_texture_array
+ */
+/*@{*/
+
+const glsl_type glsl_type::builtin_EXT_texture_array_types[] = {
+   glsl_type(GL_SAMPLER_1D_ARRAY,
+            GLSL_SAMPLER_DIM_1D, 0, 1, GLSL_TYPE_FLOAT, "sampler1DArray"),
+   glsl_type(GL_SAMPLER_1D_ARRAY_SHADOW,
+            GLSL_SAMPLER_DIM_2D, 0, 1, GLSL_TYPE_FLOAT, "sampler2DArray"),
+   glsl_type(GL_SAMPLER_2D_ARRAY,
+            GLSL_SAMPLER_DIM_1D, 1, 1, GLSL_TYPE_FLOAT, "sampler1DArrayShadow"),
+   glsl_type(GL_SAMPLER_2D_ARRAY_SHADOW,
+            GLSL_SAMPLER_DIM_2D, 1, 1, GLSL_TYPE_FLOAT, "sampler2DArrayShadow"),
+};
+/*@}*/
+
+/** \name Sampler types added by GL_EXT_texture_buffer_object
+ */
+/*@{*/
+
+const glsl_type glsl_type::builtin_EXT_texture_buffer_object_types[] = {
+   glsl_type(GL_SAMPLER_BUFFER,
+            GLSL_SAMPLER_DIM_BUF, 0, 0, GLSL_TYPE_FLOAT, "samplerBuffer"),
+   glsl_type(GL_INT_SAMPLER_BUFFER,
+            GLSL_SAMPLER_DIM_BUF, 0, 0,   GLSL_TYPE_INT, "isamplerBuffer"),
+   glsl_type(GL_UNSIGNED_INT_SAMPLER_BUFFER,
+            GLSL_SAMPLER_DIM_BUF, 0, 0,  GLSL_TYPE_UINT, "usamplerBuffer"),
+};
+/*@}*/
diff --git a/src/glsl/builtin_variables.h b/src/glsl/builtin_variables.h
new file mode 100644 (file)
index 0000000..a7dbe48
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 "main/core.h" /* for slot numbers */
+
+struct builtin_variable {
+   enum ir_variable_mode mode;
+   int slot;
+   const char *type;
+   const char *name;
+};
+
+static const builtin_variable builtin_core_vs_variables[] = {
+   { ir_var_out, VERT_RESULT_HPOS, "vec4",  "gl_Position" },
+   { ir_var_out, VERT_RESULT_PSIZ, "float", "gl_PointSize" },
+};
+
+static const builtin_variable builtin_core_fs_variables[] = {
+   { ir_var_in,  FRAG_ATTRIB_WPOS,  "vec4",  "gl_FragCoord" },
+   { ir_var_in,  FRAG_ATTRIB_FACE,  "bool",  "gl_FrontFacing" },
+   { ir_var_out, FRAG_RESULT_COLOR, "vec4",  "gl_FragColor" },
+   { ir_var_out, FRAG_RESULT_DEPTH, "float", "gl_FragDepth" },
+};
+
+static const builtin_variable builtin_110_deprecated_fs_variables[] = {
+   { ir_var_in,  FRAG_ATTRIB_COL0,  "vec4",  "gl_Color" },
+   { ir_var_in,  FRAG_ATTRIB_COL1,  "vec4",  "gl_SecondaryColor" },
+   { ir_var_in,  FRAG_ATTRIB_FOGC,  "float", "gl_FogFragCoord" },
+};
+
+static const builtin_variable builtin_110_deprecated_vs_variables[] = {
+   { ir_var_in,  VERT_ATTRIB_POS,    "vec4",  "gl_Vertex" },
+   { ir_var_in,  VERT_ATTRIB_NORMAL, "vec3",  "gl_Normal" },
+   { ir_var_in,  VERT_ATTRIB_COLOR0, "vec4",  "gl_Color" },
+   { ir_var_in,  VERT_ATTRIB_COLOR1, "vec4",  "gl_SecondaryColor" },
+   { ir_var_in,  VERT_ATTRIB_TEX0,   "vec4",  "gl_MultiTexCoord0" },
+   { ir_var_in,  VERT_ATTRIB_TEX1,   "vec4",  "gl_MultiTexCoord1" },
+   { ir_var_in,  VERT_ATTRIB_TEX2,   "vec4",  "gl_MultiTexCoord2" },
+   { ir_var_in,  VERT_ATTRIB_TEX3,   "vec4",  "gl_MultiTexCoord3" },
+   { ir_var_in,  VERT_ATTRIB_TEX4,   "vec4",  "gl_MultiTexCoord4" },
+   { ir_var_in,  VERT_ATTRIB_TEX5,   "vec4",  "gl_MultiTexCoord5" },
+   { ir_var_in,  VERT_ATTRIB_TEX6,   "vec4",  "gl_MultiTexCoord6" },
+   { ir_var_in,  VERT_ATTRIB_TEX7,   "vec4",  "gl_MultiTexCoord7" },
+   { ir_var_in,  VERT_ATTRIB_FOG,    "float", "gl_FogCoord" },
+   { ir_var_out, VERT_RESULT_HPOS,   "vec4",  "gl_ClipVertex" },
+   { ir_var_out, VERT_RESULT_COL0,   "vec4",  "gl_FrontColor" },
+   { ir_var_out, VERT_RESULT_BFC0,   "vec4",  "gl_BackColor" },
+   { ir_var_out, VERT_RESULT_COL1,   "vec4",  "gl_FrontSecondaryColor" },
+   { ir_var_out, VERT_RESULT_BFC1,   "vec4",  "gl_BackSecondaryColor" },
+   { ir_var_out, VERT_RESULT_FOGC,   "float", "gl_FogFragCoord" },
+};
+
+static const builtin_variable builtin_120_fs_variables[] = {
+   { ir_var_in,  FRAG_ATTRIB_PNTC,   "vec2",   "gl_PointCoord" },
+};
+
+static const builtin_variable builtin_130_vs_variables[] = {
+   { ir_var_in,  -1,                 "int",   "gl_VertexID" },
+};
+
+static const builtin_variable builtin_110_deprecated_uniforms[] = {
+   { ir_var_uniform, -1, "mat4", "gl_ModelViewMatrix" },
+   { ir_var_uniform, -1, "mat4", "gl_ProjectionMatrix" },
+   { ir_var_uniform, -1, "mat4", "gl_ModelViewProjectionMatrix" },
+   { ir_var_uniform, -1, "mat3", "gl_NormalMatrix" },
+   { ir_var_uniform, -1, "mat4", "gl_ModelViewMatrixInverse" },
+   { ir_var_uniform, -1, "mat4", "gl_ProjectionMatrixInverse" },
+   { ir_var_uniform, -1, "mat4", "gl_ModelViewProjectionMatrixInverse" },
+   { ir_var_uniform, -1, "mat4", "gl_ModelViewMatrixTranspose" },
+   { ir_var_uniform, -1, "mat4", "gl_ProjectionMatrixTranspose" },
+   { ir_var_uniform, -1, "mat4", "gl_ModelViewProjectionMatrixTranspose" },
+   { ir_var_uniform, -1, "mat4", "gl_ModelViewMatrixInverseTranspose" },
+   { ir_var_uniform, -1, "mat4", "gl_ProjectionMatrixInverseTranspose" },
+   { ir_var_uniform, -1, "mat4", "gl_ModelViewProjectionMatrixInverseTranspose" },
+   { ir_var_uniform, -1, "float", "gl_NormalScale" },
+   { ir_var_uniform, -1, "gl_LightModelParameters", "gl_LightModel"},
+};
+
diff --git a/src/glsl/builtins/ir/abs b/src/glsl/builtins/ir/abs
new file mode 100644 (file)
index 0000000..9048453
--- /dev/null
@@ -0,0 +1,21 @@
+((function abs
+   (signature float
+     (parameters
+       (declare (in) float arg0))
+     ((return (expression float abs (var_ref arg0)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0))
+     ((return (expression vec2 abs (var_ref arg0)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0))
+     ((return (expression vec3 abs (var_ref arg0)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0))
+     ((return (expression vec4 abs (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/acos b/src/glsl/builtins/ir/acos
new file mode 100644 (file)
index 0000000..d1cfebe
--- /dev/null
@@ -0,0 +1,22 @@
+((function acos
+   (signature float
+     (parameters
+       (declare (in) float x))
+     ((return (expression float - (constant float (1.5707963))
+                                  (call asin ((var_ref x)))))))
+   (signature vec2
+     (parameters
+       (declare (in) vec2 x))
+     ((return (expression vec2 - (constant float (1.5707963))
+                                 (call asin ((var_ref x)))))))
+   (signature vec3
+     (parameters
+       (declare (in) vec3 x))
+     ((return (expression vec3 - (constant float (1.5707963))
+                                 (call asin ((var_ref x)))))))
+   (signature vec4
+     (parameters
+       (declare (in) vec4 x))
+     ((return (expression vec4 - (constant float (1.5707963))
+                                 (call asin ((var_ref x)))))))
+))
diff --git a/src/glsl/builtins/ir/all b/src/glsl/builtins/ir/all
new file mode 100644 (file)
index 0000000..2cac0df
--- /dev/null
@@ -0,0 +1,16 @@
+((function all
+   (signature bool
+     (parameters
+       (declare (in) bvec2 arg0))
+     ((return (expression bool && (swiz x (var_ref arg0))(swiz y (var_ref arg0))))))
+
+   (signature bool
+     (parameters
+       (declare (in) bvec3 arg0))
+     ((return (expression bool && (expression bool && (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0))))))
+
+   (signature bool
+     (parameters
+       (declare (in) bvec4 arg0))
+     ((return (expression bool && (expression bool && (expression bool && (swiz x (var_ref arg0))(swiz y (var_ref arg0))) (swiz z (var_ref arg0))) (swiz w (var_ref arg0))))))
+))
diff --git a/src/glsl/builtins/ir/any b/src/glsl/builtins/ir/any
new file mode 100644 (file)
index 0000000..cc6038a
--- /dev/null
@@ -0,0 +1,16 @@
+((function any
+   (signature bool
+     (parameters
+       (declare (in) bvec2 arg0))
+     ((return (expression bool any (var_ref arg0)))))
+
+   (signature bool
+     (parameters
+       (declare (in) bvec3 arg0))
+     ((return (expression bool any (var_ref arg0)))))
+
+   (signature bool
+     (parameters
+       (declare (in) bvec4 arg0))
+     ((return (expression bool any (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/asin b/src/glsl/builtins/ir/asin
new file mode 100644 (file)
index 0000000..e230ad6
--- /dev/null
@@ -0,0 +1,97 @@
+((function asin
+   (signature float
+     (parameters
+       (declare (in) float x))
+     ((return (expression float *
+              (expression float sign (var_ref x))
+              (expression float -
+               (expression float *
+                (constant float (3.1415926))
+                (constant float (0.5)))
+               (expression float *
+                (expression float sqrt
+                 (expression float -
+                  (constant float (1.0))
+                  (expression float abs (var_ref x))))
+                (expression float +
+                 (constant float (1.5707288))
+                 (expression float *
+                  (expression float abs (var_ref x))
+                  (expression float +
+                   (constant float (-0.2121144))
+                   (expression float *
+                    (constant float (0.0742610))
+                    (expression float abs (var_ref x))))))))))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 x))
+     ((return (expression vec2 *
+              (expression vec2 sign (var_ref x))
+              (expression vec2 -
+               (expression float *
+                (constant float (3.1415926))
+                (constant float (0.5)))
+               (expression vec2 *
+                (expression vec2 sqrt
+                 (expression vec2 -
+                  (constant float (1.0))
+                  (expression vec2 abs (var_ref x))))
+                (expression vec2 +
+                 (constant float (1.5707288))
+                 (expression vec2 *
+                  (expression vec2 abs (var_ref x))
+                  (expression vec2 +
+                   (constant float (-0.2121144))
+                   (expression vec2 *
+                    (constant float (0.0742610))
+                    (expression vec2 abs (var_ref x))))))))))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 x))
+     ((return (expression vec3 *
+              (expression vec3 sign (var_ref x))
+              (expression vec3 -
+               (expression float *
+                (constant float (3.1415926))
+                (constant float (0.5)))
+               (expression vec3 *
+                (expression vec3 sqrt
+                 (expression vec3 -
+                  (constant float (1.0))
+                  (expression vec3 abs (var_ref x))))
+                (expression vec3 +
+                 (constant float (1.5707288))
+                 (expression vec3 *
+                  (expression vec3 abs (var_ref x))
+                  (expression vec3 +
+                   (constant float (-0.2121144))
+                   (expression vec3 *
+                    (constant float (0.0742610))
+                    (expression vec3 abs (var_ref x))))))))))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 x))
+     ((return (expression vec4 *
+              (expression vec4 sign (var_ref x))
+              (expression vec4 -
+               (expression float *
+                (constant float (3.1415926))
+                (constant float (0.5)))
+               (expression vec4 *
+                (expression vec4 sqrt
+                 (expression vec4 -
+                  (constant float (1.0))
+                  (expression vec4 abs (var_ref x))))
+                (expression vec4 +
+                 (constant float (1.5707288))
+                 (expression vec4 *
+                  (expression vec4 abs (var_ref x))
+                  (expression vec4 +
+                   (constant float (-0.2121144))
+                   (expression vec4 *
+                    (constant float (0.0742610))
+                    (expression vec4 abs (var_ref x))))))))))))
+))
diff --git a/src/glsl/builtins/ir/atan b/src/glsl/builtins/ir/atan
new file mode 100644 (file)
index 0000000..04e1898
--- /dev/null
@@ -0,0 +1,150 @@
+((function atan
+   (signature float
+     (parameters
+       (declare (in) float x))
+     ((return (call asin ((expression float *
+                          (var_ref x)
+                          (expression float rsq
+                           (expression float +
+                            (expression float *
+                             (var_ref x)
+                             (var_ref x))
+                            (constant float (1.0))))))))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 y_over_x))
+     ((return (call asin ((expression vec2 *
+                          (var_ref y_over_x)
+                          (expression vec2 rsq
+                           (expression vec2 +
+                            (expression vec2 *
+                             (var_ref y_over_x)
+                             (var_ref y_over_x))
+                            (constant float (1.0))))))))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 y_over_x))
+     ((return (call asin ((expression vec3 *
+                          (var_ref y_over_x)
+                          (expression vec3 rsq
+                           (expression vec3 +
+                            (expression vec3 *
+                             (var_ref y_over_x)
+                             (var_ref y_over_x))
+                            (constant float (1.0))))))))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 y_over_x))
+     ((return (call asin ((expression vec4 *
+                          (var_ref y_over_x)
+                          (expression vec4 rsq
+                           (expression vec4 +
+                            (expression vec4 *
+                             (var_ref y_over_x)
+                             (var_ref y_over_x))
+                            (constant float (1.0))))))))))
+
+  (signature float
+    (parameters
+      (declare (in ) float y)
+      (declare (in ) float x)
+    )
+    (
+      (declare () float r)
+      (declare ( ) float abs_retval)
+      (assign (constant bool (1)) (var_ref abs_retval)  (call abs ((var_ref x) ))
+) 
+      (if (expression bool > (var_ref abs_retval) (constant float (0.000100)) ) (
+        (declare ( ) float atan_retval)
+        (assign (constant bool (1)) (var_ref atan_retval)  (call atan ((expression float / (var_ref y) (var_ref x) ) ))
+) 
+        (assign (constant bool (1)) (var_ref r)  (var_ref atan_retval) ) 
+        (if (expression bool < (var_ref x) (constant float (0.000000)) ) (
+          (if (expression bool >= (var_ref y) (constant float (0.000000)) ) (
+            (declare ( ) float assignment_tmp)
+            (assign (constant bool (1)) (var_ref assignment_tmp)  (expression float + (var_ref r) (constant float (3.141593)) ) ) 
+            (assign (constant bool (1)) (var_ref r)  (var_ref assignment_tmp) ) 
+          )
+          (
+            (declare ( ) float assignment_tmp)
+            (assign (constant bool (1)) (var_ref assignment_tmp)  (expression float - (var_ref r) (constant float (3.141593)) ) ) 
+            (assign (constant bool (1)) (var_ref r)  (var_ref assignment_tmp) ) 
+          ))
+
+        )
+        (
+        ))
+
+      )
+      (
+        (declare () float sgn)
+        (assign (constant bool (1)) (var_ref sgn) (expression float sign (var_ref y)))
+        (assign (constant bool (1)) (var_ref r) (expression float * (var_ref sgn) (constant float (1.5707965))))
+      ))
+
+      (return (var_ref r) )
+    ))
+
+
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 y)
+       (declare (in) vec2 x))
+     ((declare () vec2 r)
+      (assign (constant bool (1))
+             (swiz x (var_ref r))
+             (call atan ((swiz x (var_ref y))
+                         (swiz x (var_ref x)))))
+      (assign (constant bool (1))
+             (swiz y (var_ref r))
+             (call atan ((swiz y (var_ref y))
+                         (swiz y (var_ref x)))))
+      (return (var_ref r))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 y)
+       (declare (in) vec3 x))
+     ((declare () vec3 r)
+      (assign (constant bool (1))
+             (swiz x (var_ref r))
+             (call atan ((swiz x (var_ref y))
+                         (swiz x (var_ref x)))))
+      (assign (constant bool (1))
+             (swiz y (var_ref r))
+             (call atan ((swiz y (var_ref y))
+                         (swiz y (var_ref x)))))
+      (assign (constant bool (1))
+             (swiz z (var_ref r))
+             (call atan ((swiz z (var_ref y))
+                         (swiz z (var_ref x)))))
+      (return (var_ref r))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 y)
+       (declare (in) vec4 x))
+     ((declare () vec4 r)
+      (assign (constant bool (1))
+             (swiz x (var_ref r))
+             (call atan ((swiz x (var_ref y))
+                         (swiz x (var_ref x)))))
+      (assign (constant bool (1))
+             (swiz y (var_ref r))
+             (call atan ((swiz y (var_ref y))
+                         (swiz y (var_ref x)))))
+      (assign (constant bool (1))
+             (swiz z (var_ref r))
+             (call atan ((swiz z (var_ref y))
+                         (swiz z (var_ref x)))))
+      (assign (constant bool (1))
+             (swiz w (var_ref r))
+             (call atan ((swiz w (var_ref y))
+                         (swiz w (var_ref x)))))
+      (return (var_ref r)))))
+
+))
diff --git a/src/glsl/builtins/ir/ceil b/src/glsl/builtins/ir/ceil
new file mode 100644 (file)
index 0000000..a26a775
--- /dev/null
@@ -0,0 +1,21 @@
+((function ceil
+   (signature float
+     (parameters
+       (declare (in) float arg0))
+     ((return (expression float ceil (var_ref arg0)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0))
+     ((return (expression vec2 ceil (var_ref arg0)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0))
+     ((return (expression vec3 ceil (var_ref arg0)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0))
+     ((return (expression vec4 ceil (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/clamp b/src/glsl/builtins/ir/clamp
new file mode 100644 (file)
index 0000000..2bdc466
--- /dev/null
@@ -0,0 +1,148 @@
+((function clamp
+   (signature float
+     (parameters
+       (declare (in) float arg0)
+       (declare (in) float arg1)
+       (declare (in) float arg2))
+     ((return (expression float max (expression float min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0)
+       (declare (in) vec2 arg1)
+       (declare (in) vec2 arg2))
+     ((return (expression vec2 max (expression vec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0)
+       (declare (in) vec3 arg1)
+       (declare (in) vec3 arg2))
+     ((return (expression vec3 max (expression vec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0)
+       (declare (in) vec4 arg1)
+       (declare (in) vec4 arg2))
+     ((return (expression vec4 max (expression vec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2  arg0)
+       (declare (in) float arg1)
+       (declare (in) float arg2))
+     ((return (expression vec2 max (expression vec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3  arg0)
+       (declare (in) float arg1)
+       (declare (in) float arg2))
+     ((return (expression vec3 max (expression vec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4  arg0)
+       (declare (in) float arg1)
+       (declare (in) float arg2))
+     ((return (expression vec4 max (expression vec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature int
+     (parameters
+       (declare (in) int arg0)
+       (declare (in) int arg1)
+       (declare (in) int arg2))
+     ((return (expression int max (expression int min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature ivec2
+     (parameters
+       (declare (in) ivec2 arg0)
+       (declare (in) ivec2 arg1)
+       (declare (in) ivec2 arg2))
+     ((return (expression ivec2 max (expression ivec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature ivec3
+     (parameters
+       (declare (in) ivec3 arg0)
+       (declare (in) ivec3 arg1)
+       (declare (in) ivec3 arg2))
+     ((return (expression ivec3 max (expression ivec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature ivec4
+     (parameters
+       (declare (in) ivec4 arg0)
+       (declare (in) ivec4 arg1)
+       (declare (in) ivec4 arg2))
+     ((return (expression ivec4 max (expression ivec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature ivec2
+     (parameters
+       (declare (in) ivec2 arg0)
+       (declare (in) int arg1)
+       (declare (in) int arg2))
+     ((return (expression ivec2 max (expression ivec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature ivec3
+     (parameters
+       (declare (in) ivec3 arg0)
+       (declare (in) int arg1)
+       (declare (in) int arg2))
+     ((return (expression ivec3 max (expression ivec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature ivec4
+     (parameters
+       (declare (in) ivec4 arg0)
+       (declare (in) int arg1)
+       (declare (in) int arg2))
+     ((return (expression ivec4 max (expression ivec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature uint
+     (parameters
+       (declare (in) uint arg0)
+       (declare (in) uint arg1)
+       (declare (in) uint arg2))
+     ((return (expression uint max (expression uint min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature uvec2
+     (parameters
+       (declare (in) uvec2 arg0)
+       (declare (in) uvec2 arg1)
+       (declare (in) uvec2 arg2))
+     ((return (expression uvec2 max (expression uvec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature uvec3
+     (parameters
+       (declare (in) uvec3 arg0)
+       (declare (in) uvec3 arg1)
+       (declare (in) uvec3 arg2))
+     ((return (expression uvec3 max (expression uvec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature uvec4
+     (parameters
+       (declare (in) uvec4 arg0)
+       (declare (in) uvec4 arg1)
+       (declare (in) uvec4 arg2))
+     ((return (expression uvec4 max (expression uvec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature uvec2
+     (parameters
+       (declare (in) uvec2 arg0)
+       (declare (in) uint arg1)
+       (declare (in) uint arg2))
+     ((return (expression uvec2 max (expression uvec2 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature uvec3
+     (parameters
+       (declare (in) uvec3 arg0)
+       (declare (in) uint arg1)
+       (declare (in) uint arg2))
+     ((return (expression uvec3 max (expression uvec3 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+
+   (signature uvec4
+     (parameters
+       (declare (in) uvec4 arg0)
+       (declare (in) uint arg1)
+       (declare (in) uint arg2))
+     ((return (expression uvec4 max (expression uvec4 min (var_ref arg0) (var_ref arg2)) (var_ref arg1)))))
+))
diff --git a/src/glsl/builtins/ir/cos b/src/glsl/builtins/ir/cos
new file mode 100644 (file)
index 0000000..88f266e
--- /dev/null
@@ -0,0 +1,21 @@
+((function cos
+   (signature float
+     (parameters
+       (declare (in) float angle))
+     ((return (expression float cos (var_ref angle)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 angle))
+     ((return (expression vec2 cos (var_ref angle)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 angle))
+     ((return (expression vec3 cos (var_ref angle)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 angle))
+     ((return (expression vec4 cos (var_ref angle)))))
+))
diff --git a/src/glsl/builtins/ir/cosh b/src/glsl/builtins/ir/cosh
new file mode 100644 (file)
index 0000000..45e0ae4
--- /dev/null
@@ -0,0 +1,30 @@
+((function cosh
+   (signature float
+     (parameters
+       (declare (in) float x))
+     ((return (expression float * (constant float (0.5))
+                (expression float +
+                 (expression float exp (var_ref x))
+                 (expression float exp (expression float neg (var_ref x))))))))
+   (signature vec2
+     (parameters
+       (declare (in) vec2 x))
+     ((return (expression vec2 * (constant vec2 (0.5))
+                (expression vec2 +
+                 (expression vec2 exp (var_ref x))
+                 (expression vec2 exp (expression vec2 neg (var_ref x))))))))
+   (signature vec3
+     (parameters
+       (declare (in) vec3 x))
+     ((return (expression vec3 * (constant vec3 (0.5))
+                (expression vec3 +
+                 (expression vec3 exp (var_ref x))
+                 (expression vec3 exp (expression vec3 neg (var_ref x))))))))
+   (signature vec4
+     (parameters
+       (declare (in) vec4 x))
+     ((return (expression vec4 * (constant vec4 (0.5))
+                (expression vec4 +
+                 (expression vec4 exp (var_ref x))
+                 (expression vec4 exp (expression vec4 neg (var_ref x))))))))
+))
diff --git a/src/glsl/builtins/ir/cross b/src/glsl/builtins/ir/cross
new file mode 100644 (file)
index 0000000..24717a2
--- /dev/null
@@ -0,0 +1,7 @@
+((function cross
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0)
+       (declare (in) vec3 arg1))
+     ((return (expression vec3 cross (var_ref arg0) (var_ref arg1)))))
+))
diff --git a/src/glsl/builtins/ir/dFdx b/src/glsl/builtins/ir/dFdx
new file mode 100644 (file)
index 0000000..30594d3
--- /dev/null
@@ -0,0 +1,21 @@
+((function dFdx
+   (signature float
+     (parameters
+       (declare (in) float p))
+     ((return (expression float dFdx (var_ref p)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 p))
+     ((return (expression vec2 dFdx (var_ref p)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 p))
+     ((return (expression vec3 dFdx (var_ref p)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 p))
+     ((return (expression vec4 dFdx (var_ref p)))))
+))
diff --git a/src/glsl/builtins/ir/dFdy b/src/glsl/builtins/ir/dFdy
new file mode 100644 (file)
index 0000000..fb5798d
--- /dev/null
@@ -0,0 +1,21 @@
+((function dFdy
+   (signature float
+     (parameters
+       (declare (in) float p))
+     ((return (expression float dFdy (var_ref p)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 p))
+     ((return (expression vec2 dFdy (var_ref p)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 p))
+     ((return (expression vec3 dFdy (var_ref p)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 p))
+     ((return (expression vec4 dFdy (var_ref p)))))
+))
diff --git a/src/glsl/builtins/ir/degrees b/src/glsl/builtins/ir/degrees
new file mode 100644 (file)
index 0000000..dc0d7b9
--- /dev/null
@@ -0,0 +1,21 @@
+((function degrees
+   (signature float
+     (parameters
+       (declare (in) float arg0))
+     ((return (expression float * (var_ref arg0) (constant float (57.295780))))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0))
+     ((return (expression vec2 * (var_ref arg0) (constant float (57.295780))))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0))
+     ((return (expression vec3 * (var_ref arg0) (constant float (57.295780))))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0))
+     ((return (expression vec4 * (var_ref arg0) (constant float (57.295780))))))
+))
diff --git a/src/glsl/builtins/ir/distance b/src/glsl/builtins/ir/distance
new file mode 100644 (file)
index 0000000..a2309c4
--- /dev/null
@@ -0,0 +1,33 @@
+((function distance
+   (signature float
+     (parameters
+       (declare (in) float p0)
+       (declare (in) float p1))
+     ((declare () float p)
+      (assign (constant bool (1)) (var_ref p) (expression float - (var_ref p0) (var_ref p1)))
+      (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))
+
+   (signature float
+     (parameters
+       (declare (in) vec2 p0)
+       (declare (in) vec2 p1))
+     ((declare () vec2 p)
+      (assign (constant bool (1)) (var_ref p) (expression vec2 - (var_ref p0) (var_ref p1)))
+      (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))
+
+   (signature float
+     (parameters
+       (declare (in) vec3 p0)
+       (declare (in) vec3 p1))
+     ((declare () vec3 p)
+      (assign (constant bool (1)) (var_ref p) (expression vec3 - (var_ref p0) (var_ref p1)))
+      (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))
+
+   (signature float
+     (parameters
+       (declare (in) vec4 p0)
+       (declare (in) vec4 p1))
+     ((declare () vec4 p)
+      (assign (constant bool (1)) (var_ref p) (expression vec4 - (var_ref p0) (var_ref p1)))
+      (return (expression float sqrt (expression float dot (var_ref p) (var_ref p))))))
+))
diff --git a/src/glsl/builtins/ir/dot b/src/glsl/builtins/ir/dot
new file mode 100644 (file)
index 0000000..a91a6d2
--- /dev/null
@@ -0,0 +1,25 @@
+((function dot
+   (signature float
+     (parameters
+       (declare (in) float arg0)
+       (declare (in) float arg1))
+     ((return (expression float dot (var_ref arg0) (var_ref arg1)))))
+
+   (signature float
+     (parameters
+       (declare (in) vec2 arg0)
+       (declare (in) vec2 arg1))
+     ((return (expression float dot (var_ref arg0) (var_ref arg1)))))
+
+   (signature float
+     (parameters
+       (declare (in) vec3 arg0)
+       (declare (in) vec3 arg1))
+     ((return (expression float dot (var_ref arg0) (var_ref arg1)))))
+
+   (signature float
+     (parameters
+       (declare (in) vec4 arg0)
+       (declare (in) vec4 arg1))
+     ((return (expression float dot (var_ref arg0) (var_ref arg1)))))
+))
diff --git a/src/glsl/builtins/ir/equal b/src/glsl/builtins/ir/equal
new file mode 100644 (file)
index 0000000..c394776
--- /dev/null
@@ -0,0 +1,121 @@
+((function equal
+   (signature bvec2
+     (parameters
+       (declare (in) vec2 arg0)
+       (declare (in) vec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) vec3 arg0)
+       (declare (in) vec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) vec4 arg0)
+       (declare (in) vec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool == (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec2
+     (parameters
+       (declare (in) bvec2 arg0)
+       (declare (in) bvec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) bvec3 arg0)
+       (declare (in) bvec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) bvec4 arg0)
+       (declare (in) bvec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool == (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+      (return (var_ref temp))))
+
+   (signature bvec2
+     (parameters
+       (declare (in) ivec2 arg0)
+       (declare (in) ivec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) ivec3 arg0)
+       (declare (in) ivec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) ivec4 arg0)
+       (declare (in) ivec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool == (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec2
+     (parameters
+       (declare (in) uvec2 arg0)
+       (declare (in) uvec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) uvec3 arg0)
+       (declare (in) uvec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) uvec4 arg0)
+       (declare (in) uvec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool == (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool == (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool == (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool == (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+))
diff --git a/src/glsl/builtins/ir/exp b/src/glsl/builtins/ir/exp
new file mode 100644 (file)
index 0000000..a73bd6a
--- /dev/null
@@ -0,0 +1,21 @@
+((function exp
+   (signature float
+     (parameters
+       (declare (in) float arg0))
+     ((return (expression float exp (var_ref arg0)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0))
+     ((return (expression vec2 exp (var_ref arg0)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0))
+     ((return (expression vec3 exp (var_ref arg0)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0))
+     ((return (expression vec4 exp (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/exp2 b/src/glsl/builtins/ir/exp2
new file mode 100644 (file)
index 0000000..a842d3f
--- /dev/null
@@ -0,0 +1,21 @@
+((function exp2
+   (signature float
+     (parameters
+       (declare (in) float arg0))
+     ((return (expression float exp2 (var_ref arg0)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0))
+     ((return (expression vec2 exp2 (var_ref arg0)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0))
+     ((return (expression vec3 exp2 (var_ref arg0)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0))
+     ((return (expression vec4 exp2 (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/faceforward b/src/glsl/builtins/ir/faceforward
new file mode 100644 (file)
index 0000000..d170397
--- /dev/null
@@ -0,0 +1,37 @@
+((function faceforward
+   (signature float
+     (parameters
+       (declare (in) float N)
+       (declare (in) float I)
+       (declare (in) float Nref))
+     ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))
+          ((return (var_ref N)))
+         ((return (expression float neg (var_ref N)))))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 N)
+       (declare (in) vec2 I)
+       (declare (in) vec2 Nref))
+     ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))
+          ((return (var_ref N)))
+         ((return (expression vec2 neg (var_ref N)))))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 N)
+       (declare (in) vec3 I)
+       (declare (in) vec3 Nref))
+     ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))
+          ((return (var_ref N)))
+         ((return (expression vec3 neg (var_ref N)))))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 N)
+       (declare (in) vec4 I)
+       (declare (in) vec4 Nref))
+     ((if (expression bool < (expression float dot (var_ref Nref) (var_ref I)) (constant float (0)))
+          ((return (var_ref N)))
+         ((return (expression vec4 neg (var_ref N)))))))
+))
diff --git a/src/glsl/builtins/ir/floor b/src/glsl/builtins/ir/floor
new file mode 100644 (file)
index 0000000..8dd8052
--- /dev/null
@@ -0,0 +1,21 @@
+((function floor
+   (signature float
+     (parameters
+       (declare (in) float arg0))
+     ((return (expression float floor (var_ref arg0)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0))
+     ((return (expression vec2 floor (var_ref arg0)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0))
+     ((return (expression vec3 floor (var_ref arg0)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0))
+     ((return (expression vec4 floor (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/fract b/src/glsl/builtins/ir/fract
new file mode 100644 (file)
index 0000000..3f0763d
--- /dev/null
@@ -0,0 +1,22 @@
+((function fract
+   (signature float
+     (parameters
+       (declare (in) float x))
+     ((return (expression float fract (var_ref x)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 x))
+     ((return (expression vec2 fract (var_ref x)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 x))
+     ((return (expression vec3 fract (var_ref x)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 x))
+     ((return (expression vec4 fract (var_ref x)))))
+))
+
diff --git a/src/glsl/builtins/ir/ftransform b/src/glsl/builtins/ir/ftransform
new file mode 100644 (file)
index 0000000..9ca63dc
--- /dev/null
@@ -0,0 +1,9 @@
+((declare (uniform) mat4 gl_ModelViewProjectionMatrix)
+ (declare (in) vec4 gl_Vertex)
+ (function ftransform
+   (signature vec4
+     (parameters)
+    ((return (expression vec4 *
+             (var_ref gl_ModelViewProjectionMatrix)
+             (var_ref gl_Vertex)))))
+))
diff --git a/src/glsl/builtins/ir/fwidth b/src/glsl/builtins/ir/fwidth
new file mode 100644 (file)
index 0000000..385e05d
--- /dev/null
@@ -0,0 +1,29 @@
+((function fwidth
+   (signature float
+     (parameters
+       (declare (in) float p))
+     ((return (expression float +
+                (expression float abs (expression float dFdx (var_ref p)))
+                (expression float abs (expression float dFdy (var_ref p)))))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 p))
+     ((return (expression vec2 +
+                (expression vec2 abs (expression vec2 dFdx (var_ref p)))
+                (expression vec2 abs (expression vec2 dFdy (var_ref p)))))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 p))
+     ((return (expression vec3 +
+                (expression vec3 abs (expression vec3 dFdx (var_ref p)))
+                (expression vec3 abs (expression vec3 dFdy (var_ref p)))))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 p))
+     ((return (expression vec4 +
+                (expression vec4 abs (expression vec4 dFdx (var_ref p)))
+                (expression vec4 abs (expression vec4 dFdy (var_ref p)))))))
+))
diff --git a/src/glsl/builtins/ir/greaterThan b/src/glsl/builtins/ir/greaterThan
new file mode 100644 (file)
index 0000000..ce7bd29
--- /dev/null
@@ -0,0 +1,91 @@
+((function greaterThan
+   (signature bvec2
+     (parameters
+       (declare (in) vec2 arg0)
+       (declare (in) vec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) vec3 arg0)
+       (declare (in) vec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) vec4 arg0)
+       (declare (in) vec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool > (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec2
+     (parameters
+       (declare (in) ivec2 arg0)
+       (declare (in) ivec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) ivec3 arg0)
+       (declare (in) ivec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) ivec4 arg0)
+       (declare (in) ivec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool > (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec2
+     (parameters
+       (declare (in) uvec2 arg0)
+       (declare (in) uvec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) uvec3 arg0)
+       (declare (in) uvec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) uvec4 arg0)
+       (declare (in) uvec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool > (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool > (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool > (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool > (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+))
diff --git a/src/glsl/builtins/ir/greaterThanEqual b/src/glsl/builtins/ir/greaterThanEqual
new file mode 100644 (file)
index 0000000..de1a9f9
--- /dev/null
@@ -0,0 +1,91 @@
+((function greaterThanEqual
+   (signature bvec2
+     (parameters
+       (declare (in) vec2 arg0)
+       (declare (in) vec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) vec3 arg0)
+       (declare (in) vec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) vec4 arg0)
+       (declare (in) vec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool >= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec2
+     (parameters
+       (declare (in) ivec2 arg0)
+       (declare (in) ivec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) ivec3 arg0)
+       (declare (in) ivec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) ivec4 arg0)
+       (declare (in) ivec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool >= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec2
+     (parameters
+       (declare (in) uvec2 arg0)
+       (declare (in) uvec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) uvec3 arg0)
+       (declare (in) uvec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) uvec4 arg0)
+       (declare (in) uvec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool >= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool >= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool >= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool >= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+))
diff --git a/src/glsl/builtins/ir/inversesqrt b/src/glsl/builtins/ir/inversesqrt
new file mode 100644 (file)
index 0000000..5b66d2b
--- /dev/null
@@ -0,0 +1,21 @@
+((function inversesqrt
+   (signature float
+     (parameters
+       (declare (in) float arg0))
+     ((return (expression float rsq (var_ref arg0)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0))
+     ((return (expression vec2 rsq (var_ref arg0)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0))
+     ((return (expression vec3 rsq (var_ref arg0)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0))
+     ((return (expression vec4 rsq (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/length b/src/glsl/builtins/ir/length
new file mode 100644 (file)
index 0000000..89ff7f3
--- /dev/null
@@ -0,0 +1,21 @@
+((function length
+   (signature float
+     (parameters
+       (declare (in) float arg0))
+     ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))
+
+   (signature float
+     (parameters
+       (declare (in) vec2 arg0))
+     ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))
+
+   (signature float
+     (parameters
+       (declare (in) vec3 arg0))
+     ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))
+
+   (signature float
+     (parameters
+       (declare (in) vec4 arg0))
+     ((return (expression float sqrt (expression float dot (var_ref arg0) (var_ref arg0))))))
+))
diff --git a/src/glsl/builtins/ir/lessThan b/src/glsl/builtins/ir/lessThan
new file mode 100644 (file)
index 0000000..52113b7
--- /dev/null
@@ -0,0 +1,91 @@
+((function lessThan
+   (signature bvec2
+     (parameters
+       (declare (in) vec2 arg0)
+       (declare (in) vec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) vec3 arg0)
+       (declare (in) vec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) vec4 arg0)
+       (declare (in) vec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool < (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec2
+     (parameters
+       (declare (in) ivec2 arg0)
+       (declare (in) ivec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) ivec3 arg0)
+       (declare (in) ivec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) ivec4 arg0)
+       (declare (in) ivec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool < (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec2
+     (parameters
+       (declare (in) uvec2 arg0)
+       (declare (in) uvec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) uvec3 arg0)
+       (declare (in) uvec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) uvec4 arg0)
+       (declare (in) uvec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool < (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool < (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool < (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool < (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+))
diff --git a/src/glsl/builtins/ir/lessThanEqual b/src/glsl/builtins/ir/lessThanEqual
new file mode 100644 (file)
index 0000000..4b240be
--- /dev/null
@@ -0,0 +1,91 @@
+((function lessThanEqual
+   (signature bvec2
+     (parameters
+       (declare (in) vec2 arg0)
+       (declare (in) vec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) vec3 arg0)
+       (declare (in) vec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) vec4 arg0)
+       (declare (in) vec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool <= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec2
+     (parameters
+       (declare (in) ivec2 arg0)
+       (declare (in) ivec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) ivec3 arg0)
+       (declare (in) ivec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) ivec4 arg0)
+       (declare (in) ivec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool <= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec2
+     (parameters
+       (declare (in) uvec2 arg0)
+       (declare (in) uvec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) uvec3 arg0)
+       (declare (in) uvec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) uvec4 arg0)
+       (declare (in) uvec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool <= (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool <= (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool <= (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool <= (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+))
diff --git a/src/glsl/builtins/ir/log b/src/glsl/builtins/ir/log
new file mode 100644 (file)
index 0000000..d168abb
--- /dev/null
@@ -0,0 +1,21 @@
+((function log
+   (signature float
+     (parameters
+       (declare (in) float arg0))
+     ((return (expression float log (var_ref arg0)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0))
+     ((return (expression vec2 log (var_ref arg0)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0))
+     ((return (expression vec3 log (var_ref arg0)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0))
+     ((return (expression vec4 log (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/log2 b/src/glsl/builtins/ir/log2
new file mode 100644 (file)
index 0000000..b96c627
--- /dev/null
@@ -0,0 +1,21 @@
+((function log2
+   (signature float
+     (parameters
+       (declare (in) float arg0))
+     ((return (expression float log2 (var_ref arg0)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0))
+     ((return (expression vec2 log2 (var_ref arg0)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0))
+     ((return (expression vec3 log2 (var_ref arg0)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0))
+     ((return (expression vec4 log2 (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/matrixCompMult b/src/glsl/builtins/ir/matrixCompMult
new file mode 100644 (file)
index 0000000..538da18
--- /dev/null
@@ -0,0 +1,91 @@
+((function matrixCompMult
+   (signature mat2
+     (parameters
+       (declare (in) mat2 x)
+       (declare (in) mat2 y))
+     ((declare () mat2 z)
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec2 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec2 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) 
+(return (var_ref z))))
+
+   (signature mat3
+     (parameters
+       (declare (in) mat3 x)
+       (declare (in) mat3 y))
+     ((declare () mat3 z)
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec3 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec3 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2)))  (expression vec3 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) 
+(return (var_ref z))))
+
+   (signature mat4
+     (parameters
+       (declare (in) mat4 x)
+       (declare (in) mat4 y))
+     ((declare () mat4 z)
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec4 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec4 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2)))  (expression vec4 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (3)))  (expression vec4 * (array_ref (var_ref x) (constant int (3))) (array_ref (var_ref y) (constant int (3))))) 
+(return (var_ref z))))
+
+   (signature mat2x3
+     (parameters
+       (declare (in) mat2x3 x)
+       (declare (in) mat2x3 y))
+     ((declare () mat2x3 z)
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec3 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec3 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) 
+(return (var_ref z))))
+
+   (signature mat3x2
+     (parameters
+       (declare (in) mat3x2 x)
+       (declare (in) mat3x2 y))
+     ((declare () mat3x2 z)
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec2 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec2 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2)))  (expression vec2 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) 
+(return (var_ref z))))
+
+   (signature mat2x4
+     (parameters
+       (declare (in) mat2x4 x)
+       (declare (in) mat2x4 y))
+     ((declare () mat2x4 z)
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec4 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec4 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) 
+(return (var_ref z))))
+
+   (signature mat4x2
+     (parameters
+       (declare (in) mat4x2 x)
+       (declare (in) mat4x2 y))
+     ((declare () mat4x2 z)
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec2 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec2 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2)))  (expression vec2 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (3)))  (expression vec2 * (array_ref (var_ref x) (constant int (3))) (array_ref (var_ref y) (constant int (3))))) 
+(return (var_ref z))))
+
+   (signature mat3x4
+     (parameters
+       (declare (in) mat3x4 x)
+       (declare (in) mat3x4 y))
+     ((declare () mat3x4 z)
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec4 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec4 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2)))  (expression vec4 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) 
+(return (var_ref z))))
+
+   (signature mat4x3
+     (parameters
+       (declare (in) mat4x3 x)
+       (declare (in) mat4x3 y))
+     ((declare () mat4x3 z)
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (0)))  (expression vec3 * (array_ref (var_ref x) (constant int (0))) (array_ref (var_ref y) (constant int (0))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (1)))  (expression vec3 * (array_ref (var_ref x) (constant int (1))) (array_ref (var_ref y) (constant int (1))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (2)))  (expression vec3 * (array_ref (var_ref x) (constant int (2))) (array_ref (var_ref y) (constant int (2))))) 
+      (assign (constant bool (1)) (array_ref (var_ref z) (constant int (3)))  (expression vec3 * (array_ref (var_ref x) (constant int (3))) (array_ref (var_ref y) (constant int (3))))) 
+(return (var_ref z))))
+))
diff --git a/src/glsl/builtins/ir/max b/src/glsl/builtins/ir/max
new file mode 100644 (file)
index 0000000..2b5a028
--- /dev/null
@@ -0,0 +1,127 @@
+((function max
+   (signature float
+     (parameters
+       (declare (in) float arg0)
+       (declare (in) float arg1))
+     ((return (expression float max (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0)
+       (declare (in) vec2 arg1))
+     ((return (expression vec2 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0)
+       (declare (in) vec3 arg1))
+     ((return (expression vec3 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0)
+       (declare (in) vec4 arg1))
+     ((return (expression vec4 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2  arg0)
+       (declare (in) float arg1))
+     ((return (expression vec2 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3  arg0)
+       (declare (in) float arg1))
+     ((return (expression vec3 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4  arg0)
+       (declare (in) float arg1))
+     ((return (expression vec4 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature int
+     (parameters
+       (declare (in) int arg0)
+       (declare (in) int arg1))
+     ((return (expression int max (var_ref arg0) (var_ref arg1)))))
+
+   (signature ivec2
+     (parameters
+       (declare (in) ivec2 arg0)
+       (declare (in) ivec2 arg1))
+     ((return (expression ivec2 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature ivec3
+     (parameters
+       (declare (in) ivec3 arg0)
+       (declare (in) ivec3 arg1))
+     ((return (expression ivec3 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature ivec4
+     (parameters
+       (declare (in) ivec4 arg0)
+       (declare (in) ivec4 arg1))
+     ((return (expression ivec4 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature ivec2
+     (parameters
+       (declare (in) ivec2  arg0)
+       (declare (in) int arg1))
+     ((return (expression ivec2 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature ivec3
+     (parameters
+       (declare (in) ivec3  arg0)
+       (declare (in) int arg1))
+     ((return (expression ivec3 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature ivec4
+     (parameters
+       (declare (in) ivec4  arg0)
+       (declare (in) int arg1))
+     ((return (expression ivec4 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature uint
+     (parameters
+       (declare (in) uint arg0)
+       (declare (in) uint arg1))
+     ((return (expression uint max (var_ref arg0) (var_ref arg1)))))
+
+   (signature uvec2
+     (parameters
+       (declare (in) uvec2 arg0)
+       (declare (in) uvec2 arg1))
+     ((return (expression uvec2 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature uvec3
+     (parameters
+       (declare (in) uvec3 arg0)
+       (declare (in) uvec3 arg1))
+     ((return (expression uvec3 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature uvec4
+     (parameters
+       (declare (in) uvec4 arg0)
+       (declare (in) uvec4 arg1))
+     ((return (expression uvec4 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature uvec2
+     (parameters
+       (declare (in) uvec2  arg0)
+       (declare (in) uint arg1))
+     ((return (expression uvec2 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature uvec3
+     (parameters
+       (declare (in) uvec3  arg0)
+       (declare (in) uint arg1))
+     ((return (expression uvec3 max (var_ref arg0) (var_ref arg1)))))
+
+   (signature uvec4
+     (parameters
+       (declare (in) uvec4  arg0)
+       (declare (in) uint arg1))
+     ((return (expression uvec4 max (var_ref arg0) (var_ref arg1)))))
+))
diff --git a/src/glsl/builtins/ir/min b/src/glsl/builtins/ir/min
new file mode 100644 (file)
index 0000000..2deef11
--- /dev/null
@@ -0,0 +1,127 @@
+((function min
+   (signature float
+     (parameters
+       (declare (in) float arg0)
+       (declare (in) float arg1))
+     ((return (expression float min (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0)
+       (declare (in) vec2 arg1))
+     ((return (expression vec2 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0)
+       (declare (in) vec3 arg1))
+     ((return (expression vec3 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0)
+       (declare (in) vec4 arg1))
+     ((return (expression vec4 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2  arg0)
+       (declare (in) float arg1))
+     ((return (expression vec2 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3  arg0)
+       (declare (in) float arg1))
+     ((return (expression vec3 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4  arg0)
+       (declare (in) float arg1))
+     ((return (expression vec4 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature int
+     (parameters
+       (declare (in) int arg0)
+       (declare (in) int arg1))
+     ((return (expression int min (var_ref arg0) (var_ref arg1)))))
+
+   (signature ivec2
+     (parameters
+       (declare (in) ivec2 arg0)
+       (declare (in) ivec2 arg1))
+     ((return (expression ivec2 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature ivec3
+     (parameters
+       (declare (in) ivec3 arg0)
+       (declare (in) ivec3 arg1))
+     ((return (expression ivec3 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature ivec4
+     (parameters
+       (declare (in) ivec4 arg0)
+       (declare (in) ivec4 arg1))
+     ((return (expression ivec4 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature ivec2
+     (parameters
+       (declare (in) ivec2  arg0)
+       (declare (in) int arg1))
+     ((return (expression ivec2 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature ivec3
+     (parameters
+       (declare (in) ivec3  arg0)
+       (declare (in) int arg1))
+     ((return (expression ivec3 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature ivec4
+     (parameters
+       (declare (in) ivec4  arg0)
+       (declare (in) int arg1))
+     ((return (expression ivec4 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature uint
+     (parameters
+       (declare (in) uint arg0)
+       (declare (in) uint arg1))
+     ((return (expression uint min (var_ref arg0) (var_ref arg1)))))
+
+   (signature uvec2
+     (parameters
+       (declare (in) uvec2 arg0)
+       (declare (in) uvec2 arg1))
+     ((return (expression uvec2 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature uvec3
+     (parameters
+       (declare (in) uvec3 arg0)
+       (declare (in) uvec3 arg1))
+     ((return (expression uvec3 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature uvec4
+     (parameters
+       (declare (in) uvec4 arg0)
+       (declare (in) uvec4 arg1))
+     ((return (expression uvec4 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature uvec2
+     (parameters
+       (declare (in) uvec2  arg0)
+       (declare (in) uint arg1))
+     ((return (expression uvec2 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature uvec3
+     (parameters
+       (declare (in) uvec3  arg0)
+       (declare (in) uint arg1))
+     ((return (expression uvec3 min (var_ref arg0) (var_ref arg1)))))
+
+   (signature uvec4
+     (parameters
+       (declare (in) uvec4  arg0)
+       (declare (in) uint arg1))
+     ((return (expression uvec4 min (var_ref arg0) (var_ref arg1)))))
+))
diff --git a/src/glsl/builtins/ir/mix b/src/glsl/builtins/ir/mix
new file mode 100644 (file)
index 0000000..6bc6f0a
--- /dev/null
@@ -0,0 +1,88 @@
+((function mix
+   (signature float
+     (parameters
+       (declare (in) float arg0)
+       (declare (in) float arg1)
+       (declare (in) float arg2))
+     ((return (expression float + (expression float * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression float * (var_ref arg1) (var_ref arg2))))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0)
+       (declare (in) vec2 arg1)
+       (declare (in) vec2 arg2))
+     ((return (expression vec2 + (expression vec2 * (var_ref arg0) (expression vec2 - (constant float (1.000000)) (var_ref arg2))) (expression vec2 * (var_ref arg1) (var_ref arg2))))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0)
+       (declare (in) vec3 arg1)
+       (declare (in) vec3 arg2))
+     ((return (expression vec3 + (expression vec3 * (var_ref arg0) (expression vec3 - (constant float (1.000000)) (var_ref arg2))) (expression vec3 * (var_ref arg1) (var_ref arg2))))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0)
+       (declare (in) vec4 arg1)
+       (declare (in) vec4 arg2))
+     ((return (expression vec4 + (expression vec4 * (var_ref arg0) (expression vec4 - (constant float (1.000000)) (var_ref arg2))) (expression vec4 * (var_ref arg1) (var_ref arg2))))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0)
+       (declare (in) vec2 arg1)
+       (declare (in) float arg2))
+     ((return (expression vec2 + (expression vec2 * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression vec2 * (var_ref arg1) (var_ref arg2))))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0)
+       (declare (in) vec3 arg1)
+       (declare (in) float arg2))
+     ((return (expression vec3 + (expression vec3 * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression vec3 * (var_ref arg1) (var_ref arg2))))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0)
+       (declare (in) vec4 arg1)
+       (declare (in) float arg2))
+     ((return (expression vec4 + (expression vec4 * (var_ref arg0) (expression float - (constant float (1.000000)) (var_ref arg2))) (expression vec4 * (var_ref arg1) (var_ref arg2))))))
+
+   (signature float
+     (parameters
+       (declare (in) float v1)
+       (declare (in) float v2)
+       (declare (in) bool  a))
+     ((assign (var_ref a) (var_ref v1) (var_ref v2))
+      (return (var_ref v1))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 v1)
+       (declare (in) vec2 v2)
+       (declare (in) bvec2 a))
+     ((assign (swiz x (var_ref a)) (swiz x (var_ref v1)) (swiz x (var_ref v2)))
+      (assign (swiz y (var_ref a)) (swiz y (var_ref v1)) (swiz y (var_ref v2)))
+      (return (var_ref v1))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 v1)
+       (declare (in) vec3 v2)
+       (declare (in) bvec3 a))
+     ((assign (swiz x (var_ref a)) (swiz x (var_ref v1)) (swiz x (var_ref v2)))
+      (assign (swiz y (var_ref a)) (swiz y (var_ref v1)) (swiz y (var_ref v2)))
+      (assign (swiz z (var_ref a)) (swiz z (var_ref v1)) (swiz z (var_ref v2)))
+      (return (var_ref v1))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 v1)
+       (declare (in) vec4 v2)
+       (declare (in) bvec4 a))
+     ((assign (swiz x (var_ref a)) (swiz x (var_ref v1)) (swiz x (var_ref v2)))
+      (assign (swiz y (var_ref a)) (swiz y (var_ref v1)) (swiz y (var_ref v2)))
+      (assign (swiz z (var_ref a)) (swiz z (var_ref v1)) (swiz z (var_ref v2)))
+      (assign (swiz w (var_ref a)) (swiz w (var_ref v1)) (swiz w (var_ref v2)))
+      (return (var_ref v1))))
+))
diff --git a/src/glsl/builtins/ir/mod b/src/glsl/builtins/ir/mod
new file mode 100644 (file)
index 0000000..aeaea24
--- /dev/null
@@ -0,0 +1,43 @@
+((function mod
+   (signature float
+     (parameters
+       (declare (in) float arg0)
+       (declare (in) float arg1))
+     ((return (expression float % (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0)
+       (declare (in) vec2 arg1))
+     ((return (expression vec2 % (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0)
+       (declare (in) vec3 arg1))
+     ((return (expression vec3 % (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0)
+       (declare (in) vec4 arg1))
+     ((return (expression vec4 % (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2  arg0)
+       (declare (in) float arg1))
+     ((return (expression vec2 % (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3  arg0)
+       (declare (in) float arg1))
+     ((return (expression vec3 % (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4  arg0)
+       (declare (in) float arg1))
+     ((return (expression vec4 % (var_ref arg0) (var_ref arg1)))))
+))
diff --git a/src/glsl/builtins/ir/noise1 b/src/glsl/builtins/ir/noise1
new file mode 100644 (file)
index 0000000..eb7be35
--- /dev/null
@@ -0,0 +1,18 @@
+((function noise1
+   (signature float
+     (parameters
+       (declare (in) float x))
+     ((return (constant float (0)))))
+   (signature float
+     (parameters
+       (declare (in) vec2 x))
+     ((return (constant float (0)))))
+   (signature float
+     (parameters
+       (declare (in) vec3 x))
+     ((return (constant float (0)))))
+   (signature float
+     (parameters
+       (declare (in) vec4 x))
+     ((return (constant float (0)))))
+))
diff --git a/src/glsl/builtins/ir/noise2 b/src/glsl/builtins/ir/noise2
new file mode 100644 (file)
index 0000000..ae4443a
--- /dev/null
@@ -0,0 +1,18 @@
+((function noise2
+   (signature vec2
+     (parameters
+       (declare (in) float x))
+     ((return (constant vec2 (0 0)))))
+   (signature vec2
+     (parameters
+       (declare (in) vec2 x))
+     ((return (constant vec2 (0 0)))))
+   (signature vec2
+     (parameters
+       (declare (in) vec3 x))
+     ((return (constant vec2 (0 0)))))
+   (signature vec2
+     (parameters
+       (declare (in) vec4 x))
+     ((return (constant vec2 (0 0)))))
+))
diff --git a/src/glsl/builtins/ir/noise3 b/src/glsl/builtins/ir/noise3
new file mode 100644 (file)
index 0000000..30d9681
--- /dev/null
@@ -0,0 +1,18 @@
+((function noise3
+   (signature vec3
+     (parameters
+       (declare (in) float x))
+     ((return (constant vec3 (0 0 0)))))
+   (signature vec3
+     (parameters
+       (declare (in) vec2 x))
+     ((return (constant vec3 (0 0 0)))))
+   (signature vec3
+     (parameters
+       (declare (in) vec3 x))
+     ((return (constant vec3 (0 0 0)))))
+   (signature vec3
+     (parameters
+       (declare (in) vec4 x))
+     ((return (constant vec3 (0 0 0)))))
+))
diff --git a/src/glsl/builtins/ir/noise4 b/src/glsl/builtins/ir/noise4
new file mode 100644 (file)
index 0000000..913bef2
--- /dev/null
@@ -0,0 +1,18 @@
+((function noise4
+   (signature vec4
+     (parameters
+       (declare (in) float x))
+     ((return (constant vec4 (0 0 0 0)))))
+   (signature vec4
+     (parameters
+       (declare (in) vec2 x))
+     ((return (constant vec4 (0 0 0 0)))))
+   (signature vec4
+     (parameters
+       (declare (in) vec3 x))
+     ((return (constant vec4 (0 0 0 0)))))
+   (signature vec4
+     (parameters
+       (declare (in) vec4 x))
+     ((return (constant vec4 (0 0 0 0)))))
+))
diff --git a/src/glsl/builtins/ir/normalize b/src/glsl/builtins/ir/normalize
new file mode 100644 (file)
index 0000000..be88a98
--- /dev/null
@@ -0,0 +1,21 @@
+((function normalize
+   (signature float
+     (parameters
+       (declare (in) float arg0))
+     ((return (expression float * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0))
+     ((return (expression vec2 * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0))
+     ((return (expression vec3 * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0))
+     ((return (expression vec4 * (var_ref arg0) (expression float rsq (expression float dot (var_ref arg0) (var_ref arg0)))))))
+))
diff --git a/src/glsl/builtins/ir/not b/src/glsl/builtins/ir/not
new file mode 100644 (file)
index 0000000..b696b06
--- /dev/null
@@ -0,0 +1,16 @@
+((function not
+   (signature bvec2
+     (parameters
+       (declare (in) bvec2 arg0))
+     ((return (expression bvec2 ! (var_ref arg0)))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) bvec3 arg0))
+     ((return (expression bvec3 ! (var_ref arg0)))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) bvec4 arg0))
+     ((return (expression bvec4 ! (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/notEqual b/src/glsl/builtins/ir/notEqual
new file mode 100644 (file)
index 0000000..eeeda79
--- /dev/null
@@ -0,0 +1,121 @@
+((function notEqual
+   (signature bvec2
+     (parameters
+       (declare (in) vec2 arg0)
+       (declare (in) vec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) vec3 arg0)
+       (declare (in) vec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) vec4 arg0)
+       (declare (in) vec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool != (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+      (return (var_ref temp))))
+
+   (signature bvec2
+     (parameters
+       (declare (in) bvec2 arg0)
+       (declare (in) bvec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) bvec3 arg0)
+       (declare (in) bvec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) bvec4 arg0)
+       (declare (in) bvec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool != (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+      (return (var_ref temp))))
+
+   (signature bvec2
+     (parameters
+       (declare (in) ivec2 arg0)
+       (declare (in) ivec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) ivec3 arg0)
+       (declare (in) ivec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) ivec4 arg0)
+       (declare (in) ivec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1))))
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1))))
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1))))
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool != (swiz w (var_ref arg0))(swiz w (var_ref arg1))))
+      (return (var_ref temp))))
+
+   (signature bvec2
+     (parameters
+       (declare (in) uvec2 arg0)
+       (declare (in) uvec2 arg1))
+     ((declare () bvec2 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec3
+     (parameters
+       (declare (in) uvec3 arg0)
+       (declare (in) uvec3 arg1))
+     ((declare () bvec3 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (return (var_ref temp))))
+
+   (signature bvec4
+     (parameters
+       (declare (in) uvec4 arg0)
+       (declare (in) uvec4 arg1))
+     ((declare () bvec4 temp)
+      (assign (constant bool (1)) (swiz x (var_ref temp)) (expression bool != (swiz x (var_ref arg0))(swiz x (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz y (var_ref temp)) (expression bool != (swiz y (var_ref arg0))(swiz y (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz z (var_ref temp)) (expression bool != (swiz z (var_ref arg0))(swiz z (var_ref arg1)))) 
+      (assign (constant bool (1)) (swiz w (var_ref temp)) (expression bool != (swiz w (var_ref arg0))(swiz w (var_ref arg1)))) 
+      (return (var_ref temp))))
+))
diff --git a/src/glsl/builtins/ir/outerProduct b/src/glsl/builtins/ir/outerProduct
new file mode 100644 (file)
index 0000000..69ae741
--- /dev/null
@@ -0,0 +1,92 @@
+((function outerProduct
+   (signature mat2
+     (parameters
+       (declare (in) vec2 u)
+       (declare (in) vec2 v))
+     ((declare () mat2 m)
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref u) (swiz x (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref u) (swiz y (var_ref v))))
+      (return (var_ref m))))
+
+   (signature mat2x3
+     (parameters
+       (declare (in) vec3 u)
+       (declare (in) vec2 v))
+     ((declare () mat2x3 m)
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref u) (swiz x (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref u) (swiz y (var_ref v))))
+      (return (var_ref m))))
+
+   (signature mat2x4
+     (parameters
+       (declare (in) vec4 u)
+       (declare (in) vec2 v))
+     ((declare () mat2x4 m)
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref u) (swiz x (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref u) (swiz y (var_ref v))))
+      (return (var_ref m))))
+
+   (signature mat3x2
+     (parameters
+       (declare (in) vec2 u)
+       (declare (in) vec3 v))
+     ((declare () mat3x2 m)
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref u) (swiz x (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref u) (swiz y (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec2 * (var_ref u) (swiz z (var_ref v))))
+      (return (var_ref m))
+ ))
+
+   (signature mat3
+     (parameters
+       (declare (in) vec3 u)
+       (declare (in) vec3 v))
+     ((declare () mat3 m)
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref u) (swiz x (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref u) (swiz y (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec3 * (var_ref u) (swiz z (var_ref v))))
+      (return (var_ref m))))
+
+   (signature mat3x4
+     (parameters
+       (declare (in) vec4 u)
+       (declare (in) vec3 v))
+     ((declare () mat3x4 m)
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref u) (swiz x (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref u) (swiz y (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec4 * (var_ref u) (swiz z (var_ref v))))
+      (return (var_ref m))))
+
+   (signature mat4x2
+     (parameters
+       (declare (in) vec2 u)
+       (declare (in) vec4 v))
+     ((declare () mat4x2 m)
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec2 * (var_ref u) (swiz x (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec2 * (var_ref u) (swiz y (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec2 * (var_ref u) (swiz z (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec2 * (var_ref u) (swiz w (var_ref v))))
+      (return (var_ref m))))
+
+   (signature mat4x3
+     (parameters
+       (declare (in) vec3 u)
+       (declare (in) vec4 v))
+     ((declare () mat4x3 m)
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec3 * (var_ref u) (swiz x (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec3 * (var_ref u) (swiz y (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec3 * (var_ref u) (swiz z (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec3 * (var_ref u) (swiz w (var_ref v))))
+      (return (var_ref m))))
+
+   (signature mat4
+     (parameters
+       (declare (in) vec4 u)
+       (declare (in) vec4 v))
+     ((declare () mat4 m)
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (0))) (expression vec4 * (var_ref u) (swiz x (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (1))) (expression vec4 * (var_ref u) (swiz y (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (2))) (expression vec4 * (var_ref u) (swiz z (var_ref v))))
+      (assign (constant bool (1)) (array_ref (var_ref m) (constant int (3))) (expression vec4 * (var_ref u) (swiz w (var_ref v))))
+      (return (var_ref m))))
+))
diff --git a/src/glsl/builtins/ir/pow b/src/glsl/builtins/ir/pow
new file mode 100644 (file)
index 0000000..a61bc44
--- /dev/null
@@ -0,0 +1,25 @@
+((function pow
+   (signature float
+     (parameters
+       (declare (in) float arg0)
+       (declare (in) float arg1))
+     ((return (expression float pow (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0)
+       (declare (in) vec2 arg1))
+     ((return (expression vec2 pow (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0)
+       (declare (in) vec3 arg1))
+     ((return (expression vec3 pow (var_ref arg0) (var_ref arg1)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0)
+       (declare (in) vec4 arg1))
+     ((return (expression vec4 pow (var_ref arg0) (var_ref arg1)))))
+))
diff --git a/src/glsl/builtins/ir/radians b/src/glsl/builtins/ir/radians
new file mode 100644 (file)
index 0000000..6a0f5d2
--- /dev/null
@@ -0,0 +1,21 @@
+((function radians
+   (signature float
+     (parameters
+       (declare (in) float arg0))
+     ((return (expression float * (var_ref arg0) (constant float (0.017453))))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0))
+     ((return (expression vec2 * (var_ref arg0) (constant float (0.017453))))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0))
+     ((return (expression vec3 * (var_ref arg0) (constant float (0.017453))))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0))
+     ((return (expression vec4 * (var_ref arg0) (constant float (0.017453))))))
+))
diff --git a/src/glsl/builtins/ir/reflect b/src/glsl/builtins/ir/reflect
new file mode 100644 (file)
index 0000000..8238fdc
--- /dev/null
@@ -0,0 +1,58 @@
+((function reflect
+   (signature float
+     (parameters
+       (declare (in) float i)
+       (declare (in) float n))
+     ((return (expression float -
+              (var_ref i)
+              (expression float *
+               (constant float (2.0))
+               (expression float *
+                (expression float dot
+                 (var_ref n)
+                 (var_ref i))
+                (var_ref n)))))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 i)
+       (declare (in) vec2 n))
+     ((return (expression vec2 -
+              (var_ref i)
+              (expression vec2 *
+               (constant float (2.0))
+               (expression vec2 *
+                (expression float dot
+                 (var_ref n)
+                 (var_ref i))
+                (var_ref n)))))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 i)
+       (declare (in) vec3 n))
+     ((return (expression vec3 -
+              (var_ref i)
+              (expression vec3 *
+               (constant float (2.0))
+               (expression vec3 *
+                (expression float dot
+                 (var_ref n)
+                 (var_ref i))
+                (var_ref n)))))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 i)
+       (declare (in) vec4 n))
+     ((return (expression vec4 -
+              (var_ref i)
+              (expression vec4 *
+               (constant float (2.0))
+               (expression vec4 *
+                (expression float dot
+                 (var_ref n)
+                 (var_ref i))
+                (var_ref n)))))))
+
+))
diff --git a/src/glsl/builtins/ir/refract b/src/glsl/builtins/ir/refract
new file mode 100644 (file)
index 0000000..522ab41
--- /dev/null
@@ -0,0 +1,102 @@
+((function refract
+   (signature float
+     (parameters
+       (declare (in) float i)
+       (declare (in) float n)
+       (declare (in) float eta))
+     ((declare () float k)
+      (assign (constant bool (1)) (var_ref k)
+              (expression float - (constant float (1.0))
+               (expression float * (var_ref eta)
+                 (expression float * (var_ref eta)
+                   (expression float - (constant float (1.0))
+                     (expression float * 
+                       (expression float dot (var_ref n) (var_ref i))
+                       (expression float dot (var_ref n) (var_ref i))))))))
+      (if (expression bool < (var_ref k) (constant float (0.0)))
+          ((return (constant float (0.0))))
+         ((return (expression float -
+                    (expression float * (var_ref eta) (var_ref i))
+                    (expression float *
+                      (expression float +
+                        (expression float * (var_ref eta)
+                          (expression float dot (var_ref n) (var_ref i)))
+                        (expression float sqrt (var_ref k)))
+                      (var_ref n))))))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 i)
+       (declare (in) vec2 n)
+       (declare (in) float eta))
+     ((declare () float k)
+      (assign (constant bool (1)) (var_ref k)
+              (expression float - (constant float (1.0))
+               (expression float * (var_ref eta)
+                 (expression float * (var_ref eta)
+                   (expression float - (constant float (1.0))
+                     (expression float * 
+                       (expression float dot (var_ref n) (var_ref i))
+                       (expression float dot (var_ref n) (var_ref i))))))))
+      (if (expression bool < (var_ref k) (constant float (0.0)))
+          ((return (constant vec2 (0.0 0.0))))
+         ((return (expression vec2 -
+                    (expression vec2 * (var_ref eta) (var_ref i))
+                    (expression vec2 *
+                      (expression float +
+                        (expression float * (var_ref eta)
+                          (expression float dot (var_ref n) (var_ref i)))
+                        (expression float sqrt (var_ref k)))
+                      (var_ref n))))))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 i)
+       (declare (in) vec3 n)
+       (declare (in) float eta))
+     ((declare () float k)
+      (assign (constant bool (1)) (var_ref k)
+              (expression float - (constant float (1.0))
+               (expression float * (var_ref eta)
+                 (expression float * (var_ref eta)
+                   (expression float - (constant float (1.0))
+                     (expression float * 
+                       (expression float dot (var_ref n) (var_ref i))
+                       (expression float dot (var_ref n) (var_ref i))))))))
+      (if (expression bool < (var_ref k) (constant float (0.0)))
+          ((return (constant vec3 (0.0 0.0 0.0))))
+         ((return (expression vec3 -
+                    (expression vec3 * (var_ref eta) (var_ref i))
+                    (expression vec3 *
+                      (expression float +
+                        (expression float * (var_ref eta)
+                          (expression float dot (var_ref n) (var_ref i)))
+                        (expression float sqrt (var_ref k)))
+                      (var_ref n))))))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 i)
+       (declare (in) vec4 n)
+       (declare (in) float eta))
+     ((declare () float k)
+      (assign (constant bool (1)) (var_ref k)
+              (expression float - (constant float (1.0))
+               (expression float * (var_ref eta)
+                 (expression float * (var_ref eta)
+                   (expression float - (constant float (1.0))
+                     (expression float * 
+                       (expression float dot (var_ref n) (var_ref i))
+                       (expression float dot (var_ref n) (var_ref i))))))))
+      (if (expression bool < (var_ref k) (constant float (0.0)))
+          ((return (constant vec4 (0.0 0.0 0.0 0.0))))
+         ((return (expression vec4 -
+                    (expression vec4 * (var_ref eta) (var_ref i))
+                    (expression vec4 *
+                      (expression float +
+                        (expression float * (var_ref eta)
+                          (expression float dot (var_ref n) (var_ref i)))
+                        (expression float sqrt (var_ref k)))
+                      (var_ref n))))))))
+
+))
diff --git a/src/glsl/builtins/ir/sign b/src/glsl/builtins/ir/sign
new file mode 100644 (file)
index 0000000..1f51718
--- /dev/null
@@ -0,0 +1,42 @@
+((function sign
+   (signature float
+     (parameters
+       (declare (in) float x))
+     ((return (expression float sign (var_ref x)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 x))
+     ((return (expression vec2 sign (var_ref x)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 x))
+     ((return (expression vec3 sign (var_ref x)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 x))
+     ((return (expression vec4 sign (var_ref x)))))
+
+   (signature int
+     (parameters
+       (declare (in) int x))
+     ((return (expression int sign (var_ref x)))))
+
+   (signature ivec2
+     (parameters
+       (declare (in) ivec2 x))
+     ((return (expression ivec2 sign (var_ref x)))))
+
+   (signature ivec3
+     (parameters
+       (declare (in) ivec3 x))
+     ((return (expression ivec3 sign (var_ref x)))))
+
+   (signature ivec4
+     (parameters
+       (declare (in) ivec4 x))
+     ((return (expression ivec4 sign (var_ref x)))))
+))
+
diff --git a/src/glsl/builtins/ir/sin b/src/glsl/builtins/ir/sin
new file mode 100644 (file)
index 0000000..e6009d8
--- /dev/null
@@ -0,0 +1,21 @@
+((function sin
+   (signature float
+     (parameters
+       (declare (in) float angle))
+     ((return (expression float sin (var_ref angle)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 angle))
+     ((return (expression vec2 sin (var_ref angle)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 angle))
+     ((return (expression vec3 sin (var_ref angle)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 angle))
+     ((return (expression vec4 sin (var_ref angle)))))
+))
diff --git a/src/glsl/builtins/ir/sinh b/src/glsl/builtins/ir/sinh
new file mode 100644 (file)
index 0000000..7ad4f58
--- /dev/null
@@ -0,0 +1,30 @@
+((function sinh
+   (signature float
+     (parameters
+       (declare (in) float x))
+     ((return (expression float * (constant float (0.5))
+                (expression float -
+                 (expression float exp (var_ref x))
+                 (expression float exp (expression float neg (var_ref x))))))))
+   (signature vec2
+     (parameters
+       (declare (in) vec2 x))
+     ((return (expression vec2 * (constant vec2 (0.5))
+                (expression vec2 -
+                 (expression vec2 exp (var_ref x))
+                 (expression vec2 exp (expression vec2 neg (var_ref x))))))))
+   (signature vec3
+     (parameters
+       (declare (in) vec3 x))
+     ((return (expression vec3 * (constant vec3 (0.5))
+                (expression vec3 -
+                 (expression vec3 exp (var_ref x))
+                 (expression vec3 exp (expression vec3 neg (var_ref x))))))))
+   (signature vec4
+     (parameters
+       (declare (in) vec4 x))
+     ((return (expression vec4 * (constant vec4 (0.5))
+                (expression vec4 -
+                 (expression vec4 exp (var_ref x))
+                 (expression vec4 exp (expression vec4 neg (var_ref x))))))))
+))
diff --git a/src/glsl/builtins/ir/smoothstep b/src/glsl/builtins/ir/smoothstep
new file mode 100644 (file)
index 0000000..663eec6
--- /dev/null
@@ -0,0 +1,153 @@
+((function smoothstep
+   (signature float
+     (parameters
+       (declare (in) float edge0)
+       (declare (in) float edge1)
+       (declare (in) float x))
+     ((declare () float t)
+
+      (assign (constant bool (1)) (var_ref t)
+              (expression float max
+                         (expression float min
+                                     (expression float / (expression float - (var_ref x) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+                                     (constant float (1.0)))
+                         (constant float (0.0))))
+      (return (expression float * (var_ref t) (expression float * (var_ref t) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (var_ref t))))))))
+
+   (signature vec2
+     (parameters
+       (declare (in) float edge0)
+       (declare (in) float edge1)
+       (declare (in) vec2 x))
+     ((declare () vec2 t)
+      (declare () vec2 retval)
+
+      (assign (constant bool (1)) (swiz x (var_ref t))
+              (expression float max
+                         (expression float min
+                                     (expression float / (expression float - (swiz x (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+                                     (constant float (1.0)))
+                         (constant float (0.0))))
+      (assign (constant bool (1)) (swiz x (var_ref retval)) (expression float * (swiz x (var_ref t)) (expression float * (swiz x (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz x (var_ref t)))))))
+
+      (assign (constant bool (1)) (swiz y (var_ref t))
+              (expression float max
+                         (expression float min
+                                     (expression float / (expression float - (swiz y (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+                                     (constant float (1.0)))
+                         (constant float (0.0))))
+      (assign (constant bool (1)) (swiz y (var_ref retval)) (expression float * (swiz y (var_ref t)) (expression float * (swiz y (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz y (var_ref t)))))))
+      (return (var_ref retval))
+      ))
+
+   (signature vec3
+     (parameters
+       (declare (in) float edge0)
+       (declare (in) float edge1)
+       (declare (in) vec3 x))
+     ((declare () vec3 t)
+      (declare () vec3 retval)
+
+      (assign (constant bool (1)) (swiz x (var_ref t))
+              (expression float max
+                         (expression float min
+                                     (expression float / (expression float - (swiz x (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+                                     (constant float (1.0)))
+                         (constant float (0.0))))
+      (assign (constant bool (1)) (swiz x (var_ref retval)) (expression float * (swiz x (var_ref t)) (expression float * (swiz x (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz x (var_ref t)))))))
+
+      (assign (constant bool (1)) (swiz y (var_ref t))
+              (expression float max
+                         (expression float min
+                                     (expression float / (expression float - (swiz y (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+                                     (constant float (1.0)))
+                         (constant float (0.0))))
+      (assign (constant bool (1)) (swiz y (var_ref retval)) (expression float * (swiz y (var_ref t)) (expression float * (swiz y (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz y (var_ref t)))))))
+
+      (assign (constant bool (1)) (swiz z (var_ref t))
+              (expression float max
+                         (expression float min
+                                     (expression float / (expression float - (swiz z (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+                                     (constant float (1.0)))
+                         (constant float (0.0))))
+      (assign (constant bool (1)) (swiz z (var_ref retval)) (expression float * (swiz z (var_ref t)) (expression float * (swiz z (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz z (var_ref t)))))))
+      (return (var_ref retval))
+      ))
+
+
+   (signature vec4
+     (parameters
+       (declare (in) float edge0)
+       (declare (in) float edge1)
+       (declare (in) vec4 x))
+     ((declare () vec4 t)
+      (declare () vec4 retval)
+
+      (assign (constant bool (1)) (swiz x (var_ref t))
+              (expression float max
+                         (expression float min
+                                     (expression float / (expression float - (swiz x (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+                                     (constant float (1.0)))
+                         (constant float (0.0))))
+      (assign (constant bool (1)) (swiz x (var_ref retval)) (expression float * (swiz x (var_ref t)) (expression float * (swiz x (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz x (var_ref t)))))))
+
+      (assign (constant bool (1)) (swiz y (var_ref t))
+              (expression float max
+                         (expression float min
+                                     (expression float / (expression float - (swiz y (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+                                     (constant float (1.0)))
+                         (constant float (0.0))))
+      (assign (constant bool (1)) (swiz y (var_ref retval)) (expression float * (swiz y (var_ref t)) (expression float * (swiz y (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz y (var_ref t)))))))
+
+      (assign (constant bool (1)) (swiz z (var_ref t))
+              (expression float max
+                         (expression float min
+                                     (expression float / (expression float - (swiz z (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+                                     (constant float (1.0)))
+                         (constant float (0.0))))
+      (assign (constant bool (1)) (swiz z (var_ref retval)) (expression float * (swiz z (var_ref t)) (expression float * (swiz z (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz z (var_ref t)))))))
+
+      (assign (constant bool (1)) (swiz w (var_ref t))
+              (expression float max
+                         (expression float min
+                                     (expression float / (expression float - (swiz w (var_ref x)) (var_ref edge0)) (expression float - (var_ref edge1) (var_ref edge0)))
+                                     (constant float (1.0)))
+                         (constant float (0.0))))
+      (assign (constant bool (1)) (swiz w (var_ref retval)) (expression float * (swiz w (var_ref t)) (expression float * (swiz w (var_ref t)) (expression float - (constant float (3.000000)) (expression float * (constant float (2.000000)) (swiz w (var_ref t)))))))
+      (return (var_ref retval))
+      ))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 edge0)
+       (declare (in) vec2 edge1)
+       (declare (in) vec2 x))
+     ((return (expression vec2 max
+                          (expression vec2 min
+                                      (expression vec2 / (expression vec2 - (var_ref x) (var_ref edge0)) (expression vec2 - (var_ref edge1) (var_ref edge0)))
+                                      (constant vec2 (1.0 1.0)))
+                          (constant vec2 (0.0 0.0))))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 edge0)
+       (declare (in) vec3 edge1)
+       (declare (in) vec3 x))
+     ((return (expression vec3 max
+                          (expression vec3 min
+                                      (expression vec3 / (expression vec3 - (var_ref x) (var_ref edge0)) (expression vec3 - (var_ref edge1) (var_ref edge0)))
+                                      (constant vec3 (1.0 1.0 1.0)))
+                          (constant vec3 (0.0 0.0 0.0))))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 edge0)
+       (declare (in) vec4 edge1)
+       (declare (in) vec4 x))
+     ((return (expression vec4 max
+                          (expression vec4 min
+                                      (expression vec4 / (expression vec4 - (var_ref x) (var_ref edge0)) (expression vec4 - (var_ref edge1) (var_ref edge0)))
+                                      (constant vec4 (1.0 1.0 1.0 1.0)))
+                          (constant vec4 (0.0 0.0 0.0 0.0))))))
+))
+
diff --git a/src/glsl/builtins/ir/sqrt b/src/glsl/builtins/ir/sqrt
new file mode 100644 (file)
index 0000000..0302d16
--- /dev/null
@@ -0,0 +1,21 @@
+((function sqrt
+   (signature float
+     (parameters
+       (declare (in) float arg0))
+     ((return (expression float sqrt (var_ref arg0)))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 arg0))
+     ((return (expression vec2 sqrt (var_ref arg0)))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 arg0))
+     ((return (expression vec3 sqrt (var_ref arg0)))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 arg0))
+     ((return (expression vec4 sqrt (var_ref arg0)))))
+))
diff --git a/src/glsl/builtins/ir/step b/src/glsl/builtins/ir/step
new file mode 100644 (file)
index 0000000..ce6f435
--- /dev/null
@@ -0,0 +1,68 @@
+((function step
+   (signature float
+     (parameters
+       (declare (in) float edge)
+       (declare (in) float x))
+     ((return (expression float b2f (expression bool >= (var_ref x) (var_ref edge))))))
+
+   (signature vec2
+     (parameters
+       (declare (in) float edge)
+       (declare (in) vec2 x))
+     ((declare () vec2 t)
+      (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(var_ref edge))))
+      (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(var_ref edge))))
+      (return (var_ref t))))
+
+   (signature vec3
+     (parameters
+       (declare (in) float edge)
+       (declare (in) vec3 x))
+     ((declare () vec3 t)
+      (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(var_ref edge))))
+      (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(var_ref edge))))
+      (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz z (var_ref x))(var_ref edge))))
+      (return (var_ref t))))
+
+   (signature vec4
+     (parameters
+       (declare (in) float edge)
+       (declare (in) vec4 x))
+     ((declare () vec4 t)
+      (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(var_ref edge))))
+      (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(var_ref edge))))
+      (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz z (var_ref x))(var_ref edge))))
+      (assign (constant bool (1)) (swiz w (var_ref t)) (expression float b2f (expression bool >= (swiz w (var_ref x))(var_ref edge))))
+      (return (var_ref t))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 edge)
+       (declare (in) vec2 x))
+     ((declare () vec2 t)
+      (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(swiz x (var_ref edge)))))
+      (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz y (var_ref edge)))))
+      (return (var_ref t))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 edge)
+       (declare (in) vec3 x))
+     ((declare () vec3 t)
+      (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(swiz x (var_ref edge)))))
+      (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz y (var_ref edge)))))
+      (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz z (var_ref x))(swiz z (var_ref edge)))))
+      (return (var_ref t))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 edge)
+       (declare (in) vec4 x))
+     ((declare () vec4 t)
+      (assign (constant bool (1)) (swiz x (var_ref t)) (expression float b2f (expression bool >= (swiz x (var_ref x))(swiz x (var_ref edge)))))
+      (assign (constant bool (1)) (swiz y (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz y (var_ref edge)))))
+      (assign (constant bool (1)) (swiz z (var_ref t)) (expression float b2f (expression bool >= (swiz y (var_ref x))(swiz z (var_ref edge)))))
+      (assign (constant bool (1)) (swiz w (var_ref t)) (expression float b2f (expression bool >= (swiz w (var_ref x))(swiz w (var_ref edge)))))
+      (return (var_ref t))))
+))
+
diff --git a/src/glsl/builtins/ir/tan b/src/glsl/builtins/ir/tan
new file mode 100644 (file)
index 0000000..9979863
--- /dev/null
@@ -0,0 +1,21 @@
+((function tan
+   (signature float
+     (parameters
+       (declare (in) float angle))
+     ((return (expression float / (expression float sin (var_ref angle)) (expression float cos (var_ref angle))))))
+
+   (signature vec2
+     (parameters
+       (declare (in) vec2 angle))
+     ((return (expression vec2 / (expression vec2 sin (var_ref angle)) (expression vec2 cos (var_ref angle))))))
+
+   (signature vec3
+     (parameters
+       (declare (in) vec3 angle))
+     ((return (expression vec3 / (expression vec3 sin (var_ref angle)) (expression vec3 cos (var_ref angle))))))
+
+   (signature vec4
+     (parameters
+       (declare (in) vec4 angle))
+     ((return (expression vec4 / (expression vec4 sin (var_ref angle)) (expression vec4 cos (var_ref angle))))))
+))
diff --git a/src/glsl/builtins/ir/tanh b/src/glsl/builtins/ir/tanh
new file mode 100644 (file)
index 0000000..3b7271b
--- /dev/null
@@ -0,0 +1,42 @@
+((function tanh
+   (signature float
+     (parameters
+       (declare (in) float x))
+     ((return (expression float /
+                (expression float -
+                 (expression float exp (var_ref x))
+                 (expression float exp (expression float neg (var_ref x))))
+                (expression float +
+                 (expression float exp (var_ref x))
+                 (expression float exp (expression float neg (var_ref x))))))))
+   (signature vec2
+     (parameters
+       (declare (in) vec2 x))
+     ((return (expression vec2 /
+                (expression vec2 -
+                 (expression vec2 exp (var_ref x))
+                 (expression vec2 exp (expression vec2 neg (var_ref x))))
+                (expression vec2 +
+                 (expression vec2 exp (var_ref x))
+                 (expression vec2 exp (expression vec2 neg (var_ref x))))))))
+   (signature vec3
+     (parameters
+       (declare (in) vec3 x))
+     ((return (expression vec3 /
+                (expression vec3 -
+                 (expression vec3 exp (var_ref x))
+                 (expression vec3 exp (expression vec3 neg (var_ref x))))
+                (expression vec3 +
+                 (expression vec3 exp (var_ref x))
+                 (expression vec3 exp (expression vec3 neg (var_ref x))))))))
+   (signature vec4
+     (parameters
+       (declare (in) vec4 x))
+     ((return (expression vec4 /
+                (expression vec4 -
+                 (expression vec4 exp (var_ref x))
+                 (expression vec4 exp (expression vec4 neg (var_ref x))))
+                (expression vec4 +
+                 (expression vec4 exp (var_ref x))
+                 (expression vec4 exp (expression vec4 neg (var_ref x))))))))
+))
diff --git a/src/glsl/builtins/ir/transpose b/src/glsl/builtins/ir/transpose
new file mode 100644 (file)
index 0000000..416a0ee
--- /dev/null
@@ -0,0 +1,139 @@
+((function transpose
+   (signature mat2
+     (parameters
+       (declare (in) mat2 m))
+     ((declare () mat2 t)
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) 
+(return (var_ref t))))
+
+   (signature mat3x2
+     (parameters
+       (declare (in) mat2x3 m))
+     ((declare () mat3x2 t)
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) 
+(return (var_ref t))))
+
+   (signature mat4x2
+     (parameters
+       (declare (in) mat2x4 m))
+     ((declare () mat4x2 t)
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (1))))) 
+(return (var_ref t))))
+
+   (signature mat2x3
+     (parameters
+       (declare (in) mat3x2 m))
+     ((declare () mat2x3 t)
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) 
+(return (var_ref t))))
+
+   (signature mat3
+     (parameters
+       (declare (in) mat3 m))
+     ((declare () mat3 t)
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2))))) 
+(return (var_ref t))))
+
+   (signature mat4x3
+     (parameters
+       (declare (in) mat3x4 m))
+     ((declare () mat4x3 t)
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (2))))) 
+(return (var_ref t))))
+
+   (signature mat2x4
+     (parameters
+       (declare (in) mat4x2 m))
+     ((declare () mat2x4 t)
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) 
+      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (3))))) 
+      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (3))))) 
+(return (var_ref t))))
+
+   (signature mat3x4
+     (parameters
+       (declare (in) mat4x3 m))
+     ((declare () mat3x4 t)
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2))))) 
+      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (3))))) 
+      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (3))))) 
+      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (3))))) 
+(return (var_ref t))))
+
+   (signature mat4
+     (parameters
+       (declare (in) mat4 m))
+     ((declare () mat4 t)
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz x (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (0))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz y (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (1))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (2))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (2))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (2))))) 
+      (assign (constant bool (1)) (swiz z (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (2))))) 
+      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (0)))) (swiz x (array_ref (var_ref m) (constant int (3))))) 
+      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (1)))) (swiz y (array_ref (var_ref m) (constant int (3))))) 
+      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (2)))) (swiz z (array_ref (var_ref m) (constant int (3))))) 
+      (assign (constant bool (1)) (swiz w (array_ref (var_ref t) (constant int (3)))) (swiz w (array_ref (var_ref m) (constant int (3))))) 
+(return (var_ref t))))
+)
+
+)
+
diff --git a/src/glsl/builtins/profiles/110.frag b/src/glsl/builtins/profiles/110.frag
new file mode 100644 (file)
index 0000000..25bc62c
--- /dev/null
@@ -0,0 +1,364 @@
+#version 110
+/*
+ * 8.1 - Angle and Trigonometry Functions
+ */
+float radians(float degrees);
+vec2  radians(vec2  degrees);
+vec3  radians(vec3  degrees);
+vec4  radians(vec4  degrees);
+
+float degrees(float radians);
+vec2  degrees(vec2  radians);
+vec3  degrees(vec3  radians);
+vec4  degrees(vec4  radians);
+
+float sin(float angle);
+vec2  sin(vec2  angle);
+vec3  sin(vec3  angle);
+vec4  sin(vec4  angle);
+
+float cos(float angle);
+vec2  cos(vec2  angle);
+vec3  cos(vec3  angle);
+vec4  cos(vec4  angle);
+
+float tan(float angle);
+vec2  tan(vec2  angle);
+vec3  tan(vec3  angle);
+vec4  tan(vec4  angle);
+
+float asin(float angle);
+vec2  asin(vec2  angle);
+vec3  asin(vec3  angle);
+vec4  asin(vec4  angle);
+
+float acos(float angle);
+vec2  acos(vec2  angle);
+vec3  acos(vec3  angle);
+vec4  acos(vec4  angle);
+
+float atan(float y, float x);
+vec2  atan(vec2  y, vec2  x);
+vec3  atan(vec3  y, vec3  x);
+vec4  atan(vec4  y, vec4  x);
+
+float atan(float y_over_x);
+vec2  atan(vec2  y_over_x);
+vec3  atan(vec3  y_over_x);
+vec4  atan(vec4  y_over_x);
+
+/*
+ * 8.2 - Exponential Functions
+ */
+float pow(float x, float y);
+vec2  pow(vec2  x, vec2  y);
+vec3  pow(vec3  x, vec3  y);
+vec4  pow(vec4  x, vec4  y);
+
+float exp(float x);
+vec2  exp(vec2  x);
+vec3  exp(vec3  x);
+vec4  exp(vec4  x);
+
+float log(float x);
+vec2  log(vec2  x);
+vec3  log(vec3  x);
+vec4  log(vec4  x);
+
+float exp2(float x);
+vec2  exp2(vec2  x);
+vec3  exp2(vec3  x);
+vec4  exp2(vec4  x);
+
+float log2(float x);
+vec2  log2(vec2  x);
+vec3  log2(vec3  x);
+vec4  log2(vec4  x);
+
+float sqrt(float x);
+vec2  sqrt(vec2  x);
+vec3  sqrt(vec3  x);
+vec4  sqrt(vec4  x);
+
+float inversesqrt(float x);
+vec2  inversesqrt(vec2  x);
+vec3  inversesqrt(vec3  x);
+vec4  inversesqrt(vec4  x);
+
+/*
+ * 8.3 - Common Functions
+ */
+float abs(float x);
+vec2  abs(vec2  x);
+vec3  abs(vec3  x);
+vec4  abs(vec4  x);
+
+float sign(float x);
+vec2  sign(vec2  x);
+vec3  sign(vec3  x);
+vec4  sign(vec4  x);
+
+float floor(float x);
+vec2  floor(vec2  x);
+vec3  floor(vec3  x);
+vec4  floor(vec4  x);
+
+float ceil(float x);
+vec2  ceil(vec2  x);
+vec3  ceil(vec3  x);
+vec4  ceil(vec4  x);
+
+float fract(float x);
+vec2  fract(vec2  x);
+vec3  fract(vec3  x);
+vec4  fract(vec4  x);
+
+float mod(float x, float y);
+vec2  mod(vec2  x, float y);
+vec3  mod(vec3  x, float y);
+vec4  mod(vec4  x, float y);
+
+vec2  mod(vec2  x, vec2  y);
+vec3  mod(vec3  x, vec3  y);
+vec4  mod(vec4  x, vec4  y);
+
+float min(float x, float y);
+vec2  min(vec2  x, vec2  y);
+vec3  min(vec3  x, vec3  y);
+vec4  min(vec4  x, vec4  y);
+
+vec2  min(vec2  x, float y);
+vec3  min(vec3  x, float y);
+vec4  min(vec4  x, float y);
+
+float max(float x, float y);
+vec2  max(vec2  x, vec2  y);
+vec3  max(vec3  x, vec3  y);
+vec4  max(vec4  x, vec4  y);
+
+vec2  max(vec2  x, float y);
+vec3  max(vec3  x, float y);
+vec4  max(vec4  x, float y);
+
+float clamp(float x, float minVal, float maxVal);
+vec2  clamp(vec2  x, vec2  minVal, vec2  maxVal);
+vec3  clamp(vec3  x, vec3  minVal, vec3  maxVal);
+vec4  clamp(vec4  x, vec4  minVal, vec4  maxVal);
+
+vec2  clamp(vec2  x, float minVal, float maxVal);
+vec3  clamp(vec3  x, float minVal, float maxVal);
+vec4  clamp(vec4  x, float minVal, float maxVal);
+
+float mix(float x, float y, float a);
+vec2  mix(vec2  x, vec2  y, vec2  a);
+vec3  mix(vec3  x, vec3  y, vec3  a);
+vec4  mix(vec4  x, vec4  y, vec4  a);
+
+vec2  mix(vec2  x, vec2  y, float a);
+vec3  mix(vec3  x, vec3  y, float a);
+vec4  mix(vec4  x, vec4  y, float a);
+
+float step(float edge, float x);
+vec2  step(vec2  edge, vec2  x);
+vec3  step(vec3  edge, vec3  x);
+vec4  step(vec4  edge, vec4  x);
+
+vec2  step(float edge, vec2  x);
+vec3  step(float edge, vec3  x);
+vec4  step(float edge, vec4  x);
+
+float smoothstep(float edge0, float edge1, float x);
+vec2  smoothstep(vec2  edge0, vec2  edge1, vec2  x);
+vec3  smoothstep(vec3  edge0, vec3  edge1, vec3  x);
+vec4  smoothstep(vec4  edge0, vec4  edge1, vec4  x);
+
+vec2  smoothstep(float edge0, float edge1, vec2  x);
+vec3  smoothstep(float edge0, float edge1, vec3  x);
+vec4  smoothstep(float edge0, float edge1, vec4  x);
+
+/*
+ * 8.4 - Geometric Functions
+ */
+float length(float x);
+float length(vec2  x);
+float length(vec3  x);
+float length(vec4  x);
+
+float distance(float p0, float p1);
+float distance(vec2  p0, vec2  p1);
+float distance(vec3  p0, vec3  p1);
+float distance(vec4  p0, vec4  p1);
+
+float dot(float x, float y);
+float dot(vec2  x, vec2  y);
+float dot(vec3  x, vec3  y);
+float dot(vec4  x, vec4  y);
+
+vec3 cross(vec3 x, vec3 y);
+
+float normalize(float x);
+vec2  normalize(vec2  x);
+vec3  normalize(vec3  x);
+vec4  normalize(vec4  x);
+
+float faceforward(float N, float I, float Nref);
+vec2  faceforward(vec2  N, vec2  I, vec2  Nref);
+vec3  faceforward(vec3  N, vec3  I, vec3  Nref);
+vec4  faceforward(vec4  N, vec4  I, vec4  Nref);
+
+float reflect(float I, float N);
+vec2  reflect(vec2  I, vec2  N);
+vec3  reflect(vec3  I, vec3  N);
+vec4  reflect(vec4  I, vec4  N);
+
+float refract(float I, float N, float eta);
+vec2  refract(vec2  I, vec2  N, float eta);
+vec3  refract(vec3  I, vec3  N, float eta);
+vec4  refract(vec4  I, vec4  N, float eta);
+
+
+/*
+ * 8.5 - Matrix Functions
+ */
+mat2 matrixCompMult(mat2 x, mat2 y);
+mat3 matrixCompMult(mat3 x, mat3 y);
+mat4 matrixCompMult(mat4 x, mat4 y);
+
+/*
+ * 8.6 - Vector Relational Functions
+ */
+bvec2 lessThan( vec2 x,  vec2 y);
+bvec3 lessThan( vec3 x,  vec3 y);
+bvec4 lessThan( vec4 x,  vec4 y);
+bvec2 lessThan(ivec2 x, ivec2 y);
+bvec3 lessThan(ivec3 x, ivec3 y);
+bvec4 lessThan(ivec4 x, ivec4 y);
+
+bvec2 lessThanEqual( vec2 x,  vec2 y);
+bvec3 lessThanEqual( vec3 x,  vec3 y);
+bvec4 lessThanEqual( vec4 x,  vec4 y);
+bvec2 lessThanEqual(ivec2 x, ivec2 y);
+bvec3 lessThanEqual(ivec3 x, ivec3 y);
+bvec4 lessThanEqual(ivec4 x, ivec4 y);
+
+bvec2 greaterThan( vec2 x,  vec2 y);
+bvec3 greaterThan( vec3 x,  vec3 y);
+bvec4 greaterThan( vec4 x,  vec4 y);
+bvec2 greaterThan(ivec2 x, ivec2 y);
+bvec3 greaterThan(ivec3 x, ivec3 y);
+bvec4 greaterThan(ivec4 x, ivec4 y);
+
+bvec2 greaterThanEqual( vec2 x,  vec2 y);
+bvec3 greaterThanEqual( vec3 x,  vec3 y);
+bvec4 greaterThanEqual( vec4 x,  vec4 y);
+bvec2 greaterThanEqual(ivec2 x, ivec2 y);
+bvec3 greaterThanEqual(ivec3 x, ivec3 y);
+bvec4 greaterThanEqual(ivec4 x, ivec4 y);
+
+bvec2 equal( vec2 x,  vec2 y);
+bvec3 equal( vec3 x,  vec3 y);
+bvec4 equal( vec4 x,  vec4 y);
+bvec2 equal(ivec2 x, ivec2 y);
+bvec3 equal(ivec3 x, ivec3 y);
+bvec4 equal(ivec4 x, ivec4 y);
+bvec2 equal(bvec2 x, bvec2 y);
+bvec3 equal(bvec3 x, bvec3 y);
+bvec4 equal(bvec4 x, bvec4 y);
+
+bvec2 notEqual( vec2 x,  vec2 y);
+bvec3 notEqual( vec3 x,  vec3 y);
+bvec4 notEqual( vec4 x,  vec4 y);
+bvec2 notEqual(ivec2 x, ivec2 y);
+bvec3 notEqual(ivec3 x, ivec3 y);
+bvec4 notEqual(ivec4 x, ivec4 y);
+bvec2 notEqual(bvec2 x, bvec2 y);
+bvec3 notEqual(bvec3 x, bvec3 y);
+bvec4 notEqual(bvec4 x, bvec4 y);
+
+bool any(bvec2 x);
+bool any(bvec3 x);
+bool any(bvec4 x);
+
+bool all(bvec2 x);
+bool all(bvec3 x);
+bool all(bvec4 x);
+
+bvec2 not(bvec2 x);
+bvec3 not(bvec3 x);
+bvec4 not(bvec4 x);
+
+/*
+ * 8.7 - Texture Lookup Functions
+ */
+vec4 texture1D       (sampler1D sampler, float coord);
+vec4 texture1DProj   (sampler1D sampler, vec2  coord);
+vec4 texture1DProj   (sampler1D sampler, vec4  coord);
+vec4 texture1D       (sampler1D sampler, float coord, float bias);
+vec4 texture1DProj   (sampler1D sampler, vec2  coord, float bias);
+vec4 texture1DProj   (sampler1D sampler, vec4  coord, float bias);
+
+vec4 texture2D       (sampler2D sampler, vec2 coord);
+vec4 texture2DProj   (sampler2D sampler, vec3 coord);
+vec4 texture2DProj   (sampler2D sampler, vec4 coord);
+vec4 texture2D       (sampler2D sampler, vec2 coord, float bias);
+vec4 texture2DProj   (sampler2D sampler, vec3 coord, float bias);
+vec4 texture2DProj   (sampler2D sampler, vec4 coord, float bias);
+
+vec4 texture3D       (sampler3D sampler, vec3 coord);
+vec4 texture3DProj   (sampler3D sampler, vec4 coord);
+vec4 texture3D       (sampler3D sampler, vec3 coord, float bias);
+vec4 texture3DProj   (sampler3D sampler, vec4 coord, float bias);
+
+vec4 textureCube     (samplerCube sampler, vec3 coord);
+vec4 textureCube     (samplerCube sampler, vec3 coord, float bias);
+
+vec4 shadow1D       (sampler1DShadow sampler, vec3 coord);
+vec4 shadow2D       (sampler2DShadow sampler, vec3 coord);
+vec4 shadow1DProj   (sampler1DShadow sampler, vec4 coord);
+vec4 shadow2DProj   (sampler2DShadow sampler, vec4 coord);
+vec4 shadow1D       (sampler1DShadow sampler, vec3 coord, float bias);
+vec4 shadow2D       (sampler2DShadow sampler, vec3 coord, float bias);
+vec4 shadow1DProj   (sampler1DShadow sampler, vec4 coord, float bias);
+vec4 shadow2DProj   (sampler2DShadow sampler, vec4 coord, float bias);
+
+
+/*
+ * 8.8 - Fragment Processing Functions
+ */
+float dFdx(float p);
+vec2  dFdx(vec2  p);
+vec3  dFdx(vec3  p);
+vec4  dFdx(vec4  p);
+
+float dFdy(float p);
+vec2  dFdy(vec2  p);
+vec3  dFdy(vec3  p);
+vec4  dFdy(vec4  p);
+
+float fwidth(float p);
+vec2  fwidth(vec2  p);
+vec3  fwidth(vec3  p);
+vec4  fwidth(vec4  p);
+
+/*
+ * 8.9 - Noise Functions
+ */
+float noise1(float x);
+float noise1(vec2  x);
+float noise1(vec3  x);
+float noise1(vec4  x);
+
+vec2  noise2(float x);
+vec2  noise2(vec2  x);
+vec2  noise2(vec3  x);
+vec2  noise2(vec4  x);
+
+vec3  noise3(float x);
+vec3  noise3(vec2  x);
+vec3  noise3(vec3  x);
+vec3  noise3(vec4  x);
+
+vec4  noise4(float x);
+vec4  noise4(vec2  x);
+vec4  noise4(vec3  x);
+vec4  noise4(vec4  x);
diff --git a/src/glsl/builtins/profiles/110.vert b/src/glsl/builtins/profiles/110.vert
new file mode 100644 (file)
index 0000000..545e59c
--- /dev/null
@@ -0,0 +1,351 @@
+#version 110
+/*
+ * 8.1 - Angle and Trigonometry Functions
+ */
+float radians(float degrees);
+vec2  radians(vec2  degrees);
+vec3  radians(vec3  degrees);
+vec4  radians(vec4  degrees);
+
+float degrees(float radians);
+vec2  degrees(vec2  radians);
+vec3  degrees(vec3  radians);
+vec4  degrees(vec4  radians);
+
+float sin(float angle);
+vec2  sin(vec2  angle);
+vec3  sin(vec3  angle);
+vec4  sin(vec4  angle);
+
+float cos(float angle);
+vec2  cos(vec2  angle);
+vec3  cos(vec3  angle);
+vec4  cos(vec4  angle);
+
+float tan(float angle);
+vec2  tan(vec2  angle);
+vec3  tan(vec3  angle);
+vec4  tan(vec4  angle);
+
+float asin(float angle);
+vec2  asin(vec2  angle);
+vec3  asin(vec3  angle);
+vec4  asin(vec4  angle);
+
+float acos(float angle);
+vec2  acos(vec2  angle);
+vec3  acos(vec3  angle);
+vec4  acos(vec4  angle);
+
+float atan(float y, float x);
+vec2  atan(vec2  y, vec2  x);
+vec3  atan(vec3  y, vec3  x);
+vec4  atan(vec4  y, vec4  x);
+
+float atan(float y_over_x);
+vec2  atan(vec2  y_over_x);
+vec3  atan(vec3  y_over_x);
+vec4  atan(vec4  y_over_x);
+
+/*
+ * 8.2 - Exponential Functions
+ */
+float pow(float x, float y);
+vec2  pow(vec2  x, vec2  y);
+vec3  pow(vec3  x, vec3  y);
+vec4  pow(vec4  x, vec4  y);
+
+float exp(float x);
+vec2  exp(vec2  x);
+vec3  exp(vec3  x);
+vec4  exp(vec4  x);
+
+float log(float x);
+vec2  log(vec2  x);
+vec3  log(vec3  x);
+vec4  log(vec4  x);
+
+float exp2(float x);
+vec2  exp2(vec2  x);
+vec3  exp2(vec3  x);
+vec4  exp2(vec4  x);
+
+float log2(float x);
+vec2  log2(vec2  x);
+vec3  log2(vec3  x);
+vec4  log2(vec4  x);
+
+float sqrt(float x);
+vec2  sqrt(vec2  x);
+vec3  sqrt(vec3  x);
+vec4  sqrt(vec4  x);
+
+float inversesqrt(float x);
+vec2  inversesqrt(vec2  x);
+vec3  inversesqrt(vec3  x);
+vec4  inversesqrt(vec4  x);
+
+/*
+ * 8.3 - Common Functions
+ */
+float abs(float x);
+vec2  abs(vec2  x);
+vec3  abs(vec3  x);
+vec4  abs(vec4  x);
+
+float sign(float x);
+vec2  sign(vec2  x);
+vec3  sign(vec3  x);
+vec4  sign(vec4  x);
+
+float floor(float x);
+vec2  floor(vec2  x);
+vec3  floor(vec3  x);
+vec4  floor(vec4  x);
+
+float ceil(float x);
+vec2  ceil(vec2  x);
+vec3  ceil(vec3  x);
+vec4  ceil(vec4  x);
+
+float fract(float x);
+vec2  fract(vec2  x);
+vec3  fract(vec3  x);
+vec4  fract(vec4  x);
+
+float mod(float x, float y);
+vec2  mod(vec2  x, float y);
+vec3  mod(vec3  x, float y);
+vec4  mod(vec4  x, float y);
+
+vec2  mod(vec2  x, vec2  y);
+vec3  mod(vec3  x, vec3  y);
+vec4  mod(vec4  x, vec4  y);
+
+float min(float x, float y);
+vec2  min(vec2  x, vec2  y);
+vec3  min(vec3  x, vec3  y);
+vec4  min(vec4  x, vec4  y);
+
+vec2  min(vec2  x, float y);
+vec3  min(vec3  x, float y);
+vec4  min(vec4  x, float y);
+
+float max(float x, float y);
+vec2  max(vec2  x, vec2  y);
+vec3  max(vec3  x, vec3  y);
+vec4  max(vec4  x, vec4  y);
+
+vec2  max(vec2  x, float y);
+vec3  max(vec3  x, float y);
+vec4  max(vec4  x, float y);
+
+float clamp(float x, float minVal, float maxVal);
+vec2  clamp(vec2  x, vec2  minVal, vec2  maxVal);
+vec3  clamp(vec3  x, vec3  minVal, vec3  maxVal);
+vec4  clamp(vec4  x, vec4  minVal, vec4  maxVal);
+
+vec2  clamp(vec2  x, float minVal, float maxVal);
+vec3  clamp(vec3  x, float minVal, float maxVal);
+vec4  clamp(vec4  x, float minVal, float maxVal);
+
+float mix(float x, float y, float a);
+vec2  mix(vec2  x, vec2  y, vec2  a);
+vec3  mix(vec3  x, vec3  y, vec3  a);
+vec4  mix(vec4  x, vec4  y, vec4  a);
+
+vec2  mix(vec2  x, vec2  y, float a);
+vec3  mix(vec3  x, vec3  y, float a);
+vec4  mix(vec4  x, vec4  y, float a);
+
+float step(float edge, float x);
+vec2  step(vec2  edge, vec2  x);
+vec3  step(vec3  edge, vec3  x);
+vec4  step(vec4  edge, vec4  x);
+
+vec2  step(float edge, vec2  x);
+vec3  step(float edge, vec3  x);
+vec4  step(float edge, vec4  x);
+
+float smoothstep(float edge0, float edge1, float x);
+vec2  smoothstep(vec2  edge0, vec2  edge1, vec2  x);
+vec3  smoothstep(vec3  edge0, vec3  edge1, vec3  x);
+vec4  smoothstep(vec4  edge0, vec4  edge1, vec4  x);
+
+vec2  smoothstep(float edge0, float edge1, vec2  x);
+vec3  smoothstep(float edge0, float edge1, vec3  x);
+vec4  smoothstep(float edge0, float edge1, vec4  x);
+
+/*
+ * 8.4 - Geometric Functions
+ */
+float length(float x);
+float length(vec2  x);
+float length(vec3  x);
+float length(vec4  x);
+
+float distance(float p0, float p1);
+float distance(vec2  p0, vec2  p1);
+float distance(vec3  p0, vec3  p1);
+float distance(vec4  p0, vec4  p1);
+
+float dot(float x, float y);
+float dot(vec2  x, vec2  y);
+float dot(vec3  x, vec3  y);
+float dot(vec4  x, vec4  y);
+
+vec3 cross(vec3 x, vec3 y);
+
+float normalize(float x);
+vec2  normalize(vec2  x);
+vec3  normalize(vec3  x);
+vec4  normalize(vec4  x);
+
+vec4 ftransform();
+
+float faceforward(float N, float I, float Nref);
+vec2  faceforward(vec2  N, vec2  I, vec2  Nref);
+vec3  faceforward(vec3  N, vec3  I, vec3  Nref);
+vec4  faceforward(vec4  N, vec4  I, vec4  Nref);
+
+float reflect(float I, float N);
+vec2  reflect(vec2  I, vec2  N);
+vec3  reflect(vec3  I, vec3  N);
+vec4  reflect(vec4  I, vec4  N);
+
+float refract(float I, float N, float eta);
+vec2  refract(vec2  I, vec2  N, float eta);
+vec3  refract(vec3  I, vec3  N, float eta);
+vec4  refract(vec4  I, vec4  N, float eta);
+
+
+/*
+ * 8.5 - Matrix Functions
+ */
+mat2 matrixCompMult(mat2 x, mat2 y);
+mat3 matrixCompMult(mat3 x, mat3 y);
+mat4 matrixCompMult(mat4 x, mat4 y);
+
+/*
+ * 8.6 - Vector Relational Functions
+ */
+bvec2 lessThan( vec2 x,  vec2 y);
+bvec3 lessThan( vec3 x,  vec3 y);
+bvec4 lessThan( vec4 x,  vec4 y);
+bvec2 lessThan(ivec2 x, ivec2 y);
+bvec3 lessThan(ivec3 x, ivec3 y);
+bvec4 lessThan(ivec4 x, ivec4 y);
+
+bvec2 lessThanEqual( vec2 x,  vec2 y);
+bvec3 lessThanEqual( vec3 x,  vec3 y);
+bvec4 lessThanEqual( vec4 x,  vec4 y);
+bvec2 lessThanEqual(ivec2 x, ivec2 y);
+bvec3 lessThanEqual(ivec3 x, ivec3 y);
+bvec4 lessThanEqual(ivec4 x, ivec4 y);
+
+bvec2 greaterThan( vec2 x,  vec2 y);
+bvec3 greaterThan( vec3 x,  vec3 y);
+bvec4 greaterThan( vec4 x,  vec4 y);
+bvec2 greaterThan(ivec2 x, ivec2 y);
+bvec3 greaterThan(ivec3 x, ivec3 y);
+bvec4 greaterThan(ivec4 x, ivec4 y);
+
+bvec2 greaterThanEqual( vec2 x,  vec2 y);
+bvec3 greaterThanEqual( vec3 x,  vec3 y);
+bvec4 greaterThanEqual( vec4 x,  vec4 y);
+bvec2 greaterThanEqual(ivec2 x, ivec2 y);
+bvec3 greaterThanEqual(ivec3 x, ivec3 y);
+bvec4 greaterThanEqual(ivec4 x, ivec4 y);
+
+bvec2 equal( vec2 x,  vec2 y);
+bvec3 equal( vec3 x,  vec3 y);
+bvec4 equal( vec4 x,  vec4 y);
+bvec2 equal(ivec2 x, ivec2 y);
+bvec3 equal(ivec3 x, ivec3 y);
+bvec4 equal(ivec4 x, ivec4 y);
+bvec2 equal(bvec2 x, bvec2 y);
+bvec3 equal(bvec3 x, bvec3 y);
+bvec4 equal(bvec4 x, bvec4 y);
+
+bvec2 notEqual( vec2 x,  vec2 y);
+bvec3 notEqual( vec3 x,  vec3 y);
+bvec4 notEqual( vec4 x,  vec4 y);
+bvec2 notEqual(ivec2 x, ivec2 y);
+bvec3 notEqual(ivec3 x, ivec3 y);
+bvec4 notEqual(ivec4 x, ivec4 y);
+bvec2 notEqual(bvec2 x, bvec2 y);
+bvec3 notEqual(bvec3 x, bvec3 y);
+bvec4 notEqual(bvec4 x, bvec4 y);
+
+bool any(bvec2 x);
+bool any(bvec3 x);
+bool any(bvec4 x);
+
+bool all(bvec2 x);
+bool all(bvec3 x);
+bool all(bvec4 x);
+
+bvec2 not(bvec2 x);
+bvec3 not(bvec3 x);
+bvec4 not(bvec4 x);
+
+/*
+ * 8.7 - Texture Lookup Functions
+ */
+vec4 texture1D       (sampler1D sampler, float coord);
+vec4 texture1DProj   (sampler1D sampler, vec2  coord);
+vec4 texture1DProj   (sampler1D sampler, vec4  coord);
+vec4 texture1DLod    (sampler1D sampler, float coord, float lod);
+vec4 texture1DProjLod(sampler1D sampler, vec2  coord, float lod);
+vec4 texture1DProjLod(sampler1D sampler, vec4  coord, float lod);
+
+vec4 texture2D       (sampler2D sampler, vec2 coord);
+vec4 texture2DProj   (sampler2D sampler, vec3 coord);
+vec4 texture2DProj   (sampler2D sampler, vec4 coord);
+vec4 texture2DLod    (sampler2D sampler, vec2 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);
+
+vec4 texture3D       (sampler3D sampler, vec3 coord);
+vec4 texture3DProj   (sampler3D sampler, vec4 coord);
+vec4 texture3DLod    (sampler3D sampler, vec3 coord, float lod);
+vec4 texture3DProjLod(sampler3D sampler, vec4 coord, float lod);
+
+vec4 textureCube     (samplerCube sampler, vec3 coord);
+vec4 textureCubeLod  (samplerCube sampler, vec3 coord, float lod);
+
+vec4 shadow1D       (sampler1DShadow sampler, vec3 coord);
+vec4 shadow2D       (sampler2DShadow sampler, vec3 coord);
+vec4 shadow1DProj   (sampler1DShadow sampler, vec4 coord);
+vec4 shadow2DProj   (sampler2DShadow sampler, vec4 coord);
+vec4 shadow1DLod    (sampler1DShadow sampler, vec3 coord, float lod);
+vec4 shadow2DLod    (sampler2DShadow sampler, vec3 coord, float lod);
+vec4 shadow1DProjLod(sampler1DShadow sampler, vec4 coord, float lod);
+vec4 shadow2DProjLod(sampler2DShadow sampler, vec4 coord, float lod);
+
+/*
+ * 8.8 - Fragment Processing Functions (none in vertex shader)
+ */
+
+/*
+ * 8.9 - Noise Functions
+ */
+float noise1(float x);
+float noise1(vec2  x);
+float noise1(vec3  x);
+float noise1(vec4  x);
+
+vec2  noise2(float x);
+vec2  noise2(vec2  x);
+vec2  noise2(vec3  x);
+vec2  noise2(vec4  x);
+
+vec3  noise3(float x);
+vec3  noise3(vec2  x);
+vec3  noise3(vec3  x);
+vec3  noise3(vec4  x);
+
+vec4  noise4(float x);
+vec4  noise4(vec2  x);
+vec4  noise4(vec3  x);
+vec4  noise4(vec4  x);
diff --git a/src/glsl/builtins/profiles/120.frag b/src/glsl/builtins/profiles/120.frag
new file mode 100644 (file)
index 0000000..a207435
--- /dev/null
@@ -0,0 +1,396 @@
+#version 120
+/*
+ * 8.1 - Angle and Trigonometry Functions
+ */
+float radians(float degrees);
+vec2  radians(vec2  degrees);
+vec3  radians(vec3  degrees);
+vec4  radians(vec4  degrees);
+
+float degrees(float radians);
+vec2  degrees(vec2  radians);
+vec3  degrees(vec3  radians);
+vec4  degrees(vec4  radians);
+
+float sin(float angle);
+vec2  sin(vec2  angle);
+vec3  sin(vec3  angle);
+vec4  sin(vec4  angle);
+
+float cos(float angle);
+vec2  cos(vec2  angle);
+vec3  cos(vec3  angle);
+vec4  cos(vec4  angle);
+
+float tan(float angle);
+vec2  tan(vec2  angle);
+vec3  tan(vec3  angle);
+vec4  tan(vec4  angle);
+
+float asin(float angle);
+vec2  asin(vec2  angle);
+vec3  asin(vec3  angle);
+vec4  asin(vec4  angle);
+
+float acos(float angle);
+vec2  acos(vec2  angle);
+vec3  acos(vec3  angle);
+vec4  acos(vec4  angle);
+
+float atan(float y, float x);
+vec2  atan(vec2  y, vec2  x);
+vec3  atan(vec3  y, vec3  x);
+vec4  atan(vec4  y, vec4  x);
+
+float atan(float y_over_x);
+vec2  atan(vec2  y_over_x);
+vec3  atan(vec3  y_over_x);
+vec4  atan(vec4  y_over_x);
+
+/*
+ * 8.2 - Exponential Functions
+ */
+float pow(float x, float y);
+vec2  pow(vec2  x, vec2  y);
+vec3  pow(vec3  x, vec3  y);
+vec4  pow(vec4  x, vec4  y);
+
+float exp(float x);
+vec2  exp(vec2  x);
+vec3  exp(vec3  x);
+vec4  exp(vec4  x);
+
+float log(float x);
+vec2  log(vec2  x);
+vec3  log(vec3  x);
+vec4  log(vec4  x);
+
+float exp2(float x);
+vec2  exp2(vec2  x);
+vec3  exp2(vec3  x);
+vec4  exp2(vec4  x);
+
+float log2(float x);
+vec2  log2(vec2  x);
+vec3  log2(vec3  x);
+vec4  log2(vec4  x);
+
+float sqrt(float x);
+vec2  sqrt(vec2  x);
+vec3  sqrt(vec3  x);
+vec4  sqrt(vec4  x);
+
+float inversesqrt(float x);
+vec2  inversesqrt(vec2  x);
+vec3  inversesqrt(vec3  x);
+vec4  inversesqrt(vec4  x);
+
+/*
+ * 8.3 - Common Functions
+ */
+float abs(float x);
+vec2  abs(vec2  x);
+vec3  abs(vec3  x);
+vec4  abs(vec4  x);
+
+float sign(float x);
+vec2  sign(vec2  x);
+vec3  sign(vec3  x);
+vec4  sign(vec4  x);
+
+float floor(float x);
+vec2  floor(vec2  x);
+vec3  floor(vec3  x);
+vec4  floor(vec4  x);
+
+float ceil(float x);
+vec2  ceil(vec2  x);
+vec3  ceil(vec3  x);
+vec4  ceil(vec4  x);
+
+float fract(float x);
+vec2  fract(vec2  x);
+vec3  fract(vec3  x);
+vec4  fract(vec4  x);
+
+float mod(float x, float y);
+vec2  mod(vec2  x, float y);
+vec3  mod(vec3  x, float y);
+vec4  mod(vec4  x, float y);
+
+vec2  mod(vec2  x, vec2  y);
+vec3  mod(vec3  x, vec3  y);
+vec4  mod(vec4  x, vec4  y);
+
+float min(float x, float y);
+vec2  min(vec2  x, vec2  y);
+vec3  min(vec3  x, vec3  y);
+vec4  min(vec4  x, vec4  y);
+
+vec2  min(vec2  x, float y);
+vec3  min(vec3  x, float y);
+vec4  min(vec4  x, float y);
+
+float max(float x, float y);
+vec2  max(vec2  x, vec2  y);
+vec3  max(vec3  x, vec3  y);
+vec4  max(vec4  x, vec4  y);
+
+vec2  max(vec2  x, float y);
+vec3  max(vec3  x, float y);
+vec4  max(vec4  x, float y);
+
+float clamp(float x, float minVal, float maxVal);
+vec2  clamp(vec2  x, vec2  minVal, vec2  maxVal);
+vec3  clamp(vec3  x, vec3  minVal, vec3  maxVal);
+vec4  clamp(vec4  x, vec4  minVal, vec4  maxVal);
+
+vec2  clamp(vec2  x, float minVal, float maxVal);
+vec3  clamp(vec3  x, float minVal, float maxVal);
+vec4  clamp(vec4  x, float minVal, float maxVal);
+
+float mix(float x, float y, float a);
+vec2  mix(vec2  x, vec2  y, vec2  a);
+vec3  mix(vec3  x, vec3  y, vec3  a);
+vec4  mix(vec4  x, vec4  y, vec4  a);
+
+vec2  mix(vec2  x, vec2  y, float a);
+vec3  mix(vec3  x, vec3  y, float a);
+vec4  mix(vec4  x, vec4  y, float a);
+
+float step(float edge, float x);
+vec2  step(vec2  edge, vec2  x);
+vec3  step(vec3  edge, vec3  x);
+vec4  step(vec4  edge, vec4  x);
+
+vec2  step(float edge, vec2  x);
+vec3  step(float edge, vec3  x);
+vec4  step(float edge, vec4  x);
+
+float smoothstep(float edge0, float edge1, float x);
+vec2  smoothstep(vec2  edge0, vec2  edge1, vec2  x);
+vec3  smoothstep(vec3  edge0, vec3  edge1, vec3  x);
+vec4  smoothstep(vec4  edge0, vec4  edge1, vec4  x);
+
+vec2  smoothstep(float edge0, float edge1, vec2  x);
+vec3  smoothstep(float edge0, float edge1, vec3  x);
+vec4  smoothstep(float edge0, float edge1, vec4  x);
+
+/*
+ * 8.4 - Geometric Functions
+ */
+float length(float x);
+float length(vec2  x);
+float length(vec3  x);
+float length(vec4  x);
+
+float distance(float p0, float p1);
+float distance(vec2  p0, vec2  p1);
+float distance(vec3  p0, vec3  p1);
+float distance(vec4  p0, vec4  p1);
+
+float dot(float x, float y);
+float dot(vec2  x, vec2  y);
+float dot(vec3  x, vec3  y);
+float dot(vec4  x, vec4  y);
+
+vec3 cross(vec3 x, vec3 y);
+
+float normalize(float x);
+vec2  normalize(vec2  x);
+vec3  normalize(vec3  x);
+vec4  normalize(vec4  x);
+
+float faceforward(float N, float I, float Nref);
+vec2  faceforward(vec2  N, vec2  I, vec2  Nref);
+vec3  faceforward(vec3  N, vec3  I, vec3  Nref);
+vec4  faceforward(vec4  N, vec4  I, vec4  Nref);
+
+float reflect(float I, float N);
+vec2  reflect(vec2  I, vec2  N);
+vec3  reflect(vec3  I, vec3  N);
+vec4  reflect(vec4  I, vec4  N);
+
+float refract(float I, float N, float eta);
+vec2  refract(vec2  I, vec2  N, float eta);
+vec3  refract(vec3  I, vec3  N, float eta);
+vec4  refract(vec4  I, vec4  N, float eta);
+
+
+/*
+ * 8.5 - Matrix Functions
+ */
+mat2   matrixCompMult(mat2   x, mat2   y);
+mat3   matrixCompMult(mat3   x, mat3   y);
+mat4   matrixCompMult(mat4   x, mat4   y);
+mat2x3 matrixCompMult(mat2x3 x, mat2x3 y);
+mat2x4 matrixCompMult(mat2x4 x, mat2x4 y);
+mat3x2 matrixCompMult(mat3x2 x, mat3x2 y);
+mat3x4 matrixCompMult(mat3x4 x, mat3x4 y);
+mat4x2 matrixCompMult(mat4x2 x, mat4x2 y);
+mat4x3 matrixCompMult(mat4x3 x, mat4x3 y);
+
+mat2   outerProduct(vec2 c, vec2 r);
+mat3   outerProduct(vec3 c, vec3 r);
+mat4   outerProduct(vec4 c, vec4 r);
+
+mat2x3 outerProduct(vec3 c, vec2 r);
+mat3x2 outerProduct(vec2 c, vec3 r);
+
+mat2x4 outerProduct(vec4 c, vec2 r);
+mat4x2 outerProduct(vec2 c, vec4 r);
+
+mat3x4 outerProduct(vec4 c, vec3 r);
+mat4x3 outerProduct(vec3 c, vec4 r);
+
+mat2   transpose(mat2 m);
+mat3   transpose(mat3 m);
+mat4   transpose(mat4 m);
+
+mat2x3 transpose(mat3x2 m);
+mat3x2 transpose(mat2x3 m);
+
+mat2x4 transpose(mat4x2 m);
+mat4x2 transpose(mat2x4 m);
+
+mat3x4 transpose(mat4x3 m);
+mat4x3 transpose(mat3x4 m);
+
+/*
+ * 8.6 - Vector Relational Functions
+ */
+bvec2 lessThan( vec2 x,  vec2 y);
+bvec3 lessThan( vec3 x,  vec3 y);
+bvec4 lessThan( vec4 x,  vec4 y);
+bvec2 lessThan(ivec2 x, ivec2 y);
+bvec3 lessThan(ivec3 x, ivec3 y);
+bvec4 lessThan(ivec4 x, ivec4 y);
+
+bvec2 lessThanEqual( vec2 x,  vec2 y);
+bvec3 lessThanEqual( vec3 x,  vec3 y);
+bvec4 lessThanEqual( vec4 x,  vec4 y);
+bvec2 lessThanEqual(ivec2 x, ivec2 y);
+bvec3 lessThanEqual(ivec3 x, ivec3 y);
+bvec4 lessThanEqual(ivec4 x, ivec4 y);
+
+bvec2 greaterThan( vec2 x,  vec2 y);
+bvec3 greaterThan( vec3 x,  vec3 y);
+bvec4 greaterThan( vec4 x,  vec4 y);
+bvec2 greaterThan(ivec2 x, ivec2 y);
+bvec3 greaterThan(ivec3 x, ivec3 y);
+bvec4 greaterThan(ivec4 x, ivec4 y);
+
+bvec2 greaterThanEqual( vec2 x,  vec2 y);
+bvec3 greaterThanEqual( vec3 x,  vec3 y);
+bvec4 greaterThanEqual( vec4 x,  vec4 y);
+bvec2 greaterThanEqual(ivec2 x, ivec2 y);
+bvec3 greaterThanEqual(ivec3 x, ivec3 y);
+bvec4 greaterThanEqual(ivec4 x, ivec4 y);
+
+bvec2 equal( vec2 x,  vec2 y);
+bvec3 equal( vec3 x,  vec3 y);
+bvec4 equal( vec4 x,  vec4 y);
+bvec2 equal(ivec2 x, ivec2 y);
+bvec3 equal(ivec3 x, ivec3 y);
+bvec4 equal(ivec4 x, ivec4 y);
+bvec2 equal(bvec2 x, bvec2 y);
+bvec3 equal(bvec3 x, bvec3 y);
+bvec4 equal(bvec4 x, bvec4 y);
+
+bvec2 notEqual( vec2 x,  vec2 y);
+bvec3 notEqual( vec3 x,  vec3 y);
+bvec4 notEqual( vec4 x,  vec4 y);
+bvec2 notEqual(ivec2 x, ivec2 y);
+bvec3 notEqual(ivec3 x, ivec3 y);
+bvec4 notEqual(ivec4 x, ivec4 y);
+bvec2 notEqual(bvec2 x, bvec2 y);
+bvec3 notEqual(bvec3 x, bvec3 y);
+bvec4 notEqual(bvec4 x, bvec4 y);
+
+bool any(bvec2 x);
+bool any(bvec3 x);
+bool any(bvec4 x);
+
+bool all(bvec2 x);
+bool all(bvec3 x);
+bool all(bvec4 x);
+
+bvec2 not(bvec2 x);
+bvec3 not(bvec3 x);
+bvec4 not(bvec4 x);
+
+/*
+ * 8.7 - Texture Lookup Functions
+ */
+vec4 texture1D       (sampler1D sampler, float coord);
+vec4 texture1DProj   (sampler1D sampler, vec2  coord);
+vec4 texture1DProj   (sampler1D sampler, vec4  coord);
+vec4 texture1D       (sampler1D sampler, float coord, float bias);
+vec4 texture1DProj   (sampler1D sampler, vec2  coord, float bias);
+vec4 texture1DProj   (sampler1D sampler, vec4  coord, float bias);
+
+vec4 texture2D       (sampler2D sampler, vec2 coord);
+vec4 texture2DProj   (sampler2D sampler, vec3 coord);
+vec4 texture2DProj   (sampler2D sampler, vec4 coord);
+vec4 texture2D       (sampler2D sampler, vec2 coord, float bias);
+vec4 texture2DProj   (sampler2D sampler, vec3 coord, float bias);
+vec4 texture2DProj   (sampler2D sampler, vec4 coord, float bias);
+
+vec4 texture3D       (sampler3D sampler, vec3 coord);
+vec4 texture3DProj   (sampler3D sampler, vec4 coord);
+vec4 texture3D       (sampler3D sampler, vec3 coord, float bias);
+vec4 texture3DProj   (sampler3D sampler, vec4 coord, float bias);
+
+vec4 textureCube     (samplerCube sampler, vec3 coord);
+vec4 textureCube     (samplerCube sampler, vec3 coord, float bias);
+
+vec4 shadow1D       (sampler1DShadow sampler, vec3 coord);
+vec4 shadow2D       (sampler2DShadow sampler, vec3 coord);
+vec4 shadow1DProj   (sampler1DShadow sampler, vec4 coord);
+vec4 shadow2DProj   (sampler2DShadow sampler, vec4 coord);
+vec4 shadow1D       (sampler1DShadow sampler, vec3 coord, float bias);
+vec4 shadow2D       (sampler2DShadow sampler, vec3 coord, float bias);
+vec4 shadow1DProj   (sampler1DShadow sampler, vec4 coord, float bias);
+vec4 shadow2DProj   (sampler2DShadow sampler, vec4 coord, float bias);
+
+
+/*
+ * 8.8 - Fragment Processing Functions
+ */
+float dFdx(float p);
+vec2  dFdx(vec2  p);
+vec3  dFdx(vec3  p);
+vec4  dFdx(vec4  p);
+
+float dFdy(float p);
+vec2  dFdy(vec2  p);
+vec3  dFdy(vec3  p);
+vec4  dFdy(vec4  p);
+
+float fwidth(float p);
+vec2  fwidth(vec2  p);
+vec3  fwidth(vec3  p);
+vec4  fwidth(vec4  p);
+
+/*
+ * 8.9 - Noise Functions
+ */
+float noise1(float x);
+float noise1(vec2  x);
+float noise1(vec3  x);
+float noise1(vec4  x);
+
+vec2  noise2(float x);
+vec2  noise2(vec2  x);
+vec2  noise2(vec3  x);
+vec2  noise2(vec4  x);
+
+vec3  noise3(float x);
+vec3  noise3(vec2  x);
+vec3  noise3(vec3  x);
+vec3  noise3(vec4  x);
+
+vec4  noise4(float x);
+vec4  noise4(vec2  x);
+vec4  noise4(vec3  x);
+vec4  noise4(vec4  x);
diff --git a/src/glsl/builtins/profiles/120.vert b/src/glsl/builtins/profiles/120.vert
new file mode 100644 (file)
index 0000000..e14c931
--- /dev/null
@@ -0,0 +1,383 @@
+#version 120
+/*
+ * 8.1 - Angle and Trigonometry Functions
+ */
+float radians(float degrees);
+vec2  radians(vec2  degrees);
+vec3  radians(vec3  degrees);
+vec4  radians(vec4  degrees);
+
+float degrees(float radians);
+vec2  degrees(vec2  radians);
+vec3  degrees(vec3  radians);
+vec4  degrees(vec4  radians);
+
+float sin(float angle);
+vec2  sin(vec2  angle);
+vec3  sin(vec3  angle);
+vec4  sin(vec4  angle);
+
+float cos(float angle);
+vec2  cos(vec2  angle);
+vec3  cos(vec3  angle);
+vec4  cos(vec4  angle);
+
+float tan(float angle);
+vec2  tan(vec2  angle);
+vec3  tan(vec3  angle);
+vec4  tan(vec4  angle);
+
+float asin(float angle);
+vec2  asin(vec2  angle);
+vec3  asin(vec3  angle);
+vec4  asin(vec4  angle);
+
+float acos(float angle);
+vec2  acos(vec2  angle);
+vec3  acos(vec3  angle);
+vec4  acos(vec4  angle);
+
+float atan(float y, float x);
+vec2  atan(vec2  y, vec2  x);
+vec3  atan(vec3  y, vec3  x);
+vec4  atan(vec4  y, vec4  x);
+
+float atan(float y_over_x);
+vec2  atan(vec2  y_over_x);
+vec3  atan(vec3  y_over_x);
+vec4  atan(vec4  y_over_x);
+
+/*
+ * 8.2 - Exponential Functions
+ */
+float pow(float x, float y);
+vec2  pow(vec2  x, vec2  y);
+vec3  pow(vec3  x, vec3  y);
+vec4  pow(vec4  x, vec4  y);
+
+float exp(float x);
+vec2  exp(vec2  x);
+vec3  exp(vec3  x);
+vec4  exp(vec4  x);
+
+float log(float x);
+vec2  log(vec2  x);
+vec3  log(vec3  x);
+vec4  log(vec4  x);
+
+float exp2(float x);
+vec2  exp2(vec2  x);
+vec3  exp2(vec3  x);
+vec4  exp2(vec4  x);
+
+float log2(float x);
+vec2  log2(vec2  x);
+vec3  log2(vec3  x);
+vec4  log2(vec4  x);
+
+float sqrt(float x);
+vec2  sqrt(vec2  x);
+vec3  sqrt(vec3  x);
+vec4  sqrt(vec4  x);
+
+float inversesqrt(float x);
+vec2  inversesqrt(vec2  x);
+vec3  inversesqrt(vec3  x);
+vec4  inversesqrt(vec4  x);
+
+/*
+ * 8.3 - Common Functions
+ */
+float abs(float x);
+vec2  abs(vec2  x);
+vec3  abs(vec3  x);
+vec4  abs(vec4  x);
+
+float sign(float x);
+vec2  sign(vec2  x);
+vec3  sign(vec3  x);
+vec4  sign(vec4  x);
+
+float floor(float x);
+vec2  floor(vec2  x);
+vec3  floor(vec3  x);
+vec4  floor(vec4  x);
+
+float ceil(float x);
+vec2  ceil(vec2  x);
+vec3  ceil(vec3  x);
+vec4  ceil(vec4  x);
+
+float fract(float x);
+vec2  fract(vec2  x);
+vec3  fract(vec3  x);
+vec4  fract(vec4  x);
+
+float mod(float x, float y);
+vec2  mod(vec2  x, float y);
+vec3  mod(vec3  x, float y);
+vec4  mod(vec4  x, float y);
+
+vec2  mod(vec2  x, vec2  y);
+vec3  mod(vec3  x, vec3  y);
+vec4  mod(vec4  x, vec4  y);
+
+float min(float x, float y);
+vec2  min(vec2  x, vec2  y);
+vec3  min(vec3  x, vec3  y);
+vec4  min(vec4  x, vec4  y);
+
+vec2  min(vec2  x, float y);
+vec3  min(vec3  x, float y);
+vec4  min(vec4  x, float y);
+
+float max(float x, float y);
+vec2  max(vec2  x, vec2  y);
+vec3  max(vec3  x, vec3  y);
+vec4  max(vec4  x, vec4  y);
+
+vec2  max(vec2  x, float y);
+vec3  max(vec3  x, float y);
+vec4  max(vec4  x, float y);
+
+float clamp(float x, float minVal, float maxVal);
+vec2  clamp(vec2  x, vec2  minVal, vec2  maxVal);
+vec3  clamp(vec3  x, vec3  minVal, vec3  maxVal);
+vec4  clamp(vec4  x, vec4  minVal, vec4  maxVal);
+
+vec2  clamp(vec2  x, float minVal, float maxVal);
+vec3  clamp(vec3  x, float minVal, float maxVal);
+vec4  clamp(vec4  x, float minVal, float maxVal);
+
+float mix(float x, float y, float a);
+vec2  mix(vec2  x, vec2  y, vec2  a);
+vec3  mix(vec3  x, vec3  y, vec3  a);
+vec4  mix(vec4  x, vec4  y, vec4  a);
+
+vec2  mix(vec2  x, vec2  y, float a);
+vec3  mix(vec3  x, vec3  y, float a);
+vec4  mix(vec4  x, vec4  y, float a);
+
+float step(float edge, float x);
+vec2  step(vec2  edge, vec2  x);
+vec3  step(vec3  edge, vec3  x);
+vec4  step(vec4  edge, vec4  x);
+
+vec2  step(float edge, vec2  x);
+vec3  step(float edge, vec3  x);
+vec4  step(float edge, vec4  x);
+
+float smoothstep(float edge0, float edge1, float x);
+vec2  smoothstep(vec2  edge0, vec2  edge1, vec2  x);
+vec3  smoothstep(vec3  edge0, vec3  edge1, vec3  x);
+vec4  smoothstep(vec4  edge0, vec4  edge1, vec4  x);
+
+vec2  smoothstep(float edge0, float edge1, vec2  x);
+vec3  smoothstep(float edge0, float edge1, vec3  x);
+vec4  smoothstep(float edge0, float edge1, vec4  x);
+
+/*
+ * 8.4 - Geometric Functions
+ */
+float length(float x);
+float length(vec2  x);
+float length(vec3  x);
+float length(vec4  x);
+
+float distance(float p0, float p1);
+float distance(vec2  p0, vec2  p1);
+float distance(vec3  p0, vec3  p1);
+float distance(vec4  p0, vec4  p1);
+
+float dot(float x, float y);
+float dot(vec2  x, vec2  y);
+float dot(vec3  x, vec3  y);
+float dot(vec4  x, vec4  y);
+
+vec3 cross(vec3 x, vec3 y);
+
+float normalize(float x);
+vec2  normalize(vec2  x);
+vec3  normalize(vec3  x);
+vec4  normalize(vec4  x);
+
+vec4 ftransform();
+
+float faceforward(float N, float I, float Nref);
+vec2  faceforward(vec2  N, vec2  I, vec2  Nref);
+vec3  faceforward(vec3  N, vec3  I, vec3  Nref);
+vec4  faceforward(vec4  N, vec4  I, vec4  Nref);
+
+float reflect(float I, float N);
+vec2  reflect(vec2  I, vec2  N);
+vec3  reflect(vec3  I, vec3  N);
+vec4  reflect(vec4  I, vec4  N);
+
+float refract(float I, float N, float eta);
+vec2  refract(vec2  I, vec2  N, float eta);
+vec3  refract(vec3  I, vec3  N, float eta);
+vec4  refract(vec4  I, vec4  N, float eta);
+
+
+/*
+ * 8.5 - Matrix Functions
+ */
+mat2   matrixCompMult(mat2   x, mat2   y);
+mat3   matrixCompMult(mat3   x, mat3   y);
+mat4   matrixCompMult(mat4   x, mat4   y);
+mat2x3 matrixCompMult(mat2x3 x, mat2x3 y);
+mat2x4 matrixCompMult(mat2x4 x, mat2x4 y);
+mat3x2 matrixCompMult(mat3x2 x, mat3x2 y);
+mat3x4 matrixCompMult(mat3x4 x, mat3x4 y);
+mat4x2 matrixCompMult(mat4x2 x, mat4x2 y);
+mat4x3 matrixCompMult(mat4x3 x, mat4x3 y);
+
+mat2   outerProduct(vec2 c, vec2 r);
+mat3   outerProduct(vec3 c, vec3 r);
+mat4   outerProduct(vec4 c, vec4 r);
+
+mat2x3 outerProduct(vec3 c, vec2 r);
+mat3x2 outerProduct(vec2 c, vec3 r);
+
+mat2x4 outerProduct(vec4 c, vec2 r);
+mat4x2 outerProduct(vec2 c, vec4 r);
+
+mat3x4 outerProduct(vec4 c, vec3 r);
+mat4x3 outerProduct(vec3 c, vec4 r);
+
+mat2   transpose(mat2 m);
+mat3   transpose(mat3 m);
+mat4   transpose(mat4 m);
+
+mat2x3 transpose(mat3x2 m);
+mat3x2 transpose(mat2x3 m);
+
+mat2x4 transpose(mat4x2 m);
+mat4x2 transpose(mat2x4 m);
+
+mat3x4 transpose(mat4x3 m);
+mat4x3 transpose(mat3x4 m);
+
+/*
+ * 8.6 - Vector Relational Functions
+ */
+bvec2 lessThan( vec2 x,  vec2 y);
+bvec3 lessThan( vec3 x,  vec3 y);
+bvec4 lessThan( vec4 x,  vec4 y);
+bvec2 lessThan(ivec2 x, ivec2 y);
+bvec3 lessThan(ivec3 x, ivec3 y);
+bvec4 lessThan(ivec4 x, ivec4 y);
+
+bvec2 lessThanEqual( vec2 x,  vec2 y);
+bvec3 lessThanEqual( vec3 x,  vec3 y);
+bvec4 lessThanEqual( vec4 x,  vec4 y);
+bvec2 lessThanEqual(ivec2 x, ivec2 y);
+bvec3 lessThanEqual(ivec3 x, ivec3 y);
+bvec4 lessThanEqual(ivec4 x, ivec4 y);
+
+bvec2 greaterThan( vec2 x,  vec2 y);
+bvec3 greaterThan( vec3 x,  vec3 y);
+bvec4 greaterThan( vec4 x,  vec4 y);
+bvec2 greaterThan(ivec2 x, ivec2 y);
+bvec3 greaterThan(ivec3 x, ivec3 y);
+bvec4 greaterThan(ivec4 x, ivec4 y);
+
+bvec2 greaterThanEqual( vec2 x,  vec2 y);
+bvec3 greaterThanEqual( vec3 x,  vec3 y);
+bvec4 greaterThanEqual( vec4 x,  vec4 y);
+bvec2 greaterThanEqual(ivec2 x, ivec2 y);
+bvec3 greaterThanEqual(ivec3 x, ivec3 y);
+bvec4 greaterThanEqual(ivec4 x, ivec4 y);
+
+bvec2 equal( vec2 x,  vec2 y);
+bvec3 equal( vec3 x,  vec3 y);
+bvec4 equal( vec4 x,  vec4 y);
+bvec2 equal(ivec2 x, ivec2 y);
+bvec3 equal(ivec3 x, ivec3 y);
+bvec4 equal(ivec4 x, ivec4 y);
+bvec2 equal(bvec2 x, bvec2 y);
+bvec3 equal(bvec3 x, bvec3 y);
+bvec4 equal(bvec4 x, bvec4 y);
+
+bvec2 notEqual( vec2 x,  vec2 y);
+bvec3 notEqual( vec3 x,  vec3 y);
+bvec4 notEqual( vec4 x,  vec4 y);
+bvec2 notEqual(ivec2 x, ivec2 y);
+bvec3 notEqual(ivec3 x, ivec3 y);
+bvec4 notEqual(ivec4 x, ivec4 y);
+bvec2 notEqual(bvec2 x, bvec2 y);
+bvec3 notEqual(bvec3 x, bvec3 y);
+bvec4 notEqual(bvec4 x, bvec4 y);
+
+bool any(bvec2 x);
+bool any(bvec3 x);
+bool any(bvec4 x);
+
+bool all(bvec2 x);
+bool all(bvec3 x);
+bool all(bvec4 x);
+
+bvec2 not(bvec2 x);
+bvec3 not(bvec3 x);
+bvec4 not(bvec4 x);
+
+/*
+ * 8.7 - Texture Lookup Functions
+ */
+vec4 texture1D       (sampler1D sampler, float coord);
+vec4 texture1DProj   (sampler1D sampler, vec2  coord);
+vec4 texture1DProj   (sampler1D sampler, vec4  coord);
+vec4 texture1DLod    (sampler1D sampler, float coord, float lod);
+vec4 texture1DProjLod(sampler1D sampler, vec2  coord, float lod);
+vec4 texture1DProjLod(sampler1D sampler, vec4  coord, float lod);
+
+vec4 texture2D       (sampler2D sampler, vec2 coord);
+vec4 texture2DProj   (sampler2D sampler, vec3 coord);
+vec4 texture2DProj   (sampler2D sampler, vec4 coord);
+vec4 texture2DLod    (sampler2D sampler, vec2 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);
+
+vec4 texture3D       (sampler3D sampler, vec3 coord);
+vec4 texture3DProj   (sampler3D sampler, vec4 coord);
+vec4 texture3DLod    (sampler3D sampler, vec3 coord, float lod);
+vec4 texture3DProjLod(sampler3D sampler, vec4 coord, float lod);
+
+vec4 textureCube     (samplerCube sampler, vec3 coord);
+vec4 textureCubeLod  (samplerCube sampler, vec3 coord, float lod);
+
+vec4 shadow1D       (sampler1DShadow sampler, vec3 coord);
+vec4 shadow2D       (sampler2DShadow sampler, vec3 coord);
+vec4 shadow1DProj   (sampler1DShadow sampler, vec4 coord);
+vec4 shadow2DProj   (sampler2DShadow sampler, vec4 coord);
+vec4 shadow1DLod    (sampler1DShadow sampler, vec3 coord, float lod);
+vec4 shadow2DLod    (sampler2DShadow sampler, vec3 coord, float lod);
+vec4 shadow1DProjLod(sampler1DShadow sampler, vec4 coord, float lod);
+vec4 shadow2DProjLod(sampler2DShadow sampler, vec4 coord, float lod);
+
+/*
+ * 8.8 - Fragment Processing Functions (none in vertex shader)
+ */
+
+/*
+ * 8.9 - Noise Functions
+ */
+float noise1(float x);
+float noise1(vec2  x);
+float noise1(vec3  x);
+float noise1(vec4  x);
+
+vec2  noise2(float x);
+vec2  noise2(vec2  x);
+vec2  noise2(vec3  x);
+vec2  noise2(vec4  x);
+
+vec3  noise3(float x);
+vec3  noise3(vec2  x);
+vec3  noise3(vec3  x);
+vec3  noise3(vec4  x);
+
+vec4  noise4(float x);
+vec4  noise4(vec2  x);
+vec4  noise4(vec3  x);
+vec4  noise4(vec4  x);
diff --git a/src/glsl/builtins/profiles/130.frag b/src/glsl/builtins/profiles/130.frag
new file mode 100644 (file)
index 0000000..aa7a6ad
--- /dev/null
@@ -0,0 +1,1031 @@
+#version 130
+/*
+ * 8.1 - Angle and Trigonometry Functions
+ */
+float radians(float degrees);
+vec2  radians(vec2  degrees);
+vec3  radians(vec3  degrees);
+vec4  radians(vec4  degrees);
+
+float degrees(float radians);
+vec2  degrees(vec2  radians);
+vec3  degrees(vec3  radians);
+vec4  degrees(vec4  radians);
+
+float sin(float angle);
+vec2  sin(vec2  angle);
+vec3  sin(vec3  angle);
+vec4  sin(vec4  angle);
+
+float cos(float angle);
+vec2  cos(vec2  angle);
+vec3  cos(vec3  angle);
+vec4  cos(vec4  angle);
+
+float tan(float angle);
+vec2  tan(vec2  angle);
+vec3  tan(vec3  angle);
+vec4  tan(vec4  angle);
+
+float asin(float angle);
+vec2  asin(vec2  angle);
+vec3  asin(vec3  angle);
+vec4  asin(vec4  angle);
+
+float acos(float angle);
+vec2  acos(vec2  angle);
+vec3  acos(vec3  angle);
+vec4  acos(vec4  angle);
+
+float atan(float y, float x);
+vec2  atan(vec2  y, vec2  x);
+vec3  atan(vec3  y, vec3  x);
+vec4  atan(vec4  y, vec4  x);
+
+float atan(float y_over_x);
+vec2  atan(vec2  y_over_x);
+vec3  atan(vec3  y_over_x);
+vec4  atan(vec4  y_over_x);
+
+float sinh(float x);
+vec2  sinh(vec2  x);
+vec3  sinh(vec3  x);
+vec4  sinh(vec4  x);
+
+float cosh(float x);
+vec2  cosh(vec2  x);
+vec3  cosh(vec3  x);
+vec4  cosh(vec4  x);
+
+float tanh(float x);
+vec2  tanh(vec2  x);
+vec3  tanh(vec3  x);
+vec4  tanh(vec4  x);
+
+#if 0
+float asinh(float x);
+vec2  asinh(vec2  x);
+vec3  asinh(vec3  x);
+vec4  asinh(vec4  x);
+
+float acosh(float x);
+vec2  acosh(vec2  x);
+vec3  acosh(vec3  x);
+vec4  acosh(vec4  x);
+
+float atanh(float x);
+vec2  atanh(vec2  x);
+vec3  atanh(vec3  x);
+vec4  atanh(vec4  x);
+#endif
+
+/*
+ * 8.2 - Exponential Functions
+ */
+float pow(float x, float y);
+vec2  pow(vec2  x, vec2  y);
+vec3  pow(vec3  x, vec3  y);
+vec4  pow(vec4  x, vec4  y);
+
+float exp(float x);
+vec2  exp(vec2  x);
+vec3  exp(vec3  x);
+vec4  exp(vec4  x);
+
+float log(float x);
+vec2  log(vec2  x);
+vec3  log(vec3  x);
+vec4  log(vec4  x);
+
+float exp2(float x);
+vec2  exp2(vec2  x);
+vec3  exp2(vec3  x);
+vec4  exp2(vec4  x);
+
+float log2(float x);
+vec2  log2(vec2  x);
+vec3  log2(vec3  x);
+vec4  log2(vec4  x);
+
+float sqrt(float x);
+vec2  sqrt(vec2  x);
+vec3  sqrt(vec3  x);
+vec4  sqrt(vec4  x);
+
+float inversesqrt(float x);
+vec2  inversesqrt(vec2  x);
+vec3  inversesqrt(vec3  x);
+vec4  inversesqrt(vec4  x);
+
+/*
+ * 8.3 - Common Functions
+ */
+float abs(float x);
+vec2  abs(vec2  x);
+vec3  abs(vec3  x);
+vec4  abs(vec4  x);
+int   abs(int   x);
+ivec2 abs(ivec2 x);
+ivec3 abs(ivec3 x);
+ivec4 abs(ivec4 x);
+
+float sign(float x);
+vec2  sign(vec2  x);
+vec3  sign(vec3  x);
+vec4  sign(vec4  x);
+int   sign(int   x);
+ivec2 sign(ivec2 x);
+ivec3 sign(ivec3 x);
+ivec4 sign(ivec4 x);
+
+float floor(float x);
+vec2  floor(vec2  x);
+vec3  floor(vec3  x);
+vec4  floor(vec4  x);
+
+float ceil(float x);
+vec2  ceil(vec2  x);
+vec3  ceil(vec3  x);
+vec4  ceil(vec4  x);
+
+float fract(float x);
+vec2  fract(vec2  x);
+vec3  fract(vec3  x);
+vec4  fract(vec4  x);
+
+float mod(float x, float y);
+vec2  mod(vec2  x, float y);
+vec3  mod(vec3  x, float y);
+vec4  mod(vec4  x, float y);
+
+vec2  mod(vec2  x, vec2  y);
+vec3  mod(vec3  x, vec3  y);
+vec4  mod(vec4  x, vec4  y);
+
+float min(float x, float y);
+vec2  min(vec2  x, vec2  y);
+vec3  min(vec3  x, vec3  y);
+vec4  min(vec4  x, vec4  y);
+
+vec2  min(vec2  x, float y);
+vec3  min(vec3  x, float y);
+vec4  min(vec4  x, float y);
+
+int   min(int   x, int   y);
+ivec2 min(ivec2 x, ivec2 y);
+ivec3 min(ivec3 x, ivec3 y);
+ivec4 min(ivec4 x, ivec4 y);
+
+ivec2 min(ivec2 x, int   y);
+ivec3 min(ivec3 x, int   y);
+ivec4 min(ivec4 x, int   y);
+
+uint  min(uint  x, uint  y);
+uvec2 min(uvec2 x, uvec2 y);
+uvec3 min(uvec3 x, uvec3 y);
+uvec4 min(uvec4 x, uvec4 y);
+
+uvec2 min(uvec2 x, uint  y);
+uvec3 min(uvec3 x, uint  y);
+uvec4 min(uvec4 x, uint  y);
+
+float max(float x, float y);
+vec2  max(vec2  x, vec2  y);
+vec3  max(vec3  x, vec3  y);
+vec4  max(vec4  x, vec4  y);
+
+vec2  max(vec2  x, float y);
+vec3  max(vec3  x, float y);
+vec4  max(vec4  x, float y);
+
+int   max(int   x, int   y);
+ivec2 max(ivec2 x, ivec2 y);
+ivec3 max(ivec3 x, ivec3 y);
+ivec4 max(ivec4 x, ivec4 y);
+
+ivec2 max(ivec2 x, int   y);
+ivec3 max(ivec3 x, int   y);
+ivec4 max(ivec4 x, int   y);
+
+uint  max(uint  x, uint  y);
+uvec2 max(uvec2 x, uvec2 y);
+uvec3 max(uvec3 x, uvec3 y);
+uvec4 max(uvec4 x, uvec4 y);
+
+uvec2 max(uvec2 x, uint  y);
+uvec3 max(uvec3 x, uint  y);
+uvec4 max(uvec4 x, uint  y);
+
+float clamp(float x, float minVal, float maxVal);
+vec2  clamp(vec2  x, vec2  minVal, vec2  maxVal);
+vec3  clamp(vec3  x, vec3  minVal, vec3  maxVal);
+vec4  clamp(vec4  x, vec4  minVal, vec4  maxVal);
+
+vec2  clamp(vec2  x, float minVal, float maxVal);
+vec3  clamp(vec3  x, float minVal, float maxVal);
+vec4  clamp(vec4  x, float minVal, float maxVal);
+
+int   clamp(int   x, int   minVal, int   maxVal);
+ivec2 clamp(ivec2 x, ivec2 minVal, ivec2 maxVal);
+ivec3 clamp(ivec3 x, ivec3 minVal, ivec3 maxVal);
+ivec4 clamp(ivec4 x, ivec4 minVal, ivec4 maxVal);
+
+ivec2 clamp(ivec2 x, int   minVal, int   maxVal);
+ivec3 clamp(ivec3 x, int   minVal, int   maxVal);
+ivec4 clamp(ivec4 x, int   minVal, int   maxVal);
+
+uint  clamp(uint  x, uint  minVal, uint  maxVal);
+uvec2 clamp(uvec2 x, uvec2 minVal, uvec2 maxVal);
+uvec3 clamp(uvec3 x, uvec3 minVal, uvec3 maxVal);
+uvec4 clamp(uvec4 x, uvec4 minVal, uvec4 maxVal);
+
+uvec2 clamp(uvec2 x, uint  minVal, uint  maxVal);
+uvec3 clamp(uvec3 x, uint  minVal, uint  maxVal);
+uvec4 clamp(uvec4 x, uint  minVal, uint  maxVal);
+
+float mix(float x, float y, float a);
+vec2  mix(vec2  x, vec2  y, vec2  a);
+vec3  mix(vec3  x, vec3  y, vec3  a);
+vec4  mix(vec4  x, vec4  y, vec4  a);
+
+vec2  mix(vec2  x, vec2  y, float a);
+vec3  mix(vec3  x, vec3  y, float a);
+vec4  mix(vec4  x, vec4  y, float a);
+
+float step(float edge, float x);
+vec2  step(vec2  edge, vec2  x);
+vec3  step(vec3  edge, vec3  x);
+vec4  step(vec4  edge, vec4  x);
+
+vec2  step(float edge, vec2  x);
+vec3  step(float edge, vec3  x);
+vec4  step(float edge, vec4  x);
+
+float smoothstep(float edge0, float edge1, float x);
+vec2  smoothstep(vec2  edge0, vec2  edge1, vec2  x);
+vec3  smoothstep(vec3  edge0, vec3  edge1, vec3  x);
+vec4  smoothstep(vec4  edge0, vec4  edge1, vec4  x);
+
+vec2  smoothstep(float edge0, float edge1, vec2  x);
+vec3  smoothstep(float edge0, float edge1, vec3  x);
+vec4  smoothstep(float edge0, float edge1, vec4  x);
+
+#if 0
+bool  isnan(float x);
+bvec2 isnan(vec2  x);
+bvec3 isnan(vec3  x);
+bvec4 isnan(vec4  x);
+
+bool  isinf(float x);
+bvec2 isinf(vec2  x);
+bvec3 isinf(vec3  x);
+bvec4 isinf(vec4  x);
+#endif
+
+/*
+ * 8.4 - Geometric Functions
+ */
+float length(float x);
+float length(vec2  x);
+float length(vec3  x);
+float length(vec4  x);
+
+float distance(float p0, float p1);
+float distance(vec2  p0, vec2  p1);
+float distance(vec3  p0, vec3  p1);
+float distance(vec4  p0, vec4  p1);
+
+float dot(float x, float y);
+float dot(vec2  x, vec2  y);
+float dot(vec3  x, vec3  y);
+float dot(vec4  x, vec4  y);
+
+vec3 cross(vec3 x, vec3 y);
+
+float normalize(float x);
+vec2  normalize(vec2  x);
+vec3  normalize(vec3  x);
+vec4  normalize(vec4  x);
+
+float faceforward(float N, float I, float Nref);
+vec2  faceforward(vec2  N, vec2  I, vec2  Nref);
+vec3  faceforward(vec3  N, vec3  I, vec3  Nref);
+vec4  faceforward(vec4  N, vec4  I, vec4  Nref);
+
+float reflect(float I, float N);
+vec2  reflect(vec2  I, vec2  N);
+vec3  reflect(vec3  I, vec3  N);
+vec4  reflect(vec4  I, vec4  N);
+
+float refract(float I, float N, float eta);
+vec2  refract(vec2  I, vec2  N, float eta);
+vec3  refract(vec3  I, vec3  N, float eta);
+vec4  refract(vec4  I, vec4  N, float eta);
+
+
+/*
+ * 8.5 - Matrix Functions
+ */
+mat2   matrixCompMult(mat2   x, mat2   y);
+mat3   matrixCompMult(mat3   x, mat3   y);
+mat4   matrixCompMult(mat4   x, mat4   y);
+mat2x3 matrixCompMult(mat2x3 x, mat2x3 y);
+mat2x4 matrixCompMult(mat2x4 x, mat2x4 y);
+mat3x2 matrixCompMult(mat3x2 x, mat3x2 y);
+mat3x4 matrixCompMult(mat3x4 x, mat3x4 y);
+mat4x2 matrixCompMult(mat4x2 x, mat4x2 y);
+mat4x3 matrixCompMult(mat4x3 x, mat4x3 y);
+
+mat2   outerProduct(vec2 c, vec2 r);
+mat3   outerProduct(vec3 c, vec3 r);
+mat4   outerProduct(vec4 c, vec4 r);
+
+mat2x3 outerProduct(vec3 c, vec2 r);
+mat3x2 outerProduct(vec2 c, vec3 r);
+
+mat2x4 outerProduct(vec4 c, vec2 r);
+mat4x2 outerProduct(vec2 c, vec4 r);
+
+mat3x4 outerProduct(vec4 c, vec3 r);
+mat4x3 outerProduct(vec3 c, vec4 r);
+
+mat2   transpose(mat2 m);
+mat3   transpose(mat3 m);
+mat4   transpose(mat4 m);
+
+mat2x3 transpose(mat3x2 m);
+mat3x2 transpose(mat2x3 m);
+
+mat2x4 transpose(mat4x2 m);
+mat4x2 transpose(mat2x4 m);
+
+mat3x4 transpose(mat4x3 m);
+mat4x3 transpose(mat3x4 m);
+
+/*
+ * 8.6 - Vector Relational Functions
+ */
+bvec2 lessThan( vec2 x,  vec2 y);
+bvec3 lessThan( vec3 x,  vec3 y);
+bvec4 lessThan( vec4 x,  vec4 y);
+bvec2 lessThan(ivec2 x, ivec2 y);
+bvec3 lessThan(ivec3 x, ivec3 y);
+bvec4 lessThan(ivec4 x, ivec4 y);
+bvec2 lessThan(uvec2 x, uvec2 y);
+bvec3 lessThan(uvec3 x, uvec3 y);
+bvec4 lessThan(uvec4 x, uvec4 y);
+
+bvec2 lessThanEqual( vec2 x,  vec2 y);
+bvec3 lessThanEqual( vec3 x,  vec3 y);
+bvec4 lessThanEqual( vec4 x,  vec4 y);
+bvec2 lessThanEqual(ivec2 x, ivec2 y);
+bvec3 lessThanEqual(ivec3 x, ivec3 y);
+bvec4 lessThanEqual(ivec4 x, ivec4 y);
+bvec2 lessThanEqual(uvec2 x, uvec2 y);
+bvec3 lessThanEqual(uvec3 x, uvec3 y);
+bvec4 lessThanEqual(uvec4 x, uvec4 y);
+
+bvec2 greaterThan( vec2 x,  vec2 y);
+bvec3 greaterThan( vec3 x,  vec3 y);
+bvec4 greaterThan( vec4 x,  vec4 y);
+bvec2 greaterThan(ivec2 x, ivec2 y);
+bvec3 greaterThan(ivec3 x, ivec3 y);
+bvec4 greaterThan(ivec4 x, ivec4 y);
+bvec2 greaterThan(uvec2 x, uvec2 y);
+bvec3 greaterThan(uvec3 x, uvec3 y);
+bvec4 greaterThan(uvec4 x, uvec4 y);
+
+bvec2 greaterThanEqual( vec2 x,  vec2 y);
+bvec3 greaterThanEqual( vec3 x,  vec3 y);
+bvec4 greaterThanEqual( vec4 x,  vec4 y);
+bvec2 greaterThanEqual(ivec2 x, ivec2 y);
+bvec3 greaterThanEqual(ivec3 x, ivec3 y);
+bvec4 greaterThanEqual(ivec4 x, ivec4 y);
+bvec2 greaterThanEqual(uvec2 x, uvec2 y);
+bvec3 greaterThanEqual(uvec3 x, uvec3 y);
+bvec4 greaterThanEqual(uvec4 x, uvec4 y);
+
+bvec2 equal( vec2 x,  vec2 y);
+bvec3 equal( vec3 x,  vec3 y);
+bvec4 equal( vec4 x,  vec4 y);
+bvec2 equal(ivec2 x, ivec2 y);
+bvec3 equal(ivec3 x, ivec3 y);
+bvec4 equal(ivec4 x, ivec4 y);
+bvec2 equal(uvec2 x, uvec2 y);
+bvec3 equal(uvec3 x, uvec3 y);
+bvec4 equal(uvec4 x, uvec4 y);
+bvec2 equal(bvec2 x, bvec2 y);
+bvec3 equal(bvec3 x, bvec3 y);
+bvec4 equal(bvec4 x, bvec4 y);
+
+bvec2 notEqual( vec2 x,  vec2 y);
+bvec3 notEqual( vec3 x,  vec3 y);
+bvec4 notEqual( vec4 x,  vec4 y);
+bvec2 notEqual(ivec2 x, ivec2 y);
+bvec3 notEqual(ivec3 x, ivec3 y);
+bvec4 notEqual(ivec4 x, ivec4 y);
+bvec2 notEqual(uvec2 x, uvec2 y);
+bvec3 notEqual(uvec3 x, uvec3 y);
+bvec4 notEqual(uvec4 x, uvec4 y);
+bvec2 notEqual(bvec2 x, bvec2 y);
+bvec3 notEqual(bvec3 x, bvec3 y);
+bvec4 notEqual(bvec4 x, bvec4 y);
+
+bool any(bvec2 x);
+bool any(bvec3 x);
+bool any(bvec4 x);
+
+bool all(bvec2 x);
+bool all(bvec3 x);
+bool all(bvec4 x);
+
+bvec2 not(bvec2 x);
+bvec3 not(bvec3 x);
+bvec4 not(bvec4 x);
+
+/*
+ * 8.7 - Texture Lookup Functions
+ */
+
+#if 0
+/* textureSize */
+int   textureSize( sampler1D sampler, int lod);
+int   textureSize(isampler1D sampler, int lod);
+int   textureSize(usampler1D sampler, int lod);
+
+ivec2 textureSize( sampler2D sampler, int lod);
+ivec2 textureSize(isampler2D sampler, int lod);
+ivec2 textureSize(usampler2D sampler, int lod);
+
+ivec3 textureSize( sampler3D sampler, int lod);
+ivec3 textureSize(isampler3D sampler, int lod);
+ivec3 textureSize(usampler3D sampler, int lod);
+
+ivec2 textureSize( samplerCube sampler, int lod);
+ivec2 textureSize(isamplerCube sampler, int lod);
+ivec2 textureSize(usamplerCube sampler, int lod);
+
+int   textureSize(sampler1DShadow   sampler, int lod);
+ivec2 textureSize(sampler2DShadow   sampler, int lod);
+ivec2 textureSize(samplerCubeShadow sampler, int lod);
+
+ivec2 textureSize( sampler1DArray sampler, int lod);
+ivec2 textureSize(isampler1DArray sampler, int lod);
+ivec2 textureSize(usampler1DArray sampler, int lod);
+ivec3 textureSize( sampler2DArray sampler, int lod);
+ivec2 textureSize(isampler2DArray sampler, int lod);
+ivec2 textureSize(usampler2DArray sampler, int lod);
+
+ivec2 textureSize(sampler1DArrayShadow sampler, int lod);
+ivec3 textureSize(sampler2DArrayShadow sampler, int lod);
+#endif
+
+/* texture - no bias */
+ vec4 texture( sampler1D sampler, float P);
+ivec4 texture(isampler1D sampler, float P);
+uvec4 texture(usampler1D sampler, float P);
+
+ vec4 texture( sampler2D sampler, vec2 P);
+ivec4 texture(isampler2D sampler, vec2 P);
+uvec4 texture(usampler2D sampler, vec2 P);
+
+ vec4 texture( sampler3D sampler, vec3 P);
+ivec4 texture(isampler3D sampler, vec3 P);
+uvec4 texture(usampler3D sampler, vec3 P);
+
+ vec4 texture( samplerCube sampler, vec3 P);
+ivec4 texture(isamplerCube sampler, vec3 P);
+uvec4 texture(usamplerCube sampler, vec3 P);
+
+float texture(sampler1DShadow   sampler, vec3 P);
+float texture(sampler2DShadow   sampler, vec3 P);
+float texture(samplerCubeShadow sampler, vec4 P);
+
+ vec4 texture( sampler1DArray sampler, vec2 P);
+ivec4 texture(isampler1DArray sampler, vec2 P);
+uvec4 texture(usampler1DArray sampler, vec2 P);
+
+ vec4 texture( sampler2DArray sampler, vec3 P);
+ivec4 texture(isampler2DArray sampler, vec3 P);
+uvec4 texture(usampler2DArray sampler, vec3 P);
+
+float texture(sampler1DArrayShadow sampler, vec3 P);
+float texture(sampler2DArrayShadow sampler, vec4 P);
+
+/* texture - bias variants */
+ vec4 texture( sampler1D sampler, float P, float bias);
+ivec4 texture(isampler1D sampler, float P, float bias);
+uvec4 texture(usampler1D sampler, float P, float bias);
+
+ vec4 texture( sampler2D sampler, vec2 P, float bias);
+ivec4 texture(isampler2D sampler, vec2 P, float bias);
+uvec4 texture(usampler2D sampler, vec2 P, float bias);
+
+ vec4 texture( sampler3D sampler, vec3 P, float bias);
+ivec4 texture(isampler3D sampler, vec3 P, float bias);
+uvec4 texture(usampler3D sampler, vec3 P, float bias);
+
+ vec4 texture( samplerCube sampler, vec3 P, float bias);
+ivec4 texture(isamplerCube sampler, vec3 P, float bias);
+uvec4 texture(usamplerCube sampler, vec3 P, float bias);
+
+float texture(sampler1DShadow   sampler, vec3 P, float bias);
+float texture(sampler2DShadow   sampler, vec3 P, float bias);
+float texture(samplerCubeShadow sampler, vec4 P, float bias);
+
+ vec4 texture( sampler1DArray sampler, vec2 P, float bias);
+ivec4 texture(isampler1DArray sampler, vec2 P, float bias);
+uvec4 texture(usampler1DArray sampler, vec2 P, float bias);
+
+ vec4 texture( sampler2DArray sampler, vec3 P, float bias);
+ivec4 texture(isampler2DArray sampler, vec3 P, float bias);
+uvec4 texture(usampler2DArray sampler, vec3 P, float bias);
+
+float texture(sampler1DArrayShadow sampler, vec3 P, float bias);
+
+/* textureProj - no bias */
+ vec4 textureProj( sampler1D sampler, vec2 P);
+ivec4 textureProj(isampler1D sampler, vec2 P);
+uvec4 textureProj(usampler1D sampler, vec2 P);
+ vec4 textureProj( sampler1D sampler, vec4 P);
+ivec4 textureProj(isampler1D sampler, vec4 P);
+uvec4 textureProj(usampler1D sampler, vec4 P);
+
+ vec4 textureProj( sampler2D sampler, vec3 P);
+ivec4 textureProj(isampler2D sampler, vec3 P);
+uvec4 textureProj(usampler2D sampler, vec3 P);
+ vec4 textureProj( sampler2D sampler, vec4 P);
+ivec4 textureProj(isampler2D sampler, vec4 P);
+uvec4 textureProj(usampler2D sampler, vec4 P);
+
+ vec4 textureProj( sampler3D sampler, vec4 P);
+ivec4 textureProj(isampler3D sampler, vec4 P);
+uvec4 textureProj(usampler3D sampler, vec4 P);
+
+float textureProj(sampler1DShadow sampler, vec4 P);
+float textureProj(sampler2DShadow sampler, vec4 P);
+
+/* textureProj - bias variants */
+ vec4 textureProj( sampler1D sampler, vec2 P, float bias);
+ivec4 textureProj(isampler1D sampler, vec2 P, float bias);
+uvec4 textureProj(usampler1D sampler, vec2 P, float bias);
+ vec4 textureProj( sampler1D sampler, vec4 P, float bias);
+ivec4 textureProj(isampler1D sampler, vec4 P, float bias);
+uvec4 textureProj(usampler1D sampler, vec4 P, float bias);
+
+ vec4 textureProj( sampler2D sampler, vec3 P, float bias);
+ivec4 textureProj(isampler2D sampler, vec3 P, float bias);
+uvec4 textureProj(usampler2D sampler, vec3 P, float bias);
+ vec4 textureProj( sampler2D sampler, vec4 P, float bias);
+ivec4 textureProj(isampler2D sampler, vec4 P, float bias);
+uvec4 textureProj(usampler2D sampler, vec4 P, float bias);
+
+ vec4 textureProj( sampler3D sampler, vec4 P, float bias);
+ivec4 textureProj(isampler3D sampler, vec4 P, float bias);
+uvec4 textureProj(usampler3D sampler, vec4 P, float bias);
+
+float textureProj(sampler1DShadow sampler, vec4 P, float bias);
+float textureProj(sampler2DShadow sampler, vec4 P, float bias);
+
+/* textureLod */
+ vec4 textureLod( sampler1D sampler, float P, float lod);
+ivec4 textureLod(isampler1D sampler, float P, float lod);
+uvec4 textureLod(usampler1D sampler, float P, float lod);
+
+ vec4 textureLod( sampler2D sampler, vec2 P, float lod);
+ivec4 textureLod(isampler2D sampler, vec2 P, float lod);
+uvec4 textureLod(usampler2D sampler, vec2 P, float lod);
+
+ vec4 textureLod( sampler3D sampler, vec3 P, float lod);
+ivec4 textureLod(isampler3D sampler, vec3 P, float lod);
+uvec4 textureLod(usampler3D sampler, vec3 P, float lod);
+
+ vec4 textureLod( samplerCube sampler, vec3 P, float lod);
+ivec4 textureLod(isamplerCube sampler, vec3 P, float lod);
+uvec4 textureLod(usamplerCube sampler, vec3 P, float lod);
+
+float textureLod(sampler1DShadow sampler, vec3 P, float lod);
+float textureLod(sampler2DShadow sampler, vec3 P, float lod);
+
+ vec4 textureLod( sampler1DArray sampler, vec2 P, float lod);
+ivec4 textureLod(isampler1DArray sampler, vec2 P, float lod);
+uvec4 textureLod(usampler1DArray sampler, vec2 P, float lod);
+
+ vec4 textureLod( sampler2DArray sampler, vec3 P, float lod);
+ivec4 textureLod(isampler2DArray sampler, vec3 P, float lod);
+uvec4 textureLod(usampler2DArray sampler, vec3 P, float lod);
+
+float textureLod(sampler1DArrayShadow sampler, vec3 P, float lod);
+
+#if 0
+/* textureOffset - no bias */
+ vec4 textureOffset( sampler1D sampler, float P, int offset);
+ivec4 textureOffset(isampler1D sampler, float P, int offset);
+uvec4 textureOffset(usampler1D sampler, float P, int offset);
+
+ vec4 textureOffset( sampler2D sampler, vec2 P, ivec2 offset);
+ivec4 textureOffset(isampler2D sampler, vec2 P, ivec2 offset);
+uvec4 textureOffset(usampler2D sampler, vec2 P, ivec2 offset);
+
+ vec4 textureOffset( sampler3D sampler, vec3 P, ivec3 offset);
+ivec4 textureOffset(isampler3D sampler, vec3 P, ivec3 offset);
+uvec4 textureOffset(usampler3D sampler, vec3 P, ivec3 offset);
+
+float textureOffset(sampler1DShadow sampler, vec3 P, int offset);
+float textureOffset(sampler2DShadow sampler, vec3 P, ivec2 offset);
+
+ vec4 textureOffset( sampler1DArray sampler, vec2 P, int offset);
+ivec4 textureOffset(isampler1DArray sampler, vec2 P, int offset);
+uvec4 textureOffset(usampler1DArray sampler, vec2 P, int offset);
+
+ vec4 textureOffset( sampler2DArray sampler, vec3 P, ivec2 offset);
+ivec4 textureOffset(isampler2DArray sampler, vec3 P, ivec2 offset);
+uvec4 textureOffset(usampler2DArray sampler, vec3 P, ivec2 offset);
+
+float textureOffset(sampler1DArrayShadow sampler, vec3 P, int offset);
+
+/* textureOffset - bias variants */
+ vec4 textureOffset( sampler1D sampler, float P, int offset, float bias);
+ivec4 textureOffset(isampler1D sampler, float P, int offset, float bias);
+uvec4 textureOffset(usampler1D sampler, float P, int offset, float bias);
+
+ vec4 textureOffset( sampler2D sampler, vec2 P, ivec2 offset, float bias);
+ivec4 textureOffset(isampler2D sampler, vec2 P, ivec2 offset, float bias);
+uvec4 textureOffset(usampler2D sampler, vec2 P, ivec2 offset, float bias);
+
+ vec4 textureOffset( sampler3D sampler, vec3 P, ivec3 offset, float bias);
+ivec4 textureOffset(isampler3D sampler, vec3 P, ivec3 offset, float bias);
+uvec4 textureOffset(usampler3D sampler, vec3 P, ivec3 offset, float bias);
+
+float textureOffset(sampler1DShadow sampler, vec3 P, int offset, float bias);
+float textureOffset(sampler2DShadow sampler, vec3 P, ivec2 offset, float bias);
+
+ vec4 textureOffset( sampler1DArray sampler, vec2 P, int offset, float bias);
+ivec4 textureOffset(isampler1DArray sampler, vec2 P, int offset, float bias);
+uvec4 textureOffset(usampler1DArray sampler, vec2 P, int offset, float bias);
+
+ vec4 textureOffset( sampler2DArray sampler, vec3 P, ivec2 offset, float bias);
+ivec4 textureOffset(isampler2DArray sampler, vec3 P, ivec2 offset, float bias);
+uvec4 textureOffset(usampler2DArray sampler, vec3 P, ivec2 offset, float bias);
+
+float textureOffset(sampler1DArrayShadow samp, vec3 P, int offset, float bias);
+#endif
+
+/* texelFetch */
+ vec4 texelFetch( sampler1D sampler, int P, int lod);
+ivec4 texelFetch(isampler1D sampler, int P, int lod);
+uvec4 texelFetch(usampler1D sampler, int P, int lod);
+
+ vec4 texelFetch( sampler2D sampler, ivec2 P, int lod);
+ivec4 texelFetch(isampler2D sampler, ivec2 P, int lod);
+uvec4 texelFetch(usampler2D sampler, ivec2 P, int lod);
+
+ vec4 texelFetch( sampler3D sampler, ivec3 P, int lod);
+ivec4 texelFetch(isampler3D sampler, ivec3 P, int lod);
+uvec4 texelFetch(usampler3D sampler, ivec3 P, int lod);
+
+ vec4 texelFetch( sampler1DArray sampler, ivec2 P, int lod);
+ivec4 texelFetch(isampler1DArray sampler, ivec2 P, int lod);
+uvec4 texelFetch(usampler1DArray sampler, ivec2 P, int lod);
+
+ vec4 texelFetch( sampler2DArray sampler, ivec3 P, int lod);
+ivec4 texelFetch(isampler2DArray sampler, ivec3 P, int lod);
+uvec4 texelFetch(usampler2DArray sampler, ivec3 P, int lod);
+
+#if 0
+/* texelFetchOffset */
+ vec4 texelFetchOffset( sampler1D sampler, int P, int lod, int offset);
+ivec4 texelFetchOffset(isampler1D sampler, int P, int lod, int offset);
+uvec4 texelFetchOffset(usampler1D sampler, int P, int lod, int offset);
+
+ vec4 texelFetchOffset( sampler2D sampler, ivec2 P, int lod, ivec2 offset);
+ivec4 texelFetchOffset(isampler2D sampler, ivec2 P, int lod, ivec2 offset);
+uvec4 texelFetchOffset(usampler2D sampler, ivec2 P, int lod, ivec2 offset);
+
+ vec4 texelFetchOffset( sampler3D sampler, ivec3 P, int lod, ivec3 offset);
+ivec4 texelFetchOffset(isampler3D sampler, ivec3 P, int lod, ivec3 offset);
+uvec4 texelFetchOffset(usampler3D sampler, ivec3 P, int lod, ivec3 offset);
+
+ vec4 texelFetchOffset( sampler1DArray sampler, ivec2 P, int lod, int offset);
+ivec4 texelFetchOffset(isampler1DArray sampler, ivec2 P, int lod, int offset);
+uvec4 texelFetchOffset(usampler1DArray sampler, ivec2 P, int lod, int offset);
+
+ vec4 texelFetchOffset( sampler2DArray sampler, ivec3 P, int lod, ivec2 offset);
+ivec4 texelFetchOffset(isampler2DArray sampler, ivec3 P, int lod, ivec2 offset);
+uvec4 texelFetchOffset(usampler2DArray sampler, ivec3 P, int lod, ivec2 offset);
+
+/* textureProjOffset - no bias */
+ vec4 textureProj( sampler1D sampler, vec2 P, int offset);
+ivec4 textureProj(isampler1D sampler, vec2 P, int offset);
+uvec4 textureProj(usampler1D sampler, vec2 P, int offset);
+ vec4 textureProj( sampler1D sampler, vec4 P, int offset);
+ivec4 textureProj(isampler1D sampler, vec4 P, int offset);
+uvec4 textureProj(usampler1D sampler, vec4 P, int offset);
+
+ vec4 textureProj( sampler2D sampler, vec3 P, ivec2 offset);
+ivec4 textureProj(isampler2D sampler, vec3 P, ivec2 offset);
+uvec4 textureProj(usampler2D sampler, vec3 P, ivec2 offset);
+ vec4 textureProj( sampler2D sampler, vec4 P, ivec2 offset);
+ivec4 textureProj(isampler2D sampler, vec4 P, ivec2 offset);
+uvec4 textureProj(usampler2D sampler, vec4 P, ivec2 offset);
+
+ vec4 textureProj( sampler3D sampler, vec4 P, ivec3 offset);
+ivec4 textureProj(isampler3D sampler, vec4 P, ivec3 offset);
+uvec4 textureProj(usampler3D sampler, vec4 P, ivec3 offset);
+
+float textureProj(sampler1DShadow sampler, vec4 P, int offset);
+float textureProj(sampler2DShadow sampler, vec4 P, ivec2 offset);
+
+/* textureProjOffset - bias variants */
+ vec4 textureProj( sampler1D sampler, vec2 P, int offset, float bias);
+ivec4 textureProj(isampler1D sampler, vec2 P, int offset, float bias);
+uvec4 textureProj(usampler1D sampler, vec2 P, int offset, float bias);
+ vec4 textureProj( sampler1D sampler, vec4 P, int offset, float bias);
+ivec4 textureProj(isampler1D sampler, vec4 P, int offset, float bias);
+uvec4 textureProj(usampler1D sampler, vec4 P, int offset, float bias);
+
+ vec4 textureProj( sampler2D sampler, vec3 P, ivec2 offset, float bias);
+ivec4 textureProj(isampler2D sampler, vec3 P, ivec2 offset, float bias);
+uvec4 textureProj(usampler2D sampler, vec3 P, ivec2 offset, float bias);
+ vec4 textureProj( sampler2D sampler, vec4 P, ivec2 offset, float bias);
+ivec4 textureProj(isampler2D sampler, vec4 P, ivec2 offset, float bias);
+uvec4 textureProj(usampler2D sampler, vec4 P, ivec2 offset, float bias);
+
+ vec4 textureProj( sampler3D sampler, vec4 P, ivec3 offset, float bias);
+ivec4 textureProj(isampler3D sampler, vec4 P, ivec3 offset, float bias);
+uvec4 textureProj(usampler3D sampler, vec4 P, ivec3 offset, float bias);
+
+float textureProj(sampler1DShadow sampler, vec4 P, int offset, float bias);
+float textureProj(sampler2DShadow sampler, vec4 P, ivec2 offset, float bias);
+
+/* textureLodOffset */
+ vec4 textureLodOffset( sampler1D sampler, float P, float lod, int offset);
+ivec4 textureLodOffset(isampler1D sampler, float P, float lod, int offset);
+uvec4 textureLodOffset(usampler1D sampler, float P, float lod, int offset);
+
+ vec4 textureLodOffset( sampler2D sampler, vec2 P, float lod, ivec2 offset);
+ivec4 textureLodOffset(isampler2D sampler, vec2 P, float lod, ivec2 offset);
+uvec4 textureLodOffset(usampler2D sampler, vec2 P, float lod, ivec2 offset);
+
+ vec4 textureLodOffset( sampler3D sampler, vec3 P, float lod, ivec3 offset);
+ivec4 textureLodOffset(isampler3D sampler, vec3 P, float lod, ivec3 offset);
+uvec4 textureLodOffset(usampler3D sampler, vec3 P, float lod, ivec3 offset);
+
+float textureLodOffset(sampler1DShadow samp, vec3 P, float lod, int offset);
+float textureLodOffset(sampler2DShadow samp, vec3 P, float lod, ivec2 offset);
+
+ vec4 textureLodOffset( sampler1DArray sampler, vec2 P, float lod, int offset);
+ivec4 textureLodOffset(isampler1DArray sampler, vec2 P, float lod, int offset);
+uvec4 textureLodOffset(usampler1DArray sampler, vec2 P, float lod, int offset);
+
+ vec4 textureLodOffset( sampler2DArray samp, vec3 P, float lod, ivec2 offset);
+ivec4 textureLodOffset(isampler2DArray samp, vec3 P, float lod, ivec2 offset);
+uvec4 textureLodOffset(usampler2DArray samp, vec3 P, float lod, ivec2 offset);
+
+float textureLodOffset(sampler1DArrayShadow s, vec3 P, float lod, int offset);
+#endif
+
+/* textureProjLod */
+ vec4 textureProjLod( sampler1D sampler, vec2 P, float lod);
+ivec4 textureProjLod(isampler1D sampler, vec2 P, float lod);
+uvec4 textureProjLod(usampler1D sampler, vec2 P, float lod);
+ vec4 textureProjLod( sampler1D sampler, vec4 P, float lod);
+ivec4 textureProjLod(isampler1D sampler, vec4 P, float lod);
+uvec4 textureProjLod(usampler1D sampler, vec4 P, float lod);
+
+ vec4 textureProjLod( sampler2D sampler, vec3 P, float lod);
+ivec4 textureProjLod(isampler2D sampler, vec3 P, float lod);
+uvec4 textureProjLod(usampler2D sampler, vec3 P, float lod);
+ vec4 textureProjLod( sampler2D sampler, vec4 P, float lod);
+ivec4 textureProjLod(isampler2D sampler, vec4 P, float lod);
+uvec4 textureProjLod(usampler2D sampler, vec4 P, float lod);
+
+ vec4 textureProjLod( sampler3D sampler, vec4 P, float lod);
+ivec4 textureProjLod(isampler3D sampler, vec4 P, float lod);
+uvec4 textureProjLod(usampler3D sampler, vec4 P, float lod);
+
+float textureProjLod(sampler1DShadow sampler, vec4 P, float lod);
+float textureProjLod(sampler2DShadow sampler, vec4 P, float lod);
+
+#if 0
+/* textureProjLodOffset */
+ vec4 textureProjLodOffset( sampler1D sampler, vec2 P, float lod, int offset);
+ivec4 textureProjLodOffset(isampler1D sampler, vec2 P, float lod, int offset);
+uvec4 textureProjLodOffset(usampler1D sampler, vec2 P, float lod, int offset);
+ vec4 textureProjLodOffset( sampler1D sampler, vec4 P, float lod, int offset);
+ivec4 textureProjLodOffset(isampler1D sampler, vec4 P, float lod, int offset);
+uvec4 textureProjLodOffset(usampler1D sampler, vec4 P, float lod, int offset);
+
+ vec4 textureProjLodOffset( sampler2D sampler, vec3 P, float lod, ivec2 offset);
+ivec4 textureProjLodOffset(isampler2D sampler, vec3 P, float lod, ivec2 offset);
+uvec4 textureProjLodOffset(usampler2D sampler, vec3 P, float lod, ivec2 offset);
+ vec4 textureProjLodOffset( sampler2D sampler, vec4 P, float lod, ivec2 offset);
+ivec4 textureProjLodOffset(isampler2D sampler, vec4 P, float lod, ivec2 offset);
+uvec4 textureProjLodOffset(usampler2D sampler, vec4 P, float lod, ivec2 offset);
+
+ vec4 textureProjLodOffset( sampler3D sampler, vec4 P, float lod, ivec3 offset);
+ivec4 textureProjLodOffset(isampler3D sampler, vec4 P, float lod, ivec3 offset);
+uvec4 textureProjLodOffset(usampler3D sampler, vec4 P, float lod, ivec3 offset);
+
+float textureProjLodOffset(sampler1DShadow s, vec4 P, float lod, int offset);
+float textureProjLodOffset(sampler2DShadow s, vec4 P, float lod, ivec2 offset);
+#endif
+
+/* textureGrad */
+ vec4 textureGrad( sampler1D sampler, float P, float dPdx, float dPdy);
+ivec4 textureGrad(isampler1D sampler, float P, float dPdx, float dPdy);
+uvec4 textureGrad(usampler1D sampler, float P, float dPdx, float dPdy);
+
+ vec4 textureGrad( sampler2D sampler, vec2 P, vec2 dPdx, vec2 dPdy);
+ivec4 textureGrad(isampler2D sampler, vec2 P, vec2 dPdx, vec2 dPdy);
+uvec4 textureGrad(usampler2D sampler, vec2 P, vec2 dPdx, vec2 dPdy);
+
+ vec4 textureGrad( sampler3D sampler, vec3 P, vec3 dPdx, vec3 dPdy);
+ivec4 textureGrad(isampler3D sampler, vec3 P, vec3 dPdx, vec3 dPdy);
+uvec4 textureGrad(usampler3D sampler, vec3 P, vec3 dPdx, vec3 dPdy);
+
+ vec4 textureGrad( samplerCube sampler, vec3 P, vec3 dPdx, vec3 dPdy);
+ivec4 textureGrad(isamplerCube sampler, vec3 P, vec3 dPdx, vec3 dPdy);
+uvec4 textureGrad(usamplerCube sampler, vec3 P, vec3 dPdx, vec3 dPdy);
+
+float textureGrad(sampler1DShadow   sampler, vec3 P, float dPdx, float dPdy);
+float textureGrad(sampler2DShadow   sampler, vec3 P, vec2  dPdx, vec2  dPdy);
+float textureGrad(samplerCubeShadow sampler, vec4 P, vec3  dPdx, vec3  dPdy);
+
+ vec4 textureGrad( sampler1DArray sampler, vec2 P, float dPdx, float dPdy);
+ivec4 textureGrad(isampler1DArray sampler, vec2 P, float dPdx, float dPdy);
+uvec4 textureGrad(usampler1DArray sampler, vec2 P, float dPdx, float dPdy);
+
+ vec4 textureGrad( sampler2DArray sampler, vec3 P, vec2 dPdx, vec2 dPdy);
+ivec4 textureGrad(isampler2DArray sampler, vec3 P, vec2 dPdx, vec2 dPdy);
+uvec4 textureGrad(usampler2DArray sampler, vec3 P, vec2 dPdx, vec2 dPdy);
+
+float textureGrad(sampler1DArrayShadow sampler, vec3 P, float dPdx, float dPdy);
+float textureGrad(sampler2DArrayShadow sampler, vec4 P, vec2  dPdx, vec2  dPdy);
+
+#if 0
+/* textureGradOffset */
+ vec4 textureGradOffset( sampler1D s, float P, float dx, float dy, int off);
+ivec4 textureGradOffset(isampler1D s, float P, float dx, float dy, int offset);
+uvec4 textureGradOffset(usampler1D s, float P, float dx, float dy, int offset);
+
+ vec4 textureGradOffset( sampler2D s, vec2 P, vec2 dx, vec2 dy, ivec2 offset);
+ivec4 textureGradOffset(isampler2D s, vec2 P, vec2 dx, vec2 dy, ivec2 offset);
+uvec4 textureGradOffset(usampler2D s, vec2 P, vec2 dx, vec2 dy, ivec2 offset);
+
+ vec4 textureGradOffset( sampler3D s, vec3 P, vec3 dx, vec3 dy, ivec3 offset);
+ivec4 textureGradOffset(isampler3D s, vec3 P, vec3 dx, vec3 dy, ivec3 offset);
+uvec4 textureGradOffset(usampler3D s, vec3 P, vec3 dx, vec3 dy, ivec3 offset);
+
+ vec4 textureGradOffset( samplerCube s, vec3 P, vec3 dx, vec3 dy, ivec3 offset);
+ivec4 textureGradOffset(isamplerCube s, vec3 P, vec3 dx, vec3 dy, ivec3 offset);
+uvec4 textureGradOffset(usamplerCube s, vec3 P, vec3 dx, vec3 dy, ivec3 offset);
+
+float textureGradOffset(sampler1DShadow s, vec3 P, float dx, float dy, int off);
+float textureGradOffset(sampler2DShadow s, vec3 P, vec2 dx, vec2 dy, ivec2 off);
+
+ vec4 textureGradOffset( sampler1DArray s, vec2 P, float dx, float dy, int off);
+ivec4 textureGradOffset(isampler1DArray s, vec2 P, float dx, float dy, int off);
+uvec4 textureGradOffset(usampler1DArray s, vec2 P, float dx, float dy, int off);
+
+ vec4 textureGradOffset( sampler2DArray s, vec3 P, vec2 dx, vec2 dy, ivec2 off);
+ivec4 textureGradOffset(isampler2DArray s, vec3 P, vec2 dx, vec2 dy, ivec2 off);
+uvec4 textureGradOffset(usampler2DArray s, vec3 P, vec2 dx, vec2 dy, ivec2 off);
+
+float textureGradOffset(sampler1DArrayShadow s, vec3 P, float dx, float dy, int o);
+float textureGradOffset(sampler2DArrayShadow s, vec4 P, vec2 dx, vec2 dy, ivec2 o);
+#endif
+
+/* textureProjGrad */
+ vec4 textureProjGrad( sampler1D sampler, vec2 P, float dPdx, float dPdy);
+ivec4 textureProjGrad(isampler1D sampler, vec2 P, float dPdx, float dPdy);
+uvec4 textureProjGrad(usampler1D sampler, vec2 P, float dPdx, float dPdy);
+ vec4 textureProjGrad( sampler1D sampler, vec4 P, float dPdx, float dPdy);
+ivec4 textureProjGrad(isampler1D sampler, vec4 P, float dPdx, float dPdy);
+uvec4 textureProjGrad(usampler1D sampler, vec4 P, float dPdx, float dPdy);
+
+ vec4 textureProjGrad( sampler2D sampler, vec3 P, vec2 dPdx, vec2 dPdy);
+ivec4 textureProjGrad(isampler2D sampler, vec3 P, vec2 dPdx, vec2 dPdy);
+uvec4 textureProjGrad(usampler2D sampler, vec3 P, vec2 dPdx, vec2 dPdy);
+ vec4 textureProjGrad( sampler2D sampler, vec4 P, vec2 dPdx, vec2 dPdy);
+ivec4 textureProjGrad(isampler2D sampler, vec4 P, vec2 dPdx, vec2 dPdy);
+uvec4 textureProjGrad(usampler2D sampler, vec4 P, vec2 dPdx, vec2 dPdy);
+
+ vec4 textureProjGrad( sampler3D sampler, vec4 P, vec3 dPdx, vec3 dPdy);
+ivec4 textureProjGrad(isampler3D sampler, vec4 P, vec3 dPdx, vec3 dPdy);
+uvec4 textureProjGrad(usampler3D sampler, vec4 P, vec3 dPdx, vec3 dPdy);
+
+float textureProjGrad(sampler1DShadow sampler, vec4 P, float dPdx, float dPdy);
+float textureProjGrad(sampler2DShadow sampler, vec4 P, vec2  dPdx, vec2  dPdy);
+
+#if 0
+/* textureProjGradOffset */
+ vec4 textureProjGradOffset( sampler1D s, vec2 P, float dx, float dy, int off);
+ivec4 textureProjGradOffset(isampler1D s, vec2 P, float dx, float dy, int off);
+uvec4 textureProjGradOffset(usampler1D s, vec2 P, float dx, float dy, int off);
+ vec4 textureProjGradOffset( sampler1D s, vec4 P, float dx, float dy, int off);
+ivec4 textureProjGradOffset(isampler1D s, vec4 P, float dx, float dy, int off);
+uvec4 textureProjGradOffset(usampler1D s, vec4 P, float dx, float dy, int off);
+
+ vec4 textureProjGradOffset( sampler2D s, vec3 P, vec2 dx, vec2 dy, ivec2 off);
+ivec4 textureProjGradOffset(isampler2D s, vec3 P, vec2 dx, vec2 dy, ivec2 off);
+uvec4 textureProjGradOffset(usampler2D s, vec3 P, vec2 dx, vec2 dy, ivec2 off);
+ vec4 textureProjGradOffset( sampler2D s, vec4 P, vec2 dx, vec2 dy, ivec2 off);
+ivec4 textureProjGradOffset(isampler2D s, vec4 P, vec2 dx, vec2 dy, ivec2 off);
+uvec4 textureProjGradOffset(usampler2D s, vec4 P, vec2 dx, vec2 dy, ivec2 off);
+
+ vec4 textureProjGradOffset( sampler3D s, vec4 P, vec3 dx, vec3 dy, ivec3 off);
+ivec4 textureProjGradOffset(isampler3D s, vec4 P, vec3 dx, vec3 dy, ivec3 off);
+uvec4 textureProjGradOffset(usampler3D s, vec4 P, vec3 dx, vec3 dy, ivec3 off);
+
+float textureProjGradOffset(sampler1DShadow s, vec4 P, float dx, float dy, int o);
+float textureProjGradOffset(sampler2DShadow s, vec4 P, vec2 dx, vec2 dy, vec2 o);
+#endif
+
+/*
+ * The following texture functions are deprecated:
+ */
+vec4 texture1D       (sampler1D sampler, float coord);
+vec4 texture1DProj   (sampler1D sampler, vec2  coord);
+vec4 texture1DProj   (sampler1D sampler, vec4  coord);
+vec4 texture1D       (sampler1D sampler, float coord, float bias);
+vec4 texture1DProj   (sampler1D sampler, vec2  coord, float bias);
+vec4 texture1DProj   (sampler1D sampler, vec4  coord, float bias);
+vec4 texture1DLod    (sampler1D sampler, float coord, float lod);
+vec4 texture1DProjLod(sampler1D sampler, vec2  coord, float lod);
+vec4 texture1DProjLod(sampler1D sampler, vec4  coord, float lod);
+
+vec4 texture2D       (sampler2D sampler, vec2 coord);
+vec4 texture2DProj   (sampler2D sampler, vec3 coord);
+vec4 texture2DProj   (sampler2D sampler, vec4 coord);
+vec4 texture2D       (sampler2D sampler, vec2 coord, float bias);
+vec4 texture2DProj   (sampler2D sampler, vec3 coord, float bias);
+vec4 texture2DProj   (sampler2D sampler, vec4 coord, float bias);
+vec4 texture2DLod    (sampler2D sampler, vec2 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);
+
+vec4 texture3D       (sampler3D sampler, vec3 coord);
+vec4 texture3DProj   (sampler3D sampler, vec4 coord);
+vec4 texture3D       (sampler3D sampler, vec3 coord, float bias);
+vec4 texture3DProj   (sampler3D sampler, vec4 coord, float bias);
+vec4 texture3DLod    (sampler3D sampler, vec3 coord, float lod);
+vec4 texture3DProjLod(sampler3D sampler, vec4 coord, float lod);
+
+vec4 textureCube     (samplerCube sampler, vec3 coord);
+vec4 textureCube     (samplerCube sampler, vec3 coord, float bias);
+vec4 textureCubeLod  (samplerCube sampler, vec3 coord, float lod);
+
+vec4 shadow1D       (sampler1DShadow sampler, vec3 coord);
+vec4 shadow2D       (sampler2DShadow sampler, vec3 coord);
+vec4 shadow1DProj   (sampler1DShadow sampler, vec4 coord);
+vec4 shadow2DProj   (sampler2DShadow sampler, vec4 coord);
+vec4 shadow1D       (sampler1DShadow sampler, vec3 coord, float bias);
+vec4 shadow2D       (sampler2DShadow sampler, vec3 coord, float bias);
+vec4 shadow1DProj   (sampler1DShadow sampler, vec4 coord, float bias);
+vec4 shadow2DProj   (sampler2DShadow sampler, vec4 coord, float bias);
+vec4 shadow1DLod    (sampler1DShadow sampler, vec3 coord, float lod);
+vec4 shadow2DLod    (sampler2DShadow sampler, vec3 coord, float lod);
+vec4 shadow1DProjLod(sampler1DShadow sampler, vec4 coord, float lod);
+vec4 shadow2DProjLod(sampler2DShadow sampler, vec4 coord, float lod);
+
+/*
+ * 8.8 - Fragment Processing Functions
+ */
+float dFdx(float p);
+vec2  dFdx(vec2  p);
+vec3  dFdx(vec3  p);
+vec4  dFdx(vec4  p);
+
+float dFdy(float p);
+vec2  dFdy(vec2  p);
+vec3  dFdy(vec3  p);
+vec4  dFdy(vec4  p);
+
+float fwidth(float p);
+vec2  fwidth(vec2  p);
+vec3  fwidth(vec3  p);
+vec4  fwidth(vec4  p);
+
+/*
+ * 8.9 - Noise Functions
+ */
+float noise1(float x);
+float noise1(vec2  x);
+float noise1(vec3  x);
+float noise1(vec4  x);
+
+vec2  noise2(float x);
+vec2  noise2(vec2  x);
+vec2  noise2(vec3  x);
+vec2  noise2(vec4  x);
+
+vec3  noise3(float x);
+vec3  noise3(vec2  x);
+vec3  noise3(vec3  x);
+vec3  noise3(vec4  x);
+
+vec4  noise4(float x);
+vec4  noise4(vec2  x);
+vec4  noise4(vec3  x);
+vec4  noise4(vec4  x);
diff --git a/src/glsl/builtins/profiles/130.vert b/src/glsl/builtins/profiles/130.vert
new file mode 100644 (file)
index 0000000..d0152b0
--- /dev/null
@@ -0,0 +1,1019 @@
+#version 130
+/*
+ * 8.1 - Angle and Trigonometry Functions
+ */
+float radians(float degrees);
+vec2  radians(vec2  degrees);
+vec3  radians(vec3  degrees);
+vec4  radians(vec4  degrees);
+
+float degrees(float radians);
+vec2  degrees(vec2  radians);
+vec3  degrees(vec3  radians);
+vec4  degrees(vec4  radians);
+
+float sin(float angle);
+vec2  sin(vec2  angle);
+vec3  sin(vec3  angle);
+vec4  sin(vec4  angle);
+
+float cos(float angle);
+vec2  cos(vec2  angle);
+vec3  cos(vec3  angle);
+vec4  cos(vec4  angle);
+
+float tan(float angle);
+vec2  tan(vec2  angle);
+vec3  tan(vec3  angle);
+vec4  tan(vec4  angle);
+
+float asin(float angle);
+vec2  asin(vec2  angle);
+vec3  asin(vec3  angle);
+vec4  asin(vec4  angle);
+
+float acos(float angle);
+vec2  acos(vec2  angle);
+vec3  acos(vec3  angle);
+vec4  acos(vec4  angle);
+
+float atan(float y, float x);
+vec2  atan(vec2  y, vec2  x);
+vec3  atan(vec3  y, vec3  x);
+vec4  atan(vec4  y, vec4  x);
+
+float atan(float y_over_x);
+vec2  atan(vec2  y_over_x);
+vec3  atan(vec3  y_over_x);
+vec4  atan(vec4  y_over_x);
+
+float sinh(float x);
+vec2  sinh(vec2  x);
+vec3  sinh(vec3  x);
+vec4  sinh(vec4  x);
+
+float cosh(float x);
+vec2  cosh(vec2  x);
+vec3  cosh(vec3  x);
+vec4  cosh(vec4  x);
+
+float tanh(float x);
+vec2  tanh(vec2  x);
+vec3  tanh(vec3  x);
+vec4  tanh(vec4  x);
+
+#if 0
+float asinh(float x);
+vec2  asinh(vec2  x);
+vec3  asinh(vec3  x);
+vec4  asinh(vec4  x);
+
+float acosh(float x);
+vec2  acosh(vec2  x);
+vec3  acosh(vec3  x);
+vec4  acosh(vec4  x);
+
+float atanh(float x);
+vec2  atanh(vec2  x);
+vec3  atanh(vec3  x);
+vec4  atanh(vec4  x);
+#endif
+
+/*
+ * 8.2 - Exponential Functions
+ */
+float pow(float x, float y);
+vec2  pow(vec2  x, vec2  y);
+vec3  pow(vec3  x, vec3  y);
+vec4  pow(vec4  x, vec4  y);
+
+float exp(float x);
+vec2  exp(vec2  x);
+vec3  exp(vec3  x);
+vec4  exp(vec4  x);
+
+float log(float x);
+vec2  log(vec2  x);
+vec3  log(vec3  x);
+vec4  log(vec4  x);
+
+float exp2(float x);
+vec2  exp2(vec2  x);
+vec3  exp2(vec3  x);
+vec4  exp2(vec4  x);
+
+float log2(float x);
+vec2  log2(vec2  x);
+vec3  log2(vec3  x);
+vec4  log2(vec4  x);
+
+float sqrt(float x);
+vec2  sqrt(vec2  x);
+vec3  sqrt(vec3  x);
+vec4  sqrt(vec4  x);
+
+float inversesqrt(float x);
+vec2  inversesqrt(vec2  x);
+vec3  inversesqrt(vec3  x);
+vec4  inversesqrt(vec4  x);
+
+/*
+ * 8.3 - Common Functions
+ */
+float abs(float x);
+vec2  abs(vec2  x);
+vec3  abs(vec3  x);
+vec4  abs(vec4  x);
+int   abs(int   x);
+ivec2 abs(ivec2 x);
+ivec3 abs(ivec3 x);
+ivec4 abs(ivec4 x);
+
+float sign(float x);
+vec2  sign(vec2  x);
+vec3  sign(vec3  x);
+vec4  sign(vec4  x);
+int   sign(int   x);
+ivec2 sign(ivec2 x);
+ivec3 sign(ivec3 x);
+ivec4 sign(ivec4 x);
+
+float floor(float x);
+vec2  floor(vec2  x);
+vec3  floor(vec3  x);
+vec4  floor(vec4  x);
+
+float ceil(float x);
+vec2  ceil(vec2  x);
+vec3  ceil(vec3  x);
+vec4  ceil(vec4  x);
+
+float fract(float x);
+vec2  fract(vec2  x);
+vec3  fract(vec3  x);
+vec4  fract(vec4  x);
+
+float mod(float x, float y);
+vec2  mod(vec2  x, float y);
+vec3  mod(vec3  x, float y);
+vec4  mod(vec4  x, float y);
+
+vec2  mod(vec2  x, vec2  y);
+vec3  mod(vec3  x, vec3  y);
+vec4  mod(vec4  x, vec4  y);
+
+float min(float x, float y);
+vec2  min(vec2  x, vec2  y);
+vec3  min(vec3  x, vec3  y);
+vec4  min(vec4  x, vec4  y);
+
+vec2  min(vec2  x, float y);
+vec3  min(vec3  x, float y);
+vec4  min(vec4  x, float y);
+
+int   min(int   x, int   y);
+ivec2 min(ivec2 x, ivec2 y);
+ivec3 min(ivec3 x, ivec3 y);
+ivec4 min(ivec4 x, ivec4 y);
+
+ivec2 min(ivec2 x, int   y);
+ivec3 min(ivec3 x, int   y);
+ivec4 min(ivec4 x, int   y);
+
+uint  min(uint  x, uint  y);
+uvec2 min(uvec2 x, uvec2 y);
+uvec3 min(uvec3 x, uvec3 y);
+uvec4 min(uvec4 x, uvec4 y);
+
+uvec2 min(uvec2 x, uint  y);
+uvec3 min(uvec3 x, uint  y);
+uvec4 min(uvec4 x, uint  y);
+
+float max(float x, float y);
+vec2  max(vec2  x, vec2  y);
+vec3  max(vec3  x, vec3  y);
+vec4  max(vec4  x, vec4  y);
+
+vec2  max(vec2  x, float y);
+vec3  max(vec3  x, float y);
+vec4  max(vec4  x, float y);
+
+int   max(int   x, int   y);
+ivec2 max(ivec2 x, ivec2 y);
+ivec3 max(ivec3 x, ivec3 y);
+ivec4 max(ivec4 x, ivec4 y);
+
+ivec2 max(ivec2 x, int   y);
+ivec3 max(ivec3 x, int   y);
+ivec4 max(ivec4 x, int   y);
+
+uint  max(uint  x, uint  y);
+uvec2 max(uvec2 x, uvec2 y);
+uvec3 max(uvec3 x, uvec3 y);
+uvec4 max(uvec4 x, uvec4 y);
+
+uvec2 max(uvec2 x, uint  y);
+uvec3 max(uvec3 x, uint  y);
+uvec4 max(uvec4 x, uint  y);
+
+float clamp(float x, float minVal, float maxVal);
+vec2  clamp(vec2  x, vec2  minVal, vec2  maxVal);
+vec3  clamp(vec3  x, vec3  minVal, vec3  maxVal);
+vec4  clamp(vec4  x, vec4  minVal, vec4  maxVal);
+
+vec2  clamp(vec2  x, float minVal, float maxVal);
+vec3  clamp(vec3  x, float minVal, float maxVal);
+vec4  clamp(vec4  x, float minVal, float maxVal);
+
+int   clamp(int   x, int   minVal, int   maxVal);
+ivec2 clamp(ivec2 x, ivec2 minVal, ivec2 maxVal);
+ivec3 clamp(ivec3 x, ivec3 minVal, ivec3 maxVal);
+ivec4 clamp(ivec4 x, ivec4 minVal, ivec4 maxVal);
+
+ivec2 clamp(ivec2 x, int   minVal, int   maxVal);
+ivec3 clamp(ivec3 x, int   minVal, int   maxVal);
+ivec4 clamp(ivec4 x, int   minVal, int   maxVal);
+
+uint  clamp(uint  x, uint  minVal, uint  maxVal);
+uvec2 clamp(uvec2 x, uvec2 minVal, uvec2 maxVal);
+uvec3 clamp(uvec3 x, uvec3 minVal, uvec3 maxVal);
+uvec4 clamp(uvec4 x, uvec4 minVal, uvec4 maxVal);
+
+uvec2 clamp(uvec2 x, uint  minVal, uint  maxVal);
+uvec3 clamp(uvec3 x, uint  minVal, uint  maxVal);
+uvec4 clamp(uvec4 x, uint  minVal, uint  maxVal);
+
+float mix(float x, float y, float a);
+vec2  mix(vec2  x, vec2  y, vec2  a);
+vec3  mix(vec3  x, vec3  y, vec3  a);
+vec4  mix(vec4  x, vec4  y, vec4  a);
+
+vec2  mix(vec2  x, vec2  y, float a);
+vec3  mix(vec3  x, vec3  y, float a);
+vec4  mix(vec4  x, vec4  y, float a);
+
+float step(float edge, float x);
+vec2  step(vec2  edge, vec2  x);
+vec3  step(vec3  edge, vec3  x);
+vec4  step(vec4  edge, vec4  x);
+
+vec2  step(float edge, vec2  x);
+vec3  step(float edge, vec3  x);
+vec4  step(float edge, vec4  x);
+
+float smoothstep(float edge0, float edge1, float x);
+vec2  smoothstep(vec2  edge0, vec2  edge1, vec2  x);
+vec3  smoothstep(vec3  edge0, vec3  edge1, vec3  x);
+vec4  smoothstep(vec4  edge0, vec4  edge1, vec4  x);
+
+vec2  smoothstep(float edge0, float edge1, vec2  x);
+vec3  smoothstep(float edge0, float edge1, vec3  x);
+vec4  smoothstep(float edge0, float edge1, vec4  x);
+
+#if 0
+bool  isnan(float x);
+bvec2 isnan(vec2  x);
+bvec3 isnan(vec3  x);
+bvec4 isnan(vec4  x);
+
+bool  isinf(float x);
+bvec2 isinf(vec2  x);
+bvec3 isinf(vec3  x);
+bvec4 isinf(vec4  x);
+#endif
+
+/*
+ * 8.4 - Geometric Functions
+ */
+float length(float x);
+float length(vec2  x);
+float length(vec3  x);
+float length(vec4  x);
+
+float distance(float p0, float p1);
+float distance(vec2  p0, vec2  p1);
+float distance(vec3  p0, vec3  p1);
+float distance(vec4  p0, vec4  p1);
+
+float dot(float x, float y);
+float dot(vec2  x, vec2  y);
+float dot(vec3  x, vec3  y);
+float dot(vec4  x, vec4  y);
+
+vec3 cross(vec3 x, vec3 y);
+
+float normalize(float x);
+vec2  normalize(vec2  x);
+vec3  normalize(vec3  x);
+vec4  normalize(vec4  x);
+
+vec4 ftransform();
+
+float faceforward(float N, float I, float Nref);
+vec2  faceforward(vec2  N, vec2  I, vec2  Nref);
+vec3  faceforward(vec3  N, vec3  I, vec3  Nref);
+vec4  faceforward(vec4  N, vec4  I, vec4  Nref);
+
+float reflect(float I, float N);
+vec2  reflect(vec2  I, vec2  N);
+vec3  reflect(vec3  I, vec3  N);
+vec4  reflect(vec4  I, vec4  N);
+
+float refract(float I, float N, float eta);
+vec2  refract(vec2  I, vec2  N, float eta);
+vec3  refract(vec3  I, vec3  N, float eta);
+vec4  refract(vec4  I, vec4  N, float eta);
+
+
+/*
+ * 8.5 - Matrix Functions
+ */
+mat2   matrixCompMult(mat2   x, mat2   y);
+mat3   matrixCompMult(mat3   x, mat3   y);
+mat4   matrixCompMult(mat4   x, mat4   y);
+mat2x3 matrixCompMult(mat2x3 x, mat2x3 y);
+mat2x4 matrixCompMult(mat2x4 x, mat2x4 y);
+mat3x2 matrixCompMult(mat3x2 x, mat3x2 y);
+mat3x4 matrixCompMult(mat3x4 x, mat3x4 y);
+mat4x2 matrixCompMult(mat4x2 x, mat4x2 y);
+mat4x3 matrixCompMult(mat4x3 x, mat4x3 y);
+
+mat2   outerProduct(vec2 c, vec2 r);
+mat3   outerProduct(vec3 c, vec3 r);
+mat4   outerProduct(vec4 c, vec4 r);
+
+mat2x3 outerProduct(vec3 c, vec2 r);
+mat3x2 outerProduct(vec2 c, vec3 r);
+
+mat2x4 outerProduct(vec4 c, vec2 r);
+mat4x2 outerProduct(vec2 c, vec4 r);
+
+mat3x4 outerProduct(vec4 c, vec3 r);
+mat4x3 outerProduct(vec3 c, vec4 r);
+
+mat2   transpose(mat2 m);
+mat3   transpose(mat3 m);
+mat4   transpose(mat4 m);
+
+mat2x3 transpose(mat3x2 m);
+mat3x2 transpose(mat2x3 m);
+
+mat2x4 transpose(mat4x2 m);
+mat4x2 transpose(mat2x4 m);
+
+mat3x4 transpose(mat4x3 m);
+mat4x3 transpose(mat3x4 m);
+
+/*
+ * 8.6 - Vector Relational Functions
+ */
+bvec2 lessThan( vec2 x,  vec2 y);
+bvec3 lessThan( vec3 x,  vec3 y);
+bvec4 lessThan( vec4 x,  vec4 y);
+bvec2 lessThan(ivec2 x, ivec2 y);
+bvec3 lessThan(ivec3 x, ivec3 y);
+bvec4 lessThan(ivec4 x, ivec4 y);
+bvec2 lessThan(uvec2 x, uvec2 y);
+bvec3 lessThan(uvec3 x, uvec3 y);
+bvec4 lessThan(uvec4 x, uvec4 y);
+
+bvec2 lessThanEqual( vec2 x,  vec2 y);
+bvec3 lessThanEqual( vec3 x,  vec3 y);
+bvec4 lessThanEqual( vec4 x,  vec4 y);
+bvec2 lessThanEqual(ivec2 x, ivec2 y);
+bvec3 lessThanEqual(ivec3 x, ivec3 y);
+bvec4 lessThanEqual(ivec4 x, ivec4 y);
+bvec2 lessThanEqual(uvec2 x, uvec2 y);
+bvec3 lessThanEqual(uvec3 x, uvec3 y);
+bvec4 lessThanEqual(uvec4 x, uvec4 y);
+
+bvec2 greaterThan( vec2 x,  vec2 y);
+bvec3 greaterThan( vec3 x,  vec3 y);
+bvec4 greaterThan( vec4 x,  vec4 y);
+bvec2 greaterThan(ivec2 x, ivec2 y);
+bvec3 greaterThan(ivec3 x, ivec3 y);
+bvec4 greaterThan(ivec4 x, ivec4 y);
+bvec2 greaterThan(uvec2 x, uvec2 y);
+bvec3 greaterThan(uvec3 x, uvec3 y);
+bvec4 greaterThan(uvec4 x, uvec4 y);
+
+bvec2 greaterThanEqual( vec2 x,  vec2 y);
+bvec3 greaterThanEqual( vec3 x,  vec3 y);
+bvec4 greaterThanEqual( vec4 x,  vec4 y);
+bvec2 greaterThanEqual(ivec2 x, ivec2 y);
+bvec3 greaterThanEqual(ivec3 x, ivec3 y);
+bvec4 greaterThanEqual(ivec4 x, ivec4 y);
+bvec2 greaterThanEqual(uvec2 x, uvec2 y);
+bvec3 greaterThanEqual(uvec3 x, uvec3 y);
+bvec4 greaterThanEqual(uvec4 x, uvec4 y);
+
+bvec2 equal( vec2 x,  vec2 y);
+bvec3 equal( vec3 x,  vec3 y);
+bvec4 equal( vec4 x,  vec4 y);
+bvec2 equal(ivec2 x, ivec2 y);
+bvec3 equal(ivec3 x, ivec3 y);
+bvec4 equal(ivec4 x, ivec4 y);
+bvec2 equal(uvec2 x, uvec2 y);
+bvec3 equal(uvec3 x, uvec3 y);
+bvec4 equal(uvec4 x, uvec4 y);
+bvec2 equal(bvec2 x, bvec2 y);
+bvec3 equal(bvec3 x, bvec3 y);
+bvec4 equal(bvec4 x, bvec4 y);
+
+bvec2 notEqual( vec2 x,  vec2 y);
+bvec3 notEqual( vec3 x,  vec3 y);
+bvec4 notEqual( vec4 x,  vec4 y);
+bvec2 notEqual(ivec2 x, ivec2 y);
+bvec3 notEqual(ivec3 x, ivec3 y);
+bvec4 notEqual(ivec4 x, ivec4 y);
+bvec2 notEqual(uvec2 x, uvec2 y);
+bvec3 notEqual(uvec3 x, uvec3 y);
+bvec4 notEqual(uvec4 x, uvec4 y);
+bvec2 notEqual(bvec2 x, bvec2 y);
+bvec3 notEqual(bvec3 x, bvec3 y);
+bvec4 notEqual(bvec4 x, bvec4 y);
+
+bool any(bvec2 x);
+bool any(bvec3 x);
+bool any(bvec4 x);
+
+bool all(bvec2 x);
+bool all(bvec3 x);
+bool all(bvec4 x);
+
+bvec2 not(bvec2 x);
+bvec3 not(bvec3 x);
+bvec4 not(bvec4 x);
+
+/*
+ * 8.7 - Texture Lookup Functions
+ */
+
+#if 0
+/* textureSize */
+int   textureSize( sampler1D sampler, int lod);
+int   textureSize(isampler1D sampler, int lod);
+int   textureSize(usampler1D sampler, int lod);
+
+ivec2 textureSize( sampler2D sampler, int lod);
+ivec2 textureSize(isampler2D sampler, int lod);
+ivec2 textureSize(usampler2D sampler, int lod);
+
+ivec3 textureSize( sampler3D sampler, int lod);
+ivec3 textureSize(isampler3D sampler, int lod);
+ivec3 textureSize(usampler3D sampler, int lod);
+
+ivec2 textureSize( samplerCube sampler, int lod);
+ivec2 textureSize(isamplerCube sampler, int lod);
+ivec2 textureSize(usamplerCube sampler, int lod);
+
+int   textureSize(sampler1DShadow   sampler, int lod);
+ivec2 textureSize(sampler2DShadow   sampler, int lod);
+ivec2 textureSize(samplerCubeShadow sampler, int lod);
+
+ivec2 textureSize( sampler1DArray sampler, int lod);
+ivec2 textureSize(isampler1DArray sampler, int lod);
+ivec2 textureSize(usampler1DArray sampler, int lod);
+ivec3 textureSize( sampler2DArray sampler, int lod);
+ivec2 textureSize(isampler2DArray sampler, int lod);
+ivec2 textureSize(usampler2DArray sampler, int lod);
+
+ivec2 textureSize(sampler1DArrayShadow sampler, int lod);
+ivec3 textureSize(sampler2DArrayShadow sampler, int lod);
+#endif
+
+/* texture - no bias */
+ vec4 texture( sampler1D sampler, float P);
+ivec4 texture(isampler1D sampler, float P);
+uvec4 texture(usampler1D sampler, float P);
+
+ vec4 texture( sampler2D sampler, vec2 P);
+ivec4 texture(isampler2D sampler, vec2 P);
+uvec4 texture(usampler2D sampler, vec2 P);
+
+ vec4 texture( sampler3D sampler, vec3 P);
+ivec4 texture(isampler3D sampler, vec3 P);
+uvec4 texture(usampler3D sampler, vec3 P);
+
+ vec4 texture( samplerCube sampler, vec3 P);
+ivec4 texture(isamplerCube sampler, vec3 P);
+uvec4 texture(usamplerCube sampler, vec3 P);
+
+float texture(sampler1DShadow   sampler, vec3 P);
+float texture(sampler2DShadow   sampler, vec3 P);
+float texture(samplerCubeShadow sampler, vec4 P);
+
+ vec4 texture( sampler1DArray sampler, vec2 P);
+ivec4 texture(isampler1DArray sampler, vec2 P);
+uvec4 texture(usampler1DArray sampler, vec2 P);
+
+ vec4 texture( sampler2DArray sampler, vec3 P);
+ivec4 texture(isampler2DArray sampler, vec3 P);
+uvec4 texture(usampler2DArray sampler, vec3 P);
+
+float texture(sampler1DArrayShadow sampler, vec3 P);
+float texture(sampler2DArrayShadow sampler, vec4 P);
+
+/* texture - bias variants */
+ vec4 texture( sampler1D sampler, float P, float bias);
+ivec4 texture(isampler1D sampler, float P, float bias);
+uvec4 texture(usampler1D sampler, float P, float bias);
+
+ vec4 texture( sampler2D sampler, vec2 P, float bias);
+ivec4 texture(isampler2D sampler, vec2 P, float bias);
+uvec4 texture(usampler2D sampler, vec2 P, float bias);
+
+ vec4 texture( sampler3D sampler, vec3 P, float bias);
+ivec4 texture(isampler3D sampler, vec3 P, float bias);
+uvec4 texture(usampler3D sampler, vec3 P, float bias);
+
+ vec4 texture( samplerCube sampler, vec3 P, float bias);
+ivec4 texture(isamplerCube sampler, vec3 P, float bias);
+uvec4 texture(usamplerCube sampler, vec3 P, float bias);
+
+float texture(sampler1DShadow   sampler, vec3 P, float bias);
+float texture(sampler2DShadow   sampler, vec3 P, float bias);
+float texture(samplerCubeShadow sampler, vec4 P, float bias);
+
+ vec4 texture( sampler1DArray sampler, vec2 P, float bias);
+ivec4 texture(isampler1DArray sampler, vec2 P, float bias);
+uvec4 texture(usampler1DArray sampler, vec2 P, float bias);
+
+ vec4 texture( sampler2DArray sampler, vec3 P, float bias);
+ivec4 texture(isampler2DArray sampler, vec3 P, float bias);
+uvec4 texture(usampler2DArray sampler, vec3 P, float bias);
+
+float texture(sampler1DArrayShadow sampler, vec3 P, float bias);
+
+/* textureProj - no bias */
+ vec4 textureProj( sampler1D sampler, vec2 P);
+ivec4 textureProj(isampler1D sampler, vec2 P);
+uvec4 textureProj(usampler1D sampler, vec2 P);
+ vec4 textureProj( sampler1D sampler, vec4 P);
+ivec4 textureProj(isampler1D sampler, vec4 P);
+uvec4 textureProj(usampler1D sampler, vec4 P);
+
+ vec4 textureProj( sampler2D sampler, vec3 P);
+ivec4 textureProj(isampler2D sampler, vec3 P);
+uvec4 textureProj(usampler2D sampler, vec3 P);
+ vec4 textureProj( sampler2D sampler, vec4 P);
+ivec4 textureProj(isampler2D sampler, vec4 P);
+uvec4 textureProj(usampler2D sampler, vec4 P);
+
+ vec4 textureProj( sampler3D sampler, vec4 P);
+ivec4 textureProj(isampler3D sampler, vec4 P);
+uvec4 textureProj(usampler3D sampler, vec4 P);
+
+float textureProj(sampler1DShadow sampler, vec4 P);
+float textureProj(sampler2DShadow sampler, vec4 P);
+
+/* textureProj - bias variants */
+ vec4 textureProj( sampler1D sampler, vec2 P, float bias);
+ivec4 textureProj(isampler1D sampler, vec2 P, float bias);
+uvec4 textureProj(usampler1D sampler, vec2 P, float bias);
+ vec4 textureProj( sampler1D sampler, vec4 P, float bias);
+ivec4 textureProj(isampler1D sampler, vec4 P, float bias);
+uvec4 textureProj(usampler1D sampler, vec4 P, float bias);
+
+ vec4 textureProj( sampler2D sampler, vec3 P, float bias);
+ivec4 textureProj(isampler2D sampler, vec3 P, float bias);
+uvec4 textureProj(usampler2D sampler, vec3 P, float bias);
+ vec4 textureProj( sampler2D sampler, vec4 P, float bias);
+ivec4 textureProj(isampler2D sampler, vec4 P, float bias);
+uvec4 textureProj(usampler2D sampler, vec4 P, float bias);
+
+ vec4 textureProj( sampler3D sampler, vec4 P, float bias);
+ivec4 textureProj(isampler3D sampler, vec4 P, float bias);
+uvec4 textureProj(usampler3D sampler, vec4 P, float bias);
+
+float textureProj(sampler1DShadow sampler, vec4 P, float bias);
+float textureProj(sampler2DShadow sampler, vec4 P, float bias);
+
+/* textureLod */
+ vec4 textureLod( sampler1D sampler, float P, float lod);
+ivec4 textureLod(isampler1D sampler, float P, float lod);
+uvec4 textureLod(usampler1D sampler, float P, float lod);
+
+ vec4 textureLod( sampler2D sampler, vec2 P, float lod);
+ivec4 textureLod(isampler2D sampler, vec2 P, float lod);
+uvec4 textureLod(usampler2D sampler, vec2 P, float lod);
+
+ vec4 textureLod( sampler3D sampler, vec3 P, float lod);
+ivec4 textureLod(isampler3D sampler, vec3 P, float lod);
+uvec4 textureLod(usampler3D sampler, vec3 P, float lod);
+
+ vec4 textureLod( samplerCube sampler, vec3 P, float lod);
+ivec4 textureLod(isamplerCube sampler, vec3 P, float lod);
+uvec4 textureLod(usamplerCube sampler, vec3 P, float lod);
+
+float textureLod(sampler1DShadow sampler, vec3 P, float lod);
+float textureLod(sampler2DShadow sampler, vec3 P, float lod);
+
+ vec4 textureLod( sampler1DArray sampler, vec2 P, float lod);
+ivec4 textureLod(isampler1DArray sampler, vec2 P, float lod);
+uvec4 textureLod(usampler1DArray sampler, vec2 P, float lod);
+
+ vec4 textureLod( sampler2DArray sampler, vec3 P, float lod);
+ivec4 textureLod(isampler2DArray sampler, vec3 P, float lod);
+uvec4 textureLod(usampler2DArray sampler, vec3 P, float lod);
+
+float textureLod(sampler1DArrayShadow sampler, vec3 P, float lod);
+
+#if 0
+/* textureOffset - no bias */
+ vec4 textureOffset( sampler1D sampler, float P, int offset);
+ivec4 textureOffset(isampler1D sampler, float P, int offset);
+uvec4 textureOffset(usampler1D sampler, float P, int offset);
+
+ vec4 textureOffset( sampler2D sampler, vec2 P, ivec2 offset);
+ivec4 textureOffset(isampler2D sampler, vec2 P, ivec2 offset);
+uvec4 textureOffset(usampler2D sampler, vec2 P, ivec2 offset);
+
+ vec4 textureOffset( sampler3D sampler, vec3 P, ivec3 offset);
+ivec4 textureOffset(isampler3D sampler, vec3 P, ivec3 offset);
+uvec4 textureOffset(usampler3D sampler, vec3 P, ivec3 offset);
+
+float textureOffset(sampler1DShadow sampler, vec3 P, int offset);
+float textureOffset(sampler2DShadow sampler, vec3 P, ivec2 offset);
+
+ vec4 textureOffset( sampler1DArray sampler, vec2 P, int offset);
+ivec4 textureOffset(isampler1DArray sampler, vec2 P, int offset);
+uvec4 textureOffset(usampler1DArray sampler, vec2 P, int offset);
+
+ vec4 textureOffset( sampler2DArray sampler, vec3 P, ivec2 offset);
+ivec4 textureOffset(isampler2DArray sampler, vec3 P, ivec2 offset);
+uvec4 textureOffset(usampler2DArray sampler, vec3 P, ivec2 offset);
+
+float textureOffset(sampler1DArrayShadow sampler, vec3 P, int offset);
+
+/* textureOffset - bias variants */
+ vec4 textureOffset( sampler1D sampler, float P, int offset, float bias);
+ivec4 textureOffset(isampler1D sampler, float P, int offset, float bias);
+uvec4 textureOffset(usampler1D sampler, float P, int offset, float bias);
+
+ vec4 textureOffset( sampler2D sampler, vec2 P, ivec2 offset, float bias);
+ivec4 textureOffset(isampler2D sampler, vec2 P, ivec2 offset, float bias);
+uvec4 textureOffset(usampler2D sampler, vec2 P, ivec2 offset, float bias);
+
+ vec4 textureOffset( sampler3D sampler, vec3 P, ivec3 offset, float bias);
+ivec4 textureOffset(isampler3D sampler, vec3 P, ivec3 offset, float bias);
+uvec4 textureOffset(usampler3D sampler, vec3 P, ivec3 offset, float bias);
+
+float textureOffset(sampler1DShadow sampler, vec3 P, int offset, float bias);
+float textureOffset(sampler2DShadow sampler, vec3 P, ivec2 offset, float bias);
+
+ vec4 textureOffset( sampler1DArray sampler, vec2 P, int offset, float bias);
+ivec4 textureOffset(isampler1DArray sampler, vec2 P, int offset, float bias);
+uvec4 textureOffset(usampler1DArray sampler, vec2 P, int offset, float bias);
+
+ vec4 textureOffset( sampler2DArray sampler, vec3 P, ivec2 offset, float bias);
+ivec4 textureOffset(isampler2DArray sampler, vec3 P, ivec2 offset, float bias);
+uvec4 textureOffset(usampler2DArray sampler, vec3 P, ivec2 offset, float bias);
+
+float textureOffset(sampler1DArrayShadow samp, vec3 P, int offset, float bias);
+#endif
+
+/* texelFetch */
+ vec4 texelFetch( sampler1D sampler, int P, int lod);
+ivec4 texelFetch(isampler1D sampler, int P, int lod);
+uvec4 texelFetch(usampler1D sampler, int P, int lod);
+
+ vec4 texelFetch( sampler2D sampler, ivec2 P, int lod);
+ivec4 texelFetch(isampler2D sampler, ivec2 P, int lod);
+uvec4 texelFetch(usampler2D sampler, ivec2 P, int lod);
+
+ vec4 texelFetch( sampler3D sampler, ivec3 P, int lod);
+ivec4 texelFetch(isampler3D sampler, ivec3 P, int lod);
+uvec4 texelFetch(usampler3D sampler, ivec3 P, int lod);
+
+ vec4 texelFetch( sampler1DArray sampler, ivec2 P, int lod);
+ivec4 texelFetch(isampler1DArray sampler, ivec2 P, int lod);
+uvec4 texelFetch(usampler1DArray sampler, ivec2 P, int lod);
+
+ vec4 texelFetch( sampler2DArray sampler, ivec3 P, int lod);
+ivec4 texelFetch(isampler2DArray sampler, ivec3 P, int lod);
+uvec4 texelFetch(usampler2DArray sampler, ivec3 P, int lod);
+
+#if 0
+/* texelFetchOffset */
+ vec4 texelFetchOffset( sampler1D sampler, int P, int lod, int offset);
+ivec4 texelFetchOffset(isampler1D sampler, int P, int lod, int offset);
+uvec4 texelFetchOffset(usampler1D sampler, int P, int lod, int offset);
+
+ vec4 texelFetchOffset( sampler2D sampler, ivec2 P, int lod, ivec2 offset);
+ivec4 texelFetchOffset(isampler2D sampler, ivec2 P, int lod, ivec2 offset);
+uvec4 texelFetchOffset(usampler2D sampler, ivec2 P, int lod, ivec2 offset);
+
+ vec4 texelFetchOffset( sampler3D sampler, ivec3 P, int lod, ivec3 offset);
+ivec4 texelFetchOffset(isampler3D sampler, ivec3 P, int lod, ivec3 offset);
+uvec4 texelFetchOffset(usampler3D sampler, ivec3 P, int lod, ivec3 offset);
+
+ vec4 texelFetchOffset( sampler1DArray sampler, ivec2 P, int lod, int offset);
+ivec4 texelFetchOffset(isampler1DArray sampler, ivec2 P, int lod, int offset);
+uvec4 texelFetchOffset(usampler1DArray sampler, ivec2 P, int lod, int offset);
+
+ vec4 texelFetchOffset( sampler2DArray sampler, ivec3 P, int lod, ivec2 offset);
+ivec4 texelFetchOffset(isampler2DArray sampler, ivec3 P, int lod, ivec2 offset);
+uvec4 texelFetchOffset(usampler2DArray sampler, ivec3 P, int lod, ivec2 offset);
+
+/* textureProjOffset - no bias */
+ vec4 textureProj( sampler1D sampler, vec2 P, int offset);
+ivec4 textureProj(isampler1D sampler, vec2 P, int offset);
+uvec4 textureProj(usampler1D sampler, vec2 P, int offset);
+ vec4 textureProj( sampler1D sampler, vec4 P, int offset);
+ivec4 textureProj(isampler1D sampler, vec4 P, int offset);
+uvec4 textureProj(usampler1D sampler, vec4 P, int offset);
+
+ vec4 textureProj( sampler2D sampler, vec3 P, ivec2 offset);
+ivec4 textureProj(isampler2D sampler, vec3 P, ivec2 offset);
+uvec4 textureProj(usampler2D sampler, vec3 P, ivec2 offset);
+ vec4 textureProj( sampler2D sampler, vec4 P, ivec2 offset);
+ivec4 textureProj(isampler2D sampler, vec4 P, ivec2 offset);
+uvec4 textureProj(usampler2D sampler, vec4 P, ivec2 offset);
+
+ vec4 textureProj( sampler3D sampler, vec4 P, ivec3 offset);
+ivec4 textureProj(isampler3D sampler, vec4 P, ivec3 offset);
+uvec4 textureProj(usampler3D sampler, vec4 P, ivec3 offset);
+
+float textureProj(sampler1DShadow sampler, vec4 P, int offset);
+float textureProj(sampler2DShadow sampler, vec4 P, ivec2 offset);
+
+/* textureProjOffset - bias variants */
+ vec4 textureProj( sampler1D sampler, vec2 P, int offset, float bias);
+ivec4 textureProj(isampler1D sampler, vec2 P, int offset, float bias);
+uvec4 textureProj(usampler1D sampler, vec2 P, int offset, float bias);
+ vec4 textureProj( sampler1D sampler, vec4 P, int offset, float bias);
+ivec4 textureProj(isampler1D sampler, vec4 P, int offset, float bias);
+uvec4 textureProj(usampler1D sampler, vec4 P, int offset, float bias);
+
+ vec4 textureProj( sampler2D sampler, vec3 P, ivec2 offset, float bias);
+ivec4 textureProj(isampler2D sampler, vec3 P, ivec2 offset, float bias);
+uvec4 textureProj(usampler2D sampler, vec3 P, ivec2 offset, float bias);
+ vec4 textureProj( sampler2D sampler, vec4 P, ivec2 offset, float bias);
+ivec4 textureProj(isampler2D sampler, vec4 P, ivec2 offset, float bias);
+uvec4 textureProj(usampler2D sampler, vec4 P, ivec2 offset, float bias);
+
+ vec4 textureProj( sampler3D sampler, vec4 P, ivec3 offset, float bias);
+ivec4 textureProj(isampler3D sampler, vec4 P, ivec3 offset, float bias);
+uvec4 textureProj(usampler3D sampler, vec4 P, ivec3 offset, float bias);
+
+float textureProj(sampler1DShadow sampler, vec4 P, int offset, float bias);
+float textureProj(sampler2DShadow sampler, vec4 P, ivec2 offset, float bias);
+
+/* textureLodOffset */
+ vec4 textureLodOffset( sampler1D sampler, float P, float lod, int offset);
+ivec4 textureLodOffset(isampler1D sampler, float P, float lod, int offset);
+uvec4 textureLodOffset(usampler1D sampler, float P, float lod, int offset);
+
+ vec4 textureLodOffset( sampler2D sampler, vec2 P, float lod, ivec2 offset);
+ivec4 textureLodOffset(isampler2D sampler, vec2 P, float lod, ivec2 offset);
+uvec4 textureLodOffset(usampler2D sampler, vec2 P, float lod, ivec2 offset);
+
+ vec4 textureLodOffset( sampler3D sampler, vec3 P, float lod, ivec3 offset);
+ivec4 textureLodOffset(isampler3D sampler, vec3 P, float lod, ivec3 offset);
+uvec4 textureLodOffset(usampler3D sampler, vec3 P, float lod, ivec3 offset);
+
+float textureLodOffset(sampler1DShadow samp, vec3 P, float lod, int offset);
+float textureLodOffset(sampler2DShadow samp, vec3 P, float lod, ivec2 offset);
+
+ vec4 textureLodOffset( sampler1DArray sampler, vec2 P, float lod, int offset);
+ivec4 textureLodOffset(isampler1DArray sampler, vec2 P, float lod, int offset);
+uvec4 textureLodOffset(usampler1DArray sampler, vec2 P, float lod, int offset);
+
+ vec4 textureLodOffset( sampler2DArray samp, vec3 P, float lod, ivec2 offset);
+ivec4 textureLodOffset(isampler2DArray samp, vec3 P, float lod, ivec2 offset);
+uvec4 textureLodOffset(usampler2DArray samp, vec3 P, float lod, ivec2 offset);
+
+float textureLodOffset(sampler1DArrayShadow s, vec3 P, float lod, int offset);
+#endif
+
+/* textureProjLod */
+ vec4 textureProjLod( sampler1D sampler, vec2 P, float lod);
+ivec4 textureProjLod(isampler1D sampler, vec2 P, float lod);
+uvec4 textureProjLod(usampler1D sampler, vec2 P, float lod);
+ vec4 textureProjLod( sampler1D sampler, vec4 P, float lod);
+ivec4 textureProjLod(isampler1D sampler, vec4 P, float lod);
+uvec4 textureProjLod(usampler1D sampler, vec4 P, float lod);
+
+ vec4 textureProjLod( sampler2D sampler, vec3 P, float lod);
+ivec4 textureProjLod(isampler2D sampler, vec3 P, float lod);
+uvec4 textureProjLod(usampler2D sampler, vec3 P, float lod);
+ vec4 textureProjLod( sampler2D sampler, vec4 P, float lod);
+ivec4 textureProjLod(isampler2D sampler, vec4 P, float lod);
+uvec4 textureProjLod(usampler2D sampler, vec4 P, float lod);
+
+ vec4 textureProjLod( sampler3D sampler, vec4 P, float lod);
+ivec4 textureProjLod(isampler3D sampler, vec4 P, float lod);
+uvec4 textureProjLod(usampler3D sampler, vec4 P, float lod);
+
+float textureProjLod(sampler1DShadow sampler, vec4 P, float lod);
+float textureProjLod(sampler2DShadow sampler, vec4 P, float lod);
+
+#if 0
+/* textureProjLodOffset */
+ vec4 textureProjLodOffset( sampler1D sampler, vec2 P, float lod, int offset);
+ivec4 textureProjLodOffset(isampler1D sampler, vec2 P, float lod, int offset);
+uvec4 textureProjLodOffset(usampler1D sampler, vec2 P, float lod, int offset);
+ vec4 textureProjLodOffset( sampler1D sampler, vec4 P, float lod, int offset);
+ivec4 textureProjLodOffset(isampler1D sampler, vec4 P, float lod, int offset);
+uvec4 textureProjLodOffset(usampler1D sampler, vec4 P, float lod, int offset);
+
+ vec4 textureProjLodOffset( sampler2D sampler, vec3 P, float lod, ivec2 offset);
+ivec4 textureProjLodOffset(isampler2D sampler, vec3 P, float lod, ivec2 offset);
+uvec4 textureProjLodOffset(usampler2D sampler, vec3 P, float lod, ivec2 offset);
+ vec4 textureProjLodOffset( sampler2D sampler, vec4 P, float lod, ivec2 offset);
+ivec4 textureProjLodOffset(isampler2D sampler, vec4 P, float lod, ivec2 offset);
+uvec4 textureProjLodOffset(usampler2D sampler, vec4 P, float lod, ivec2 offset);
+
+ vec4 textureProjLodOffset( sampler3D sampler, vec4 P, float lod, ivec3 offset);
+ivec4 textureProjLodOffset(isampler3D sampler, vec4 P, float lod, ivec3 offset);
+uvec4 textureProjLodOffset(usampler3D sampler, vec4 P, float lod, ivec3 offset);
+
+float textureProjLodOffset(sampler1DShadow s, vec4 P, float lod, int offset);
+float textureProjLodOffset(sampler2DShadow s, vec4 P, float lod, ivec2 offset);
+#endif
+
+/* textureGrad */
+ vec4 textureGrad( sampler1D sampler, float P, float dPdx, float dPdy);
+ivec4 textureGrad(isampler1D sampler, float P, float dPdx, float dPdy);
+uvec4 textureGrad(usampler1D sampler, float P, float dPdx, float dPdy);
+
+ vec4 textureGrad( sampler2D sampler, vec2 P, vec2 dPdx, vec2 dPdy);
+ivec4 textureGrad(isampler2D sampler, vec2 P, vec2 dPdx, vec2 dPdy);
+uvec4 textureGrad(usampler2D sampler, vec2 P, vec2 dPdx, vec2 dPdy);
+
+ vec4 textureGrad( sampler3D sampler, vec3 P, vec3 dPdx, vec3 dPdy);
+ivec4 textureGrad(isampler3D sampler, vec3 P, vec3 dPdx, vec3 dPdy);
+uvec4 textureGrad(usampler3D sampler, vec3 P, vec3 dPdx, vec3 dPdy);
+
+ vec4 textureGrad( samplerCube sampler, vec3 P, vec3 dPdx, vec3 dPdy);
+ivec4 textureGrad(isamplerCube sampler, vec3 P, vec3 dPdx, vec3 dPdy);
+uvec4 textureGrad(usamplerCube sampler, vec3 P, vec3 dPdx, vec3 dPdy);
+
+float textureGrad(sampler1DShadow   sampler, vec3 P, float dPdx, float dPdy);
+float textureGrad(sampler2DShadow   sampler, vec3 P, vec2  dPdx, vec2  dPdy);
+float textureGrad(samplerCubeShadow sampler, vec4 P, vec3  dPdx, vec3  dPdy);
+
+ vec4 textureGrad( sampler1DArray sampler, vec2 P, float dPdx, float dPdy);
+ivec4 textureGrad(isampler1DArray sampler, vec2 P, float dPdx, float dPdy);
+uvec4 textureGrad(usampler1DArray sampler, vec2 P, float dPdx, float dPdy);
+
+ vec4 textureGrad( sampler2DArray sampler, vec3 P, vec2 dPdx, vec2 dPdy);
+ivec4 textureGrad(isampler2DArray sampler, vec3 P, vec2 dPdx, vec2 dPdy);
+uvec4 textureGrad(usampler2DArray sampler, vec3 P, vec2 dPdx, vec2 dPdy);
+
+float textureGrad(sampler1DArrayShadow sampler, vec3 P, float dPdx, float dPdy);
+float textureGrad(sampler2DArrayShadow sampler, vec4 P, vec2  dPdx, vec2  dPdy);
+
+#if 0
+/* textureGradOffset */
+ vec4 textureGradOffset( sampler1D s, float P, float dx, float dy, int off);
+ivec4 textureGradOffset(isampler1D s, float P, float dx, float dy, int offset);
+uvec4 textureGradOffset(usampler1D s, float P, float dx, float dy, int offset);
+
+ vec4 textureGradOffset( sampler2D s, vec2 P, vec2 dx, vec2 dy, ivec2 offset);
+ivec4 textureGradOffset(isampler2D s, vec2 P, vec2 dx, vec2 dy, ivec2 offset);
+uvec4 textureGradOffset(usampler2D s, vec2 P, vec2 dx, vec2 dy, ivec2 offset);
+
+ vec4 textureGradOffset( sampler3D s, vec3 P, vec3 dx, vec3 dy, ivec3 offset);
+ivec4 textureGradOffset(isampler3D s, vec3 P, vec3 dx, vec3 dy, ivec3 offset);
+uvec4 textureGradOffset(usampler3D s, vec3 P, vec3 dx, vec3 dy, ivec3 offset);
+
+ vec4 textureGradOffset( samplerCube s, vec3 P, vec3 dx, vec3 dy, ivec3 offset);
+ivec4 textureGradOffset(isamplerCube s, vec3 P, vec3 dx, vec3 dy, ivec3 offset);
+uvec4 textureGradOffset(usamplerCube s, vec3 P, vec3 dx, vec3 dy, ivec3 offset);
+
+float textureGradOffset(sampler1DShadow s, vec3 P, float dx, float dy, int off);
+float textureGradOffset(sampler2DShadow s, vec3 P, vec2 dx, vec2 dy, ivec2 off);
+
+ vec4 textureGradOffset( sampler1DArray s, vec2 P, float dx, float dy, int off);
+ivec4 textureGradOffset(isampler1DArray s, vec2 P, float dx, float dy, int off);
+uvec4 textureGradOffset(usampler1DArray s, vec2 P, float dx, float dy, int off);
+
+ vec4 textureGradOffset( sampler2DArray s, vec3 P, vec2 dx, vec2 dy, ivec2 off);
+ivec4 textureGradOffset(isampler2DArray s, vec3 P, vec2 dx, vec2 dy, ivec2 off);
+uvec4 textureGradOffset(usampler2DArray s, vec3 P, vec2 dx, vec2 dy, ivec2 off);
+
+float textureGradOffset(sampler1DArrayShadow s, vec3 P, float dx, float dy, int o);
+float textureGradOffset(sampler2DArrayShadow s, vec4 P, vec2 dx, vec2 dy, ivec2 o);
+#endif
+
+/* textureProjGrad */
+ vec4 textureProjGrad( sampler1D sampler, vec2 P, float dPdx, float dPdy);
+ivec4 textureProjGrad(isampler1D sampler, vec2 P, float dPdx, float dPdy);
+uvec4 textureProjGrad(usampler1D sampler, vec2 P, float dPdx, float dPdy);
+ vec4 textureProjGrad( sampler1D sampler, vec4 P, float dPdx, float dPdy);
+ivec4 textureProjGrad(isampler1D sampler, vec4 P, float dPdx, float dPdy);
+uvec4 textureProjGrad(usampler1D sampler, vec4 P, float dPdx, float dPdy);
+
+ vec4 textureProjGrad( sampler2D sampler, vec3 P, vec2 dPdx, vec2 dPdy);
+ivec4 textureProjGrad(isampler2D sampler, vec3 P, vec2 dPdx, vec2 dPdy);
+uvec4 textureProjGrad(usampler2D sampler, vec3 P, vec2 dPdx, vec2 dPdy);
+ vec4 textureProjGrad( sampler2D sampler, vec4 P, vec2 dPdx, vec2 dPdy);
+ivec4 textureProjGrad(isampler2D sampler, vec4 P, vec2 dPdx, vec2 dPdy);
+uvec4 textureProjGrad(usampler2D sampler, vec4 P, vec2 dPdx, vec2 dPdy);
+
+ vec4 textureProjGrad( sampler3D sampler, vec4 P, vec3 dPdx, vec3 dPdy);
+ivec4 textureProjGrad(isampler3D sampler, vec4 P, vec3 dPdx, vec3 dPdy);
+uvec4 textureProjGrad(usampler3D sampler, vec4 P, vec3 dPdx, vec3 dPdy);
+
+float textureProjGrad(sampler1DShadow sampler, vec4 P, float dPdx, float dPdy);
+float textureProjGrad(sampler2DShadow sampler, vec4 P, vec2  dPdx, vec2  dPdy);
+
+#if 0
+/* textureProjGradOffset */
+ vec4 textureProjGradOffset( sampler1D s, vec2 P, float dx, float dy, int off);
+ivec4 textureProjGradOffset(isampler1D s, vec2 P, float dx, float dy, int off);
+uvec4 textureProjGradOffset(usampler1D s, vec2 P, float dx, float dy, int off);
+ vec4 textureProjGradOffset( sampler1D s, vec4 P, float dx, float dy, int off);
+ivec4 textureProjGradOffset(isampler1D s, vec4 P, float dx, float dy, int off);
+uvec4 textureProjGradOffset(usampler1D s, vec4 P, float dx, float dy, int off);
+
+ vec4 textureProjGradOffset( sampler2D s, vec3 P, vec2 dx, vec2 dy, ivec2 off);
+ivec4 textureProjGradOffset(isampler2D s, vec3 P, vec2 dx, vec2 dy, ivec2 off);
+uvec4 textureProjGradOffset(usampler2D s, vec3 P, vec2 dx, vec2 dy, ivec2 off);
+ vec4 textureProjGradOffset( sampler2D s, vec4 P, vec2 dx, vec2 dy, ivec2 off);
+ivec4 textureProjGradOffset(isampler2D s, vec4 P, vec2 dx, vec2 dy, ivec2 off);
+uvec4 textureProjGradOffset(usampler2D s, vec4 P, vec2 dx, vec2 dy, ivec2 off);
+
+ vec4 textureProjGradOffset( sampler3D s, vec4 P, vec3 dx, vec3 dy, ivec3 off);
+ivec4 textureProjGradOffset(isampler3D s, vec4 P, vec3 dx, vec3 dy, ivec3 off);
+uvec4 textureProjGradOffset(usampler3D s, vec4 P, vec3 dx, vec3 dy, ivec3 off);
+
+float textureProjGradOffset(sampler1DShadow s, vec4 P, float dx, float dy, int o);
+float textureProjGradOffset(sampler2DShadow s, vec4 P, vec2 dx, vec2 dy, vec2 o);
+#endif
+
+/*
+ * The following texture functions are deprecated:
+ */
+vec4 texture1D       (sampler1D sampler, float coord);
+vec4 texture1DProj   (sampler1D sampler, vec2  coord);
+vec4 texture1DProj   (sampler1D sampler, vec4  coord);
+vec4 texture1D       (sampler1D sampler, float coord, float bias);
+vec4 texture1DProj   (sampler1D sampler, vec2  coord, float bias);
+vec4 texture1DProj   (sampler1D sampler, vec4  coord, float bias);
+vec4 texture1DLod    (sampler1D sampler, float coord, float lod);
+vec4 texture1DProjLod(sampler1D sampler, vec2  coord, float lod);
+vec4 texture1DProjLod(sampler1D sampler, vec4  coord, float lod);
+
+vec4 texture2D       (sampler2D sampler, vec2 coord);
+vec4 texture2DProj   (sampler2D sampler, vec3 coord);
+vec4 texture2DProj   (sampler2D sampler, vec4 coord);
+vec4 texture2D       (sampler2D sampler, vec2 coord, float bias);
+vec4 texture2DProj   (sampler2D sampler, vec3 coord, float bias);
+vec4 texture2DProj   (sampler2D sampler, vec4 coord, float bias);
+vec4 texture2DLod    (sampler2D sampler, vec2 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);
+vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);
+
+vec4 texture3D       (sampler3D sampler, vec3 coord);
+vec4 texture3DProj   (sampler3D sampler, vec4 coord);
+vec4 texture3D       (sampler3D sampler, vec3 coord, float bias);
+vec4 texture3DProj   (sampler3D sampler, vec4 coord, float bias);
+vec4 texture3DLod    (sampler3D sampler, vec3 coord, float lod);
+vec4 texture3DProjLod(sampler3D sampler, vec4 coord, float lod);
+
+vec4 textureCube     (samplerCube sampler, vec3 coord);
+vec4 textureCube     (samplerCube sampler, vec3 coord, float bias);
+vec4 textureCubeLod  (samplerCube sampler, vec3 coord, float lod);
+
+vec4 shadow1D       (sampler1DShadow sampler, vec3 coord);
+vec4 shadow2D       (sampler2DShadow sampler, vec3 coord);
+vec4 shadow1DProj   (sampler1DShadow sampler, vec4 coord);
+vec4 shadow2DProj   (sampler2DShadow sampler, vec4 coord);
+vec4 shadow1D       (sampler1DShadow sampler, vec3 coord, float bias);
+vec4 shadow2D       (sampler2DShadow sampler, vec3 coord, float bias);
+vec4 shadow1DProj   (sampler1DShadow sampler, vec4 coord, float bias);
+vec4 shadow2DProj   (sampler2DShadow sampler, vec4 coord, float bias);
+vec4 shadow1DLod    (sampler1DShadow sampler, vec3 coord, float lod);
+vec4 shadow2DLod    (sampler2DShadow sampler, vec3 coord, float lod);
+vec4 shadow1DProjLod(sampler1DShadow sampler, vec4 coord, float lod);
+vec4 shadow2DProjLod(sampler2DShadow sampler, vec4 coord, float lod);
+
+/*
+ * 8.8 - Fragment Processing Functions (none in vertex shader)
+ */
+
+/*
+ * 8.9 - Noise Functions
+ */
+float noise1(float x);
+float noise1(vec2  x);
+float noise1(vec3  x);
+float noise1(vec4  x);
+
+vec2  noise2(float x);
+vec2  noise2(vec2  x);
+vec2  noise2(vec3  x);
+vec2  noise2(vec4  x);
+
+vec3  noise3(float x);
+vec3  noise3(vec2  x);
+vec3  noise3(vec3  x);
+vec3  noise3(vec4  x);
+
+vec4  noise4(float x);
+vec4  noise4(vec2  x);
+vec4  noise4(vec3  x);
+vec4  noise4(vec4  x);
diff --git a/src/glsl/builtins/profiles/ARB_texture_rectangle.frag b/src/glsl/builtins/profiles/ARB_texture_rectangle.frag
new file mode 100644 (file)
index 0000000..8938aa3
--- /dev/null
@@ -0,0 +1,7 @@
+#extension GL_ARB_texture_rectangle : enable
+vec4 texture2DRect(sampler2DRect sampler, vec2 coord);
+vec4 texture2DRectProj(sampler2DRect sampler, vec3 coord);
+vec4 texture2DRectProj(sampler2DRect sampler, vec4 coord);
+
+vec4 shadow2DRect(sampler2DRectShadow sampler, vec3 coord);
+vec4 shadow2DRectProj(sampler2DRectShadow sampler, vec4 coord);
diff --git a/src/glsl/builtins/profiles/ARB_texture_rectangle.vert b/src/glsl/builtins/profiles/ARB_texture_rectangle.vert
new file mode 100644 (file)
index 0000000..8938aa3
--- /dev/null
@@ -0,0 +1,7 @@
+#extension GL_ARB_texture_rectangle : enable
+vec4 texture2DRect(sampler2DRect sampler, vec2 coord);
+vec4 texture2DRectProj(sampler2DRect sampler, vec3 coord);
+vec4 texture2DRectProj(sampler2DRect sampler, vec4 coord);
+
+vec4 shadow2DRect(sampler2DRectShadow sampler, vec3 coord);
+vec4 shadow2DRectProj(sampler2DRectShadow sampler, vec4 coord);
diff --git a/src/glsl/builtins/profiles/EXT_texture_array.frag b/src/glsl/builtins/profiles/EXT_texture_array.frag
new file mode 100644 (file)
index 0000000..d0ce981
--- /dev/null
@@ -0,0 +1,11 @@
+#extension GL_EXT_texture_array : enable
+vec4 texture1DArray(sampler1DArray sampler, vec2 coord);
+vec4 texture1DArray(sampler1DArray sampler, vec2 coord, float bias);
+
+vec4 texture2DArray(sampler2DArray sampler, vec3 coord);
+vec4 texture2DArray(sampler2DArray sampler, vec3 coord, float bias);
+
+vec4 shadow1DArray(sampler1DArrayShadow sampler, vec3 coord);
+vec4 shadow1DArray(sampler1DArrayShadow sampler, vec3 coord, float bias);
+
+vec4 shadow2DArray(sampler2DArrayShadow sampler, vec4 coord);
diff --git a/src/glsl/builtins/profiles/EXT_texture_array.vert b/src/glsl/builtins/profiles/EXT_texture_array.vert
new file mode 100644 (file)
index 0000000..6b1b7f2
--- /dev/null
@@ -0,0 +1,11 @@
+#extension GL_EXT_texture_array : enable
+vec4 texture1DArray(sampler1DArray sampler, vec2 coord);
+vec4 texture1DArrayLod(sampler1DArray sampler, vec2 coord, float lod);
+
+vec4 texture2DArray(sampler2DArray sampler, vec3 coord);
+vec4 texture2DArrayLod(sampler2DArray sampler, vec3 coord, float lod);
+
+vec4 shadow1DArray(sampler1DArrayShadow sampler, vec3 coord);
+vec4 shadow1DArrayLod(sampler1DArrayShadow sampler, vec3 coord, float lod);
+
+vec4 shadow2DArray(sampler2DArrayShadow sampler, vec4 coord);
diff --git a/src/glsl/builtins/tools/builtin_function.cpp b/src/glsl/builtins/tools/builtin_function.cpp
new file mode 100644 (file)
index 0000000..c44804f
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 "glsl_parser_extras.h"
+
+/* A dummy file.  When compiling prototypes, we don't care about builtins.
+ * We really don't want to half-compile builtin_functions.cpp and fail, though.
+ */
+void
+_mesa_glsl_release_functions(void)
+{
+}
+
+void
+_mesa_glsl_initialize_functions(exec_list *instructions,
+                               struct _mesa_glsl_parse_state *state)
+{
+}
diff --git a/src/glsl/builtins/tools/generate_builtins.py b/src/glsl/builtins/tools/generate_builtins.py
new file mode 100755 (executable)
index 0000000..5accc1b
--- /dev/null
@@ -0,0 +1,240 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import re
+from glob import glob
+from os import path
+from subprocess import Popen, PIPE
+
+# Local module: generator for texture lookup builtins
+from texture_builtins import generate_texture_functions
+
+builtins_dir = path.join(path.dirname(path.abspath(__file__)), "..")
+
+# Read the files in builtins/ir/*...add them to the supplied dictionary.
+def read_ir_files(fs):
+    for filename in glob(path.join(path.join(builtins_dir, 'ir'), '*')):
+        with open(filename) as f:
+            fs[path.basename(filename)] = f.read()
+
+# Return a dictionary containing all builtin definitions (even generated)
+def get_builtin_definitions():
+    fs = {}
+    generate_texture_functions(fs)
+    read_ir_files(fs)
+    return fs
+
+def stringify(s):
+    t = s.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n"\n   "')
+    return '   "' + t + '"\n'
+
+def write_function_definitions():
+    fs = get_builtin_definitions()
+    for k, v in sorted(fs.iteritems()):
+        print 'static const char *builtin_' + k + ' ='
+        print stringify(v), ';'
+
+def run_compiler(args):
+    compiler_path = path.join(path.join(builtins_dir, '..'), 'glsl_compiler')
+    command = [compiler_path, '--dump-lir'] + args
+    p = Popen(command, 1, stdout=PIPE, shell=False)
+    output = p.communicate()[0]
+
+    # Clean up output a bit by killing whitespace before a closing paren.
+    kill_paren_whitespace = re.compile(r'[ \n]*\)', re.MULTILINE);
+    output = kill_paren_whitespace.sub(')', output);
+
+    # Also toss any duplicate newlines
+    output = output.replace('\n\n', '\n')
+
+    return (output, p.returncode)
+
+def write_profile(filename, profile):
+    (proto_ir, returncode) = run_compiler([filename])
+
+    if returncode != 0:
+        print '#error builtins profile', profile, 'failed to compile'
+        return
+
+    # Kill any global variable declarations.  We don't want them.
+    kill_globals = re.compile(r'^\(declare.*\n', re.MULTILINE);
+    proto_ir = kill_globals.sub('', proto_ir)
+
+    # Kill pointer addresses.  They're not necessary in prototypes and just
+    # clutter the diff output.
+    proto_ir = re.sub(r'@0x[0-9a-f]+', '', proto_ir);
+
+    print 'static const char *prototypes_for_' + profile + ' ='
+    print stringify(proto_ir), ';'
+
+    # Print a table of all the functions (not signatures) referenced.
+    # This is done so we can avoid bothering with a hash table in the C++ code.
+
+    function_names = set()
+    for func in re.finditer(r'\(function (.+)\n', proto_ir):
+        function_names.add(func.group(1))
+
+    print 'static const char *functions_for_' + profile + ' [] = {'
+    for func in sorted(function_names):
+        print '   builtin_' + func + ','
+    print '};'
+
+def write_profiles():
+    profiles = get_profile_list()
+    for (filename, profile) in profiles:
+        write_profile(filename, profile)
+
+def get_profile_list():
+    profiles = []
+    for pfile in sorted(glob(path.join(path.join(builtins_dir, 'profiles'), '*'))):
+        profiles.append((pfile, path.basename(pfile).replace('.', '_')))
+    return profiles
+
+if __name__ == "__main__":
+    print """/* DO NOT MODIFY - automatically generated by generate_builtins.py */
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 "main/core.h" /* for struct gl_shader */
+#include "glsl_parser_extras.h"
+#include "ir_reader.h"
+#include "program.h"
+#include "ast.h"
+
+extern "C" struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
+
+gl_shader *
+read_builtins(GLenum target, const char *protos, const char **functions, unsigned count)
+{
+   gl_shader *sh = _mesa_new_shader(NULL, 0, target);
+   struct _mesa_glsl_parse_state *st =
+      new(sh) _mesa_glsl_parse_state(NULL, target, sh);
+
+   st->language_version = 130;
+   st->symbols->language_version = 130;
+   st->ARB_texture_rectangle_enable = true;
+   st->EXT_texture_array_enable = true;
+   _mesa_glsl_initialize_types(st);
+
+   sh->ir = new(sh) exec_list;
+   sh->symbols = st->symbols;
+
+   /* Read the IR containing the prototypes */
+   _mesa_glsl_read_ir(st, sh->ir, protos, true);
+
+   /* Read ALL the function bodies, telling the IR reader not to scan for
+    * prototypes (we've already created them).  The IR reader will skip any
+    * signature that does not already exist as a prototype.
+    */
+   for (unsigned i = 0; i < count; i++) {
+      _mesa_glsl_read_ir(st, sh->ir, functions[i], false);
+
+      if (st->error) {
+         printf("error reading builtin: %.35s ...\\n", functions[i]);
+         talloc_free(sh);
+         return NULL;
+      }
+   }
+
+   reparent_ir(sh->ir, sh);
+   delete st;
+
+   return sh;
+}
+"""
+
+    write_function_definitions()
+    write_profiles()
+
+    profiles = get_profile_list()
+
+    print 'static gl_shader *builtin_profiles[%d];' % len(profiles)
+
+    print """
+void *builtin_mem_ctx = NULL;
+
+void
+_mesa_glsl_release_functions(void)
+{
+   talloc_free(builtin_mem_ctx);
+   builtin_mem_ctx = NULL;
+}
+
+static void
+_mesa_read_profile(struct _mesa_glsl_parse_state *state,
+                  exec_list *instructions,
+                   int profile_index,
+                  const char *prototypes,
+                  const char **functions,
+                   int count)
+{
+   gl_shader *sh = builtin_profiles[profile_index];
+
+   if (sh == NULL) {
+      sh = read_builtins(GL_VERTEX_SHADER, prototypes, functions, count);
+      talloc_steal(builtin_mem_ctx, sh);
+      builtin_profiles[profile_index] = sh;
+   }
+
+   import_prototypes(sh->ir, instructions, state->symbols, state);
+   state->builtins_to_link[state->num_builtins_to_link] = sh;
+   state->num_builtins_to_link++;
+}
+
+void
+_mesa_glsl_initialize_functions(exec_list *instructions,
+                                struct _mesa_glsl_parse_state *state)
+{
+   if (builtin_mem_ctx == NULL) {
+      builtin_mem_ctx = talloc_init("GLSL built-in functions");
+      memset(&builtin_profiles, 0, sizeof(builtin_profiles));
+   }
+
+   state->num_builtins_to_link = 0;
+"""
+
+    i=0
+    for (filename, profile) in profiles:
+        if profile.endswith('_vert'):
+            check = 'state->target == vertex_shader && '
+        elif profile.endswith('_frag'):
+            check = 'state->target == fragment_shader && '
+
+        version = re.sub(r'_(vert|frag)$', '', profile)
+        if version.isdigit():
+            check += 'state->language_version == ' + version
+        else: # an extension name
+            check += 'state->' + version + '_enable'
+
+        print '   if (' + check + ') {'
+        print '      _mesa_read_profile(state, instructions, %d,' % i
+        print '                         prototypes_for_' + profile + ','
+        print '                         functions_for_' + profile + ','
+        print '                         Elements(functions_for_' + profile + '));'
+        print '   }'
+        print
+        i = i + 1
+    print '}'
+
diff --git a/src/glsl/builtins/tools/generate_matrixCompMultGLSL.py b/src/glsl/builtins/tools/generate_matrixCompMultGLSL.py
new file mode 100755 (executable)
index 0000000..391ad11
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+
+def gen_matrix(x, y = 0):
+    if y == 0:
+        y = x
+    type = "mat" + str(x)
+    if x != y:
+        type = type + "x" + str(y)
+    print type + " matrixCompMult(" + type + " x, " + type + " y)\n{"
+    print "    " + type + " z;"
+
+    for i in range(x):
+        print "    z[" + str(i) + "] = x[" + str(i) + "] * y[" + str(i) + "];"
+    print "    return z;\n}"
+
+print "#version 120"
+# 1.10
+gen_matrix(2)
+gen_matrix(3)
+gen_matrix(4)
+
+# 1.20
+gen_matrix(2,3) # mat2x3 means 2 columns, 3 rows
+gen_matrix(3,2)
+gen_matrix(2,4)
+gen_matrix(4,2)
+gen_matrix(3,4)
+gen_matrix(4,3)
diff --git a/src/glsl/builtins/tools/generate_outerProductGLSL.py b/src/glsl/builtins/tools/generate_outerProductGLSL.py
new file mode 100755 (executable)
index 0000000..c561cc3
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/python
+
+def gen(x, y):
+    type = "mat" + str(x)
+    if x != y:
+        type = type + "x" + str(y)
+    print type + " outerProduct(vec" + str(y) + " u, vec" + str(x) + " v)\n{"
+    print "    " + type + " m;"
+
+    for i in range(x):
+        print "    m[" + str(i) + "] = u * v[" + str(i) + "];"
+    print "    return m;\n}"
+
+print "#version 120"
+gen(2,2)
+gen(2,3) # mat2x3 means 2 columns, 3 rows
+gen(2,4)
+gen(3,2)
+gen(3,3)
+gen(3,4)
+gen(4,2)
+gen(4,3)
+gen(4,4)
diff --git a/src/glsl/builtins/tools/generate_transposeGLSL.py b/src/glsl/builtins/tools/generate_transposeGLSL.py
new file mode 100755 (executable)
index 0000000..8f669ce
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+
+def gen(x, y):
+    origtype = "mat" + str(x)
+    trantype = "mat" + str(y)
+    if x != y:
+        origtype = origtype + "x" + str(y)
+        trantype = trantype + "x" + str(x)
+    print trantype + " transpose(" + origtype + " m)\n{"
+    print "    " + trantype + " t;"
+
+    # The obvious implementation of transpose
+    for i in range(x):
+        for j in range(y):
+            print "    t[" + str(j) + "][" + str(i) + "] =",
+            print "m[" + str(i) + "][" + str(j) + "];"
+    print "    return t;\n}"
+
+print "#version 120"
+gen(2,2)
+gen(2,3) # mat2x3 means 2 columns, 3 rows
+gen(2,4)
+gen(3,2)
+gen(3,3)
+gen(3,4)
+gen(4,2)
+gen(4,3)
+gen(4,4)
diff --git a/src/glsl/builtins/tools/texture_builtins.py b/src/glsl/builtins/tools/texture_builtins.py
new file mode 100755 (executable)
index 0000000..8bf708b
--- /dev/null
@@ -0,0 +1,349 @@
+#!/usr/bin/python
+
+import sys
+import StringIO
+
+def vec_type(g, size):
+    if size == 1:
+        if g == "i":
+            return "int"
+        elif g == "u":
+            return "uint"
+        return "float"
+    return g + "vec" + str(size)
+
+# Get the base dimension - i.e. sampler3D gives 3
+# Array samplers also get +1 here since the layer is really an extra coordinate
+def get_coord_dim(sampler_type):
+    if sampler_type[0].isdigit():
+        coord_dim = int(sampler_type[0])
+    elif sampler_type.startswith("Cube"):
+        coord_dim = 3
+    else:
+        assert False ("coord_dim: invalid sampler_type: " + sampler_type)
+
+    if sampler_type.find("Array") != -1:
+        coord_dim += 1
+    return coord_dim
+
+# Get the number of extra vector components (i.e. shadow comparitor)
+def get_extra_dim(sampler_type, use_proj, unused_fields):
+    extra_dim = unused_fields
+    if sampler_type.find("Shadow") != -1:
+        extra_dim += 1
+    if use_proj:
+        extra_dim += 1
+    return extra_dim
+
+def generate_sigs(g, tex_inst, sampler_type, use_proj = False, unused_fields = 0):
+    coord_dim = get_coord_dim(sampler_type)
+    extra_dim = get_extra_dim(sampler_type, use_proj, unused_fields)
+
+    # Print parameters
+    print "   (signature " + g + "vec4"
+    print "     (parameters"
+    print "       (declare (in) " + g + "sampler" + sampler_type + " sampler)"
+    print "       (declare (in) " + vec_type("i" if tex_inst == "txf" else "", coord_dim + extra_dim) + " P)",
+    if tex_inst == "txb":
+        print "\n       (declare (in) float bias)",
+    elif tex_inst == "txl":
+        print "\n       (declare (in) float lod)",
+    elif tex_inst == "txf":
+        print "\n       (declare (in) int lod)",
+    elif tex_inst == "txd":
+        grad_type = vec_type("", coord_dim)
+        print "\n       (declare (in) " + grad_type + " dPdx)",
+        print "\n       (declare (in) " + grad_type + " dPdy)",
+
+    print ")\n     ((return (" + tex_inst + " (var_ref sampler)",
+
+    # Coordinate
+    if extra_dim > 0:
+        print "(swiz " + "xyzw"[:coord_dim] + " (var_ref P))",
+    else:
+        print "(var_ref P)",
+
+    # Offset
+    print "(0 0 0)",
+
+    if tex_inst != "txf":
+        # Projective divisor
+        if use_proj:
+            print "(swiz " + "xyzw"[coord_dim + extra_dim-1] + " (var_ref P))",
+        else:
+            print "1",
+
+        # Shadow comparitor
+        if sampler_type == "2DArrayShadow": # a special case:
+            print "(swiz w (var_ref P))",   # ...array layer is z; shadow is w
+        elif sampler_type.endswith("Shadow"):
+            print "(swiz z (var_ref P))",
+        else:
+            print "()",
+
+    # Bias/explicit LOD/gradient:
+    if tex_inst == "txb":
+        print "(var_ref bias)",
+    elif tex_inst == "txl" or tex_inst == "txf":
+        print "(var_ref lod)",
+    elif tex_inst == "txd":
+        print "((var_ref dPdx) (var_ref dPdy))",
+    print "))))\n"
+
+def generate_fiu_sigs(tex_inst, sampler_type, use_proj = False, unused_fields = 0):
+    generate_sigs("",  tex_inst, sampler_type, use_proj, unused_fields)
+    generate_sigs("i", tex_inst, sampler_type, use_proj, unused_fields)
+    generate_sigs("u", tex_inst, sampler_type, use_proj, unused_fields)
+
+def start_function(name):
+    sys.stdout = StringIO.StringIO()
+    print "((function " + name
+
+def end_function(fs, name):
+    print "))"
+    fs[name] = sys.stdout.getvalue();
+    sys.stdout.close()
+
+# Generate all the functions and store them in the supplied dictionary.
+# This is better than writing them to actual files since they should never be
+# edited; it'd also be easy to confuse them with the many hand-generated files.
+#
+# Takes a dictionary as an argument.
+def generate_texture_functions(fs):
+    start_function("texture")
+    generate_fiu_sigs("tex", "1D")
+    generate_fiu_sigs("tex", "2D")
+    generate_fiu_sigs("tex", "3D")
+    generate_fiu_sigs("tex", "Cube")
+    generate_fiu_sigs("tex", "1DArray")
+    generate_fiu_sigs("tex", "2DArray")
+
+    generate_fiu_sigs("txb", "1D")
+    generate_fiu_sigs("txb", "2D")
+    generate_fiu_sigs("txb", "3D")
+    generate_fiu_sigs("txb", "Cube")
+    generate_fiu_sigs("txb", "1DArray")
+    generate_fiu_sigs("txb", "2DArray")
+    end_function(fs, "texture")
+
+    start_function("textureProj")
+    generate_fiu_sigs("tex", "1D", True)
+    generate_fiu_sigs("tex", "1D", True, 2)
+    generate_fiu_sigs("tex", "2D", True)
+    generate_fiu_sigs("tex", "2D", True, 1)
+    generate_fiu_sigs("tex", "3D", True)
+
+    generate_fiu_sigs("txb", "1D", True)
+    generate_fiu_sigs("txb", "1D", True, 2)
+    generate_fiu_sigs("txb", "2D", True)
+    generate_fiu_sigs("txb", "2D", True, 1)
+    generate_fiu_sigs("txb", "3D", True)
+    end_function(fs, "textureProj")
+
+    start_function("textureLod")
+    generate_fiu_sigs("txl", "1D")
+    generate_fiu_sigs("txl", "2D")
+    generate_fiu_sigs("txl", "3D")
+    generate_fiu_sigs("txl", "Cube")
+    generate_fiu_sigs("txl", "1DArray")
+    generate_fiu_sigs("txl", "2DArray")
+    end_function(fs, "textureLod")
+
+    start_function("texelFetch")
+    generate_fiu_sigs("txf", "1D")
+    generate_fiu_sigs("txf", "2D")
+    generate_fiu_sigs("txf", "3D")
+    generate_fiu_sigs("txf", "1DArray")
+    generate_fiu_sigs("txf", "2DArray")
+    end_function(fs, "texelFetch")
+
+    start_function("textureProjLod")
+    generate_fiu_sigs("txl", "1D", True)
+    generate_fiu_sigs("txl", "1D", True, 2)
+    generate_fiu_sigs("txl", "2D", True)
+    generate_fiu_sigs("txl", "2D", True, 1)
+    generate_fiu_sigs("txl", "3D", True)
+    end_function(fs, "textureProjLod")
+
+    start_function("textureGrad")
+    generate_fiu_sigs("txd", "1D")
+    generate_fiu_sigs("txd", "2D")
+    generate_fiu_sigs("txd", "3D")
+    generate_fiu_sigs("txd", "Cube")
+    generate_fiu_sigs("txd", "1DArray")
+    generate_fiu_sigs("txd", "2DArray")
+    end_function(fs, "textureGrad")
+
+    start_function("textureProjGrad")
+    generate_fiu_sigs("txd", "1D", True)
+    generate_fiu_sigs("txd", "1D", True, 2)
+    generate_fiu_sigs("txd", "2D", True)
+    generate_fiu_sigs("txd", "2D", True, 1)
+    generate_fiu_sigs("txd", "3D", True)
+    end_function(fs, "textureProjGrad")
+
+    # ARB_texture_rectangle extension
+    start_function("texture2DRect")
+    generate_sigs("", "tex", "2DRect")
+    end_function(fs, "texture2DRect")
+
+    start_function("texture2DRectProj")
+    generate_sigs("", "tex", "2DRect", True)
+    generate_sigs("", "tex", "2DRect", True, 1)
+    end_function(fs, "texture2DRectProj")
+
+    start_function("shadow2DRect")
+    generate_sigs("", "tex", "2DRectShadow")
+    end_function(fs, "shadow2DRect")
+
+    start_function("shadow2DRectProj")
+    generate_sigs("", "tex", "2DRectShadow", True)
+    end_function(fs, "shadow2DRectProj")
+
+    # EXT_texture_array extension
+    start_function("texture1DArray")
+    generate_sigs("", "tex", "1DArray")
+    generate_sigs("", "txb", "1DArray")
+    end_function(fs, "texture1DArray")
+
+    start_function("texture1DArrayLod")
+    generate_sigs("", "txl", "1DArray")
+    end_function(fs, "texture1DArrayLod")
+
+    start_function("texture2DArray")
+    generate_sigs("", "tex", "2DArray")
+    generate_sigs("", "txb", "2DArray")
+    end_function(fs, "texture2DArray")
+
+    start_function("texture2DArrayLod")
+    generate_sigs("", "txl", "2DArray")
+    end_function(fs, "texture2DArrayLod")
+
+    start_function("shadow1DArray")
+    generate_sigs("", "tex", "1DArrayShadow")
+    generate_sigs("", "txb", "1DArrayShadow")
+    end_function(fs, "shadow1DArray")
+
+    start_function("shadow1DArrayLod")
+    generate_sigs("", "txl", "1DArrayShadow")
+    end_function(fs, "shadow1DArrayLod")
+
+    start_function("shadow2DArray")
+    generate_sigs("", "tex", "2DArrayShadow")
+    end_function(fs, "shadow2DArray")
+
+    # Deprecated (110/120 style) functions with silly names:
+    start_function("texture1D")
+    generate_sigs("", "tex", "1D")
+    generate_sigs("", "txb", "1D")
+    end_function(fs, "texture1D")
+
+    start_function("texture1DLod")
+    generate_sigs("", "txl", "1D")
+    end_function(fs, "texture1DLod")
+
+    start_function("texture1DProj")
+    generate_sigs("", "tex", "1D", True)
+    generate_sigs("", "tex", "1D", True, 2)
+    generate_sigs("", "txb", "1D", True)
+    generate_sigs("", "txb", "1D", True, 2)
+    end_function(fs, "texture1DProj")
+
+    start_function("texture1DProjLod")
+    generate_sigs("", "txl", "1D", True)
+    generate_sigs("", "txl", "1D", True, 2)
+    end_function(fs, "texture1DProjLod")
+
+    start_function("texture2D")
+    generate_sigs("", "tex", "2D")
+    generate_sigs("", "txb", "2D")
+    end_function(fs, "texture2D")
+
+    start_function("texture2DLod")
+    generate_sigs("", "txl", "2D")
+    end_function(fs, "texture2DLod")
+
+    start_function("texture2DProj")
+    generate_sigs("", "tex", "2D", True)
+    generate_sigs("", "tex", "2D", True, 1)
+    generate_sigs("", "txb", "2D", True)
+    generate_sigs("", "txb", "2D", True, 1)
+    end_function(fs, "texture2DProj")
+
+    start_function("texture2DProjLod")
+    generate_sigs("", "txl", "2D", True)
+    generate_sigs("", "txl", "2D", True, 1)
+    end_function(fs, "texture2DProjLod")
+
+    start_function("texture3D")
+    generate_sigs("", "tex", "3D")
+    generate_sigs("", "txb", "3D")
+    end_function(fs, "texture3D")
+
+    start_function("texture3DLod")
+    generate_sigs("", "txl", "3D")
+    end_function(fs, "texture3DLod")
+
+    start_function("texture3DProj")
+    generate_sigs("", "tex", "3D", True)
+    generate_sigs("", "txb", "3D", True)
+    end_function(fs, "texture3DProj")
+
+    start_function("texture3DProjLod")
+    generate_sigs("", "txl", "3D", True)
+    end_function(fs, "texture3DProjLod")
+
+    start_function("textureCube")
+    generate_sigs("", "tex", "Cube")
+    generate_sigs("", "txb", "Cube")
+    end_function(fs, "textureCube")
+
+    start_function("textureCubeLod")
+    generate_sigs("", "txl", "Cube")
+    end_function(fs, "textureCubeLod")
+
+    start_function("shadow1D")
+    generate_sigs("", "tex", "1DShadow", False, 1)
+    generate_sigs("", "txb", "1DShadow", False, 1)
+    end_function(fs, "shadow1D")
+
+    start_function("shadow1DLod")
+    generate_sigs("", "txl", "1DShadow", False, 1)
+    end_function(fs, "shadow1DLod")
+
+    start_function("shadow1DProj")
+    generate_sigs("", "tex", "1DShadow", True, 1)
+    generate_sigs("", "txb", "1DShadow", True, 1)
+    end_function(fs, "shadow1DProj")
+
+    start_function("shadow1DProjLod")
+    generate_sigs("", "txl", "1DShadow", True, 1)
+    end_function(fs, "shadow1DProjLod")
+
+    start_function("shadow2D")
+    generate_sigs("", "tex", "2DShadow")
+    generate_sigs("", "txb", "2DShadow")
+    end_function(fs, "shadow2D")
+
+    start_function("shadow2DLod")
+    generate_sigs("", "txl", "2DShadow")
+    end_function(fs, "shadow2DLod")
+
+    start_function("shadow2DProj")
+    generate_sigs("", "tex", "2DShadow", True)
+    generate_sigs("", "txb", "2DShadow", True)
+    end_function(fs, "shadow2DProj")
+
+    start_function("shadow2DProjLod")
+    generate_sigs("", "txl", "2DShadow", True)
+    end_function(fs, "shadow2DProjLod")
+
+    sys.stdout = sys.__stdout__
+    return fs
+
+# If you actually run this script, it'll print out all the functions.
+if __name__ == "__main__":
+    fs = {}
+    generate_texture_functions(fs);
+    for k, v in fs.iteritems():
+       print v
diff --git a/src/glsl/cl/Makefile b/src/glsl/cl/Makefile
deleted file mode 100644 (file)
index 04a52df..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#src/glsl/cl/Makefile
-
-TOP = ../../..
-
-include $(TOP)/configs/current
-
-LIBNAME = glslcl
-
-C_SOURCES = \
-       sl_cl_parse.c
-
-include ../Makefile.template
-
diff --git a/src/glsl/cl/sl_cl_parse.c b/src/glsl/cl/sl_cl_parse.c
deleted file mode 100644 (file)
index c1bc603..0000000
+++ /dev/null
@@ -1,3027 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "../pp/sl_pp_public.h"
-#include "../pp/sl_pp_token.h"
-#include "sl_cl_parse.h"
-
-
-/* revision number - increment after each change affecting emitted output */
-#define REVISION                                   5
-
-/* external declaration (or precision or invariant stmt) */
-#define EXTERNAL_NULL                              0
-#define EXTERNAL_FUNCTION_DEFINITION               1
-#define EXTERNAL_DECLARATION                       2
-#define DEFAULT_PRECISION                          3
-#define INVARIANT_STMT                             4
-
-/* precision */
-#define PRECISION_DEFAULT                          0
-#define PRECISION_LOW                              1
-#define PRECISION_MEDIUM                           2
-#define PRECISION_HIGH                             3
-
-/* declaration */
-#define DECLARATION_FUNCTION_PROTOTYPE             1
-#define DECLARATION_INIT_DECLARATOR_LIST           2
-
-/* function type */
-#define FUNCTION_ORDINARY                          0
-#define FUNCTION_CONSTRUCTOR                       1
-#define FUNCTION_OPERATOR                          2
-
-/* function call type */
-#define FUNCTION_CALL_NONARRAY                     0
-#define FUNCTION_CALL_ARRAY                        1
-
-/* operator type */
-#define OPERATOR_ADDASSIGN                         1
-#define OPERATOR_SUBASSIGN                         2
-#define OPERATOR_MULASSIGN                         3
-#define OPERATOR_DIVASSIGN                         4
-/*#define OPERATOR_MODASSIGN                         5*/
-/*#define OPERATOR_LSHASSIGN                         6*/
-/*#define OPERATOR_RSHASSIGN                         7*/
-/*#define OPERATOR_ORASSIGN                          8*/
-/*#define OPERATOR_XORASSIGN                         9*/
-/*#define OPERATOR_ANDASSIGN                         10*/
-#define OPERATOR_LOGICALXOR                        11
-/*#define OPERATOR_BITOR                             12*/
-/*#define OPERATOR_BITXOR                            13*/
-/*#define OPERATOR_BITAND                            14*/
-#define OPERATOR_LESS                              15
-#define OPERATOR_GREATER                           16
-#define OPERATOR_LESSEQUAL                         17
-#define OPERATOR_GREATEREQUAL                      18
-/*#define OPERATOR_LSHIFT                            19*/
-/*#define OPERATOR_RSHIFT                            20*/
-#define OPERATOR_MULTIPLY                          21
-#define OPERATOR_DIVIDE                            22
-/*#define OPERATOR_MODULUS                           23*/
-#define OPERATOR_INCREMENT                         24
-#define OPERATOR_DECREMENT                         25
-#define OPERATOR_PLUS                              26
-#define OPERATOR_MINUS                             27
-/*#define OPERATOR_COMPLEMENT                        28*/
-#define OPERATOR_NOT                               29
-
-/* init declarator list */
-#define DECLARATOR_NONE                            0
-#define DECLARATOR_NEXT                            1
-
-/* variable declaration */
-#define VARIABLE_NONE                              0
-#define VARIABLE_IDENTIFIER                        1
-#define VARIABLE_INITIALIZER                       2
-#define VARIABLE_ARRAY_EXPLICIT                    3
-#define VARIABLE_ARRAY_UNKNOWN                     4
-
-/* type qualifier */
-#define TYPE_QUALIFIER_NONE                        0
-#define TYPE_QUALIFIER_CONST                       1
-#define TYPE_QUALIFIER_ATTRIBUTE                   2
-#define TYPE_QUALIFIER_VARYING                     3
-#define TYPE_QUALIFIER_UNIFORM                     4
-#define TYPE_QUALIFIER_FIXEDOUTPUT                 5
-#define TYPE_QUALIFIER_FIXEDINPUT                  6
-
-/* invariant qualifier */
-#define TYPE_VARIANT                               90
-#define TYPE_INVARIANT                             91
-
-/* centroid qualifier */
-#define TYPE_CENTER                                95
-#define TYPE_CENTROID                              96
-
-/* layout qualifiers */
-#define LAYOUT_QUALIFIER_NONE                      0
-#define LAYOUT_QUALIFIER_UPPER_LEFT                1
-#define LAYOUT_QUALIFIER_PIXEL_CENTER_INTEGER      2
-
-/* type specifier */
-#define TYPE_SPECIFIER_VOID                        0
-#define TYPE_SPECIFIER_BOOL                        1
-#define TYPE_SPECIFIER_BVEC2                       2
-#define TYPE_SPECIFIER_BVEC3                       3
-#define TYPE_SPECIFIER_BVEC4                       4
-#define TYPE_SPECIFIER_INT                         5
-#define TYPE_SPECIFIER_IVEC2                       6
-#define TYPE_SPECIFIER_IVEC3                       7
-#define TYPE_SPECIFIER_IVEC4                       8
-#define TYPE_SPECIFIER_FLOAT                       9
-#define TYPE_SPECIFIER_VEC2                        10
-#define TYPE_SPECIFIER_VEC3                        11
-#define TYPE_SPECIFIER_VEC4                        12
-#define TYPE_SPECIFIER_MAT2                        13
-#define TYPE_SPECIFIER_MAT3                        14
-#define TYPE_SPECIFIER_MAT4                        15
-#define TYPE_SPECIFIER_SAMPLER1D                   16
-#define TYPE_SPECIFIER_SAMPLER2D                   17
-#define TYPE_SPECIFIER_SAMPLER3D                   18
-#define TYPE_SPECIFIER_SAMPLERCUBE                 19
-#define TYPE_SPECIFIER_SAMPLER1DSHADOW             20
-#define TYPE_SPECIFIER_SAMPLER2DSHADOW             21
-#define TYPE_SPECIFIER_SAMPLER2DRECT               22
-#define TYPE_SPECIFIER_SAMPLER2DRECTSHADOW         23
-#define TYPE_SPECIFIER_STRUCT                      24
-#define TYPE_SPECIFIER_TYPENAME                    25
-
-/* OpenGL 2.1 */
-#define TYPE_SPECIFIER_MAT23                       26
-#define TYPE_SPECIFIER_MAT32                       27
-#define TYPE_SPECIFIER_MAT24                       28
-#define TYPE_SPECIFIER_MAT42                       29
-#define TYPE_SPECIFIER_MAT34                       30
-#define TYPE_SPECIFIER_MAT43                       31
-
-/* GL_EXT_texture_array */
-#define TYPE_SPECIFIER_SAMPLER_1D_ARRAY            32
-#define TYPE_SPECIFIER_SAMPLER_2D_ARRAY            33
-#define TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW     34
-#define TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW     35
-
-/* type specifier array */
-#define TYPE_SPECIFIER_NONARRAY                    0
-#define TYPE_SPECIFIER_ARRAY                       1
-
-/* structure field */
-#define FIELD_NONE                                 0
-#define FIELD_NEXT                                 1
-#define FIELD_ARRAY                                2
-
-/* operation */
-#define OP_END                                     0
-#define OP_BLOCK_BEGIN_NO_NEW_SCOPE                1
-#define OP_BLOCK_BEGIN_NEW_SCOPE                   2
-#define OP_DECLARE                                 3
-#define OP_ASM                                     4
-#define OP_BREAK                                   5
-#define OP_CONTINUE                                6
-#define OP_DISCARD                                 7
-#define OP_RETURN                                  8
-#define OP_EXPRESSION                              9
-#define OP_IF                                      10
-#define OP_WHILE                                   11
-#define OP_DO                                      12
-#define OP_FOR                                     13
-#define OP_PUSH_VOID                               14
-#define OP_PUSH_BOOL                               15
-#define OP_PUSH_INT                                16
-#define OP_PUSH_FLOAT                              17
-#define OP_PUSH_IDENTIFIER                         18
-#define OP_SEQUENCE                                19
-#define OP_ASSIGN                                  20
-#define OP_ADDASSIGN                               21
-#define OP_SUBASSIGN                               22
-#define OP_MULASSIGN                               23
-#define OP_DIVASSIGN                               24
-/*#define OP_MODASSIGN                               25*/
-/*#define OP_LSHASSIGN                               26*/
-/*#define OP_RSHASSIGN                               27*/
-/*#define OP_ORASSIGN                                28*/
-/*#define OP_XORASSIGN                               29*/
-/*#define OP_ANDASSIGN                               30*/
-#define OP_SELECT                                  31
-#define OP_LOGICALOR                               32
-#define OP_LOGICALXOR                              33
-#define OP_LOGICALAND                              34
-/*#define OP_BITOR                                   35*/
-/*#define OP_BITXOR                                  36*/
-/*#define OP_BITAND                                  37*/
-#define OP_EQUAL                                   38
-#define OP_NOTEQUAL                                39
-#define OP_LESS                                    40
-#define OP_GREATER                                 41
-#define OP_LESSEQUAL                               42
-#define OP_GREATEREQUAL                            43
-/*#define OP_LSHIFT                                  44*/
-/*#define OP_RSHIFT                                  45*/
-#define OP_ADD                                     46
-#define OP_SUBTRACT                                47
-#define OP_MULTIPLY                                48
-#define OP_DIVIDE                                  49
-/*#define OP_MODULUS                                 50*/
-#define OP_PREINCREMENT                            51
-#define OP_PREDECREMENT                            52
-#define OP_PLUS                                    53
-#define OP_MINUS                                   54
-/*#define OP_COMPLEMENT                              55*/
-#define OP_NOT                                     56
-#define OP_SUBSCRIPT                               57
-#define OP_CALL                                    58
-#define OP_FIELD                                   59
-#define OP_POSTINCREMENT                           60
-#define OP_POSTDECREMENT                           61
-#define OP_PRECISION                               62
-#define OP_METHOD                                  63
-
-/* parameter qualifier */
-#define PARAM_QUALIFIER_IN                         0
-#define PARAM_QUALIFIER_OUT                        1
-#define PARAM_QUALIFIER_INOUT                      2
-#define PARAM_QUALIFIER_NONE                       3
-
-/* function parameter */
-#define PARAMETER_NONE                             0
-#define PARAMETER_NEXT                             1
-
-/* function parameter array presence */
-#define PARAMETER_ARRAY_NOT_PRESENT                0
-#define PARAMETER_ARRAY_PRESENT                    1
-
-
-struct parse_dict {
-   int _void;
-   int _float;
-   int _int;
-   int _bool;
-   int vec2;
-   int vec3;
-   int vec4;
-   int bvec2;
-   int bvec3;
-   int bvec4;
-   int ivec2;
-   int ivec3;
-   int ivec4;
-   int mat2;
-   int mat3;
-   int mat4;
-   int mat2x3;
-   int mat3x2;
-   int mat2x4;
-   int mat4x2;
-   int mat3x4;
-   int mat4x3;
-   int sampler1D;
-   int sampler2D;
-   int sampler3D;
-   int samplerCube;
-   int sampler1DShadow;
-   int sampler2DShadow;
-   int sampler2DRect;
-   int sampler2DRectShadow;
-   int sampler1DArray;
-   int sampler2DArray;
-   int sampler1DArrayShadow;
-   int sampler2DArrayShadow;
-
-   int invariant;
-
-   int centroid;
-
-   int precision;
-   int lowp;
-   int mediump;
-   int highp;
-
-   int _const;
-   int attribute;
-   int varying;
-   int uniform;
-   int __fixed_output;
-   int __fixed_input;
-
-   int in;
-   int out;
-   int inout;
-
-   int layout;
-   int origin_upper_left;
-   int pixel_center_integer;
-
-   int _struct;
-
-   int __constructor;
-   int __operator;
-   int ___asm;
-
-   int _if;
-   int _else;
-   int _for;
-   int _while;
-   int _do;
-
-   int _continue;
-   int _break;
-   int _return;
-   int discard;
-
-   int _false;
-   int _true;
-
-   int all;
-   int _GL_ARB_fragment_coord_conventions;
-   int _GL_ARB_texture_rectangle;
-};
-
-
-struct parse_context {
-   struct sl_pp_context *context;
-
-   struct parse_dict dict;
-
-   struct sl_pp_token_info *tokens;
-   unsigned int tokens_read;
-   unsigned int tokens_cap;
-
-   unsigned char *out_buf;
-   unsigned int out_cap;
-
-   unsigned int shader_type;
-   unsigned int parsing_builtin;
-
-   unsigned int fragment_coord_conventions:1;
-   unsigned int texture_rectangle:1;
-
-   char error[256];
-   int process_error;
-};
-
-
-struct parse_state {
-   unsigned int in;
-   unsigned int out;
-};
-
-
-static unsigned int
-_emit(struct parse_context *ctx,
-      unsigned int *out,
-      unsigned char b)
-{
-   if (*out == ctx->out_cap) {
-      ctx->out_cap += 4096;
-      ctx->out_buf = (unsigned char *)realloc(ctx->out_buf, ctx->out_cap * sizeof(unsigned char));
-   }
-   ctx->out_buf[*out] = b;
-   return (*out)++;
-}
-
-
-static void
-_update(struct parse_context *ctx,
-        unsigned int out,
-        unsigned char b)
-{
-   ctx->out_buf[out] = b;
-}
-
-
-static void
-_error(struct parse_context *ctx,
-       const char *msg)
-{
-   if (ctx->error[0] == '\0') {
-      strncpy(ctx->error, msg, sizeof(ctx->error) - 1);
-      ctx->error[sizeof(ctx->error) - 1] = '\0';
-   }
-}
-
-
-static const struct sl_pp_token_info *
-_fetch_token(struct parse_context *ctx,
-             unsigned int pos)
-{
-   if (ctx->process_error) {
-      return NULL;
-   }
-
-   while (pos >= ctx->tokens_read) {
-      if (ctx->tokens_read == ctx->tokens_cap) {
-         ctx->tokens_cap += 1024;
-         ctx->tokens = realloc(ctx->tokens,
-                               ctx->tokens_cap * sizeof(struct sl_pp_token_info));
-         if (!ctx->tokens) {
-            _error(ctx, "out of memory");
-            ctx->process_error = 1;
-            return NULL;
-         }
-      }
-      if (sl_pp_process_get(ctx->context, &ctx->tokens[ctx->tokens_read])) {
-         _error(ctx, sl_pp_context_error_message(ctx->context));
-         ctx->process_error = 1;
-         return NULL;
-      }
-      switch (ctx->tokens[ctx->tokens_read].token) {
-      case SL_PP_COMMA:
-      case SL_PP_SEMICOLON:
-      case SL_PP_LBRACE:
-      case SL_PP_RBRACE:
-      case SL_PP_LPAREN:
-      case SL_PP_RPAREN:
-      case SL_PP_LBRACKET:
-      case SL_PP_RBRACKET:
-      case SL_PP_DOT:
-      case SL_PP_INCREMENT:
-      case SL_PP_ADDASSIGN:
-      case SL_PP_PLUS:
-      case SL_PP_DECREMENT:
-      case SL_PP_SUBASSIGN:
-      case SL_PP_MINUS:
-      case SL_PP_BITNOT:
-      case SL_PP_NOTEQUAL:
-      case SL_PP_NOT:
-      case SL_PP_MULASSIGN:
-      case SL_PP_STAR:
-      case SL_PP_DIVASSIGN:
-      case SL_PP_SLASH:
-      case SL_PP_MODASSIGN:
-      case SL_PP_MODULO:
-      case SL_PP_LSHIFTASSIGN:
-      case SL_PP_LSHIFT:
-      case SL_PP_LESSEQUAL:
-      case SL_PP_LESS:
-      case SL_PP_RSHIFTASSIGN:
-      case SL_PP_RSHIFT:
-      case SL_PP_GREATEREQUAL:
-      case SL_PP_GREATER:
-      case SL_PP_EQUAL:
-      case SL_PP_ASSIGN:
-      case SL_PP_AND:
-      case SL_PP_BITANDASSIGN:
-      case SL_PP_BITAND:
-      case SL_PP_XOR:
-      case SL_PP_BITXORASSIGN:
-      case SL_PP_BITXOR:
-      case SL_PP_OR:
-      case SL_PP_BITORASSIGN:
-      case SL_PP_BITOR:
-      case SL_PP_QUESTION:
-      case SL_PP_COLON:
-      case SL_PP_IDENTIFIER:
-      case SL_PP_UINT:
-      case SL_PP_FLOAT:
-      case SL_PP_EXTENSION_REQUIRE:
-      case SL_PP_EXTENSION_ENABLE:
-      case SL_PP_EXTENSION_WARN:
-      case SL_PP_EXTENSION_DISABLE:
-      case SL_PP_EOF:
-         ctx->tokens_read++;
-         break;
-      default:
-         ; /* no-op */
-      }
-   }
-   return &ctx->tokens[pos];
-}
-
-
-/**
- * Try to parse/match a particular token.
- * \return 0 for success, -1 for error.
- */
-static int
-_parse_token(struct parse_context *ctx,
-             enum sl_pp_token token,
-             struct parse_state *ps)
-{
-   const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
-
-   if (input && input->token == token) {
-      ps->in++;
-      return 0;
-   }
-   return -1;
-}
-
-
-/**
- * Try to parse an identifer.
- * \return 0 for success, -1 for error
- */
-static int
-_parse_id(struct parse_context *ctx,
-          int id,
-          struct parse_state *ps)
-{
-   const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
-
-   if (input && input->token == SL_PP_IDENTIFIER && input->data.identifier == id) {
-      ps->in++;
-      return 0;
-   }
-   return -1;
-}
-
-
-static int
-_parse_identifier(struct parse_context *ctx,
-                  struct parse_state *ps)
-{
-   const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
-
-   if (input && input->token == SL_PP_IDENTIFIER) {
-      const char *cstr = sl_pp_context_cstr(ctx->context, input->data.identifier);
-
-      do {
-         _emit(ctx, &ps->out, *cstr);
-      } while (*cstr++);
-      ps->in++;
-      return 0;
-   }
-   return -1;
-}
-
-
-static int
-_parse_float(struct parse_context *ctx,
-             struct parse_state *ps)
-{
-   const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
-
-   if (input && input->token == SL_PP_FLOAT) {
-      const char *cstr = sl_pp_context_cstr(ctx->context, input->data._float);
-
-      _emit(ctx, &ps->out, 1);
-      do {
-         _emit(ctx, &ps->out, *cstr);
-      } while (*cstr++);
-      ps->in++;
-      return 0;
-   }
-   return -1;
-}
-
-
-static int
-_parse_uint(struct parse_context *ctx,
-            struct parse_state *ps)
-{
-   const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
-
-   if (input && input->token == SL_PP_UINT) {
-      const char *cstr = sl_pp_context_cstr(ctx->context, input->data._uint);
-
-      _emit(ctx, &ps->out, 1);
-      do {
-         _emit(ctx, &ps->out, *cstr);
-      } while (*cstr++);
-      ps->in++;
-      return 0;
-   }
-   return -1;
-}
-
-
-/**************************************/
-
-
-static int
-_parse_unary_expression(struct parse_context *ctx,
-                        struct parse_state *ps);
-
-static int
-_parse_conditional_expression(struct parse_context *ctx,
-                              struct parse_state *ps);
-
-
-static int
-_parse_constant_expression(struct parse_context *ctx,
-                           struct parse_state *ps);
-
-
-static int
-_parse_primary_expression(struct parse_context *ctx,
-                          struct parse_state *ps);
-
-
-static int
-_parse_statement(struct parse_context *ctx,
-                 struct parse_state *ps);
-
-
-static int
-_parse_type_specifier(struct parse_context *ctx,
-                      struct parse_state *ps);
-
-
-static int
-_parse_declaration(struct parse_context *ctx,
-                   struct parse_state *ps);
-
-
-static int
-_parse_statement_list(struct parse_context *ctx,
-                      struct parse_state *ps);
-
-
-static int
-_parse_assignment_expression(struct parse_context *ctx,
-                             struct parse_state *ps);
-
-
-static int
-_parse_precision(struct parse_context *ctx,
-                 struct parse_state *ps);
-
-
-static int
-_parse_overriden_operator(struct parse_context *ctx,
-                          struct parse_state *ps)
-{
-   unsigned int op;
-
-   if (_parse_token(ctx, SL_PP_INCREMENT, ps) == 0) {
-      op = OPERATOR_INCREMENT;
-   } else if (_parse_token(ctx, SL_PP_ADDASSIGN, ps) == 0) {
-      op = OPERATOR_ADDASSIGN;
-   } else if (_parse_token(ctx, SL_PP_PLUS, ps) == 0) {
-      op = OPERATOR_PLUS;
-   } else if (_parse_token(ctx, SL_PP_DECREMENT, ps) == 0) {
-      op = OPERATOR_DECREMENT;
-   } else if (_parse_token(ctx, SL_PP_SUBASSIGN, ps) == 0) {
-      op = OPERATOR_SUBASSIGN;
-   } else if (_parse_token(ctx, SL_PP_MINUS, ps) == 0) {
-      op = OPERATOR_MINUS;
-   } else if (_parse_token(ctx, SL_PP_NOT, ps) == 0) {
-      op = OPERATOR_NOT;
-   } else if (_parse_token(ctx, SL_PP_MULASSIGN, ps) == 0) {
-      op = OPERATOR_MULASSIGN;
-   } else if (_parse_token(ctx, SL_PP_STAR, ps) == 0) {
-      op = OPERATOR_MULTIPLY;
-   } else if (_parse_token(ctx, SL_PP_DIVASSIGN, ps) == 0) {
-      op = OPERATOR_DIVASSIGN;
-   } else if (_parse_token(ctx, SL_PP_SLASH, ps) == 0) {
-      op = OPERATOR_DIVIDE;
-   } else if (_parse_token(ctx, SL_PP_LESSEQUAL, ps) == 0) {
-      op = OPERATOR_LESSEQUAL;
-   } else if (_parse_token(ctx, SL_PP_LESS, ps) == 0) {
-      op = OPERATOR_LESS;
-   } else if (_parse_token(ctx, SL_PP_GREATEREQUAL, ps) == 0) {
-      op = OPERATOR_GREATEREQUAL;
-   } else if (_parse_token(ctx, SL_PP_GREATER, ps) == 0) {
-      op = OPERATOR_GREATER;
-   } else if (_parse_token(ctx, SL_PP_XOR, ps) == 0) {
-      op = OPERATOR_LOGICALXOR;
-   } else {
-      return -1;
-   }
-
-   _emit(ctx, &ps->out, op);
-   return 0;
-}
-
-
-static int
-_parse_function_decl_identifier(struct parse_context *ctx,
-                                struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-   unsigned int e = _emit(ctx, &p.out, 0);
-
-   if (ctx->parsing_builtin && _parse_id(ctx, ctx->dict.__constructor, &p) == 0) {
-      _update(ctx, e, FUNCTION_CONSTRUCTOR);
-      *ps = p;
-      return 0;
-   }
-
-   if (ctx->parsing_builtin && _parse_id(ctx, ctx->dict.__operator, &p) == 0) {
-      _update(ctx, e, FUNCTION_OPERATOR);
-      if (_parse_overriden_operator(ctx, &p) == 0) {
-         *ps = p;
-         return 0;
-      }
-      return -1;
-   }
-
-   if (_parse_identifier(ctx, &p) == 0) {
-      _update(ctx, e, FUNCTION_ORDINARY);
-      *ps = p;
-      return 0;
-   }
-
-   return -1;
-}
-
-
-static int
-_parse_invariant_qualifier(struct parse_context *ctx,
-                           struct parse_state *ps)
-{
-   if (_parse_id(ctx, ctx->dict.invariant, ps)) {
-      return -1;
-   }
-   _emit(ctx, &ps->out, TYPE_INVARIANT);
-   return 0;
-}
-
-
-static int
-_parse_centroid_qualifier(struct parse_context *ctx,
-                          struct parse_state *ps)
-{
-   if (_parse_id(ctx, ctx->dict.centroid, ps)) {
-      return -1;
-   }
-   _emit(ctx, &ps->out, TYPE_CENTROID);
-   return 0;
-}
-
-
-static int
-_parse_layout_qualifier(struct parse_context *ctx,
-                        struct parse_state *ps)
-{
-   if (_parse_id(ctx, ctx->dict.layout, ps) == 0) {
-      if (!ctx->fragment_coord_conventions) {
-         _error(ctx, "GL_ARB_fragment_coord_conventions extension must be enabled "
-                     "in order to use a layout qualifier");
-         return -1;
-      }
-
-      /* Layout qualifiers are only defined for fragment shaders,
-       * so do an early check.
-       */
-      if (ctx->shader_type != 1) {
-         _error(ctx, "layout qualifiers are only valid for fragment shaders");
-         return -1;
-      }
-
-      /* start of a parenthesised list of layout qualifiers */
-
-      if (_parse_token(ctx, SL_PP_LPAREN, ps)) {
-         _error(ctx, "expected `('");
-         return -1;
-      }
-
-      /* parse comma-separated ID list */
-      while (1) {
-         if (_parse_id(ctx, ctx->dict.origin_upper_left, ps) == 0) {
-            _emit(ctx, &ps->out, LAYOUT_QUALIFIER_UPPER_LEFT);
-         }
-         else if (_parse_id(ctx, ctx->dict.pixel_center_integer, ps) == 0) {
-            _emit(ctx, &ps->out, LAYOUT_QUALIFIER_PIXEL_CENTER_INTEGER);
-         }
-         else {
-            _error(ctx, "expected a layout qualifier name");
-            return -1;
-         }
-
-         if (_parse_token(ctx, SL_PP_RPAREN, ps) == 0) {
-            /* all done */
-            break;
-         }
-         else if (_parse_token(ctx, SL_PP_COMMA, ps) == 0) {
-            /* another layout qualifier is coming */
-         }
-         else {
-            _error(ctx, "expected `,' or `)'");
-            return -1;
-         }
-      }
-   }
-
-   return 0;
-}
-
-
-static int
-_parse_storage_qualifier(struct parse_context *ctx,
-                         struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-   const struct sl_pp_token_info *input = _fetch_token(ctx, p.in);
-   unsigned int e = _emit(ctx, &p.out, 0);
-   int id;
-
-   if (!input || input->token != SL_PP_IDENTIFIER) {
-      return -1;
-   }
-   id = input->data.identifier;
-
-   if (id == ctx->dict._const) {
-      _update(ctx, e, TYPE_QUALIFIER_CONST);
-   } else if (ctx->shader_type == 2 && id == ctx->dict.attribute) {
-      _update(ctx, e, TYPE_QUALIFIER_ATTRIBUTE);
-   } else if (id == ctx->dict.varying) {
-      _update(ctx, e, TYPE_QUALIFIER_VARYING);
-   } else if (id == ctx->dict.uniform) {
-      _update(ctx, e, TYPE_QUALIFIER_UNIFORM);
-   } else if (ctx->parsing_builtin && id == ctx->dict.__fixed_output) {
-      _update(ctx, e, TYPE_QUALIFIER_FIXEDOUTPUT);
-   } else if (ctx->parsing_builtin && id == ctx->dict.__fixed_input) {
-      _update(ctx, e, TYPE_QUALIFIER_FIXEDINPUT);
-   } else {
-      return -1;
-   }
-   _parse_token(ctx, SL_PP_IDENTIFIER, &p);
-   *ps = p;
-   return 0;
-}
-
-static int
-_parse_struct_declarator(struct parse_context *ctx,
-                         struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-   unsigned int e;
-
-   if (_parse_identifier(ctx, &p)) {
-      return -1;
-   }
-   e = _emit(ctx, &p.out, FIELD_NONE);
-   *ps = p;
-
-   if (_parse_token(ctx, SL_PP_LBRACKET, &p)) {
-      return 0;
-   }
-   if (_parse_constant_expression(ctx, &p)) {
-      _error(ctx, "expected constant integral expression");
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_RBRACKET, &p)) {
-      _error(ctx, "expected `]'");
-      return -1;
-   }
-   _update(ctx, e, FIELD_ARRAY);
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_struct_declarator_list(struct parse_context *ctx,
-                              struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_struct_declarator(ctx, &p)) {
-      return -1;
-   }
-
-   for (;;) {
-      *ps = p;
-      _emit(ctx, &p.out, FIELD_NEXT);
-      if (_parse_token(ctx, SL_PP_COMMA, &p)) {
-         return 0;
-      }
-      if (_parse_struct_declarator(ctx, &p)) {
-         return 0;
-      }
-   }
-}
-
-
-static int
-_parse_struct_declaration(struct parse_context *ctx,
-                          struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_type_specifier(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_struct_declarator_list(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, FIELD_NONE);
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_struct_declaration_list(struct parse_context *ctx,
-                               struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_struct_declaration(ctx, &p)) {
-      return -1;
-   }
-
-   for (;;) {
-      *ps = p;
-      _emit(ctx, &p.out, FIELD_NEXT);
-      if (_parse_struct_declaration(ctx, &p)) {
-         return 0;
-      }
-   }
-}
-
-
-static int
-_parse_struct_specifier(struct parse_context *ctx,
-                        struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_id(ctx, ctx->dict._struct, &p)) {
-      return -1;
-   }
-   if (_parse_identifier(ctx, &p)) {
-      _emit(ctx, &p.out, '\0');
-   }
-   if (_parse_token(ctx, SL_PP_LBRACE, &p)) {
-      _error(ctx, "expected `{'");
-      return -1;
-   }
-   if (_parse_struct_declaration_list(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_RBRACE, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, FIELD_NONE);
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_type_specifier_nonarray(struct parse_context *ctx,
-                               struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-   unsigned int e = _emit(ctx, &p.out, 0);
-   const struct sl_pp_token_info *input;
-   int id;
-
-   if (_parse_struct_specifier(ctx, &p) == 0) {
-      _update(ctx, e, TYPE_SPECIFIER_STRUCT);
-      *ps = p;
-      return 0;
-   }
-
-   input = _fetch_token(ctx, p.in);
-   if (!input || input->token != SL_PP_IDENTIFIER) {
-      return -1;
-   }
-   id = input->data.identifier;
-
-   if (id == ctx->dict._void) {
-      _update(ctx, e, TYPE_SPECIFIER_VOID);
-   } else if (id == ctx->dict._float) {
-      _update(ctx, e, TYPE_SPECIFIER_FLOAT);
-   } else if (id == ctx->dict._int) {
-      _update(ctx, e, TYPE_SPECIFIER_INT);
-   } else if (id == ctx->dict._bool) {
-      _update(ctx, e, TYPE_SPECIFIER_BOOL);
-   } else if (id == ctx->dict.vec2) {
-      _update(ctx, e, TYPE_SPECIFIER_VEC2);
-   } else if (id == ctx->dict.vec3) {
-      _update(ctx, e, TYPE_SPECIFIER_VEC3);
-   } else if (id == ctx->dict.vec4) {
-      _update(ctx, e, TYPE_SPECIFIER_VEC4);
-   } else if (id == ctx->dict.bvec2) {
-      _update(ctx, e, TYPE_SPECIFIER_BVEC2);
-   } else if (id == ctx->dict.bvec3) {
-      _update(ctx, e, TYPE_SPECIFIER_BVEC3);
-   } else if (id == ctx->dict.bvec4) {
-      _update(ctx, e, TYPE_SPECIFIER_BVEC4);
-   } else if (id == ctx->dict.ivec2) {
-      _update(ctx, e, TYPE_SPECIFIER_IVEC2);
-   } else if (id == ctx->dict.ivec3) {
-      _update(ctx, e, TYPE_SPECIFIER_IVEC3);
-   } else if (id == ctx->dict.ivec4) {
-      _update(ctx, e, TYPE_SPECIFIER_IVEC4);
-   } else if (id == ctx->dict.mat2) {
-      _update(ctx, e, TYPE_SPECIFIER_MAT2);
-   } else if (id == ctx->dict.mat3) {
-      _update(ctx, e, TYPE_SPECIFIER_MAT3);
-   } else if (id == ctx->dict.mat4) {
-      _update(ctx, e, TYPE_SPECIFIER_MAT4);
-   } else if (id == ctx->dict.mat2x3) {
-      _update(ctx, e, TYPE_SPECIFIER_MAT23);
-   } else if (id == ctx->dict.mat3x2) {
-      _update(ctx, e, TYPE_SPECIFIER_MAT32);
-   } else if (id == ctx->dict.mat2x4) {
-      _update(ctx, e, TYPE_SPECIFIER_MAT24);
-   } else if (id == ctx->dict.mat4x2) {
-      _update(ctx, e, TYPE_SPECIFIER_MAT42);
-   } else if (id == ctx->dict.mat3x4) {
-      _update(ctx, e, TYPE_SPECIFIER_MAT34);
-   } else if (id == ctx->dict.mat4x3) {
-      _update(ctx, e, TYPE_SPECIFIER_MAT43);
-   } else if (id == ctx->dict.sampler1D) {
-      _update(ctx, e, TYPE_SPECIFIER_SAMPLER1D);
-   } else if (id == ctx->dict.sampler2D) {
-      _update(ctx, e, TYPE_SPECIFIER_SAMPLER2D);
-   } else if (id == ctx->dict.sampler3D) {
-      _update(ctx, e, TYPE_SPECIFIER_SAMPLER3D);
-   } else if (id == ctx->dict.samplerCube) {
-      _update(ctx, e, TYPE_SPECIFIER_SAMPLERCUBE);
-   } else if (id == ctx->dict.sampler1DShadow) {
-      _update(ctx, e, TYPE_SPECIFIER_SAMPLER1DSHADOW);
-   } else if (id == ctx->dict.sampler2DShadow) {
-      _update(ctx, e, TYPE_SPECIFIER_SAMPLER2DSHADOW);
-   } else if (id == ctx->dict.sampler2DRect) {
-      if (!ctx->texture_rectangle) {
-         _error(ctx, "GL_ARB_texture_rectangle extension must be enabled "
-                     "in order to use a rect sampler");
-         return -1;
-      }
-      _update(ctx, e, TYPE_SPECIFIER_SAMPLER2DRECT);
-   } else if (id == ctx->dict.sampler2DRectShadow) {
-      if (!ctx->texture_rectangle) {
-         _error(ctx, "GL_ARB_texture_rectangle extension must be enabled "
-                     "in order to use a rect sampler");
-         return -1;
-      }
-      _update(ctx, e, TYPE_SPECIFIER_SAMPLER2DRECTSHADOW);
-   } else if (id == ctx->dict.sampler1DArray) {
-      _update(ctx, e, TYPE_SPECIFIER_SAMPLER_1D_ARRAY);
-   } else if (id == ctx->dict.sampler2DArray) {
-      /* XXX check for GL_EXT_texture_array */
-      _update(ctx, e, TYPE_SPECIFIER_SAMPLER_2D_ARRAY);
-   } else if (id == ctx->dict.sampler1DArrayShadow) {
-      _update(ctx, e, TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW);
-   } else if (id == ctx->dict.sampler2DArrayShadow) {
-      _update(ctx, e, TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW);
-   } else if (_parse_identifier(ctx, &p) == 0) {
-      _update(ctx, e, TYPE_SPECIFIER_TYPENAME);
-      *ps = p;
-      return 0;
-   } else {
-      return -1;
-   }
-
-   _parse_token(ctx, SL_PP_IDENTIFIER, &p);
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_type_specifier_array(struct parse_context *ctx,
-                            struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_token(ctx, SL_PP_LBRACKET, &p)) {
-      return -1;
-   }
-   if (_parse_constant_expression(ctx, &p)) {
-      _error(ctx, "expected constant integral expression");
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_RBRACKET, &p)) {
-      _error(ctx, "expected `]'");
-      return -1;
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_type_specifier(struct parse_context *ctx,
-                      struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-   unsigned int e;
-
-   if (_parse_type_specifier_nonarray(ctx, &p)) {
-      return -1;
-   }
-
-   e = _emit(ctx, &p.out, TYPE_SPECIFIER_ARRAY);
-   if (_parse_type_specifier_array(ctx, &p)) {
-      _update(ctx, e, TYPE_SPECIFIER_NONARRAY);
-   }
-   *ps = p;
-   return 0;
-}
-
-static int
-_parse_parameter_qualifier(struct parse_context *ctx,
-                           struct parse_state *ps)
-{
-   unsigned int e = _emit(ctx, &ps->out, PARAM_QUALIFIER_NONE);
-
-   if (_parse_id(ctx, ctx->dict.in, ps) == 0) {
-      _update(ctx, e, PARAM_QUALIFIER_IN);
-   } else if (_parse_id(ctx, ctx->dict.out, ps) == 0) {
-      _update(ctx, e, PARAM_QUALIFIER_OUT);
-   } else if (_parse_id(ctx, ctx->dict.inout, ps) == 0) {
-      _update(ctx, e, PARAM_QUALIFIER_INOUT);
-   }
-   return 0;
-}
-
-static int
-_parse_fully_specified_type(struct parse_context *ctx,
-                            struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_layout_qualifier(ctx, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, LAYOUT_QUALIFIER_NONE);
-
-   if (_parse_invariant_qualifier(ctx, &p)) {
-      _emit(ctx, &p.out, TYPE_VARIANT);
-   }
-
-   if (_parse_centroid_qualifier(ctx, &p)) {
-      _emit(ctx, &p.out, TYPE_CENTER);
-   }
-   if (_parse_storage_qualifier(ctx, &p)) {
-      _emit(ctx, &p.out, TYPE_QUALIFIER_NONE);
-   }
-   _parse_parameter_qualifier(ctx, &p);
-   if (_parse_precision(ctx, &p)) {
-      _emit(ctx, &p.out, PRECISION_DEFAULT);
-   }
-   if (_parse_type_specifier(ctx, &p)) {
-      return -1;
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_function_header(struct parse_context *ctx,
-                       struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_fully_specified_type(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_function_decl_identifier(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_LPAREN, &p)) {
-      return -1;
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_function_identifier(struct parse_context *ctx,
-                           struct parse_state *ps)
-{
-   struct parse_state p;
-   unsigned int e;
-
-   if (_parse_identifier(ctx, ps)) {
-      return -1;
-   }
-   e = _emit(ctx, &ps->out, FUNCTION_CALL_NONARRAY);
-
-   p = *ps;
-   if (_parse_token(ctx, SL_PP_LBRACKET, &p)) {
-      return 0;
-   }
-   if (_parse_constant_expression(ctx, &p)) {
-      _error(ctx, "expected constant integral expression");
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_RBRACKET, &p)) {
-      _error(ctx, "expected `]'");
-      return -1;
-   }
-   _update(ctx, e, FUNCTION_CALL_ARRAY);
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_function_call_header(struct parse_context *ctx,
-                            struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_function_identifier(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_LPAREN, &p)) {
-      return -1;
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_assign_expression(struct parse_context *ctx,
-                         struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-   unsigned int op;
-
-   if (_parse_unary_expression(ctx, &p)) {
-      return -1;
-   }
-
-   if (_parse_token(ctx, SL_PP_ASSIGN, &p) == 0) {
-      op = OP_ASSIGN;
-   } else if (_parse_token(ctx, SL_PP_MULASSIGN, &p) == 0) {
-      op = OP_MULASSIGN;
-   } else if (_parse_token(ctx, SL_PP_DIVASSIGN, &p) == 0) {
-      op = OP_DIVASSIGN;
-   } else if (_parse_token(ctx, SL_PP_ADDASSIGN, &p) == 0) {
-      op = OP_ADDASSIGN;
-   } else if (_parse_token(ctx, SL_PP_SUBASSIGN, &p) == 0) {
-      op = OP_SUBASSIGN;
-   } else {
-      return -1;
-   }
-
-   if (_parse_assignment_expression(ctx, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, op);
-
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_assignment_expression(struct parse_context *ctx,
-                             struct parse_state *ps)
-{
-   if (_parse_assign_expression(ctx, ps) == 0) {
-      return 0;
-   }
-
-   if (_parse_conditional_expression(ctx, ps) == 0) {
-      return 0;
-   }
-
-   return -1;
-}
-
-
-static int
-_parse_function_call_header_with_parameters(struct parse_context *ctx,
-                                            struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_function_call_header(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_assignment_expression(ctx, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, OP_END);
-   for (;;) {
-      *ps = p;
-      if (_parse_token(ctx, SL_PP_COMMA, &p)) {
-         return 0;
-      }
-      if (_parse_assignment_expression(ctx, &p)) {
-         return 0;
-      }
-      _emit(ctx, &p.out, OP_END);
-   }
-}
-
-
-static int
-_parse_function_call_header_no_parameters(struct parse_context *ctx,
-                                          struct parse_state *ps)
-{
-   if (_parse_function_call_header(ctx, ps)) {
-      return -1;
-   }
-   _parse_id(ctx, ctx->dict._void, ps);
-   return 0;
-}
-
-
-static int
-_parse_function_call_generic(struct parse_context *ctx,
-                             struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_function_call_header_with_parameters(ctx, &p) == 0) {
-      if (_parse_token(ctx, SL_PP_RPAREN, &p) == 0) {
-         *ps = p;
-         return 0;
-      }
-      _error(ctx, "expected `)'");
-      return -1;
-   }
-
-   p = *ps;
-   if (_parse_function_call_header_no_parameters(ctx, &p) == 0) {
-      if (_parse_token(ctx, SL_PP_RPAREN, &p) == 0) {
-         *ps = p;
-         return 0;
-      }
-      _error(ctx, "expected `)'");
-      return -1;
-   }
-
-   return -1;
-}
-
-
-static int
-_parse_method_call(struct parse_context *ctx,
-                   struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   _emit(ctx, &p.out, OP_METHOD);
-   if (_parse_identifier(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_DOT, &p)) {
-      return -1;
-   }
-   if (_parse_function_call_generic(ctx, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, OP_END);
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_regular_function_call(struct parse_context *ctx,
-                             struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   _emit(ctx, &p.out, OP_CALL);
-   if (_parse_function_call_generic(ctx, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, OP_END);
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_function_call(struct parse_context *ctx,
-                     struct parse_state *ps)
-{
-   if (_parse_regular_function_call(ctx, ps) == 0) {
-      return 0;
-   }
-
-   if (_parse_method_call(ctx, ps) == 0) {
-      return 0;
-   }
-
-   return -1;
-}
-
-
-static int
-_parse_expression(struct parse_context *ctx,
-                  struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_assignment_expression(ctx, &p)) {
-      return -1;
-   }
-
-   for (;;) {
-      *ps = p;
-      if (_parse_token(ctx, SL_PP_COMMA, &p)) {
-         return 0;
-      }
-      if (_parse_assignment_expression(ctx, &p)) {
-         return 0;
-      }
-      _emit(ctx, &p.out, OP_SEQUENCE);
-   }
-}
-
-
-static int
-_parse_postfix_expression(struct parse_context *ctx,
-                          struct parse_state *ps)
-{
-   struct parse_state p;
-
-   if (_parse_function_call(ctx, ps)) {
-      if (_parse_primary_expression(ctx, ps)) {
-         return -1;
-      }
-   }
-
-   for (p = *ps;;) {
-      *ps = p;
-      if (_parse_token(ctx, SL_PP_INCREMENT, &p) == 0) {
-         _emit(ctx, &p.out, OP_POSTINCREMENT);
-      } else if (_parse_token(ctx, SL_PP_DECREMENT, &p) == 0) {
-         _emit(ctx, &p.out, OP_POSTDECREMENT);
-      } else if (_parse_token(ctx, SL_PP_LBRACKET, &p) == 0) {
-         if (_parse_expression(ctx, &p)) {
-            _error(ctx, "expected an integral expression");
-            return -1;
-         }
-         if (_parse_token(ctx, SL_PP_RBRACKET, &p)) {
-            _error(ctx, "expected `]'");
-            return -1;
-         }
-         _emit(ctx, &p.out, OP_SUBSCRIPT);
-      } else if (_parse_token(ctx, SL_PP_DOT, &p) == 0) {
-         _emit(ctx, &p.out, OP_FIELD);
-         if (_parse_identifier(ctx, &p)) {
-            return 0;
-         }
-      } else {
-         return 0;
-      }
-   }
-}
-
-
-static int
-_parse_unary_expression(struct parse_context *ctx,
-                        struct parse_state *ps)
-{
-   struct parse_state p;
-   unsigned int op;
-
-   if (_parse_postfix_expression(ctx, ps) == 0) {
-      return 0;
-   }
-
-   p = *ps;
-   if (_parse_token(ctx, SL_PP_INCREMENT, &p) == 0) {
-      op = OP_PREINCREMENT;
-   } else if (_parse_token(ctx, SL_PP_DECREMENT, &p) == 0) {
-      op = OP_PREDECREMENT;
-   } else if (_parse_token(ctx, SL_PP_PLUS, &p) == 0) {
-      op = OP_PLUS;
-   } else if (_parse_token(ctx, SL_PP_MINUS, &p) == 0) {
-      op = OP_MINUS;
-   } else if (_parse_token(ctx, SL_PP_NOT, &p) == 0) {
-      op = OP_NOT;
-   } else {
-      return -1;
-   }
-
-   if (_parse_unary_expression(ctx, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, op);
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_multiplicative_expression(struct parse_context *ctx,
-                                 struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_unary_expression(ctx, &p)) {
-      return -1;
-   }
-   for (;;) {
-      unsigned int op;
-
-      *ps = p;
-      if (_parse_token(ctx, SL_PP_STAR, &p) == 0) {
-         op = OP_MULTIPLY;
-      } else if (_parse_token(ctx, SL_PP_SLASH, &p) == 0) {
-         op = OP_DIVIDE;
-      } else {
-         return 0;
-      }
-      if (_parse_unary_expression(ctx, &p)) {
-         return 0;
-      }
-      _emit(ctx, &p.out, op);
-   }
-}
-
-
-static int
-_parse_additive_expression(struct parse_context *ctx,
-                           struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_multiplicative_expression(ctx, &p)) {
-      return -1;
-   }
-   for (;;) {
-      unsigned int op;
-
-      *ps = p;
-      if (_parse_token(ctx, SL_PP_PLUS, &p) == 0) {
-         op = OP_ADD;
-      } else if (_parse_token(ctx, SL_PP_MINUS, &p) == 0) {
-         op = OP_SUBTRACT;
-      } else {
-         return 0;
-      }
-      if (_parse_multiplicative_expression(ctx, &p)) {
-         return 0;
-      }
-      _emit(ctx, &p.out, op);
-   }
-}
-
-
-static int
-_parse_relational_expression(struct parse_context *ctx,
-                             struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_additive_expression(ctx, &p)) {
-      return -1;
-   }
-   for (;;) {
-      unsigned int op;
-
-      *ps = p;
-      if (_parse_token(ctx, SL_PP_LESS, &p) == 0) {
-         op = OP_LESS;
-      } else if (_parse_token(ctx, SL_PP_GREATER, &p) == 0) {
-         op = OP_GREATER;
-      } else if (_parse_token(ctx, SL_PP_LESSEQUAL, &p) == 0) {
-         op = OP_LESSEQUAL;
-      } else if (_parse_token(ctx, SL_PP_GREATEREQUAL, &p) == 0) {
-         op = OP_GREATEREQUAL;
-      } else {
-         return 0;
-      }
-      if (_parse_additive_expression(ctx, &p)) {
-         return 0;
-      }
-      _emit(ctx, &p.out, op);
-   }
-}
-
-
-static int
-_parse_equality_expression(struct parse_context *ctx,
-                           struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_relational_expression(ctx, &p)) {
-      return -1;
-   }
-   for (;;) {
-      unsigned int op;
-
-      *ps = p;
-      if (_parse_token(ctx, SL_PP_EQUAL, &p) == 0) {
-         op = OP_EQUAL;
-      } else if (_parse_token(ctx, SL_PP_NOTEQUAL, &p) == 0) {
-         op = OP_NOTEQUAL;
-      } else {
-         return 0;
-      }
-      if (_parse_relational_expression(ctx, &p)) {
-         return -1;
-      }
-      _emit(ctx, &p.out, op);
-   }
-}
-
-
-static int
-_parse_logical_and_expression(struct parse_context *ctx,
-                              struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_equality_expression(ctx, &p)) {
-      return -1;
-   }
-   for (;;) {
-      *ps = p;
-      if (_parse_token(ctx, SL_PP_AND, &p)) {
-         return 0;
-      }
-      if (_parse_equality_expression(ctx, &p)) {
-         return 0;
-      }
-      _emit(ctx, &p.out, OP_LOGICALAND);
-   }
-}
-
-
-static int
-_parse_logical_xor_expression(struct parse_context *ctx,
-                              struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_logical_and_expression(ctx, &p)) {
-      return -1;
-   }
-   for (;;) {
-      *ps = p;
-      if (_parse_token(ctx, SL_PP_XOR, &p)) {
-         return 0;
-      }
-      if (_parse_logical_and_expression(ctx, &p)) {
-         return 0;
-      }
-      _emit(ctx, &p.out, OP_LOGICALXOR);
-   }
-}
-
-
-static int
-_parse_logical_or_expression(struct parse_context *ctx,
-                             struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_logical_xor_expression(ctx, &p)) {
-      return -1;
-   }
-   for (;;) {
-      *ps = p;
-      if (_parse_token(ctx, SL_PP_OR, &p)) {
-         return 0;
-      }
-      if (_parse_logical_xor_expression(ctx, &p)) {
-         return 0;
-      }
-      _emit(ctx, &p.out, OP_LOGICALOR);
-   }
-}
-
-
-static int
-_parse_conditional_expression(struct parse_context *ctx,
-                              struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_logical_or_expression(ctx, &p)) {
-      return -1;
-   }
-   for (;;) {
-      *ps = p;
-      if (_parse_token(ctx, SL_PP_QUESTION, &p)) {
-         return 0;
-      }
-      if (_parse_expression(ctx, &p)) {
-         return 0;
-      }
-      if (_parse_token(ctx, SL_PP_COLON, &p)) {
-         return 0;
-      }
-      if (_parse_conditional_expression(ctx, &p)) {
-         return 0;
-      }
-      _emit(ctx, &p.out, OP_SELECT);
-   }
-}
-
-
-static int
-_parse_constant_expression(struct parse_context *ctx,
-                           struct parse_state *ps)
-{
-   if (_parse_conditional_expression(ctx, ps)) {
-      return -1;
-   }
-   _emit(ctx, &ps->out, OP_END);
-   return 0;
-}
-
-
-static int
-_parse_parameter_declarator_array(struct parse_context *ctx,
-                                  struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_token(ctx, SL_PP_LBRACKET, &p)) {
-      return -1;
-   }
-   if (_parse_constant_expression(ctx, &p)) {
-      _error(ctx, "expected constant integral expression");
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_RBRACKET, &p)) {
-      _error(ctx, "expected `]'");
-      return -1;
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_parameter_declarator(struct parse_context *ctx,
-                            struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-   unsigned int e;
-
-   if (_parse_type_specifier(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_identifier(ctx, &p)) {
-      return -1;
-   }
-   e = _emit(ctx, &p.out, PARAMETER_ARRAY_PRESENT);
-   if (_parse_parameter_declarator_array(ctx, &p)) {
-      _update(ctx, e, PARAMETER_ARRAY_NOT_PRESENT);
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_parameter_type_specifier_array(struct parse_context *ctx,
-                                      struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_token(ctx, SL_PP_LBRACKET, &p)) {
-      return -1;
-   }
-   if (_parse_constant_expression(ctx, &p)) {
-      _error(ctx, "expected constant integral expression");
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_RBRACKET, &p)) {
-      _error(ctx, "expected `]'");
-      return -1;
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_parameter_type_specifier(struct parse_context *ctx,
-                                struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-   unsigned int e;
-
-   if (_parse_type_specifier(ctx, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, '\0');
-
-   e = _emit(ctx, &p.out, PARAMETER_ARRAY_PRESENT);
-   if (_parse_parameter_type_specifier_array(ctx, &p)) {
-      _update(ctx, e, PARAMETER_ARRAY_NOT_PRESENT);
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_parameter_declaration(struct parse_context *ctx,
-                             struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-   unsigned int e = _emit(ctx, &p.out, PARAMETER_NEXT);
-
-   (void) e;
-
-   if (_parse_storage_qualifier(ctx, &p)) {
-      _emit(ctx, &p.out, TYPE_QUALIFIER_NONE);
-   }
-   _parse_parameter_qualifier(ctx, &p);
-   if (_parse_precision(ctx, &p)) {
-      _emit(ctx, &p.out, PRECISION_DEFAULT);
-   }
-   if (_parse_parameter_declarator(ctx, &p) == 0) {
-      *ps = p;
-      return 0;
-   }
-   if (_parse_parameter_type_specifier(ctx, &p) == 0) {
-      *ps = p;
-      return 0;
-   }
-
-   return -1;
-}
-
-
-static int
-_parse_function_header_with_parameters(struct parse_context *ctx,
-                                       struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_function_header(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_parameter_declaration(ctx, &p)) {
-      return -1;
-   }
-
-   for (;;) {
-      *ps = p;
-      if (_parse_token(ctx, SL_PP_COMMA, &p)) {
-         return 0;
-      }
-      if (_parse_parameter_declaration(ctx, &p)) {
-         return 0;
-      }
-   }
-}
-
-
-static int
-_parse_function_declarator(struct parse_context *ctx,
-                           struct parse_state *ps)
-{
-   if (_parse_function_header_with_parameters(ctx, ps) == 0) {
-      return 0;
-   }
-
-   if (_parse_function_header(ctx, ps) == 0) {
-      return 0;
-   }
-
-   return -1;
-}
-
-
-static int
-_parse_function_prototype(struct parse_context *ctx,
-                          struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_function_header(ctx, &p) == 0) {
-      if (_parse_id(ctx, ctx->dict._void, &p) == 0) {
-         if (_parse_token(ctx, SL_PP_RPAREN, &p) == 0) {
-            _emit(ctx, &p.out, PARAMETER_NONE);
-            *ps = p;
-            return 0;
-         }
-         _error(ctx, "expected `)'");
-         return -1;
-      }
-   }
-
-   p = *ps;
-   if (_parse_function_declarator(ctx, &p) == 0) {
-      if (_parse_token(ctx, SL_PP_RPAREN, &p) == 0) {
-         _emit(ctx, &p.out, PARAMETER_NONE);
-         *ps = p;
-         return 0;
-      }
-      _error(ctx, "expected `)'");
-      return -1;
-   }
-
-   return -1;
-}
-
-
-static int
-_parse_precision(struct parse_context *ctx,
-                 struct parse_state *ps)
-{
-   const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
-   int id;
-   unsigned int precision;
-
-   if (!input || input->token != SL_PP_IDENTIFIER) {
-      return -1;
-   }
-   id = input->data.identifier;
-
-   if (id == ctx->dict.lowp) {
-      precision = PRECISION_LOW;
-   } else if (id == ctx->dict.mediump) {
-      precision = PRECISION_MEDIUM;
-   } else if (id == ctx->dict.highp) {
-      precision = PRECISION_HIGH;
-   } else {
-      return -1;
-   }
-
-   _parse_token(ctx, SL_PP_IDENTIFIER, ps);
-   _emit(ctx, &ps->out, precision);
-   return 0;
-}
-
-
-static int
-_parse_prectype(struct parse_context *ctx,
-                 struct parse_state *ps)
-{
-   const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
-   int id;
-   unsigned int type;
-
-   if (!input || input->token != SL_PP_IDENTIFIER) {
-      return -1;
-   }
-   id = input->data.identifier;
-
-   if (id == ctx->dict._int) {
-      type = TYPE_SPECIFIER_INT;
-   } else if (id == ctx->dict._float) {
-      type = TYPE_SPECIFIER_FLOAT;
-   } else if (id == ctx->dict.sampler1D) {
-      type = TYPE_SPECIFIER_SAMPLER1D;
-   } else if (id == ctx->dict.sampler2D) {
-      type = TYPE_SPECIFIER_SAMPLER2D;
-   } else if (id == ctx->dict.sampler3D) {
-      type = TYPE_SPECIFIER_SAMPLER3D;
-   } else if (id == ctx->dict.samplerCube) {
-      type = TYPE_SPECIFIER_SAMPLERCUBE;
-   } else if (id == ctx->dict.sampler1DShadow) {
-      type = TYPE_SPECIFIER_SAMPLER1DSHADOW;
-   } else if (id == ctx->dict.sampler2DShadow) {
-      type = TYPE_SPECIFIER_SAMPLER2DSHADOW;
-   } else if (id == ctx->dict.sampler2DRect) {
-      if (!ctx->texture_rectangle) {
-         _error(ctx, "GL_ARB_texture_rectangle extension must be enabled "
-                     "in order to use a rect sampler");
-         return -1;
-      }
-      type = TYPE_SPECIFIER_SAMPLER2DRECT;
-   } else if (id == ctx->dict.sampler2DRectShadow) {
-      if (!ctx->texture_rectangle) {
-         _error(ctx, "GL_ARB_texture_rectangle extension must be enabled "
-                     "in order to use a rect sampler");
-         return -1;
-      }
-      type = TYPE_SPECIFIER_SAMPLER2DRECTSHADOW;
-   } else if (id == ctx->dict.sampler1DArray) {
-      type = TYPE_SPECIFIER_SAMPLER_1D_ARRAY;
-   } else if (id == ctx->dict.sampler2DArray) {
-      type = TYPE_SPECIFIER_SAMPLER_2D_ARRAY;
-   } else if (id == ctx->dict.sampler1DArrayShadow) {
-      type = TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW;
-   } else if (id == ctx->dict.sampler2DArrayShadow) {
-      type = TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW;
-   } else {
-      return -1;
-   }
-
-   _parse_token(ctx, SL_PP_IDENTIFIER, ps);
-   _emit(ctx, &ps->out, type);
-   return 0;
-}
-
-
-static int
-_parse_precision_stmt(struct parse_context *ctx,
-                      struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_id(ctx, ctx->dict.precision, &p)) {
-      return -1;
-   }
-   if (_parse_precision(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_prectype(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
-      return -1;
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_floatconstant(struct parse_context *ctx,
-                     struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   _emit(ctx, &p.out, OP_PUSH_FLOAT);
-   if (_parse_float(ctx, &p)) {
-      return -1;
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_intconstant(struct parse_context *ctx,
-                   struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   _emit(ctx, &p.out, OP_PUSH_INT);
-   if (_parse_uint(ctx, &p)) {
-      return -1;
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_boolconstant(struct parse_context *ctx,
-                    struct parse_state *ps)
-{
-   if (_parse_id(ctx, ctx->dict._false, ps) == 0) {
-      _emit(ctx, &ps->out, OP_PUSH_BOOL);
-      _emit(ctx, &ps->out, 2);  /* radix */
-      _emit(ctx, &ps->out, '0');
-      _emit(ctx, &ps->out, '\0');
-      return 0;
-   }
-
-   if (_parse_id(ctx, ctx->dict._true, ps) == 0) {
-      _emit(ctx, &ps->out, OP_PUSH_BOOL);
-      _emit(ctx, &ps->out, 2);  /* radix */
-      _emit(ctx, &ps->out, '1');
-      _emit(ctx, &ps->out, '\0');
-      return 0;
-   }
-
-   return -1;
-}
-
-
-static int
-_parse_variable_identifier(struct parse_context *ctx,
-                           struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   _emit(ctx, &p.out, OP_PUSH_IDENTIFIER);
-   if (_parse_identifier(ctx, &p)) {
-      return -1;
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_primary_expression(struct parse_context *ctx,
-                          struct parse_state *ps)
-{
-   struct parse_state p;
-
-   if (_parse_floatconstant(ctx, ps) == 0) {
-      return 0;
-   }
-   if (_parse_boolconstant(ctx, ps) == 0) {
-      return 0;
-   }
-   if (_parse_intconstant(ctx, ps) == 0) {
-      return 0;
-   }
-   if (_parse_variable_identifier(ctx, ps) == 0) {
-      return 0;
-   }
-
-   p = *ps;
-   if (_parse_token(ctx, SL_PP_LPAREN, &p)) {
-      return -1;
-   }
-   if (_parse_expression(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_RPAREN, &p)) {
-      return -1;
-   }
-
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_asm_argument(struct parse_context *ctx,
-                    struct parse_state *ps)
-{
-   if (_parse_variable_identifier(ctx, ps) == 0) {
-      struct parse_state p = *ps;
-
-      if (_parse_token(ctx, SL_PP_DOT, &p)) {
-         return 0;
-      }
-      _emit(ctx, &p.out, OP_FIELD);
-      if (_parse_identifier(ctx, &p)) {
-         return 0;
-      }
-      *ps = p;
-      return 0;
-   }
-
-   if (_parse_floatconstant(ctx, ps) == 0) {
-      return 0;
-   }
-
-   return -1;
-}
-
-
-static int
-_parse_asm_arguments(struct parse_context *ctx,
-                     struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_asm_argument(ctx, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, OP_END);
-
-   for (;;) {
-      *ps = p;
-      if (_parse_token(ctx, SL_PP_COMMA, &p)) {
-         return 0;
-      }
-      if (_parse_asm_argument(ctx, &p)) {
-         return 0;
-      }
-      _emit(ctx, &p.out, OP_END);
-   }
-}
-
-
-static int
-_parse_asm_statement(struct parse_context *ctx,
-                     struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_id(ctx, ctx->dict.___asm, &p)) {
-      return -1;
-   }
-   if (_parse_identifier(ctx, &p)) {
-      return -1;
-   }
-   /* optional arguments */
-   _parse_asm_arguments(ctx, &p);
-   if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, OP_END);
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_selection_statement(struct parse_context *ctx,
-                           struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   _emit(ctx, &p.out, OP_IF);
-   if (_parse_id(ctx, ctx->dict._if, &p)) {
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_LPAREN, &p)) {
-      _error(ctx, "expected `('");
-      return -1;
-   }
-   if (_parse_expression(ctx, &p)) {
-      _error(ctx, "expected an expression");
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_RPAREN, &p)) {
-      _error(ctx, "expected `)'");
-      return -1;
-   }
-   _emit(ctx, &p.out, OP_END);
-   if (_parse_statement(ctx, &p)) {
-      return -1;
-   }
-
-   *ps = p;
-   if (_parse_id(ctx, ctx->dict._else, &p) == 0) {
-      if (_parse_statement(ctx, &p) == 0) {
-         *ps = p;
-         return 0;
-      }
-   }
-
-   _emit(ctx, &ps->out, OP_EXPRESSION);
-   _emit(ctx, &ps->out, OP_PUSH_VOID);
-   _emit(ctx, &ps->out, OP_END);
-   return 0;
-}
-
-
-static int
-_parse_expression_statement(struct parse_context *ctx,
-                            struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_expression(ctx, &p)) {
-      _emit(ctx, &p.out, OP_PUSH_VOID);
-   }
-   if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, OP_END);
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_for_init_statement(struct parse_context *ctx,
-                          struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-   unsigned int e = _emit(ctx, &p.out, OP_EXPRESSION);
-
-   if (_parse_expression_statement(ctx, &p) == 0) {
-      *ps = p;
-      return 0;
-   }
-
-   if (_parse_declaration(ctx, &p) == 0) {
-      _update(ctx, e, OP_DECLARE);
-      *ps = p;
-      return 0;
-   }
-
-   return -1;
-}
-
-
-static int
-_parse_initializer(struct parse_context *ctx,
-                   struct parse_state *ps)
-{
-   if (_parse_assignment_expression(ctx, ps) == 0) {
-      _emit(ctx, &ps->out, OP_END);
-      return 0;
-   }
-   return -1;
-}
-
-
-static int
-_parse_condition_initializer(struct parse_context *ctx,
-                             struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   _emit(ctx, &p.out, OP_DECLARE);
-   _emit(ctx, &p.out, DECLARATION_INIT_DECLARATOR_LIST);
-   if (_parse_fully_specified_type(ctx, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, VARIABLE_IDENTIFIER);
-   if (_parse_identifier(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_ASSIGN, &p)) {
-      _error(ctx, "expected `='");
-      return -1;
-   }
-   _emit(ctx, &p.out, VARIABLE_INITIALIZER);
-   if (_parse_initializer(ctx, &p)) {
-      _error(ctx, "expected an initialiser");
-      return -1;
-   }
-   _emit(ctx, &p.out, DECLARATOR_NONE);
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_condition(struct parse_context *ctx,
-                 struct parse_state *ps)
-{
-   struct parse_state p;
-
-   if (_parse_condition_initializer(ctx, ps) == 0) {
-      return 0;
-   }
-
-   p = *ps;
-   _emit(ctx, &p.out, OP_EXPRESSION);
-   if (_parse_expression(ctx, &p) == 0) {
-      _emit(ctx, &p.out, OP_END);
-      *ps = p;
-      return 0;
-   }
-
-   return -1;
-}
-
-
-static int
-_parse_for_rest_statement(struct parse_context *ctx,
-                          struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_condition(ctx, &p)) {
-      _emit(ctx, &p.out, OP_EXPRESSION);
-      _emit(ctx, &p.out, OP_PUSH_BOOL);
-      _emit(ctx, &p.out, 2);
-      _emit(ctx, &p.out, '1');
-      _emit(ctx, &p.out, '\0');
-      _emit(ctx, &p.out, OP_END);
-   }
-   if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
-      return -1;
-   }
-   if (_parse_expression(ctx, &p)) {
-      _emit(ctx, &p.out, OP_PUSH_VOID);
-   }
-   _emit(ctx, &p.out, OP_END);
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_iteration_statement(struct parse_context *ctx,
-                           struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_id(ctx, ctx->dict._while, &p) == 0) {
-      _emit(ctx, &p.out, OP_WHILE);
-      if (_parse_token(ctx, SL_PP_LPAREN, &p)) {
-         _error(ctx, "expected `('");
-         return -1;
-      }
-      if (_parse_condition(ctx, &p)) {
-         _error(ctx, "expected an expression");
-         return -1;
-      }
-      if (_parse_token(ctx, SL_PP_RPAREN, &p)) {
-         _error(ctx, "expected `)'");
-         return -1;
-      }
-      if (_parse_statement(ctx, &p)) {
-         return -1;
-      }
-      *ps = p;
-      return 0;
-   }
-
-   if (_parse_id(ctx, ctx->dict._do, &p) == 0) {
-      _emit(ctx, &p.out, OP_DO);
-      if (_parse_statement(ctx, &p)) {
-         return -1;
-      }
-      if (_parse_id(ctx, ctx->dict._while, &p)) {
-         return -1;
-      }
-      if (_parse_token(ctx, SL_PP_LPAREN, &p)) {
-         _error(ctx, "expected `('");
-         return -1;
-      }
-      if (_parse_expression(ctx, &p)) {
-         _error(ctx, "expected an expression");
-         return -1;
-      }
-      if (_parse_token(ctx, SL_PP_RPAREN, &p)) {
-         _error(ctx, "expected `)'");
-         return -1;
-      }
-      _emit(ctx, &p.out, OP_END);
-      if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
-         _error(ctx, "expected `;'");
-         return -1;
-      }
-      *ps = p;
-      return 0;
-   }
-
-   if (_parse_id(ctx, ctx->dict._for, &p) == 0) {
-      _emit(ctx, &p.out, OP_FOR);
-      if (_parse_token(ctx, SL_PP_LPAREN, &p)) {
-         _error(ctx, "expected `('");
-         return -1;
-      }
-      if (_parse_for_init_statement(ctx, &p)) {
-         return -1;
-      }
-      if (_parse_for_rest_statement(ctx, &p)) {
-         return -1;
-      }
-      if (_parse_token(ctx, SL_PP_RPAREN, &p)) {
-         _error(ctx, "expected `)'");
-         return -1;
-      }
-      if (_parse_statement(ctx, &p)) {
-         return -1;
-      }
-      *ps = p;
-      return 0;
-   }
-
-   return -1;
-}
-
-
-static int
-_parse_jump_statement(struct parse_context *ctx,
-                      struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-   unsigned int e = _emit(ctx, &p.out, 0);
-
-   if (_parse_id(ctx, ctx->dict._continue, &p) == 0) {
-      _update(ctx, e, OP_CONTINUE);
-   } else if (_parse_id(ctx, ctx->dict._break, &p) == 0) {
-      _update(ctx, e, OP_BREAK);
-   } else if (_parse_id(ctx, ctx->dict._return, &p) == 0) {
-      _update(ctx, e, OP_RETURN);
-      if (_parse_expression(ctx, &p)) {
-         _emit(ctx, &p.out, OP_PUSH_VOID);
-      }
-      _emit(ctx, &p.out, OP_END);
-   } else if (ctx->shader_type == 1 && _parse_id(ctx, ctx->dict.discard, &p) == 0) {
-      _update(ctx, e, OP_DISCARD);
-   } else {
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
-      return -1;
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_simple_statement(struct parse_context *ctx,
-                        struct parse_state *ps)
-{
-   struct parse_state p;
-   unsigned int e;
-
-   if (_parse_selection_statement(ctx, ps) == 0) {
-      return 0;
-   }
-
-   if (_parse_iteration_statement(ctx, ps) == 0) {
-      return 0;
-   }
-
-   if (_parse_jump_statement(ctx, ps) == 0) {
-      return 0;
-   }
-
-   p = *ps;
-   e = _emit(ctx, &p.out, OP_EXPRESSION);
-   if (_parse_expression_statement(ctx, &p) == 0) {
-      *ps = p;
-      return 0;
-   }
-
-   if (_parse_precision_stmt(ctx, &p) == 0) {
-      _update(ctx, e, OP_PRECISION);
-      *ps = p;
-      return 0;
-   }
-
-   if (ctx->parsing_builtin && _parse_asm_statement(ctx, &p) == 0) {
-      _update(ctx, e, OP_ASM);
-      *ps = p;
-      return 0;
-   }
-
-   if (_parse_declaration(ctx, &p) == 0) {
-      _update(ctx, e, OP_DECLARE);
-      *ps = p;
-      return 0;
-   }
-
-   return -1;
-}
-
-
-static int
-_parse_compound_statement(struct parse_context *ctx,
-                          struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_token(ctx, SL_PP_LBRACE, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, OP_BLOCK_BEGIN_NEW_SCOPE);
-   _parse_statement_list(ctx, &p);
-   if (_parse_token(ctx, SL_PP_RBRACE, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, OP_END);
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_statement(struct parse_context *ctx,
-                 struct parse_state *ps)
-{
-   if (_parse_compound_statement(ctx, ps) == 0) {
-      return 0;
-   }
-
-   if (_parse_simple_statement(ctx, ps) == 0) {
-      return 0;
-   }
-
-   return -1;
-}
-
-
-static int
-_parse_statement_list(struct parse_context *ctx,
-                      struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_statement(ctx, &p)) {
-      return -1;
-   }
-
-   for (;;) {
-      *ps = p;
-      if (_parse_statement(ctx, &p)) {
-         return 0;
-      }
-   }
-}
-
-
-static int
-_parse_compound_statement_no_new_scope(struct parse_context *ctx,
-                                       struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_token(ctx, SL_PP_LBRACE, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, OP_BLOCK_BEGIN_NO_NEW_SCOPE);
-   _parse_statement_list(ctx, &p);
-   if (_parse_token(ctx, SL_PP_RBRACE, &p)) {
-      return -1;
-   }
-   _emit(ctx, &p.out, OP_END);
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_function_definition(struct parse_context *ctx,
-                           struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_function_prototype(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_compound_statement_no_new_scope(ctx, &p)) {
-      return -1;
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_invariant_stmt(struct parse_context *ctx,
-                      struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_id(ctx, ctx->dict.invariant, &p)) {
-      return -1;
-   }
-   if (_parse_identifier(ctx, &p)) {
-      return -1;
-   }
-   if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
-      return -1;
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_single_declaration(struct parse_context *ctx,
-                          struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-   unsigned int e;
-
-   if (_parse_fully_specified_type(ctx, &p)) {
-      return -1;
-   }
-
-   e = _emit(ctx, &p.out, VARIABLE_IDENTIFIER);
-   if (_parse_identifier(ctx, &p)) {
-      _update(ctx, e, VARIABLE_NONE);
-      *ps = p;
-      return 0;
-   }
-
-   e = _emit(ctx, &p.out, VARIABLE_NONE);
-   *ps = p;
-
-   if (_parse_token(ctx, SL_PP_ASSIGN, &p) == 0) {
-      _update(ctx, e, VARIABLE_INITIALIZER);
-      if (_parse_initializer(ctx, &p) == 0) {
-         *ps = p;
-         return 0;
-      }
-      _error(ctx, "expected an initialiser");
-      return -1;
-   }
-   p = *ps;
-
-   if (_parse_token(ctx, SL_PP_LBRACKET, &p) == 0) {
-      if (_parse_constant_expression(ctx, &p)) {
-         _update(ctx, e, VARIABLE_ARRAY_UNKNOWN);
-      } else {
-         _update(ctx, e, VARIABLE_ARRAY_EXPLICIT);
-      }
-      if (_parse_token(ctx, SL_PP_RBRACKET, &p) == 0) {
-         *ps = p;
-         return 0;
-      }
-      _error(ctx, "expected `]'");
-      return -1;
-   }
-   return 0;
-}
-
-
-static int
-_parse_init_declarator_list(struct parse_context *ctx,
-                            struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-
-   if (_parse_single_declaration(ctx, &p)) {
-      return -1;
-   }
-
-   for (;;) {
-      unsigned int e;
-
-      *ps = p;
-      if (_parse_token(ctx, SL_PP_COMMA, &p)) {
-         break;
-      }
-      _emit(ctx, &p.out, DECLARATOR_NEXT);
-      _emit(ctx, &p.out, VARIABLE_IDENTIFIER);
-      if (_parse_identifier(ctx, &p)) {
-         break;
-      }
-
-      e = _emit(ctx, &p.out, VARIABLE_NONE);
-      *ps = p;
-
-      if (_parse_token(ctx, SL_PP_ASSIGN, &p) == 0) {
-         if (_parse_initializer(ctx, &p) == 0) {
-            _update(ctx, e, VARIABLE_INITIALIZER);
-            *ps = p;
-            continue;
-         }
-         _error(ctx, "expected an initialiser");
-         break;
-      }
-      p = *ps;
-
-      if (_parse_token(ctx, SL_PP_LBRACKET, &p) == 0) {
-         unsigned int arr;
-
-         if (_parse_constant_expression(ctx, &p)) {
-            arr = VARIABLE_ARRAY_UNKNOWN;
-         } else {
-            arr = VARIABLE_ARRAY_EXPLICIT;
-         }
-         if (_parse_token(ctx, SL_PP_RBRACKET, &p) == 0) {
-            _update(ctx, e, arr);
-            *ps = p;
-            continue;
-         }
-         _error(ctx, "expected `]'");
-         break;
-      }
-      p = *ps;
-   }
-
-   _emit(ctx, &ps->out, DECLARATOR_NONE);
-   return 0;
-}
-
-
-static int
-_parse_declaration(struct parse_context *ctx,
-                   struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-   unsigned int e = _emit(ctx, &p.out, DECLARATION_FUNCTION_PROTOTYPE);
-
-   if (_parse_function_prototype(ctx, &p)) {
-      if (_parse_init_declarator_list(ctx, &p)) {
-         return -1;
-      }
-      _update(ctx, e, DECLARATION_INIT_DECLARATOR_LIST);
-   }
-   if (_parse_token(ctx, SL_PP_SEMICOLON, &p)) {
-      _error(ctx, "expected `;'");
-      return -1;
-   }
-   *ps = p;
-   return 0;
-}
-
-
-static int
-_parse_external_declaration(struct parse_context *ctx,
-                            struct parse_state *ps)
-{
-   struct parse_state p = *ps;
-   unsigned int e = _emit(ctx, &p.out, 0);
-
-   if (_parse_precision_stmt(ctx, &p) == 0) {
-      _update(ctx, e, DEFAULT_PRECISION);
-      *ps = p;
-      return 0;
-   }
-
-   if (_parse_function_definition(ctx, &p) == 0) {
-      _update(ctx, e, EXTERNAL_FUNCTION_DEFINITION);
-      *ps = p;
-      return 0;
-   }
-
-   if (_parse_invariant_stmt(ctx, &p) == 0) {
-      _update(ctx, e, INVARIANT_STMT);
-      *ps = p;
-      return 0;
-   }
-
-   if (_parse_declaration(ctx, &p) == 0) {
-      _update(ctx, e, EXTERNAL_DECLARATION);
-      *ps = p;
-      return 0;
-   }
-
-   _error(ctx, "expected an identifier");
-   return -1;
-}
-
-
-static int
-_parse_extensions(struct parse_context *ctx,
-                  struct parse_state *ps)
-{
-   for (;;) {
-      const struct sl_pp_token_info *input = _fetch_token(ctx, ps->in);
-      unsigned int enable;
-
-      if (!input) {
-         return -1;
-      }
-
-      switch (input->token) {
-      case SL_PP_EXTENSION_REQUIRE:
-      case SL_PP_EXTENSION_ENABLE:
-      case SL_PP_EXTENSION_WARN:
-         enable = 1;
-         break;
-      case SL_PP_EXTENSION_DISABLE:
-         enable = 0;
-         break;
-      default:
-         return 0;
-      }
-
-      ps->in++;
-      if (input->data.extension == ctx->dict.all) {
-         ctx->fragment_coord_conventions = enable;
-      }
-      else if (input->data.extension == ctx->dict._GL_ARB_fragment_coord_conventions) {
-         ctx->fragment_coord_conventions = enable;
-      }
-      else if (input->data.extension == ctx->dict._GL_ARB_texture_rectangle) {
-         ctx->texture_rectangle = enable;
-      }
-   }
-}
-
-
-static int
-_parse_translation_unit(struct parse_context *ctx,
-                        struct parse_state *ps)
-{
-   _emit(ctx, &ps->out, REVISION);
-   if (_parse_extensions(ctx, ps)) {
-      return -1;
-   }
-   if (_parse_external_declaration(ctx, ps)) {
-      return -1;
-   }
-   for (;;) {
-      if (_parse_extensions(ctx, ps)) {
-         return -1;
-      }
-      if (_parse_external_declaration(ctx, ps)) {
-         break;
-      }
-   }
-   _emit(ctx, &ps->out, EXTERNAL_NULL);
-   if (_parse_token(ctx, SL_PP_EOF, ps)) {
-      return -1;
-   }
-   return 0;
-}
-
-
-#define ADD_NAME_STR(CTX, NAME, STR)\
-   do {\
-      (CTX).dict.NAME = sl_pp_context_add_unique_str((CTX).context, (STR));\
-      if ((CTX).dict.NAME == -1) {\
-         return -1;\
-      }\
-   } while (0)
-
-#define ADD_NAME(CTX, NAME) ADD_NAME_STR(CTX, NAME, #NAME)
-
-
-int
-sl_cl_compile(struct sl_pp_context *context,
-              unsigned int shader_type,
-              unsigned int parsing_builtin,
-              unsigned char **output,
-              unsigned int *cboutput,
-              char *error,
-              unsigned int cberror)
-{
-   struct parse_context ctx;
-   struct parse_state ps;
-
-   ctx.context = context;
-
-   ADD_NAME_STR(ctx, _void, "void");
-   ADD_NAME_STR(ctx, _float, "float");
-   ADD_NAME_STR(ctx, _int, "int");
-   ADD_NAME_STR(ctx, _bool, "bool");
-   ADD_NAME(ctx, vec2);
-   ADD_NAME(ctx, vec3);
-   ADD_NAME(ctx, vec4);
-   ADD_NAME(ctx, bvec2);
-   ADD_NAME(ctx, bvec3);
-   ADD_NAME(ctx, bvec4);
-   ADD_NAME(ctx, ivec2);
-   ADD_NAME(ctx, ivec3);
-   ADD_NAME(ctx, ivec4);
-   ADD_NAME(ctx, mat2);
-   ADD_NAME(ctx, mat3);
-   ADD_NAME(ctx, mat4);
-   ADD_NAME(ctx, mat2x3);
-   ADD_NAME(ctx, mat3x2);
-   ADD_NAME(ctx, mat2x4);
-   ADD_NAME(ctx, mat4x2);
-   ADD_NAME(ctx, mat3x4);
-   ADD_NAME(ctx, mat4x3);
-   ADD_NAME(ctx, sampler1D);
-   ADD_NAME(ctx, sampler2D);
-   ADD_NAME(ctx, sampler3D);
-   ADD_NAME(ctx, samplerCube);
-   ADD_NAME(ctx, sampler1DShadow);
-   ADD_NAME(ctx, sampler2DShadow);
-   ADD_NAME(ctx, sampler2DRect);
-   ADD_NAME(ctx, sampler2DRectShadow);
-   ADD_NAME(ctx, sampler1DArray);
-   ADD_NAME(ctx, sampler2DArray);
-   ADD_NAME(ctx, sampler1DArrayShadow);
-   ADD_NAME(ctx, sampler2DArrayShadow);
-
-   ADD_NAME(ctx, invariant);
-
-   ADD_NAME(ctx, centroid);
-
-   ADD_NAME(ctx, precision);
-   ADD_NAME(ctx, lowp);
-   ADD_NAME(ctx, mediump);
-   ADD_NAME(ctx, highp);
-
-   ADD_NAME_STR(ctx, _const, "const");
-   ADD_NAME(ctx, attribute);
-   ADD_NAME(ctx, varying);
-   ADD_NAME(ctx, uniform);
-   ADD_NAME(ctx, __fixed_output);
-   ADD_NAME(ctx, __fixed_input);
-
-   ADD_NAME(ctx, in);
-   ADD_NAME(ctx, out);
-   ADD_NAME(ctx, inout);
-
-   ADD_NAME(ctx, layout);
-   ADD_NAME(ctx, origin_upper_left);
-   ADD_NAME(ctx, pixel_center_integer);
-
-   ADD_NAME_STR(ctx, _struct, "struct");
-
-   ADD_NAME(ctx, __constructor);
-   ADD_NAME(ctx, __operator);
-   ADD_NAME_STR(ctx, ___asm, "__asm");
-
-   ADD_NAME_STR(ctx, _if, "if");
-   ADD_NAME_STR(ctx, _else, "else");
-   ADD_NAME_STR(ctx, _for, "for");
-   ADD_NAME_STR(ctx, _while, "while");
-   ADD_NAME_STR(ctx, _do, "do");
-
-   ADD_NAME_STR(ctx, _continue, "continue");
-   ADD_NAME_STR(ctx, _break, "break");
-   ADD_NAME_STR(ctx, _return, "return");
-   ADD_NAME(ctx, discard);
-
-   ADD_NAME_STR(ctx, _false, "false");
-   ADD_NAME_STR(ctx, _true, "true");
-
-   ADD_NAME(ctx, all);
-   ADD_NAME_STR(ctx, _GL_ARB_fragment_coord_conventions, "GL_ARB_fragment_coord_conventions");
-   ADD_NAME_STR(ctx, _GL_ARB_texture_rectangle, "GL_ARB_texture_rectangle");
-
-   ctx.out_buf = NULL;
-   ctx.out_cap = 0;
-
-   ctx.shader_type = shader_type;
-   ctx.parsing_builtin = 1;
-
-   ctx.fragment_coord_conventions = 0;
-   ctx.texture_rectangle = 1;
-
-   ctx.error[0] = '\0';
-   ctx.process_error = 0;
-
-   ctx.tokens_cap = 1024;
-   ctx.tokens_read = 0;
-   ctx.tokens = malloc(ctx.tokens_cap * sizeof(struct sl_pp_token_info));
-   if (!ctx.tokens) {
-      strncpy(error, "out of memory", cberror - 1);
-      error[cberror - 1] = '\0';
-      return -1;
-   }
-
-   ps.in = 0;
-   ps.out = 0;
-
-   if (_parse_translation_unit(&ctx, &ps)) {
-      strncpy(error, ctx.error, cberror);
-      free(ctx.tokens);
-      return -1;
-   }
-
-   *output = ctx.out_buf;
-   *cboutput = ps.out;
-   free(ctx.tokens);
-   return 0;
-}
diff --git a/src/glsl/cl/sl_cl_parse.h b/src/glsl/cl/sl_cl_parse.h
deleted file mode 100644 (file)
index a954d43..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#ifndef SL_CL_PARSE_H
-#define SL_CL_PARSE_H
-
-struct sl_pp_context;
-
-int
-sl_cl_compile(struct sl_pp_context *context,
-              unsigned int shader_type,
-              unsigned int parsing_builtin,
-              unsigned char **output,
-              unsigned int *cboutput,
-              char *error,
-              unsigned int cberror);
-
-#endif /* SL_CL_PARSE_H */
diff --git a/src/glsl/configure.ac b/src/glsl/configure.ac
new file mode 100644 (file)
index 0000000..73ce67d
--- /dev/null
@@ -0,0 +1,69 @@
+#                                               -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.61)
+AC_INIT(glsl, XXXXX, idr@freedesktop.org, glsl)
+AC_CONFIG_SRCDIR([Makefile.am])
+AM_CONFIG_HEADER([config.h])
+AC_CONFIG_FILES([glcpp/Makefile])
+
+AM_INIT_AUTOMAKE
+LT_INIT
+
+AM_MAINTAINER_MODE
+
+# Checks for programs.
+AC_PROG_CXX
+AC_PROG_CC
+AC_PROG_MAKE_SET
+AC_PROG_YACC
+AC_PROG_LEX
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+# Checks for libraries.
+
+# Checks for header files.
+
+# Checks for typedefs, structures, and compiler characteristics.
+
+# Checks for library functions.
+AC_HEADER_STDC
+
+AH_TOP([#ifndef GLSL_CONFIG_H
+#define GLSL_CONFIG_H])
+AH_BOTTOM([#endif /* GLSL_CONFIG_H */])
+
+PKG_CHECK_MODULES([talloc], [talloc >= 2.0])
+
+AC_ARG_ENABLE([debug],
+    [AS_HELP_STRING([--enable-debug],
+        [use debug compiler flags and macros @<:@default=disabled@:>@])],
+    [enable_debug="$enableval"],
+    [enable_debug=no]
+)
+if test "x$enable_debug" = xyes; then
+    DEFINES="$DEFINES -DDEBUG"
+    if test "x$GCC" = xyes; then
+       # Remove any -g or -O flags from the command line
+       CFLAGS=[`echo $CFLAGS | sed 's/-g[^ \t]*[ \t]*//g;s/-O[^ \t]*[ \t]*//g'`]
+        CFLAGS="$CFLAGS -O0 -ggdb3 -fstack-protector -D_FORTIFY_SOURCE=2"
+    fi
+    if test "x$GXX" = xyes; then
+       # Remove any -g flags from the command line
+       CXXFLAGS=[`echo $CXXFLAGS | sed 's/-g[^ \t]*[ \t]*//g;s/-O[^ \t]*[ \t]*//g'`]
+        CXXFLAGS="$CXXFLAGS -O0 -ggdb3 -fstack-protector -D_FORTIFY_SOURCE=2"
+    fi
+fi
+
+if test "x$GXX" = xyes ; then
+       WARN="-Wall -Wextra -Wunsafe-loop-optimizations -Wstack-protector"
+else
+       WARN=""
+fi
+
+CFLAGS="$CFLAGS $WARN"
+CXXFLAGS="$CXXFLAGS $WARN"
+YFLAGS="-d -v"
+
+AC_OUTPUT([Makefile])
diff --git a/src/glsl/glcpp/.gitignore b/src/glsl/glcpp/.gitignore
new file mode 100644 (file)
index 0000000..dbc37e1
--- /dev/null
@@ -0,0 +1,8 @@
+glcpp
+glcpp-parse.output
+*.o
+*.lo
+*.la
+.libs
+*~
+tests/*.out
diff --git a/src/glsl/glcpp/Makefile.am b/src/glsl/glcpp/Makefile.am
new file mode 100644 (file)
index 0000000..81147e6
--- /dev/null
@@ -0,0 +1,44 @@
+# Copyright Â© 2010 Intel Corporation
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+# AUTHORS, COPYRIGHT HOLDERS, 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.
+
+noinst_LTLIBRARIES = libglcpp.la
+libglcpp_la_SOURCES = \
+       glcpp-lex.l \
+       glcpp-parse.y \
+       glcpp.h \
+       pp.c
+
+BUILT_SOURCES = glcpp-parse.h glcpp-parse.c glcpp-lex.c
+CLEANFILES = $(BUILT_SOURCES)
+
+glcpp-parse.h: glcpp-parse.c
+
+bin_PROGRAMS = glcpp
+glcpp_LDADD = libglcpp.la
+glcpp_LDFLAGS = @LDFLAGS@ $(talloc_LIBS)
+glcpp_SOURCES = glcpp.c
+
+.l.c:
+       $(LEXCOMPILE) --outfile="$@" $<
+
+test: glcpp
+       @(cd tests; ./glcpp-test)
diff --git a/src/glsl/glcpp/README b/src/glsl/glcpp/README
new file mode 100644 (file)
index 0000000..0b5ef50
--- /dev/null
@@ -0,0 +1,32 @@
+glcpp -- GLSL "C" preprocessor
+
+This is a simple preprocessor designed to provide the preprocessing
+needs of the GLSL language. The requirements for this preprocessor are
+specified in the GLSL 1.30 specification availble from:
+
+http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.30.10.pdf
+
+This specification is not precise on some semantics, (for example,
+#define and #if), defining these merely "as is standard for C++
+preprocessors". To fill in these details, I've been using a draft of
+the C99 standard as available from:
+
+http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
+
+Any downstream compiler accepting output from glcpp should be prepared
+to encounter and deal with the following preprocessor macros:
+
+       #line
+       #pragma
+       #extension
+
+All other macros will be handles according to the GLSL specification
+and will not appear in the output.
+
+Known limitations
+-----------------
+The __LINE__ and __FILE__ macros are not yet supported.
+
+A file that ends with a function-like macro name as the last
+non-whitespace token will result in a parse error, (where it should be
+passed through as is).
\ No newline at end of file
diff --git a/src/glsl/glcpp/glcpp-lex.c b/src/glsl/glcpp/glcpp-lex.c
new file mode 100644 (file)
index 0000000..0f99ea1
--- /dev/null
@@ -0,0 +1,2691 @@
+#line 2 "glcpp/glcpp-lex.c"
+
+#line 4 "glcpp/glcpp-lex.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else  /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE glcpp_restart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    #define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+               *yy_cp = yyg->yy_hold_char; \
+               YY_RESTORE_YY_MORE_OFFSET \
+               yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+               YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+               } \
+       while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+       {
+       FILE *yy_input_file;
+
+       char *yy_ch_buf;                /* input buffer */
+       char *yy_buf_pos;               /* current position in input buffer */
+
+       /* Size of input buffer in bytes, not including room for EOB
+        * characters.
+        */
+       yy_size_t yy_buf_size;
+
+       /* Number of characters read into yy_ch_buf, not including EOB
+        * characters.
+        */
+       int yy_n_chars;
+
+       /* Whether we "own" the buffer - i.e., we know we created it,
+        * and can realloc() it to grow it, and should free() it to
+        * delete it.
+        */
+       int yy_is_our_buffer;
+
+       /* Whether this is an "interactive" input source; if so, and
+        * if we're using stdio for input, then we want to use getc()
+        * instead of fread(), to make sure we stop fetching input after
+        * each newline.
+        */
+       int yy_is_interactive;
+
+       /* Whether we're considered to be at the beginning of a line.
+        * If so, '^' rules will be active on the next match, otherwise
+        * not.
+        */
+       int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+       /* Whether to try to fill the input buffer when we reach the
+        * end of it.
+        */
+       int yy_fill_buffer;
+
+       int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+       /* When an EOF's been seen but there's still some text to process
+        * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+        * shouldn't try reading from the input source any more.  We might
+        * still have a bunch of tokens to match, though, because of
+        * possible backing-up.
+        *
+        * When we actually see the EOF, we change the status to "new"
+        * (via glcpp_restart()), so that the user can continue scanning by
+        * just pointing yyin at a new input file.
+        */
+#define YY_BUFFER_EOF_PENDING 2
+
+       };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void glcpp_restart (FILE *input_file ,yyscan_t yyscanner );
+void glcpp__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE glcpp__create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void glcpp__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void glcpp__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void glcpp_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void glcpp_pop_buffer_state (yyscan_t yyscanner );
+
+static void glcpp_ensure_buffer_stack (yyscan_t yyscanner );
+static void glcpp__load_buffer_state (yyscan_t yyscanner );
+static void glcpp__init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER glcpp__flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE glcpp__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE glcpp__scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE glcpp__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *glcpp_alloc (yy_size_t ,yyscan_t yyscanner );
+void *glcpp_realloc (void *,yy_size_t ,yyscan_t yyscanner );
+void glcpp_free (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer glcpp__create_buffer
+
+#define yy_set_interactive(is_interactive) \
+       { \
+       if ( ! YY_CURRENT_BUFFER ){ \
+        glcpp_ensure_buffer_stack (yyscanner); \
+               YY_CURRENT_BUFFER_LVALUE =    \
+            glcpp__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+       } \
+       YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+       }
+
+#define yy_set_bol(at_bol) \
+       { \
+       if ( ! YY_CURRENT_BUFFER ){\
+        glcpp_ensure_buffer_stack (yyscanner); \
+               YY_CURRENT_BUFFER_LVALUE =    \
+            glcpp__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+       } \
+       YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+       }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define glcpp_wrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+       yyg->yytext_ptr = yy_bp; \
+       yyleng = (size_t) (yy_cp - yy_bp); \
+       yyg->yy_hold_char = *yy_cp; \
+       *yy_cp = '\0'; \
+       yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 43
+#define YY_END_OF_BUFFER 44
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+       {
+       flex_int32_t yy_verify;
+       flex_int32_t yy_nxt;
+       };
+static yyconst flex_int16_t yy_acclist[137] =
+    {   0,
+        3,    3,   44,   39,   43,   40,   43,   41,   43,   43,
+       38,   43,   43,   38,   43,   38,   43,   38,   43,   25,
+       39,   43,   24,   39,   43,   38,   43,   38,   43,   38,
+       43,   37,   39,   43,   37,   39,   43,   38,   43,   40,
+       43,   23,   43,   43,    3,   43,    4,   43,    5,   43,
+       42,   43,   39,   18,   40,   32,   35,   33,    2,    1,
+       25,   39,   25,   39,   39,   24,   39,   24,   39,   27,
+       29,   31,   30,   28,   37,   39,   37,   39,   34,   40,
+       23,   23,    3,    4,    5,    6,    5,    7,    1,   26,
+       39,   37,   39,16398,   26,   39,   37,   39,   18,   37,
+
+       39,16399,16400, 8206,   18, 8206,   37,   39, 8207,   18,
+     8208,   18,16401,   19,16396,   22,   36,   37,   39,   21,
+     8209,   18,   19, 8204,   18,16397,16404, 8205,   18,   11,
+       18,    9,    8, 8212,   10,   18
+    } ;
+
+static yyconst flex_int16_t yy_accept[164] =
+    {   0,
+        1,    1,    1,    1,    1,    2,    3,    3,    3,    4,
+        6,    8,   10,   11,   13,   14,   16,   18,   20,   23,
+       26,   28,   30,   32,   35,   38,   40,   42,   44,   45,
+       47,   49,   51,   53,   54,   54,   55,   56,   57,   58,
+       59,   60,   61,   63,   65,   66,   68,   70,   71,   72,
+       73,   74,   75,   77,   79,   80,   81,   82,   83,   83,
+       83,   83,   83,   83,   83,   83,   84,   85,   86,   87,
+       88,   89,   90,   92,   94,   94,   94,   94,   94,   94,
+       95,   95,   95,   95,   95,   97,   99,   99,   99,   99,
+       99,   99,   99,   99,  100,  100,  100,  100,  100,  100,
+
+      100,  102,  102,  103,  104,  104,  104,  104,  104,  106,
+      106,  107,  107,  107,  107,  107,  107,  107,  109,  109,
+      109,  111,  111,  113,  114,  115,  115,  116,  116,  116,
+      116,  117,  117,  120,  121,  121,  123,  124,  124,  124,
+      126,  127,  127,  127,  127,  128,  128,  128,  130,  130,
+      132,  132,  133,  134,  134,  134,  134,  135,  135,  135,
+      137,  137,  137
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        4,    4,    4,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    5,    1,    6,    1,    7,    8,    1,    9,
+        7,   10,    7,    7,    7,    7,   11,   12,   13,   13,
+       13,   13,   13,   13,   13,   14,   14,    1,    7,   15,
+       16,   17,    1,    1,   18,   18,   18,   18,   18,   18,
+       19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
+       19,   19,   19,   19,   20,   19,   19,   21,   19,   19,
+        7,    1,    7,    7,   19,    1,   22,   18,   18,   23,
+
+       24,   25,   26,   19,   27,   19,   19,   28,   29,   30,
+       31,   32,   19,   33,   34,   35,   36,   37,   19,   38,
+       19,   19,    7,   39,    7,    7,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[40] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    2,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[182] =
+    {   0,
+        0,   38,    0,    0,   38,   39,  499,  498,  500,   48,
+       43,  552,  496,   44,   63,  495,   59,   65,   87,  125,
+       58,   67,   68,  164,  203,   40,   75,  241,  552,  494,
+      552,  140,  552,  140,  493,  552,  144,  492,  491,  487,
+      486,  485,  156,  179,  267,    0,  209,  472,  471,  470,
+      469,  468,  446,  124,  466,  153,  462,  458,  154,  198,
+      159,  155,  183,  160,  193,  460,  552,  222,  552,  227,
+      552,  459,  204,  161,  231,  232,  238,  243,  236,  303,
+      245,  180,  247,  249,  281,   56,  257,  271,  248,  259,
+      252,  264,  455,  454,  297,  299,  312,  313,  320,  294,
+
+      407,  295,  427,  426,  321,  296,  324,  425,  552,  424,
+      552,  327,  329,  195,  328,  331,  332,  230,  334,  378,
+      552,  377,  552,  371,  370,  335,  365,  337,  358,  342,
+      360,  344,  326,  255,  340,  552,  260,  338,  246,  552,
+      197,  364,  192,  352,  382,  348,  186,  552,  420,  552,
+      423,  184,  141,  437,  421,  447,   79,  476,  346,  552,
+      453,  552,  515,  517,  519,  521,  523,  525,   71,  527,
+      529,  531,  533,  535,  537,  539,  541,  543,  545,  547,
+      549
+    } ;
+
+static yyconst flex_int16_t yy_def[182] =
+    {   0,
+      162,    1,  163,  163,  164,  164,  165,  165,  162,  166,
+      167,  162,  167,  167,  167,  167,  167,  167,  162,  166,
+      167,  167,  167,  168,  168,  167,  167,  167,  162,  169,
+      162,  170,  162,   20,  167,  162,  167,  167,  167,  167,
+      167,  171,   19,   20,   20,   20,   20,  167,  167,  167,
+      167,  167,   25,   25,  167,  167,   28,   28,  167,  167,
+      167,  167,  167,  167,  167,  169,  162,  170,  162,  170,
+      162,  171,   45,   25,  167,  167,  167,  167,  167,  167,
+      167,  167,  167,  167,   20,   25,  167,  167,  167,  167,
+      167,  167,  172,  173,  167,  167,  167,  167,  167,  167,
+
+       25,  167,  174,  175,  167,  167,  167,  172,  162,  173,
+      162,  167,  167,  167,  167,  167,  167,   25,  167,  174,
+      162,  175,  162,  176,  177,  167,  178,  167,  167,  167,
+      167,  167,   25,  167,  176,  162,  177,  167,  178,  162,
+      179,  167,  180,  167,  162,  167,  179,  162,  167,  162,
+      167,  180,  167,  181,  167,  167,  167,  181,  167,  162,
+      167,    0,  162,  162,  162,  162,  162,  162,  162,  162,
+      162,  162,  162,  162,  162,  162,  162,  162,  162,  162,
+      162
+    } ;
+
+static yyconst flex_int16_t yy_nxt[592] =
+    {   0,
+       10,   11,   12,   13,   14,   15,   16,   17,   16,   16,
+       18,   19,   20,   20,   21,   22,   23,   24,   24,   24,
+       24,   24,   25,   24,   24,   24,   24,   24,   24,   24,
+       24,   24,   24,   24,   24,   24,   24,   24,   26,   27,
+       31,   31,   36,   28,   37,   36,   36,   32,   32,   35,
+       36,   35,   35,   35,   35,   35,   35,   35,   35,   38,
+       36,   36,   35,   35,   35,   36,   40,   36,   39,   36,
+       36,   66,   48,   49,   41,   42,   56,   36,   55,   53,
+       57,   36,   50,   51,   52,  101,   35,   34,   35,   36,
+       35,   35,   35,   35,   35,   35,   35,   35,   43,   43,
+
+       34,   35,   35,   35,   34,   34,   44,   45,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   44,   34,   45,   35,   35,   36,   35,   35,
+       35,   35,   35,   35,   35,   35,   46,   46,   46,   35,
+       35,   35,   69,   36,   47,   37,   36,   53,   74,   70,
+       71,   34,   34,   34,   56,   36,   36,   36,   57,   34,
+       47,   36,   36,   35,   34,   35,   36,   35,   35,   35,
+       35,   35,   35,   35,   35,   34,   34,   75,   35,   35,
+       35,   81,   36,   80,   53,   36,   36,   86,  148,   83,
+       34,   34,   34,   34,   36,   36,  129,   36,   34,  148,
+
+       36,   98,   35,   34,   35,   36,   35,   35,   35,   35,
+       35,   35,   35,   35,   34,   82,   84,   35,   35,   35,
+       34,   34,   34,   85,   69,   76,   54,   77,   34,   69,
+       78,  162,  162,   36,   36,   79,   70,   71,   36,   85,
+       36,   35,   58,   36,   34,   36,   39,   36,  140,   36,
+       36,   36,  133,   53,   36,   87,  145,   36,   88,   36,
+       90,   36,   36,   59,   60,   89,   36,   61,   62,   99,
+       92,  104,   63,   36,   97,   91,   64,   65,   73,   73,
+       73,  100,  106,  102,   73,  105,   34,  107,   73,   73,
+       73,   73,   34,   34,   34,  103,   36,   36,   36,   36,
+
+       34,   36,   34,   93,   93,   94,   93,   93,   93,   93,
+       93,   93,   93,   93,   36,   36,   34,   93,   93,   93,
+      112,  113,   36,   36,  119,   95,   36,  117,  125,   36,
+       36,   36,   96,   36,   36,  114,   36,   36,  115,   36,
+       36,   93,  136,  116,   36,  124,   36,  159,  160,   53,
+       36,  127,  128,  126,   36,  131,  130,  134,  132,  129,
+       36,  141,   36,  143,  146,  149,  150,  140,  138,  142,
+      142,  142,   36,  136,  144,  151,  151,  151,  155,  123,
+      121,  153,   35,  145,   36,   35,   35,   35,   35,   35,
+       35,   35,   35,   35,   35,   35,   35,   35,   35,  154,
+
+      154,  154,  154,  154,  154,  154,  154,  154,  154,  154,
+      154,  154,  154,  154,  154,  154,  154,  154,  154,  154,
+       35,  149,  150,   36,  149,  150,  111,  109,  123,  121,
+      118,  156,  156,  156,  151,  151,  151,   35,   35,   36,
+       35,   35,   35,   35,   35,  157,   35,   35,  159,  160,
+      143,   35,   35,   35,  159,  160,  111,  109,  161,  161,
+      161,   36,   67,   35,  161,  161,  161,   35,   36,   53,
+       36,   36,   36,   36,   36,   35,   35,   35,   36,   35,
+       35,   35,   35,   35,  157,   35,   35,   36,   36,   36,
+       35,   35,   35,   36,   36,   36,   67,   36,   36,  162,
+
+       29,   29,  162,  162,  162,  162,  162,  162,  162,  162,
+      162,  162,  162,  162,   35,   29,   29,   30,   30,   33,
+       33,   34,   34,   35,   35,   53,   53,   68,   68,   72,
+       72,  108,  108,  110,  110,  120,  120,  122,  122,  135,
+      135,  137,  137,  139,  139,  147,  147,  152,  152,  158,
+      158,    9,  162,  162,  162,  162,  162,  162,  162,  162,
+      162,  162,  162,  162,  162,  162,  162,  162,  162,  162,
+      162,  162,  162,  162,  162,  162,  162,  162,  162,  162,
+      162,  162,  162,  162,  162,  162,  162,  162,  162,  162,
+      162
+
+    } ;
+
+static yyconst flex_int16_t yy_chk[592] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    2,
+        5,    6,   26,    2,   11,   11,   14,    5,    6,   10,
+       10,   10,   10,   10,   10,   10,   10,   10,   10,   14,
+       21,   17,   10,   10,   10,   15,   17,   18,   15,   22,
+       23,  169,   21,   21,   18,   18,   27,   27,   26,   86,
+       27,  157,   22,   23,   23,   86,   10,   19,   19,   19,
+       19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
+
+       19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
+       19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
+       19,   19,   19,   19,   19,   19,   20,   20,   20,   20,
+       20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
+       20,   20,   32,  153,   20,   37,   37,   54,   54,   32,
+       32,   34,   34,   34,   56,   56,   59,   62,   56,   34,
+       20,   61,   64,   20,   24,   24,   24,   24,   24,   24,
+       24,   24,   24,   24,   24,   34,   43,   59,   24,   24,
+       24,   62,   82,   61,   74,   63,  152,   74,  147,   64,
+       44,   44,   44,   43,  143,   65,  114,  114,   44,  141,
+
+       60,   82,   24,   25,   25,   25,   25,   25,   25,   25,
+       25,   25,   25,   25,   44,   63,   65,   25,   25,   25,
+       47,   47,   47,   73,   68,   60,   25,   60,   47,   70,
+       60,   68,   68,   75,   76,   60,   70,   70,   79,   73,
+       77,   25,   28,   28,   47,   78,   28,   81,  139,   83,
+       89,   84,  118,  118,   91,   75,  134,  134,   76,   87,
+       77,   90,  137,   28,   28,   76,   92,   28,   28,   83,
+       79,   89,   28,   88,   81,   78,   28,   28,   45,   45,
+       45,   84,   91,   87,   45,   90,   45,   92,   45,   45,
+       45,   45,   85,   85,   85,   88,  100,  102,  106,   95,
+
+       85,   96,   45,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   97,   98,   85,   80,   80,   80,
+       95,   96,   99,  105,  102,   80,  107,  100,  106,  112,
+      115,  113,   80,  116,  117,   97,  119,  126,   98,  128,
+      138,   80,  135,   99,  130,  105,  132,  159,  159,  133,
+      146,  112,  113,  107,  144,  116,  115,  119,  117,  129,
+      129,  128,  131,  130,  138,  142,  142,  127,  126,  129,
+      129,  129,  125,  124,  132,  142,  142,  142,  146,  122,
+      120,  144,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  149,  149,  155,  151,  151,  110,  108,  104,  103,
+      101,  149,  149,  149,  151,  151,  151,  154,  154,  154,
+      154,  154,  154,  154,  154,  154,  154,  154,  156,  156,
+      155,  154,  154,  154,  161,  161,   94,   93,  156,  156,
+      156,   72,   66,   58,  161,  161,  161,   57,   55,   53,
+       52,   51,   50,   49,   48,  154,  158,  158,  158,  158,
+      158,  158,  158,  158,  158,  158,  158,   42,   41,   40,
+      158,  158,  158,   39,   38,   35,   30,   16,   13,    9,
+
+        8,    7,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,  158,  163,  163,  164,  164,  165,
+      165,  166,  166,  167,  167,  168,  168,  170,  170,  171,
+      171,  172,  172,  173,  173,  174,  174,  175,  175,  176,
+      176,  177,  177,  178,  178,  179,  179,  180,  180,  181,
+      181,  162,  162,  162,  162,  162,  162,  162,  162,  162,
+      162,  162,  162,  162,  162,  162,  162,  162,  162,  162,
+      162,  162,  162,  162,  162,  162,  162,  162,  162,  162,
+      162,  162,  162,  162,  162,  162,  162,  162,  162,  162,
+      162
+
+    } ;
+
+#define YY_TRAILING_MASK 0x2000
+#define YY_TRAILING_HEAD_MASK 0x4000
+#define REJECT \
+{ \
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */ \
+yy_cp = yyg->yy_full_match; /* restore poss. backed-over text */ \
+yyg->yy_lp = yyg->yy_full_lp; /* restore orig. accepting pos. */ \
+yyg->yy_state_ptr = yyg->yy_full_state; /* restore orig. state */ \
+yy_current_state = *yyg->yy_state_ptr; /* restore curr. state */ \
+++yyg->yy_lp; \
+goto find_rule; \
+}
+
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "glcpp/glcpp-lex.l"
+#line 2 "glcpp/glcpp-lex.l"
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 <string.h>
+#include <ctype.h>
+
+#include "glcpp.h"
+#include "glcpp-parse.h"
+
+/* Flex annoyingly generates some functions without making them
+ * static. Let's declare them here. */
+int glcpp_get_column  (yyscan_t yyscanner);
+void glcpp_set_column (int  column_no , yyscan_t yyscanner);
+
+#define YY_NO_INPUT
+
+#define YY_USER_ACTION                                          \
+   do {                                                         \
+      yylloc->first_column = yycolumn + 1;                      \
+      yylloc->first_line = yylineno;                            \
+      yycolumn += yyleng;                                       \
+   } while(0);
+
+#define YY_USER_INIT                   \
+       do {                            \
+               yylineno = 1;           \
+               yycolumn = 1;           \
+               yylloc->source = 0;     \
+       } while(0)
+
+#line 709 "glcpp/glcpp-lex.c"
+
+#define INITIAL 0
+#define DONE 1
+#define COMMENT 2
+#define UNREACHABLE 3
+
+#define YY_EXTRA_TYPE glcpp_parser_t *
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+    {
+
+    /* User-defined. Not touched by flex. */
+    YY_EXTRA_TYPE yyextra_r;
+
+    /* The rest are the same as the globals declared in the non-reentrant scanner. */
+    FILE *yyin_r, *yyout_r;
+    size_t yy_buffer_stack_top; /**< index of top of stack. */
+    size_t yy_buffer_stack_max; /**< capacity of stack. */
+    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+    char yy_hold_char;
+    int yy_n_chars;
+    int yyleng_r;
+    char *yy_c_buf_p;
+    int yy_init;
+    int yy_start;
+    int yy_did_buffer_switch_on_eof;
+    int yy_start_stack_ptr;
+    int yy_start_stack_depth;
+    int *yy_start_stack;
+    yy_state_type yy_last_accepting_state;
+    char* yy_last_accepting_cpos;
+
+    int yylineno_r;
+    int yy_flex_debug_r;
+
+    yy_state_type *yy_state_buf;
+    yy_state_type *yy_state_ptr;
+    char *yy_full_match;
+    int yy_lp;
+
+    /* These are only needed for trailing context rules,
+     * but there's no conditional variable for that yet. */
+    int yy_looking_for_trail_begin;
+    int yy_full_lp;
+    int *yy_full_state;
+
+    char *yytext_r;
+    int yy_more_flag;
+    int yy_more_len;
+
+    YYSTYPE * yylval_r;
+
+    YYLTYPE * yylloc_r;
+
+    }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+    /* This must go here because YYSTYPE and YYLTYPE are included
+     * from bison output in section 1.*/
+    #    define yylval yyg->yylval_r
+    
+    #    define yylloc yyg->yylloc_r
+    
+int glcpp_lex_init (yyscan_t* scanner);
+
+int glcpp_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int glcpp_lex_destroy (yyscan_t yyscanner );
+
+int glcpp_get_debug (yyscan_t yyscanner );
+
+void glcpp_set_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE glcpp_get_extra (yyscan_t yyscanner );
+
+void glcpp_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *glcpp_get_in (yyscan_t yyscanner );
+
+void glcpp_set_in  (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *glcpp_get_out (yyscan_t yyscanner );
+
+void glcpp_set_out  (FILE * out_str ,yyscan_t yyscanner );
+
+int glcpp_get_leng (yyscan_t yyscanner );
+
+char *glcpp_get_text (yyscan_t yyscanner );
+
+int glcpp_get_lineno (yyscan_t yyscanner );
+
+void glcpp_set_lineno (int line_number ,yyscan_t yyscanner );
+
+YYSTYPE * glcpp_get_lval (yyscan_t yyscanner );
+
+void glcpp_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+       YYLTYPE *glcpp_get_lloc (yyscan_t yyscanner );
+    
+        void glcpp_set_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
+    
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int glcpp_wrap (yyscan_t yyscanner );
+#else
+extern int glcpp_wrap (yyscan_t yyscanner );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  ,yyscan_t yyscanner);
+    
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+    static void yy_push_state (int new_state ,yyscan_t yyscanner);
+    
+    static void yy_pop_state (yyscan_t yyscanner );
+    
+    static int yy_top_state (yyscan_t yyscanner );
+    
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+               { \
+               int c = '*'; \
+               size_t n; \
+               for ( n = 0; n < max_size && \
+                            (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+                       buf[n] = (char) c; \
+               if ( c == '\n' ) \
+                       buf[n++] = (char) c; \
+               if ( c == EOF && ferror( yyin ) ) \
+                       YY_FATAL_ERROR( "input in flex scanner failed" ); \
+               result = n; \
+               } \
+       else \
+               { \
+               errno=0; \
+               while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+                       { \
+                       if( errno != EINTR) \
+                               { \
+                               YY_FATAL_ERROR( "input in flex scanner failed" ); \
+                               break; \
+                               } \
+                       errno=0; \
+                       clearerr(yyin); \
+                       } \
+               }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int glcpp_lex \
+               (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
+
+#define YY_DECL int glcpp_lex \
+               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+       if ( yyleng > 0 ) \
+               YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+                               (yytext[yyleng - 1] == '\n'); \
+       YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+       register yy_state_type yy_current_state;
+       register char *yy_cp, *yy_bp;
+       register int yy_act;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+#line 76 "glcpp/glcpp-lex.l"
+
+
+       /* Single-line comments */
+#line 972 "glcpp/glcpp-lex.c"
+
+    yylval = yylval_param;
+
+    yylloc = yylloc_param;
+
+       if ( !yyg->yy_init )
+               {
+               yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+               YY_USER_INIT;
+#endif
+
+        /* Create the reject buffer large enough to save one state per allowed character. */
+        if ( ! yyg->yy_state_buf )
+            yyg->yy_state_buf = (yy_state_type *)glcpp_alloc(YY_STATE_BUF_SIZE  ,yyscanner);
+            if ( ! yyg->yy_state_buf )
+                YY_FATAL_ERROR( "out of dynamic memory in glcpp_lex()" );
+
+               if ( ! yyg->yy_start )
+                       yyg->yy_start = 1;      /* first start state */
+
+               if ( ! yyin )
+                       yyin = stdin;
+
+               if ( ! yyout )
+                       yyout = stdout;
+
+               if ( ! YY_CURRENT_BUFFER ) {
+                       glcpp_ensure_buffer_stack (yyscanner);
+                       YY_CURRENT_BUFFER_LVALUE =
+                               glcpp__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+               }
+
+               glcpp__load_buffer_state(yyscanner );
+               }
+
+       while ( 1 )             /* loops until end-of-file is reached */
+               {
+               yy_cp = yyg->yy_c_buf_p;
+
+               /* Support of yytext. */
+               *yy_cp = yyg->yy_hold_char;
+
+               /* yy_bp points to the position in yy_ch_buf of the start of
+                * the current run.
+                */
+               yy_bp = yy_cp;
+
+               yy_current_state = yyg->yy_start;
+               yy_current_state += YY_AT_BOL();
+
+               yyg->yy_state_ptr = yyg->yy_state_buf;
+               *yyg->yy_state_ptr++ = yy_current_state;
+
+yy_match:
+               do
+                       {
+                       register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+                       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                               {
+                               yy_current_state = (int) yy_def[yy_current_state];
+                               if ( yy_current_state >= 163 )
+                                       yy_c = yy_meta[(unsigned int) yy_c];
+                               }
+                       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+                       *yyg->yy_state_ptr++ = yy_current_state;
+                       ++yy_cp;
+                       }
+               while ( yy_current_state != 162 );
+
+yy_find_action:
+               yy_current_state = *--yyg->yy_state_ptr;
+               yyg->yy_lp = yy_accept[yy_current_state];
+find_rule: /* we branch to this label when backing up */
+               for ( ; ; ) /* until we find what rule we matched */
+                       {
+                       if ( yyg->yy_lp && yyg->yy_lp < yy_accept[yy_current_state + 1] )
+                               {
+                               yy_act = yy_acclist[yyg->yy_lp];
+                               if ( yy_act & YY_TRAILING_HEAD_MASK ||
+                                    yyg->yy_looking_for_trail_begin )
+                                       {
+                                       if ( yy_act == yyg->yy_looking_for_trail_begin )
+                                               {
+                                               yyg->yy_looking_for_trail_begin = 0;
+                                               yy_act &= ~YY_TRAILING_HEAD_MASK;
+                                               break;
+                                               }
+                                       }
+                               else if ( yy_act & YY_TRAILING_MASK )
+                                       {
+                                       yyg->yy_looking_for_trail_begin = yy_act & ~YY_TRAILING_MASK;
+                                       yyg->yy_looking_for_trail_begin |= YY_TRAILING_HEAD_MASK;
+                                       yyg->yy_full_match = yy_cp;
+                                       yyg->yy_full_state = yyg->yy_state_ptr;
+                                       yyg->yy_full_lp = yyg->yy_lp;
+                                       }
+                               else
+                                       {
+                                       yyg->yy_full_match = yy_cp;
+                                       yyg->yy_full_state = yyg->yy_state_ptr;
+                                       yyg->yy_full_lp = yyg->yy_lp;
+                                       break;
+                                       }
+                               ++yyg->yy_lp;
+                               goto find_rule;
+                               }
+                       --yy_cp;
+                       yy_current_state = *--yyg->yy_state_ptr;
+                       yyg->yy_lp = yy_accept[yy_current_state];
+                       }
+
+               YY_DO_BEFORE_ACTION;
+
+do_action:     /* This label is used only to access EOF actions. */
+
+               switch ( yy_act )
+       { /* beginning of action switch */
+case 1:
+YY_RULE_SETUP
+#line 79 "glcpp/glcpp-lex.l"
+{
+}
+       YY_BREAK
+/* Multi-line comments */
+case 2:
+YY_RULE_SETUP
+#line 83 "glcpp/glcpp-lex.l"
+{ yy_push_state(COMMENT, yyscanner); }
+       YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 84 "glcpp/glcpp-lex.l"
+
+       YY_BREAK
+case 4:
+/* rule 4 can match eol */
+YY_RULE_SETUP
+#line 85 "glcpp/glcpp-lex.l"
+{ yylineno++; yycolumn = 0; }
+       YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 86 "glcpp/glcpp-lex.l"
+
+       YY_BREAK
+case 6:
+/* rule 6 can match eol */
+YY_RULE_SETUP
+#line 87 "glcpp/glcpp-lex.l"
+{ yylineno++; yycolumn = 0; }
+       YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 88 "glcpp/glcpp-lex.l"
+{
+       yy_pop_state(yyscanner);
+       if (yyextra->space_tokens)
+               return SPACE;
+}
+       YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 94 "glcpp/glcpp-lex.l"
+{
+       yylval->str = talloc_strdup (yyextra, yytext);
+       yyextra->space_tokens = 0;
+       return HASH_VERSION;
+}
+       YY_BREAK
+/* glcpp doesn't handle #extension, #version, or #pragma directives.
+        * Simply pass them through to the main compiler's lexer/parser. */
+case 9:
+YY_RULE_SETUP
+#line 102 "glcpp/glcpp-lex.l"
+{
+       yylval->str = talloc_strdup (yyextra, yytext);
+       yylineno++;
+       yycolumn = 0;
+       return OTHER;
+}
+       YY_BREAK
+case 10:
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 109 "glcpp/glcpp-lex.l"
+{
+       /* Eat characters until the first digit is
+        * encountered
+        */
+       char *ptr = yytext;
+       while (!isdigit(*ptr))
+               ptr++;
+
+       /* Subtract one from the line number because
+        * yylineno is zero-based instead of
+        * one-based.
+        */
+       yylineno = strtol(ptr, &ptr, 0) - 1;
+       yylloc->source = strtol(ptr, NULL, 0);
+}
+       YY_BREAK
+case 11:
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 125 "glcpp/glcpp-lex.l"
+{
+       /* Eat characters until the first digit is
+        * encountered
+        */
+       char *ptr = yytext;
+       while (!isdigit(*ptr))
+               ptr++;
+
+       /* Subtract one from the line number because
+        * yylineno is zero-based instead of
+        * one-based.
+        */
+       yylineno = strtol(ptr, &ptr, 0) - 1;
+}
+       YY_BREAK
+case 12:
+/* rule 12 can match eol */
+YY_RULE_SETUP
+#line 140 "glcpp/glcpp-lex.l"
+{
+       yyextra->lexing_if = 1;
+       yyextra->space_tokens = 0;
+       return HASH_IFDEF;
+}
+       YY_BREAK
+case 13:
+/* rule 13 can match eol */
+YY_RULE_SETUP
+#line 146 "glcpp/glcpp-lex.l"
+{
+       yyextra->lexing_if = 1;
+       yyextra->space_tokens = 0;
+       return HASH_IFNDEF;
+}
+       YY_BREAK
+case 14:
+/* rule 14 can match eol */
+YY_RULE_SETUP
+#line 152 "glcpp/glcpp-lex.l"
+{
+       yyextra->lexing_if = 1;
+       yyextra->space_tokens = 0;
+       return HASH_IF;
+}
+       YY_BREAK
+case 15:
+/* rule 15 can match eol */
+YY_RULE_SETUP
+#line 158 "glcpp/glcpp-lex.l"
+{
+       yyextra->lexing_if = 1;
+       yyextra->space_tokens = 0;
+       return HASH_ELIF;
+}
+       YY_BREAK
+case 16:
+/* rule 16 can match eol */
+YY_RULE_SETUP
+#line 164 "glcpp/glcpp-lex.l"
+{
+       yyextra->space_tokens = 0;
+       return HASH_ELSE;
+}
+       YY_BREAK
+case 17:
+/* rule 17 can match eol */
+YY_RULE_SETUP
+#line 169 "glcpp/glcpp-lex.l"
+{
+       yyextra->space_tokens = 0;
+       return HASH_ENDIF;
+}
+       YY_BREAK
+/* When skipping (due to an #if 0 or similar) consume anything
+        * up to a newline. We do this with less priority than any
+        * #if-related directive (#if, #elif, #else, #endif), but with
+        * more priority than any other directive or token to avoid
+        * any side-effects from skipped content.
+        *
+        * We use the lexing_if flag to avoid skipping any part of an
+        * if conditional expression. */
+case 18:
+/* rule 18 can match eol */
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 182 "glcpp/glcpp-lex.l"
+{
+       /* Since this rule always matches, YY_USER_ACTION gets called for it,
+        * wrongly incrementing yycolumn.  We undo that effect here. */
+       yycolumn -= yyleng;
+       if (yyextra->lexing_if ||
+           yyextra->skip_stack == NULL ||
+           yyextra->skip_stack->type == SKIP_NO_SKIP)
+       {
+               REJECT;
+       }
+}
+       YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 194 "glcpp/glcpp-lex.l"
+{
+       char *p;
+       for (p = yytext; !isalpha(p[0]); p++); /* skip "  #   " */
+       p += 5; /* skip "error" */
+       glcpp_error(yylloc, yyextra, "#error%s", p);
+}
+       YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 201 "glcpp/glcpp-lex.l"
+{
+       yyextra->space_tokens = 0;
+       return HASH_DEFINE_FUNC;
+}
+       YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 206 "glcpp/glcpp-lex.l"
+{
+       yyextra->space_tokens = 0;
+       return HASH_DEFINE_OBJ;
+}
+       YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 211 "glcpp/glcpp-lex.l"
+{
+       yyextra->space_tokens = 0;
+       return HASH_UNDEF;
+}
+       YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 216 "glcpp/glcpp-lex.l"
+{
+       yyextra->space_tokens = 0;
+       return HASH;
+}
+       YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 221 "glcpp/glcpp-lex.l"
+{
+       yylval->str = talloc_strdup (yyextra, yytext);
+       return INTEGER_STRING;
+}
+       YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 226 "glcpp/glcpp-lex.l"
+{
+       yylval->str = talloc_strdup (yyextra, yytext);
+       return INTEGER_STRING;
+}
+       YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 231 "glcpp/glcpp-lex.l"
+{
+       yylval->str = talloc_strdup (yyextra, yytext);
+       return INTEGER_STRING;
+}
+       YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 236 "glcpp/glcpp-lex.l"
+{
+       return LEFT_SHIFT;
+}
+       YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 240 "glcpp/glcpp-lex.l"
+{
+       return RIGHT_SHIFT;
+}
+       YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 244 "glcpp/glcpp-lex.l"
+{
+       return LESS_OR_EQUAL;
+}
+       YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 248 "glcpp/glcpp-lex.l"
+{
+       return GREATER_OR_EQUAL;
+}
+       YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 252 "glcpp/glcpp-lex.l"
+{
+       return EQUAL;
+}
+       YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 256 "glcpp/glcpp-lex.l"
+{
+       return NOT_EQUAL;
+}
+       YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 260 "glcpp/glcpp-lex.l"
+{
+       return AND;
+}
+       YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 264 "glcpp/glcpp-lex.l"
+{
+       return OR;
+}
+       YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 268 "glcpp/glcpp-lex.l"
+{
+       return PASTE;
+}
+       YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 272 "glcpp/glcpp-lex.l"
+{
+       return DEFINED;
+}
+       YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 276 "glcpp/glcpp-lex.l"
+{
+       yylval->str = talloc_strdup (yyextra, yytext);
+       return IDENTIFIER;
+}
+       YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 281 "glcpp/glcpp-lex.l"
+{
+       return yytext[0];
+}
+       YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 285 "glcpp/glcpp-lex.l"
+{
+       yylval->str = talloc_strdup (yyextra, yytext);
+       return OTHER;
+}
+       YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 290 "glcpp/glcpp-lex.l"
+{
+       if (yyextra->space_tokens) {
+               return SPACE;
+       }
+}
+       YY_BREAK
+case 41:
+/* rule 41 can match eol */
+YY_RULE_SETUP
+#line 296 "glcpp/glcpp-lex.l"
+{
+       yyextra->lexing_if = 0;
+       yylineno++;
+       yycolumn = 0;
+       return NEWLINE;
+}
+       YY_BREAK
+/* Handle missing newline at EOF. */
+case YY_STATE_EOF(INITIAL):
+#line 304 "glcpp/glcpp-lex.l"
+{
+       BEGIN DONE; /* Don't keep matching this rule forever. */
+       yyextra->lexing_if = 0;
+       return NEWLINE;
+}
+       YY_BREAK
+/* We don't actually use the UNREACHABLE start condition. We
+       only have this action here so that we can pretend to call some
+       generated functions, (to avoid "defined but not used"
+       warnings. */
+case 42:
+YY_RULE_SETUP
+#line 314 "glcpp/glcpp-lex.l"
+{
+       unput('.');
+       yy_top_state(yyextra);
+}
+       YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 319 "glcpp/glcpp-lex.l"
+ECHO;
+       YY_BREAK
+#line 1489 "glcpp/glcpp-lex.c"
+                       case YY_STATE_EOF(DONE):
+                       case YY_STATE_EOF(COMMENT):
+                       case YY_STATE_EOF(UNREACHABLE):
+                               yyterminate();
+
+       case YY_END_OF_BUFFER:
+               {
+               /* Amount of text matched not including the EOB char. */
+               int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+               /* Undo the effects of YY_DO_BEFORE_ACTION. */
+               *yy_cp = yyg->yy_hold_char;
+               YY_RESTORE_YY_MORE_OFFSET
+
+               if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+                       {
+                       /* We're scanning a new file or input source.  It's
+                        * possible that this happened because the user
+                        * just pointed yyin at a new source and called
+                        * glcpp_lex().  If so, then we have to assure
+                        * consistency between YY_CURRENT_BUFFER and our
+                        * globals.  Here is the right place to do so, because
+                        * this is the first action (other than possibly a
+                        * back-up) that will match for the new input source.
+                        */
+                       yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+                       YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+                       YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+                       }
+
+               /* Note that here we test for yy_c_buf_p "<=" to the position
+                * of the first EOB in the buffer, since yy_c_buf_p will
+                * already have been incremented past the NUL character
+                * (since all states make transitions on EOB to the
+                * end-of-buffer state).  Contrast this with the test
+                * in input().
+                */
+               if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+                       { /* This was really a NUL. */
+                       yy_state_type yy_next_state;
+
+                       yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+                       yy_current_state = yy_get_previous_state( yyscanner );
+
+                       /* Okay, we're now positioned to make the NUL
+                        * transition.  We couldn't have
+                        * yy_get_previous_state() go ahead and do it
+                        * for us because it doesn't know how to deal
+                        * with the possibility of jamming (and we don't
+                        * want to build jamming into it because then it
+                        * will run more slowly).
+                        */
+
+                       yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+                       yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+                       if ( yy_next_state )
+                               {
+                               /* Consume the NUL. */
+                               yy_cp = ++yyg->yy_c_buf_p;
+                               yy_current_state = yy_next_state;
+                               goto yy_match;
+                               }
+
+                       else
+                               {
+                               yy_cp = yyg->yy_c_buf_p;
+                               goto yy_find_action;
+                               }
+                       }
+
+               else switch ( yy_get_next_buffer( yyscanner ) )
+                       {
+                       case EOB_ACT_END_OF_FILE:
+                               {
+                               yyg->yy_did_buffer_switch_on_eof = 0;
+
+                               if ( glcpp_wrap(yyscanner ) )
+                                       {
+                                       /* Note: because we've taken care in
+                                        * yy_get_next_buffer() to have set up
+                                        * yytext, we can now set up
+                                        * yy_c_buf_p so that if some total
+                                        * hoser (like flex itself) wants to
+                                        * call the scanner after we return the
+                                        * YY_NULL, it'll still work - another
+                                        * YY_NULL will get returned.
+                                        */
+                                       yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+                                       yy_act = YY_STATE_EOF(YY_START);
+                                       goto do_action;
+                                       }
+
+                               else
+                                       {
+                                       if ( ! yyg->yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+                                       }
+                               break;
+                               }
+
+                       case EOB_ACT_CONTINUE_SCAN:
+                               yyg->yy_c_buf_p =
+                                       yyg->yytext_ptr + yy_amount_of_matched_text;
+
+                               yy_current_state = yy_get_previous_state( yyscanner );
+
+                               yy_cp = yyg->yy_c_buf_p;
+                               yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+                               goto yy_match;
+
+                       case EOB_ACT_LAST_MATCH:
+                               yyg->yy_c_buf_p =
+                               &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+                               yy_current_state = yy_get_previous_state( yyscanner );
+
+                               yy_cp = yyg->yy_c_buf_p;
+                               yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+                               goto yy_find_action;
+                       }
+               break;
+               }
+
+       default:
+               YY_FATAL_ERROR(
+                       "fatal flex scanner internal error--no action found" );
+       } /* end of action switch */
+               } /* end of scanning one token */
+} /* end of glcpp_lex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *     EOB_ACT_LAST_MATCH -
+ *     EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *     EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+       register char *source = yyg->yytext_ptr;
+       register int number_to_move, i;
+       int ret_val;
+
+       if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+               YY_FATAL_ERROR(
+               "fatal flex scanner internal error--end of buffer missed" );
+
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+               { /* Don't try to fill the buffer, so this is an EOF. */
+               if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+                       {
+                       /* We matched a single character, the EOB, so
+                        * treat this as a final EOF.
+                        */
+                       return EOB_ACT_END_OF_FILE;
+                       }
+
+               else
+                       {
+                       /* We matched some text prior to the EOB, first
+                        * process it.
+                        */
+                       return EOB_ACT_LAST_MATCH;
+                       }
+               }
+
+       /* Try to read more data. */
+
+       /* First move last chars to start of buffer. */
+       number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+       for ( i = 0; i < number_to_move; ++i )
+               *(dest++) = *(source++);
+
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+               /* don't do the read, it's not guaranteed to return an EOF,
+                * just force an EOF
+                */
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+       else
+               {
+                       int num_to_read =
+                       YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+               while ( num_to_read <= 0 )
+                       { /* Not enough room in the buffer - grow it. */
+
+                       YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+
+                       }
+
+               if ( num_to_read > YY_READ_BUF_SIZE )
+                       num_to_read = YY_READ_BUF_SIZE;
+
+               /* Read in more data. */
+               YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+                       yyg->yy_n_chars, (size_t) num_to_read );
+
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+               }
+
+       if ( yyg->yy_n_chars == 0 )
+               {
+               if ( number_to_move == YY_MORE_ADJ )
+                       {
+                       ret_val = EOB_ACT_END_OF_FILE;
+                       glcpp_restart(yyin  ,yyscanner);
+                       }
+
+               else
+                       {
+                       ret_val = EOB_ACT_LAST_MATCH;
+                       YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+                               YY_BUFFER_EOF_PENDING;
+                       }
+               }
+
+       else
+               ret_val = EOB_ACT_CONTINUE_SCAN;
+
+       if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+               /* Extend the array by 50%, plus the number we really need. */
+               yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+               YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) glcpp_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+               if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+                       YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+       }
+
+       yyg->yy_n_chars += number_to_move;
+       YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+       YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+       yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+       return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+       register yy_state_type yy_current_state;
+       register char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       yy_current_state = yyg->yy_start;
+       yy_current_state += YY_AT_BOL();
+
+       yyg->yy_state_ptr = yyg->yy_state_buf;
+       *yyg->yy_state_ptr++ = yy_current_state;
+
+       for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+               {
+               register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+               while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                       {
+                       yy_current_state = (int) yy_def[yy_current_state];
+                       if ( yy_current_state >= 163 )
+                               yy_c = yy_meta[(unsigned int) yy_c];
+                       }
+               yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+               *yyg->yy_state_ptr++ = yy_current_state;
+               }
+
+       return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *     next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+       register int yy_is_jam;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+
+       register YY_CHAR yy_c = 1;
+       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+               {
+               yy_current_state = (int) yy_def[yy_current_state];
+               if ( yy_current_state >= 163 )
+                       yy_c = yy_meta[(unsigned int) yy_c];
+               }
+       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+       yy_is_jam = (yy_current_state == 162);
+       if ( ! yy_is_jam )
+               *yyg->yy_state_ptr++ = yy_current_state;
+
+       return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
+{
+       register char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    yy_cp = yyg->yy_c_buf_p;
+
+       /* undo effects of setting up yytext */
+       *yy_cp = yyg->yy_hold_char;
+
+       if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+               { /* need to shift things up to make room */
+               /* +2 for EOB chars. */
+               register int number_to_move = yyg->yy_n_chars + 2;
+               register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+                                       YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+               register char *source =
+                               &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+               while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+                       *--dest = *--source;
+
+               yy_cp += (int) (dest - source);
+               yy_bp += (int) (dest - source);
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+                       yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+               if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+                       YY_FATAL_ERROR( "flex scanner push-back overflow" );
+               }
+
+       *--yy_cp = (char) c;
+
+       yyg->yytext_ptr = yy_bp;
+       yyg->yy_hold_char = *yy_cp;
+       yyg->yy_c_buf_p = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (yyscan_t yyscanner)
+#else
+    static int input  (yyscan_t yyscanner)
+#endif
+
+{
+       int c;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       *yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+       if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+               {
+               /* yy_c_buf_p now points to the character we want to return.
+                * If this occurs *before* the EOB characters, then it's a
+                * valid NUL; if not, then we've hit the end of the buffer.
+                */
+               if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+                       /* This was really a NUL. */
+                       *yyg->yy_c_buf_p = '\0';
+
+               else
+                       { /* need more input */
+                       int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+                       ++yyg->yy_c_buf_p;
+
+                       switch ( yy_get_next_buffer( yyscanner ) )
+                               {
+                               case EOB_ACT_LAST_MATCH:
+                                       /* This happens because yy_g_n_b()
+                                        * sees that we've accumulated a
+                                        * token and flags that we need to
+                                        * try matching the token before
+                                        * proceeding.  But for input(),
+                                        * there's no matching to consider.
+                                        * So convert the EOB_ACT_LAST_MATCH
+                                        * to EOB_ACT_END_OF_FILE.
+                                        */
+
+                                       /* Reset buffer status. */
+                                       glcpp_restart(yyin ,yyscanner);
+
+                                       /*FALLTHROUGH*/
+
+                               case EOB_ACT_END_OF_FILE:
+                                       {
+                                       if ( glcpp_wrap(yyscanner ) )
+                                               return EOF;
+
+                                       if ( ! yyg->yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+#ifdef __cplusplus
+                                       return yyinput(yyscanner);
+#else
+                                       return input(yyscanner);
+#endif
+                                       }
+
+                               case EOB_ACT_CONTINUE_SCAN:
+                                       yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+                                       break;
+                               }
+                       }
+               }
+
+       c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
+       *yyg->yy_c_buf_p = '\0';        /* preserve yytext */
+       yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+       YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+       return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void glcpp_restart  (FILE * input_file , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       if ( ! YY_CURRENT_BUFFER ){
+        glcpp_ensure_buffer_stack (yyscanner);
+               YY_CURRENT_BUFFER_LVALUE =
+            glcpp__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+       }
+
+       glcpp__init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+       glcpp__load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+    void glcpp__switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       /* TODO. We should be able to replace this entire function body
+        * with
+        *              glcpp_pop_buffer_state();
+        *              glcpp_push_buffer_state(new_buffer);
+     */
+       glcpp_ensure_buffer_stack (yyscanner);
+       if ( YY_CURRENT_BUFFER == new_buffer )
+               return;
+
+       if ( YY_CURRENT_BUFFER )
+               {
+               /* Flush out information for old buffer. */
+               *yyg->yy_c_buf_p = yyg->yy_hold_char;
+               YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+               }
+
+       YY_CURRENT_BUFFER_LVALUE = new_buffer;
+       glcpp__load_buffer_state(yyscanner );
+
+       /* We don't actually know whether we did this switch during
+        * EOF (glcpp_wrap()) processing, but the only time this flag
+        * is looked at is after glcpp_wrap() is called, so it's safe
+        * to go ahead and always set it.
+        */
+       yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void glcpp__load_buffer_state  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+       yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+       yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+       yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE glcpp__create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
+{
+       YY_BUFFER_STATE b;
+    
+       b = (YY_BUFFER_STATE) glcpp_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in glcpp__create_buffer()" );
+
+       b->yy_buf_size = size;
+
+       /* yy_ch_buf has to be 2 characters longer than the size given because
+        * we need to put in 2 end-of-buffer characters.
+        */
+       b->yy_ch_buf = (char *) glcpp_alloc(b->yy_buf_size + 2 ,yyscanner );
+       if ( ! b->yy_ch_buf )
+               YY_FATAL_ERROR( "out of dynamic memory in glcpp__create_buffer()" );
+
+       b->yy_is_our_buffer = 1;
+
+       glcpp__init_buffer(b,file ,yyscanner);
+
+       return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with glcpp__create_buffer()
+ * @param yyscanner The scanner object.
+ */
+    void glcpp__delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       if ( ! b )
+               return;
+
+       if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+               YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+       if ( b->yy_is_our_buffer )
+               glcpp_free((void *) b->yy_ch_buf ,yyscanner );
+
+       glcpp_free((void *) b ,yyscanner );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a glcpp_restart() or at EOF.
+ */
+    static void glcpp__init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
+
+{
+       int oerrno = errno;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       glcpp__flush_buffer(b ,yyscanner);
+
+       b->yy_input_file = file;
+       b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then glcpp__init_buffer was _probably_
+     * called from glcpp_restart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+       errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+    void glcpp__flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       if ( ! b )
+               return;
+
+       b->yy_n_chars = 0;
+
+       /* We always need two end-of-buffer characters.  The first causes
+        * a transition to the end-of-buffer state.  The second causes
+        * a jam in that state.
+        */
+       b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+       b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+       b->yy_buf_pos = &b->yy_ch_buf[0];
+
+       b->yy_at_bol = 1;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       if ( b == YY_CURRENT_BUFFER )
+               glcpp__load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  @param yyscanner The scanner object.
+ */
+void glcpp_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       if (new_buffer == NULL)
+               return;
+
+       glcpp_ensure_buffer_stack(yyscanner);
+
+       /* This block is copied from glcpp__switch_to_buffer. */
+       if ( YY_CURRENT_BUFFER )
+               {
+               /* Flush out information for old buffer. */
+               *yyg->yy_c_buf_p = yyg->yy_hold_char;
+               YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+               }
+
+       /* Only push if top exists. Otherwise, replace top. */
+       if (YY_CURRENT_BUFFER)
+               yyg->yy_buffer_stack_top++;
+       YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+       /* copied from glcpp__switch_to_buffer. */
+       glcpp__load_buffer_state(yyscanner );
+       yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  @param yyscanner The scanner object.
+ */
+void glcpp_pop_buffer_state (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       if (!YY_CURRENT_BUFFER)
+               return;
+
+       glcpp__delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+       YY_CURRENT_BUFFER_LVALUE = NULL;
+       if (yyg->yy_buffer_stack_top > 0)
+               --yyg->yy_buffer_stack_top;
+
+       if (YY_CURRENT_BUFFER) {
+               glcpp__load_buffer_state(yyscanner );
+               yyg->yy_did_buffer_switch_on_eof = 1;
+       }
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void glcpp_ensure_buffer_stack (yyscan_t yyscanner)
+{
+       int num_to_alloc;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       if (!yyg->yy_buffer_stack) {
+
+               /* First allocation is just for 2 elements, since we don't know if this
+                * scanner will even need a stack. We use 2 instead of 1 to avoid an
+                * immediate realloc on the next call.
+         */
+               num_to_alloc = 1;
+               yyg->yy_buffer_stack = (struct yy_buffer_state**)glcpp_alloc
+                                                               (num_to_alloc * sizeof(struct yy_buffer_state*)
+                                                               , yyscanner);
+               if ( ! yyg->yy_buffer_stack )
+                       YY_FATAL_ERROR( "out of dynamic memory in glcpp_ensure_buffer_stack()" );
+                                                                 
+               memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+                               
+               yyg->yy_buffer_stack_max = num_to_alloc;
+               yyg->yy_buffer_stack_top = 0;
+               return;
+       }
+
+       if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+               /* Increase the buffer to prepare for a possible push. */
+               int grow_size = 8 /* arbitrary grow size */;
+
+               num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+               yyg->yy_buffer_stack = (struct yy_buffer_state**)glcpp_realloc
+                                                               (yyg->yy_buffer_stack,
+                                                               num_to_alloc * sizeof(struct yy_buffer_state*)
+                                                               , yyscanner);
+               if ( ! yyg->yy_buffer_stack )
+                       YY_FATAL_ERROR( "out of dynamic memory in glcpp_ensure_buffer_stack()" );
+
+               /* zero only the new slots.*/
+               memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+               yyg->yy_buffer_stack_max = num_to_alloc;
+       }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE glcpp__scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
+{
+       YY_BUFFER_STATE b;
+    
+       if ( size < 2 ||
+            base[size-2] != YY_END_OF_BUFFER_CHAR ||
+            base[size-1] != YY_END_OF_BUFFER_CHAR )
+               /* They forgot to leave room for the EOB's. */
+               return 0;
+
+       b = (YY_BUFFER_STATE) glcpp_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in glcpp__scan_buffer()" );
+
+       b->yy_buf_size = size - 2;      /* "- 2" to take care of EOB's */
+       b->yy_buf_pos = b->yy_ch_buf = base;
+       b->yy_is_our_buffer = 0;
+       b->yy_input_file = 0;
+       b->yy_n_chars = b->yy_buf_size;
+       b->yy_is_interactive = 0;
+       b->yy_at_bol = 1;
+       b->yy_fill_buffer = 0;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       glcpp__switch_to_buffer(b ,yyscanner );
+
+       return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to glcpp_lex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       glcpp__scan_bytes() instead.
+ */
+YY_BUFFER_STATE glcpp__scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+    
+       return glcpp__scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to glcpp_lex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE glcpp__scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
+{
+       YY_BUFFER_STATE b;
+       char *buf;
+       yy_size_t n;
+       int i;
+    
+       /* Get memory for full buffer, including space for trailing EOB's. */
+       n = _yybytes_len + 2;
+       buf = (char *) glcpp_alloc(n ,yyscanner );
+       if ( ! buf )
+               YY_FATAL_ERROR( "out of dynamic memory in glcpp__scan_bytes()" );
+
+       for ( i = 0; i < _yybytes_len; ++i )
+               buf[i] = yybytes[i];
+
+       buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+       b = glcpp__scan_buffer(buf,n ,yyscanner);
+       if ( ! b )
+               YY_FATAL_ERROR( "bad buffer in glcpp__scan_bytes()" );
+
+       /* It's okay to grow etc. this buffer, and we should throw it
+        * away when we're done.
+        */
+       b->yy_is_our_buffer = 1;
+
+       return b;
+}
+
+    static void yy_push_state (int  new_state , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       if ( yyg->yy_start_stack_ptr >= yyg->yy_start_stack_depth )
+               {
+               yy_size_t new_size;
+
+               yyg->yy_start_stack_depth += YY_START_STACK_INCR;
+               new_size = yyg->yy_start_stack_depth * sizeof( int );
+
+               if ( ! yyg->yy_start_stack )
+                       yyg->yy_start_stack = (int *) glcpp_alloc(new_size ,yyscanner );
+
+               else
+                       yyg->yy_start_stack = (int *) glcpp_realloc((void *) yyg->yy_start_stack,new_size ,yyscanner );
+
+               if ( ! yyg->yy_start_stack )
+                       YY_FATAL_ERROR( "out of memory expanding start-condition stack" );
+               }
+
+       yyg->yy_start_stack[yyg->yy_start_stack_ptr++] = YY_START;
+
+       BEGIN(new_state);
+}
+
+    static void yy_pop_state  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       if ( --yyg->yy_start_stack_ptr < 0 )
+               YY_FATAL_ERROR( "start-condition stack underflow" );
+
+       BEGIN(yyg->yy_start_stack[yyg->yy_start_stack_ptr]);
+}
+
+    static int yy_top_state  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       return yyg->yy_start_stack[yyg->yy_start_stack_ptr - 1];
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+       (void) fprintf( stderr, "%s\n", msg );
+       exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+               yytext[yyleng] = yyg->yy_hold_char; \
+               yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+               yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+               *yyg->yy_c_buf_p = '\0'; \
+               yyleng = yyless_macro_arg; \
+               } \
+       while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE glcpp_get_extra  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int glcpp_get_lineno  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int glcpp_get_column  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *glcpp_get_in  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *glcpp_get_out  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int glcpp_get_leng  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *glcpp_get_text  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void glcpp_set_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void glcpp_set_lineno (int  line_number , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* lineno is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "glcpp_set_lineno called with no buffer" , yyscanner); 
+    
+    yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void glcpp_set_column (int  column_no , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* column is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "glcpp_set_column called with no buffer" , yyscanner); 
+    
+    yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see glcpp__switch_to_buffer
+ */
+void glcpp_set_in (FILE *  in_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyin = in_str ;
+}
+
+void glcpp_set_out (FILE *  out_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyout = out_str ;
+}
+
+int glcpp_get_debug  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yy_flex_debug;
+}
+
+void glcpp_set_debug (int  bdebug , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * glcpp_get_lval  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yylval;
+}
+
+void glcpp_set_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yylval = yylval_param;
+}
+
+YYLTYPE *glcpp_get_lloc  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yylloc;
+}
+    
+void glcpp_set_lloc (YYLTYPE *  yylloc_param , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yylloc = yylloc_param;
+}
+    
+/* User-visible API */
+
+/* glcpp_lex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int glcpp_lex_init(yyscan_t* ptr_yy_globals)
+
+{
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+
+    *ptr_yy_globals = (yyscan_t) glcpp_alloc ( sizeof( struct yyguts_t ), NULL );
+
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+
+    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* glcpp_lex_init_extra has the same functionality as glcpp_lex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to glcpp_alloc in
+ * the yyextra field.
+ */
+
+int glcpp_lex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+    struct yyguts_t dummy_yyguts;
+
+    glcpp_set_extra (yy_user_defined, &dummy_yyguts);
+
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+       
+    *ptr_yy_globals = (yyscan_t) glcpp_alloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+       
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+    
+    /* By setting to 0xAA, we expose bugs in
+    yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+    
+    glcpp_set_extra (yy_user_defined, *ptr_yy_globals);
+    
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from glcpp_lex_destroy(), so don't allocate here.
+     */
+
+    yyg->yy_buffer_stack = 0;
+    yyg->yy_buffer_stack_top = 0;
+    yyg->yy_buffer_stack_max = 0;
+    yyg->yy_c_buf_p = (char *) 0;
+    yyg->yy_init = 0;
+    yyg->yy_start = 0;
+
+    yyg->yy_start_stack_ptr = 0;
+    yyg->yy_start_stack_depth = 0;
+    yyg->yy_start_stack =  NULL;
+
+    yyg->yy_state_buf = 0;
+    yyg->yy_state_ptr = 0;
+    yyg->yy_full_match = 0;
+    yyg->yy_lp = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * glcpp_lex_init()
+     */
+    return 0;
+}
+
+/* glcpp_lex_destroy is for both reentrant and non-reentrant scanners. */
+int glcpp_lex_destroy  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    /* Pop the buffer stack, destroying each element. */
+       while(YY_CURRENT_BUFFER){
+               glcpp__delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+               YY_CURRENT_BUFFER_LVALUE = NULL;
+               glcpp_pop_buffer_state(yyscanner);
+       }
+
+       /* Destroy the stack itself. */
+       glcpp_free(yyg->yy_buffer_stack ,yyscanner);
+       yyg->yy_buffer_stack = NULL;
+
+    /* Destroy the start condition stack. */
+        glcpp_free(yyg->yy_start_stack ,yyscanner );
+        yyg->yy_start_stack = NULL;
+
+    glcpp_free ( yyg->yy_state_buf , yyscanner);
+    yyg->yy_state_buf  = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * glcpp_lex() is called, initialization will occur. */
+    yy_init_globals( yyscanner);
+
+    /* Destroy the main struct (reentrant only). */
+    glcpp_free ( yyscanner , yyscanner );
+    yyscanner = NULL;
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+       register int i;
+       for ( i = 0; i < n; ++i )
+               s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+       register int n;
+       for ( n = 0; s[n]; ++n )
+               ;
+
+       return n;
+}
+#endif
+
+void *glcpp_alloc (yy_size_t  size , yyscan_t yyscanner)
+{
+       return (void *) malloc( size );
+}
+
+void *glcpp_realloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
+{
+       /* The cast to (char *) in the following accommodates both
+        * implementations that use char* generic pointers, and those
+        * that use void* generic pointers.  It works with the latter
+        * because both ANSI C and C++ allow castless assignment from
+        * any pointer type to void*, and deal with argument conversions
+        * as though doing an assignment.
+        */
+       return (void *) realloc( (char *) ptr, size );
+}
+
+void glcpp_free (void * ptr , yyscan_t yyscanner)
+{
+       free( (char *) ptr );   /* see glcpp_realloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 319 "glcpp/glcpp-lex.l"
+
+
+
+void
+glcpp_lex_set_source_string(glcpp_parser_t *parser, const char *shader)
+{
+       glcpp__scan_string(shader,parser->scanner);
+}
+
diff --git a/src/glsl/glcpp/glcpp-lex.l b/src/glsl/glcpp/glcpp-lex.l
new file mode 100644 (file)
index 0000000..8eb84ed
--- /dev/null
@@ -0,0 +1,325 @@
+%{
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 <string.h>
+#include <ctype.h>
+
+#include "glcpp.h"
+#include "glcpp-parse.h"
+
+/* Flex annoyingly generates some functions without making them
+ * static. Let's declare them here. */
+int glcpp_get_column  (yyscan_t yyscanner);
+void glcpp_set_column (int  column_no , yyscan_t yyscanner);
+
+#define YY_NO_INPUT
+
+#define YY_USER_ACTION                                          \
+   do {                                                         \
+      yylloc->first_column = yycolumn + 1;                      \
+      yylloc->first_line = yylineno;                            \
+      yycolumn += yyleng;                                       \
+   } while(0);
+
+#define YY_USER_INIT                   \
+       do {                            \
+               yylineno = 1;           \
+               yycolumn = 1;           \
+               yylloc->source = 0;     \
+       } while(0)
+%}
+
+%option bison-bridge bison-locations reentrant noyywrap
+%option extra-type="glcpp_parser_t *"
+%option prefix="glcpp_"
+%option stack
+%option never-interactive
+
+%x DONE COMMENT UNREACHABLE
+
+SPACE          [[:space:]]
+NONSPACE       [^[:space:]]
+NEWLINE                [\n]
+HSPACE         [ \t]
+HASH           ^{HSPACE}*#{HSPACE}*
+IDENTIFIER     [_a-zA-Z][_a-zA-Z0-9]*
+PUNCTUATION    [][(){}.&*~!/%<>^|;,=+-]
+OTHER          [^][(){}.&*~!/%<>^|;,=#[:space:]+-]+
+
+DIGITS                 [0-9][0-9]*
+DECIMAL_INTEGER                [1-9][0-9]*[uU]?
+OCTAL_INTEGER          0[0-7]*[uU]?
+HEXADECIMAL_INTEGER    0[xX][0-9a-fA-F]+[uU]?
+
+%%
+
+       /* Single-line comments */
+"//"[^\n]* {
+}
+
+       /* Multi-line comments */
+"/*"                    { yy_push_state(COMMENT, yyscanner); }
+<COMMENT>[^*\n]*
+<COMMENT>[^*\n]*\n      { yylineno++; yycolumn = 0; }
+<COMMENT>"*"+[^*/\n]*
+<COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; }
+<COMMENT>"*"+"/"        {
+       yy_pop_state(yyscanner);
+       if (yyextra->space_tokens)
+               return SPACE;
+}
+
+{HASH}version {
+       yylval->str = talloc_strdup (yyextra, yytext);
+       yyextra->space_tokens = 0;
+       return HASH_VERSION;
+}
+
+       /* glcpp doesn't handle #extension, #version, or #pragma directives.
+        * Simply pass them through to the main compiler's lexer/parser. */
+{HASH}(extension|pragma)[^\n]+ {
+       yylval->str = talloc_strdup (yyextra, yytext);
+       yylineno++;
+       yycolumn = 0;
+       return OTHER;
+}
+
+{HASH}line{HSPACE}+{DIGITS}{HSPACE}+{DIGITS}{HSPACE}*$ {
+       /* Eat characters until the first digit is
+        * encountered
+        */
+       char *ptr = yytext;
+       while (!isdigit(*ptr))
+               ptr++;
+
+       /* Subtract one from the line number because
+        * yylineno is zero-based instead of
+        * one-based.
+        */
+       yylineno = strtol(ptr, &ptr, 0) - 1;
+       yylloc->source = strtol(ptr, NULL, 0);
+}
+
+{HASH}line{HSPACE}+{DIGITS}{HSPACE}*$ {
+       /* Eat characters until the first digit is
+        * encountered
+        */
+       char *ptr = yytext;
+       while (!isdigit(*ptr))
+               ptr++;
+
+       /* Subtract one from the line number because
+        * yylineno is zero-based instead of
+        * one-based.
+        */
+       yylineno = strtol(ptr, &ptr, 0) - 1;
+}
+
+{HASH}ifdef/.*\n {
+       yyextra->lexing_if = 1;
+       yyextra->space_tokens = 0;
+       return HASH_IFDEF;
+}
+
+{HASH}ifndef/.*\n {
+       yyextra->lexing_if = 1;
+       yyextra->space_tokens = 0;
+       return HASH_IFNDEF;
+}
+
+{HASH}if/[^_a-zA-Z0-9].*\n {
+       yyextra->lexing_if = 1;
+       yyextra->space_tokens = 0;
+       return HASH_IF;
+}
+
+{HASH}elif/.*\n {
+       yyextra->lexing_if = 1;
+       yyextra->space_tokens = 0;
+       return HASH_ELIF;
+}
+
+{HASH}else/.*\n {
+       yyextra->space_tokens = 0;
+       return HASH_ELSE;
+}
+
+{HASH}endif/.*\n {
+       yyextra->space_tokens = 0;
+       return HASH_ENDIF;
+}
+
+       /* When skipping (due to an #if 0 or similar) consume anything
+        * up to a newline. We do this with less priority than any
+        * #if-related directive (#if, #elif, #else, #endif), but with
+        * more priority than any other directive or token to avoid
+        * any side-effects from skipped content.
+        *
+        * We use the lexing_if flag to avoid skipping any part of an
+        * if conditional expression. */
+[^\n]+/\n {
+       /* Since this rule always matches, YY_USER_ACTION gets called for it,
+        * wrongly incrementing yycolumn.  We undo that effect here. */
+       yycolumn -= yyleng;
+       if (yyextra->lexing_if ||
+           yyextra->skip_stack == NULL ||
+           yyextra->skip_stack->type == SKIP_NO_SKIP)
+       {
+               REJECT;
+       }
+}
+
+{HASH}error.* {
+       char *p;
+       for (p = yytext; !isalpha(p[0]); p++); /* skip "  #   " */
+       p += 5; /* skip "error" */
+       glcpp_error(yylloc, yyextra, "#error%s", p);
+}
+
+{HASH}define{HSPACE}+/{IDENTIFIER}"(" {
+       yyextra->space_tokens = 0;
+       return HASH_DEFINE_FUNC;
+}
+
+{HASH}define {
+       yyextra->space_tokens = 0;
+       return HASH_DEFINE_OBJ;
+}
+
+{HASH}undef {
+       yyextra->space_tokens = 0;
+       return HASH_UNDEF;
+}
+
+{HASH} {
+       yyextra->space_tokens = 0;
+       return HASH;
+}
+
+{DECIMAL_INTEGER} {
+       yylval->str = talloc_strdup (yyextra, yytext);
+       return INTEGER_STRING;
+}
+
+{OCTAL_INTEGER} {
+       yylval->str = talloc_strdup (yyextra, yytext);
+       return INTEGER_STRING;
+}
+
+{HEXADECIMAL_INTEGER} {
+       yylval->str = talloc_strdup (yyextra, yytext);
+       return INTEGER_STRING;
+}
+
+"<<"  {
+       return LEFT_SHIFT;
+}
+
+">>" {
+       return RIGHT_SHIFT;
+}
+
+"<=" {
+       return LESS_OR_EQUAL;
+}
+
+">=" {
+       return GREATER_OR_EQUAL;
+}
+
+"==" {
+       return EQUAL;
+}
+
+"!=" {
+       return NOT_EQUAL;
+}
+
+"&&" {
+       return AND;
+}
+
+"||" {
+       return OR;
+}
+
+"##" {
+       return PASTE;
+}
+
+"defined" {
+       return DEFINED;
+}
+
+{IDENTIFIER} {
+       yylval->str = talloc_strdup (yyextra, yytext);
+       return IDENTIFIER;
+}
+
+{PUNCTUATION} {
+       return yytext[0];
+}
+
+{OTHER}+ {
+       yylval->str = talloc_strdup (yyextra, yytext);
+       return OTHER;
+}
+
+{HSPACE}+ {
+       if (yyextra->space_tokens) {
+               return SPACE;
+       }
+}
+
+\n {
+       yyextra->lexing_if = 0;
+       yylineno++;
+       yycolumn = 0;
+       return NEWLINE;
+}
+
+       /* Handle missing newline at EOF. */
+<INITIAL><<EOF>> {
+       BEGIN DONE; /* Don't keep matching this rule forever. */
+       yyextra->lexing_if = 0;
+       return NEWLINE;
+}
+
+       /* We don't actually use the UNREACHABLE start condition. We
+       only have this action here so that we can pretend to call some
+       generated functions, (to avoid "defined but not used"
+       warnings. */
+<UNREACHABLE>. {
+       unput('.');
+       yy_top_state(yyextra);
+}
+
+%%
+
+void
+glcpp_lex_set_source_string(glcpp_parser_t *parser, const char *shader)
+{
+       yy_scan_string(shader, parser->scanner);
+}
diff --git a/src/glsl/glcpp/glcpp-parse.c b/src/glsl/glcpp/glcpp-parse.c
new file mode 100644 (file)
index 0000000..91eb0bf
--- /dev/null
@@ -0,0 +1,4168 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1.  */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+   
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+   
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.4.1"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 1
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+/* Using locations.  */
+#define YYLSP_NEEDED 1
+
+
+
+/* Copy the first part of user declarations.  */
+
+/* Line 189 of yacc.c  */
+#line 1 "glcpp/glcpp-parse.y"
+
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <inttypes.h>
+
+#include "glcpp.h"
+#include "main/core.h" /* for struct gl_extensions */
+
+#define glcpp_print(stream, str) stream = talloc_strdup_append(stream, str)
+#define glcpp_printf(stream, fmt, args, ...) \
+       stream = talloc_asprintf_append(stream, fmt, args)
+
+static void
+yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error);
+
+static void
+_define_object_macro (glcpp_parser_t *parser,
+                     YYLTYPE *loc,
+                     const char *macro,
+                     token_list_t *replacements);
+
+static void
+_define_function_macro (glcpp_parser_t *parser,
+                       YYLTYPE *loc,
+                       const char *macro,
+                       string_list_t *parameters,
+                       token_list_t *replacements);
+
+static string_list_t *
+_string_list_create (void *ctx);
+
+static void
+_string_list_append_item (string_list_t *list, const char *str);
+
+static int
+_string_list_contains (string_list_t *list, const char *member, int *index);
+
+static int
+_string_list_length (string_list_t *list);
+
+static int
+_string_list_equal (string_list_t *a, string_list_t *b);
+
+static argument_list_t *
+_argument_list_create (void *ctx);
+
+static void
+_argument_list_append (argument_list_t *list, token_list_t *argument);
+
+static int
+_argument_list_length (argument_list_t *list);
+
+static token_list_t *
+_argument_list_member_at (argument_list_t *list, int index);
+
+/* Note: This function talloc_steal()s the str pointer. */
+static token_t *
+_token_create_str (void *ctx, int type, char *str);
+
+static token_t *
+_token_create_ival (void *ctx, int type, int ival);
+
+static token_list_t *
+_token_list_create (void *ctx);
+
+/* Note: This function adds a talloc_reference() to token.
+ *
+ * You may want to talloc_unlink any current reference if you no
+ * longer need it. */
+static void
+_token_list_append (token_list_t *list, token_t *token);
+
+static void
+_token_list_append_list (token_list_t *list, token_list_t *tail);
+
+static int
+_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b);
+
+static active_list_t *
+_active_list_push (active_list_t *list,
+                  const char *identifier,
+                  token_node_t *marker);
+
+static active_list_t *
+_active_list_pop (active_list_t *list);
+
+int
+_active_list_contains (active_list_t *list, const char *identifier);
+
+static void
+_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list);
+
+static void
+_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
+                                token_list_t *list);
+
+static void
+_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
+                                        token_list_t *list);
+
+static void
+_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
+                                 int condition);
+
+static void
+_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
+                                   const char *type, int condition);
+
+static void
+_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc);
+
+#define yylex glcpp_parser_lex
+
+static int
+glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser);
+
+static void
+glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list);
+
+static void
+add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
+
+
+
+/* Line 189 of yacc.c  */
+#line 223 "glcpp/glcpp-parse.c"
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     COMMA_FINAL = 258,
+     DEFINED = 259,
+     ELIF_EXPANDED = 260,
+     HASH = 261,
+     HASH_DEFINE_FUNC = 262,
+     HASH_DEFINE_OBJ = 263,
+     HASH_ELIF = 264,
+     HASH_ELSE = 265,
+     HASH_ENDIF = 266,
+     HASH_IF = 267,
+     HASH_IFDEF = 268,
+     HASH_IFNDEF = 269,
+     HASH_UNDEF = 270,
+     HASH_VERSION = 271,
+     IDENTIFIER = 272,
+     IF_EXPANDED = 273,
+     INTEGER = 274,
+     INTEGER_STRING = 275,
+     NEWLINE = 276,
+     OTHER = 277,
+     PLACEHOLDER = 278,
+     SPACE = 279,
+     PASTE = 280,
+     OR = 281,
+     AND = 282,
+     NOT_EQUAL = 283,
+     EQUAL = 284,
+     GREATER_OR_EQUAL = 285,
+     LESS_OR_EQUAL = 286,
+     RIGHT_SHIFT = 287,
+     LEFT_SHIFT = 288,
+     UNARY = 289
+   };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 264 of yacc.c  */
+#line 311 "glcpp/glcpp-parse.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+    int yyi;
+#endif
+{
+  return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+            && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+        || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+            && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+  YYLTYPE yyls_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+      + 2 * YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)             \
+      do                                       \
+       {                                       \
+         YYSIZE_T yyi;                         \
+         for (yyi = 0; yyi < (Count); yyi++)   \
+           (To)[yyi] = (From)[yyi];            \
+       }                                       \
+      while (YYID (0))
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                          \
+    do                                                                 \
+      {                                                                        \
+       YYSIZE_T yynewbytes;                                            \
+       YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+       Stack = &yyptr->Stack_alloc;                                    \
+       yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+       yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                        \
+    while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  2
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   606
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  57
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  17
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  101
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  162
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   289
+
+#define YYTRANSLATE(YYX)                                               \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,    47,     2,     2,     2,    43,    30,     2,
+      45,    46,    41,    39,    49,    40,    54,    42,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,    55,
+      33,    56,    34,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,    50,     2,    51,    29,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,    52,    28,    53,    48,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    31,    32,    35,    36,    37,    38,    44
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const yytype_uint16 yyprhs[] =
+{
+       0,     0,     3,     4,     7,     9,    11,    13,    16,    20,
+      24,    29,    36,    44,    48,    52,    55,    60,    65,    69,
+      72,    75,    78,    82,    85,    87,    89,    91,    95,    99,
+     103,   107,   111,   115,   119,   123,   127,   131,   135,   139,
+     143,   147,   151,   155,   159,   163,   166,   169,   172,   175,
+     179,   181,   185,   187,   190,   193,   194,   196,   197,   199,
+     202,   207,   209,   211,   214,   216,   219,   221,   223,   225,
+     227,   229,   231,   233,   235,   237,   239,   241,   243,   245,
+     247,   249,   251,   253,   255,   257,   259,   261,   263,   265,
+     267,   269,   271,   273,   275,   277,   279,   281,   283,   285,
+     287,   289
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const yytype_int8 yyrhs[] =
+{
+      58,     0,    -1,    -1,    58,    59,    -1,    61,    -1,    65,
+      -1,    60,    -1,     6,    66,    -1,    18,    63,    21,    -1,
+       5,    63,    21,    -1,     8,    17,    67,    21,    -1,     7,
+      17,    45,    46,    67,    21,    -1,     7,    17,    45,    64,
+      46,    67,    21,    -1,    15,    17,    21,    -1,    12,    70,
+      21,    -1,    12,    21,    -1,    13,    17,    68,    21,    -1,
+      14,    17,    68,    21,    -1,     9,    70,    21,    -1,     9,
+      21,    -1,    10,    21,    -1,    11,    21,    -1,    16,    62,
+      21,    -1,     6,    21,    -1,    20,    -1,    19,    -1,    62,
+      -1,    63,    26,    63,    -1,    63,    27,    63,    -1,    63,
+      28,    63,    -1,    63,    29,    63,    -1,    63,    30,    63,
+      -1,    63,    31,    63,    -1,    63,    32,    63,    -1,    63,
+      35,    63,    -1,    63,    36,    63,    -1,    63,    34,    63,
+      -1,    63,    33,    63,    -1,    63,    37,    63,    -1,    63,
+      38,    63,    -1,    63,    40,    63,    -1,    63,    39,    63,
+      -1,    63,    43,    63,    -1,    63,    42,    63,    -1,    63,
+      41,    63,    -1,    47,    63,    -1,    48,    63,    -1,    40,
+      63,    -1,    39,    63,    -1,    45,    63,    46,    -1,    17,
+      -1,    64,    49,    17,    -1,    21,    -1,    71,    21,    -1,
+      71,    21,    -1,    -1,    71,    -1,    -1,    71,    -1,     4,
+      17,    -1,     4,    45,    17,    46,    -1,    72,    -1,    69,
+      -1,    70,    69,    -1,    72,    -1,    71,    72,    -1,    17,
+      -1,    20,    -1,    73,    -1,    22,    -1,    24,    -1,    50,
+      -1,    51,    -1,    45,    -1,    46,    -1,    52,    -1,    53,
+      -1,    54,    -1,    30,    -1,    41,    -1,    39,    -1,    40,
+      -1,    48,    -1,    47,    -1,    42,    -1,    43,    -1,    38,
+      -1,    37,    -1,    33,    -1,    34,    -1,    36,    -1,    35,
+      -1,    32,    -1,    31,    -1,    29,    -1,    28,    -1,    27,
+      -1,    26,    -1,    55,    -1,    49,    -1,    56,    -1,    25,
+      -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,   187,   187,   189,   193,   196,   201,   202,   206,   209,
+     215,   218,   221,   224,   232,   251,   261,   266,   271,   290,
+     305,   308,   311,   320,   324,   333,   338,   339,   342,   345,
+     348,   351,   354,   357,   360,   363,   366,   369,   372,   375,
+     378,   381,   384,   387,   390,   393,   396,   399,   402,   405,
+     411,   416,   424,   425,   429,   435,   436,   439,   441,   448,
+     452,   456,   461,   467,   475,   481,   489,   493,   497,   501,
+     505,   512,   513,   514,   515,   516,   517,   518,   519,   520,
+     521,   522,   523,   524,   525,   526,   527,   528,   529,   530,
+     531,   532,   533,   534,   535,   536,   537,   538,   539,   540,
+     541,   542
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "COMMA_FINAL", "DEFINED",
+  "ELIF_EXPANDED", "HASH", "HASH_DEFINE_FUNC", "HASH_DEFINE_OBJ",
+  "HASH_ELIF", "HASH_ELSE", "HASH_ENDIF", "HASH_IF", "HASH_IFDEF",
+  "HASH_IFNDEF", "HASH_UNDEF", "HASH_VERSION", "IDENTIFIER", "IF_EXPANDED",
+  "INTEGER", "INTEGER_STRING", "NEWLINE", "OTHER", "PLACEHOLDER", "SPACE",
+  "PASTE", "OR", "AND", "'|'", "'^'", "'&'", "NOT_EQUAL", "EQUAL", "'<'",
+  "'>'", "GREATER_OR_EQUAL", "LESS_OR_EQUAL", "RIGHT_SHIFT", "LEFT_SHIFT",
+  "'+'", "'-'", "'*'", "'/'", "'%'", "UNARY", "'('", "')'", "'!'", "'~'",
+  "','", "'['", "']'", "'{'", "'}'", "'.'", "';'", "'='", "$accept",
+  "input", "line", "expanded_line", "control_line", "integer_constant",
+  "expression", "identifier_list", "text_line", "non_directive",
+  "replacement_list", "junk", "conditional_token", "conditional_tokens",
+  "pp_tokens", "preprocessing_token", "operator", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   124,    94,
+      38,   283,   284,    60,    62,   285,   286,   287,   288,    43,
+      45,    42,    47,    37,   289,    40,    41,    33,   126,    44,
+      91,    93,   123,   125,    46,    59,    61
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    57,    58,    58,    59,    59,    59,    59,    60,    60,
+      61,    61,    61,    61,    61,    61,    61,    61,    61,    61,
+      61,    61,    61,    61,    62,    62,    63,    63,    63,    63,
+      63,    63,    63,    63,    63,    63,    63,    63,    63,    63,
+      63,    63,    63,    63,    63,    63,    63,    63,    63,    63,
+      64,    64,    65,    65,    66,    67,    67,    68,    68,    69,
+      69,    69,    70,    70,    71,    71,    72,    72,    72,    72,
+      72,    73,    73,    73,    73,    73,    73,    73,    73,    73,
+      73,    73,    73,    73,    73,    73,    73,    73,    73,    73,
+      73,    73,    73,    73,    73,    73,    73,    73,    73,    73,
+      73,    73
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     0,     2,     1,     1,     1,     2,     3,     3,
+       4,     6,     7,     3,     3,     2,     4,     4,     3,     2,
+       2,     2,     3,     2,     1,     1,     1,     3,     3,     3,
+       3,     3,     3,     3,     3,     3,     3,     3,     3,     3,
+       3,     3,     3,     3,     3,     2,     2,     2,     2,     3,
+       1,     3,     1,     2,     2,     0,     1,     0,     1,     2,
+       4,     1,     1,     2,     1,     2,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       2,     0,     1,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    66,     0,    67,    52,    69,
+      70,   101,    97,    96,    95,    94,    78,    93,    92,    88,
+      89,    91,    90,    87,    86,    80,    81,    79,    84,    85,
+      73,    74,    83,    82,    99,    71,    72,    75,    76,    77,
+      98,   100,     3,     6,     4,     5,     0,    64,    68,    25,
+      24,     0,     0,     0,     0,     0,    26,     0,    23,     7,
+       0,     0,    55,     0,    19,    62,     0,    61,    20,    21,
+      15,     0,    57,    57,     0,     0,     0,    53,    65,    48,
+      47,     0,    45,    46,     9,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    54,     0,     0,    56,    59,     0,    18,
+      63,    14,     0,    58,     0,    13,    22,     8,    49,    27,
+      28,    29,    30,    31,    32,    33,    37,    36,    34,    35,
+      38,    39,    41,    40,    44,    43,    42,    50,    55,     0,
+      10,     0,    16,    17,     0,    55,     0,    60,    11,     0,
+      51,    12
+};
+
+/* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int16 yydefgoto[] =
+{
+      -1,     1,    52,    53,    54,    66,    67,   149,    55,    69,
+     115,   122,    75,    76,   116,    57,    58
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -147
+static const yytype_int16 yypact[] =
+{
+    -147,   112,  -147,    28,   -10,    55,    62,   152,   -15,    59,
+     192,    85,    86,    87,    51,  -147,    28,  -147,  -147,  -147,
+    -147,  -147,  -147,  -147,  -147,  -147,  -147,  -147,  -147,  -147,
+    -147,  -147,  -147,  -147,  -147,  -147,  -147,  -147,  -147,  -147,
+    -147,  -147,  -147,  -147,  -147,  -147,  -147,  -147,  -147,  -147,
+    -147,  -147,  -147,  -147,  -147,  -147,   312,  -147,  -147,  -147,
+    -147,    28,    28,    28,    28,    28,  -147,   428,  -147,  -147,
+     352,    63,   392,    17,  -147,  -147,   232,  -147,  -147,  -147,
+    -147,   272,   392,   392,    84,    89,   451,  -147,  -147,  -147,
+    -147,   469,  -147,  -147,  -147,    28,    28,    28,    28,    28,
+      28,    28,    28,    28,    28,    28,    28,    28,    28,    28,
+      28,    28,    28,  -147,    60,    90,   392,  -147,    96,  -147,
+    -147,  -147,    93,   392,    94,  -147,  -147,  -147,  -147,   489,
+     505,   520,   534,   547,   558,   558,    18,    18,    18,    18,
+     563,   563,    23,    23,  -147,  -147,  -147,  -147,   392,    32,
+    -147,    61,  -147,  -147,   110,   392,   118,  -147,  -147,   149,
+    -147,  -147
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yytype_int16 yypgoto[] =
+{
+    -147,  -147,  -147,  -147,  -147,   157,   -11,  -147,  -147,  -147,
+    -146,    92,   -68,   200,     0,    -7,  -147
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+      77,    56,   154,    77,    70,    86,    78,    15,   120,   159,
+      17,    68,    19,   120,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
+      36,    37,    38,    39,   117,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    59,    60,    88,
+      89,    90,    91,    92,    93,   106,   107,   108,   109,   110,
+     111,   112,   118,    88,   110,   111,   112,    61,    62,    77,
+      59,    60,    71,    63,    77,    64,    65,   147,   155,    72,
+      79,   156,   123,   123,   129,   130,   131,   132,   133,   134,
+     135,   136,   137,   138,   139,   140,   141,   142,   143,   144,
+     145,   146,    82,    83,    84,   125,   148,   157,   114,    88,
+     126,   150,     2,   151,   152,   153,    88,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
+      16,   158,    17,    18,    19,   160,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,    73,    40,    41,    42,
+      43,    44,    45,    46,    47,    48,    49,    50,    51,    15,
+     161,    85,    17,    74,    19,   124,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,    73,    40,    41,    42,
+      43,    44,    45,    46,    47,    48,    49,    50,    51,    15,
+      81,     0,    17,    80,    19,     0,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,    73,    40,    41,    42,
+      43,    44,    45,    46,    47,    48,    49,    50,    51,    15,
+       0,     0,    17,   119,    19,     0,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,    73,    40,    41,    42,
+      43,    44,    45,    46,    47,    48,    49,    50,    51,    15,
+       0,     0,    17,   121,    19,     0,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,     0,    40,    41,    42,
+      43,    44,    45,    46,    47,    48,    49,    50,    51,    15,
+       0,     0,    17,    87,    19,     0,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,     0,    40,    41,    42,
+      43,    44,    45,    46,    47,    48,    49,    50,    51,    15,
+       0,     0,    17,   113,    19,     0,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,     0,    40,    41,    42,
+      43,    44,    45,    46,    47,    48,    49,    50,    51,    15,
+       0,     0,    17,     0,    19,     0,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,     0,    40,    41,    42,
+      43,    44,    45,    46,    47,    48,    49,    50,    51,    94,
+       0,     0,     0,     0,    95,    96,    97,    98,    99,   100,
+     101,   102,   103,   104,   105,   106,   107,   108,   109,   110,
+     111,   112,   127,     0,     0,     0,     0,    95,    96,    97,
+      98,    99,   100,   101,   102,   103,   104,   105,   106,   107,
+     108,   109,   110,   111,   112,    95,    96,    97,    98,    99,
+     100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
+     110,   111,   112,     0,     0,   128,    96,    97,    98,    99,
+     100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
+     110,   111,   112,    97,    98,    99,   100,   101,   102,   103,
+     104,   105,   106,   107,   108,   109,   110,   111,   112,    98,
+      99,   100,   101,   102,   103,   104,   105,   106,   107,   108,
+     109,   110,   111,   112,    99,   100,   101,   102,   103,   104,
+     105,   106,   107,   108,   109,   110,   111,   112,   100,   101,
+     102,   103,   104,   105,   106,   107,   108,   109,   110,   111,
+     112,   102,   103,   104,   105,   106,   107,   108,   109,   110,
+     111,   112,   108,   109,   110,   111,   112
+};
+
+static const yytype_int16 yycheck[] =
+{
+       7,     1,   148,    10,     4,    16,    21,    17,    76,   155,
+      20,    21,    22,    81,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
+      40,    41,    42,    43,    17,    45,    46,    47,    48,    49,
+      50,    51,    52,    53,    54,    55,    56,    19,    20,    56,
+      61,    62,    63,    64,    65,    37,    38,    39,    40,    41,
+      42,    43,    45,    70,    41,    42,    43,    39,    40,    76,
+      19,    20,    17,    45,    81,    47,    48,    17,    46,    17,
+      21,    49,    82,    83,    95,    96,    97,    98,    99,   100,
+     101,   102,   103,   104,   105,   106,   107,   108,   109,   110,
+     111,   112,    17,    17,    17,    21,    46,    46,    45,   116,
+      21,    21,     0,    17,    21,    21,   123,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
+      18,    21,    20,    21,    22,    17,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,     4,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    17,
+      21,    14,    20,    21,    22,    83,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,     4,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    17,
+      10,    -1,    20,    21,    22,    -1,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,     4,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    17,
+      -1,    -1,    20,    21,    22,    -1,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,     4,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    17,
+      -1,    -1,    20,    21,    22,    -1,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    -1,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    17,
+      -1,    -1,    20,    21,    22,    -1,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    -1,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    17,
+      -1,    -1,    20,    21,    22,    -1,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    -1,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    17,
+      -1,    -1,    20,    -1,    22,    -1,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    -1,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    21,
+      -1,    -1,    -1,    -1,    26,    27,    28,    29,    30,    31,
+      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
+      42,    43,    21,    -1,    -1,    -1,    -1,    26,    27,    28,
+      29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
+      39,    40,    41,    42,    43,    26,    27,    28,    29,    30,
+      31,    32,    33,    34,    35,    36,    37,    38,    39,    40,
+      41,    42,    43,    -1,    -1,    46,    27,    28,    29,    30,
+      31,    32,    33,    34,    35,    36,    37,    38,    39,    40,
+      41,    42,    43,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    29,
+      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
+      40,    41,    42,    43,    30,    31,    32,    33,    34,    35,
+      36,    37,    38,    39,    40,    41,    42,    43,    31,    32,
+      33,    34,    35,    36,    37,    38,    39,    40,    41,    42,
+      43,    33,    34,    35,    36,    37,    38,    39,    40,    41,
+      42,    43,    39,    40,    41,    42,    43
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,    58,     0,     5,     6,     7,     8,     9,    10,    11,
+      12,    13,    14,    15,    16,    17,    18,    20,    21,    22,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    59,    60,    61,    65,    71,    72,    73,    19,
+      20,    39,    40,    45,    47,    48,    62,    63,    21,    66,
+      71,    17,    17,     4,    21,    69,    70,    72,    21,    21,
+      21,    70,    17,    17,    17,    62,    63,    21,    72,    63,
+      63,    63,    63,    63,    21,    26,    27,    28,    29,    30,
+      31,    32,    33,    34,    35,    36,    37,    38,    39,    40,
+      41,    42,    43,    21,    45,    67,    71,    17,    45,    21,
+      69,    21,    68,    71,    68,    21,    21,    21,    46,    63,
+      63,    63,    63,    63,    63,    63,    63,    63,    63,    63,
+      63,    63,    63,    63,    63,    63,    63,    17,    46,    64,
+      21,    17,    21,    21,    67,    46,    49,    46,    21,    67,
+      17,    21
+};
+
+#define yyerrok                (yyerrstatus = 0)
+#define yyclearin      (yychar = YYEMPTY)
+#define YYEMPTY                (-2)
+#define YYEOF          0
+
+#define YYACCEPT       goto yyacceptlab
+#define YYABORT                goto yyabortlab
+#define YYERROR                goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL         goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                 \
+do                                                             \
+  if (yychar == YYEMPTY && yylen == 1)                         \
+    {                                                          \
+      yychar = (Token);                                                \
+      yylval = (Value);                                                \
+      yytoken = YYTRANSLATE (yychar);                          \
+      YYPOPSTACK (1);                                          \
+      goto yybackup;                                           \
+    }                                                          \
+  else                                                         \
+    {                                                          \
+      yyerror (&yylloc, parser, YY_("syntax error: cannot back up")); \
+      YYERROR;                                                 \
+    }                                                          \
+while (YYID (0))
+
+
+#define YYTERROR       1
+#define YYERRCODE      256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)                               \
+    do                                                                 \
+      if (YYID (N))                                                    \
+       {                                                               \
+         (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
+         (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
+         (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
+         (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
+       }                                                               \
+      else                                                             \
+       {                                                               \
+         (Current).first_line   = (Current).last_line   =              \
+           YYRHSLOC (Rhs, 0).last_line;                                \
+         (Current).first_column = (Current).last_column =              \
+           YYRHSLOC (Rhs, 0).last_column;                              \
+       }                                                               \
+    while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)                 \
+     fprintf (File, "%d.%d-%d.%d",                     \
+             (Loc).first_line, (Loc).first_column,     \
+             (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval, &yylloc, parser)
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                       \
+do {                                           \
+  if (yydebug)                                 \
+    YYFPRINTF Args;                            \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                   \
+do {                                                                     \
+  if (yydebug)                                                           \
+    {                                                                    \
+      YYFPRINTF (stderr, "%s ", Title);                                          \
+      yy_symbol_print (stderr,                                           \
+                 Type, Value, Location, parser); \
+      YYFPRINTF (stderr, "\n");                                                  \
+    }                                                                    \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, glcpp_parser_t *parser)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, parser)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    YYLTYPE const * const yylocationp;
+    glcpp_parser_t *parser;
+#endif
+{
+  if (!yyvaluep)
+    return;
+  YYUSE (yylocationp);
+  YYUSE (parser);
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+       break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, glcpp_parser_t *parser)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, parser)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    YYLTYPE const * const yylocationp;
+    glcpp_parser_t *parser;
+#endif
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  YY_LOCATION_PRINT (yyoutput, *yylocationp);
+  YYFPRINTF (yyoutput, ": ");
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, parser);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+    yytype_int16 *yybottom;
+    yytype_int16 *yytop;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                           \
+do {                                                           \
+  if (yydebug)                                                 \
+    yy_stack_print ((Bottom), (Top));                          \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, glcpp_parser_t *parser)
+#else
+static void
+yy_reduce_print (yyvsp, yylsp, yyrule, parser)
+    YYSTYPE *yyvsp;
+    YYLTYPE *yylsp;
+    int yyrule;
+    glcpp_parser_t *parser;
+#endif
+{
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+            yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+                      &(yyvsp[(yyi + 1) - (yynrhs)])
+                      , &(yylsp[(yyi + 1) - (yynrhs)])                , parser);
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)         \
+do {                                   \
+  if (yydebug)                         \
+    yy_reduce_print (yyvsp, yylsp, Rule, parser); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef        YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+\f
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+    const char *yystr;
+#endif
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+    char *yydest;
+    const char *yysrc;
+#endif
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+       switch (*++yyp)
+         {
+         case '\'':
+         case ',':
+           goto do_not_strip_quotes;
+
+         case '\\':
+           if (*++yyp != '\\')
+             goto do_not_strip_quotes;
+           /* Fall through.  */
+         default:
+           if (yyres)
+             yyres[yyn] = *yyp;
+           yyn++;
+           break;
+
+         case '"':
+           if (yyres)
+             yyres[yyn] = '\0';
+           return yyn;
+         }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+  int yyn = yypact[yystate];
+
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+        constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+                   + sizeof yyexpecting - 1
+                   + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+                      * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+        YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+       if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+         {
+           if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+             {
+               yycount = 1;
+               yysize = yysize0;
+               yyformat[sizeof yyunexpected - 1] = '\0';
+               break;
+             }
+           yyarg[yycount++] = yytname[yyx];
+           yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+           yysize_overflow |= (yysize1 < yysize);
+           yysize = yysize1;
+           yyfmt = yystpcpy (yyfmt, yyprefix);
+           yyprefix = yyor;
+         }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+       return YYSIZE_MAXIMUM;
+
+      if (yyresult)
+       {
+         /* Avoid sprintf, as that infringes on the user's name space.
+            Don't have undefined behavior even if the translation
+            produced a string with the wrong number of "%s"s.  */
+         char *yyp = yyresult;
+         int yyi = 0;
+         while ((*yyp = *yyf) != '\0')
+           {
+             if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+               {
+                 yyp += yytnamerr (yyp, yyarg[yyi++]);
+                 yyf += 2;
+               }
+             else
+               {
+                 yyp++;
+                 yyf++;
+               }
+           }
+       }
+      return yysize;
+    }
+}
+#endif /* YYERROR_VERBOSE */
+\f
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, glcpp_parser_t *parser)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, yylocationp, parser)
+    const char *yymsg;
+    int yytype;
+    YYSTYPE *yyvaluep;
+    YYLTYPE *yylocationp;
+    glcpp_parser_t *parser;
+#endif
+{
+  YYUSE (yyvaluep);
+  YYUSE (yylocationp);
+  YYUSE (parser);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+
+      default:
+       break;
+    }
+}
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (glcpp_parser_t *parser);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse.  |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+    void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (glcpp_parser_t *parser)
+#else
+int
+yyparse (parser)
+    glcpp_parser_t *parser;
+#endif
+#endif
+{
+/* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+
+/* Location data for the lookahead symbol.  */
+YYLTYPE yylloc;
+
+    /* Number of syntax errors so far.  */
+    int yynerrs;
+
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       `yyss': related to states.
+       `yyvs': related to semantic values.
+       `yyls': related to locations.
+
+       Refer to the stacks thru separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    /* The location stack.  */
+    YYLTYPE yylsa[YYINITDEPTH];
+    YYLTYPE *yyls;
+    YYLTYPE *yylsp;
+
+    /* The locations where the error started and ended.  */
+    YYLTYPE yyerror_range[2];
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+  YYLTYPE yyloc;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yytoken = 0;
+  yyss = yyssa;
+  yyvs = yyvsa;
+  yyls = yylsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+  yyssp = yyss;
+  yyvsp = yyvs;
+  yylsp = yyls;
+
+#if YYLTYPE_IS_TRIVIAL
+  /* Initialize the default location before parsing starts.  */
+  yylloc.first_line   = yylloc.last_line   = 1;
+  yylloc.first_column = yylloc.last_column = 1;
+#endif
+
+/* User initialization code.  */
+
+/* Line 1242 of yacc.c  */
+#line 154 "glcpp/glcpp-parse.y"
+{
+       yylloc.first_line = 1;
+       yylloc.first_column = 1;
+       yylloc.last_line = 1;
+       yylloc.last_column = 1;
+       yylloc.source = 0;
+}
+
+/* Line 1242 of yacc.c  */
+#line 1616 "glcpp/glcpp-parse.c"
+  yylsp[0] = yylloc;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+       /* Give user a chance to reallocate the stack.  Use copies of
+          these so that the &'s don't force the real ones into
+          memory.  */
+       YYSTYPE *yyvs1 = yyvs;
+       yytype_int16 *yyss1 = yyss;
+       YYLTYPE *yyls1 = yyls;
+
+       /* Each stack pointer address is followed by the size of the
+          data in use in that stack, in bytes.  This used to be a
+          conditional around just the two extra args, but that might
+          be undefined if yyoverflow is a macro.  */
+       yyoverflow (YY_("memory exhausted"),
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+                   &yyls1, yysize * sizeof (*yylsp),
+                   &yystacksize);
+
+       yyls = yyls1;
+       yyss = yyss1;
+       yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+       goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+       yystacksize = YYMAXDEPTH;
+
+      {
+       yytype_int16 *yyss1 = yyss;
+       union yyalloc *yyptr =
+         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+       if (! yyptr)
+         goto yyexhaustedlab;
+       YYSTACK_RELOCATE (yyss_alloc, yyss);
+       YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+       YYSTACK_RELOCATE (yyls_alloc, yyls);
+#  undef YYSTACK_RELOCATE
+       if (yyss1 != yyssa)
+         YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+      yylsp = yyls + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                 (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+       YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+       goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  *++yyvsp = yylval;
+  *++yylsp = yylloc;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+  /* Default location.  */
+  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 4:
+
+/* Line 1455 of yacc.c  */
+#line 193 "glcpp/glcpp-parse.y"
+    {
+               glcpp_print(parser->output, "\n");
+       ;}
+    break;
+
+  case 5:
+
+/* Line 1455 of yacc.c  */
+#line 196 "glcpp/glcpp-parse.y"
+    {
+               _glcpp_parser_print_expanded_token_list (parser, (yyvsp[(1) - (1)].token_list));
+               glcpp_print(parser->output, "\n");
+               talloc_free ((yyvsp[(1) - (1)].token_list));
+       ;}
+    break;
+
+  case 8:
+
+/* Line 1455 of yacc.c  */
+#line 206 "glcpp/glcpp-parse.y"
+    {
+               _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (3)]), (yyvsp[(2) - (3)].ival));
+       ;}
+    break;
+
+  case 9:
+
+/* Line 1455 of yacc.c  */
+#line 209 "glcpp/glcpp-parse.y"
+    {
+               _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (3)]), "elif", (yyvsp[(2) - (3)].ival));
+       ;}
+    break;
+
+  case 10:
+
+/* Line 1455 of yacc.c  */
+#line 215 "glcpp/glcpp-parse.y"
+    {
+               _define_object_macro (parser, & (yylsp[(2) - (4)]), (yyvsp[(2) - (4)].str), (yyvsp[(3) - (4)].token_list));
+       ;}
+    break;
+
+  case 11:
+
+/* Line 1455 of yacc.c  */
+#line 218 "glcpp/glcpp-parse.y"
+    {
+               _define_function_macro (parser, & (yylsp[(2) - (6)]), (yyvsp[(2) - (6)].str), NULL, (yyvsp[(5) - (6)].token_list));
+       ;}
+    break;
+
+  case 12:
+
+/* Line 1455 of yacc.c  */
+#line 221 "glcpp/glcpp-parse.y"
+    {
+               _define_function_macro (parser, & (yylsp[(2) - (7)]), (yyvsp[(2) - (7)].str), (yyvsp[(4) - (7)].string_list), (yyvsp[(6) - (7)].token_list));
+       ;}
+    break;
+
+  case 13:
+
+/* Line 1455 of yacc.c  */
+#line 224 "glcpp/glcpp-parse.y"
+    {
+               macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (3)].str));
+               if (macro) {
+                       hash_table_remove (parser->defines, (yyvsp[(2) - (3)].str));
+                       talloc_free (macro);
+               }
+               talloc_free ((yyvsp[(2) - (3)].str));
+       ;}
+    break;
+
+  case 14:
+
+/* Line 1455 of yacc.c  */
+#line 232 "glcpp/glcpp-parse.y"
+    {
+               /* Be careful to only evaluate the 'if' expression if
+                * we are not skipping. When we are skipping, we
+                * simply push a new 0-valued 'if' onto the skip
+                * stack.
+                *
+                * This avoids generating diagnostics for invalid
+                * expressions that are being skipped. */
+               if (parser->skip_stack == NULL ||
+                   parser->skip_stack->type == SKIP_NO_SKIP)
+               {
+                       _glcpp_parser_expand_if (parser, IF_EXPANDED, (yyvsp[(2) - (3)].token_list));
+               }       
+               else
+               {
+                       _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (3)]), 0);
+                       parser->skip_stack->type = SKIP_TO_ENDIF;
+               }
+       ;}
+    break;
+
+  case 15:
+
+/* Line 1455 of yacc.c  */
+#line 251 "glcpp/glcpp-parse.y"
+    {
+               /* #if without an expression is only an error if we
+                *  are not skipping */
+               if (parser->skip_stack == NULL ||
+                   parser->skip_stack->type == SKIP_NO_SKIP)
+               {
+                       glcpp_error(& (yylsp[(1) - (2)]), parser, "#if with no expression");
+               }       
+               _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (2)]), 0);
+       ;}
+    break;
+
+  case 16:
+
+/* Line 1455 of yacc.c  */
+#line 261 "glcpp/glcpp-parse.y"
+    {
+               macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (4)].str));
+               talloc_free ((yyvsp[(2) - (4)].str));
+               _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (4)]), macro != NULL);
+       ;}
+    break;
+
+  case 17:
+
+/* Line 1455 of yacc.c  */
+#line 266 "glcpp/glcpp-parse.y"
+    {
+               macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (4)].str));
+               talloc_free ((yyvsp[(2) - (4)].str));
+               _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (4)]), macro == NULL);
+       ;}
+    break;
+
+  case 18:
+
+/* Line 1455 of yacc.c  */
+#line 271 "glcpp/glcpp-parse.y"
+    {
+               /* Be careful to only evaluate the 'elif' expression
+                * if we are not skipping. When we are skipping, we
+                * simply change to a 0-valued 'elif' on the skip
+                * stack.
+                *
+                * This avoids generating diagnostics for invalid
+                * expressions that are being skipped. */
+               if (parser->skip_stack &&
+                   parser->skip_stack->type == SKIP_TO_ELSE)
+               {
+                       _glcpp_parser_expand_if (parser, ELIF_EXPANDED, (yyvsp[(2) - (3)].token_list));
+               }
+               else
+               {
+                       _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (3)]),
+                                                           "elif", 0);
+               }
+       ;}
+    break;
+
+  case 19:
+
+/* Line 1455 of yacc.c  */
+#line 290 "glcpp/glcpp-parse.y"
+    {
+               /* #elif without an expression is an error unless we
+                * are skipping. */
+               if (parser->skip_stack &&
+                   parser->skip_stack->type == SKIP_TO_ELSE)
+               {
+                       glcpp_error(& (yylsp[(1) - (2)]), parser, "#elif with no expression");
+               }
+               else
+               {
+                       _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (2)]),
+                                                           "elif", 0);
+                       glcpp_warning(& (yylsp[(1) - (2)]), parser, "ignoring illegal #elif without expression");
+               }
+       ;}
+    break;
+
+  case 20:
+
+/* Line 1455 of yacc.c  */
+#line 305 "glcpp/glcpp-parse.y"
+    {
+               _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (2)]), "else", 1);
+       ;}
+    break;
+
+  case 21:
+
+/* Line 1455 of yacc.c  */
+#line 308 "glcpp/glcpp-parse.y"
+    {
+               _glcpp_parser_skip_stack_pop (parser, & (yylsp[(1) - (2)]));
+       ;}
+    break;
+
+  case 22:
+
+/* Line 1455 of yacc.c  */
+#line 311 "glcpp/glcpp-parse.y"
+    {
+               macro_t *macro = hash_table_find (parser->defines, "__VERSION__");
+               if (macro) {
+                       hash_table_remove (parser->defines, "__VERSION__");
+                       talloc_free (macro);
+               }
+               add_builtin_define (parser, "__VERSION__", (yyvsp[(2) - (3)].ival));
+               glcpp_printf(parser->output, "#version %" PRIiMAX, (yyvsp[(2) - (3)].ival));
+       ;}
+    break;
+
+  case 24:
+
+/* Line 1455 of yacc.c  */
+#line 324 "glcpp/glcpp-parse.y"
+    {
+               if (strlen ((yyvsp[(1) - (1)].str)) >= 3 && strncmp ((yyvsp[(1) - (1)].str), "0x", 2) == 0) {
+                       (yyval.ival) = strtoll ((yyvsp[(1) - (1)].str) + 2, NULL, 16);
+               } else if ((yyvsp[(1) - (1)].str)[0] == '0') {
+                       (yyval.ival) = strtoll ((yyvsp[(1) - (1)].str), NULL, 8);
+               } else {
+                       (yyval.ival) = strtoll ((yyvsp[(1) - (1)].str), NULL, 10);
+               }
+       ;}
+    break;
+
+  case 25:
+
+/* Line 1455 of yacc.c  */
+#line 333 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (1)].ival);
+       ;}
+    break;
+
+  case 27:
+
+/* Line 1455 of yacc.c  */
+#line 339 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) || (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 28:
+
+/* Line 1455 of yacc.c  */
+#line 342 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) && (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 29:
+
+/* Line 1455 of yacc.c  */
+#line 345 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) | (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 30:
+
+/* Line 1455 of yacc.c  */
+#line 348 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) ^ (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 31:
+
+/* Line 1455 of yacc.c  */
+#line 351 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) & (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 32:
+
+/* Line 1455 of yacc.c  */
+#line 354 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) != (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 33:
+
+/* Line 1455 of yacc.c  */
+#line 357 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) == (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 34:
+
+/* Line 1455 of yacc.c  */
+#line 360 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) >= (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 35:
+
+/* Line 1455 of yacc.c  */
+#line 363 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) <= (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 36:
+
+/* Line 1455 of yacc.c  */
+#line 366 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) > (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 37:
+
+/* Line 1455 of yacc.c  */
+#line 369 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) < (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 38:
+
+/* Line 1455 of yacc.c  */
+#line 372 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) >> (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 39:
+
+/* Line 1455 of yacc.c  */
+#line 375 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) << (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 40:
+
+/* Line 1455 of yacc.c  */
+#line 378 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) - (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 41:
+
+/* Line 1455 of yacc.c  */
+#line 381 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) + (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 42:
+
+/* Line 1455 of yacc.c  */
+#line 384 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) % (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 43:
+
+/* Line 1455 of yacc.c  */
+#line 387 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) / (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 44:
+
+/* Line 1455 of yacc.c  */
+#line 390 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(1) - (3)].ival) * (yyvsp[(3) - (3)].ival);
+       ;}
+    break;
+
+  case 45:
+
+/* Line 1455 of yacc.c  */
+#line 393 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = ! (yyvsp[(2) - (2)].ival);
+       ;}
+    break;
+
+  case 46:
+
+/* Line 1455 of yacc.c  */
+#line 396 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = ~ (yyvsp[(2) - (2)].ival);
+       ;}
+    break;
+
+  case 47:
+
+/* Line 1455 of yacc.c  */
+#line 399 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = - (yyvsp[(2) - (2)].ival);
+       ;}
+    break;
+
+  case 48:
+
+/* Line 1455 of yacc.c  */
+#line 402 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = + (yyvsp[(2) - (2)].ival);
+       ;}
+    break;
+
+  case 49:
+
+/* Line 1455 of yacc.c  */
+#line 405 "glcpp/glcpp-parse.y"
+    {
+               (yyval.ival) = (yyvsp[(2) - (3)].ival);
+       ;}
+    break;
+
+  case 50:
+
+/* Line 1455 of yacc.c  */
+#line 411 "glcpp/glcpp-parse.y"
+    {
+               (yyval.string_list) = _string_list_create (parser);
+               _string_list_append_item ((yyval.string_list), (yyvsp[(1) - (1)].str));
+               talloc_steal ((yyval.string_list), (yyvsp[(1) - (1)].str));
+       ;}
+    break;
+
+  case 51:
+
+/* Line 1455 of yacc.c  */
+#line 416 "glcpp/glcpp-parse.y"
+    {
+               (yyval.string_list) = (yyvsp[(1) - (3)].string_list);   
+               _string_list_append_item ((yyval.string_list), (yyvsp[(3) - (3)].str));
+               talloc_steal ((yyval.string_list), (yyvsp[(3) - (3)].str));
+       ;}
+    break;
+
+  case 52:
+
+/* Line 1455 of yacc.c  */
+#line 424 "glcpp/glcpp-parse.y"
+    { (yyval.token_list) = NULL; ;}
+    break;
+
+  case 54:
+
+/* Line 1455 of yacc.c  */
+#line 429 "glcpp/glcpp-parse.y"
+    {
+               yyerror (& (yylsp[(1) - (2)]), parser, "Invalid tokens after #");
+       ;}
+    break;
+
+  case 55:
+
+/* Line 1455 of yacc.c  */
+#line 435 "glcpp/glcpp-parse.y"
+    { (yyval.token_list) = NULL; ;}
+    break;
+
+  case 58:
+
+/* Line 1455 of yacc.c  */
+#line 441 "glcpp/glcpp-parse.y"
+    {
+               glcpp_warning(&(yylsp[(1) - (1)]), parser, "extra tokens at end of directive");
+       ;}
+    break;
+
+  case 59:
+
+/* Line 1455 of yacc.c  */
+#line 448 "glcpp/glcpp-parse.y"
+    {
+               int v = hash_table_find (parser->defines, (yyvsp[(2) - (2)].str)) ? 1 : 0;
+               (yyval.token) = _token_create_ival (parser, INTEGER, v);
+       ;}
+    break;
+
+  case 60:
+
+/* Line 1455 of yacc.c  */
+#line 452 "glcpp/glcpp-parse.y"
+    {
+               int v = hash_table_find (parser->defines, (yyvsp[(3) - (4)].str)) ? 1 : 0;
+               (yyval.token) = _token_create_ival (parser, INTEGER, v);
+       ;}
+    break;
+
+  case 62:
+
+/* Line 1455 of yacc.c  */
+#line 461 "glcpp/glcpp-parse.y"
+    {
+               parser->space_tokens = 1;
+               (yyval.token_list) = _token_list_create (parser);
+               _token_list_append ((yyval.token_list), (yyvsp[(1) - (1)].token));
+               talloc_unlink (parser, (yyvsp[(1) - (1)].token));
+       ;}
+    break;
+
+  case 63:
+
+/* Line 1455 of yacc.c  */
+#line 467 "glcpp/glcpp-parse.y"
+    {
+               (yyval.token_list) = (yyvsp[(1) - (2)].token_list);
+               _token_list_append ((yyval.token_list), (yyvsp[(2) - (2)].token));
+               talloc_unlink (parser, (yyvsp[(2) - (2)].token));
+       ;}
+    break;
+
+  case 64:
+
+/* Line 1455 of yacc.c  */
+#line 475 "glcpp/glcpp-parse.y"
+    {
+               parser->space_tokens = 1;
+               (yyval.token_list) = _token_list_create (parser);
+               _token_list_append ((yyval.token_list), (yyvsp[(1) - (1)].token));
+               talloc_unlink (parser, (yyvsp[(1) - (1)].token));
+       ;}
+    break;
+
+  case 65:
+
+/* Line 1455 of yacc.c  */
+#line 481 "glcpp/glcpp-parse.y"
+    {
+               (yyval.token_list) = (yyvsp[(1) - (2)].token_list);
+               _token_list_append ((yyval.token_list), (yyvsp[(2) - (2)].token));
+               talloc_unlink (parser, (yyvsp[(2) - (2)].token));
+       ;}
+    break;
+
+  case 66:
+
+/* Line 1455 of yacc.c  */
+#line 489 "glcpp/glcpp-parse.y"
+    {
+               (yyval.token) = _token_create_str (parser, IDENTIFIER, (yyvsp[(1) - (1)].str));
+               (yyval.token)->location = yylloc;
+       ;}
+    break;
+
+  case 67:
+
+/* Line 1455 of yacc.c  */
+#line 493 "glcpp/glcpp-parse.y"
+    {
+               (yyval.token) = _token_create_str (parser, INTEGER_STRING, (yyvsp[(1) - (1)].str));
+               (yyval.token)->location = yylloc;
+       ;}
+    break;
+
+  case 68:
+
+/* Line 1455 of yacc.c  */
+#line 497 "glcpp/glcpp-parse.y"
+    {
+               (yyval.token) = _token_create_ival (parser, (yyvsp[(1) - (1)].ival), (yyvsp[(1) - (1)].ival));
+               (yyval.token)->location = yylloc;
+       ;}
+    break;
+
+  case 69:
+
+/* Line 1455 of yacc.c  */
+#line 501 "glcpp/glcpp-parse.y"
+    {
+               (yyval.token) = _token_create_str (parser, OTHER, (yyvsp[(1) - (1)].str));
+               (yyval.token)->location = yylloc;
+       ;}
+    break;
+
+  case 70:
+
+/* Line 1455 of yacc.c  */
+#line 505 "glcpp/glcpp-parse.y"
+    {
+               (yyval.token) = _token_create_ival (parser, SPACE, SPACE);
+               (yyval.token)->location = yylloc;
+       ;}
+    break;
+
+  case 71:
+
+/* Line 1455 of yacc.c  */
+#line 512 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '['; ;}
+    break;
+
+  case 72:
+
+/* Line 1455 of yacc.c  */
+#line 513 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = ']'; ;}
+    break;
+
+  case 73:
+
+/* Line 1455 of yacc.c  */
+#line 514 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '('; ;}
+    break;
+
+  case 74:
+
+/* Line 1455 of yacc.c  */
+#line 515 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = ')'; ;}
+    break;
+
+  case 75:
+
+/* Line 1455 of yacc.c  */
+#line 516 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '{'; ;}
+    break;
+
+  case 76:
+
+/* Line 1455 of yacc.c  */
+#line 517 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '}'; ;}
+    break;
+
+  case 77:
+
+/* Line 1455 of yacc.c  */
+#line 518 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '.'; ;}
+    break;
+
+  case 78:
+
+/* Line 1455 of yacc.c  */
+#line 519 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '&'; ;}
+    break;
+
+  case 79:
+
+/* Line 1455 of yacc.c  */
+#line 520 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '*'; ;}
+    break;
+
+  case 80:
+
+/* Line 1455 of yacc.c  */
+#line 521 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '+'; ;}
+    break;
+
+  case 81:
+
+/* Line 1455 of yacc.c  */
+#line 522 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '-'; ;}
+    break;
+
+  case 82:
+
+/* Line 1455 of yacc.c  */
+#line 523 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '~'; ;}
+    break;
+
+  case 83:
+
+/* Line 1455 of yacc.c  */
+#line 524 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '!'; ;}
+    break;
+
+  case 84:
+
+/* Line 1455 of yacc.c  */
+#line 525 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '/'; ;}
+    break;
+
+  case 85:
+
+/* Line 1455 of yacc.c  */
+#line 526 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '%'; ;}
+    break;
+
+  case 86:
+
+/* Line 1455 of yacc.c  */
+#line 527 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = LEFT_SHIFT; ;}
+    break;
+
+  case 87:
+
+/* Line 1455 of yacc.c  */
+#line 528 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = RIGHT_SHIFT; ;}
+    break;
+
+  case 88:
+
+/* Line 1455 of yacc.c  */
+#line 529 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '<'; ;}
+    break;
+
+  case 89:
+
+/* Line 1455 of yacc.c  */
+#line 530 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '>'; ;}
+    break;
+
+  case 90:
+
+/* Line 1455 of yacc.c  */
+#line 531 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = LESS_OR_EQUAL; ;}
+    break;
+
+  case 91:
+
+/* Line 1455 of yacc.c  */
+#line 532 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = GREATER_OR_EQUAL; ;}
+    break;
+
+  case 92:
+
+/* Line 1455 of yacc.c  */
+#line 533 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = EQUAL; ;}
+    break;
+
+  case 93:
+
+/* Line 1455 of yacc.c  */
+#line 534 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = NOT_EQUAL; ;}
+    break;
+
+  case 94:
+
+/* Line 1455 of yacc.c  */
+#line 535 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '^'; ;}
+    break;
+
+  case 95:
+
+/* Line 1455 of yacc.c  */
+#line 536 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '|'; ;}
+    break;
+
+  case 96:
+
+/* Line 1455 of yacc.c  */
+#line 537 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = AND; ;}
+    break;
+
+  case 97:
+
+/* Line 1455 of yacc.c  */
+#line 538 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = OR; ;}
+    break;
+
+  case 98:
+
+/* Line 1455 of yacc.c  */
+#line 539 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = ';'; ;}
+    break;
+
+  case 99:
+
+/* Line 1455 of yacc.c  */
+#line 540 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = ','; ;}
+    break;
+
+  case 100:
+
+/* Line 1455 of yacc.c  */
+#line 541 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = '='; ;}
+    break;
+
+  case 101:
+
+/* Line 1455 of yacc.c  */
+#line 542 "glcpp/glcpp-parse.y"
+    { (yyval.ival) = PASTE; ;}
+    break;
+
+
+
+/* Line 1455 of yacc.c  */
+#line 2643 "glcpp/glcpp-parse.c"
+      default: break;
+    }
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+  *++yylsp = yyloc;
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (&yylloc, parser, YY_("syntax error"));
+#else
+      {
+       YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+       if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+         {
+           YYSIZE_T yyalloc = 2 * yysize;
+           if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+             yyalloc = YYSTACK_ALLOC_MAXIMUM;
+           if (yymsg != yymsgbuf)
+             YYSTACK_FREE (yymsg);
+           yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+           if (yymsg)
+             yymsg_alloc = yyalloc;
+           else
+             {
+               yymsg = yymsgbuf;
+               yymsg_alloc = sizeof yymsgbuf;
+             }
+         }
+
+       if (0 < yysize && yysize <= yymsg_alloc)
+         {
+           (void) yysyntax_error (yymsg, yystate, yychar);
+           yyerror (&yylloc, parser, yymsg);
+         }
+       else
+         {
+           yyerror (&yylloc, parser, YY_("syntax error"));
+           if (yysize != 0)
+             goto yyexhaustedlab;
+         }
+      }
+#endif
+    }
+
+  yyerror_range[0] = yylloc;
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+        error, discard it.  */
+
+      if (yychar <= YYEOF)
+       {
+         /* Return failure if at end of input.  */
+         if (yychar == YYEOF)
+           YYABORT;
+       }
+      else
+       {
+         yydestruct ("Error: discarding",
+                     yytoken, &yylval, &yylloc, parser);
+         yychar = YYEMPTY;
+       }
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  yyerror_range[0] = yylsp[1-yylen];
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;     /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+       {
+         yyn += YYTERROR;
+         if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+           {
+             yyn = yytable[yyn];
+             if (0 < yyn)
+               break;
+           }
+       }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+       YYABORT;
+
+      yyerror_range[0] = *yylsp;
+      yydestruct ("Error: popping",
+                 yystos[yystate], yyvsp, yylsp, parser);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  *++yyvsp = yylval;
+
+  yyerror_range[1] = yylloc;
+  /* Using YYLLOC is tempting, but would change the location of
+     the lookahead.  YYLOC is available though.  */
+  YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
+  *++yylsp = yyloc;
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (&yylloc, parser, YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+                yytoken, &yylval, &yylloc, parser);
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                 yystos[*yyssp], yyvsp, yylsp, parser);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+
+/* Line 1675 of yacc.c  */
+#line 545 "glcpp/glcpp-parse.y"
+
+
+string_list_t *
+_string_list_create (void *ctx)
+{
+       string_list_t *list;
+
+       list = talloc (ctx, string_list_t);
+       list->head = NULL;
+       list->tail = NULL;
+
+       return list;
+}
+
+void
+_string_list_append_item (string_list_t *list, const char *str)
+{
+       string_node_t *node;
+
+       node = talloc (list, string_node_t);
+       node->str = talloc_strdup (node, str);
+
+       node->next = NULL;
+
+       if (list->head == NULL) {
+               list->head = node;
+       } else {
+               list->tail->next = node;
+       }
+
+       list->tail = node;
+}
+
+int
+_string_list_contains (string_list_t *list, const char *member, int *index)
+{
+       string_node_t *node;
+       int i;
+
+       if (list == NULL)
+               return 0;
+
+       for (i = 0, node = list->head; node; i++, node = node->next) {
+               if (strcmp (node->str, member) == 0) {
+                       if (index)
+                               *index = i;
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+int
+_string_list_length (string_list_t *list)
+{
+       int length = 0;
+       string_node_t *node;
+
+       if (list == NULL)
+               return 0;
+
+       for (node = list->head; node; node = node->next)
+               length++;
+
+       return length;
+}
+
+int
+_string_list_equal (string_list_t *a, string_list_t *b)
+{
+       string_node_t *node_a, *node_b;
+
+       if (a == NULL && b == NULL)
+               return 1;
+
+       if (a == NULL || b == NULL)
+               return 0;
+
+       for (node_a = a->head, node_b = b->head;
+            node_a && node_b;
+            node_a = node_a->next, node_b = node_b->next)
+       {
+               if (strcmp (node_a->str, node_b->str))
+                       return 0;
+       }
+
+       /* Catch the case of lists being different lengths, (which
+        * would cause the loop above to terminate after the shorter
+        * list). */
+       return node_a == node_b;
+}
+
+argument_list_t *
+_argument_list_create (void *ctx)
+{
+       argument_list_t *list;
+
+       list = talloc (ctx, argument_list_t);
+       list->head = NULL;
+       list->tail = NULL;
+
+       return list;
+}
+
+void
+_argument_list_append (argument_list_t *list, token_list_t *argument)
+{
+       argument_node_t *node;
+
+       node = talloc (list, argument_node_t);
+       node->argument = argument;
+
+       node->next = NULL;
+
+       if (list->head == NULL) {
+               list->head = node;
+       } else {
+               list->tail->next = node;
+       }
+
+       list->tail = node;
+}
+
+int
+_argument_list_length (argument_list_t *list)
+{
+       int length = 0;
+       argument_node_t *node;
+
+       if (list == NULL)
+               return 0;
+
+       for (node = list->head; node; node = node->next)
+               length++;
+
+       return length;
+}
+
+token_list_t *
+_argument_list_member_at (argument_list_t *list, int index)
+{
+       argument_node_t *node;
+       int i;
+
+       if (list == NULL)
+               return NULL;
+
+       node = list->head;
+       for (i = 0; i < index; i++) {
+               node = node->next;
+               if (node == NULL)
+                       break;
+       }
+
+       if (node)
+               return node->argument;
+
+       return NULL;
+}
+
+/* Note: This function talloc_steal()s the str pointer. */
+token_t *
+_token_create_str (void *ctx, int type, char *str)
+{
+       token_t *token;
+
+       token = talloc (ctx, token_t);
+       token->type = type;
+       token->value.str = talloc_steal (token, str);
+
+       return token;
+}
+
+token_t *
+_token_create_ival (void *ctx, int type, int ival)
+{
+       token_t *token;
+
+       token = talloc (ctx, token_t);
+       token->type = type;
+       token->value.ival = ival;
+
+       return token;
+}
+
+token_list_t *
+_token_list_create (void *ctx)
+{
+       token_list_t *list;
+
+       list = talloc (ctx, token_list_t);
+       list->head = NULL;
+       list->tail = NULL;
+       list->non_space_tail = NULL;
+
+       return list;
+}
+
+void
+_token_list_append (token_list_t *list, token_t *token)
+{
+       token_node_t *node;
+
+       node = talloc (list, token_node_t);
+       node->token = talloc_reference (list, token);
+
+       node->next = NULL;
+
+       if (list->head == NULL) {
+               list->head = node;
+       } else {
+               list->tail->next = node;
+       }
+
+       list->tail = node;
+       if (token->type != SPACE)
+               list->non_space_tail = node;
+}
+
+void
+_token_list_append_list (token_list_t *list, token_list_t *tail)
+{
+       if (tail == NULL || tail->head == NULL)
+               return;
+
+       if (list->head == NULL) {
+               list->head = tail->head;
+       } else {
+               list->tail->next = tail->head;
+       }
+
+       list->tail = tail->tail;
+       list->non_space_tail = tail->non_space_tail;
+}
+
+static token_list_t *
+_token_list_copy (void *ctx, token_list_t *other)
+{
+       token_list_t *copy;
+       token_node_t *node;
+
+       if (other == NULL)
+               return NULL;
+
+       copy = _token_list_create (ctx);
+       for (node = other->head; node; node = node->next)
+               _token_list_append (copy, node->token);
+
+       return copy;
+}
+
+static void
+_token_list_trim_trailing_space (token_list_t *list)
+{
+       token_node_t *tail, *next;
+
+       if (list->non_space_tail) {
+               tail = list->non_space_tail->next;
+               list->non_space_tail->next = NULL;
+               list->tail = list->non_space_tail;
+
+               while (tail) {
+                       next = tail->next;
+                       talloc_free (tail);
+                       tail = next;
+               }
+       }
+}
+
+int
+_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b)
+{
+       token_node_t *node_a, *node_b;
+
+       node_a = a->head;
+       node_b = b->head;
+
+       while (1)
+       {
+               if (node_a == NULL && node_b == NULL)
+                       break;
+
+               if (node_a == NULL || node_b == NULL)
+                       return 0;
+
+               if (node_a->token->type == SPACE) {
+                       node_a = node_a->next;
+                       continue;
+               }
+
+               if (node_b->token->type == SPACE) {
+                       node_b = node_b->next;
+                       continue;
+               }
+
+               if (node_a->token->type != node_b->token->type)
+                       return 0;
+
+               switch (node_a->token->type) {
+               case INTEGER:
+                       if (node_a->token->value.ival != 
+                           node_b->token->value.ival)
+                       {
+                               return 0;
+                       }
+                       break;
+               case IDENTIFIER:
+               case INTEGER_STRING:
+               case OTHER:
+                       if (strcmp (node_a->token->value.str,
+                                   node_b->token->value.str))
+                       {
+                               return 0;
+                       }
+                       break;
+               }
+
+               node_a = node_a->next;
+               node_b = node_b->next;
+       }
+
+       return 1;
+}
+
+static void
+_token_print (char **out, token_t *token)
+{
+       if (token->type < 256) {
+               glcpp_printf (*out, "%c", token->type);
+               return;
+       }
+
+       switch (token->type) {
+       case INTEGER:
+               glcpp_printf (*out, "%" PRIiMAX, token->value.ival);
+               break;
+       case IDENTIFIER:
+       case INTEGER_STRING:
+       case OTHER:
+               glcpp_print (*out, token->value.str);
+               break;
+       case SPACE:
+               glcpp_print (*out, " ");
+               break;
+       case LEFT_SHIFT:
+               glcpp_print (*out, "<<");
+               break;
+       case RIGHT_SHIFT:
+               glcpp_print (*out, ">>");
+               break;
+       case LESS_OR_EQUAL:
+               glcpp_print (*out, "<=");
+               break;
+       case GREATER_OR_EQUAL:
+               glcpp_print (*out, ">=");
+               break;
+       case EQUAL:
+               glcpp_print (*out, "==");
+               break;
+       case NOT_EQUAL:
+               glcpp_print (*out, "!=");
+               break;
+       case AND:
+               glcpp_print (*out, "&&");
+               break;
+       case OR:
+               glcpp_print (*out, "||");
+               break;
+       case PASTE:
+               glcpp_print (*out, "##");
+               break;
+       case COMMA_FINAL:
+               glcpp_print (*out, ",");
+               break;
+       case PLACEHOLDER:
+               /* Nothing to print. */
+               break;
+       default:
+               assert(!"Error: Don't know how to print token.");
+               break;
+       }
+}
+
+/* Return a new token (talloc()ed off of 'token') formed by pasting
+ * 'token' and 'other'. Note that this function may return 'token' or
+ * 'other' directly rather than allocating anything new.
+ *
+ * Caution: Only very cursory error-checking is performed to see if
+ * the final result is a valid single token. */
+static token_t *
+_token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
+{
+       token_t *combined = NULL;
+
+       /* Pasting a placeholder onto anything makes no change. */
+       if (other->type == PLACEHOLDER)
+               return token;
+
+       /* When 'token' is a placeholder, just return 'other'. */
+       if (token->type == PLACEHOLDER)
+               return other;
+
+       /* A very few single-character punctuators can be combined
+        * with another to form a multi-character punctuator. */
+       switch (token->type) {
+       case '<':
+               if (other->type == '<')
+                       combined = _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT);
+               else if (other->type == '=')
+                       combined = _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL);
+               break;
+       case '>':
+               if (other->type == '>')
+                       combined = _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT);
+               else if (other->type == '=')
+                       combined = _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL);
+               break;
+       case '=':
+               if (other->type == '=')
+                       combined = _token_create_ival (token, EQUAL, EQUAL);
+               break;
+       case '!':
+               if (other->type == '=')
+                       combined = _token_create_ival (token, NOT_EQUAL, NOT_EQUAL);
+               break;
+       case '&':
+               if (other->type == '&')
+                       combined = _token_create_ival (token, AND, AND);
+               break;
+       case '|':
+               if (other->type == '|')
+                       combined = _token_create_ival (token, OR, OR);
+               break;
+       }
+
+       if (combined != NULL) {
+               /* Inherit the location from the first token */
+               combined->location = token->location;
+               return combined;
+       }
+
+       /* Two string-valued tokens can usually just be mashed
+        * together.
+        *
+        * XXX: This isn't actually legitimate. Several things here
+        * should result in a diagnostic since the result cannot be a
+        * valid, single pre-processing token. For example, pasting
+        * "123" and "abc" is not legal, but we don't catch that
+        * here. */
+       if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) &&
+           (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING))
+       {
+               char *str;
+
+               str = talloc_asprintf (token, "%s%s", token->value.str,
+                                      other->value.str);
+               combined = _token_create_str (token, token->type, str);
+               combined->location = token->location;
+               return combined;
+       }
+
+       glcpp_error (&token->location, parser, "");
+       glcpp_print (parser->info_log, "Pasting \"");
+       _token_print (&parser->info_log, token);
+       glcpp_print (parser->info_log, "\" and \"");
+       _token_print (&parser->info_log, other);
+       glcpp_print (parser->info_log, "\" does not give a valid preprocessing token.\n");
+
+       return token;
+}
+
+static void
+_token_list_print (glcpp_parser_t *parser, token_list_t *list)
+{
+       token_node_t *node;
+
+       if (list == NULL)
+               return;
+
+       for (node = list->head; node; node = node->next)
+               _token_print (&parser->output, node->token);
+}
+
+void
+yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error)
+{
+       glcpp_error(locp, parser, "%s", error);
+}
+
+static void add_builtin_define(glcpp_parser_t *parser,
+                              const char *name, int value)
+{
+   token_t *tok;
+   token_list_t *list;
+
+   tok = _token_create_ival (parser, INTEGER, value);
+
+   list = _token_list_create(parser);
+   _token_list_append(list, tok);
+   _define_object_macro(parser, NULL, name, list);
+
+   talloc_unlink(parser, tok);
+}
+
+glcpp_parser_t *
+glcpp_parser_create (const struct gl_extensions *extensions)
+{
+       glcpp_parser_t *parser;
+       int language_version;
+
+       parser = talloc (NULL, glcpp_parser_t);
+
+       glcpp_lex_init_extra (parser, &parser->scanner);
+       parser->defines = hash_table_ctor (32, hash_table_string_hash,
+                                          hash_table_string_compare);
+       parser->active = NULL;
+       parser->lexing_if = 0;
+       parser->space_tokens = 1;
+       parser->newline_as_space = 0;
+       parser->in_control_line = 0;
+       parser->paren_count = 0;
+
+       parser->skip_stack = NULL;
+
+       parser->lex_from_list = NULL;
+       parser->lex_from_node = NULL;
+
+       parser->output = talloc_strdup(parser, "");
+       parser->info_log = talloc_strdup(parser, "");
+       parser->error = 0;
+
+       /* Add pre-defined macros. */
+       add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
+       add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
+
+       if (extensions != NULL) {
+          if (extensions->EXT_texture_array) {
+             add_builtin_define(parser, "GL_EXT_texture_array", 1);
+          }
+
+          if (extensions->ARB_fragment_coord_conventions)
+             add_builtin_define(parser, "GL_ARB_fragment_coord_conventions",
+                                1);
+       }
+
+       language_version = 110;
+       add_builtin_define(parser, "__VERSION__", language_version);
+
+       return parser;
+}
+
+int
+glcpp_parser_parse (glcpp_parser_t *parser)
+{
+       return yyparse (parser);
+}
+
+void
+glcpp_parser_destroy (glcpp_parser_t *parser)
+{
+       glcpp_lex_destroy (parser->scanner);
+       hash_table_dtor (parser->defines);
+       talloc_free (parser);
+}
+
+typedef enum function_status
+{
+       FUNCTION_STATUS_SUCCESS,
+       FUNCTION_NOT_A_FUNCTION,
+       FUNCTION_UNBALANCED_PARENTHESES
+} function_status_t;
+
+/* Find a set of function-like macro arguments by looking for a
+ * balanced set of parentheses.
+ *
+ * When called, 'node' should be the opening-parenthesis token, (or
+ * perhaps preceeding SPACE tokens). Upon successful return *last will
+ * be the last consumed node, (corresponding to the closing right
+ * parenthesis).
+ *
+ * Return values:
+ *
+ *   FUNCTION_STATUS_SUCCESS:
+ *
+ *     Successfully parsed a set of function arguments.        
+ *
+ *   FUNCTION_NOT_A_FUNCTION:
+ *
+ *     Macro name not followed by a '('. This is not an error, but
+ *     simply that the macro name should be treated as a non-macro.
+ *
+ *   FUNCTION_UNBALANCED_PARENTHESES
+ *
+ *     Macro name is not followed by a balanced set of parentheses.
+ */
+static function_status_t
+_arguments_parse (argument_list_t *arguments,
+                 token_node_t *node,
+                 token_node_t **last)
+{
+       token_list_t *argument;
+       int paren_count;
+
+       node = node->next;
+
+       /* Ignore whitespace before first parenthesis. */
+       while (node && node->token->type == SPACE)
+               node = node->next;
+
+       if (node == NULL || node->token->type != '(')
+               return FUNCTION_NOT_A_FUNCTION;
+
+       node = node->next;
+
+       argument = _token_list_create (arguments);
+       _argument_list_append (arguments, argument);
+
+       for (paren_count = 1; node; node = node->next) {
+               if (node->token->type == '(')
+               {
+                       paren_count++;
+               }
+               else if (node->token->type == ')')
+               {
+                       paren_count--;
+                       if (paren_count == 0)
+                               break;
+               }
+
+               if (node->token->type == ',' &&
+                        paren_count == 1)
+               {
+                       _token_list_trim_trailing_space (argument);
+                       argument = _token_list_create (arguments);
+                       _argument_list_append (arguments, argument);
+               }
+               else {
+                       if (argument->head == NULL) {
+                               /* Don't treat initial whitespace as
+                                * part of the arguement. */
+                               if (node->token->type == SPACE)
+                                       continue;
+                       }
+                       _token_list_append (argument, node->token);
+               }
+       }
+
+       if (paren_count)
+               return FUNCTION_UNBALANCED_PARENTHESES;
+
+       *last = node;
+
+       return FUNCTION_STATUS_SUCCESS;
+}
+
+static token_list_t *
+_token_list_create_with_one_space (void *ctx)
+{
+       token_list_t *list;
+       token_t *space;
+
+       list = _token_list_create (ctx);
+       space = _token_create_ival (list, SPACE, SPACE);
+       _token_list_append (list, space);
+
+       return list;
+}
+
+static void
+_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list)
+{
+       token_list_t *expanded;
+       token_t *token;
+
+       expanded = _token_list_create (parser);
+       token = _token_create_ival (parser, type, type);
+       _token_list_append (expanded, token);
+       _glcpp_parser_expand_token_list (parser, list);
+       _token_list_append_list (expanded, list);
+       glcpp_parser_lex_from (parser, expanded);
+}
+
+/* This is a helper function that's essentially part of the
+ * implementation of _glcpp_parser_expand_node. It shouldn't be called
+ * except for by that function.
+ *
+ * Returns NULL if node is a simple token with no expansion, (that is,
+ * although 'node' corresponds to an identifier defined as a
+ * function-like macro, it is not followed with a parenthesized
+ * argument list).
+ *
+ * Compute the complete expansion of node (which is a function-like
+ * macro) and subsequent nodes which are arguments.
+ *
+ * Returns the token list that results from the expansion and sets
+ * *last to the last node in the list that was consumed by the
+ * expansion. Specifically, *last will be set as follows: as the
+ * token of the closing right parenthesis.
+ */
+static token_list_t *
+_glcpp_parser_expand_function (glcpp_parser_t *parser,
+                              token_node_t *node,
+                              token_node_t **last)
+                              
+{
+       macro_t *macro;
+       const char *identifier;
+       argument_list_t *arguments;
+       function_status_t status;
+       token_list_t *substituted;
+       int parameter_index;
+
+       identifier = node->token->value.str;
+
+       macro = hash_table_find (parser->defines, identifier);
+
+       assert (macro->is_function);
+
+       arguments = _argument_list_create (parser);
+       status = _arguments_parse (arguments, node, last);
+
+       switch (status) {
+       case FUNCTION_STATUS_SUCCESS:
+               break;
+       case FUNCTION_NOT_A_FUNCTION:
+               return NULL;
+       case FUNCTION_UNBALANCED_PARENTHESES:
+               glcpp_error (&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier);
+               return NULL;
+       }
+
+       /* Replace a macro defined as empty with a SPACE token. */
+       if (macro->replacements == NULL) {
+               talloc_free (arguments);
+               return _token_list_create_with_one_space (parser);
+       }
+
+       if (! ((_argument_list_length (arguments) == 
+               _string_list_length (macro->parameters)) ||
+              (_string_list_length (macro->parameters) == 0 &&
+               _argument_list_length (arguments) == 1 &&
+               arguments->head->argument->head == NULL)))
+       {
+               glcpp_error (&node->token->location, parser,
+                             "Error: macro %s invoked with %d arguments (expected %d)\n",
+                             identifier,
+                             _argument_list_length (arguments),
+                             _string_list_length (macro->parameters));
+               return NULL;
+       }
+
+       /* Perform argument substitution on the replacement list. */
+       substituted = _token_list_create (arguments);
+
+       for (node = macro->replacements->head; node; node = node->next)
+       {
+               if (node->token->type == IDENTIFIER &&
+                   _string_list_contains (macro->parameters,
+                                          node->token->value.str,
+                                          &parameter_index))
+               {
+                       token_list_t *argument;
+                       argument = _argument_list_member_at (arguments,
+                                                            parameter_index);
+                       /* Before substituting, we expand the argument
+                        * tokens, or append a placeholder token for
+                        * an empty argument. */
+                       if (argument->head) {
+                               token_list_t *expanded_argument;
+                               expanded_argument = _token_list_copy (parser,
+                                                                     argument);
+                               _glcpp_parser_expand_token_list (parser,
+                                                                expanded_argument);
+                               _token_list_append_list (substituted,
+                                                        expanded_argument);
+                       } else {
+                               token_t *new_token;
+
+                               new_token = _token_create_ival (substituted,
+                                                               PLACEHOLDER,
+                                                               PLACEHOLDER);
+                               _token_list_append (substituted, new_token);
+                       }
+               } else {
+                       _token_list_append (substituted, node->token);
+               }
+       }
+
+       /* After argument substitution, and before further expansion
+        * below, implement token pasting. */
+
+       _token_list_trim_trailing_space (substituted);
+
+       node = substituted->head;
+       while (node)
+       {
+               token_node_t *next_non_space;
+
+               /* Look ahead for a PASTE token, skipping space. */
+               next_non_space = node->next;
+               while (next_non_space && next_non_space->token->type == SPACE)
+                       next_non_space = next_non_space->next;
+
+               if (next_non_space == NULL)
+                       break;
+
+               if (next_non_space->token->type != PASTE) {
+                       node = next_non_space;
+                       continue;
+               }
+
+               /* Now find the next non-space token after the PASTE. */
+               next_non_space = next_non_space->next;
+               while (next_non_space && next_non_space->token->type == SPACE)
+                       next_non_space = next_non_space->next;
+
+               if (next_non_space == NULL) {
+                       yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n");
+                       return NULL;
+               }
+
+               node->token = _token_paste (parser, node->token, next_non_space->token);
+               node->next = next_non_space->next;
+               if (next_non_space == substituted->tail)
+                       substituted->tail = node;
+
+               node = node->next;
+       }
+
+       substituted->non_space_tail = substituted->tail;
+
+       return substituted;
+}
+
+/* Compute the complete expansion of node, (and subsequent nodes after
+ * 'node' in the case that 'node' is a function-like macro and
+ * subsequent nodes are arguments).
+ *
+ * Returns NULL if node is a simple token with no expansion.
+ *
+ * Otherwise, returns the token list that results from the expansion
+ * and sets *last to the last node in the list that was consumed by
+ * the expansion. Specifically, *last will be set as follows:
+ *
+ *     As 'node' in the case of object-like macro expansion.
+ *
+ *     As the token of the closing right parenthesis in the case of
+ *     function-like macro expansion.
+ */
+static token_list_t *
+_glcpp_parser_expand_node (glcpp_parser_t *parser,
+                          token_node_t *node,
+                          token_node_t **last)
+{
+       token_t *token = node->token;
+       const char *identifier;
+       macro_t *macro;
+
+       /* We only expand identifiers */
+       if (token->type != IDENTIFIER) {
+               /* We change any COMMA into a COMMA_FINAL to prevent
+                * it being mistaken for an argument separator
+                * later. */
+               if (token->type == ',') {
+                       token->type = COMMA_FINAL;
+                       token->value.ival = COMMA_FINAL;
+               }
+
+               return NULL;
+       }
+
+       /* Look up this identifier in the hash table. */
+       identifier = token->value.str;
+       macro = hash_table_find (parser->defines, identifier);
+
+       /* Not a macro, so no expansion needed. */
+       if (macro == NULL)
+               return NULL;
+
+       /* Finally, don't expand this macro if we're already actively
+        * expanding it, (to avoid infinite recursion). */
+       if (_active_list_contains (parser->active, identifier)) {
+               /* We change the token type here from IDENTIFIER to
+                * OTHER to prevent any future expansion of this
+                * unexpanded token. */
+               char *str;
+               token_list_t *expansion;
+               token_t *final;
+
+               str = talloc_strdup (parser, token->value.str);
+               final = _token_create_str (parser, OTHER, str);
+               expansion = _token_list_create (parser);
+               _token_list_append (expansion, final);
+               *last = node;
+               return expansion;
+       }
+
+       if (! macro->is_function)
+       {
+               *last = node;
+
+               /* Replace a macro defined as empty with a SPACE token. */
+               if (macro->replacements == NULL)
+                       return _token_list_create_with_one_space (parser);
+
+               return _token_list_copy (parser, macro->replacements);
+       }
+
+       return _glcpp_parser_expand_function (parser, node, last);
+}
+
+/* Push a new identifier onto the active list, returning the new list.
+ *
+ * Here, 'marker' is the token node that appears in the list after the
+ * expansion of 'identifier'. That is, when the list iterator begins
+ * examinging 'marker', then it is time to pop this node from the
+ * active stack.
+ */
+active_list_t *
+_active_list_push (active_list_t *list,
+                  const char *identifier,
+                  token_node_t *marker)
+{
+       active_list_t *node;
+
+       node = talloc (list, active_list_t);
+       node->identifier = talloc_strdup (node, identifier);
+       node->marker = marker;
+       node->next = list;
+
+       return node;
+}
+
+active_list_t *
+_active_list_pop (active_list_t *list)
+{
+       active_list_t *node = list;
+
+       if (node == NULL)
+               return NULL;
+
+       node = list->next;
+       talloc_free (list);
+
+       return node;
+}
+
+int
+_active_list_contains (active_list_t *list, const char *identifier)
+{
+       active_list_t *node;
+
+       if (list == NULL)
+               return 0;
+
+       for (node = list; node; node = node->next)
+               if (strcmp (node->identifier, identifier) == 0)
+                       return 1;
+
+       return 0;
+}
+
+/* Walk over the token list replacing nodes with their expansion.
+ * Whenever nodes are expanded the walking will walk over the new
+ * nodes, continuing to expand as necessary. The results are placed in
+ * 'list' itself;
+ */
+static void
+_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
+                                token_list_t *list)
+{
+       token_node_t *node_prev;
+       token_node_t *node, *last = NULL;
+       token_list_t *expansion;
+
+       if (list == NULL)
+               return;
+
+       _token_list_trim_trailing_space (list);
+
+       node_prev = NULL;
+       node = list->head;
+
+       while (node) {
+
+               while (parser->active && parser->active->marker == node)
+                       parser->active = _active_list_pop (parser->active);
+
+               /* Find the expansion for node, which will replace all
+                * nodes from node to last, inclusive. */
+               expansion = _glcpp_parser_expand_node (parser, node, &last);
+               if (expansion) {
+                       token_node_t *n;
+
+                       for (n = node; n != last->next; n = n->next)
+                               while (parser->active &&
+                                      parser->active->marker == n)
+                               {
+                                       parser->active = _active_list_pop (parser->active);
+                               }
+
+                       parser->active = _active_list_push (parser->active,
+                                                           node->token->value.str,
+                                                           last->next);
+                       
+                       /* Splice expansion into list, supporting a
+                        * simple deletion if the expansion is
+                        * empty. */
+                       if (expansion->head) {
+                               if (node_prev)
+                                       node_prev->next = expansion->head;
+                               else
+                                       list->head = expansion->head;
+                               expansion->tail->next = last->next;
+                               if (last == list->tail)
+                                       list->tail = expansion->tail;
+                       } else {
+                               if (node_prev)
+                                       node_prev->next = last->next;
+                               else
+                                       list->head = last->next;
+                               if (last == list->tail)
+                                       list->tail = NULL;
+                       }
+               } else {
+                       node_prev = node;
+               }
+               node = node_prev ? node_prev->next : list->head;
+       }
+
+       while (parser->active)
+               parser->active = _active_list_pop (parser->active);
+
+       list->non_space_tail = list->tail;
+}
+
+void
+_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
+                                        token_list_t *list)
+{
+       if (list == NULL)
+               return;
+
+       _glcpp_parser_expand_token_list (parser, list);
+
+       _token_list_trim_trailing_space (list);
+
+       _token_list_print (parser, list);
+}
+
+static void
+_check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc,
+                               const char *identifier)
+{
+       /* According to the GLSL specification, macro names starting with "__"
+        * or "GL_" are reserved for future use.  So, don't allow them.
+        */
+       if (strncmp(identifier, "__", 2) == 0) {
+               glcpp_error (loc, parser, "Macro names starting with \"__\" are reserved.\n");
+       }
+       if (strncmp(identifier, "GL_", 3) == 0) {
+               glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n");
+       }
+}
+
+static int
+_macro_equal (macro_t *a, macro_t *b)
+{
+       if (a->is_function != b->is_function)
+               return 0;
+
+       if (a->is_function) {
+               if (! _string_list_equal (a->parameters, b->parameters))
+                       return 0;
+       }
+
+       return _token_list_equal_ignoring_space (a->replacements,
+                                                b->replacements);
+}
+
+void
+_define_object_macro (glcpp_parser_t *parser,
+                     YYLTYPE *loc,
+                     const char *identifier,
+                     token_list_t *replacements)
+{
+       macro_t *macro, *previous;
+
+       if (loc != NULL)
+               _check_for_reserved_macro_name(parser, loc, identifier);
+
+       macro = talloc (parser, macro_t);
+
+       macro->is_function = 0;
+       macro->parameters = NULL;
+       macro->identifier = talloc_strdup (macro, identifier);
+       macro->replacements = talloc_steal (macro, replacements);
+
+       previous = hash_table_find (parser->defines, identifier);
+       if (previous) {
+               if (_macro_equal (macro, previous)) {
+                       talloc_free (macro);
+                       return;
+               }
+               glcpp_error (loc, parser, "Redefinition of macro %s\n",
+                            identifier);
+       }
+
+       hash_table_insert (parser->defines, macro, identifier);
+}
+
+void
+_define_function_macro (glcpp_parser_t *parser,
+                       YYLTYPE *loc,
+                       const char *identifier,
+                       string_list_t *parameters,
+                       token_list_t *replacements)
+{
+       macro_t *macro, *previous;
+
+       _check_for_reserved_macro_name(parser, loc, identifier);
+
+       macro = talloc (parser, macro_t);
+
+       macro->is_function = 1;
+       macro->parameters = talloc_steal (macro, parameters);
+       macro->identifier = talloc_strdup (macro, identifier);
+       macro->replacements = talloc_steal (macro, replacements);
+
+       previous = hash_table_find (parser->defines, identifier);
+       if (previous) {
+               if (_macro_equal (macro, previous)) {
+                       talloc_free (macro);
+                       return;
+               }
+               glcpp_error (loc, parser, "Redefinition of macro %s\n",
+                            identifier);
+       }
+
+       hash_table_insert (parser->defines, macro, identifier);
+}
+
+static int
+glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
+{
+       token_node_t *node;
+       int ret;
+
+       if (parser->lex_from_list == NULL) {
+               ret = glcpp_lex (yylval, yylloc, parser->scanner);
+
+               /* XXX: This ugly block of code exists for the sole
+                * purpose of converting a NEWLINE token into a SPACE
+                * token, but only in the case where we have seen a
+                * function-like macro name, but have not yet seen its
+                * closing parenthesis.
+                *
+                * There's perhaps a more compact way to do this with
+                * mid-rule actions in the grammar.
+                *
+                * I'm definitely not pleased with the complexity of
+                * this code here.
+                */
+               if (parser->newline_as_space)
+               {
+                       if (ret == '(') {
+                               parser->paren_count++;
+                       } else if (ret == ')') {
+                               parser->paren_count--;
+                               if (parser->paren_count == 0)
+                                       parser->newline_as_space = 0;
+                       } else if (ret == NEWLINE) {
+                               ret = SPACE;
+                       } else if (ret != SPACE) {
+                               if (parser->paren_count == 0)
+                                       parser->newline_as_space = 0;
+                       }
+               }
+               else if (parser->in_control_line)
+               {
+                       if (ret == NEWLINE)
+                               parser->in_control_line = 0;
+               }
+               else if (ret == HASH_DEFINE_OBJ || ret == HASH_DEFINE_FUNC ||
+                          ret == HASH_UNDEF || ret == HASH_IF ||
+                          ret == HASH_IFDEF || ret == HASH_IFNDEF ||
+                          ret == HASH_ELIF || ret == HASH_ELSE ||
+                          ret == HASH_ENDIF || ret == HASH)
+               {
+                       parser->in_control_line = 1;
+               }
+               else if (ret == IDENTIFIER)
+               {
+                       macro_t *macro;
+                       macro = hash_table_find (parser->defines,
+                                                yylval->str);
+                       if (macro && macro->is_function) {
+                               parser->newline_as_space = 1;
+                               parser->paren_count = 0;
+                       }
+               }
+
+               return ret;
+       }
+
+       node = parser->lex_from_node;
+
+       if (node == NULL) {
+               talloc_free (parser->lex_from_list);
+               parser->lex_from_list = NULL;
+               return NEWLINE;
+       }
+
+       *yylval = node->token->value;
+       ret = node->token->type;
+
+       parser->lex_from_node = node->next;
+
+       return ret;
+}
+
+static void
+glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list)
+{
+       token_node_t *node;
+
+       assert (parser->lex_from_list == NULL);
+
+       /* Copy list, eliminating any space tokens. */
+       parser->lex_from_list = _token_list_create (parser);
+
+       for (node = list->head; node; node = node->next) {
+               if (node->token->type == SPACE)
+                       continue;
+               _token_list_append (parser->lex_from_list, node->token);
+       }
+
+       talloc_free (list);
+
+       parser->lex_from_node = parser->lex_from_list->head;
+
+       /* It's possible the list consisted of nothing but whitespace. */
+       if (parser->lex_from_node == NULL) {
+               talloc_free (parser->lex_from_list);
+               parser->lex_from_list = NULL;
+       }
+}
+
+static void
+_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
+                                 int condition)
+{
+       skip_type_t current = SKIP_NO_SKIP;
+       skip_node_t *node;
+
+       if (parser->skip_stack)
+               current = parser->skip_stack->type;
+
+       node = talloc (parser, skip_node_t);
+       node->loc = *loc;
+
+       if (current == SKIP_NO_SKIP) {
+               if (condition)
+                       node->type = SKIP_NO_SKIP;
+               else
+                       node->type = SKIP_TO_ELSE;
+       } else {
+               node->type = SKIP_TO_ENDIF;
+       }
+
+       node->next = parser->skip_stack;
+       parser->skip_stack = node;
+}
+
+static void
+_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
+                                   const char *type, int condition)
+{
+       if (parser->skip_stack == NULL) {
+               glcpp_error (loc, parser, "%s without #if\n", type);
+               return;
+       }
+
+       if (parser->skip_stack->type == SKIP_TO_ELSE) {
+               if (condition)
+                       parser->skip_stack->type = SKIP_NO_SKIP;
+       } else {
+               parser->skip_stack->type = SKIP_TO_ENDIF;
+       }
+}
+
+static void
+_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc)
+{
+       skip_node_t *node;
+
+       if (parser->skip_stack == NULL) {
+               glcpp_error (loc, parser, "#endif without #if\n");
+               return;
+       }
+
+       node = parser->skip_stack;
+       parser->skip_stack = node->next;
+       talloc_free (node);
+}
+
diff --git a/src/glsl/glcpp/glcpp-parse.h b/src/glsl/glcpp/glcpp-parse.h
new file mode 100644 (file)
index 0000000..5075893
--- /dev/null
@@ -0,0 +1,101 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1.  */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+   
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+   
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     COMMA_FINAL = 258,
+     DEFINED = 259,
+     ELIF_EXPANDED = 260,
+     HASH = 261,
+     HASH_DEFINE_FUNC = 262,
+     HASH_DEFINE_OBJ = 263,
+     HASH_ELIF = 264,
+     HASH_ELSE = 265,
+     HASH_ENDIF = 266,
+     HASH_IF = 267,
+     HASH_IFDEF = 268,
+     HASH_IFNDEF = 269,
+     HASH_UNDEF = 270,
+     HASH_VERSION = 271,
+     IDENTIFIER = 272,
+     IF_EXPANDED = 273,
+     INTEGER = 274,
+     INTEGER_STRING = 275,
+     NEWLINE = 276,
+     OTHER = 277,
+     PLACEHOLDER = 278,
+     SPACE = 279,
+     PASTE = 280,
+     OR = 281,
+     AND = 282,
+     NOT_EQUAL = 283,
+     EQUAL = 284,
+     GREATER_OR_EQUAL = 285,
+     LESS_OR_EQUAL = 286,
+     RIGHT_SHIFT = 287,
+     LEFT_SHIFT = 288,
+     UNARY = 289
+   };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+
diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y
new file mode 100644 (file)
index 0000000..3c28edf
--- /dev/null
@@ -0,0 +1,1850 @@
+%{
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <inttypes.h>
+
+#include "glcpp.h"
+#include "main/core.h" /* for struct gl_extensions */
+
+#define glcpp_print(stream, str) stream = talloc_strdup_append(stream, str)
+#define glcpp_printf(stream, fmt, args, ...) \
+       stream = talloc_asprintf_append(stream, fmt, args)
+
+static void
+yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error);
+
+static void
+_define_object_macro (glcpp_parser_t *parser,
+                     YYLTYPE *loc,
+                     const char *macro,
+                     token_list_t *replacements);
+
+static void
+_define_function_macro (glcpp_parser_t *parser,
+                       YYLTYPE *loc,
+                       const char *macro,
+                       string_list_t *parameters,
+                       token_list_t *replacements);
+
+static string_list_t *
+_string_list_create (void *ctx);
+
+static void
+_string_list_append_item (string_list_t *list, const char *str);
+
+static int
+_string_list_contains (string_list_t *list, const char *member, int *index);
+
+static int
+_string_list_length (string_list_t *list);
+
+static int
+_string_list_equal (string_list_t *a, string_list_t *b);
+
+static argument_list_t *
+_argument_list_create (void *ctx);
+
+static void
+_argument_list_append (argument_list_t *list, token_list_t *argument);
+
+static int
+_argument_list_length (argument_list_t *list);
+
+static token_list_t *
+_argument_list_member_at (argument_list_t *list, int index);
+
+/* Note: This function talloc_steal()s the str pointer. */
+static token_t *
+_token_create_str (void *ctx, int type, char *str);
+
+static token_t *
+_token_create_ival (void *ctx, int type, int ival);
+
+static token_list_t *
+_token_list_create (void *ctx);
+
+/* Note: This function adds a talloc_reference() to token.
+ *
+ * You may want to talloc_unlink any current reference if you no
+ * longer need it. */
+static void
+_token_list_append (token_list_t *list, token_t *token);
+
+static void
+_token_list_append_list (token_list_t *list, token_list_t *tail);
+
+static int
+_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b);
+
+static active_list_t *
+_active_list_push (active_list_t *list,
+                  const char *identifier,
+                  token_node_t *marker);
+
+static active_list_t *
+_active_list_pop (active_list_t *list);
+
+int
+_active_list_contains (active_list_t *list, const char *identifier);
+
+static void
+_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list);
+
+static void
+_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
+                                token_list_t *list);
+
+static void
+_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
+                                        token_list_t *list);
+
+static void
+_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
+                                 int condition);
+
+static void
+_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
+                                   const char *type, int condition);
+
+static void
+_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc);
+
+#define yylex glcpp_parser_lex
+
+static int
+glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser);
+
+static void
+glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list);
+
+static void
+add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
+
+%}
+
+%pure-parser
+%error-verbose
+
+%locations
+%initial-action {
+       @$.first_line = 1;
+       @$.first_column = 1;
+       @$.last_line = 1;
+       @$.last_column = 1;
+       @$.source = 0;
+}
+
+%parse-param {glcpp_parser_t *parser}
+%lex-param {glcpp_parser_t *parser}
+
+%expect 0
+%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING NEWLINE OTHER PLACEHOLDER SPACE
+%token PASTE
+%type <ival> expression INTEGER operator SPACE integer_constant
+%type <str> IDENTIFIER INTEGER_STRING OTHER
+%type <string_list> identifier_list
+%type <token> preprocessing_token conditional_token
+%type <token_list> pp_tokens replacement_list text_line conditional_tokens
+%left OR
+%left AND
+%left '|'
+%left '^'
+%left '&'
+%left EQUAL NOT_EQUAL
+%left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL
+%left LEFT_SHIFT RIGHT_SHIFT
+%left '+' '-'
+%left '*' '/' '%'
+%right UNARY
+
+%%
+
+input:
+       /* empty */
+|      input line
+;
+
+line:
+       control_line {
+               glcpp_print(parser->output, "\n");
+       }
+|      text_line {
+               _glcpp_parser_print_expanded_token_list (parser, $1);
+               glcpp_print(parser->output, "\n");
+               talloc_free ($1);
+       }
+|      expanded_line
+|      HASH non_directive
+;
+
+expanded_line:
+       IF_EXPANDED expression NEWLINE {
+               _glcpp_parser_skip_stack_push_if (parser, & @1, $2);
+       }
+|      ELIF_EXPANDED expression NEWLINE {
+               _glcpp_parser_skip_stack_change_if (parser, & @1, "elif", $2);
+       }
+;
+
+control_line:
+       HASH_DEFINE_OBJ IDENTIFIER replacement_list NEWLINE {
+               _define_object_macro (parser, & @2, $2, $3);
+       }
+|      HASH_DEFINE_FUNC IDENTIFIER '(' ')' replacement_list NEWLINE {
+               _define_function_macro (parser, & @2, $2, NULL, $5);
+       }
+|      HASH_DEFINE_FUNC IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE {
+               _define_function_macro (parser, & @2, $2, $4, $6);
+       }
+|      HASH_UNDEF IDENTIFIER NEWLINE {
+               macro_t *macro = hash_table_find (parser->defines, $2);
+               if (macro) {
+                       hash_table_remove (parser->defines, $2);
+                       talloc_free (macro);
+               }
+               talloc_free ($2);
+       }
+|      HASH_IF conditional_tokens NEWLINE {
+               /* Be careful to only evaluate the 'if' expression if
+                * we are not skipping. When we are skipping, we
+                * simply push a new 0-valued 'if' onto the skip
+                * stack.
+                *
+                * This avoids generating diagnostics for invalid
+                * expressions that are being skipped. */
+               if (parser->skip_stack == NULL ||
+                   parser->skip_stack->type == SKIP_NO_SKIP)
+               {
+                       _glcpp_parser_expand_if (parser, IF_EXPANDED, $2);
+               }       
+               else
+               {
+                       _glcpp_parser_skip_stack_push_if (parser, & @1, 0);
+                       parser->skip_stack->type = SKIP_TO_ENDIF;
+               }
+       }
+|      HASH_IF NEWLINE {
+               /* #if without an expression is only an error if we
+                *  are not skipping */
+               if (parser->skip_stack == NULL ||
+                   parser->skip_stack->type == SKIP_NO_SKIP)
+               {
+                       glcpp_error(& @1, parser, "#if with no expression");
+               }       
+               _glcpp_parser_skip_stack_push_if (parser, & @1, 0);
+       }
+|      HASH_IFDEF IDENTIFIER junk NEWLINE {
+               macro_t *macro = hash_table_find (parser->defines, $2);
+               talloc_free ($2);
+               _glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL);
+       }
+|      HASH_IFNDEF IDENTIFIER junk NEWLINE {
+               macro_t *macro = hash_table_find (parser->defines, $2);
+               talloc_free ($2);
+               _glcpp_parser_skip_stack_push_if (parser, & @1, macro == NULL);
+       }
+|      HASH_ELIF conditional_tokens NEWLINE {
+               /* Be careful to only evaluate the 'elif' expression
+                * if we are not skipping. When we are skipping, we
+                * simply change to a 0-valued 'elif' on the skip
+                * stack.
+                *
+                * This avoids generating diagnostics for invalid
+                * expressions that are being skipped. */
+               if (parser->skip_stack &&
+                   parser->skip_stack->type == SKIP_TO_ELSE)
+               {
+                       _glcpp_parser_expand_if (parser, ELIF_EXPANDED, $2);
+               }
+               else
+               {
+                       _glcpp_parser_skip_stack_change_if (parser, & @1,
+                                                           "elif", 0);
+               }
+       }
+|      HASH_ELIF NEWLINE {
+               /* #elif without an expression is an error unless we
+                * are skipping. */
+               if (parser->skip_stack &&
+                   parser->skip_stack->type == SKIP_TO_ELSE)
+               {
+                       glcpp_error(& @1, parser, "#elif with no expression");
+               }
+               else
+               {
+                       _glcpp_parser_skip_stack_change_if (parser, & @1,
+                                                           "elif", 0);
+                       glcpp_warning(& @1, parser, "ignoring illegal #elif without expression");
+               }
+       }
+|      HASH_ELSE NEWLINE {
+               _glcpp_parser_skip_stack_change_if (parser, & @1, "else", 1);
+       }
+|      HASH_ENDIF NEWLINE {
+               _glcpp_parser_skip_stack_pop (parser, & @1);
+       }
+|      HASH_VERSION integer_constant NEWLINE {
+               macro_t *macro = hash_table_find (parser->defines, "__VERSION__");
+               if (macro) {
+                       hash_table_remove (parser->defines, "__VERSION__");
+                       talloc_free (macro);
+               }
+               add_builtin_define (parser, "__VERSION__", $2);
+               glcpp_printf(parser->output, "#version %" PRIiMAX, $2);
+       }
+|      HASH NEWLINE
+;
+
+integer_constant:
+       INTEGER_STRING {
+               if (strlen ($1) >= 3 && strncmp ($1, "0x", 2) == 0) {
+                       $$ = strtoll ($1 + 2, NULL, 16);
+               } else if ($1[0] == '0') {
+                       $$ = strtoll ($1, NULL, 8);
+               } else {
+                       $$ = strtoll ($1, NULL, 10);
+               }
+       }
+|      INTEGER {
+               $$ = $1;
+       }
+
+expression:
+       integer_constant
+|      expression OR expression {
+               $$ = $1 || $3;
+       }
+|      expression AND expression {
+               $$ = $1 && $3;
+       }
+|      expression '|' expression {
+               $$ = $1 | $3;
+       }
+|      expression '^' expression {
+               $$ = $1 ^ $3;
+       }
+|      expression '&' expression {
+               $$ = $1 & $3;
+       }
+|      expression NOT_EQUAL expression {
+               $$ = $1 != $3;
+       }
+|      expression EQUAL expression {
+               $$ = $1 == $3;
+       }
+|      expression GREATER_OR_EQUAL expression {
+               $$ = $1 >= $3;
+       }
+|      expression LESS_OR_EQUAL expression {
+               $$ = $1 <= $3;
+       }
+|      expression '>' expression {
+               $$ = $1 > $3;
+       }
+|      expression '<' expression {
+               $$ = $1 < $3;
+       }
+|      expression RIGHT_SHIFT expression {
+               $$ = $1 >> $3;
+       }
+|      expression LEFT_SHIFT expression {
+               $$ = $1 << $3;
+       }
+|      expression '-' expression {
+               $$ = $1 - $3;
+       }
+|      expression '+' expression {
+               $$ = $1 + $3;
+       }
+|      expression '%' expression {
+               $$ = $1 % $3;
+       }
+|      expression '/' expression {
+               $$ = $1 / $3;
+       }
+|      expression '*' expression {
+               $$ = $1 * $3;
+       }
+|      '!' expression %prec UNARY {
+               $$ = ! $2;
+       }
+|      '~' expression %prec UNARY {
+               $$ = ~ $2;
+       }
+|      '-' expression %prec UNARY {
+               $$ = - $2;
+       }
+|      '+' expression %prec UNARY {
+               $$ = + $2;
+       }
+|      '(' expression ')' {
+               $$ = $2;
+       }
+;
+
+identifier_list:
+       IDENTIFIER {
+               $$ = _string_list_create (parser);
+               _string_list_append_item ($$, $1);
+               talloc_steal ($$, $1);
+       }
+|      identifier_list ',' IDENTIFIER {
+               $$ = $1;        
+               _string_list_append_item ($$, $3);
+               talloc_steal ($$, $3);
+       }
+;
+
+text_line:
+       NEWLINE { $$ = NULL; }
+|      pp_tokens NEWLINE
+;
+
+non_directive:
+       pp_tokens NEWLINE {
+               yyerror (& @1, parser, "Invalid tokens after #");
+       }
+;
+
+replacement_list:
+       /* empty */ { $$ = NULL; }
+|      pp_tokens
+;
+
+junk:
+       /* empty */
+|      pp_tokens {
+               glcpp_warning(&@1, parser, "extra tokens at end of directive");
+       }
+;
+
+conditional_token:
+       /* Handle "defined" operator */
+       DEFINED IDENTIFIER {
+               int v = hash_table_find (parser->defines, $2) ? 1 : 0;
+               $$ = _token_create_ival (parser, INTEGER, v);
+       }
+|      DEFINED '(' IDENTIFIER ')' {
+               int v = hash_table_find (parser->defines, $3) ? 1 : 0;
+               $$ = _token_create_ival (parser, INTEGER, v);
+       }
+|      preprocessing_token
+;
+
+conditional_tokens:
+       /* Exactly the same as pp_tokens, but using conditional_token */
+       conditional_token {
+               parser->space_tokens = 1;
+               $$ = _token_list_create (parser);
+               _token_list_append ($$, $1);
+               talloc_unlink (parser, $1);
+       }
+|      conditional_tokens conditional_token {
+               $$ = $1;
+               _token_list_append ($$, $2);
+               talloc_unlink (parser, $2);
+       }
+;
+
+pp_tokens:
+       preprocessing_token {
+               parser->space_tokens = 1;
+               $$ = _token_list_create (parser);
+               _token_list_append ($$, $1);
+               talloc_unlink (parser, $1);
+       }
+|      pp_tokens preprocessing_token {
+               $$ = $1;
+               _token_list_append ($$, $2);
+               talloc_unlink (parser, $2);
+       }
+;
+
+preprocessing_token:
+       IDENTIFIER {
+               $$ = _token_create_str (parser, IDENTIFIER, $1);
+               $$->location = yylloc;
+       }
+|      INTEGER_STRING {
+               $$ = _token_create_str (parser, INTEGER_STRING, $1);
+               $$->location = yylloc;
+       }
+|      operator {
+               $$ = _token_create_ival (parser, $1, $1);
+               $$->location = yylloc;
+       }
+|      OTHER {
+               $$ = _token_create_str (parser, OTHER, $1);
+               $$->location = yylloc;
+       }
+|      SPACE {
+               $$ = _token_create_ival (parser, SPACE, SPACE);
+               $$->location = yylloc;
+       }
+;
+
+operator:
+       '['                     { $$ = '['; }
+|      ']'                     { $$ = ']'; }
+|      '('                     { $$ = '('; }
+|      ')'                     { $$ = ')'; }
+|      '{'                     { $$ = '{'; }
+|      '}'                     { $$ = '}'; }
+|      '.'                     { $$ = '.'; }
+|      '&'                     { $$ = '&'; }
+|      '*'                     { $$ = '*'; }
+|      '+'                     { $$ = '+'; }
+|      '-'                     { $$ = '-'; }
+|      '~'                     { $$ = '~'; }
+|      '!'                     { $$ = '!'; }
+|      '/'                     { $$ = '/'; }
+|      '%'                     { $$ = '%'; }
+|      LEFT_SHIFT              { $$ = LEFT_SHIFT; }
+|      RIGHT_SHIFT             { $$ = RIGHT_SHIFT; }
+|      '<'                     { $$ = '<'; }
+|      '>'                     { $$ = '>'; }
+|      LESS_OR_EQUAL           { $$ = LESS_OR_EQUAL; }
+|      GREATER_OR_EQUAL        { $$ = GREATER_OR_EQUAL; }
+|      EQUAL                   { $$ = EQUAL; }
+|      NOT_EQUAL               { $$ = NOT_EQUAL; }
+|      '^'                     { $$ = '^'; }
+|      '|'                     { $$ = '|'; }
+|      AND                     { $$ = AND; }
+|      OR                      { $$ = OR; }
+|      ';'                     { $$ = ';'; }
+|      ','                     { $$ = ','; }
+|      '='                     { $$ = '='; }
+|      PASTE                   { $$ = PASTE; }
+;
+
+%%
+
+string_list_t *
+_string_list_create (void *ctx)
+{
+       string_list_t *list;
+
+       list = talloc (ctx, string_list_t);
+       list->head = NULL;
+       list->tail = NULL;
+
+       return list;
+}
+
+void
+_string_list_append_item (string_list_t *list, const char *str)
+{
+       string_node_t *node;
+
+       node = talloc (list, string_node_t);
+       node->str = talloc_strdup (node, str);
+
+       node->next = NULL;
+
+       if (list->head == NULL) {
+               list->head = node;
+       } else {
+               list->tail->next = node;
+       }
+
+       list->tail = node;
+}
+
+int
+_string_list_contains (string_list_t *list, const char *member, int *index)
+{
+       string_node_t *node;
+       int i;
+
+       if (list == NULL)
+               return 0;
+
+       for (i = 0, node = list->head; node; i++, node = node->next) {
+               if (strcmp (node->str, member) == 0) {
+                       if (index)
+                               *index = i;
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+int
+_string_list_length (string_list_t *list)
+{
+       int length = 0;
+       string_node_t *node;
+
+       if (list == NULL)
+               return 0;
+
+       for (node = list->head; node; node = node->next)
+               length++;
+
+       return length;
+}
+
+int
+_string_list_equal (string_list_t *a, string_list_t *b)
+{
+       string_node_t *node_a, *node_b;
+
+       if (a == NULL && b == NULL)
+               return 1;
+
+       if (a == NULL || b == NULL)
+               return 0;
+
+       for (node_a = a->head, node_b = b->head;
+            node_a && node_b;
+            node_a = node_a->next, node_b = node_b->next)
+       {
+               if (strcmp (node_a->str, node_b->str))
+                       return 0;
+       }
+
+       /* Catch the case of lists being different lengths, (which
+        * would cause the loop above to terminate after the shorter
+        * list). */
+       return node_a == node_b;
+}
+
+argument_list_t *
+_argument_list_create (void *ctx)
+{
+       argument_list_t *list;
+
+       list = talloc (ctx, argument_list_t);
+       list->head = NULL;
+       list->tail = NULL;
+
+       return list;
+}
+
+void
+_argument_list_append (argument_list_t *list, token_list_t *argument)
+{
+       argument_node_t *node;
+
+       node = talloc (list, argument_node_t);
+       node->argument = argument;
+
+       node->next = NULL;
+
+       if (list->head == NULL) {
+               list->head = node;
+       } else {
+               list->tail->next = node;
+       }
+
+       list->tail = node;
+}
+
+int
+_argument_list_length (argument_list_t *list)
+{
+       int length = 0;
+       argument_node_t *node;
+
+       if (list == NULL)
+               return 0;
+
+       for (node = list->head; node; node = node->next)
+               length++;
+
+       return length;
+}
+
+token_list_t *
+_argument_list_member_at (argument_list_t *list, int index)
+{
+       argument_node_t *node;
+       int i;
+
+       if (list == NULL)
+               return NULL;
+
+       node = list->head;
+       for (i = 0; i < index; i++) {
+               node = node->next;
+               if (node == NULL)
+                       break;
+       }
+
+       if (node)
+               return node->argument;
+
+       return NULL;
+}
+
+/* Note: This function talloc_steal()s the str pointer. */
+token_t *
+_token_create_str (void *ctx, int type, char *str)
+{
+       token_t *token;
+
+       token = talloc (ctx, token_t);
+       token->type = type;
+       token->value.str = talloc_steal (token, str);
+
+       return token;
+}
+
+token_t *
+_token_create_ival (void *ctx, int type, int ival)
+{
+       token_t *token;
+
+       token = talloc (ctx, token_t);
+       token->type = type;
+       token->value.ival = ival;
+
+       return token;
+}
+
+token_list_t *
+_token_list_create (void *ctx)
+{
+       token_list_t *list;
+
+       list = talloc (ctx, token_list_t);
+       list->head = NULL;
+       list->tail = NULL;
+       list->non_space_tail = NULL;
+
+       return list;
+}
+
+void
+_token_list_append (token_list_t *list, token_t *token)
+{
+       token_node_t *node;
+
+       node = talloc (list, token_node_t);
+       node->token = talloc_reference (list, token);
+
+       node->next = NULL;
+
+       if (list->head == NULL) {
+               list->head = node;
+       } else {
+               list->tail->next = node;
+       }
+
+       list->tail = node;
+       if (token->type != SPACE)
+               list->non_space_tail = node;
+}
+
+void
+_token_list_append_list (token_list_t *list, token_list_t *tail)
+{
+       if (tail == NULL || tail->head == NULL)
+               return;
+
+       if (list->head == NULL) {
+               list->head = tail->head;
+       } else {
+               list->tail->next = tail->head;
+       }
+
+       list->tail = tail->tail;
+       list->non_space_tail = tail->non_space_tail;
+}
+
+static token_list_t *
+_token_list_copy (void *ctx, token_list_t *other)
+{
+       token_list_t *copy;
+       token_node_t *node;
+
+       if (other == NULL)
+               return NULL;
+
+       copy = _token_list_create (ctx);
+       for (node = other->head; node; node = node->next)
+               _token_list_append (copy, node->token);
+
+       return copy;
+}
+
+static void
+_token_list_trim_trailing_space (token_list_t *list)
+{
+       token_node_t *tail, *next;
+
+       if (list->non_space_tail) {
+               tail = list->non_space_tail->next;
+               list->non_space_tail->next = NULL;
+               list->tail = list->non_space_tail;
+
+               while (tail) {
+                       next = tail->next;
+                       talloc_free (tail);
+                       tail = next;
+               }
+       }
+}
+
+int
+_token_list_equal_ignoring_space (token_list_t *a, token_list_t *b)
+{
+       token_node_t *node_a, *node_b;
+
+       node_a = a->head;
+       node_b = b->head;
+
+       while (1)
+       {
+               if (node_a == NULL && node_b == NULL)
+                       break;
+
+               if (node_a == NULL || node_b == NULL)
+                       return 0;
+
+               if (node_a->token->type == SPACE) {
+                       node_a = node_a->next;
+                       continue;
+               }
+
+               if (node_b->token->type == SPACE) {
+                       node_b = node_b->next;
+                       continue;
+               }
+
+               if (node_a->token->type != node_b->token->type)
+                       return 0;
+
+               switch (node_a->token->type) {
+               case INTEGER:
+                       if (node_a->token->value.ival != 
+                           node_b->token->value.ival)
+                       {
+                               return 0;
+                       }
+                       break;
+               case IDENTIFIER:
+               case INTEGER_STRING:
+               case OTHER:
+                       if (strcmp (node_a->token->value.str,
+                                   node_b->token->value.str))
+                       {
+                               return 0;
+                       }
+                       break;
+               }
+
+               node_a = node_a->next;
+               node_b = node_b->next;
+       }
+
+       return 1;
+}
+
+static void
+_token_print (char **out, token_t *token)
+{
+       if (token->type < 256) {
+               glcpp_printf (*out, "%c", token->type);
+               return;
+       }
+
+       switch (token->type) {
+       case INTEGER:
+               glcpp_printf (*out, "%" PRIiMAX, token->value.ival);
+               break;
+       case IDENTIFIER:
+       case INTEGER_STRING:
+       case OTHER:
+               glcpp_print (*out, token->value.str);
+               break;
+       case SPACE:
+               glcpp_print (*out, " ");
+               break;
+       case LEFT_SHIFT:
+               glcpp_print (*out, "<<");
+               break;
+       case RIGHT_SHIFT:
+               glcpp_print (*out, ">>");
+               break;
+       case LESS_OR_EQUAL:
+               glcpp_print (*out, "<=");
+               break;
+       case GREATER_OR_EQUAL:
+               glcpp_print (*out, ">=");
+               break;
+       case EQUAL:
+               glcpp_print (*out, "==");
+               break;
+       case NOT_EQUAL:
+               glcpp_print (*out, "!=");
+               break;
+       case AND:
+               glcpp_print (*out, "&&");
+               break;
+       case OR:
+               glcpp_print (*out, "||");
+               break;
+       case PASTE:
+               glcpp_print (*out, "##");
+               break;
+       case COMMA_FINAL:
+               glcpp_print (*out, ",");
+               break;
+       case PLACEHOLDER:
+               /* Nothing to print. */
+               break;
+       default:
+               assert(!"Error: Don't know how to print token.");
+               break;
+       }
+}
+
+/* Return a new token (talloc()ed off of 'token') formed by pasting
+ * 'token' and 'other'. Note that this function may return 'token' or
+ * 'other' directly rather than allocating anything new.
+ *
+ * Caution: Only very cursory error-checking is performed to see if
+ * the final result is a valid single token. */
+static token_t *
+_token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
+{
+       token_t *combined = NULL;
+
+       /* Pasting a placeholder onto anything makes no change. */
+       if (other->type == PLACEHOLDER)
+               return token;
+
+       /* When 'token' is a placeholder, just return 'other'. */
+       if (token->type == PLACEHOLDER)
+               return other;
+
+       /* A very few single-character punctuators can be combined
+        * with another to form a multi-character punctuator. */
+       switch (token->type) {
+       case '<':
+               if (other->type == '<')
+                       combined = _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT);
+               else if (other->type == '=')
+                       combined = _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL);
+               break;
+       case '>':
+               if (other->type == '>')
+                       combined = _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT);
+               else if (other->type == '=')
+                       combined = _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL);
+               break;
+       case '=':
+               if (other->type == '=')
+                       combined = _token_create_ival (token, EQUAL, EQUAL);
+               break;
+       case '!':
+               if (other->type == '=')
+                       combined = _token_create_ival (token, NOT_EQUAL, NOT_EQUAL);
+               break;
+       case '&':
+               if (other->type == '&')
+                       combined = _token_create_ival (token, AND, AND);
+               break;
+       case '|':
+               if (other->type == '|')
+                       combined = _token_create_ival (token, OR, OR);
+               break;
+       }
+
+       if (combined != NULL) {
+               /* Inherit the location from the first token */
+               combined->location = token->location;
+               return combined;
+       }
+
+       /* Two string-valued tokens can usually just be mashed
+        * together.
+        *
+        * XXX: This isn't actually legitimate. Several things here
+        * should result in a diagnostic since the result cannot be a
+        * valid, single pre-processing token. For example, pasting
+        * "123" and "abc" is not legal, but we don't catch that
+        * here. */
+       if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) &&
+           (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING))
+       {
+               char *str;
+
+               str = talloc_asprintf (token, "%s%s", token->value.str,
+                                      other->value.str);
+               combined = _token_create_str (token, token->type, str);
+               combined->location = token->location;
+               return combined;
+       }
+
+       glcpp_error (&token->location, parser, "");
+       glcpp_print (parser->info_log, "Pasting \"");
+       _token_print (&parser->info_log, token);
+       glcpp_print (parser->info_log, "\" and \"");
+       _token_print (&parser->info_log, other);
+       glcpp_print (parser->info_log, "\" does not give a valid preprocessing token.\n");
+
+       return token;
+}
+
+static void
+_token_list_print (glcpp_parser_t *parser, token_list_t *list)
+{
+       token_node_t *node;
+
+       if (list == NULL)
+               return;
+
+       for (node = list->head; node; node = node->next)
+               _token_print (&parser->output, node->token);
+}
+
+void
+yyerror (YYLTYPE *locp, glcpp_parser_t *parser, const char *error)
+{
+       glcpp_error(locp, parser, "%s", error);
+}
+
+static void add_builtin_define(glcpp_parser_t *parser,
+                              const char *name, int value)
+{
+   token_t *tok;
+   token_list_t *list;
+
+   tok = _token_create_ival (parser, INTEGER, value);
+
+   list = _token_list_create(parser);
+   _token_list_append(list, tok);
+   _define_object_macro(parser, NULL, name, list);
+
+   talloc_unlink(parser, tok);
+}
+
+glcpp_parser_t *
+glcpp_parser_create (const struct gl_extensions *extensions)
+{
+       glcpp_parser_t *parser;
+       int language_version;
+
+       parser = talloc (NULL, glcpp_parser_t);
+
+       glcpp_lex_init_extra (parser, &parser->scanner);
+       parser->defines = hash_table_ctor (32, hash_table_string_hash,
+                                          hash_table_string_compare);
+       parser->active = NULL;
+       parser->lexing_if = 0;
+       parser->space_tokens = 1;
+       parser->newline_as_space = 0;
+       parser->in_control_line = 0;
+       parser->paren_count = 0;
+
+       parser->skip_stack = NULL;
+
+       parser->lex_from_list = NULL;
+       parser->lex_from_node = NULL;
+
+       parser->output = talloc_strdup(parser, "");
+       parser->info_log = talloc_strdup(parser, "");
+       parser->error = 0;
+
+       /* Add pre-defined macros. */
+       add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
+       add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
+
+       if (extensions != NULL) {
+          if (extensions->EXT_texture_array) {
+             add_builtin_define(parser, "GL_EXT_texture_array", 1);
+          }
+
+          if (extensions->ARB_fragment_coord_conventions)
+             add_builtin_define(parser, "GL_ARB_fragment_coord_conventions",
+                                1);
+       }
+
+       language_version = 110;
+       add_builtin_define(parser, "__VERSION__", language_version);
+
+       return parser;
+}
+
+int
+glcpp_parser_parse (glcpp_parser_t *parser)
+{
+       return yyparse (parser);
+}
+
+void
+glcpp_parser_destroy (glcpp_parser_t *parser)
+{
+       glcpp_lex_destroy (parser->scanner);
+       hash_table_dtor (parser->defines);
+       talloc_free (parser);
+}
+
+typedef enum function_status
+{
+       FUNCTION_STATUS_SUCCESS,
+       FUNCTION_NOT_A_FUNCTION,
+       FUNCTION_UNBALANCED_PARENTHESES
+} function_status_t;
+
+/* Find a set of function-like macro arguments by looking for a
+ * balanced set of parentheses.
+ *
+ * When called, 'node' should be the opening-parenthesis token, (or
+ * perhaps preceeding SPACE tokens). Upon successful return *last will
+ * be the last consumed node, (corresponding to the closing right
+ * parenthesis).
+ *
+ * Return values:
+ *
+ *   FUNCTION_STATUS_SUCCESS:
+ *
+ *     Successfully parsed a set of function arguments.        
+ *
+ *   FUNCTION_NOT_A_FUNCTION:
+ *
+ *     Macro name not followed by a '('. This is not an error, but
+ *     simply that the macro name should be treated as a non-macro.
+ *
+ *   FUNCTION_UNBALANCED_PARENTHESES
+ *
+ *     Macro name is not followed by a balanced set of parentheses.
+ */
+static function_status_t
+_arguments_parse (argument_list_t *arguments,
+                 token_node_t *node,
+                 token_node_t **last)
+{
+       token_list_t *argument;
+       int paren_count;
+
+       node = node->next;
+
+       /* Ignore whitespace before first parenthesis. */
+       while (node && node->token->type == SPACE)
+               node = node->next;
+
+       if (node == NULL || node->token->type != '(')
+               return FUNCTION_NOT_A_FUNCTION;
+
+       node = node->next;
+
+       argument = _token_list_create (arguments);
+       _argument_list_append (arguments, argument);
+
+       for (paren_count = 1; node; node = node->next) {
+               if (node->token->type == '(')
+               {
+                       paren_count++;
+               }
+               else if (node->token->type == ')')
+               {
+                       paren_count--;
+                       if (paren_count == 0)
+                               break;
+               }
+
+               if (node->token->type == ',' &&
+                        paren_count == 1)
+               {
+                       _token_list_trim_trailing_space (argument);
+                       argument = _token_list_create (arguments);
+                       _argument_list_append (arguments, argument);
+               }
+               else {
+                       if (argument->head == NULL) {
+                               /* Don't treat initial whitespace as
+                                * part of the arguement. */
+                               if (node->token->type == SPACE)
+                                       continue;
+                       }
+                       _token_list_append (argument, node->token);
+               }
+       }
+
+       if (paren_count)
+               return FUNCTION_UNBALANCED_PARENTHESES;
+
+       *last = node;
+
+       return FUNCTION_STATUS_SUCCESS;
+}
+
+static token_list_t *
+_token_list_create_with_one_space (void *ctx)
+{
+       token_list_t *list;
+       token_t *space;
+
+       list = _token_list_create (ctx);
+       space = _token_create_ival (list, SPACE, SPACE);
+       _token_list_append (list, space);
+
+       return list;
+}
+
+static void
+_glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list)
+{
+       token_list_t *expanded;
+       token_t *token;
+
+       expanded = _token_list_create (parser);
+       token = _token_create_ival (parser, type, type);
+       _token_list_append (expanded, token);
+       _glcpp_parser_expand_token_list (parser, list);
+       _token_list_append_list (expanded, list);
+       glcpp_parser_lex_from (parser, expanded);
+}
+
+/* This is a helper function that's essentially part of the
+ * implementation of _glcpp_parser_expand_node. It shouldn't be called
+ * except for by that function.
+ *
+ * Returns NULL if node is a simple token with no expansion, (that is,
+ * although 'node' corresponds to an identifier defined as a
+ * function-like macro, it is not followed with a parenthesized
+ * argument list).
+ *
+ * Compute the complete expansion of node (which is a function-like
+ * macro) and subsequent nodes which are arguments.
+ *
+ * Returns the token list that results from the expansion and sets
+ * *last to the last node in the list that was consumed by the
+ * expansion. Specifically, *last will be set as follows: as the
+ * token of the closing right parenthesis.
+ */
+static token_list_t *
+_glcpp_parser_expand_function (glcpp_parser_t *parser,
+                              token_node_t *node,
+                              token_node_t **last)
+                              
+{
+       macro_t *macro;
+       const char *identifier;
+       argument_list_t *arguments;
+       function_status_t status;
+       token_list_t *substituted;
+       int parameter_index;
+
+       identifier = node->token->value.str;
+
+       macro = hash_table_find (parser->defines, identifier);
+
+       assert (macro->is_function);
+
+       arguments = _argument_list_create (parser);
+       status = _arguments_parse (arguments, node, last);
+
+       switch (status) {
+       case FUNCTION_STATUS_SUCCESS:
+               break;
+       case FUNCTION_NOT_A_FUNCTION:
+               return NULL;
+       case FUNCTION_UNBALANCED_PARENTHESES:
+               glcpp_error (&node->token->location, parser, "Macro %s call has unbalanced parentheses\n", identifier);
+               return NULL;
+       }
+
+       /* Replace a macro defined as empty with a SPACE token. */
+       if (macro->replacements == NULL) {
+               talloc_free (arguments);
+               return _token_list_create_with_one_space (parser);
+       }
+
+       if (! ((_argument_list_length (arguments) == 
+               _string_list_length (macro->parameters)) ||
+              (_string_list_length (macro->parameters) == 0 &&
+               _argument_list_length (arguments) == 1 &&
+               arguments->head->argument->head == NULL)))
+       {
+               glcpp_error (&node->token->location, parser,
+                             "Error: macro %s invoked with %d arguments (expected %d)\n",
+                             identifier,
+                             _argument_list_length (arguments),
+                             _string_list_length (macro->parameters));
+               return NULL;
+       }
+
+       /* Perform argument substitution on the replacement list. */
+       substituted = _token_list_create (arguments);
+
+       for (node = macro->replacements->head; node; node = node->next)
+       {
+               if (node->token->type == IDENTIFIER &&
+                   _string_list_contains (macro->parameters,
+                                          node->token->value.str,
+                                          &parameter_index))
+               {
+                       token_list_t *argument;
+                       argument = _argument_list_member_at (arguments,
+                                                            parameter_index);
+                       /* Before substituting, we expand the argument
+                        * tokens, or append a placeholder token for
+                        * an empty argument. */
+                       if (argument->head) {
+                               token_list_t *expanded_argument;
+                               expanded_argument = _token_list_copy (parser,
+                                                                     argument);
+                               _glcpp_parser_expand_token_list (parser,
+                                                                expanded_argument);
+                               _token_list_append_list (substituted,
+                                                        expanded_argument);
+                       } else {
+                               token_t *new_token;
+
+                               new_token = _token_create_ival (substituted,
+                                                               PLACEHOLDER,
+                                                               PLACEHOLDER);
+                               _token_list_append (substituted, new_token);
+                       }
+               } else {
+                       _token_list_append (substituted, node->token);
+               }
+       }
+
+       /* After argument substitution, and before further expansion
+        * below, implement token pasting. */
+
+       _token_list_trim_trailing_space (substituted);
+
+       node = substituted->head;
+       while (node)
+       {
+               token_node_t *next_non_space;
+
+               /* Look ahead for a PASTE token, skipping space. */
+               next_non_space = node->next;
+               while (next_non_space && next_non_space->token->type == SPACE)
+                       next_non_space = next_non_space->next;
+
+               if (next_non_space == NULL)
+                       break;
+
+               if (next_non_space->token->type != PASTE) {
+                       node = next_non_space;
+                       continue;
+               }
+
+               /* Now find the next non-space token after the PASTE. */
+               next_non_space = next_non_space->next;
+               while (next_non_space && next_non_space->token->type == SPACE)
+                       next_non_space = next_non_space->next;
+
+               if (next_non_space == NULL) {
+                       yyerror (&node->token->location, parser, "'##' cannot appear at either end of a macro expansion\n");
+                       return NULL;
+               }
+
+               node->token = _token_paste (parser, node->token, next_non_space->token);
+               node->next = next_non_space->next;
+               if (next_non_space == substituted->tail)
+                       substituted->tail = node;
+
+               node = node->next;
+       }
+
+       substituted->non_space_tail = substituted->tail;
+
+       return substituted;
+}
+
+/* Compute the complete expansion of node, (and subsequent nodes after
+ * 'node' in the case that 'node' is a function-like macro and
+ * subsequent nodes are arguments).
+ *
+ * Returns NULL if node is a simple token with no expansion.
+ *
+ * Otherwise, returns the token list that results from the expansion
+ * and sets *last to the last node in the list that was consumed by
+ * the expansion. Specifically, *last will be set as follows:
+ *
+ *     As 'node' in the case of object-like macro expansion.
+ *
+ *     As the token of the closing right parenthesis in the case of
+ *     function-like macro expansion.
+ */
+static token_list_t *
+_glcpp_parser_expand_node (glcpp_parser_t *parser,
+                          token_node_t *node,
+                          token_node_t **last)
+{
+       token_t *token = node->token;
+       const char *identifier;
+       macro_t *macro;
+
+       /* We only expand identifiers */
+       if (token->type != IDENTIFIER) {
+               /* We change any COMMA into a COMMA_FINAL to prevent
+                * it being mistaken for an argument separator
+                * later. */
+               if (token->type == ',') {
+                       token->type = COMMA_FINAL;
+                       token->value.ival = COMMA_FINAL;
+               }
+
+               return NULL;
+       }
+
+       /* Look up this identifier in the hash table. */
+       identifier = token->value.str;
+       macro = hash_table_find (parser->defines, identifier);
+
+       /* Not a macro, so no expansion needed. */
+       if (macro == NULL)
+               return NULL;
+
+       /* Finally, don't expand this macro if we're already actively
+        * expanding it, (to avoid infinite recursion). */
+       if (_active_list_contains (parser->active, identifier)) {
+               /* We change the token type here from IDENTIFIER to
+                * OTHER to prevent any future expansion of this
+                * unexpanded token. */
+               char *str;
+               token_list_t *expansion;
+               token_t *final;
+
+               str = talloc_strdup (parser, token->value.str);
+               final = _token_create_str (parser, OTHER, str);
+               expansion = _token_list_create (parser);
+               _token_list_append (expansion, final);
+               *last = node;
+               return expansion;
+       }
+
+       if (! macro->is_function)
+       {
+               *last = node;
+
+               /* Replace a macro defined as empty with a SPACE token. */
+               if (macro->replacements == NULL)
+                       return _token_list_create_with_one_space (parser);
+
+               return _token_list_copy (parser, macro->replacements);
+       }
+
+       return _glcpp_parser_expand_function (parser, node, last);
+}
+
+/* Push a new identifier onto the active list, returning the new list.
+ *
+ * Here, 'marker' is the token node that appears in the list after the
+ * expansion of 'identifier'. That is, when the list iterator begins
+ * examinging 'marker', then it is time to pop this node from the
+ * active stack.
+ */
+active_list_t *
+_active_list_push (active_list_t *list,
+                  const char *identifier,
+                  token_node_t *marker)
+{
+       active_list_t *node;
+
+       node = talloc (list, active_list_t);
+       node->identifier = talloc_strdup (node, identifier);
+       node->marker = marker;
+       node->next = list;
+
+       return node;
+}
+
+active_list_t *
+_active_list_pop (active_list_t *list)
+{
+       active_list_t *node = list;
+
+       if (node == NULL)
+               return NULL;
+
+       node = list->next;
+       talloc_free (list);
+
+       return node;
+}
+
+int
+_active_list_contains (active_list_t *list, const char *identifier)
+{
+       active_list_t *node;
+
+       if (list == NULL)
+               return 0;
+
+       for (node = list; node; node = node->next)
+               if (strcmp (node->identifier, identifier) == 0)
+                       return 1;
+
+       return 0;
+}
+
+/* Walk over the token list replacing nodes with their expansion.
+ * Whenever nodes are expanded the walking will walk over the new
+ * nodes, continuing to expand as necessary. The results are placed in
+ * 'list' itself;
+ */
+static void
+_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
+                                token_list_t *list)
+{
+       token_node_t *node_prev;
+       token_node_t *node, *last = NULL;
+       token_list_t *expansion;
+
+       if (list == NULL)
+               return;
+
+       _token_list_trim_trailing_space (list);
+
+       node_prev = NULL;
+       node = list->head;
+
+       while (node) {
+
+               while (parser->active && parser->active->marker == node)
+                       parser->active = _active_list_pop (parser->active);
+
+               /* Find the expansion for node, which will replace all
+                * nodes from node to last, inclusive. */
+               expansion = _glcpp_parser_expand_node (parser, node, &last);
+               if (expansion) {
+                       token_node_t *n;
+
+                       for (n = node; n != last->next; n = n->next)
+                               while (parser->active &&
+                                      parser->active->marker == n)
+                               {
+                                       parser->active = _active_list_pop (parser->active);
+                               }
+
+                       parser->active = _active_list_push (parser->active,
+                                                           node->token->value.str,
+                                                           last->next);
+                       
+                       /* Splice expansion into list, supporting a
+                        * simple deletion if the expansion is
+                        * empty. */
+                       if (expansion->head) {
+                               if (node_prev)
+                                       node_prev->next = expansion->head;
+                               else
+                                       list->head = expansion->head;
+                               expansion->tail->next = last->next;
+                               if (last == list->tail)
+                                       list->tail = expansion->tail;
+                       } else {
+                               if (node_prev)
+                                       node_prev->next = last->next;
+                               else
+                                       list->head = last->next;
+                               if (last == list->tail)
+                                       list->tail = NULL;
+                       }
+               } else {
+                       node_prev = node;
+               }
+               node = node_prev ? node_prev->next : list->head;
+       }
+
+       while (parser->active)
+               parser->active = _active_list_pop (parser->active);
+
+       list->non_space_tail = list->tail;
+}
+
+void
+_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
+                                        token_list_t *list)
+{
+       if (list == NULL)
+               return;
+
+       _glcpp_parser_expand_token_list (parser, list);
+
+       _token_list_trim_trailing_space (list);
+
+       _token_list_print (parser, list);
+}
+
+static void
+_check_for_reserved_macro_name (glcpp_parser_t *parser, YYLTYPE *loc,
+                               const char *identifier)
+{
+       /* According to the GLSL specification, macro names starting with "__"
+        * or "GL_" are reserved for future use.  So, don't allow them.
+        */
+       if (strncmp(identifier, "__", 2) == 0) {
+               glcpp_error (loc, parser, "Macro names starting with \"__\" are reserved.\n");
+       }
+       if (strncmp(identifier, "GL_", 3) == 0) {
+               glcpp_error (loc, parser, "Macro names starting with \"GL_\" are reserved.\n");
+       }
+}
+
+static int
+_macro_equal (macro_t *a, macro_t *b)
+{
+       if (a->is_function != b->is_function)
+               return 0;
+
+       if (a->is_function) {
+               if (! _string_list_equal (a->parameters, b->parameters))
+                       return 0;
+       }
+
+       return _token_list_equal_ignoring_space (a->replacements,
+                                                b->replacements);
+}
+
+void
+_define_object_macro (glcpp_parser_t *parser,
+                     YYLTYPE *loc,
+                     const char *identifier,
+                     token_list_t *replacements)
+{
+       macro_t *macro, *previous;
+
+       if (loc != NULL)
+               _check_for_reserved_macro_name(parser, loc, identifier);
+
+       macro = talloc (parser, macro_t);
+
+       macro->is_function = 0;
+       macro->parameters = NULL;
+       macro->identifier = talloc_strdup (macro, identifier);
+       macro->replacements = talloc_steal (macro, replacements);
+
+       previous = hash_table_find (parser->defines, identifier);
+       if (previous) {
+               if (_macro_equal (macro, previous)) {
+                       talloc_free (macro);
+                       return;
+               }
+               glcpp_error (loc, parser, "Redefinition of macro %s\n",
+                            identifier);
+       }
+
+       hash_table_insert (parser->defines, macro, identifier);
+}
+
+void
+_define_function_macro (glcpp_parser_t *parser,
+                       YYLTYPE *loc,
+                       const char *identifier,
+                       string_list_t *parameters,
+                       token_list_t *replacements)
+{
+       macro_t *macro, *previous;
+
+       _check_for_reserved_macro_name(parser, loc, identifier);
+
+       macro = talloc (parser, macro_t);
+
+       macro->is_function = 1;
+       macro->parameters = talloc_steal (macro, parameters);
+       macro->identifier = talloc_strdup (macro, identifier);
+       macro->replacements = talloc_steal (macro, replacements);
+
+       previous = hash_table_find (parser->defines, identifier);
+       if (previous) {
+               if (_macro_equal (macro, previous)) {
+                       talloc_free (macro);
+                       return;
+               }
+               glcpp_error (loc, parser, "Redefinition of macro %s\n",
+                            identifier);
+       }
+
+       hash_table_insert (parser->defines, macro, identifier);
+}
+
+static int
+glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
+{
+       token_node_t *node;
+       int ret;
+
+       if (parser->lex_from_list == NULL) {
+               ret = glcpp_lex (yylval, yylloc, parser->scanner);
+
+               /* XXX: This ugly block of code exists for the sole
+                * purpose of converting a NEWLINE token into a SPACE
+                * token, but only in the case where we have seen a
+                * function-like macro name, but have not yet seen its
+                * closing parenthesis.
+                *
+                * There's perhaps a more compact way to do this with
+                * mid-rule actions in the grammar.
+                *
+                * I'm definitely not pleased with the complexity of
+                * this code here.
+                */
+               if (parser->newline_as_space)
+               {
+                       if (ret == '(') {
+                               parser->paren_count++;
+                       } else if (ret == ')') {
+                               parser->paren_count--;
+                               if (parser->paren_count == 0)
+                                       parser->newline_as_space = 0;
+                       } else if (ret == NEWLINE) {
+                               ret = SPACE;
+                       } else if (ret != SPACE) {
+                               if (parser->paren_count == 0)
+                                       parser->newline_as_space = 0;
+                       }
+               }
+               else if (parser->in_control_line)
+               {
+                       if (ret == NEWLINE)
+                               parser->in_control_line = 0;
+               }
+               else if (ret == HASH_DEFINE_OBJ || ret == HASH_DEFINE_FUNC ||
+                          ret == HASH_UNDEF || ret == HASH_IF ||
+                          ret == HASH_IFDEF || ret == HASH_IFNDEF ||
+                          ret == HASH_ELIF || ret == HASH_ELSE ||
+                          ret == HASH_ENDIF || ret == HASH)
+               {
+                       parser->in_control_line = 1;
+               }
+               else if (ret == IDENTIFIER)
+               {
+                       macro_t *macro;
+                       macro = hash_table_find (parser->defines,
+                                                yylval->str);
+                       if (macro && macro->is_function) {
+                               parser->newline_as_space = 1;
+                               parser->paren_count = 0;
+                       }
+               }
+
+               return ret;
+       }
+
+       node = parser->lex_from_node;
+
+       if (node == NULL) {
+               talloc_free (parser->lex_from_list);
+               parser->lex_from_list = NULL;
+               return NEWLINE;
+       }
+
+       *yylval = node->token->value;
+       ret = node->token->type;
+
+       parser->lex_from_node = node->next;
+
+       return ret;
+}
+
+static void
+glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list)
+{
+       token_node_t *node;
+
+       assert (parser->lex_from_list == NULL);
+
+       /* Copy list, eliminating any space tokens. */
+       parser->lex_from_list = _token_list_create (parser);
+
+       for (node = list->head; node; node = node->next) {
+               if (node->token->type == SPACE)
+                       continue;
+               _token_list_append (parser->lex_from_list, node->token);
+       }
+
+       talloc_free (list);
+
+       parser->lex_from_node = parser->lex_from_list->head;
+
+       /* It's possible the list consisted of nothing but whitespace. */
+       if (parser->lex_from_node == NULL) {
+               talloc_free (parser->lex_from_list);
+               parser->lex_from_list = NULL;
+       }
+}
+
+static void
+_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
+                                 int condition)
+{
+       skip_type_t current = SKIP_NO_SKIP;
+       skip_node_t *node;
+
+       if (parser->skip_stack)
+               current = parser->skip_stack->type;
+
+       node = talloc (parser, skip_node_t);
+       node->loc = *loc;
+
+       if (current == SKIP_NO_SKIP) {
+               if (condition)
+                       node->type = SKIP_NO_SKIP;
+               else
+                       node->type = SKIP_TO_ELSE;
+       } else {
+               node->type = SKIP_TO_ENDIF;
+       }
+
+       node->next = parser->skip_stack;
+       parser->skip_stack = node;
+}
+
+static void
+_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
+                                   const char *type, int condition)
+{
+       if (parser->skip_stack == NULL) {
+               glcpp_error (loc, parser, "%s without #if\n", type);
+               return;
+       }
+
+       if (parser->skip_stack->type == SKIP_TO_ELSE) {
+               if (condition)
+                       parser->skip_stack->type = SKIP_NO_SKIP;
+       } else {
+               parser->skip_stack->type = SKIP_TO_ENDIF;
+       }
+}
+
+static void
+_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc)
+{
+       skip_node_t *node;
+
+       if (parser->skip_stack == NULL) {
+               glcpp_error (loc, parser, "#endif without #if\n");
+               return;
+       }
+
+       node = parser->skip_stack;
+       parser->skip_stack = node->next;
+       talloc_free (node);
+}
diff --git a/src/glsl/glcpp/glcpp.c b/src/glsl/glcpp/glcpp.c
new file mode 100644 (file)
index 0000000..5671493
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include "glcpp.h"
+
+extern int yydebug;
+
+/* Read from fd until EOF and return a string of everything read.
+ */
+static char *
+load_text_fd (void *ctx, int fd)
+{
+#define CHUNK 4096
+       char *text = NULL;
+       ssize_t text_size = 0;
+       ssize_t total_read = 0;
+       ssize_t bytes;
+
+       while (1) {
+               if (total_read + CHUNK + 1 > text_size) {
+                       text_size = text_size ? text_size * 2 : CHUNK + 1;
+                       text = talloc_realloc_size (ctx, text, text_size);
+                       if (text == NULL) {
+                               fprintf (stderr, "Out of memory\n");
+                               return NULL;
+                       }
+               }
+               bytes = read (fd, text + total_read, CHUNK);
+               if (bytes < 0) {
+                       fprintf (stderr, "Error while reading: %s\n",
+                                strerror (errno));
+                       talloc_free (text);
+                       return NULL;
+               }
+
+               if (bytes == 0) {
+                       break;
+               }
+
+               total_read += bytes;
+       }
+
+       text[total_read] = '\0';
+
+       return text;
+}
+
+static char *
+load_text_file(void *ctx, const char *filename)
+{
+       char *text;
+       int fd;
+
+       if (filename == NULL || strcmp (filename, "-") == 0)
+               return load_text_fd (ctx, STDIN_FILENO);
+
+       fd = open (filename, O_RDONLY);
+       if (fd < 0) {
+               fprintf (stderr, "Failed to open file %s: %s\n",
+                        filename, strerror (errno));
+               return NULL;
+       }
+
+       text = load_text_fd (ctx, fd);
+
+       close(fd);
+
+       return text;
+}
+
+int
+main (int argc, char *argv[])
+{
+       char *filename = NULL;
+       void *ctx = talloc(NULL, void*);
+       char *info_log = talloc_strdup(ctx, "");
+       const char *shader;
+       int ret;
+
+       if (argc) {
+               filename = argv[1];
+       }
+
+       shader = load_text_file (ctx, filename);
+       if (shader == NULL)
+          return 1;
+
+       ret = preprocess(ctx, &shader, &info_log, NULL);
+
+       printf("%s", shader);
+       fprintf(stderr, "%s", info_log);
+
+       talloc_free(ctx);
+
+       return ret;
+}
diff --git a/src/glsl/glcpp/glcpp.h b/src/glsl/glcpp/glcpp.h
new file mode 100644 (file)
index 0000000..0bebdb9
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+#ifndef GLCPP_H
+#define GLCPP_H
+
+#include <stdint.h>
+
+#include <talloc.h>
+
+#include "program/hash_table.h"
+
+#define yyscan_t void*
+
+/* Some data types used for parser values. */
+
+typedef struct string_node {
+       const char *str;
+       struct string_node *next;
+} string_node_t;
+
+typedef struct string_list {
+       string_node_t *head;
+       string_node_t *tail;
+} string_list_t;
+
+typedef struct token token_t;
+typedef struct token_list token_list_t;
+
+typedef union YYSTYPE
+{
+       intmax_t ival;
+       char *str;
+       string_list_t *string_list;
+       token_t *token;
+       token_list_t *token_list;
+} YYSTYPE;
+
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+
+typedef struct YYLTYPE {
+   int first_line;
+   int first_column;
+   int last_line;
+   int last_column;
+   unsigned source;
+} YYLTYPE;
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+
+# define YYLLOC_DEFAULT(Current, Rhs, N)                       \
+do {                                                           \
+   if (N)                                                      \
+   {                                                           \
+      (Current).first_line   = YYRHSLOC(Rhs, 1).first_line;    \
+      (Current).first_column = YYRHSLOC(Rhs, 1).first_column;  \
+      (Current).last_line    = YYRHSLOC(Rhs, N).last_line;     \
+      (Current).last_column  = YYRHSLOC(Rhs, N).last_column;   \
+   }                                                           \
+   else                                                                \
+   {                                                           \
+      (Current).first_line   = (Current).last_line =           \
+        YYRHSLOC(Rhs, 0).last_line;                            \
+      (Current).first_column = (Current).last_column =         \
+        YYRHSLOC(Rhs, 0).last_column;                          \
+   }                                                           \
+   (Current).source = 0;                                       \
+} while (0)
+
+struct token {
+       int type;
+       YYSTYPE value;
+       YYLTYPE location;
+};
+
+typedef struct token_node {
+       token_t *token;
+       struct token_node *next;
+} token_node_t;
+
+struct token_list {
+       token_node_t *head;
+       token_node_t *tail;
+       token_node_t *non_space_tail;
+};
+
+typedef struct argument_node {
+       token_list_t *argument;
+       struct argument_node *next;
+} argument_node_t;
+
+typedef struct argument_list {
+       argument_node_t *head;
+       argument_node_t *tail;
+} argument_list_t;
+
+typedef struct glcpp_parser glcpp_parser_t;
+
+typedef enum {
+       TOKEN_CLASS_IDENTIFIER,
+       TOKEN_CLASS_IDENTIFIER_FINALIZED,
+       TOKEN_CLASS_FUNC_MACRO,
+       TOKEN_CLASS_OBJ_MACRO
+} token_class_t;
+
+token_class_t
+glcpp_parser_classify_token (glcpp_parser_t *parser,
+                            const char *identifier,
+                            int *parameter_index);
+
+typedef struct {
+       int is_function;
+       string_list_t *parameters;
+       const char *identifier;
+       token_list_t *replacements;
+} macro_t;
+
+typedef struct expansion_node {
+       macro_t *macro;
+       token_node_t *replacements;
+       struct expansion_node *next;
+} expansion_node_t;
+
+typedef enum skip_type {
+       SKIP_NO_SKIP,
+       SKIP_TO_ELSE,
+       SKIP_TO_ENDIF
+} skip_type_t;
+
+typedef struct skip_node {
+       skip_type_t type;
+       YYLTYPE loc; /* location of the initial #if/#elif/... */
+       struct skip_node *next;
+} skip_node_t;
+
+typedef struct active_list {
+       const char *identifier;
+       token_node_t *marker;
+       struct active_list *next;
+} active_list_t;
+
+struct glcpp_parser {
+       yyscan_t scanner;
+       struct hash_table *defines;
+       active_list_t *active;
+       int lexing_if;
+       int space_tokens;
+       int newline_as_space;
+       int in_control_line;
+       int paren_count;
+       skip_node_t *skip_stack;
+       token_list_t *lex_from_list;
+       token_node_t *lex_from_node;
+       char *output;
+       char *info_log;
+       int error;
+};
+
+struct gl_extensions;
+
+glcpp_parser_t *
+glcpp_parser_create (const struct gl_extensions *extensions);
+
+int
+glcpp_parser_parse (glcpp_parser_t *parser);
+
+void
+glcpp_parser_destroy (glcpp_parser_t *parser);
+
+int
+preprocess(void *talloc_ctx, const char **shader, char **info_log,
+          const struct gl_extensions *extensions);
+
+/* Functions for writing to the info log */
+
+void
+glcpp_error (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...);
+
+void
+glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...);
+
+/* Generated by glcpp-lex.l to glcpp-lex.c */
+
+int
+glcpp_lex_init_extra (glcpp_parser_t *parser, yyscan_t* scanner);
+
+void
+glcpp_lex_set_source_string(glcpp_parser_t *parser, const char *shader);
+
+int
+glcpp_lex (YYSTYPE *lvalp, YYLTYPE *llocp, yyscan_t scanner);
+
+int
+glcpp_lex_destroy (yyscan_t scanner);
+
+/* Generated by glcpp-parse.y to glcpp-parse.c */
+
+int
+yyparse (glcpp_parser_t *parser);
+
+#endif
diff --git a/src/glsl/glcpp/pp.c b/src/glsl/glcpp/pp.c
new file mode 100644 (file)
index 0000000..a1d00c4
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include "glcpp.h"
+#include "main/core.h" /* for isblank() on MSVC */
+
+void
+glcpp_error (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
+{
+       va_list ap;
+
+       parser->error = 1;
+       parser->info_log = talloc_asprintf_append(parser->info_log,
+                                                 "%u:%u(%u): "
+                                                 "preprocessor error: ",
+                                                 locp->source,
+                                                 locp->first_line,
+                                                 locp->first_column);
+       va_start(ap, fmt);
+       parser->info_log = talloc_vasprintf_append(parser->info_log, fmt, ap);
+       va_end(ap);
+       parser->info_log = talloc_strdup_append(parser->info_log, "\n");
+}
+
+void
+glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
+{
+       va_list ap;
+
+       parser->info_log = talloc_asprintf_append(parser->info_log,
+                                                 "%u:%u(%u): "
+                                                 "preprocessor warning: ",
+                                                 locp->source,
+                                                 locp->first_line,
+                                                 locp->first_column);
+       va_start(ap, fmt);
+       parser->info_log = talloc_vasprintf_append(parser->info_log, fmt, ap);
+       va_end(ap);
+       parser->info_log = talloc_strdup_append(parser->info_log, "\n");
+}
+
+/* Searches backwards for '^ *#' from a given starting point. */
+static int
+in_directive(const char *shader, const char *ptr)
+{
+       assert(ptr >= shader);
+
+       /* Search backwards for '#'. If we find a \n first, it doesn't count */
+       for (; ptr >= shader && *ptr != '#'; ptr--) {
+               if (*ptr == '\n')
+                       return 0;
+       }
+       if (ptr >= shader) {
+               /* Found '#'...look for spaces preceded by a newline */
+               for (ptr--; ptr >= shader && isblank(*ptr); ptr--);
+               // FIXME: I don't think the '\n' case can happen
+               if (ptr < shader || *ptr == '\n')
+                       return 1;
+       }
+       return 0;
+}
+
+/* Remove any line continuation characters in preprocessing directives.
+ * However, ignore any in GLSL code, as "There is no line continuation
+ * character" (1.30 page 9) in GLSL.
+ */
+static char *
+remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
+{
+       int in_continued_line = 0;
+       int extra_newlines = 0;
+       char *clean = talloc_strdup(ctx, "");
+       const char *search_start = shader;
+       const char *newline;
+       while ((newline = strchr(search_start, '\n')) != NULL) {
+               const char *backslash = NULL;
+
+               /* # of characters preceding the newline. */
+               int n = newline - shader;
+
+               /* Find the preceding '\', if it exists */
+               if (n >= 1 && newline[-1] == '\\')
+                       backslash = newline - 1;
+               else if (n >= 2 && newline[-1] == '\r' && newline[-2] == '\\')
+                       backslash = newline - 2;
+
+               /* Double backslashes don't count (the backslash is escaped) */
+               if (backslash != NULL && backslash[-1] == '\\') {
+                       backslash = NULL;
+               }
+
+               if (backslash != NULL) {
+                       /* We found a line continuation, but do we care? */
+                       if (!in_continued_line) {
+                               if (in_directive(shader, backslash)) {
+                                       in_continued_line = 1;
+                                       extra_newlines = 0;
+                               }
+                       }
+                       if (in_continued_line) {
+                               /* Copy everything before the \ */
+                               clean = talloc_strndup_append(clean, shader, backslash - shader);
+                               shader = newline + 1;
+                               extra_newlines++;
+                       }
+               } else if (in_continued_line) {
+                       /* Copy everything up to and including the \n */
+                       clean = talloc_strndup_append(clean, shader, newline - shader + 1);
+                       shader = newline + 1;
+                       /* Output extra newlines to make line numbers match */
+                       for (; extra_newlines > 0; extra_newlines--)
+                               clean = talloc_strdup_append(clean, "\n");
+                       in_continued_line = 0;
+               }
+               search_start = newline + 1;
+       }
+       clean = talloc_strdup_append(clean, shader);
+       return clean;
+}
+
+int
+preprocess(void *talloc_ctx, const char **shader, char **info_log,
+          const struct gl_extensions *extensions)
+{
+       int errors;
+       glcpp_parser_t *parser = glcpp_parser_create (extensions);
+       *shader = remove_line_continuations(parser, *shader);
+
+       glcpp_lex_set_source_string (parser, *shader);
+
+       glcpp_parser_parse (parser);
+
+       if (parser->skip_stack)
+               glcpp_error (&parser->skip_stack->loc, parser, "Unterminated #if\n");
+
+       *info_log = talloc_strdup_append(*info_log, parser->info_log);
+
+       talloc_steal(talloc_ctx, parser->output);
+       *shader = parser->output;
+
+       errors = parser->error;
+       glcpp_parser_destroy (parser);
+       return errors;
+}
diff --git a/src/glsl/glcpp/tests/000-content-with-spaces.c b/src/glsl/glcpp/tests/000-content-with-spaces.c
new file mode 100644 (file)
index 0000000..696cb3a
--- /dev/null
@@ -0,0 +1 @@
+this is  four  tokens
diff --git a/src/glsl/glcpp/tests/000-content-with-spaces.c.expected b/src/glsl/glcpp/tests/000-content-with-spaces.c.expected
new file mode 100644 (file)
index 0000000..83f7834
--- /dev/null
@@ -0,0 +1,2 @@
+this is four tokens
+
diff --git a/src/glsl/glcpp/tests/001-define.c b/src/glsl/glcpp/tests/001-define.c
new file mode 100644 (file)
index 0000000..cbf2fee
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo 1
+foo
diff --git a/src/glsl/glcpp/tests/001-define.c.expected b/src/glsl/glcpp/tests/001-define.c.expected
new file mode 100644 (file)
index 0000000..878fd15
--- /dev/null
@@ -0,0 +1,3 @@
+
+1
+
diff --git a/src/glsl/glcpp/tests/002-define-chain.c b/src/glsl/glcpp/tests/002-define-chain.c
new file mode 100644 (file)
index 0000000..87d75c6
--- /dev/null
@@ -0,0 +1,3 @@
+#define foo 1
+#define bar foo
+bar
diff --git a/src/glsl/glcpp/tests/002-define-chain.c.expected b/src/glsl/glcpp/tests/002-define-chain.c.expected
new file mode 100644 (file)
index 0000000..43d484d
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+1
+
diff --git a/src/glsl/glcpp/tests/003-define-chain-reverse.c b/src/glsl/glcpp/tests/003-define-chain-reverse.c
new file mode 100644 (file)
index 0000000..a18b724
--- /dev/null
@@ -0,0 +1,3 @@
+#define bar foo
+#define foo 1
+bar
diff --git a/src/glsl/glcpp/tests/003-define-chain-reverse.c.expected b/src/glsl/glcpp/tests/003-define-chain-reverse.c.expected
new file mode 100644 (file)
index 0000000..43d484d
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+1
+
diff --git a/src/glsl/glcpp/tests/004-define-recursive.c b/src/glsl/glcpp/tests/004-define-recursive.c
new file mode 100644 (file)
index 0000000..2ac56ea
--- /dev/null
@@ -0,0 +1,6 @@
+#define foo bar
+#define bar baz
+#define baz foo
+foo
+bar
+baz
diff --git a/src/glsl/glcpp/tests/004-define-recursive.c.expected b/src/glsl/glcpp/tests/004-define-recursive.c.expected
new file mode 100644 (file)
index 0000000..4d2698b
--- /dev/null
@@ -0,0 +1,7 @@
+
+
+
+foo
+bar
+baz
+
diff --git a/src/glsl/glcpp/tests/005-define-composite-chain.c b/src/glsl/glcpp/tests/005-define-composite-chain.c
new file mode 100644 (file)
index 0000000..f5521df
--- /dev/null
@@ -0,0 +1,3 @@
+#define foo 1
+#define bar a foo
+bar
diff --git a/src/glsl/glcpp/tests/005-define-composite-chain.c.expected b/src/glsl/glcpp/tests/005-define-composite-chain.c.expected
new file mode 100644 (file)
index 0000000..c67358f
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+a 1
+
diff --git a/src/glsl/glcpp/tests/006-define-composite-chain-reverse.c b/src/glsl/glcpp/tests/006-define-composite-chain-reverse.c
new file mode 100644 (file)
index 0000000..4bb91a1
--- /dev/null
@@ -0,0 +1,3 @@
+#define bar a foo
+#define foo 1
+bar
diff --git a/src/glsl/glcpp/tests/006-define-composite-chain-reverse.c.expected b/src/glsl/glcpp/tests/006-define-composite-chain-reverse.c.expected
new file mode 100644 (file)
index 0000000..c67358f
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+a 1
+
diff --git a/src/glsl/glcpp/tests/007-define-composite-recursive.c b/src/glsl/glcpp/tests/007-define-composite-recursive.c
new file mode 100644 (file)
index 0000000..5784565
--- /dev/null
@@ -0,0 +1,6 @@
+#define foo a bar
+#define bar b baz
+#define baz c foo
+foo
+bar
+baz
diff --git a/src/glsl/glcpp/tests/007-define-composite-recursive.c.expected b/src/glsl/glcpp/tests/007-define-composite-recursive.c.expected
new file mode 100644 (file)
index 0000000..30fe4dc
--- /dev/null
@@ -0,0 +1,7 @@
+
+
+
+a b c foo
+b c a bar
+c a b baz
+
diff --git a/src/glsl/glcpp/tests/008-define-empty.c b/src/glsl/glcpp/tests/008-define-empty.c
new file mode 100644 (file)
index 0000000..b1bd17e
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo
+foo
diff --git a/src/glsl/glcpp/tests/008-define-empty.c.expected b/src/glsl/glcpp/tests/008-define-empty.c.expected
new file mode 100644 (file)
index 0000000..c0f53d7
--- /dev/null
@@ -0,0 +1,3 @@
+
+
diff --git a/src/glsl/glcpp/tests/009-undef.c b/src/glsl/glcpp/tests/009-undef.c
new file mode 100644 (file)
index 0000000..3fc1fb4
--- /dev/null
@@ -0,0 +1,4 @@
+#define foo 1
+foo
+#undef foo
+foo
diff --git a/src/glsl/glcpp/tests/009-undef.c.expected b/src/glsl/glcpp/tests/009-undef.c.expected
new file mode 100644 (file)
index 0000000..03a7061
--- /dev/null
@@ -0,0 +1,5 @@
+
+1
+
+foo
+
diff --git a/src/glsl/glcpp/tests/010-undef-re-define.c b/src/glsl/glcpp/tests/010-undef-re-define.c
new file mode 100644 (file)
index 0000000..32ff737
--- /dev/null
@@ -0,0 +1,6 @@
+#define foo 1
+foo
+#undef foo
+foo
+#define foo 2
+foo
diff --git a/src/glsl/glcpp/tests/010-undef-re-define.c.expected b/src/glsl/glcpp/tests/010-undef-re-define.c.expected
new file mode 100644 (file)
index 0000000..f4f7efd
--- /dev/null
@@ -0,0 +1,7 @@
+
+1
+
+foo
+
+2
+
diff --git a/src/glsl/glcpp/tests/011-define-func-empty.c b/src/glsl/glcpp/tests/011-define-func-empty.c
new file mode 100644 (file)
index 0000000..d9ce13c
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo()
+foo()
diff --git a/src/glsl/glcpp/tests/011-define-func-empty.c.expected b/src/glsl/glcpp/tests/011-define-func-empty.c.expected
new file mode 100644 (file)
index 0000000..c0f53d7
--- /dev/null
@@ -0,0 +1,3 @@
+
+
diff --git a/src/glsl/glcpp/tests/012-define-func-no-args.c b/src/glsl/glcpp/tests/012-define-func-no-args.c
new file mode 100644 (file)
index 0000000..c2bb730
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo() bar
+foo()
diff --git a/src/glsl/glcpp/tests/012-define-func-no-args.c.expected b/src/glsl/glcpp/tests/012-define-func-no-args.c.expected
new file mode 100644 (file)
index 0000000..0353767
--- /dev/null
@@ -0,0 +1,3 @@
+
+bar
+
diff --git a/src/glsl/glcpp/tests/013-define-func-1-arg-unused.c b/src/glsl/glcpp/tests/013-define-func-1-arg-unused.c
new file mode 100644 (file)
index 0000000..f78fb8b
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo(x) 1
+foo(bar)
diff --git a/src/glsl/glcpp/tests/013-define-func-1-arg-unused.c.expected b/src/glsl/glcpp/tests/013-define-func-1-arg-unused.c.expected
new file mode 100644 (file)
index 0000000..878fd15
--- /dev/null
@@ -0,0 +1,3 @@
+
+1
+
diff --git a/src/glsl/glcpp/tests/014-define-func-2-arg-unused.c b/src/glsl/glcpp/tests/014-define-func-2-arg-unused.c
new file mode 100644 (file)
index 0000000..11feb26
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo(x,y) 1
+foo(bar,baz)
diff --git a/src/glsl/glcpp/tests/014-define-func-2-arg-unused.c.expected b/src/glsl/glcpp/tests/014-define-func-2-arg-unused.c.expected
new file mode 100644 (file)
index 0000000..878fd15
--- /dev/null
@@ -0,0 +1,3 @@
+
+1
+
diff --git a/src/glsl/glcpp/tests/015-define-object-with-parens.c b/src/glsl/glcpp/tests/015-define-object-with-parens.c
new file mode 100644 (file)
index 0000000..558da9c
--- /dev/null
@@ -0,0 +1,4 @@
+#define foo ()1
+foo()
+#define bar ()2
+bar()
diff --git a/src/glsl/glcpp/tests/015-define-object-with-parens.c.expected b/src/glsl/glcpp/tests/015-define-object-with-parens.c.expected
new file mode 100644 (file)
index 0000000..d6f8cb9
--- /dev/null
@@ -0,0 +1,5 @@
+
+()1()
+
+()2()
+
diff --git a/src/glsl/glcpp/tests/016-define-func-1-arg.c b/src/glsl/glcpp/tests/016-define-func-1-arg.c
new file mode 100644 (file)
index 0000000..a2e2404
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo(x) ((x)+1)
+foo(bar)
diff --git a/src/glsl/glcpp/tests/016-define-func-1-arg.c.expected b/src/glsl/glcpp/tests/016-define-func-1-arg.c.expected
new file mode 100644 (file)
index 0000000..7f1828a
--- /dev/null
@@ -0,0 +1,3 @@
+
+((bar)+1)
+
diff --git a/src/glsl/glcpp/tests/017-define-func-2-args.c b/src/glsl/glcpp/tests/017-define-func-2-args.c
new file mode 100644 (file)
index 0000000..c725383
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo(x,y) ((x)*(y))
+foo(bar,baz)
diff --git a/src/glsl/glcpp/tests/017-define-func-2-args.c.expected b/src/glsl/glcpp/tests/017-define-func-2-args.c.expected
new file mode 100644 (file)
index 0000000..9f341da
--- /dev/null
@@ -0,0 +1,3 @@
+
+((bar)*(baz))
+
diff --git a/src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c b/src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c
new file mode 100644 (file)
index 0000000..668130b
--- /dev/null
@@ -0,0 +1,3 @@
+#define x 0
+#define foo(x) x
+foo(1)
diff --git a/src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c.expected b/src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c.expected
new file mode 100644 (file)
index 0000000..43d484d
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+1
+
diff --git a/src/glsl/glcpp/tests/019-define-func-1-arg-multi.c b/src/glsl/glcpp/tests/019-define-func-1-arg-multi.c
new file mode 100644 (file)
index 0000000..c4e62b2
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo(x) (x)
+foo(this is more than one word)
diff --git a/src/glsl/glcpp/tests/019-define-func-1-arg-multi.c.expected b/src/glsl/glcpp/tests/019-define-func-1-arg-multi.c.expected
new file mode 100644 (file)
index 0000000..4314fc8
--- /dev/null
@@ -0,0 +1,3 @@
+
+(this is more than one word)
+
diff --git a/src/glsl/glcpp/tests/020-define-func-2-arg-multi.c b/src/glsl/glcpp/tests/020-define-func-2-arg-multi.c
new file mode 100644 (file)
index 0000000..3049ad1
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo(x,y) x,two fish,red fish,y
+foo(one fish, blue fish)
diff --git a/src/glsl/glcpp/tests/020-define-func-2-arg-multi.c.expected b/src/glsl/glcpp/tests/020-define-func-2-arg-multi.c.expected
new file mode 100644 (file)
index 0000000..5648e4f
--- /dev/null
@@ -0,0 +1,3 @@
+
+one fish,two fish,red fish,blue fish
+
diff --git a/src/glsl/glcpp/tests/021-define-func-compose.c b/src/glsl/glcpp/tests/021-define-func-compose.c
new file mode 100644 (file)
index 0000000..21ddd0e
--- /dev/null
@@ -0,0 +1,3 @@
+#define bar(x) (1+(x))
+#define foo(y) (2*(y))
+foo(bar(3))
diff --git a/src/glsl/glcpp/tests/021-define-func-compose.c.expected b/src/glsl/glcpp/tests/021-define-func-compose.c.expected
new file mode 100644 (file)
index 0000000..1d62105
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+(2*((1+(3))))
+
diff --git a/src/glsl/glcpp/tests/022-define-func-arg-with-parens.c b/src/glsl/glcpp/tests/022-define-func-arg-with-parens.c
new file mode 100644 (file)
index 0000000..c20d73a
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo(x) (x)
+foo(argument(including parens)for the win)
diff --git a/src/glsl/glcpp/tests/022-define-func-arg-with-parens.c.expected b/src/glsl/glcpp/tests/022-define-func-arg-with-parens.c.expected
new file mode 100644 (file)
index 0000000..66c1658
--- /dev/null
@@ -0,0 +1,3 @@
+
+(argument(including parens)for the win)
+
diff --git a/src/glsl/glcpp/tests/023-define-extra-whitespace.c b/src/glsl/glcpp/tests/023-define-extra-whitespace.c
new file mode 100644 (file)
index 0000000..7ebfed6
--- /dev/null
@@ -0,0 +1,8 @@
+#define noargs() 1 
+# define onearg(foo) foo 
+ # define  twoargs( x , y ) x y 
+       #       define  threeargs(      a       ,       b       ,       c       ) a b c 
+noargs ( ) 
+onearg ( 2 ) 
+twoargs ( 3 , 4 ) 
+threeargs ( 5 , 6 , 7 ) 
diff --git a/src/glsl/glcpp/tests/023-define-extra-whitespace.c.expected b/src/glsl/glcpp/tests/023-define-extra-whitespace.c.expected
new file mode 100644 (file)
index 0000000..573829c
--- /dev/null
@@ -0,0 +1,9 @@
+
+
+
+
+1
+2
+3 4
+5 6 7
+
diff --git a/src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c b/src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c
new file mode 100644 (file)
index 0000000..e788adc
--- /dev/null
@@ -0,0 +1,3 @@
+#define  foo foo
+#define  bar foo
+bar
diff --git a/src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c.expected b/src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c.expected
new file mode 100644 (file)
index 0000000..ad955fc
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+foo
+
diff --git a/src/glsl/glcpp/tests/025-func-macro-as-non-macro.c b/src/glsl/glcpp/tests/025-func-macro-as-non-macro.c
new file mode 100644 (file)
index 0000000..b433671
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo(bar) bar
+foo bar
diff --git a/src/glsl/glcpp/tests/025-func-macro-as-non-macro.c.expected b/src/glsl/glcpp/tests/025-func-macro-as-non-macro.c.expected
new file mode 100644 (file)
index 0000000..960f445
--- /dev/null
@@ -0,0 +1,3 @@
+
+foo bar
+
diff --git a/src/glsl/glcpp/tests/026-define-func-extra-newlines.c b/src/glsl/glcpp/tests/026-define-func-extra-newlines.c
new file mode 100644 (file)
index 0000000..0d83740
--- /dev/null
@@ -0,0 +1,6 @@
+#define foo(a) bar
+
+foo
+(
+1
+)
diff --git a/src/glsl/glcpp/tests/026-define-func-extra-newlines.c.expected b/src/glsl/glcpp/tests/026-define-func-extra-newlines.c.expected
new file mode 100644 (file)
index 0000000..f0888f2
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+bar
+
diff --git a/src/glsl/glcpp/tests/027-define-chain-obj-to-func.c b/src/glsl/glcpp/tests/027-define-chain-obj-to-func.c
new file mode 100644 (file)
index 0000000..5ccb52c
--- /dev/null
@@ -0,0 +1,3 @@
+#define failure() success
+#define foo failure()
+foo
diff --git a/src/glsl/glcpp/tests/027-define-chain-obj-to-func.c.expected b/src/glsl/glcpp/tests/027-define-chain-obj-to-func.c.expected
new file mode 100644 (file)
index 0000000..aef762e
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c b/src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c
new file mode 100644 (file)
index 0000000..44962a7
--- /dev/null
@@ -0,0 +1,3 @@
+#define success() failure
+#define foo success
+foo
diff --git a/src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c.expected b/src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c.expected
new file mode 100644 (file)
index 0000000..aef762e
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c b/src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c
new file mode 100644 (file)
index 0000000..261f7d2
--- /dev/null
@@ -0,0 +1,3 @@
+#define bar(failure) failure
+#define foo bar(success)
+foo
diff --git a/src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c.expected b/src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c.expected
new file mode 100644 (file)
index 0000000..aef762e
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c b/src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c
new file mode 100644 (file)
index 0000000..e56fbef
--- /dev/null
@@ -0,0 +1,4 @@
+#define baz(failure) failure
+#define bar(failure) failure
+#define foo bar(baz(success))
+foo
diff --git a/src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c.expected b/src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c.expected
new file mode 100644 (file)
index 0000000..729bdd1
--- /dev/null
@@ -0,0 +1,5 @@
+
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c b/src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c
new file mode 100644 (file)
index 0000000..3f4c874
--- /dev/null
@@ -0,0 +1,4 @@
+#define baz(failure) failure
+#define bar(failure) failure
+#define foo() bar(baz(success))
+foo()
diff --git a/src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c.expected b/src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c.expected
new file mode 100644 (file)
index 0000000..729bdd1
--- /dev/null
@@ -0,0 +1,5 @@
+
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/032-define-func-self-recurse.c b/src/glsl/glcpp/tests/032-define-func-self-recurse.c
new file mode 100644 (file)
index 0000000..b3ac70f
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo(a) foo(2*(a))
+foo(3)
diff --git a/src/glsl/glcpp/tests/032-define-func-self-recurse.c.expected b/src/glsl/glcpp/tests/032-define-func-self-recurse.c.expected
new file mode 100644 (file)
index 0000000..541d44d
--- /dev/null
@@ -0,0 +1,3 @@
+
+foo(2*(3))
+
diff --git a/src/glsl/glcpp/tests/033-define-func-self-compose.c b/src/glsl/glcpp/tests/033-define-func-self-compose.c
new file mode 100644 (file)
index 0000000..f65e482
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo(a) foo(2*(a))
+foo(foo(3))
diff --git a/src/glsl/glcpp/tests/033-define-func-self-compose.c.expected b/src/glsl/glcpp/tests/033-define-func-self-compose.c.expected
new file mode 100644 (file)
index 0000000..6ea6905
--- /dev/null
@@ -0,0 +1,3 @@
+
+foo(2*(foo(2*(3))))
+
diff --git a/src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c b/src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c
new file mode 100644 (file)
index 0000000..209a5f7
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo(bar) bar
+foo(foo)
diff --git a/src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c.expected b/src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c.expected
new file mode 100644 (file)
index 0000000..24823b1
--- /dev/null
@@ -0,0 +1,3 @@
+
+foo
+
diff --git a/src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c b/src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c
new file mode 100644 (file)
index 0000000..c307fbe
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo(bar) bar
+foo(1+foo)
diff --git a/src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c.expected b/src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c.expected
new file mode 100644 (file)
index 0000000..137a9ea
--- /dev/null
@@ -0,0 +1,3 @@
+
+1+foo
+
diff --git a/src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c b/src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c
new file mode 100644 (file)
index 0000000..b21ff33
--- /dev/null
@@ -0,0 +1,3 @@
+#define bar success
+#define foo(x) x
+foo(more bar)
diff --git a/src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c.expected b/src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c.expected
new file mode 100644 (file)
index 0000000..ff6360b
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+more success
+
diff --git a/src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c b/src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c
new file mode 100644 (file)
index 0000000..b3a2f37
--- /dev/null
@@ -0,0 +1,3 @@
+#define expand(x) expand(x once)
+#define foo(x) x
+foo(expand(just))
diff --git a/src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c.expected b/src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c.expected
new file mode 100644 (file)
index 0000000..cbadee8
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+expand(just once)
+
diff --git a/src/glsl/glcpp/tests/038-func-arg-with-commas.c b/src/glsl/glcpp/tests/038-func-arg-with-commas.c
new file mode 100644 (file)
index 0000000..1407c7d
--- /dev/null
@@ -0,0 +1,2 @@
+#define foo(x) success
+foo(argument (with,embedded , commas) -- tricky)
diff --git a/src/glsl/glcpp/tests/038-func-arg-with-commas.c.expected b/src/glsl/glcpp/tests/038-func-arg-with-commas.c.expected
new file mode 100644 (file)
index 0000000..5a28fb3
--- /dev/null
@@ -0,0 +1,3 @@
+
+success
+
diff --git a/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c b/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c
new file mode 100644 (file)
index 0000000..0f7fe63
--- /dev/null
@@ -0,0 +1,3 @@
+#define foo(a) (a)
+#define bar two,words
+foo(bar)
diff --git a/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected b/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected
new file mode 100644 (file)
index 0000000..b73869d
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+(two,words)
+
diff --git a/src/glsl/glcpp/tests/040-token-pasting.c b/src/glsl/glcpp/tests/040-token-pasting.c
new file mode 100644 (file)
index 0000000..caab3ba
--- /dev/null
@@ -0,0 +1,2 @@
+#define paste(a,b) a ## b
+paste(one , token)
diff --git a/src/glsl/glcpp/tests/040-token-pasting.c.expected b/src/glsl/glcpp/tests/040-token-pasting.c.expected
new file mode 100644 (file)
index 0000000..36f6699
--- /dev/null
@@ -0,0 +1,3 @@
+
+onetoken
+
diff --git a/src/glsl/glcpp/tests/041-if-0.c b/src/glsl/glcpp/tests/041-if-0.c
new file mode 100644 (file)
index 0000000..2cab677
--- /dev/null
@@ -0,0 +1,5 @@
+success_1
+#if 0
+failure
+#endif
+success_2
diff --git a/src/glsl/glcpp/tests/041-if-0.c.expected b/src/glsl/glcpp/tests/041-if-0.c.expected
new file mode 100644 (file)
index 0000000..3800024
--- /dev/null
@@ -0,0 +1,6 @@
+success_1
+
+
+
+success_2
+
diff --git a/src/glsl/glcpp/tests/042-if-1.c b/src/glsl/glcpp/tests/042-if-1.c
new file mode 100644 (file)
index 0000000..874a25c
--- /dev/null
@@ -0,0 +1,5 @@
+success_1
+#if 1
+success_2
+#endif
+success_3
diff --git a/src/glsl/glcpp/tests/042-if-1.c.expected b/src/glsl/glcpp/tests/042-if-1.c.expected
new file mode 100644 (file)
index 0000000..e591044
--- /dev/null
@@ -0,0 +1,6 @@
+success_1
+
+success_2
+
+success_3
+
diff --git a/src/glsl/glcpp/tests/043-if-0-else.c b/src/glsl/glcpp/tests/043-if-0-else.c
new file mode 100644 (file)
index 0000000..323351f
--- /dev/null
@@ -0,0 +1,7 @@
+success_1
+#if 0
+failure
+#else
+success_2
+#endif
+success_3
diff --git a/src/glsl/glcpp/tests/043-if-0-else.c.expected b/src/glsl/glcpp/tests/043-if-0-else.c.expected
new file mode 100644 (file)
index 0000000..ee9e677
--- /dev/null
@@ -0,0 +1,8 @@
+success_1
+
+
+
+success_2
+
+success_3
+
diff --git a/src/glsl/glcpp/tests/044-if-1-else.c b/src/glsl/glcpp/tests/044-if-1-else.c
new file mode 100644 (file)
index 0000000..28dfc25
--- /dev/null
@@ -0,0 +1,7 @@
+success_1
+#if 1
+success_2
+#else
+failure
+#endif
+success_3
diff --git a/src/glsl/glcpp/tests/044-if-1-else.c.expected b/src/glsl/glcpp/tests/044-if-1-else.c.expected
new file mode 100644 (file)
index 0000000..129f5c8
--- /dev/null
@@ -0,0 +1,8 @@
+success_1
+
+success_2
+
+
+
+success_3
+
diff --git a/src/glsl/glcpp/tests/045-if-0-elif.c b/src/glsl/glcpp/tests/045-if-0-elif.c
new file mode 100644 (file)
index 0000000..e50f686
--- /dev/null
@@ -0,0 +1,11 @@
+success_1
+#if 0
+failure_1
+#elif 0
+failure_2
+#elif 1
+success_3
+#elif 1
+failure_3
+#endif
+success_4
diff --git a/src/glsl/glcpp/tests/045-if-0-elif.c.expected b/src/glsl/glcpp/tests/045-if-0-elif.c.expected
new file mode 100644 (file)
index 0000000..97a11b4
--- /dev/null
@@ -0,0 +1,12 @@
+success_1
+
+
+
+
+
+success_3
+
+
+
+success_4
+
diff --git a/src/glsl/glcpp/tests/046-if-1-elsif.c b/src/glsl/glcpp/tests/046-if-1-elsif.c
new file mode 100644 (file)
index 0000000..130515a
--- /dev/null
@@ -0,0 +1,11 @@
+success_1
+#if 1
+success_2
+#elif 0
+failure_1
+#elif 1
+failure_2
+#elif 0
+failure_3
+#endif
+success_3
diff --git a/src/glsl/glcpp/tests/046-if-1-elsif.c.expected b/src/glsl/glcpp/tests/046-if-1-elsif.c.expected
new file mode 100644 (file)
index 0000000..b928b91
--- /dev/null
@@ -0,0 +1,12 @@
+success_1
+
+success_2
+
+
+
+
+
+
+
+success_3
+
diff --git a/src/glsl/glcpp/tests/047-if-elif-else.c b/src/glsl/glcpp/tests/047-if-elif-else.c
new file mode 100644 (file)
index 0000000..e8f0838
--- /dev/null
@@ -0,0 +1,11 @@
+success_1
+#if 0
+failure_1
+#elif 0
+failure_2
+#elif 0
+failure_3
+#else
+success_2
+#endif
+success_3
diff --git a/src/glsl/glcpp/tests/047-if-elif-else.c.expected b/src/glsl/glcpp/tests/047-if-elif-else.c.expected
new file mode 100644 (file)
index 0000000..e5b53a3
--- /dev/null
@@ -0,0 +1,12 @@
+success_1
+
+
+
+
+
+
+
+success_2
+
+success_3
+
diff --git a/src/glsl/glcpp/tests/048-if-nested.c b/src/glsl/glcpp/tests/048-if-nested.c
new file mode 100644 (file)
index 0000000..fc4679c
--- /dev/null
@@ -0,0 +1,11 @@
+success_1
+#if 0
+failure_1
+#if 1
+failure_2
+#else
+failure_3
+#endif
+failure_4
+#endif
+success_2
diff --git a/src/glsl/glcpp/tests/048-if-nested.c.expected b/src/glsl/glcpp/tests/048-if-nested.c.expected
new file mode 100644 (file)
index 0000000..c61fd0b
--- /dev/null
@@ -0,0 +1,12 @@
+success_1
+
+
+
+
+
+
+
+
+
+success_2
+
diff --git a/src/glsl/glcpp/tests/049-if-expression-precedence.c b/src/glsl/glcpp/tests/049-if-expression-precedence.c
new file mode 100644 (file)
index 0000000..833ea03
--- /dev/null
@@ -0,0 +1,5 @@
+#if 1 + 2 * 3 + - (25 % 17 - + 1)
+failure with operator precedence
+#else
+success
+#endif
diff --git a/src/glsl/glcpp/tests/049-if-expression-precedence.c.expected b/src/glsl/glcpp/tests/049-if-expression-precedence.c.expected
new file mode 100644 (file)
index 0000000..569debb
--- /dev/null
@@ -0,0 +1,6 @@
+
+
+
+success
+
+
diff --git a/src/glsl/glcpp/tests/050-if-defined.c b/src/glsl/glcpp/tests/050-if-defined.c
new file mode 100644 (file)
index 0000000..34f0f95
--- /dev/null
@@ -0,0 +1,17 @@
+#if defined foo
+failure_1
+#else
+success_1
+#endif
+#define foo
+#if defined foo
+success_2
+#else
+failure_2
+#endif
+#undef foo
+#if defined foo
+failure_3
+#else
+success_3
+#endif
diff --git a/src/glsl/glcpp/tests/050-if-defined.c.expected b/src/glsl/glcpp/tests/050-if-defined.c.expected
new file mode 100644 (file)
index 0000000..3f01955
--- /dev/null
@@ -0,0 +1,18 @@
+
+
+
+success_1
+
+
+
+success_2
+
+
+
+
+
+
+
+success_3
+
+
diff --git a/src/glsl/glcpp/tests/051-if-relational.c b/src/glsl/glcpp/tests/051-if-relational.c
new file mode 100644 (file)
index 0000000..c3db488
--- /dev/null
@@ -0,0 +1,35 @@
+#if 3 < 2
+failure_1
+#else
+success_1
+#endif
+
+#if 3 >= 2
+success_2
+#else
+failure_2
+#endif
+
+#if 2 + 3 <= 5
+success_3
+#else
+failure_3
+#endif
+
+#if 3 - 2 == 1
+success_3
+#else
+failure_3
+#endif
+
+#if 1 > 3
+failure_4
+#else
+success_4
+#endif
+
+#if 1 != 5
+success_5
+#else
+failure_5
+#endif
diff --git a/src/glsl/glcpp/tests/051-if-relational.c.expected b/src/glsl/glcpp/tests/051-if-relational.c.expected
new file mode 100644 (file)
index 0000000..d2b76f1
--- /dev/null
@@ -0,0 +1,36 @@
+
+
+
+success_1
+
+
+
+success_2
+
+
+
+
+
+success_3
+
+
+
+
+
+success_3
+
+
+
+
+
+
+
+success_4
+
+
+
+success_5
+
+
+
+
diff --git a/src/glsl/glcpp/tests/052-if-bitwise.c b/src/glsl/glcpp/tests/052-if-bitwise.c
new file mode 100644 (file)
index 0000000..2d8e45e
--- /dev/null
@@ -0,0 +1,20 @@
+#if (0xaaaaaaaa | 0x55555555) != 4294967295
+failure_1
+#else
+success_1
+#endif
+#if (0x12345678 ^ 0xfdecba98) == 4023971040
+success_2
+#else
+failure_2
+#endif
+#if (~ 0xdeadbeef) != -3735928560
+failure_3
+#else
+success_3
+#endif
+#if (0667 & 0733) == 403
+success_4
+#else
+failure_4
+#endif
diff --git a/src/glsl/glcpp/tests/052-if-bitwise.c.expected b/src/glsl/glcpp/tests/052-if-bitwise.c.expected
new file mode 100644 (file)
index 0000000..bb5d92e
--- /dev/null
@@ -0,0 +1,21 @@
+
+
+
+success_1
+
+
+success_2
+
+
+
+
+
+
+success_3
+
+
+success_4
+
+
+
+
diff --git a/src/glsl/glcpp/tests/053-if-divide-and-shift.c b/src/glsl/glcpp/tests/053-if-divide-and-shift.c
new file mode 100644 (file)
index 0000000..d24c54a
--- /dev/null
@@ -0,0 +1,15 @@
+#if (15 / 2) != 7
+failure_1
+#else
+success_1
+#endif
+#if (1 << 12) == 4096
+success_2
+#else
+failure_2
+#endif
+#if (31762 >> 8) != 124
+failure_3
+#else
+success_3
+#endif
diff --git a/src/glsl/glcpp/tests/053-if-divide-and-shift.c.expected b/src/glsl/glcpp/tests/053-if-divide-and-shift.c.expected
new file mode 100644 (file)
index 0000000..f97e936
--- /dev/null
@@ -0,0 +1,16 @@
+
+
+
+success_1
+
+
+success_2
+
+
+
+
+
+
+success_3
+
+
diff --git a/src/glsl/glcpp/tests/054-if-with-macros.c b/src/glsl/glcpp/tests/054-if-with-macros.c
new file mode 100644 (file)
index 0000000..3da79a0
--- /dev/null
@@ -0,0 +1,34 @@
+#define one 1
+#define two 2
+#define three 3
+#define five 5
+#if five < two
+failure_1
+#else
+success_1
+#endif
+#if three >= two
+success_2
+#else
+failure_2
+#endif
+#if two + three <= five
+success_3
+#else
+failure_3
+#endif
+#if five - two == three
+success_4
+#else
+failure_4
+#endif
+#if one > three
+failure_5
+#else
+success_5
+#endif
+#if one != five
+success_6
+#else
+failure_6
+#endif
diff --git a/src/glsl/glcpp/tests/054-if-with-macros.c.expected b/src/glsl/glcpp/tests/054-if-with-macros.c.expected
new file mode 100644 (file)
index 0000000..27ea496
--- /dev/null
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+success_1
+
+
+success_2
+
+
+
+
+success_3
+
+
+
+
+success_4
+
+
+
+
+
+
+success_5
+
+
+success_6
+
+
+
+
diff --git a/src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c b/src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c
new file mode 100644 (file)
index 0000000..00f2c23
--- /dev/null
@@ -0,0 +1,3 @@
+#define failure() success
+#define foo failure
+foo()
diff --git a/src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c.expected b/src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c.expected
new file mode 100644 (file)
index 0000000..aef762e
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/056-macro-argument-with-comma.c b/src/glsl/glcpp/tests/056-macro-argument-with-comma.c
new file mode 100644 (file)
index 0000000..58701d1
--- /dev/null
@@ -0,0 +1,4 @@
+#define bar with,embedded,commas
+#define function(x) success
+#define foo function
+foo(bar)
diff --git a/src/glsl/glcpp/tests/056-macro-argument-with-comma.c.expected b/src/glsl/glcpp/tests/056-macro-argument-with-comma.c.expected
new file mode 100644 (file)
index 0000000..729bdd1
--- /dev/null
@@ -0,0 +1,5 @@
+
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/057-empty-arguments.c b/src/glsl/glcpp/tests/057-empty-arguments.c
new file mode 100644 (file)
index 0000000..6140232
--- /dev/null
@@ -0,0 +1,6 @@
+#define zero() success
+zero()
+#define one(x) success
+one()
+#define two(x,y) success
+two(,)
diff --git a/src/glsl/glcpp/tests/057-empty-arguments.c.expected b/src/glsl/glcpp/tests/057-empty-arguments.c.expected
new file mode 100644 (file)
index 0000000..4e3aad5
--- /dev/null
@@ -0,0 +1,7 @@
+
+success
+
+success
+
+success
+
diff --git a/src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c b/src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c
new file mode 100644 (file)
index 0000000..8ac260c
--- /dev/null
@@ -0,0 +1,5 @@
+#define paste(x,y) x ## y
+paste(a,b)
+paste(a,)
+paste(,b)
+paste(,)
diff --git a/src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c.expected b/src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c.expected
new file mode 100644 (file)
index 0000000..a1c34e5
--- /dev/null
@@ -0,0 +1,6 @@
+
+ab
+a
+b
+
+
diff --git a/src/glsl/glcpp/tests/059-token-pasting-integer.c b/src/glsl/glcpp/tests/059-token-pasting-integer.c
new file mode 100644 (file)
index 0000000..37b895a
--- /dev/null
@@ -0,0 +1,4 @@
+#define paste(x,y) x ## y
+paste(1,2)
+paste(1,000)
+paste(identifier,2)
diff --git a/src/glsl/glcpp/tests/059-token-pasting-integer.c.expected b/src/glsl/glcpp/tests/059-token-pasting-integer.c.expected
new file mode 100644 (file)
index 0000000..f1a2cd2
--- /dev/null
@@ -0,0 +1,5 @@
+
+12
+1000
+identifier2
+
diff --git a/src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c b/src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c
new file mode 100644 (file)
index 0000000..ed80ea8
--- /dev/null
@@ -0,0 +1,3 @@
+#define double(a) a*2
+#define foo double(
+foo 5)
diff --git a/src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c.expected b/src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c.expected
new file mode 100644 (file)
index 0000000..c1f0d24
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+5*2
+
diff --git a/src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c b/src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c
new file mode 100644 (file)
index 0000000..6dbfd1f
--- /dev/null
@@ -0,0 +1,5 @@
+#define foo(x) success
+#define bar foo
+#define baz bar
+#define joe baz
+joe (failure)
diff --git a/src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c.expected b/src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c.expected
new file mode 100644 (file)
index 0000000..111f7d1
--- /dev/null
@@ -0,0 +1,6 @@
+
+
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/062-if-0-skips-garbage.c b/src/glsl/glcpp/tests/062-if-0-skips-garbage.c
new file mode 100644 (file)
index 0000000..d9e439b
--- /dev/null
@@ -0,0 +1,5 @@
+#define foo(a,b)
+#if 0
+foo(bar)
+foo(
+#endif
diff --git a/src/glsl/glcpp/tests/062-if-0-skips-garbage.c.expected b/src/glsl/glcpp/tests/062-if-0-skips-garbage.c.expected
new file mode 100644 (file)
index 0000000..6fb66a5
--- /dev/null
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/glsl/glcpp/tests/063-comments.c b/src/glsl/glcpp/tests/063-comments.c
new file mode 100644 (file)
index 0000000..e641d2f
--- /dev/null
@@ -0,0 +1,20 @@
+/* this is a comment */
+// so is this
+// */
+f = g/**//h;
+/*//*/l();
+m = n//**/o
++ p;
+/* this
+comment spans
+multiple lines and
+contains *** stars
+and slashes / *** /
+and other stuff.
+****/
+more code here
+/* Test that /* nested
+   comments */
+are not treated like comments.
+/*/ this is a comment */
+/*/*/
diff --git a/src/glsl/glcpp/tests/063-comments.c.expected b/src/glsl/glcpp/tests/063-comments.c.expected
new file mode 100644 (file)
index 0000000..ed4feed
--- /dev/null
@@ -0,0 +1,14 @@
+
+
+f = g /h;
+ l();
+m = n
++ p;
+more code here
+are not treated like comments.
+
diff --git a/src/glsl/glcpp/tests/064-version.c b/src/glsl/glcpp/tests/064-version.c
new file mode 100644 (file)
index 0000000..2132648
--- /dev/null
@@ -0,0 +1,2 @@
+#version 130
+#define FOO
diff --git a/src/glsl/glcpp/tests/064-version.c.expected b/src/glsl/glcpp/tests/064-version.c.expected
new file mode 100644 (file)
index 0000000..3af7111
--- /dev/null
@@ -0,0 +1,3 @@
+#version 130
+
+
diff --git a/src/glsl/glcpp/tests/065-if-defined-parens.c b/src/glsl/glcpp/tests/065-if-defined-parens.c
new file mode 100644 (file)
index 0000000..48aa0f8
--- /dev/null
@@ -0,0 +1,17 @@
+#if defined(foo)
+failure_1
+#else
+success_1
+#endif
+#define foo
+#if defined ( foo )
+success_2
+#else
+failure_2
+#endif
+#undef foo
+#if defined (foo)
+failure_3
+#else
+success_3
+#endif
diff --git a/src/glsl/glcpp/tests/065-if-defined-parens.c.expected b/src/glsl/glcpp/tests/065-if-defined-parens.c.expected
new file mode 100644 (file)
index 0000000..3f01955
--- /dev/null
@@ -0,0 +1,18 @@
+
+
+
+success_1
+
+
+
+success_2
+
+
+
+
+
+
+
+success_3
+
+
diff --git a/src/glsl/glcpp/tests/066-if-nospace-expression.c b/src/glsl/glcpp/tests/066-if-nospace-expression.c
new file mode 100644 (file)
index 0000000..3b0b473
--- /dev/null
@@ -0,0 +1,3 @@
+#if(1)
+success
+#endif
diff --git a/src/glsl/glcpp/tests/066-if-nospace-expression.c.expected b/src/glsl/glcpp/tests/066-if-nospace-expression.c.expected
new file mode 100644 (file)
index 0000000..0e84a7c
--- /dev/null
@@ -0,0 +1,4 @@
+
+success
+
+
diff --git a/src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c b/src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c
new file mode 100644 (file)
index 0000000..f46cce4
--- /dev/null
@@ -0,0 +1,40 @@
+#define D1
+#define D2
+
+#define result success
+
+#ifdef U1
+#ifdef U2
+#undef result
+#define result failure
+#endif
+#endif
+result
+
+#ifndef D1
+#ifndef D2
+#undef result
+#define result failure
+#endif
+#endif
+result
+
+#undef result
+#define result failure
+#ifdef D1
+#ifdef D2
+#undef result
+#define result success
+#endif
+#endif
+result
+
+#undef result
+#define result failure
+#ifndef U1
+#ifndef U2
+#undef result
+#define result success
+#endif
+#endif
+result
diff --git a/src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c.expected b/src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c.expected
new file mode 100644 (file)
index 0000000..3340daa
--- /dev/null
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+success
+
+
+
+
+
+
+
+success
+
+
+
+
+
+
+
+
+
+success
+
+
+
+
+
+
+
+
+
+success
+
diff --git a/src/glsl/glcpp/tests/068-accidental-pasting.c b/src/glsl/glcpp/tests/068-accidental-pasting.c
new file mode 100644 (file)
index 0000000..699ac51
--- /dev/null
@@ -0,0 +1,11 @@
+#define empty
+<empty<
+<empty=
+>empty>
+>empty=
+=empty=
+!empty=
+&empty&
+|empty|
++empty+
+-empty-
diff --git a/src/glsl/glcpp/tests/068-accidental-pasting.c.expected b/src/glsl/glcpp/tests/068-accidental-pasting.c.expected
new file mode 100644 (file)
index 0000000..ce41cd6
--- /dev/null
@@ -0,0 +1,12 @@
+
+< <
+< =
+> >
+> =
+= =
+! =
+& &
+| |
++ +
+- -
+
diff --git a/src/glsl/glcpp/tests/069-repeated-argument.c b/src/glsl/glcpp/tests/069-repeated-argument.c
new file mode 100644 (file)
index 0000000..2b46ead
--- /dev/null
@@ -0,0 +1,2 @@
+#define double(x) x x
+double(1)
diff --git a/src/glsl/glcpp/tests/069-repeated-argument.c.expected b/src/glsl/glcpp/tests/069-repeated-argument.c.expected
new file mode 100644 (file)
index 0000000..755c4d4
--- /dev/null
@@ -0,0 +1,3 @@
+
+1 1
+
diff --git a/src/glsl/glcpp/tests/070-undefined-macro-in-expression.c b/src/glsl/glcpp/tests/070-undefined-macro-in-expression.c
new file mode 100644 (file)
index 0000000..b6dc2ba
--- /dev/null
@@ -0,0 +1,2 @@
+#if UNDEFINED_MACRO
+#endif
diff --git a/src/glsl/glcpp/tests/070-undefined-macro-in-expression.c.expected b/src/glsl/glcpp/tests/070-undefined-macro-in-expression.c.expected
new file mode 100644 (file)
index 0000000..2bb38a1
--- /dev/null
@@ -0,0 +1,2 @@
+0:1(21): preprocessor error: syntax error, unexpected IDENTIFIER
+
diff --git a/src/glsl/glcpp/tests/071-punctuator.c b/src/glsl/glcpp/tests/071-punctuator.c
new file mode 100644 (file)
index 0000000..959d682
--- /dev/null
@@ -0,0 +1 @@
+a = b
diff --git a/src/glsl/glcpp/tests/071-punctuator.c.expected b/src/glsl/glcpp/tests/071-punctuator.c.expected
new file mode 100644 (file)
index 0000000..fee253b
--- /dev/null
@@ -0,0 +1,2 @@
+a = b
+
diff --git a/src/glsl/glcpp/tests/072-token-pasting-same-line.c b/src/glsl/glcpp/tests/072-token-pasting-same-line.c
new file mode 100644 (file)
index 0000000..e421e9d
--- /dev/null
@@ -0,0 +1,2 @@
+#define paste(x) success_ ## x
+paste(1) paste(2) paste(3)
diff --git a/src/glsl/glcpp/tests/072-token-pasting-same-line.c.expected b/src/glsl/glcpp/tests/072-token-pasting-same-line.c.expected
new file mode 100644 (file)
index 0000000..c780b43
--- /dev/null
@@ -0,0 +1,3 @@
+
+success_1 success_2 success_3
+
diff --git a/src/glsl/glcpp/tests/073-if-in-ifdef.c b/src/glsl/glcpp/tests/073-if-in-ifdef.c
new file mode 100644 (file)
index 0000000..61a4809
--- /dev/null
@@ -0,0 +1,4 @@
+#ifdef UNDEF
+#if UNDEF > 1
+#endif
+#endif
diff --git a/src/glsl/glcpp/tests/073-if-in-ifdef.c.expected b/src/glsl/glcpp/tests/073-if-in-ifdef.c.expected
new file mode 100644 (file)
index 0000000..3f2ff2d
--- /dev/null
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/src/glsl/glcpp/tests/074-elif-undef.c b/src/glsl/glcpp/tests/074-elif-undef.c
new file mode 100644 (file)
index 0000000..67aac89
--- /dev/null
@@ -0,0 +1,3 @@
+#ifndef UNDEF
+#elif UNDEF < 0
+#endif
diff --git a/src/glsl/glcpp/tests/074-elif-undef.c.expected b/src/glsl/glcpp/tests/074-elif-undef.c.expected
new file mode 100644 (file)
index 0000000..fd40910
--- /dev/null
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/glsl/glcpp/tests/075-elif-elif-undef.c b/src/glsl/glcpp/tests/075-elif-elif-undef.c
new file mode 100644 (file)
index 0000000..264bc4f
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef UNDEF
+#elif UNDEF < 0
+#elif UNDEF == 3
+#endif
diff --git a/src/glsl/glcpp/tests/075-elif-elif-undef.c.expected b/src/glsl/glcpp/tests/075-elif-elif-undef.c.expected
new file mode 100644 (file)
index 0000000..3f2ff2d
--- /dev/null
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/src/glsl/glcpp/tests/076-elif-undef-nested.c b/src/glsl/glcpp/tests/076-elif-undef-nested.c
new file mode 100644 (file)
index 0000000..ebd550e
--- /dev/null
@@ -0,0 +1,5 @@
+#ifdef UNDEF
+#if UNDEF == 4
+#elif UNDEF == 5
+#endif
+#endif
diff --git a/src/glsl/glcpp/tests/076-elif-undef-nested.c.expected b/src/glsl/glcpp/tests/076-elif-undef-nested.c.expected
new file mode 100644 (file)
index 0000000..6fb66a5
--- /dev/null
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/glsl/glcpp/tests/077-else-without-if.c b/src/glsl/glcpp/tests/077-else-without-if.c
new file mode 100644 (file)
index 0000000..81f00bf
--- /dev/null
@@ -0,0 +1 @@
+#else
diff --git a/src/glsl/glcpp/tests/077-else-without-if.c.expected b/src/glsl/glcpp/tests/077-else-without-if.c.expected
new file mode 100644 (file)
index 0000000..d289b36
--- /dev/null
@@ -0,0 +1,4 @@
+0:1(2): preprocessor error: else without #if
+
+
+
diff --git a/src/glsl/glcpp/tests/078-elif-without-if.c b/src/glsl/glcpp/tests/078-elif-without-if.c
new file mode 100644 (file)
index 0000000..60466b3
--- /dev/null
@@ -0,0 +1 @@
+#elif defined FOO
diff --git a/src/glsl/glcpp/tests/078-elif-without-if.c.expected b/src/glsl/glcpp/tests/078-elif-without-if.c.expected
new file mode 100644 (file)
index 0000000..7d41f0a
--- /dev/null
@@ -0,0 +1,4 @@
+0:1(2): preprocessor error: elif without #if
+
+
+
diff --git a/src/glsl/glcpp/tests/079-endif-without-if.c b/src/glsl/glcpp/tests/079-endif-without-if.c
new file mode 100644 (file)
index 0000000..69331c3
--- /dev/null
@@ -0,0 +1 @@
+#endif
diff --git a/src/glsl/glcpp/tests/079-endif-without-if.c.expected b/src/glsl/glcpp/tests/079-endif-without-if.c.expected
new file mode 100644 (file)
index 0000000..08dd335
--- /dev/null
@@ -0,0 +1,4 @@
+0:1(2): preprocessor error: #endif without #if
+
+
+
diff --git a/src/glsl/glcpp/tests/080-if-without-expression.c b/src/glsl/glcpp/tests/080-if-without-expression.c
new file mode 100644 (file)
index 0000000..a27ba36
--- /dev/null
@@ -0,0 +1,4 @@
+/* Error message for unskipped #if with no expression. */
+#if
+#endif
+
diff --git a/src/glsl/glcpp/tests/080-if-without-expression.c.expected b/src/glsl/glcpp/tests/080-if-without-expression.c.expected
new file mode 100644 (file)
index 0000000..768ba0f
--- /dev/null
@@ -0,0 +1,6 @@
+0:2(1): preprocessor error: #if with no expression
+
+
+
+
diff --git a/src/glsl/glcpp/tests/081-elif-without-expression.c b/src/glsl/glcpp/tests/081-elif-without-expression.c
new file mode 100644 (file)
index 0000000..79c7866
--- /dev/null
@@ -0,0 +1,3 @@
+#if 0
+#elif
+#endif
diff --git a/src/glsl/glcpp/tests/081-elif-without-expression.c.expected b/src/glsl/glcpp/tests/081-elif-without-expression.c.expected
new file mode 100644 (file)
index 0000000..974f0f5
--- /dev/null
@@ -0,0 +1,5 @@
+0:2(1): preprocessor error: #elif with no expression
+
+
+
+
diff --git a/src/glsl/glcpp/tests/082-invalid-paste.c b/src/glsl/glcpp/tests/082-invalid-paste.c
new file mode 100644 (file)
index 0000000..40bf644
--- /dev/null
@@ -0,0 +1,2 @@
+#define PASTE(x,y) x ## y
+PASTE(<,>)
diff --git a/src/glsl/glcpp/tests/082-invalid-paste.c.expected b/src/glsl/glcpp/tests/082-invalid-paste.c.expected
new file mode 100644 (file)
index 0000000..2c92440
--- /dev/null
@@ -0,0 +1,5 @@
+0:2(7): preprocessor error: 
+Pasting "<" and ">" does not give a valid preprocessing token.
+
+<
+
diff --git a/src/glsl/glcpp/tests/083-unterminated-if.c b/src/glsl/glcpp/tests/083-unterminated-if.c
new file mode 100644 (file)
index 0000000..9180635
--- /dev/null
@@ -0,0 +1,2 @@
+#if 1
+
diff --git a/src/glsl/glcpp/tests/083-unterminated-if.c.expected b/src/glsl/glcpp/tests/083-unterminated-if.c.expected
new file mode 100644 (file)
index 0000000..a69f8ba
--- /dev/null
@@ -0,0 +1,5 @@
+0:1(7): preprocessor error: Unterminated #if
+
+
+
+
diff --git a/src/glsl/glcpp/tests/084-unbalanced-parentheses.c b/src/glsl/glcpp/tests/084-unbalanced-parentheses.c
new file mode 100644 (file)
index 0000000..0789ba5
--- /dev/null
@@ -0,0 +1,2 @@
+#define FUNC(x) (2*(x))
+FUNC(23
diff --git a/src/glsl/glcpp/tests/085-incorrect-argument-count.c b/src/glsl/glcpp/tests/085-incorrect-argument-count.c
new file mode 100644 (file)
index 0000000..91bea60
--- /dev/null
@@ -0,0 +1,5 @@
+#define MULT(x,y) ((x)*(y))
+MULT()
+MULT(1)
+MULT(1,2,3)
+
diff --git a/src/glsl/glcpp/tests/085-incorrect-argument-count.c.expected b/src/glsl/glcpp/tests/085-incorrect-argument-count.c.expected
new file mode 100644 (file)
index 0000000..1df30cb
--- /dev/null
@@ -0,0 +1,12 @@
+0:2(1): preprocessor error: Error: macro MULT invoked with 1 arguments (expected 2)
+
+0:3(1): preprocessor error: Error: macro MULT invoked with 1 arguments (expected 2)
+
+0:4(1): preprocessor error: Error: macro MULT invoked with 3 arguments (expected 2)
+
+
+MULT()
+MULT(1)
+MULT(1,2,3)
+
+
diff --git a/src/glsl/glcpp/tests/086-reserved-macro-names.c b/src/glsl/glcpp/tests/086-reserved-macro-names.c
new file mode 100644 (file)
index 0000000..fd0c29f
--- /dev/null
@@ -0,0 +1,2 @@
+#define __BAD reserved
+#define GL_ALSO_BAD() also reserved
diff --git a/src/glsl/glcpp/tests/086-reserved-macro-names.c.expected b/src/glsl/glcpp/tests/086-reserved-macro-names.c.expected
new file mode 100644 (file)
index 0000000..6a9df68
--- /dev/null
@@ -0,0 +1,7 @@
+0:1(10): preprocessor error: Macro names starting with "__" are reserved.
+
+0:2(9): preprocessor error: Macro names starting with "GL_" are reserved.
+
+
+
+
diff --git a/src/glsl/glcpp/tests/087-if-comments.c b/src/glsl/glcpp/tests/087-if-comments.c
new file mode 100644 (file)
index 0000000..ce8dc43
--- /dev/null
@@ -0,0 +1,5 @@
+#if (1 == 0) // dangerous comment
+fail
+#else
+win
+#endif
diff --git a/src/glsl/glcpp/tests/087-if-comments.c.expected b/src/glsl/glcpp/tests/087-if-comments.c.expected
new file mode 100644 (file)
index 0000000..827e548
--- /dev/null
@@ -0,0 +1,6 @@
+
+
+
+win
+
+
diff --git a/src/glsl/glcpp/tests/088-redefine-macro-legitimate.c b/src/glsl/glcpp/tests/088-redefine-macro-legitimate.c
new file mode 100644 (file)
index 0000000..0e0666b
--- /dev/null
@@ -0,0 +1,5 @@
+#define abc 123
+#define abc 123
+
+#define foo(x) (x)+23
+#define foo(x) ( x ) + 23
diff --git a/src/glsl/glcpp/tests/088-redefine-macro-legitimate.c.expected b/src/glsl/glcpp/tests/088-redefine-macro-legitimate.c.expected
new file mode 100644 (file)
index 0000000..6fb66a5
--- /dev/null
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/glsl/glcpp/tests/089-redefine-macro-error.c b/src/glsl/glcpp/tests/089-redefine-macro-error.c
new file mode 100644 (file)
index 0000000..b3d1391
--- /dev/null
@@ -0,0 +1,17 @@
+#define x y
+#define x z
+
+#define abc 123
+#define abc() 123
+
+#define foo() bar
+#define foo(x) bar
+
+#define bar() baz
+#define bar baz
+
+#define biff(a,b) a+b
+#define biff(a,b,c) a+b
+
+#define oper(a,b) a+b
+#define oper(a,b) a*b
diff --git a/src/glsl/glcpp/tests/089-redefine-macro-error.c.expected b/src/glsl/glcpp/tests/089-redefine-macro-error.c.expected
new file mode 100644 (file)
index 0000000..6209ead
--- /dev/null
@@ -0,0 +1,30 @@
+0:2(9): preprocessor error: Redefinition of macro x
+
+0:5(9): preprocessor error: Redefinition of macro abc
+
+0:8(9): preprocessor error: Redefinition of macro foo
+
+0:11(9): preprocessor error: Redefinition of macro bar
+
+0:14(9): preprocessor error: Redefinition of macro biff
+
+0:17(9): preprocessor error: Redefinition of macro oper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/glsl/glcpp/tests/090-hash-error.c b/src/glsl/glcpp/tests/090-hash-error.c
new file mode 100644 (file)
index 0000000..d19bb7f
--- /dev/null
@@ -0,0 +1 @@
+#error human error
diff --git a/src/glsl/glcpp/tests/090-hash-error.c.expected b/src/glsl/glcpp/tests/090-hash-error.c.expected
new file mode 100644 (file)
index 0000000..f2f1fbe
--- /dev/null
@@ -0,0 +1,3 @@
+0:1(2): preprocessor error: #error human error
+
+
diff --git a/src/glsl/glcpp/tests/091-hash-line.c b/src/glsl/glcpp/tests/091-hash-line.c
new file mode 100644 (file)
index 0000000..fea35d3
--- /dev/null
@@ -0,0 +1,8 @@
+#line 0
+#error line 0 error
+#line 25
+#error line 25 error
+#line 0 1
+#error source 1, line 0 error
+#line 30 2
+#error source 2, line 30 error
diff --git a/src/glsl/glcpp/tests/091-hash-line.c.expected b/src/glsl/glcpp/tests/091-hash-line.c.expected
new file mode 100644 (file)
index 0000000..e663398
--- /dev/null
@@ -0,0 +1,13 @@
+0:0(1): preprocessor error: #error line 0 error
+0:25(1): preprocessor error: #error line 25 error
+1:0(1): preprocessor error: #error source 1, line 0 error
+2:30(1): preprocessor error: #error source 2, line 30 error
+
+
+
+
+
+
+
+
+
diff --git a/src/glsl/glcpp/tests/099-c99-example.c b/src/glsl/glcpp/tests/099-c99-example.c
new file mode 100644 (file)
index 0000000..d1976b1
--- /dev/null
@@ -0,0 +1,17 @@
+#define  x      3
+#define  f(a)   f(x * (a))
+#undef   x
+#define  x      2
+#define  g      f
+#define  z      z[0]
+#define  h      g(~
+#define  m(a)   a(w)
+#define  w      0,1
+#define  t(a)   a
+#define  p()    int
+#define  q(x)   x
+#define  r(x,y) x ## y
+f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
+g(x +(3,4)-w) | h 5) & m
+       (f)^m(m);
+p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,)};
diff --git a/src/glsl/glcpp/tests/099-c99-example.c.expected b/src/glsl/glcpp/tests/099-c99-example.c.expected
new file mode 100644 (file)
index 0000000..19be750
--- /dev/null
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
+f(2 * (2 +(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
+int i[] = { 1, 23, 4, 5, };
+
diff --git a/src/glsl/glcpp/tests/glcpp-test b/src/glsl/glcpp/tests/glcpp-test
new file mode 100755 (executable)
index 0000000..5dc08ea
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+trap 'rm $test.valgrind-errors; exit 1' INT QUIT
+
+total=0
+pass=0
+clean=0
+
+echo "====== Testing for correctness ======"
+for test in *.c; do
+    echo -n "Testing $test..."
+    ../glcpp < $test > $test.out 2>&1
+    total=$((total+1))
+    if cmp $test.expected $test.out >/dev/null 2>&1; then
+       echo "PASS"
+       pass=$((pass+1))
+    else
+       echo "FAIL"
+       diff -u $test.expected $test.out
+    fi
+done
+
+echo ""
+echo "$pass/$total tests returned correct results"
+echo ""
+
+echo "====== Testing for valgrind cleanliness ======"
+for test in *.c; do
+    echo -n "Testing $test with valgrind..."
+    valgrind --error-exitcode=31 --log-file=$test.valgrind-errors ../glcpp < $test >/dev/null 2>&1
+    if [ "$?" = "31" ]; then
+       echo "ERRORS"
+       cat $test.valgrind-errors
+    else
+       echo "CLEAN"
+       clean=$((clean+1))
+       rm $test.valgrind-errors
+    fi
+done
+
+echo ""
+echo "$pass/$total tests returned correct results"
+echo "$clean/$total tests are valgrind-clean"
+
+if [ "$pass" = "$total" ] && [ "$clean" = "$total" ]; then
+    exit 0
+else
+    exit 1
+fi
+
diff --git a/src/glsl/glsl_lexer.cpp b/src/glsl/glsl_lexer.cpp
new file mode 100644 (file)
index 0000000..873df60
--- /dev/null
@@ -0,0 +1,3492 @@
+#line 2 "glsl_lexer.cpp"
+
+#line 4 "glsl_lexer.cpp"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else  /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE _mesa_glsl_restart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    #define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+               *yy_cp = yyg->yy_hold_char; \
+               YY_RESTORE_YY_MORE_OFFSET \
+               yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+               YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+               } \
+       while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+       {
+       FILE *yy_input_file;
+
+       char *yy_ch_buf;                /* input buffer */
+       char *yy_buf_pos;               /* current position in input buffer */
+
+       /* Size of input buffer in bytes, not including room for EOB
+        * characters.
+        */
+       yy_size_t yy_buf_size;
+
+       /* Number of characters read into yy_ch_buf, not including EOB
+        * characters.
+        */
+       int yy_n_chars;
+
+       /* Whether we "own" the buffer - i.e., we know we created it,
+        * and can realloc() it to grow it, and should free() it to
+        * delete it.
+        */
+       int yy_is_our_buffer;
+
+       /* Whether this is an "interactive" input source; if so, and
+        * if we're using stdio for input, then we want to use getc()
+        * instead of fread(), to make sure we stop fetching input after
+        * each newline.
+        */
+       int yy_is_interactive;
+
+       /* Whether we're considered to be at the beginning of a line.
+        * If so, '^' rules will be active on the next match, otherwise
+        * not.
+        */
+       int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+       /* Whether to try to fill the input buffer when we reach the
+        * end of it.
+        */
+       int yy_fill_buffer;
+
+       int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+       /* When an EOF's been seen but there's still some text to process
+        * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+        * shouldn't try reading from the input source any more.  We might
+        * still have a bunch of tokens to match, though, because of
+        * possible backing-up.
+        *
+        * When we actually see the EOF, we change the status to "new"
+        * (via _mesa_glsl_restart()), so that the user can continue scanning by
+        * just pointing yyin at a new input file.
+        */
+#define YY_BUFFER_EOF_PENDING 2
+
+       };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void _mesa_glsl_restart (FILE *input_file ,yyscan_t yyscanner );
+void _mesa_glsl__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE _mesa_glsl__create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void _mesa_glsl__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void _mesa_glsl__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void _mesa_glsl_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void _mesa_glsl_pop_buffer_state (yyscan_t yyscanner );
+
+static void _mesa_glsl_ensure_buffer_stack (yyscan_t yyscanner );
+static void _mesa_glsl__load_buffer_state (yyscan_t yyscanner );
+static void _mesa_glsl__init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER _mesa_glsl__flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE _mesa_glsl__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE _mesa_glsl__scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE _mesa_glsl__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *_mesa_glsl_alloc (yy_size_t ,yyscan_t yyscanner );
+void *_mesa_glsl_realloc (void *,yy_size_t ,yyscan_t yyscanner );
+void _mesa_glsl_free (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer _mesa_glsl__create_buffer
+
+#define yy_set_interactive(is_interactive) \
+       { \
+       if ( ! YY_CURRENT_BUFFER ){ \
+        _mesa_glsl_ensure_buffer_stack (yyscanner); \
+               YY_CURRENT_BUFFER_LVALUE =    \
+            _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+       } \
+       YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+       }
+
+#define yy_set_bol(at_bol) \
+       { \
+       if ( ! YY_CURRENT_BUFFER ){\
+        _mesa_glsl_ensure_buffer_stack (yyscanner); \
+               YY_CURRENT_BUFFER_LVALUE =    \
+            _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+       } \
+       YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+       }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define _mesa_glsl_wrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+       yyg->yytext_ptr = yy_bp; \
+       yyleng = (size_t) (yy_cp - yy_bp); \
+       yyg->yy_hold_char = *yy_cp; \
+       *yy_cp = '\0'; \
+       yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 183
+#define YY_END_OF_BUFFER 184
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+       {
+       flex_int32_t yy_verify;
+       flex_int32_t yy_nxt;
+       };
+static yyconst flex_int16_t yy_accept[708] =
+    {   0,
+        0,    0,   15,   15,    0,    0,  184,  182,    1,   20,
+      182,  182,  182,  182,  182,  182,  182,  182,   96,   94,
+      182,  182,  182,  181,  182,  181,  181,  181,  181,  181,
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+      181,  181,  181,  181,  181,  182,    1,  182,   91,  183,
+       15,   19,  183,   18,   16,   17,   13,   12,    1,   80,
+       87,   81,   90,   84,   75,   86,   76,   93,   98,   85,
+       99,   96,    0,    0,  101,    0,   94,    0,   77,   79,
+       78,    0,  181,   83,  181,  181,  181,  181,  181,  181,
+      181,  181,  181,  181,  181,  181,   28,  181,  181,  181,
+
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+       32,  181,  181,   56,  181,  181,  181,  181,  181,  181,
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+      181,  181,  181,  181,  181,   92,   82,    1,    0,    0,
+        2,    0,    0,    0,    0,   15,   14,   18,   17,    0,
+       98,   97,    0,   99,    0,  100,   95,   88,   89,  181,
+      104,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+      181,  181,   31,  181,  181,  181,  181,  181,  181,  181,
+
+      181,  181,  181,   25,  181,  181,  181,  181,  181,  181,
+      181,  181,  181,  181,   57,  181,  181,  181,  181,  181,
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+      181,  181,    0,    0,    0,    0,   14,    0,   98,    0,
+       97,    0,   99,  100,  181,  181,   23,  181,  181,  144,
+      181,  181,  181,  181,  181,  181,  181,  181,  181,   30,
+      107,  181,  181,  181,  181,   63,  181,  181,  112,  126,
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+      181,  123,  147,   44,   45,   46,  181,  181,  181,  181,
+
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+      181,  181,  181,  181,  181,  181,  110,  102,  181,  181,
+      181,  181,  181,  181,  181,   41,   42,   43,   73,  181,
+      181,    0,    0,    0,    0,    0,   97,  181,  181,   26,
+       35,   36,   37,  181,  105,  181,   22,  181,  181,  181,
+      181,  134,  135,  136,  181,  103,  181,  127,   24,  137,
+      138,  139,  149,  131,  132,  133,  181,  181,  181,   58,
+      129,  181,  181,   38,   39,   40,  181,  181,  181,  181,
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+      181,  181,  124,  181,  181,  181,  181,  181,  181,  181,
+
+      181,  181,  181,  106,  181,  146,  181,  181,   29,    0,
+        0,    0,    0,  153,  181,  181,  151,  181,  181,  181,
+      125,  120,  156,  181,  181,  181,  181,  181,  181,  115,
+      181,  181,   74,   47,   48,   49,   50,   51,   52,   53,
+       54,   55,  181,  181,  181,  181,  130,  111,  181,  181,
+      118,   34,  181,  181,  143,   64,  119,   72,  154,  113,
+      181,  181,  181,  181,  181,  181,  181,    0,    0,    0,
+        0,  181,  181,  181,  114,   33,  181,  181,  181,  181,
+      181,  181,  157,  158,  159,  181,  181,  181,  181,  148,
+      181,  181,  181,  181,  181,  181,  181,  181,  108,  181,
+
+      181,  181,  181,  181,   59,  181,   60,  181,    0,    0,
+        0,    0,    0,  181,   61,   27,  121,  161,  162,  163,
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+      181,  116,  181,  181,  181,  181,  181,  181,  181,  181,
+      181,  109,  165,  166,  167,  181,  181,  128,  117,    0,
+        0,    6,    0,    0,    0,   11,    3,   21,  181,  181,
+      181,  181,  181,  181,  181,  181,  181,  160,  122,   62,
+      145,  181,  152,  150,  180,   66,   67,   68,  181,  181,
+      181,  181,  181,  181,    0,    0,    0,    0,    0,    0,
+      181,  181,  181,  164,  181,  181,  181,  181,  181,  181,
+
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  168,
+        4,    0,    5,    0,    0,    0,    0,    0,  181,  181,
+      181,  181,  181,  181,  181,  177,  181,  181,  181,  181,
+      181,  181,   69,  181,  181,  181,    0,    0,    0,  181,
+      181,  178,  169,  181,  170,  181,  181,  181,  181,  181,
+      181,  181,  181,  181,  179,    0,    0,  171,  172,  175,
+      176,   65,  181,  140,  181,  141,  155,  173,  174,    0,
+        0,  181,  181,  181,    0,    0,    0,   70,  181,   71,
+        0,    0,    0,  181,    0,    0,    0,  181,    0,    0,
+        7,    0,    0,  181,    0,    8,    0,    0,  142,    0,
+
+        0,    0,    0,    9,    0,   10,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    4,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    5,    1,    6,    1,    7,    8,    1,    9,
+       10,   11,   12,    1,   13,   14,   15,   16,   17,   18,
+       19,   20,   21,   21,   21,   22,   22,   23,    1,   24,
+       25,   26,    1,    1,   27,   28,   29,   30,   31,   32,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   34,   35,   33,   33,   33,   33,   36,   33,   33,
+        1,    1,    1,   37,   38,    1,   39,   40,   41,   42,
+
+       43,   44,   45,   46,   47,   48,   49,   50,   51,   52,
+       53,   54,   33,   55,   56,   57,   58,   59,   60,   61,
+       62,   63,    1,   64,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[65] =
+    {   0,
+        1,    2,    3,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    4,    4,    4,    4,    4,
+        4,    5,    1,    1,    1,    1,    6,    6,    6,    6,
+        5,    5,    7,    7,    7,    8,    1,    7,    6,    6,
+        6,    6,    5,    5,    7,    7,    7,    7,    7,    7,
+        7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
+        8,    7,    7,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[719] =
+    {   0,
+        0,   63,   88,    0, 1076, 1075, 1077, 1080,   64, 1080,
+     1051, 1050,   59, 1049,   58,   60,   58, 1048,  139,  187,
+       47, 1047,   56,    0, 1034,  121,  110,  137,  138,  134,
+      163, 1017,  173,  177,  115,  149,  140, 1011,  159,  121,
+      187,  194,  194,  172, 1022,  171,  249,  240, 1042, 1080,
+      250, 1080, 1051,  241, 1080,    0, 1080, 1080,  262, 1080,
+     1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080,  236, 1080,
+      238,  187,  286,  303, 1080,    0,    0, 1040, 1080, 1080,
+     1080, 1039,    0, 1080, 1006, 1011, 1004, 1007, 1016, 1015,
+     1001, 1004, 1016,   35, 1010,  997,  994, 1008,  994,  991,
+
+      991,  997,  215,  232,  991, 1002,  987,  993,  997,  998,
+        0,  989, 1000,  234,  995,  975,  226,  979,  993,  983,
+      119,  976,  234,  989,  991,  973,  969,  977,  974,  963,
+      972,  256,  970,  976,  971,  974,  962,  965,  967,  245,
+      970,  961,  974,  227,  967, 1080, 1080,  308,  294,  324,
+     1080,  952,  965,  956,  967,  329,    0,  338,    0,  368,
+     1080,  303,  379, 1080,  386,  393,    0, 1080, 1080,  962,
+        0,  953,  957,  967,  964,  947,  946,  946,  950,  216,
+      961,  958,  958,  956,  953,  944,  951,  937,  935,  948,
+      933,  950,    0,  947,  934,  942,  939,  943,  944,  937,
+
+      934,  922,  921,  935,  938,  935,  922,  929,  919,  320,
+      925,  928,  918,  926,  914,  918,  909,  924,  914,  905,
+      924,  907,  905,  916,  905,  900,  898,  912,  897,  899,
+      896,  908,  907,  910,  288,  901,  895,  884,  331,  903,
+      905,  893,  885,  889,  901,  884,    0,  400,  410,  427,
+     1080,  439,  446, 1080,  879,  890,    0,  887,  343,    0,
+      880,  878,  880,  875,  884,  872,  890,  878,  346,    0,
+        0,  872,  883,  882,  882,    0,  866,  350,    0,    0,
+      868,  353,  876,  877,  867,  861,  860,  861,  860,  357,
+      856,    0,    0,  852,  851,  850,  852,  853,  858,  852,
+
+      848,  862,  857,  856,  855,  846,  849,  849,  841,  844,
+      839,  848,  853,  838,  851,  841,    0,    0,  848,  844,
+      835,  835,  841,  840,  837,    0,    0,    0,    0,  826,
+      839,  838,  837,  834,  822,  453,  463,  834,  836,    0,
+        0,    0,    0,  822,    0,  822,    0,  821,  822,  816,
+      827,    0,    0,    0,  817,    0,  813,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,  824,  469,  823,    0,
+        0,  821,  817,    0,    0,    0,  806,  415,  432,  473,
+      811,  807,  813,  803,  801,  815,  799,  799,  813,  801,
+      813,  808,    0,  806,  803,  807,  790,  792,  799,  805,
+
+      800,  799,  786,    0,  788,    0,  787,  791,    0,  785,
+      834,  784,  787,    0,  775,  785,    0,  773,  773,  787,
+        0,  789,    0,  482,  797,  796,  795,  766,  765,    0,
+      783,  782,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,  766,  780,  766,  763,    0,    0,  769,  768,
+        0,    0,  766,  758,    0,    0,    0,    0,    0,    0,
+      755,  767,  485,  759,  766,  763,  757,  750,  503,  766,
+      751,  746,  760,  758,    0,    0,  750,  769,  768,  767,
+      738,  737,  301,  481,    0,  750,  753,  751,  739,    0,
+      749,  746,  745,  734,  733,  732,  509,  741,    0,  753,
+
+      752,  751,  722,  721,    0,  736,    0,  734,  729,  515,
+      527,  773,  722,  730,    0,    0,    0,  745,  744,    0,
+      726,  729,  713,  721,  711,  719,  720,  720,  719,  704,
+      717,    0,  718,  706,  705,  701,  725,  724,  723,  694,
+      693,    0,  723,  722,    0,  704,  707,    0,    0,  693,
+      537, 1080,  561,    0,  567,  340, 1080,    0,  690,  689,
+      699,  699,  686,  701,  684,  699,  694,    0,    0,    0,
+        0,  679,    0,    0,    0,  700,  389,  700,  689,  692,
+      676,  675,  685,  685,  675,  529,  589,  474,  683,  671,
+      669,  668,  679,    0,  682,  678,  680,  676,  662,  669,
+
+      669,  671,  667,  669,  667,  667,  654,  653,  664,    0,
+     1080,  531, 1080,  596,    0,  616,  666,  648,  665,  664,
+      647,  635,  643,  633,  634,    0,  627,  646,  635,  607,
+      604,  601,    0,  604,  603,  586,  533,  572,  580,  564,
+      563,    0,    0,  564,    0,  540,  554,  552,  516,  530,
+      505,  486,  453,  450,    0,  461,  443,    0,    0,    0,
+        0,    0,  400,  406,  385,    0,    0,    0,    0,  343,
+      389,  319,  267,  249,  487,  341,  235,    0,  200,    0,
+      507,  498,  184,  157,  150,  564,  559,  136,  565,  591,
+     1080,  593,  550,  112,  594, 1080,  569,  576,    0,  123,
+
+      619,  621,  637, 1080,  638, 1080, 1080,  648,  653,  658,
+      663,  665,  667,  673,  680,  685,  690,  695
+    } ;
+
+static yyconst flex_int16_t yy_def[719] =
+    {   0,
+      707,    1,  707,    3,  708,  708,  707,  707,  707,  707,
+      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
+      707,  707,  707,  709,  707,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  707,  707,  707,  707,  707,
+      707,  707,  707,  707,  707,  710,  707,  707,  707,  707,
+      707,  707,  707,  707,  707,  707,  707,  707,  711,  707,
+      712,   19,  707,  707,  707,  713,   20,  707,  707,  707,
+      707,  707,  709,  707,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  707,  707,  707,  707,  707,
+      707,  707,  707,  707,  707,  707,  714,  707,  710,  707,
+      707,  712,  707,  707,  707,  707,  713,  707,  707,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  707,  707,  707,  707,  714,  707,  707,  707,
+      707,  707,  707,  707,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  707,  707,  707,  707,  707,  707,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  707,
+      707,  707,  707,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  707,  707,  707,
+      707,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+
+      709,  709,  709,  709,  709,  709,  709,  709,  707,  715,
+      707,  707,  707,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  707,
+      707,  707,  707,  716,  707,  707,  707,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  707,  717,  707,  716,  707,  707,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      707,  707,  707,  707,  718,  707,  707,  707,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  718,  707,  707,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  709,
+      709,  709,  709,  709,  709,  707,  707,  709,  709,  709,
+      709,  709,  709,  709,  709,  709,  709,  709,  709,  707,
+      707,  709,  709,  709,  707,  707,  707,  709,  709,  709,
+      707,  707,  707,  709,  707,  707,  707,  709,  707,  707,
+      707,  707,  707,  709,  707,  707,  707,  707,  709,  707,
+
+      707,  707,  707,  707,  707,  707,    0,  707,  707,  707,
+      707,  707,  707,  707,  707,  707,  707,  707
+    } ;
+
+static yyconst flex_int16_t yy_nxt[1145] =
+    {   0,
+        8,    9,   10,    9,   11,    8,   12,   13,    8,    8,
+       14,   15,   16,   17,   18,   19,   20,   20,   20,   20,
+       20,   20,    8,   21,   22,   23,   24,   24,   24,   24,
+       24,   24,   24,   24,   24,   24,   25,   24,   26,   27,
+       28,   29,   30,   31,   32,   33,   34,   24,   24,   35,
+       36,   37,   38,   39,   40,   41,   42,   43,   44,   45,
+       24,   24,   24,   46,   47,   59,   62,   59,   48,   65,
+       78,   79,   67,   69,   69,   69,   69,   69,   69,   69,
+       81,   82,   66,   63,   68,  179,  180,   49,   50,   51,
+       52,   51,   50,   50,   50,   50,   50,   50,   50,   50,
+
+       50,   50,   53,   50,   54,   54,   54,   54,   54,   54,
+       55,   50,   50,   50,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   50,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   50,   71,  116,   72,   72,   72,   72,   72,   72,
+       73,   85,   88,  126,   89,  213,  702,  117,   90,   74,
+       75,  699,  214,  127,   76,   91,   86,   87,  120,   92,
+       95,   74,   75,   99,   96,  100,   93,  118,  694,   94,
+       97,  119,  121,  689,  101,  146,   98,  123,  688,   76,
+
+       71,  102,   77,   77,   77,   77,   77,   77,   77,  103,
+      142,  108,  104,  124,  143,  105,  125,   74,   75,  109,
+      111,  106,  707,  112,  144,  128,  687,  113,  114,   74,
+       75,  110,  129,  130,  147,  115,  135,  131,  684,  136,
+      139,  150,  151,  132,  133,  140,  134,  707,  137,  141,
+      148,  156,   59,  156,  149,  138,  158,  158,  158,  158,
+      158,  158,  158,   59,  189,   59,  160,  161,  163,  164,
+      191,  264,  265,  240,  216,  190,  241,  208,  160,  161,
+      163,  164,  152,  201,  192,  209,  202,  203,  217,  153,
+      204,  235,  205,  154,  226,  150,  151,  683,  155,   71,
+
+      236,   73,   73,   73,   73,   73,   73,   73,  680,  148,
+      227,   59,  679,  149,  165,  165,   74,   75,  166,  166,
+      166,  166,  166,  166,  166,  150,  151,  523,   74,   75,
+      156,  321,  156,  250,  251,  524,  152,  294,  295,  296,
+      322,  556,  681,  153,  675,  250,  251,  154,  326,  327,
+      328,  676,  155,  158,  158,  158,  158,  158,  158,  158,
+      341,  342,  343,  352,  353,  354,  152,  360,  361,  362,
+      364,  365,  366,  153,  374,  375,  376,  154,  678,  248,
+      248,  589,  155,  249,  249,  249,  249,  249,  249,  249,
+      252,  252,  590,  682,  253,  253,  253,  253,  253,  253,
+
+      253,  166,  166,  166,  166,  166,  166,  166,  166,  166,
+      166,  166,  166,  166,  166,  249,  249,  249,  249,  249,
+      249,  249,  602,  603,  254,  249,  249,  249,  249,  249,
+      249,  249,  434,  435,  436,  677,  254,  674,  336,  336,
+      673,  161,  337,  337,  337,  337,  337,  337,  337,  437,
+      438,  439,  672,  161,  253,  253,  253,  253,  253,  253,
+      253,  253,  253,  253,  253,  253,  253,  253,  337,  337,
+      337,  337,  337,  337,  337,  551,  552,  164,  337,  337,
+      337,  337,  337,  337,  337,  425,  426,  427,  675,  164,
+      440,  441,  442,  671,  251,  676,  428,  429,  478,  479,
+
+      480,  500,  501,  502,  469,  670,  251,  525,  681,  481,
+      482,  669,  503,  504,  668,  526,  551,  552,  510,  511,
+      511,  511,  511,  511,  511,  537,  538,  539,  551,  552,
+      612,  613,  612,  613,  612,  613,  540,  541,  551,  552,
+      667,  685,  555,  555,  555,  555,  555,  555,  555,  686,
+      554,  697,  586,  587,  587,  587,  587,  587,  587,  682,
+      692,  666,  551,  552,  615,  690,  695,  693,  551,  552,
+      697,  665,  664,  691,  696,  554,  553,  553,  553,  553,
+      553,  553,  555,  555,  555,  555,  555,  555,  555,  615,
+      612,  613,  690,  663,  692,  695,  662,  612,  613,  661,
+
+      691,  693,  698,  696,  616,  616,  616,  616,  616,  616,
+      616,  614,  614,  614,  614,  614,  614,  612,  613,  700,
+      703,  698,  705,  660,  659,  658,  657,  701,  704,  656,
+      706,  616,  616,  616,  616,  616,  616,  616,  703,  705,
+      655,  654,  653,  652,  651,  650,  704,  706,   57,   57,
+       57,   57,   57,   57,   57,   57,   83,   83,   83,   83,
+       83,  159,  159,  159,  159,  159,   69,   69,  162,  162,
+      167,  167,  167,  247,  247,  649,  247,  247,  247,  247,
+      247,  553,  553,  553,  648,  647,  646,  553,  588,  588,
+      588,  614,  614,  614,  645,  644,  643,  614,  637,  637,
+
+      637,  642,  641,  640,  639,  638,  636,  635,  634,  633,
+      632,  631,  630,  629,  628,  627,  626,  625,  624,  623,
+      622,  621,  620,  619,  618,  617,  611,  610,  609,  608,
+      607,  606,  605,  604,  601,  600,  599,  598,  597,  596,
+      595,  594,  593,  592,  591,  585,  584,  583,  582,  581,
+      580,  579,  578,  577,  576,  575,  574,  573,  572,  571,
+      570,  569,  568,  567,  566,  565,  564,  563,  562,  561,
+      560,  559,  558,  557,  556,  550,  549,  548,  547,  546,
+      545,  544,  543,  542,  536,  535,  534,  533,  532,  531,
+      530,  529,  528,  527,  522,  521,  520,  519,  518,  517,
+
+      516,  515,  514,  513,  512,  509,  508,  507,  506,  505,
+      499,  498,  497,  496,  495,  494,  493,  492,  491,  490,
+      489,  488,  487,  486,  485,  484,  483,  477,  476,  475,
+      474,  473,  472,  471,  470,  469,  468,  467,  466,  465,
+      464,  463,  462,  461,  460,  459,  458,  457,  456,  455,
+      454,  453,  452,  451,  450,  449,  448,  447,  446,  445,
+      444,  443,  433,  432,  431,  430,  424,  423,  422,  421,
+      420,  419,  418,  417,  416,  415,  414,  413,  412,  411,
+      410,  409,  408,  407,  406,  405,  404,  403,  402,  401,
+      400,  399,  398,  397,  396,  395,  394,  393,  392,  391,
+
+      390,  389,  388,  387,  386,  385,  384,  383,  382,  381,
+      380,  379,  378,  377,  373,  372,  371,  370,  369,  368,
+      367,  363,  359,  358,  357,  356,  355,  351,  350,  349,
+      348,  347,  346,  345,  344,  340,  339,  338,  335,  334,
+      333,  332,  331,  330,  329,  325,  324,  323,  320,  319,
+      318,  317,  316,  315,  314,  313,  312,  311,  310,  309,
+      308,  307,  306,  305,  304,  303,  302,  301,  300,  299,
+      298,  297,  293,  292,  291,  290,  289,  288,  287,  286,
+      285,  284,  283,  282,  281,  280,  279,  278,  277,  276,
+      275,  274,  273,  272,  271,  270,  269,  268,  267,  266,
+
+      263,  262,  261,  260,  259,  258,  257,  256,  255,  246,
+      245,  244,  243,  242,  239,  238,  237,  234,  233,  232,
+      231,  230,  229,  228,  225,  224,  223,  222,  221,  220,
+      219,  218,  215,  212,  211,  210,  207,  206,  200,  199,
+      198,  197,  196,  195,  194,  193,  188,  187,  186,  185,
+      184,  183,  182,  181,  178,  177,  176,  175,  174,  173,
+      172,  171,  170,  169,  168,  157,   80,  145,  122,  107,
+       84,   80,   70,   64,   61,   60,  707,   58,   58,    7,
+      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
+      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
+
+      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
+      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
+      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
+      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
+      707,  707,  707,  707
+    } ;
+
+static yyconst flex_int16_t yy_chk[1145] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    2,    9,   13,    9,    2,   15,
+       21,   21,   16,   17,   17,   17,   17,   17,   17,   17,
+       23,   23,   15,   13,   16,   94,   94,    2,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,   19,   35,   19,   19,   19,   19,   19,   19,
+       19,   26,   27,   40,   27,  121,  700,   35,   27,   19,
+       19,  694,  121,   40,   19,   28,   26,   26,   37,   28,
+       29,   19,   19,   30,   29,   30,   28,   36,  688,   28,
+       29,   36,   37,  685,   30,   46,   29,   39,  684,   19,
+
+       20,   31,   20,   20,   20,   20,   20,   20,   20,   31,
+       44,   33,   31,   39,   44,   31,   39,   20,   20,   33,
+       34,   31,   72,   34,   44,   41,  683,   34,   34,   20,
+       20,   33,   41,   41,   46,   34,   42,   41,  679,   42,
+       43,   48,   48,   41,   41,   43,   41,   72,   42,   43,
+       47,   51,   47,   51,   47,   42,   54,   54,   54,   54,
+       54,   54,   54,   59,  103,   59,   69,   69,   71,   71,
+      104,  180,  180,  144,  123,  103,  144,  117,   69,   69,
+       71,   71,   48,  114,  104,  117,  114,  114,  123,   48,
+      114,  140,  114,   48,  132,  149,  149,  677,   48,   73,
+
+      140,   73,   73,   73,   73,   73,   73,   73,  674,  148,
+      132,  148,  673,  148,   74,   74,   73,   73,   74,   74,
+       74,   74,   74,   74,   74,  150,  150,  483,   73,   73,
+      156,  235,  156,  162,  162,  483,  149,  210,  210,  210,
+      235,  556,  676,  149,  670,  162,  162,  149,  239,  239,
+      239,  670,  149,  158,  158,  158,  158,  158,  158,  158,
+      259,  259,  259,  269,  269,  269,  150,  278,  278,  278,
+      282,  282,  282,  150,  290,  290,  290,  150,  672,  160,
+      160,  556,  150,  160,  160,  160,  160,  160,  160,  160,
+      163,  163,  556,  676,  163,  163,  163,  163,  163,  163,
+
+      163,  165,  165,  165,  165,  165,  165,  165,  166,  166,
+      166,  166,  166,  166,  166,  248,  248,  248,  248,  248,
+      248,  248,  577,  577,  166,  249,  249,  249,  249,  249,
+      249,  249,  378,  378,  378,  671,  166,  665,  250,  250,
+      664,  249,  250,  250,  250,  250,  250,  250,  250,  379,
+      379,  379,  663,  249,  252,  252,  252,  252,  252,  252,
+      252,  253,  253,  253,  253,  253,  253,  253,  336,  336,
+      336,  336,  336,  336,  336,  588,  588,  253,  337,  337,
+      337,  337,  337,  337,  337,  368,  368,  368,  675,  253,
+      380,  380,  380,  657,  337,  675,  368,  368,  424,  424,
+
+      424,  463,  463,  463,  469,  656,  337,  484,  681,  424,
+      424,  654,  463,  463,  653,  484,  510,  510,  469,  469,
+      469,  469,  469,  469,  469,  497,  497,  497,  511,  511,
+      586,  586,  612,  612,  637,  637,  497,  497,  551,  551,
+      652,  682,  511,  511,  511,  511,  511,  511,  511,  682,
+      510,  693,  551,  551,  551,  551,  551,  551,  551,  681,
+      687,  651,  553,  553,  586,  686,  689,  687,  555,  555,
+      697,  650,  649,  686,  689,  510,  553,  553,  553,  553,
+      553,  553,  555,  555,  555,  555,  555,  555,  555,  586,
+      587,  587,  690,  648,  692,  695,  647,  614,  614,  646,
+
+      690,  692,  693,  695,  587,  587,  587,  587,  587,  587,
+      587,  614,  614,  614,  614,  614,  614,  616,  616,  698,
+      701,  697,  702,  644,  641,  640,  639,  698,  701,  638,
+      702,  616,  616,  616,  616,  616,  616,  616,  703,  705,
+      636,  635,  634,  632,  631,  630,  703,  705,  708,  708,
+      708,  708,  708,  708,  708,  708,  709,  709,  709,  709,
+      709,  710,  710,  710,  710,  710,  711,  711,  712,  712,
+      713,  713,  713,  714,  714,  629,  714,  714,  714,  714,
+      714,  715,  715,  715,  628,  627,  625,  715,  716,  716,
+      716,  717,  717,  717,  624,  623,  622,  717,  718,  718,
+
+      718,  621,  620,  619,  618,  617,  609,  608,  607,  606,
+      605,  604,  603,  602,  601,  600,  599,  598,  597,  596,
+      595,  593,  592,  591,  590,  589,  585,  584,  583,  582,
+      581,  580,  579,  578,  576,  572,  567,  566,  565,  564,
+      563,  562,  561,  560,  559,  550,  547,  546,  544,  543,
+      541,  540,  539,  538,  537,  536,  535,  534,  533,  531,
+      530,  529,  528,  527,  526,  525,  524,  523,  522,  521,
+      519,  518,  514,  513,  512,  509,  508,  506,  504,  503,
+      502,  501,  500,  498,  496,  495,  494,  493,  492,  491,
+      489,  488,  487,  486,  482,  481,  480,  479,  478,  477,
+
+      474,  473,  472,  471,  470,  468,  467,  466,  465,  464,
+      462,  461,  454,  453,  450,  449,  446,  445,  444,  443,
+      432,  431,  429,  428,  427,  426,  425,  422,  420,  419,
+      418,  416,  415,  413,  412,  411,  410,  408,  407,  405,
+      403,  402,  401,  400,  399,  398,  397,  396,  395,  394,
+      392,  391,  390,  389,  388,  387,  386,  385,  384,  383,
+      382,  381,  377,  373,  372,  369,  367,  357,  355,  351,
+      350,  349,  348,  346,  344,  339,  338,  335,  334,  333,
+      332,  331,  330,  325,  324,  323,  322,  321,  320,  319,
+      316,  315,  314,  313,  312,  311,  310,  309,  308,  307,
+
+      306,  305,  304,  303,  302,  301,  300,  299,  298,  297,
+      296,  295,  294,  291,  289,  288,  287,  286,  285,  284,
+      283,  281,  277,  275,  274,  273,  272,  268,  267,  266,
+      265,  264,  263,  262,  261,  258,  256,  255,  246,  245,
+      244,  243,  242,  241,  240,  238,  237,  236,  234,  233,
+      232,  231,  230,  229,  228,  227,  226,  225,  224,  223,
+      222,  221,  220,  219,  218,  217,  216,  215,  214,  213,
+      212,  211,  209,  208,  207,  206,  205,  204,  203,  202,
+      201,  200,  199,  198,  197,  196,  195,  194,  192,  191,
+      190,  189,  188,  187,  186,  185,  184,  183,  182,  181,
+
+      179,  178,  177,  176,  175,  174,  173,  172,  170,  155,
+      154,  153,  152,  145,  143,  142,  141,  139,  138,  137,
+      136,  135,  134,  133,  131,  130,  129,  128,  127,  126,
+      125,  124,  122,  120,  119,  118,  116,  115,  113,  112,
+      110,  109,  108,  107,  106,  105,  102,  101,  100,   99,
+       98,   97,   96,   95,   93,   92,   91,   90,   89,   88,
+       87,   86,   85,   82,   78,   53,   49,   45,   38,   32,
+       25,   22,   18,   14,   12,   11,    7,    6,    5,  707,
+      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
+      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
+
+      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
+      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
+      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
+      707,  707,  707,  707,  707,  707,  707,  707,  707,  707,
+      707,  707,  707,  707
+    } ;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "glsl_lexer.lpp"
+#line 2 "glsl_lexer.lpp"
+/*
+ * Copyright Â© 2008, 2009 Intel Corporation
+ *
+ * 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 <ctype.h>
+#include "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_parser.h"
+
+#define YY_USER_ACTION                                         \
+   do {                                                                \
+      yylloc->source = 0;                                      \
+      yylloc->first_column = yycolumn + 1;                     \
+      yylloc->first_line = yylineno + 1;                       \
+      yycolumn += yyleng;                                      \
+   } while(0);
+
+#define YY_USER_INIT yylineno = 0; yycolumn = 0;
+
+#define TOKEN_OR_IDENTIFIER(version, token)                     \
+   do {                                                                 \
+      if (yyextra->language_version >= version) {               \
+        return token;                                           \
+      } else {                                                  \
+        yylval->identifier = strdup(yytext);                    \
+        return IDENTIFIER;                                      \
+      }                                                                 \
+   } while (0)
+
+#define RESERVED_WORD(version, token)                                  \
+   do {                                                                        \
+      if (yyextra->language_version >= version) {                      \
+        return token;                                                  \
+      } else {                                                         \
+        _mesa_glsl_error(yylloc, yyextra,                              \
+                         "Illegal use of reserved word `%s'", yytext); \
+        return ERROR_TOK;                                              \
+      }                                                                        \
+   } while (0)
+
+#line 989 "glsl_lexer.cpp"
+
+#define INITIAL 0
+#define PP 1
+#define PRAGMA 2
+
+#define YY_EXTRA_TYPE struct _mesa_glsl_parse_state *
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+    {
+
+    /* User-defined. Not touched by flex. */
+    YY_EXTRA_TYPE yyextra_r;
+
+    /* The rest are the same as the globals declared in the non-reentrant scanner. */
+    FILE *yyin_r, *yyout_r;
+    size_t yy_buffer_stack_top; /**< index of top of stack. */
+    size_t yy_buffer_stack_max; /**< capacity of stack. */
+    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+    char yy_hold_char;
+    int yy_n_chars;
+    int yyleng_r;
+    char *yy_c_buf_p;
+    int yy_init;
+    int yy_start;
+    int yy_did_buffer_switch_on_eof;
+    int yy_start_stack_ptr;
+    int yy_start_stack_depth;
+    int *yy_start_stack;
+    yy_state_type yy_last_accepting_state;
+    char* yy_last_accepting_cpos;
+
+    int yylineno_r;
+    int yy_flex_debug_r;
+
+    char *yytext_r;
+    int yy_more_flag;
+    int yy_more_len;
+
+    YYSTYPE * yylval_r;
+
+    YYLTYPE * yylloc_r;
+
+    }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+    /* This must go here because YYSTYPE and YYLTYPE are included
+     * from bison output in section 1.*/
+    #    define yylval yyg->yylval_r
+    
+    #    define yylloc yyg->yylloc_r
+    
+int _mesa_glsl_lex_init (yyscan_t* scanner);
+
+int _mesa_glsl_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int _mesa_glsl_lex_destroy (yyscan_t yyscanner );
+
+int _mesa_glsl_get_debug (yyscan_t yyscanner );
+
+void _mesa_glsl_set_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE _mesa_glsl_get_extra (yyscan_t yyscanner );
+
+void _mesa_glsl_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *_mesa_glsl_get_in (yyscan_t yyscanner );
+
+void _mesa_glsl_set_in  (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *_mesa_glsl_get_out (yyscan_t yyscanner );
+
+void _mesa_glsl_set_out  (FILE * out_str ,yyscan_t yyscanner );
+
+int _mesa_glsl_get_leng (yyscan_t yyscanner );
+
+char *_mesa_glsl_get_text (yyscan_t yyscanner );
+
+int _mesa_glsl_get_lineno (yyscan_t yyscanner );
+
+void _mesa_glsl_set_lineno (int line_number ,yyscan_t yyscanner );
+
+YYSTYPE * _mesa_glsl_get_lval (yyscan_t yyscanner );
+
+void _mesa_glsl_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+       YYLTYPE *_mesa_glsl_get_lloc (yyscan_t yyscanner );
+    
+        void _mesa_glsl_set_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
+    
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int _mesa_glsl_wrap (yyscan_t yyscanner );
+#else
+extern int _mesa_glsl_wrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+               { \
+               int c = '*'; \
+               size_t n; \
+               for ( n = 0; n < max_size && \
+                            (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+                       buf[n] = (char) c; \
+               if ( c == '\n' ) \
+                       buf[n++] = (char) c; \
+               if ( c == EOF && ferror( yyin ) ) \
+                       YY_FATAL_ERROR( "input in flex scanner failed" ); \
+               result = n; \
+               } \
+       else \
+               { \
+               errno=0; \
+               while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+                       { \
+                       if( errno != EINTR) \
+                               { \
+                               YY_FATAL_ERROR( "input in flex scanner failed" ); \
+                               break; \
+                               } \
+                       errno=0; \
+                       clearerr(yyin); \
+                       } \
+               }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int _mesa_glsl_lex \
+               (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
+
+#define YY_DECL int _mesa_glsl_lex \
+               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+       if ( yyleng > 0 ) \
+               YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+                               (yytext[yyleng - 1] == '\n'); \
+       YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+       register yy_state_type yy_current_state;
+       register char *yy_cp, *yy_bp;
+       register int yy_act;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+#line 76 "glsl_lexer.lpp"
+
+
+#line 1231 "glsl_lexer.cpp"
+
+    yylval = yylval_param;
+
+    yylloc = yylloc_param;
+
+       if ( !yyg->yy_init )
+               {
+               yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+               YY_USER_INIT;
+#endif
+
+               if ( ! yyg->yy_start )
+                       yyg->yy_start = 1;      /* first start state */
+
+               if ( ! yyin )
+                       yyin = stdin;
+
+               if ( ! yyout )
+                       yyout = stdout;
+
+               if ( ! YY_CURRENT_BUFFER ) {
+                       _mesa_glsl_ensure_buffer_stack (yyscanner);
+                       YY_CURRENT_BUFFER_LVALUE =
+                               _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+               }
+
+               _mesa_glsl__load_buffer_state(yyscanner );
+               }
+
+       while ( 1 )             /* loops until end-of-file is reached */
+               {
+               yy_cp = yyg->yy_c_buf_p;
+
+               /* Support of yytext. */
+               *yy_cp = yyg->yy_hold_char;
+
+               /* yy_bp points to the position in yy_ch_buf of the start of
+                * the current run.
+                */
+               yy_bp = yy_cp;
+
+               yy_current_state = yyg->yy_start;
+               yy_current_state += YY_AT_BOL();
+yy_match:
+               do
+                       {
+                       register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+                       if ( yy_accept[yy_current_state] )
+                               {
+                               yyg->yy_last_accepting_state = yy_current_state;
+                               yyg->yy_last_accepting_cpos = yy_cp;
+                               }
+                       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                               {
+                               yy_current_state = (int) yy_def[yy_current_state];
+                               if ( yy_current_state >= 708 )
+                                       yy_c = yy_meta[(unsigned int) yy_c];
+                               }
+                       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+                       ++yy_cp;
+                       }
+               while ( yy_current_state != 707 );
+               yy_cp = yyg->yy_last_accepting_cpos;
+               yy_current_state = yyg->yy_last_accepting_state;
+
+yy_find_action:
+               yy_act = yy_accept[yy_current_state];
+
+               YY_DO_BEFORE_ACTION;
+
+do_action:     /* This label is used only to access EOF actions. */
+
+               switch ( yy_act )
+       { /* beginning of action switch */
+                       case 0: /* must back up */
+                       /* undo the effects of YY_DO_BEFORE_ACTION */
+                       *yy_cp = yyg->yy_hold_char;
+                       yy_cp = yyg->yy_last_accepting_cpos;
+                       yy_current_state = yyg->yy_last_accepting_state;
+                       goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 78 "glsl_lexer.lpp"
+;
+       YY_BREAK
+/* Preprocessor tokens. */ 
+case 2:
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 81 "glsl_lexer.lpp"
+;
+       YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 82 "glsl_lexer.lpp"
+{ BEGIN PP; return VERSION; }
+       YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 83 "glsl_lexer.lpp"
+{ BEGIN PP; return EXTENSION; }
+       YY_BREAK
+case 5:
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 84 "glsl_lexer.lpp"
+{
+                                  /* Eat characters until the first digit is
+                                   * encountered
+                                   */
+                                  char *ptr = yytext;
+                                  while (!isdigit(*ptr))
+                                     ptr++;
+
+                                  /* Subtract one from the line number because
+                                   * yylineno is zero-based instead of
+                                   * one-based.
+                                   */
+                                  yylineno = strtol(ptr, &ptr, 0) - 1;
+                                  yylloc->source = strtol(ptr, NULL, 0);
+                               }
+       YY_BREAK
+case 6:
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 99 "glsl_lexer.lpp"
+{
+                                  /* Eat characters until the first digit is
+                                   * encountered
+                                   */
+                                  char *ptr = yytext;
+                                  while (!isdigit(*ptr))
+                                     ptr++;
+
+                                  /* Subtract one from the line number because
+                                   * yylineno is zero-based instead of
+                                   * one-based.
+                                   */
+                                  yylineno = strtol(ptr, &ptr, 0) - 1;
+                               }
+       YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 113 "glsl_lexer.lpp"
+{
+                                 BEGIN PP;
+                                 return PRAGMA_DEBUG_ON;
+                               }
+       YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 117 "glsl_lexer.lpp"
+{
+                                 BEGIN PP;
+                                 return PRAGMA_DEBUG_OFF;
+                               }
+       YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 121 "glsl_lexer.lpp"
+{
+                                 BEGIN PP;
+                                 return PRAGMA_OPTIMIZE_ON;
+                               }
+       YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 125 "glsl_lexer.lpp"
+{
+                                 BEGIN PP;
+                                 return PRAGMA_OPTIMIZE_OFF;
+                               }
+       YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 129 "glsl_lexer.lpp"
+{ BEGIN PRAGMA; }
+       YY_BREAK
+case 12:
+/* rule 12 can match eol */
+YY_RULE_SETUP
+#line 131 "glsl_lexer.lpp"
+{ BEGIN 0; yylineno++; yycolumn = 0; }
+       YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 132 "glsl_lexer.lpp"
+{ }
+       YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 134 "glsl_lexer.lpp"
+{ }
+       YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 135 "glsl_lexer.lpp"
+{ }
+       YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 136 "glsl_lexer.lpp"
+return COLON;
+       YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 137 "glsl_lexer.lpp"
+{
+                                  yylval->identifier = strdup(yytext);
+                                  return IDENTIFIER;
+                               }
+       YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 141 "glsl_lexer.lpp"
+{
+                                   yylval->n = strtol(yytext, NULL, 10);
+                                   return INTCONSTANT;
+                               }
+       YY_BREAK
+case 19:
+/* rule 19 can match eol */
+YY_RULE_SETUP
+#line 145 "glsl_lexer.lpp"
+{ BEGIN 0; yylineno++; yycolumn = 0; return EOL; }
+       YY_BREAK
+case 20:
+/* rule 20 can match eol */
+YY_RULE_SETUP
+#line 147 "glsl_lexer.lpp"
+{ yylineno++; yycolumn = 0; }
+       YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 149 "glsl_lexer.lpp"
+return ATTRIBUTE;
+       YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 150 "glsl_lexer.lpp"
+return CONST_TOK;
+       YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 151 "glsl_lexer.lpp"
+return BOOL_TOK;
+       YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 152 "glsl_lexer.lpp"
+return FLOAT_TOK;
+       YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 153 "glsl_lexer.lpp"
+return INT_TOK;
+       YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 155 "glsl_lexer.lpp"
+return BREAK;
+       YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 156 "glsl_lexer.lpp"
+return CONTINUE;
+       YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 157 "glsl_lexer.lpp"
+return DO;
+       YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 158 "glsl_lexer.lpp"
+return WHILE;
+       YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 159 "glsl_lexer.lpp"
+return ELSE;
+       YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 160 "glsl_lexer.lpp"
+return FOR;
+       YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 161 "glsl_lexer.lpp"
+return IF;
+       YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 162 "glsl_lexer.lpp"
+return DISCARD;
+       YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 163 "glsl_lexer.lpp"
+return RETURN;
+       YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 165 "glsl_lexer.lpp"
+return BVEC2;
+       YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 166 "glsl_lexer.lpp"
+return BVEC3;
+       YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 167 "glsl_lexer.lpp"
+return BVEC4;
+       YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 168 "glsl_lexer.lpp"
+return IVEC2;
+       YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 169 "glsl_lexer.lpp"
+return IVEC3;
+       YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 170 "glsl_lexer.lpp"
+return IVEC4;
+       YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 171 "glsl_lexer.lpp"
+return VEC2;
+       YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 172 "glsl_lexer.lpp"
+return VEC3;
+       YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 173 "glsl_lexer.lpp"
+return VEC4;
+       YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 174 "glsl_lexer.lpp"
+return MAT2X2;
+       YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 175 "glsl_lexer.lpp"
+return MAT3X3;
+       YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 176 "glsl_lexer.lpp"
+return MAT4X4;
+       YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 177 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT2X2);
+       YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 178 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT2X3);
+       YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 179 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT2X4);
+       YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 180 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT3X2);
+       YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 181 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT3X3);
+       YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 182 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT3X4);
+       YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 183 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT4X2);
+       YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 184 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT4X3);
+       YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 185 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MAT4X4);
+       YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 187 "glsl_lexer.lpp"
+return IN_TOK;
+       YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 188 "glsl_lexer.lpp"
+return OUT_TOK;
+       YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 189 "glsl_lexer.lpp"
+return INOUT_TOK;
+       YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 190 "glsl_lexer.lpp"
+return UNIFORM;
+       YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 191 "glsl_lexer.lpp"
+return VARYING;
+       YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 192 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, CENTROID);
+       YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 193 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, INVARIANT);
+       YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 195 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, FLAT);
+       YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 196 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, SMOOTH);
+       YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 197 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, NOPERSPECTIVE);
+       YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 199 "glsl_lexer.lpp"
+return SAMPLER1D;
+       YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 200 "glsl_lexer.lpp"
+return SAMPLER2D;
+       YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 201 "glsl_lexer.lpp"
+return SAMPLER3D;
+       YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 202 "glsl_lexer.lpp"
+return SAMPLERCUBE;
+       YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 203 "glsl_lexer.lpp"
+return SAMPLER1DSHADOW;
+       YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 204 "glsl_lexer.lpp"
+return SAMPLER2DSHADOW;
+       YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 206 "glsl_lexer.lpp"
+return STRUCT;
+       YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 207 "glsl_lexer.lpp"
+return VOID_TOK;
+       YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 209 "glsl_lexer.lpp"
+{
+                 if ((yyextra->language_version >= 140)
+                     || (yyextra->ARB_fragment_coord_conventions_enable)){
+                     return LAYOUT_TOK;
+                  } else {
+                     yylval->identifier = strdup(yytext);
+                     return IDENTIFIER;
+                  }
+               }
+       YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 219 "glsl_lexer.lpp"
+return INC_OP;
+       YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 220 "glsl_lexer.lpp"
+return DEC_OP;
+       YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 221 "glsl_lexer.lpp"
+return LE_OP;
+       YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 222 "glsl_lexer.lpp"
+return GE_OP;
+       YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 223 "glsl_lexer.lpp"
+return EQ_OP;
+       YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 224 "glsl_lexer.lpp"
+return NE_OP;
+       YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 225 "glsl_lexer.lpp"
+return AND_OP;
+       YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 226 "glsl_lexer.lpp"
+return OR_OP;
+       YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 227 "glsl_lexer.lpp"
+return XOR_OP;
+       YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 229 "glsl_lexer.lpp"
+return MUL_ASSIGN;
+       YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 230 "glsl_lexer.lpp"
+return DIV_ASSIGN;
+       YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 231 "glsl_lexer.lpp"
+return ADD_ASSIGN;
+       YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 232 "glsl_lexer.lpp"
+return MOD_ASSIGN;
+       YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 233 "glsl_lexer.lpp"
+return LEFT_ASSIGN;
+       YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 234 "glsl_lexer.lpp"
+return RIGHT_ASSIGN;
+       YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 235 "glsl_lexer.lpp"
+return AND_ASSIGN;
+       YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 236 "glsl_lexer.lpp"
+return XOR_ASSIGN;
+       YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 237 "glsl_lexer.lpp"
+return OR_ASSIGN;
+       YY_BREAK
+case 93:
+YY_RULE_SETUP
+#line 238 "glsl_lexer.lpp"
+return SUB_ASSIGN;
+       YY_BREAK
+case 94:
+YY_RULE_SETUP
+#line 240 "glsl_lexer.lpp"
+{
+                           yylval->n = strtol(yytext, NULL, 10);
+                           return INTCONSTANT;
+                       }
+       YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 244 "glsl_lexer.lpp"
+{
+                           yylval->n = strtol(yytext + 2, NULL, 16);
+                           return INTCONSTANT;
+                       }
+       YY_BREAK
+case 96:
+YY_RULE_SETUP
+#line 248 "glsl_lexer.lpp"
+{
+                           yylval->n = strtol(yytext, NULL, 8);
+                           return INTCONSTANT;
+                       }
+       YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 253 "glsl_lexer.lpp"
+{
+                           yylval->real = strtod(yytext, NULL);
+                           return FLOATCONSTANT;
+                       }
+       YY_BREAK
+case 98:
+YY_RULE_SETUP
+#line 257 "glsl_lexer.lpp"
+{
+                           yylval->real = strtod(yytext, NULL);
+                           return FLOATCONSTANT;
+                       }
+       YY_BREAK
+case 99:
+YY_RULE_SETUP
+#line 261 "glsl_lexer.lpp"
+{
+                           yylval->real = strtod(yytext, NULL);
+                           return FLOATCONSTANT;
+                       }
+       YY_BREAK
+case 100:
+YY_RULE_SETUP
+#line 265 "glsl_lexer.lpp"
+{
+                           yylval->real = strtod(yytext, NULL);
+                           return FLOATCONSTANT;
+                       }
+       YY_BREAK
+case 101:
+YY_RULE_SETUP
+#line 269 "glsl_lexer.lpp"
+{
+                           yylval->real = strtod(yytext, NULL);
+                           return FLOATCONSTANT;
+                       }
+       YY_BREAK
+case 102:
+YY_RULE_SETUP
+#line 274 "glsl_lexer.lpp"
+{
+                           yylval->n = 1;
+                           return BOOLCONSTANT;
+                       }
+       YY_BREAK
+case 103:
+YY_RULE_SETUP
+#line 278 "glsl_lexer.lpp"
+{
+                           yylval->n = 0;
+                           return BOOLCONSTANT;
+                       }
+       YY_BREAK
+/* Reserved words in GLSL 1.10. */
+case 104:
+YY_RULE_SETUP
+#line 285 "glsl_lexer.lpp"
+RESERVED_WORD(999, ASM);
+       YY_BREAK
+case 105:
+YY_RULE_SETUP
+#line 286 "glsl_lexer.lpp"
+RESERVED_WORD(999, CLASS);
+       YY_BREAK
+case 106:
+YY_RULE_SETUP
+#line 287 "glsl_lexer.lpp"
+RESERVED_WORD(999, UNION);
+       YY_BREAK
+case 107:
+YY_RULE_SETUP
+#line 288 "glsl_lexer.lpp"
+RESERVED_WORD(999, ENUM);
+       YY_BREAK
+case 108:
+YY_RULE_SETUP
+#line 289 "glsl_lexer.lpp"
+RESERVED_WORD(999, TYPEDEF);
+       YY_BREAK
+case 109:
+YY_RULE_SETUP
+#line 290 "glsl_lexer.lpp"
+RESERVED_WORD(999, TEMPLATE);
+       YY_BREAK
+case 110:
+YY_RULE_SETUP
+#line 291 "glsl_lexer.lpp"
+RESERVED_WORD(999, THIS);
+       YY_BREAK
+case 111:
+YY_RULE_SETUP
+#line 292 "glsl_lexer.lpp"
+RESERVED_WORD(999, PACKED_TOK);
+       YY_BREAK
+case 112:
+YY_RULE_SETUP
+#line 293 "glsl_lexer.lpp"
+RESERVED_WORD(999, GOTO);
+       YY_BREAK
+case 113:
+YY_RULE_SETUP
+#line 294 "glsl_lexer.lpp"
+RESERVED_WORD(130, SWITCH);
+       YY_BREAK
+case 114:
+YY_RULE_SETUP
+#line 295 "glsl_lexer.lpp"
+RESERVED_WORD(130, DEFAULT);
+       YY_BREAK
+case 115:
+YY_RULE_SETUP
+#line 296 "glsl_lexer.lpp"
+RESERVED_WORD(999, INLINE_TOK);
+       YY_BREAK
+case 116:
+YY_RULE_SETUP
+#line 297 "glsl_lexer.lpp"
+RESERVED_WORD(999, NOINLINE);
+       YY_BREAK
+case 117:
+YY_RULE_SETUP
+#line 298 "glsl_lexer.lpp"
+RESERVED_WORD(999, VOLATILE);
+       YY_BREAK
+case 118:
+YY_RULE_SETUP
+#line 299 "glsl_lexer.lpp"
+RESERVED_WORD(999, PUBLIC_TOK);
+       YY_BREAK
+case 119:
+YY_RULE_SETUP
+#line 300 "glsl_lexer.lpp"
+RESERVED_WORD(999, STATIC);
+       YY_BREAK
+case 120:
+YY_RULE_SETUP
+#line 301 "glsl_lexer.lpp"
+RESERVED_WORD(999, EXTERN);
+       YY_BREAK
+case 121:
+YY_RULE_SETUP
+#line 302 "glsl_lexer.lpp"
+RESERVED_WORD(999, EXTERNAL);
+       YY_BREAK
+case 122:
+YY_RULE_SETUP
+#line 303 "glsl_lexer.lpp"
+RESERVED_WORD(999, INTERFACE);
+       YY_BREAK
+case 123:
+YY_RULE_SETUP
+#line 304 "glsl_lexer.lpp"
+RESERVED_WORD(999, LONG_TOK);
+       YY_BREAK
+case 124:
+YY_RULE_SETUP
+#line 305 "glsl_lexer.lpp"
+RESERVED_WORD(999, SHORT_TOK);
+       YY_BREAK
+case 125:
+YY_RULE_SETUP
+#line 306 "glsl_lexer.lpp"
+RESERVED_WORD(999, DOUBLE_TOK);
+       YY_BREAK
+case 126:
+YY_RULE_SETUP
+#line 307 "glsl_lexer.lpp"
+RESERVED_WORD(999, HALF);
+       YY_BREAK
+case 127:
+YY_RULE_SETUP
+#line 308 "glsl_lexer.lpp"
+RESERVED_WORD(999, FIXED_TOK);
+       YY_BREAK
+case 128:
+YY_RULE_SETUP
+#line 309 "glsl_lexer.lpp"
+RESERVED_WORD(999, UNSIGNED);
+       YY_BREAK
+case 129:
+YY_RULE_SETUP
+#line 310 "glsl_lexer.lpp"
+RESERVED_WORD(999, INPUT_TOK);
+       YY_BREAK
+case 130:
+YY_RULE_SETUP
+#line 311 "glsl_lexer.lpp"
+RESERVED_WORD(999, OUTPUT);
+       YY_BREAK
+case 131:
+YY_RULE_SETUP
+#line 312 "glsl_lexer.lpp"
+RESERVED_WORD(999, HVEC2);
+       YY_BREAK
+case 132:
+YY_RULE_SETUP
+#line 313 "glsl_lexer.lpp"
+RESERVED_WORD(999, HVEC3);
+       YY_BREAK
+case 133:
+YY_RULE_SETUP
+#line 314 "glsl_lexer.lpp"
+RESERVED_WORD(999, HVEC4);
+       YY_BREAK
+case 134:
+YY_RULE_SETUP
+#line 315 "glsl_lexer.lpp"
+RESERVED_WORD(999, DVEC2);
+       YY_BREAK
+case 135:
+YY_RULE_SETUP
+#line 316 "glsl_lexer.lpp"
+RESERVED_WORD(999, DVEC3);
+       YY_BREAK
+case 136:
+YY_RULE_SETUP
+#line 317 "glsl_lexer.lpp"
+RESERVED_WORD(999, DVEC4);
+       YY_BREAK
+case 137:
+YY_RULE_SETUP
+#line 318 "glsl_lexer.lpp"
+RESERVED_WORD(999, FVEC2);
+       YY_BREAK
+case 138:
+YY_RULE_SETUP
+#line 319 "glsl_lexer.lpp"
+RESERVED_WORD(999, FVEC3);
+       YY_BREAK
+case 139:
+YY_RULE_SETUP
+#line 320 "glsl_lexer.lpp"
+RESERVED_WORD(999, FVEC4);
+       YY_BREAK
+case 140:
+YY_RULE_SETUP
+#line 321 "glsl_lexer.lpp"
+return SAMPLER2DRECT;
+       YY_BREAK
+case 141:
+YY_RULE_SETUP
+#line 322 "glsl_lexer.lpp"
+RESERVED_WORD(999, SAMPLER3DRECT);
+       YY_BREAK
+case 142:
+YY_RULE_SETUP
+#line 323 "glsl_lexer.lpp"
+return SAMPLER2DRECTSHADOW;
+       YY_BREAK
+case 143:
+YY_RULE_SETUP
+#line 324 "glsl_lexer.lpp"
+RESERVED_WORD(999, SIZEOF);
+       YY_BREAK
+case 144:
+YY_RULE_SETUP
+#line 325 "glsl_lexer.lpp"
+RESERVED_WORD(999, CAST);
+       YY_BREAK
+case 145:
+YY_RULE_SETUP
+#line 326 "glsl_lexer.lpp"
+RESERVED_WORD(999, NAMESPACE);
+       YY_BREAK
+case 146:
+YY_RULE_SETUP
+#line 327 "glsl_lexer.lpp"
+RESERVED_WORD(999, USING);
+       YY_BREAK
+/* Additional reserved words in GLSL 1.20. */
+case 147:
+YY_RULE_SETUP
+#line 330 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, LOWP);
+       YY_BREAK
+case 148:
+YY_RULE_SETUP
+#line 331 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, MEDIUMP);
+       YY_BREAK
+case 149:
+YY_RULE_SETUP
+#line 332 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, HIGHP);
+       YY_BREAK
+case 150:
+YY_RULE_SETUP
+#line 333 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(120, PRECISION);
+       YY_BREAK
+/* Additional reserved words in GLSL 1.30. */
+case 151:
+YY_RULE_SETUP
+#line 336 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, COMMON);
+       YY_BREAK
+case 152:
+YY_RULE_SETUP
+#line 337 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, PARTITION);
+       YY_BREAK
+case 153:
+YY_RULE_SETUP
+#line 338 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, ACTIVE);
+       YY_BREAK
+case 154:
+YY_RULE_SETUP
+#line 339 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, SUPERP);
+       YY_BREAK
+case 155:
+YY_RULE_SETUP
+#line 340 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, SAMPLERBUFFER);
+       YY_BREAK
+case 156:
+YY_RULE_SETUP
+#line 341 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, FILTER);
+       YY_BREAK
+case 157:
+YY_RULE_SETUP
+#line 342 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGE1D);
+       YY_BREAK
+case 158:
+YY_RULE_SETUP
+#line 343 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGE2D);
+       YY_BREAK
+case 159:
+YY_RULE_SETUP
+#line 344 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGE3D);
+       YY_BREAK
+case 160:
+YY_RULE_SETUP
+#line 345 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGECUBE);
+       YY_BREAK
+case 161:
+YY_RULE_SETUP
+#line 346 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IIMAGE1D);
+       YY_BREAK
+case 162:
+YY_RULE_SETUP
+#line 347 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IIMAGE2D);
+       YY_BREAK
+case 163:
+YY_RULE_SETUP
+#line 348 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IIMAGE3D);
+       YY_BREAK
+case 164:
+YY_RULE_SETUP
+#line 349 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IIMAGECUBE);
+       YY_BREAK
+case 165:
+YY_RULE_SETUP
+#line 350 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, UIMAGE1D);
+       YY_BREAK
+case 166:
+YY_RULE_SETUP
+#line 351 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, UIMAGE2D);
+       YY_BREAK
+case 167:
+YY_RULE_SETUP
+#line 352 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, UIMAGE3D);
+       YY_BREAK
+case 168:
+YY_RULE_SETUP
+#line 353 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, UIMAGECUBE);
+       YY_BREAK
+case 169:
+YY_RULE_SETUP
+#line 354 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGE1DARRAY);
+       YY_BREAK
+case 170:
+YY_RULE_SETUP
+#line 355 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGE2DARRAY);
+       YY_BREAK
+case 171:
+YY_RULE_SETUP
+#line 356 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IIMAGE1DARRAY);
+       YY_BREAK
+case 172:
+YY_RULE_SETUP
+#line 357 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IIMAGE2DARRAY);
+       YY_BREAK
+case 173:
+YY_RULE_SETUP
+#line 358 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, UIMAGE1DARRAY);
+       YY_BREAK
+case 174:
+YY_RULE_SETUP
+#line 359 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, UIMAGE2DARRAY);
+       YY_BREAK
+case 175:
+YY_RULE_SETUP
+#line 360 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGE1DSHADOW);
+       YY_BREAK
+case 176:
+YY_RULE_SETUP
+#line 361 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGE2DSHADOW);
+       YY_BREAK
+case 177:
+YY_RULE_SETUP
+#line 362 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IMAGEBUFFER);
+       YY_BREAK
+case 178:
+YY_RULE_SETUP
+#line 363 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, IIMAGEBUFFER);
+       YY_BREAK
+case 179:
+YY_RULE_SETUP
+#line 364 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, UIMAGEBUFFER);
+       YY_BREAK
+case 180:
+YY_RULE_SETUP
+#line 365 "glsl_lexer.lpp"
+TOKEN_OR_IDENTIFIER(130, ROW_MAJOR);
+       YY_BREAK
+case 181:
+YY_RULE_SETUP
+#line 367 "glsl_lexer.lpp"
+{
+                           struct _mesa_glsl_parse_state *state = yyextra;
+                           void *ctx = state;  
+                           yylval->identifier = talloc_strdup(ctx, yytext);
+                           return IDENTIFIER;
+                       }
+       YY_BREAK
+case 182:
+YY_RULE_SETUP
+#line 374 "glsl_lexer.lpp"
+{ return yytext[0]; }
+       YY_BREAK
+case 183:
+YY_RULE_SETUP
+#line 376 "glsl_lexer.lpp"
+ECHO;
+       YY_BREAK
+#line 2334 "glsl_lexer.cpp"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(PP):
+case YY_STATE_EOF(PRAGMA):
+       yyterminate();
+
+       case YY_END_OF_BUFFER:
+               {
+               /* Amount of text matched not including the EOB char. */
+               int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+               /* Undo the effects of YY_DO_BEFORE_ACTION. */
+               *yy_cp = yyg->yy_hold_char;
+               YY_RESTORE_YY_MORE_OFFSET
+
+               if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+                       {
+                       /* We're scanning a new file or input source.  It's
+                        * possible that this happened because the user
+                        * just pointed yyin at a new source and called
+                        * _mesa_glsl_lex().  If so, then we have to assure
+                        * consistency between YY_CURRENT_BUFFER and our
+                        * globals.  Here is the right place to do so, because
+                        * this is the first action (other than possibly a
+                        * back-up) that will match for the new input source.
+                        */
+                       yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+                       YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+                       YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+                       }
+
+               /* Note that here we test for yy_c_buf_p "<=" to the position
+                * of the first EOB in the buffer, since yy_c_buf_p will
+                * already have been incremented past the NUL character
+                * (since all states make transitions on EOB to the
+                * end-of-buffer state).  Contrast this with the test
+                * in input().
+                */
+               if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+                       { /* This was really a NUL. */
+                       yy_state_type yy_next_state;
+
+                       yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+                       yy_current_state = yy_get_previous_state( yyscanner );
+
+                       /* Okay, we're now positioned to make the NUL
+                        * transition.  We couldn't have
+                        * yy_get_previous_state() go ahead and do it
+                        * for us because it doesn't know how to deal
+                        * with the possibility of jamming (and we don't
+                        * want to build jamming into it because then it
+                        * will run more slowly).
+                        */
+
+                       yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+                       yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+                       if ( yy_next_state )
+                               {
+                               /* Consume the NUL. */
+                               yy_cp = ++yyg->yy_c_buf_p;
+                               yy_current_state = yy_next_state;
+                               goto yy_match;
+                               }
+
+                       else
+                               {
+                               yy_cp = yyg->yy_last_accepting_cpos;
+                               yy_current_state = yyg->yy_last_accepting_state;
+                               goto yy_find_action;
+                               }
+                       }
+
+               else switch ( yy_get_next_buffer( yyscanner ) )
+                       {
+                       case EOB_ACT_END_OF_FILE:
+                               {
+                               yyg->yy_did_buffer_switch_on_eof = 0;
+
+                               if ( _mesa_glsl_wrap(yyscanner ) )
+                                       {
+                                       /* Note: because we've taken care in
+                                        * yy_get_next_buffer() to have set up
+                                        * yytext, we can now set up
+                                        * yy_c_buf_p so that if some total
+                                        * hoser (like flex itself) wants to
+                                        * call the scanner after we return the
+                                        * YY_NULL, it'll still work - another
+                                        * YY_NULL will get returned.
+                                        */
+                                       yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+                                       yy_act = YY_STATE_EOF(YY_START);
+                                       goto do_action;
+                                       }
+
+                               else
+                                       {
+                                       if ( ! yyg->yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+                                       }
+                               break;
+                               }
+
+                       case EOB_ACT_CONTINUE_SCAN:
+                               yyg->yy_c_buf_p =
+                                       yyg->yytext_ptr + yy_amount_of_matched_text;
+
+                               yy_current_state = yy_get_previous_state( yyscanner );
+
+                               yy_cp = yyg->yy_c_buf_p;
+                               yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+                               goto yy_match;
+
+                       case EOB_ACT_LAST_MATCH:
+                               yyg->yy_c_buf_p =
+                               &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+                               yy_current_state = yy_get_previous_state( yyscanner );
+
+                               yy_cp = yyg->yy_c_buf_p;
+                               yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+                               goto yy_find_action;
+                       }
+               break;
+               }
+
+       default:
+               YY_FATAL_ERROR(
+                       "fatal flex scanner internal error--no action found" );
+       } /* end of action switch */
+               } /* end of scanning one token */
+} /* end of _mesa_glsl_lex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *     EOB_ACT_LAST_MATCH -
+ *     EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *     EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+       register char *source = yyg->yytext_ptr;
+       register int number_to_move, i;
+       int ret_val;
+
+       if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+               YY_FATAL_ERROR(
+               "fatal flex scanner internal error--end of buffer missed" );
+
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+               { /* Don't try to fill the buffer, so this is an EOF. */
+               if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+                       {
+                       /* We matched a single character, the EOB, so
+                        * treat this as a final EOF.
+                        */
+                       return EOB_ACT_END_OF_FILE;
+                       }
+
+               else
+                       {
+                       /* We matched some text prior to the EOB, first
+                        * process it.
+                        */
+                       return EOB_ACT_LAST_MATCH;
+                       }
+               }
+
+       /* Try to read more data. */
+
+       /* First move last chars to start of buffer. */
+       number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+       for ( i = 0; i < number_to_move; ++i )
+               *(dest++) = *(source++);
+
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+               /* don't do the read, it's not guaranteed to return an EOF,
+                * just force an EOF
+                */
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+       else
+               {
+                       int num_to_read =
+                       YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+               while ( num_to_read <= 0 )
+                       { /* Not enough room in the buffer - grow it. */
+
+                       /* just a shorter name for the current buffer */
+                       YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+                       int yy_c_buf_p_offset =
+                               (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+                       if ( b->yy_is_our_buffer )
+                               {
+                               int new_size = b->yy_buf_size * 2;
+
+                               if ( new_size <= 0 )
+                                       b->yy_buf_size += b->yy_buf_size / 8;
+                               else
+                                       b->yy_buf_size *= 2;
+
+                               b->yy_ch_buf = (char *)
+                                       /* Include room in for 2 EOB chars. */
+                                       _mesa_glsl_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+                               }
+                       else
+                               /* Can't grow it, we don't own it. */
+                               b->yy_ch_buf = 0;
+
+                       if ( ! b->yy_ch_buf )
+                               YY_FATAL_ERROR(
+                               "fatal error - scanner input buffer overflow" );
+
+                       yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+                       num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+                                               number_to_move - 1;
+
+                       }
+
+               if ( num_to_read > YY_READ_BUF_SIZE )
+                       num_to_read = YY_READ_BUF_SIZE;
+
+               /* Read in more data. */
+               YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+                       yyg->yy_n_chars, (size_t) num_to_read );
+
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+               }
+
+       if ( yyg->yy_n_chars == 0 )
+               {
+               if ( number_to_move == YY_MORE_ADJ )
+                       {
+                       ret_val = EOB_ACT_END_OF_FILE;
+                       _mesa_glsl_restart(yyin  ,yyscanner);
+                       }
+
+               else
+                       {
+                       ret_val = EOB_ACT_LAST_MATCH;
+                       YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+                               YY_BUFFER_EOF_PENDING;
+                       }
+               }
+
+       else
+               ret_val = EOB_ACT_CONTINUE_SCAN;
+
+       if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+               /* Extend the array by 50%, plus the number we really need. */
+               yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+               YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) _mesa_glsl_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+               if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+                       YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+       }
+
+       yyg->yy_n_chars += number_to_move;
+       YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+       YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+       yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+       return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+       register yy_state_type yy_current_state;
+       register char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       yy_current_state = yyg->yy_start;
+       yy_current_state += YY_AT_BOL();
+
+       for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+               {
+               register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+               if ( yy_accept[yy_current_state] )
+                       {
+                       yyg->yy_last_accepting_state = yy_current_state;
+                       yyg->yy_last_accepting_cpos = yy_cp;
+                       }
+               while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                       {
+                       yy_current_state = (int) yy_def[yy_current_state];
+                       if ( yy_current_state >= 708 )
+                               yy_c = yy_meta[(unsigned int) yy_c];
+                       }
+               yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+               }
+
+       return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *     next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+       register int yy_is_jam;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+       register char *yy_cp = yyg->yy_c_buf_p;
+
+       register YY_CHAR yy_c = 1;
+       if ( yy_accept[yy_current_state] )
+               {
+               yyg->yy_last_accepting_state = yy_current_state;
+               yyg->yy_last_accepting_cpos = yy_cp;
+               }
+       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+               {
+               yy_current_state = (int) yy_def[yy_current_state];
+               if ( yy_current_state >= 708 )
+                       yy_c = yy_meta[(unsigned int) yy_c];
+               }
+       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+       yy_is_jam = (yy_current_state == 707);
+
+       return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (yyscan_t yyscanner)
+#else
+    static int input  (yyscan_t yyscanner)
+#endif
+
+{
+       int c;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       *yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+       if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+               {
+               /* yy_c_buf_p now points to the character we want to return.
+                * If this occurs *before* the EOB characters, then it's a
+                * valid NUL; if not, then we've hit the end of the buffer.
+                */
+               if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+                       /* This was really a NUL. */
+                       *yyg->yy_c_buf_p = '\0';
+
+               else
+                       { /* need more input */
+                       int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+                       ++yyg->yy_c_buf_p;
+
+                       switch ( yy_get_next_buffer( yyscanner ) )
+                               {
+                               case EOB_ACT_LAST_MATCH:
+                                       /* This happens because yy_g_n_b()
+                                        * sees that we've accumulated a
+                                        * token and flags that we need to
+                                        * try matching the token before
+                                        * proceeding.  But for input(),
+                                        * there's no matching to consider.
+                                        * So convert the EOB_ACT_LAST_MATCH
+                                        * to EOB_ACT_END_OF_FILE.
+                                        */
+
+                                       /* Reset buffer status. */
+                                       _mesa_glsl_restart(yyin ,yyscanner);
+
+                                       /*FALLTHROUGH*/
+
+                               case EOB_ACT_END_OF_FILE:
+                                       {
+                                       if ( _mesa_glsl_wrap(yyscanner ) )
+                                               return EOF;
+
+                                       if ( ! yyg->yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+#ifdef __cplusplus
+                                       return yyinput(yyscanner);
+#else
+                                       return input(yyscanner);
+#endif
+                                       }
+
+                               case EOB_ACT_CONTINUE_SCAN:
+                                       yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+                                       break;
+                               }
+                       }
+               }
+
+       c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
+       *yyg->yy_c_buf_p = '\0';        /* preserve yytext */
+       yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+       YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+       return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void _mesa_glsl_restart  (FILE * input_file , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       if ( ! YY_CURRENT_BUFFER ){
+        _mesa_glsl_ensure_buffer_stack (yyscanner);
+               YY_CURRENT_BUFFER_LVALUE =
+            _mesa_glsl__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+       }
+
+       _mesa_glsl__init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+       _mesa_glsl__load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+    void _mesa_glsl__switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       /* TODO. We should be able to replace this entire function body
+        * with
+        *              _mesa_glsl_pop_buffer_state();
+        *              _mesa_glsl_push_buffer_state(new_buffer);
+     */
+       _mesa_glsl_ensure_buffer_stack (yyscanner);
+       if ( YY_CURRENT_BUFFER == new_buffer )
+               return;
+
+       if ( YY_CURRENT_BUFFER )
+               {
+               /* Flush out information for old buffer. */
+               *yyg->yy_c_buf_p = yyg->yy_hold_char;
+               YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+               }
+
+       YY_CURRENT_BUFFER_LVALUE = new_buffer;
+       _mesa_glsl__load_buffer_state(yyscanner );
+
+       /* We don't actually know whether we did this switch during
+        * EOF (_mesa_glsl_wrap()) processing, but the only time this flag
+        * is looked at is after _mesa_glsl_wrap() is called, so it's safe
+        * to go ahead and always set it.
+        */
+       yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void _mesa_glsl__load_buffer_state  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+       yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+       yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+       yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE _mesa_glsl__create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
+{
+       YY_BUFFER_STATE b;
+    
+       b = (YY_BUFFER_STATE) _mesa_glsl_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__create_buffer()" );
+
+       b->yy_buf_size = size;
+
+       /* yy_ch_buf has to be 2 characters longer than the size given because
+        * we need to put in 2 end-of-buffer characters.
+        */
+       b->yy_ch_buf = (char *) _mesa_glsl_alloc(b->yy_buf_size + 2 ,yyscanner );
+       if ( ! b->yy_ch_buf )
+               YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__create_buffer()" );
+
+       b->yy_is_our_buffer = 1;
+
+       _mesa_glsl__init_buffer(b,file ,yyscanner);
+
+       return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with _mesa_glsl__create_buffer()
+ * @param yyscanner The scanner object.
+ */
+    void _mesa_glsl__delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       if ( ! b )
+               return;
+
+       if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+               YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+       if ( b->yy_is_our_buffer )
+               _mesa_glsl_free((void *) b->yy_ch_buf ,yyscanner );
+
+       _mesa_glsl_free((void *) b ,yyscanner );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a _mesa_glsl_restart() or at EOF.
+ */
+    static void _mesa_glsl__init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
+
+{
+       int oerrno = errno;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       _mesa_glsl__flush_buffer(b ,yyscanner);
+
+       b->yy_input_file = file;
+       b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then _mesa_glsl__init_buffer was _probably_
+     * called from _mesa_glsl_restart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+       errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+    void _mesa_glsl__flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       if ( ! b )
+               return;
+
+       b->yy_n_chars = 0;
+
+       /* We always need two end-of-buffer characters.  The first causes
+        * a transition to the end-of-buffer state.  The second causes
+        * a jam in that state.
+        */
+       b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+       b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+       b->yy_buf_pos = &b->yy_ch_buf[0];
+
+       b->yy_at_bol = 1;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       if ( b == YY_CURRENT_BUFFER )
+               _mesa_glsl__load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  @param yyscanner The scanner object.
+ */
+void _mesa_glsl_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       if (new_buffer == NULL)
+               return;
+
+       _mesa_glsl_ensure_buffer_stack(yyscanner);
+
+       /* This block is copied from _mesa_glsl__switch_to_buffer. */
+       if ( YY_CURRENT_BUFFER )
+               {
+               /* Flush out information for old buffer. */
+               *yyg->yy_c_buf_p = yyg->yy_hold_char;
+               YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+               }
+
+       /* Only push if top exists. Otherwise, replace top. */
+       if (YY_CURRENT_BUFFER)
+               yyg->yy_buffer_stack_top++;
+       YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+       /* copied from _mesa_glsl__switch_to_buffer. */
+       _mesa_glsl__load_buffer_state(yyscanner );
+       yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  @param yyscanner The scanner object.
+ */
+void _mesa_glsl_pop_buffer_state (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       if (!YY_CURRENT_BUFFER)
+               return;
+
+       _mesa_glsl__delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+       YY_CURRENT_BUFFER_LVALUE = NULL;
+       if (yyg->yy_buffer_stack_top > 0)
+               --yyg->yy_buffer_stack_top;
+
+       if (YY_CURRENT_BUFFER) {
+               _mesa_glsl__load_buffer_state(yyscanner );
+               yyg->yy_did_buffer_switch_on_eof = 1;
+       }
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void _mesa_glsl_ensure_buffer_stack (yyscan_t yyscanner)
+{
+       int num_to_alloc;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       if (!yyg->yy_buffer_stack) {
+
+               /* First allocation is just for 2 elements, since we don't know if this
+                * scanner will even need a stack. We use 2 instead of 1 to avoid an
+                * immediate realloc on the next call.
+         */
+               num_to_alloc = 1;
+               yyg->yy_buffer_stack = (struct yy_buffer_state**)_mesa_glsl_alloc
+                                                               (num_to_alloc * sizeof(struct yy_buffer_state*)
+                                                               , yyscanner);
+               if ( ! yyg->yy_buffer_stack )
+                       YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl_ensure_buffer_stack()" );
+                                                                 
+               memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+                               
+               yyg->yy_buffer_stack_max = num_to_alloc;
+               yyg->yy_buffer_stack_top = 0;
+               return;
+       }
+
+       if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+               /* Increase the buffer to prepare for a possible push. */
+               int grow_size = 8 /* arbitrary grow size */;
+
+               num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+               yyg->yy_buffer_stack = (struct yy_buffer_state**)_mesa_glsl_realloc
+                                                               (yyg->yy_buffer_stack,
+                                                               num_to_alloc * sizeof(struct yy_buffer_state*)
+                                                               , yyscanner);
+               if ( ! yyg->yy_buffer_stack )
+                       YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl_ensure_buffer_stack()" );
+
+               /* zero only the new slots.*/
+               memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+               yyg->yy_buffer_stack_max = num_to_alloc;
+       }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE _mesa_glsl__scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
+{
+       YY_BUFFER_STATE b;
+    
+       if ( size < 2 ||
+            base[size-2] != YY_END_OF_BUFFER_CHAR ||
+            base[size-1] != YY_END_OF_BUFFER_CHAR )
+               /* They forgot to leave room for the EOB's. */
+               return 0;
+
+       b = (YY_BUFFER_STATE) _mesa_glsl_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__scan_buffer()" );
+
+       b->yy_buf_size = size - 2;      /* "- 2" to take care of EOB's */
+       b->yy_buf_pos = b->yy_ch_buf = base;
+       b->yy_is_our_buffer = 0;
+       b->yy_input_file = 0;
+       b->yy_n_chars = b->yy_buf_size;
+       b->yy_is_interactive = 0;
+       b->yy_at_bol = 1;
+       b->yy_fill_buffer = 0;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       _mesa_glsl__switch_to_buffer(b ,yyscanner );
+
+       return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to _mesa_glsl_lex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       _mesa_glsl__scan_bytes() instead.
+ */
+YY_BUFFER_STATE _mesa_glsl__scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+    
+       return _mesa_glsl__scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to _mesa_glsl_lex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE _mesa_glsl__scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
+{
+       YY_BUFFER_STATE b;
+       char *buf;
+       yy_size_t n;
+       int i;
+    
+       /* Get memory for full buffer, including space for trailing EOB's. */
+       n = _yybytes_len + 2;
+       buf = (char *) _mesa_glsl_alloc(n ,yyscanner );
+       if ( ! buf )
+               YY_FATAL_ERROR( "out of dynamic memory in _mesa_glsl__scan_bytes()" );
+
+       for ( i = 0; i < _yybytes_len; ++i )
+               buf[i] = yybytes[i];
+
+       buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+       b = _mesa_glsl__scan_buffer(buf,n ,yyscanner);
+       if ( ! b )
+               YY_FATAL_ERROR( "bad buffer in _mesa_glsl__scan_bytes()" );
+
+       /* It's okay to grow etc. this buffer, and we should throw it
+        * away when we're done.
+        */
+       b->yy_is_our_buffer = 1;
+
+       return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+       (void) fprintf( stderr, "%s\n", msg );
+       exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+               yytext[yyleng] = yyg->yy_hold_char; \
+               yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+               yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+               *yyg->yy_c_buf_p = '\0'; \
+               yyleng = yyless_macro_arg; \
+               } \
+       while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE _mesa_glsl_get_extra  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int _mesa_glsl_get_lineno  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int _mesa_glsl_get_column  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *_mesa_glsl_get_in  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *_mesa_glsl_get_out  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int _mesa_glsl_get_leng  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *_mesa_glsl_get_text  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void _mesa_glsl_set_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void _mesa_glsl_set_lineno (int  line_number , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* lineno is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "_mesa_glsl_set_lineno called with no buffer" , yyscanner); 
+    
+    yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void _mesa_glsl_set_column (int  column_no , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* column is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "_mesa_glsl_set_column called with no buffer" , yyscanner); 
+    
+    yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see _mesa_glsl__switch_to_buffer
+ */
+void _mesa_glsl_set_in (FILE *  in_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyin = in_str ;
+}
+
+void _mesa_glsl_set_out (FILE *  out_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyout = out_str ;
+}
+
+int _mesa_glsl_get_debug  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yy_flex_debug;
+}
+
+void _mesa_glsl_set_debug (int  bdebug , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * _mesa_glsl_get_lval  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yylval;
+}
+
+void _mesa_glsl_set_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yylval = yylval_param;
+}
+
+YYLTYPE *_mesa_glsl_get_lloc  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yylloc;
+}
+    
+void _mesa_glsl_set_lloc (YYLTYPE *  yylloc_param , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yylloc = yylloc_param;
+}
+    
+/* User-visible API */
+
+/* _mesa_glsl_lex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int _mesa_glsl_lex_init(yyscan_t* ptr_yy_globals)
+
+{
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+
+    *ptr_yy_globals = (yyscan_t) _mesa_glsl_alloc ( sizeof( struct yyguts_t ), NULL );
+
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+
+    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* _mesa_glsl_lex_init_extra has the same functionality as _mesa_glsl_lex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to _mesa_glsl_alloc in
+ * the yyextra field.
+ */
+
+int _mesa_glsl_lex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+    struct yyguts_t dummy_yyguts;
+
+    _mesa_glsl_set_extra (yy_user_defined, &dummy_yyguts);
+
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+       
+    *ptr_yy_globals = (yyscan_t) _mesa_glsl_alloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+       
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+    
+    /* By setting to 0xAA, we expose bugs in
+    yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+    
+    _mesa_glsl_set_extra (yy_user_defined, *ptr_yy_globals);
+    
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from _mesa_glsl_lex_destroy(), so don't allocate here.
+     */
+
+    yyg->yy_buffer_stack = 0;
+    yyg->yy_buffer_stack_top = 0;
+    yyg->yy_buffer_stack_max = 0;
+    yyg->yy_c_buf_p = (char *) 0;
+    yyg->yy_init = 0;
+    yyg->yy_start = 0;
+
+    yyg->yy_start_stack_ptr = 0;
+    yyg->yy_start_stack_depth = 0;
+    yyg->yy_start_stack =  NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * _mesa_glsl_lex_init()
+     */
+    return 0;
+}
+
+/* _mesa_glsl_lex_destroy is for both reentrant and non-reentrant scanners. */
+int _mesa_glsl_lex_destroy  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    /* Pop the buffer stack, destroying each element. */
+       while(YY_CURRENT_BUFFER){
+               _mesa_glsl__delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+               YY_CURRENT_BUFFER_LVALUE = NULL;
+               _mesa_glsl_pop_buffer_state(yyscanner);
+       }
+
+       /* Destroy the stack itself. */
+       _mesa_glsl_free(yyg->yy_buffer_stack ,yyscanner);
+       yyg->yy_buffer_stack = NULL;
+
+    /* Destroy the start condition stack. */
+        _mesa_glsl_free(yyg->yy_start_stack ,yyscanner );
+        yyg->yy_start_stack = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * _mesa_glsl_lex() is called, initialization will occur. */
+    yy_init_globals( yyscanner);
+
+    /* Destroy the main struct (reentrant only). */
+    _mesa_glsl_free ( yyscanner , yyscanner );
+    yyscanner = NULL;
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+       register int i;
+       for ( i = 0; i < n; ++i )
+               s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+       register int n;
+       for ( n = 0; s[n]; ++n )
+               ;
+
+       return n;
+}
+#endif
+
+void *_mesa_glsl_alloc (yy_size_t  size , yyscan_t yyscanner)
+{
+       return (void *) malloc( size );
+}
+
+void *_mesa_glsl_realloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
+{
+       /* The cast to (char *) in the following accommodates both
+        * implementations that use char* generic pointers, and those
+        * that use void* generic pointers.  It works with the latter
+        * because both ANSI C and C++ allow castless assignment from
+        * any pointer type to void*, and deal with argument conversions
+        * as though doing an assignment.
+        */
+       return (void *) realloc( (char *) ptr, size );
+}
+
+void _mesa_glsl_free (void * ptr , yyscan_t yyscanner)
+{
+       free( (char *) ptr );   /* see _mesa_glsl_realloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 376 "glsl_lexer.lpp"
+
+
+
+void
+_mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, const char *string)
+{
+   _mesa_glsl_lex_init_extra(state,& state->scanner);
+   _mesa_glsl__scan_string(string,state->scanner);
+}
+
+void
+_mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state)
+{
+   _mesa_glsl_lex_destroy(state->scanner);
+}
+
diff --git a/src/glsl/glsl_lexer.lpp b/src/glsl/glsl_lexer.lpp
new file mode 100644 (file)
index 0000000..1de1fb4
--- /dev/null
@@ -0,0 +1,389 @@
+%{
+/*
+ * Copyright Â© 2008, 2009 Intel Corporation
+ *
+ * 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 <ctype.h>
+#include "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_parser.h"
+
+#define YY_USER_ACTION                                         \
+   do {                                                                \
+      yylloc->source = 0;                                      \
+      yylloc->first_column = yycolumn + 1;                     \
+      yylloc->first_line = yylineno + 1;                       \
+      yycolumn += yyleng;                                      \
+   } while(0);
+
+#define YY_USER_INIT yylineno = 0; yycolumn = 0;
+
+#define TOKEN_OR_IDENTIFIER(version, token)                     \
+   do {                                                                 \
+      if (yyextra->language_version >= version) {               \
+        return token;                                           \
+      } else {                                                  \
+        yylval->identifier = strdup(yytext);                    \
+        return IDENTIFIER;                                      \
+      }                                                                 \
+   } while (0)
+
+#define RESERVED_WORD(version, token)                                  \
+   do {                                                                        \
+      if (yyextra->language_version >= version) {                      \
+        return token;                                                  \
+      } else {                                                         \
+        _mesa_glsl_error(yylloc, yyextra,                              \
+                         "Illegal use of reserved word `%s'", yytext); \
+        return ERROR_TOK;                                              \
+      }                                                                        \
+   } while (0)
+%}
+
+%option bison-bridge bison-locations reentrant noyywrap
+%option nounput noyy_top_state
+%option never-interactive
+%option prefix="_mesa_glsl_"
+%option extra-type="struct _mesa_glsl_parse_state *"
+
+%x PP PRAGMA
+
+DEC_INT                [1-9][0-9]*
+HEX_INT                0[xX][0-9a-fA-F]+
+OCT_INT                0[0-7]*
+INT            ({DEC_INT}|{HEX_INT}|{OCT_INT})
+SPC            [ \t]*
+SPCP           [ \t]+
+HASH           ^{SPC}#{SPC}
+%%
+
+[ \r\t]+               ;
+
+    /* Preprocessor tokens. */ 
+^[ \t]*#[ \t]*$                        ;
+^[ \t]*#[ \t]*version          { BEGIN PP; return VERSION; }
+^[ \t]*#[ \t]*extension                { BEGIN PP; return EXTENSION; }
+{HASH}line{SPCP}{INT}{SPCP}{INT}{SPC}$ {
+                                  /* Eat characters until the first digit is
+                                   * encountered
+                                   */
+                                  char *ptr = yytext;
+                                  while (!isdigit(*ptr))
+                                     ptr++;
+
+                                  /* Subtract one from the line number because
+                                   * yylineno is zero-based instead of
+                                   * one-based.
+                                   */
+                                  yylineno = strtol(ptr, &ptr, 0) - 1;
+                                  yylloc->source = strtol(ptr, NULL, 0);
+                               }
+{HASH}line{SPCP}{INT}{SPC}$    {
+                                  /* Eat characters until the first digit is
+                                   * encountered
+                                   */
+                                  char *ptr = yytext;
+                                  while (!isdigit(*ptr))
+                                     ptr++;
+
+                                  /* Subtract one from the line number because
+                                   * yylineno is zero-based instead of
+                                   * one-based.
+                                   */
+                                  yylineno = strtol(ptr, &ptr, 0) - 1;
+                               }
+^{SPC}#{SPC}pragma{SPCP}debug{SPC}\({SPC}on{SPC}\) {
+                                 BEGIN PP;
+                                 return PRAGMA_DEBUG_ON;
+                               }
+^{SPC}#{SPC}pragma{SPCP}debug{SPC}\({SPC}off{SPC}\) {
+                                 BEGIN PP;
+                                 return PRAGMA_DEBUG_OFF;
+                               }
+^{SPC}#{SPC}pragma{SPCP}optimize{SPC}\({SPC}on{SPC}\) {
+                                 BEGIN PP;
+                                 return PRAGMA_OPTIMIZE_ON;
+                               }
+^{SPC}#{SPC}pragma{SPCP}optimize{SPC}\({SPC}off{SPC}\) {
+                                 BEGIN PP;
+                                 return PRAGMA_OPTIMIZE_OFF;
+                               }
+^{SPC}#{SPC}pragma{SPCP}       { BEGIN PRAGMA; }
+
+<PRAGMA>\n                     { BEGIN 0; yylineno++; yycolumn = 0; }
+<PRAGMA>.                      { }
+
+<PP>\/\/[^\n]*                 { }
+<PP>[ \t\r]*                   { }
+<PP>:                          return COLON;
+<PP>[_a-zA-Z][_a-zA-Z0-9]*     {
+                                  yylval->identifier = strdup(yytext);
+                                  return IDENTIFIER;
+                               }
+<PP>[1-9][0-9]*                        {
+                                   yylval->n = strtol(yytext, NULL, 10);
+                                   return INTCONSTANT;
+                               }
+<PP>\n                         { BEGIN 0; yylineno++; yycolumn = 0; return EOL; }
+
+\n             { yylineno++; yycolumn = 0; }
+
+attribute      return ATTRIBUTE;
+const          return CONST_TOK;
+bool           return BOOL_TOK;
+float          return FLOAT_TOK;
+int            return INT_TOK;
+
+break          return BREAK;
+continue       return CONTINUE;
+do             return DO;
+while          return WHILE;
+else           return ELSE;
+for            return FOR;
+if             return IF;
+discard                return DISCARD;
+return         return RETURN;
+
+bvec2          return BVEC2;
+bvec3          return BVEC3;
+bvec4          return BVEC4;
+ivec2          return IVEC2;
+ivec3          return IVEC3;
+ivec4          return IVEC4;
+vec2           return VEC2;
+vec3           return VEC3;
+vec4           return VEC4;
+mat2           return MAT2X2;
+mat3           return MAT3X3;
+mat4           return MAT4X4;
+mat2x2         TOKEN_OR_IDENTIFIER(120, MAT2X2);
+mat2x3         TOKEN_OR_IDENTIFIER(120, MAT2X3);
+mat2x4         TOKEN_OR_IDENTIFIER(120, MAT2X4);
+mat3x2         TOKEN_OR_IDENTIFIER(120, MAT3X2);
+mat3x3         TOKEN_OR_IDENTIFIER(120, MAT3X3);
+mat3x4         TOKEN_OR_IDENTIFIER(120, MAT3X4);
+mat4x2         TOKEN_OR_IDENTIFIER(120, MAT4X2);
+mat4x3         TOKEN_OR_IDENTIFIER(120, MAT4X3);
+mat4x4         TOKEN_OR_IDENTIFIER(120, MAT4X4);
+
+in             return IN_TOK;
+out            return OUT_TOK;
+inout          return INOUT_TOK;
+uniform                return UNIFORM;
+varying                return VARYING;
+centroid       TOKEN_OR_IDENTIFIER(120, CENTROID);
+invariant      TOKEN_OR_IDENTIFIER(120, INVARIANT);
+
+flat           TOKEN_OR_IDENTIFIER(130, FLAT);
+smooth         TOKEN_OR_IDENTIFIER(130, SMOOTH);
+noperspective  TOKEN_OR_IDENTIFIER(130, NOPERSPECTIVE);
+
+sampler1D      return SAMPLER1D;
+sampler2D      return SAMPLER2D;
+sampler3D      return SAMPLER3D;
+samplerCube    return SAMPLERCUBE;
+sampler1DShadow        return SAMPLER1DSHADOW;
+sampler2DShadow        return SAMPLER2DSHADOW;
+
+struct         return STRUCT;
+void           return VOID_TOK;
+
+layout         {
+                 if ((yyextra->language_version >= 140)
+                     || (yyextra->ARB_fragment_coord_conventions_enable)){
+                     return LAYOUT_TOK;
+                  } else {
+                     yylval->identifier = strdup(yytext);
+                     return IDENTIFIER;
+                  }
+               }
+
+\+\+           return INC_OP;
+--             return DEC_OP;
+\<=            return LE_OP;
+>=             return GE_OP;
+==             return EQ_OP;
+!=             return NE_OP;
+&&             return AND_OP;
+\|\|           return OR_OP;
+"^^"           return XOR_OP;
+
+\*=            return MUL_ASSIGN;
+\/=            return DIV_ASSIGN;
+\+=            return ADD_ASSIGN;
+\%=            return MOD_ASSIGN;
+\<\<=          return LEFT_ASSIGN;
+>>=            return RIGHT_ASSIGN;
+&=             return AND_ASSIGN;
+^=             return XOR_ASSIGN;
+\|=            return OR_ASSIGN;
+-=             return SUB_ASSIGN;
+
+[1-9][0-9]*            {
+                           yylval->n = strtol(yytext, NULL, 10);
+                           return INTCONSTANT;
+                       }
+0[xX][0-9a-fA-F]+      {
+                           yylval->n = strtol(yytext + 2, NULL, 16);
+                           return INTCONSTANT;
+                       }
+0[0-7]*                        {
+                           yylval->n = strtol(yytext, NULL, 8);
+                           return INTCONSTANT;
+                       }
+
+[0-9]+\.[0-9]+([eE][+-]?[0-9]+)?[fF]?  {
+                           yylval->real = strtod(yytext, NULL);
+                           return FLOATCONSTANT;
+                       }
+\.[0-9]+([eE][+-]?[0-9]+)?[fF]?                {
+                           yylval->real = strtod(yytext, NULL);
+                           return FLOATCONSTANT;
+                       }
+[0-9]+\.([eE][+-]?[0-9]+)?[fF]?                {
+                           yylval->real = strtod(yytext, NULL);
+                           return FLOATCONSTANT;
+                       }
+[0-9]+[eE][+-]?[0-9]+[fF]?             {
+                           yylval->real = strtod(yytext, NULL);
+                           return FLOATCONSTANT;
+                       }
+[0-9]+[fF]             {
+                           yylval->real = strtod(yytext, NULL);
+                           return FLOATCONSTANT;
+                       }
+
+true                   {
+                           yylval->n = 1;
+                           return BOOLCONSTANT;
+                       }
+false                  {
+                           yylval->n = 0;
+                           return BOOLCONSTANT;
+                       }
+
+
+    /* Reserved words in GLSL 1.10. */
+asm            RESERVED_WORD(999, ASM);
+class          RESERVED_WORD(999, CLASS);
+union          RESERVED_WORD(999, UNION);
+enum           RESERVED_WORD(999, ENUM);
+typedef                RESERVED_WORD(999, TYPEDEF);
+template       RESERVED_WORD(999, TEMPLATE);
+this           RESERVED_WORD(999, THIS);
+packed         RESERVED_WORD(999, PACKED_TOK);
+goto           RESERVED_WORD(999, GOTO);
+switch         RESERVED_WORD(130, SWITCH);
+default                RESERVED_WORD(130, DEFAULT);
+inline         RESERVED_WORD(999, INLINE_TOK);
+noinline       RESERVED_WORD(999, NOINLINE);
+volatile       RESERVED_WORD(999, VOLATILE);
+public         RESERVED_WORD(999, PUBLIC_TOK);
+static         RESERVED_WORD(999, STATIC);
+extern         RESERVED_WORD(999, EXTERN);
+external       RESERVED_WORD(999, EXTERNAL);
+interface      RESERVED_WORD(999, INTERFACE);
+long           RESERVED_WORD(999, LONG_TOK);
+short          RESERVED_WORD(999, SHORT_TOK);
+double         RESERVED_WORD(999, DOUBLE_TOK);
+half           RESERVED_WORD(999, HALF);
+fixed          RESERVED_WORD(999, FIXED_TOK);
+unsigned       RESERVED_WORD(999, UNSIGNED);
+input          RESERVED_WORD(999, INPUT_TOK);
+output         RESERVED_WORD(999, OUTPUT);
+hvec2          RESERVED_WORD(999, HVEC2);
+hvec3          RESERVED_WORD(999, HVEC3);
+hvec4          RESERVED_WORD(999, HVEC4);
+dvec2          RESERVED_WORD(999, DVEC2);
+dvec3          RESERVED_WORD(999, DVEC3);
+dvec4          RESERVED_WORD(999, DVEC4);
+fvec2          RESERVED_WORD(999, FVEC2);
+fvec3          RESERVED_WORD(999, FVEC3);
+fvec4          RESERVED_WORD(999, FVEC4);
+sampler2DRect          return SAMPLER2DRECT;
+sampler3DRect          RESERVED_WORD(999, SAMPLER3DRECT);
+sampler2DRectShadow    return SAMPLER2DRECTSHADOW;
+sizeof         RESERVED_WORD(999, SIZEOF);
+cast           RESERVED_WORD(999, CAST);
+namespace      RESERVED_WORD(999, NAMESPACE);
+using          RESERVED_WORD(999, USING);
+
+    /* Additional reserved words in GLSL 1.20. */
+lowp           TOKEN_OR_IDENTIFIER(120, LOWP);
+mediump                TOKEN_OR_IDENTIFIER(120, MEDIUMP);
+highp          TOKEN_OR_IDENTIFIER(120, HIGHP);
+precision      TOKEN_OR_IDENTIFIER(120, PRECISION);
+
+    /* Additional reserved words in GLSL 1.30. */
+common         TOKEN_OR_IDENTIFIER(130, COMMON);
+partition      TOKEN_OR_IDENTIFIER(130, PARTITION);
+active         TOKEN_OR_IDENTIFIER(130, ACTIVE);
+superp         TOKEN_OR_IDENTIFIER(130, SUPERP);
+samplerBuffer  TOKEN_OR_IDENTIFIER(130, SAMPLERBUFFER);
+filter         TOKEN_OR_IDENTIFIER(130, FILTER);
+image1D                TOKEN_OR_IDENTIFIER(130, IMAGE1D);
+image2D                TOKEN_OR_IDENTIFIER(130, IMAGE2D);
+image3D                TOKEN_OR_IDENTIFIER(130, IMAGE3D);
+imageCube      TOKEN_OR_IDENTIFIER(130, IMAGECUBE);
+iimage1D       TOKEN_OR_IDENTIFIER(130, IIMAGE1D);
+iimage2D       TOKEN_OR_IDENTIFIER(130, IIMAGE2D);
+iimage3D       TOKEN_OR_IDENTIFIER(130, IIMAGE3D);
+iimageCube     TOKEN_OR_IDENTIFIER(130, IIMAGECUBE);
+uimage1D       TOKEN_OR_IDENTIFIER(130, UIMAGE1D);
+uimage2D       TOKEN_OR_IDENTIFIER(130, UIMAGE2D);
+uimage3D       TOKEN_OR_IDENTIFIER(130, UIMAGE3D);
+uimageCube     TOKEN_OR_IDENTIFIER(130, UIMAGECUBE);
+image1DArray   TOKEN_OR_IDENTIFIER(130, IMAGE1DARRAY);
+image2DArray   TOKEN_OR_IDENTIFIER(130, IMAGE2DARRAY);
+iimage1DArray  TOKEN_OR_IDENTIFIER(130, IIMAGE1DARRAY);
+iimage2DArray  TOKEN_OR_IDENTIFIER(130, IIMAGE2DARRAY);
+uimage1DArray  TOKEN_OR_IDENTIFIER(130, UIMAGE1DARRAY);
+uimage2DArray  TOKEN_OR_IDENTIFIER(130, UIMAGE2DARRAY);
+image1DShadow  TOKEN_OR_IDENTIFIER(130, IMAGE1DSHADOW);
+image2DShadow  TOKEN_OR_IDENTIFIER(130, IMAGE2DSHADOW);
+imageBuffer    TOKEN_OR_IDENTIFIER(130, IMAGEBUFFER);
+iimageBuffer   TOKEN_OR_IDENTIFIER(130, IIMAGEBUFFER);
+uimageBuffer   TOKEN_OR_IDENTIFIER(130, UIMAGEBUFFER);
+row_major      TOKEN_OR_IDENTIFIER(130, ROW_MAJOR);
+
+[_a-zA-Z][_a-zA-Z0-9]* {
+                           struct _mesa_glsl_parse_state *state = yyextra;
+                           void *ctx = state;  
+                           yylval->identifier = talloc_strdup(ctx, yytext);
+                           return IDENTIFIER;
+                       }
+
+.                      { return yytext[0]; }
+
+%%
+
+void
+_mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, const char *string)
+{
+   yylex_init_extra(state, & state->scanner);
+   yy_scan_string(string, state->scanner);
+}
+
+void
+_mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state)
+{
+   yylex_destroy(state->scanner);
+}
diff --git a/src/glsl/glsl_parser.cpp b/src/glsl/glsl_parser.cpp
new file mode 100644 (file)
index 0000000..e36bb03
--- /dev/null
@@ -0,0 +1,5268 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1.  */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+   
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+   
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.4.1"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 1
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+/* Using locations.  */
+#define YYLSP_NEEDED 1
+
+/* Substitute the variable and function names.  */
+#define yyparse         _mesa_glsl_parse
+#define yylex           _mesa_glsl_lex
+#define yyerror         _mesa_glsl_error
+#define yylval          _mesa_glsl_lval
+#define yychar          _mesa_glsl_char
+#define yydebug         _mesa_glsl_debug
+#define yynerrs         _mesa_glsl_nerrs
+#define yylloc          _mesa_glsl_lloc
+
+/* Copy the first part of user declarations.  */
+
+/* Line 189 of yacc.c  */
+#line 1 "glsl_parser.ypp"
+
+/*
+ * Copyright Â© 2008, 2009 Intel Corporation
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <assert.h>
+    
+#include "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_types.h"
+
+#define YYLEX_PARAM state->scanner
+
+
+
+/* Line 189 of yacc.c  */
+#line 118 "glsl_parser.cpp"
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     ATTRIBUTE = 258,
+     CONST_TOK = 259,
+     BOOL_TOK = 260,
+     FLOAT_TOK = 261,
+     INT_TOK = 262,
+     UINT_TOK = 263,
+     BREAK = 264,
+     CONTINUE = 265,
+     DO = 266,
+     ELSE = 267,
+     FOR = 268,
+     IF = 269,
+     DISCARD = 270,
+     RETURN = 271,
+     SWITCH = 272,
+     CASE = 273,
+     DEFAULT = 274,
+     BVEC2 = 275,
+     BVEC3 = 276,
+     BVEC4 = 277,
+     IVEC2 = 278,
+     IVEC3 = 279,
+     IVEC4 = 280,
+     UVEC2 = 281,
+     UVEC3 = 282,
+     UVEC4 = 283,
+     VEC2 = 284,
+     VEC3 = 285,
+     VEC4 = 286,
+     CENTROID = 287,
+     IN_TOK = 288,
+     OUT_TOK = 289,
+     INOUT_TOK = 290,
+     UNIFORM = 291,
+     VARYING = 292,
+     NOPERSPECTIVE = 293,
+     FLAT = 294,
+     SMOOTH = 295,
+     MAT2X2 = 296,
+     MAT2X3 = 297,
+     MAT2X4 = 298,
+     MAT3X2 = 299,
+     MAT3X3 = 300,
+     MAT3X4 = 301,
+     MAT4X2 = 302,
+     MAT4X3 = 303,
+     MAT4X4 = 304,
+     SAMPLER1D = 305,
+     SAMPLER2D = 306,
+     SAMPLER3D = 307,
+     SAMPLERCUBE = 308,
+     SAMPLER1DSHADOW = 309,
+     SAMPLER2DSHADOW = 310,
+     SAMPLERCUBESHADOW = 311,
+     SAMPLER1DARRAY = 312,
+     SAMPLER2DARRAY = 313,
+     SAMPLER1DARRAYSHADOW = 314,
+     SAMPLER2DARRAYSHADOW = 315,
+     ISAMPLER1D = 316,
+     ISAMPLER2D = 317,
+     ISAMPLER3D = 318,
+     ISAMPLERCUBE = 319,
+     ISAMPLER1DARRAY = 320,
+     ISAMPLER2DARRAY = 321,
+     USAMPLER1D = 322,
+     USAMPLER2D = 323,
+     USAMPLER3D = 324,
+     USAMPLERCUBE = 325,
+     USAMPLER1DARRAY = 326,
+     USAMPLER2DARRAY = 327,
+     STRUCT = 328,
+     VOID_TOK = 329,
+     WHILE = 330,
+     IDENTIFIER = 331,
+     FLOATCONSTANT = 332,
+     INTCONSTANT = 333,
+     UINTCONSTANT = 334,
+     BOOLCONSTANT = 335,
+     FIELD_SELECTION = 336,
+     LEFT_OP = 337,
+     RIGHT_OP = 338,
+     INC_OP = 339,
+     DEC_OP = 340,
+     LE_OP = 341,
+     GE_OP = 342,
+     EQ_OP = 343,
+     NE_OP = 344,
+     AND_OP = 345,
+     OR_OP = 346,
+     XOR_OP = 347,
+     MUL_ASSIGN = 348,
+     DIV_ASSIGN = 349,
+     ADD_ASSIGN = 350,
+     MOD_ASSIGN = 351,
+     LEFT_ASSIGN = 352,
+     RIGHT_ASSIGN = 353,
+     AND_ASSIGN = 354,
+     XOR_ASSIGN = 355,
+     OR_ASSIGN = 356,
+     SUB_ASSIGN = 357,
+     INVARIANT = 358,
+     LOWP = 359,
+     MEDIUMP = 360,
+     HIGHP = 361,
+     SUPERP = 362,
+     PRECISION = 363,
+     VERSION = 364,
+     EXTENSION = 365,
+     LINE = 366,
+     COLON = 367,
+     EOL = 368,
+     INTERFACE = 369,
+     OUTPUT = 370,
+     PRAGMA_DEBUG_ON = 371,
+     PRAGMA_DEBUG_OFF = 372,
+     PRAGMA_OPTIMIZE_ON = 373,
+     PRAGMA_OPTIMIZE_OFF = 374,
+     LAYOUT_TOK = 375,
+     ASM = 376,
+     CLASS = 377,
+     UNION = 378,
+     ENUM = 379,
+     TYPEDEF = 380,
+     TEMPLATE = 381,
+     THIS = 382,
+     PACKED_TOK = 383,
+     GOTO = 384,
+     INLINE_TOK = 385,
+     NOINLINE = 386,
+     VOLATILE = 387,
+     PUBLIC_TOK = 388,
+     STATIC = 389,
+     EXTERN = 390,
+     EXTERNAL = 391,
+     LONG_TOK = 392,
+     SHORT_TOK = 393,
+     DOUBLE_TOK = 394,
+     HALF = 395,
+     FIXED_TOK = 396,
+     UNSIGNED = 397,
+     INPUT_TOK = 398,
+     OUPTUT = 399,
+     HVEC2 = 400,
+     HVEC3 = 401,
+     HVEC4 = 402,
+     DVEC2 = 403,
+     DVEC3 = 404,
+     DVEC4 = 405,
+     FVEC2 = 406,
+     FVEC3 = 407,
+     FVEC4 = 408,
+     SAMPLER2DRECT = 409,
+     SAMPLER3DRECT = 410,
+     SAMPLER2DRECTSHADOW = 411,
+     SIZEOF = 412,
+     CAST = 413,
+     NAMESPACE = 414,
+     USING = 415,
+     ERROR_TOK = 416,
+     COMMON = 417,
+     PARTITION = 418,
+     ACTIVE = 419,
+     SAMPLERBUFFER = 420,
+     FILTER = 421,
+     IMAGE1D = 422,
+     IMAGE2D = 423,
+     IMAGE3D = 424,
+     IMAGECUBE = 425,
+     IMAGE1DARRAY = 426,
+     IMAGE2DARRAY = 427,
+     IIMAGE1D = 428,
+     IIMAGE2D = 429,
+     IIMAGE3D = 430,
+     IIMAGECUBE = 431,
+     IIMAGE1DARRAY = 432,
+     IIMAGE2DARRAY = 433,
+     UIMAGE1D = 434,
+     UIMAGE2D = 435,
+     UIMAGE3D = 436,
+     UIMAGECUBE = 437,
+     UIMAGE1DARRAY = 438,
+     UIMAGE2DARRAY = 439,
+     IMAGE1DSHADOW = 440,
+     IMAGE2DSHADOW = 441,
+     IMAGEBUFFER = 442,
+     IIMAGEBUFFER = 443,
+     UIMAGEBUFFER = 444,
+     ROW_MAJOR = 445
+   };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 214 of yacc.c  */
+#line 52 "glsl_parser.ypp"
+
+   int n;
+   float real;
+   char *identifier;
+
+   union {
+      struct ast_type_qualifier q;
+      unsigned i;
+   } type_qualifier;
+
+   ast_node *node;
+   ast_type_specifier *type_specifier;
+   ast_fully_specified_type *fully_specified_type;
+   ast_function *function;
+   ast_parameter_declarator *parameter_declarator;
+   ast_function_definition *function_definition;
+   ast_compound_statement *compound_statement;
+   ast_expression *expression;
+   ast_declarator_list *declarator_list;
+   ast_struct_specifier *struct_specifier;
+   ast_declaration *declaration;
+
+   struct {
+      ast_node *cond;
+      ast_expression *rest;
+   } for_rest_statement;
+
+
+
+/* Line 214 of yacc.c  */
+#line 374 "glsl_parser.cpp"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 264 of yacc.c  */
+#line 399 "glsl_parser.cpp"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+    int yyi;
+#endif
+{
+  return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+            && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+        || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+            && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+  YYLTYPE yyls_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+      + 2 * YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)             \
+      do                                       \
+       {                                       \
+         YYSIZE_T yyi;                         \
+         for (yyi = 0; yyi < (Count); yyi++)   \
+           (To)[yyi] = (From)[yyi];            \
+       }                                       \
+      while (YYID (0))
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                          \
+    do                                                                 \
+      {                                                                        \
+       YYSIZE_T yynewbytes;                                            \
+       YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+       Stack = &yyptr->Stack_alloc;                                    \
+       yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+       yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                        \
+    while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  5
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   4115
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  215
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  90
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  278
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  419
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   445
+
+#define YYTRANSLATE(YYX)                                               \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,   199,     2,     2,     2,   203,   206,     2,
+     191,   192,   201,   197,   196,   198,   195,   202,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,   210,   212,
+     204,   211,   205,   209,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,   193,     2,   194,   207,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,   213,   208,   214,   200,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
+      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
+      95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
+     105,   106,   107,   108,   109,   110,   111,   112,   113,   114,
+     115,   116,   117,   118,   119,   120,   121,   122,   123,   124,
+     125,   126,   127,   128,   129,   130,   131,   132,   133,   134,
+     135,   136,   137,   138,   139,   140,   141,   142,   143,   144,
+     145,   146,   147,   148,   149,   150,   151,   152,   153,   154,
+     155,   156,   157,   158,   159,   160,   161,   162,   163,   164,
+     165,   166,   167,   168,   169,   170,   171,   172,   173,   174,
+     175,   176,   177,   178,   179,   180,   181,   182,   183,   184,
+     185,   186,   187,   188,   189,   190
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const yytype_uint16 yyprhs[] =
+{
+       0,     0,     3,     4,     9,    10,    14,    17,    20,    23,
+      26,    27,    30,    36,    38,    41,    43,    45,    47,    49,
+      51,    53,    57,    59,    64,    66,    70,    73,    76,    78,
+      80,    82,    86,    89,    92,    95,    97,   100,   104,   107,
+     109,   111,   113,   115,   118,   121,   124,   126,   128,   130,
+     132,   134,   138,   142,   146,   148,   152,   156,   158,   162,
+     166,   168,   172,   176,   180,   184,   186,   190,   194,   196,
+     200,   202,   206,   208,   212,   214,   218,   220,   224,   226,
+     230,   232,   238,   240,   244,   246,   248,   250,   252,   254,
+     256,   258,   260,   262,   264,   266,   268,   272,   274,   277,
+     280,   285,   288,   290,   292,   295,   299,   303,   306,   312,
+     316,   319,   323,   326,   327,   329,   331,   333,   335,   337,
+     341,   347,   354,   362,   371,   377,   379,   382,   387,   393,
+     400,   408,   413,   416,   418,   421,   422,   424,   429,   431,
+     435,   437,   439,   441,   443,   445,   447,   450,   453,   455,
+     457,   460,   463,   466,   468,   471,   474,   476,   478,   481,
+     483,   487,   492,   494,   496,   498,   500,   502,   504,   506,
+     508,   510,   512,   514,   516,   518,   520,   522,   524,   526,
+     528,   530,   532,   534,   536,   538,   540,   542,   544,   546,
+     548,   550,   552,   554,   556,   558,   560,   562,   564,   566,
+     568,   570,   572,   574,   576,   578,   580,   582,   584,   586,
+     588,   590,   592,   594,   596,   598,   600,   602,   604,   606,
+     612,   617,   619,   622,   626,   628,   632,   634,   639,   641,
+     643,   645,   647,   649,   651,   653,   655,   657,   659,   661,
+     663,   665,   667,   670,   674,   676,   678,   681,   685,   687,
+     690,   692,   695,   703,   709,   715,   723,   725,   730,   736,
+     740,   743,   749,   757,   764,   766,   768,   770,   771,   774,
+     778,   781,   784,   787,   791,   794,   796,   798,   800
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const yytype_int16 yyrhs[] =
+{
+     216,     0,    -1,    -1,   218,   220,   217,   222,    -1,    -1,
+     109,    78,   113,    -1,   116,   113,    -1,   117,   113,    -1,
+     118,   113,    -1,   119,   113,    -1,    -1,   220,   221,    -1,
+     110,    76,   112,    76,   113,    -1,   303,    -1,   222,   303,
+      -1,    76,    -1,   223,    -1,    78,    -1,    79,    -1,    77,
+      -1,    80,    -1,   191,   250,   192,    -1,   224,    -1,   225,
+     193,   226,   194,    -1,   227,    -1,   225,   195,    76,    -1,
+     225,    84,    -1,   225,    85,    -1,   250,    -1,   228,    -1,
+     229,    -1,   225,   195,   229,    -1,   231,   192,    -1,   230,
+     192,    -1,   232,    74,    -1,   232,    -1,   232,   248,    -1,
+     231,   196,   248,    -1,   233,   191,    -1,   272,    -1,    76,
+      -1,    81,    -1,   225,    -1,    84,   234,    -1,    85,   234,
+      -1,   235,   234,    -1,   197,    -1,   198,    -1,   199,    -1,
+     200,    -1,   234,    -1,   236,   201,   234,    -1,   236,   202,
+     234,    -1,   236,   203,   234,    -1,   236,    -1,   237,   197,
+     236,    -1,   237,   198,   236,    -1,   237,    -1,   238,    82,
+     237,    -1,   238,    83,   237,    -1,   238,    -1,   239,   204,
+     238,    -1,   239,   205,   238,    -1,   239,    86,   238,    -1,
+     239,    87,   238,    -1,   239,    -1,   240,    88,   239,    -1,
+     240,    89,   239,    -1,   240,    -1,   241,   206,   240,    -1,
+     241,    -1,   242,   207,   241,    -1,   242,    -1,   243,   208,
+     242,    -1,   243,    -1,   244,    90,   243,    -1,   244,    -1,
+     245,    92,   244,    -1,   245,    -1,   246,    91,   245,    -1,
+     246,    -1,   246,   209,   250,   210,   248,    -1,   247,    -1,
+     234,   249,   248,    -1,   211,    -1,    93,    -1,    94,    -1,
+      96,    -1,    95,    -1,   102,    -1,    97,    -1,    98,    -1,
+      99,    -1,   100,    -1,   101,    -1,   248,    -1,   250,   196,
+     248,    -1,   247,    -1,   253,   212,    -1,   261,   212,    -1,
+     108,   276,   273,   212,    -1,   254,   192,    -1,   256,    -1,
+     255,    -1,   256,   258,    -1,   255,   196,   258,    -1,   263,
+      76,   191,    -1,   272,    76,    -1,   272,    76,   193,   251,
+     194,    -1,   269,   259,   257,    -1,   259,   257,    -1,   269,
+     259,   260,    -1,   259,   260,    -1,    -1,    33,    -1,    34,
+      -1,    35,    -1,   272,    -1,   262,    -1,   261,   196,    76,
+      -1,   261,   196,    76,   193,   194,    -1,   261,   196,    76,
+     193,   251,   194,    -1,   261,   196,    76,   193,   194,   211,
+     282,    -1,   261,   196,    76,   193,   251,   194,   211,   282,
+      -1,   261,   196,    76,   211,   282,    -1,   263,    -1,   263,
+      76,    -1,   263,    76,   193,   194,    -1,   263,    76,   193,
+     251,   194,    -1,   263,    76,   193,   194,   211,   282,    -1,
+     263,    76,   193,   251,   194,   211,   282,    -1,   263,    76,
+     211,   282,    -1,   103,    76,    -1,   272,    -1,   270,   272,
+      -1,    -1,   265,    -1,   120,   191,   266,   192,    -1,   267,
+      -1,   266,   196,   267,    -1,    76,    -1,    40,    -1,    39,
+      -1,    38,    -1,     4,    -1,   271,    -1,   268,   270,    -1,
+     103,   270,    -1,     4,    -1,     3,    -1,   264,    37,    -1,
+      32,    37,    -1,   264,    33,    -1,    34,    -1,    32,    33,
+      -1,    32,    34,    -1,    36,    -1,   273,    -1,   276,   273,
+      -1,   274,    -1,   274,   193,   194,    -1,   274,   193,   251,
+     194,    -1,   275,    -1,   277,    -1,    76,    -1,    74,    -1,
+       6,    -1,     7,    -1,     8,    -1,     5,    -1,    29,    -1,
+      30,    -1,    31,    -1,    20,    -1,    21,    -1,    22,    -1,
+      23,    -1,    24,    -1,    25,    -1,    26,    -1,    27,    -1,
+      28,    -1,    41,    -1,    42,    -1,    43,    -1,    44,    -1,
+      45,    -1,    46,    -1,    47,    -1,    48,    -1,    49,    -1,
+      50,    -1,    51,    -1,   154,    -1,    52,    -1,    53,    -1,
+      54,    -1,    55,    -1,   156,    -1,    56,    -1,    57,    -1,
+      58,    -1,    59,    -1,    60,    -1,    61,    -1,    62,    -1,
+      63,    -1,    64,    -1,    65,    -1,    66,    -1,    67,    -1,
+      68,    -1,    69,    -1,    70,    -1,    71,    -1,    72,    -1,
+     106,    -1,   105,    -1,   104,    -1,    73,    76,   213,   278,
+     214,    -1,    73,   213,   278,   214,    -1,   279,    -1,   278,
+     279,    -1,   272,   280,   212,    -1,   281,    -1,   280,   196,
+     281,    -1,    76,    -1,    76,   193,   251,   194,    -1,   248,
+      -1,   252,    -1,   285,    -1,   286,    -1,   288,    -1,   287,
+      -1,   294,    -1,   283,    -1,   292,    -1,   293,    -1,   296,
+      -1,   297,    -1,   298,    -1,   302,    -1,   213,   214,    -1,
+     213,   291,   214,    -1,   290,    -1,   287,    -1,   213,   214,
+      -1,   213,   291,   214,    -1,   284,    -1,   291,   284,    -1,
+     212,    -1,   250,   212,    -1,    14,   191,   250,   192,   285,
+      12,   285,    -1,    14,   191,   250,   192,   285,    -1,    14,
+     191,   250,   192,   286,    -1,    14,   191,   250,   192,   285,
+      12,   286,    -1,   250,    -1,   263,    76,   211,   282,    -1,
+      17,   191,   250,   192,   288,    -1,    18,   250,   210,    -1,
+      19,   210,    -1,    75,   191,   295,   192,   289,    -1,    11,
+     284,    75,   191,   250,   192,   212,    -1,    13,   191,   299,
+     301,   192,   289,    -1,   292,    -1,   283,    -1,   295,    -1,
+      -1,   300,   212,    -1,   300,   212,   250,    -1,    10,   212,
+      -1,     9,   212,    -1,    16,   212,    -1,    16,   250,   212,
+      -1,    15,   212,    -1,   304,    -1,   252,    -1,   219,    -1,
+     253,   290,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,   211,   211,   210,   219,   223,   242,   243,   244,   245,
+     248,   250,   254,   263,   271,   282,   286,   293,   300,   307,
+     314,   321,   328,   329,   335,   339,   346,   352,   361,   365,
+     369,   370,   379,   380,   384,   385,   389,   395,   407,   411,
+     417,   424,   435,   436,   442,   448,   458,   459,   460,   461,
+     465,   466,   472,   478,   487,   488,   494,   503,   504,   510,
+     519,   520,   526,   532,   538,   547,   548,   554,   563,   564,
+     573,   574,   583,   584,   593,   594,   603,   604,   613,   614,
+     623,   624,   633,   634,   643,   644,   645,   646,   647,   648,
+     649,   650,   651,   652,   653,   657,   661,   677,   681,   685,
+     689,   703,   707,   708,   712,   717,   725,   736,   746,   761,
+     768,   773,   784,   796,   797,   798,   799,   803,   807,   808,
+     817,   826,   835,   844,   853,   866,   877,   886,   895,   904,
+     913,   922,   931,   945,   952,   963,   964,   968,   975,   976,
+     983,  1017,  1018,  1019,  1023,  1027,  1028,  1032,  1040,  1041,
+    1042,  1043,  1044,  1045,  1046,  1047,  1048,  1052,  1053,  1061,
+    1062,  1068,  1077,  1083,  1089,  1098,  1099,  1100,  1101,  1102,
+    1103,  1104,  1105,  1106,  1107,  1108,  1109,  1110,  1111,  1112,
+    1113,  1114,  1115,  1116,  1117,  1118,  1119,  1120,  1121,  1122,
+    1123,  1124,  1125,  1126,  1127,  1128,  1129,  1130,  1131,  1132,
+    1133,  1134,  1135,  1136,  1137,  1138,  1139,  1140,  1141,  1142,
+    1143,  1144,  1145,  1146,  1147,  1148,  1152,  1163,  1174,  1188,
+    1194,  1203,  1208,  1216,  1231,  1236,  1244,  1250,  1259,  1263,
+    1269,  1270,  1274,  1275,  1279,  1283,  1284,  1285,  1286,  1287,
+    1288,  1289,  1293,  1299,  1308,  1309,  1313,  1319,  1328,  1338,
+    1350,  1356,  1365,  1374,  1380,  1386,  1395,  1399,  1413,  1417,
+    1418,  1422,  1429,  1436,  1446,  1447,  1451,  1453,  1459,  1464,
+    1473,  1479,  1485,  1491,  1497,  1506,  1507,  1508,  1512
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "ATTRIBUTE", "CONST_TOK", "BOOL_TOK",
+  "FLOAT_TOK", "INT_TOK", "UINT_TOK", "BREAK", "CONTINUE", "DO", "ELSE",
+  "FOR", "IF", "DISCARD", "RETURN", "SWITCH", "CASE", "DEFAULT", "BVEC2",
+  "BVEC3", "BVEC4", "IVEC2", "IVEC3", "IVEC4", "UVEC2", "UVEC3", "UVEC4",
+  "VEC2", "VEC3", "VEC4", "CENTROID", "IN_TOK", "OUT_TOK", "INOUT_TOK",
+  "UNIFORM", "VARYING", "NOPERSPECTIVE", "FLAT", "SMOOTH", "MAT2X2",
+  "MAT2X3", "MAT2X4", "MAT3X2", "MAT3X3", "MAT3X4", "MAT4X2", "MAT4X3",
+  "MAT4X4", "SAMPLER1D", "SAMPLER2D", "SAMPLER3D", "SAMPLERCUBE",
+  "SAMPLER1DSHADOW", "SAMPLER2DSHADOW", "SAMPLERCUBESHADOW",
+  "SAMPLER1DARRAY", "SAMPLER2DARRAY", "SAMPLER1DARRAYSHADOW",
+  "SAMPLER2DARRAYSHADOW", "ISAMPLER1D", "ISAMPLER2D", "ISAMPLER3D",
+  "ISAMPLERCUBE", "ISAMPLER1DARRAY", "ISAMPLER2DARRAY", "USAMPLER1D",
+  "USAMPLER2D", "USAMPLER3D", "USAMPLERCUBE", "USAMPLER1DARRAY",
+  "USAMPLER2DARRAY", "STRUCT", "VOID_TOK", "WHILE", "IDENTIFIER",
+  "FLOATCONSTANT", "INTCONSTANT", "UINTCONSTANT", "BOOLCONSTANT",
+  "FIELD_SELECTION", "LEFT_OP", "RIGHT_OP", "INC_OP", "DEC_OP", "LE_OP",
+  "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP", "XOR_OP", "MUL_ASSIGN",
+  "DIV_ASSIGN", "ADD_ASSIGN", "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN",
+  "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN", "SUB_ASSIGN", "INVARIANT",
+  "LOWP", "MEDIUMP", "HIGHP", "SUPERP", "PRECISION", "VERSION",
+  "EXTENSION", "LINE", "COLON", "EOL", "INTERFACE", "OUTPUT",
+  "PRAGMA_DEBUG_ON", "PRAGMA_DEBUG_OFF", "PRAGMA_OPTIMIZE_ON",
+  "PRAGMA_OPTIMIZE_OFF", "LAYOUT_TOK", "ASM", "CLASS", "UNION", "ENUM",
+  "TYPEDEF", "TEMPLATE", "THIS", "PACKED_TOK", "GOTO", "INLINE_TOK",
+  "NOINLINE", "VOLATILE", "PUBLIC_TOK", "STATIC", "EXTERN", "EXTERNAL",
+  "LONG_TOK", "SHORT_TOK", "DOUBLE_TOK", "HALF", "FIXED_TOK", "UNSIGNED",
+  "INPUT_TOK", "OUPTUT", "HVEC2", "HVEC3", "HVEC4", "DVEC2", "DVEC3",
+  "DVEC4", "FVEC2", "FVEC3", "FVEC4", "SAMPLER2DRECT", "SAMPLER3DRECT",
+  "SAMPLER2DRECTSHADOW", "SIZEOF", "CAST", "NAMESPACE", "USING",
+  "ERROR_TOK", "COMMON", "PARTITION", "ACTIVE", "SAMPLERBUFFER", "FILTER",
+  "IMAGE1D", "IMAGE2D", "IMAGE3D", "IMAGECUBE", "IMAGE1DARRAY",
+  "IMAGE2DARRAY", "IIMAGE1D", "IIMAGE2D", "IIMAGE3D", "IIMAGECUBE",
+  "IIMAGE1DARRAY", "IIMAGE2DARRAY", "UIMAGE1D", "UIMAGE2D", "UIMAGE3D",
+  "UIMAGECUBE", "UIMAGE1DARRAY", "UIMAGE2DARRAY", "IMAGE1DSHADOW",
+  "IMAGE2DSHADOW", "IMAGEBUFFER", "IIMAGEBUFFER", "UIMAGEBUFFER",
+  "ROW_MAJOR", "'('", "')'", "'['", "']'", "'.'", "','", "'+'", "'-'",
+  "'!'", "'~'", "'*'", "'/'", "'%'", "'<'", "'>'", "'&'", "'^'", "'|'",
+  "'?'", "':'", "'='", "';'", "'{'", "'}'", "$accept", "translation_unit",
+  "$@1", "version_statement", "pragma_statement",
+  "extension_statement_list", "extension_statement",
+  "external_declaration_list", "variable_identifier", "primary_expression",
+  "postfix_expression", "integer_expression", "function_call",
+  "function_call_or_method", "function_call_generic",
+  "function_call_header_no_parameters",
+  "function_call_header_with_parameters", "function_call_header",
+  "function_identifier", "unary_expression", "unary_operator",
+  "multiplicative_expression", "additive_expression", "shift_expression",
+  "relational_expression", "equality_expression", "and_expression",
+  "exclusive_or_expression", "inclusive_or_expression",
+  "logical_and_expression", "logical_xor_expression",
+  "logical_or_expression", "conditional_expression",
+  "assignment_expression", "assignment_operator", "expression",
+  "constant_expression", "declaration", "function_prototype",
+  "function_declarator", "function_header_with_parameters",
+  "function_header", "parameter_declarator", "parameter_declaration",
+  "parameter_qualifier", "parameter_type_specifier",
+  "init_declarator_list", "single_declaration", "fully_specified_type",
+  "opt_layout_qualifier", "layout_qualifier", "layout_qualifier_id_list",
+  "layout_qualifier_id", "interpolation_qualifier",
+  "parameter_type_qualifier", "type_qualifier", "storage_qualifier",
+  "type_specifier", "type_specifier_no_prec", "type_specifier_nonarray",
+  "basic_type_specifier_nonarray", "precision_qualifier",
+  "struct_specifier", "struct_declaration_list", "struct_declaration",
+  "struct_declarator_list", "struct_declarator", "initializer",
+  "declaration_statement", "statement", "statement_matched",
+  "statement_unmatched", "simple_statement", "compound_statement",
+  "statement_no_new_scope", "compound_statement_no_new_scope",
+  "statement_list", "expression_statement", "selection_statement_matched",
+  "selection_statement_unmatched", "condition", "switch_statement",
+  "case_label", "iteration_statement", "for_init_statement",
+  "conditionopt", "for_rest_statement", "jump_statement",
+  "external_declaration", "function_definition", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
+     305,   306,   307,   308,   309,   310,   311,   312,   313,   314,
+     315,   316,   317,   318,   319,   320,   321,   322,   323,   324,
+     325,   326,   327,   328,   329,   330,   331,   332,   333,   334,
+     335,   336,   337,   338,   339,   340,   341,   342,   343,   344,
+     345,   346,   347,   348,   349,   350,   351,   352,   353,   354,
+     355,   356,   357,   358,   359,   360,   361,   362,   363,   364,
+     365,   366,   367,   368,   369,   370,   371,   372,   373,   374,
+     375,   376,   377,   378,   379,   380,   381,   382,   383,   384,
+     385,   386,   387,   388,   389,   390,   391,   392,   393,   394,
+     395,   396,   397,   398,   399,   400,   401,   402,   403,   404,
+     405,   406,   407,   408,   409,   410,   411,   412,   413,   414,
+     415,   416,   417,   418,   419,   420,   421,   422,   423,   424,
+     425,   426,   427,   428,   429,   430,   431,   432,   433,   434,
+     435,   436,   437,   438,   439,   440,   441,   442,   443,   444,
+     445,    40,    41,    91,    93,    46,    44,    43,    45,    33,
+     126,    42,    47,    37,    60,    62,    38,    94,   124,    63,
+      58,    61,    59,   123,   125
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint16 yyr1[] =
+{
+       0,   215,   217,   216,   218,   218,   219,   219,   219,   219,
+     220,   220,   221,   222,   222,   223,   224,   224,   224,   224,
+     224,   224,   225,   225,   225,   225,   225,   225,   226,   227,
+     228,   228,   229,   229,   230,   230,   231,   231,   232,   233,
+     233,   233,   234,   234,   234,   234,   235,   235,   235,   235,
+     236,   236,   236,   236,   237,   237,   237,   238,   238,   238,
+     239,   239,   239,   239,   239,   240,   240,   240,   241,   241,
+     242,   242,   243,   243,   244,   244,   245,   245,   246,   246,
+     247,   247,   248,   248,   249,   249,   249,   249,   249,   249,
+     249,   249,   249,   249,   249,   250,   250,   251,   252,   252,
+     252,   253,   254,   254,   255,   255,   256,   257,   257,   258,
+     258,   258,   258,   259,   259,   259,   259,   260,   261,   261,
+     261,   261,   261,   261,   261,   262,   262,   262,   262,   262,
+     262,   262,   262,   263,   263,   264,   264,   265,   266,   266,
+     267,   268,   268,   268,   269,   270,   270,   270,   271,   271,
+     271,   271,   271,   271,   271,   271,   271,   272,   272,   273,
+     273,   273,   274,   274,   274,   275,   275,   275,   275,   275,
+     275,   275,   275,   275,   275,   275,   275,   275,   275,   275,
+     275,   275,   275,   275,   275,   275,   275,   275,   275,   275,
+     275,   275,   275,   275,   275,   275,   275,   275,   275,   275,
+     275,   275,   275,   275,   275,   275,   275,   275,   275,   275,
+     275,   275,   275,   275,   275,   275,   276,   276,   276,   277,
+     277,   278,   278,   279,   280,   280,   281,   281,   282,   283,
+     284,   284,   285,   285,   286,   287,   287,   287,   287,   287,
+     287,   287,   288,   288,   289,   289,   290,   290,   291,   291,
+     292,   292,   293,   294,   294,   294,   295,   295,   296,   297,
+     297,   298,   298,   298,   299,   299,   300,   300,   301,   301,
+     302,   302,   302,   302,   302,   303,   303,   303,   304
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     0,     4,     0,     3,     2,     2,     2,     2,
+       0,     2,     5,     1,     2,     1,     1,     1,     1,     1,
+       1,     3,     1,     4,     1,     3,     2,     2,     1,     1,
+       1,     3,     2,     2,     2,     1,     2,     3,     2,     1,
+       1,     1,     1,     2,     2,     2,     1,     1,     1,     1,
+       1,     3,     3,     3,     1,     3,     3,     1,     3,     3,
+       1,     3,     3,     3,     3,     1,     3,     3,     1,     3,
+       1,     3,     1,     3,     1,     3,     1,     3,     1,     3,
+       1,     5,     1,     3,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     3,     1,     2,     2,
+       4,     2,     1,     1,     2,     3,     3,     2,     5,     3,
+       2,     3,     2,     0,     1,     1,     1,     1,     1,     3,
+       5,     6,     7,     8,     5,     1,     2,     4,     5,     6,
+       7,     4,     2,     1,     2,     0,     1,     4,     1,     3,
+       1,     1,     1,     1,     1,     1,     2,     2,     1,     1,
+       2,     2,     2,     1,     2,     2,     1,     1,     2,     1,
+       3,     4,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     5,
+       4,     1,     2,     3,     1,     3,     1,     4,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     2,     3,     1,     1,     2,     3,     1,     2,
+       1,     2,     7,     5,     5,     7,     1,     4,     5,     3,
+       2,     5,     7,     6,     1,     1,     1,     0,     2,     3,
+       2,     2,     2,     3,     2,     1,     1,     1,     2
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const yytype_uint16 yydefact[] =
+{
+       4,     0,     0,    10,     0,     1,     2,     5,     0,   135,
+      11,     0,   149,   148,   169,   166,   167,   168,   173,   174,
+     175,   176,   177,   178,   179,   180,   181,   170,   171,   172,
+       0,   153,   156,   143,   142,   141,   182,   183,   184,   185,
+     186,   187,   188,   189,   190,   191,   192,   194,   195,   196,
+     197,   199,   200,   201,   202,   203,   204,   205,   206,   207,
+     208,   209,   210,   211,   212,   213,   214,   215,     0,   165,
+     164,   135,   218,   217,   216,     0,     0,     0,     0,     0,
+       0,   193,   198,   277,   135,   276,     0,     0,   103,   113,
+       0,   118,   125,     0,   136,   135,     0,   145,   133,   157,
+     159,   162,     0,   163,    13,   275,     0,   154,   155,   151,
+       0,     0,   132,   135,   147,     0,     6,     7,     8,     9,
+       0,    14,    98,   135,   278,   101,   113,   144,   114,   115,
+     116,   104,     0,   113,     0,    99,   126,   152,   150,   146,
+     134,     0,   158,     0,     0,     0,     0,   221,     0,   140,
+       0,   138,     0,     0,   135,     0,     0,     0,     0,     0,
+       0,     0,     0,    15,    19,    17,    18,    20,    41,     0,
+       0,     0,    46,    47,    48,    49,   250,   135,   246,    16,
+      22,    42,    24,    29,    30,     0,     0,    35,     0,    50,
+       0,    54,    57,    60,    65,    68,    70,    72,    74,    76,
+      78,    80,    82,    95,     0,   229,     0,   133,   235,   248,
+     230,   231,   233,   232,   135,   236,   237,   234,   238,   239,
+     240,   241,   105,   110,   112,   117,     0,   119,   106,     0,
+       0,   160,    50,    97,     0,    39,    12,     0,   226,     0,
+     224,   220,   222,   100,   137,     0,   271,   270,     0,   135,
+       0,   274,   272,     0,     0,     0,   260,   135,    43,    44,
+       0,   242,   135,    26,    27,     0,     0,    33,    32,     0,
+     165,    36,    38,    85,    86,    88,    87,    90,    91,    92,
+      93,    94,    89,    84,     0,    45,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   251,   247,   249,
+     107,   109,   111,     0,     0,   127,     0,   228,   131,   161,
+     219,     0,     0,   223,   139,     0,   265,   264,   135,     0,
+     273,     0,   259,   256,     0,     0,    21,   243,     0,    28,
+      25,    31,    37,    83,    51,    52,    53,    55,    56,    58,
+      59,    63,    64,    61,    62,    66,    67,    69,    71,    73,
+      75,    77,    79,     0,    96,     0,   120,     0,   124,     0,
+     128,     0,   225,     0,   266,     0,     0,   135,     0,     0,
+     135,    23,     0,     0,     0,   121,   129,     0,   227,     0,
+     268,   135,   253,   254,   258,     0,     0,   245,   261,   244,
+      81,   108,   122,     0,   130,     0,   269,   263,   135,   257,
+       0,   123,   262,   252,   255,     0,   135,     0,   135
+};
+
+/* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int16 yydefgoto[] =
+{
+      -1,     2,     9,     3,    83,     6,    10,    84,   179,   180,
+     181,   338,   182,   183,   184,   185,   186,   187,   188,   189,
+     190,   191,   192,   193,   194,   195,   196,   197,   198,   199,
+     200,   201,   202,   203,   284,   204,   234,   205,   206,    87,
+      88,    89,   223,   131,   132,   224,    90,    91,    92,    93,
+      94,   150,   151,    95,   133,    96,    97,   235,    99,   100,
+     101,   102,   103,   146,   147,   239,   240,   318,   208,   209,
+     210,   211,   212,   213,   398,   399,   214,   215,   216,   217,
+     335,   218,   219,   220,   328,   375,   376,   221,   104,   105
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -367
+static const yytype_int16 yypact[] =
+{
+     -88,   -21,    24,  -367,   -53,  -367,    -3,  -367,     9,  3699,
+    -367,     0,  -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,
+    -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,
+     126,  -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,
+    -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,
+    -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,
+    -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,   -75,  -367,
+    -367,    29,  -367,  -367,  -367,    92,     4,    12,    20,    26,
+     -49,  -367,  -367,  -367,  3580,  -367,  -197,   -45,   -46,     3,
+    -134,  -367,    82,    71,  -367,    52,  3887,  -367,  -367,  -367,
+     -29,  -367,  3959,  -367,  -367,  -367,    97,  -367,  -367,  -367,
+     -19,  3887,  -367,    52,  -367,  3959,  -367,  -367,  -367,  -367,
+     130,  -367,  -367,   282,  -367,  -367,    47,  -367,  -367,  -367,
+    -367,  -367,  3887,   187,   139,  -367,  -162,  -367,  -367,  -367,
+    -367,  2675,  -367,   105,  3887,   154,  2064,  -367,    23,  -367,
+     -62,  -367,    27,    31,  1130,    50,    53,    33,  2296,    55,
+    3218,    37,    58,   -67,  -367,  -367,  -367,  -367,  -367,  3218,
+    3218,  3218,  -367,  -367,  -367,  -367,  -367,   494,  -367,  -367,
+    -367,   -66,  -367,  -367,  -367,    60,   -56,  3399,    64,   -54,
+    3218,    22,     6,   118,   -84,   120,    51,    54,    56,   168,
+     167,   -83,  -367,  -367,  -103,  -367,    48,    72,  -367,  -367,
+    -367,  -367,  -367,  -367,   706,  -367,  -367,  -367,  -367,  -367,
+    -367,  -367,  -367,  -367,  -367,   186,  3887,  -139,  -367,  2856,
+    3218,  -367,  -367,  -367,    73,  -367,  -367,  2180,    75,  -102,
+    -367,  -367,  -367,  -367,  -367,   130,  -367,  -367,   190,  1750,
+    3218,  -367,  -367,   -90,  3218,  -146,  -367,  2494,  -367,  -367,
+     -48,  -367,   918,  -367,  -367,  3218,  3815,  -367,  -367,  3218,
+      74,  -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,
+    -367,  -367,  -367,  -367,  3218,  -367,  3218,  3218,  3218,  3218,
+    3218,  3218,  3218,  3218,  3218,  3218,  3218,  3218,  3218,  3218,
+    3218,  3218,  3218,  3218,  3218,  3218,  3218,  -367,  -367,  -367,
+      76,  -367,  -367,  3037,  3218,    59,    77,  -367,  -367,  -367,
+    -367,  3218,   154,  -367,  -367,    81,  -367,  -367,  1948,   -40,
+    -367,   -27,  -367,    78,   197,    83,  -367,  -367,    84,    78,
+      85,  -367,  -367,  -367,  -367,  -367,  -367,    22,    22,     6,
+       6,   118,   118,   118,   118,   -84,   -84,   120,    51,    54,
+      56,   168,   167,   -97,  -367,  3218,    66,    86,  -367,  3218,
+      68,    87,  -367,  3218,  -367,    70,    91,  1130,   102,   106,
+    1341,  -367,  3218,    90,  3218,   153,  -367,  3218,  -367,   -26,
+    3218,  1341,   353,  -367,  -367,  3218,   103,  -367,  -367,  -367,
+    -367,  -367,  -367,  3218,  -367,   157,    78,  -367,  1130,  -367,
+    3218,  -367,  -367,  -367,  -367,   -25,  1552,   358,  1552
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yytype_int16 yypgoto[] =
+{
+    -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,  -367,
+    -367,  -367,  -367,  -367,   107,  -367,  -367,  -367,  -367,  -111,
+    -367,   -63,   -59,   -82,   -60,    79,    80,    88,    89,    69,
+      93,  -367,  -114,  -153,  -367,  -154,  -224,    11,    14,  -367,
+    -367,  -367,   148,   249,   243,   151,  -367,  -367,  -245,  -367,
+    -367,  -367,   134,  -367,  -367,   -43,  -367,    -9,   -89,  -367,
+    -367,   306,  -367,   239,  -136,  -367,    62,  -241,   143,  -143,
+    -342,  -355,  -366,    15,     5,   308,   218,   149,  -367,  -367,
+      94,  -367,  -367,  -367,  -367,  -367,  -367,  -367,   316,  -367
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -268
+static const yytype_int16 yytable[] =
+{
+      98,   110,   293,   294,   253,   316,   255,   127,   304,  -164,
+     242,   248,   334,   142,   397,   122,   123,   260,   263,   264,
+      85,     1,   393,    86,     5,   397,   148,   233,   114,   228,
+     232,   229,    12,    13,   271,   392,   128,   129,   130,   273,
+     274,   275,   276,   277,   278,   279,   280,   281,   282,   230,
+     306,   127,   139,   414,   313,    12,    13,     4,   258,   259,
+       7,    30,   134,    31,   332,    32,   413,    33,    34,    35,
+     114,   309,   314,   368,   417,    98,   413,   317,   135,   285,
+     128,   129,   130,   334,    30,    11,    31,   140,    32,   367,
+      33,    34,    35,   306,   322,    85,   329,   371,    86,   306,
+     331,   242,   145,   333,   137,   112,   306,     8,   138,   307,
+     323,   339,   106,   382,   207,   233,   342,   116,   232,   309,
+     295,   296,   330,   225,   -40,   117,   305,   265,   386,   266,
+     244,   343,   113,   118,   245,   145,   268,   145,   111,   119,
+     269,   383,   120,   402,   336,   207,   404,   125,   306,    80,
+     126,   363,   377,   364,   409,   113,   306,   283,   136,   107,
+     108,   317,   411,   109,   141,   378,   405,   416,   207,   306,
+     306,   306,    80,   143,   333,   344,   345,   346,   232,   232,
+     232,   232,   232,   232,   232,   232,   232,   232,   232,   232,
+     232,   232,   232,   232,   144,  -102,    72,    73,    74,   233,
+     291,   292,   232,   289,   290,   207,   149,   233,   297,   298,
+     232,   351,   352,   353,   354,   227,   317,   225,   236,   389,
+     128,   129,   130,   286,   287,   288,   347,   348,   145,   400,
+     238,   317,   349,   350,   317,   243,   406,   355,   356,   246,
+     207,   249,   317,   247,   250,   251,   254,   256,   207,   257,
+     317,   233,   267,   207,   232,   272,   415,   299,   302,   303,
+     122,   300,   310,   -39,   301,   325,   -34,   319,   321,   365,
+     369,   370,   373,   379,   306,   380,   -40,   384,   381,   387,
+     385,   388,   390,   391,   401,    12,    13,    14,    15,    16,
+      17,   152,   153,   154,   410,   155,   156,   157,   158,   159,
+     160,   161,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,   177,    31,   395,    32,   207,
+      33,    34,    35,    36,    37,    38,    39,    40,    41,    42,
+      43,    44,    45,    46,    47,    48,    49,    50,    51,    52,
+      53,    54,    55,    56,    57,    58,    59,    60,    61,    62,
+      63,    64,    65,    66,    67,    68,    69,   162,   163,   164,
+     165,   166,   167,   168,   403,   408,   169,   170,   207,   412,
+     418,   207,   361,   341,   311,   222,   226,   312,   357,   324,
+     358,   115,   207,   237,   372,    71,    72,    73,    74,   359,
+      75,   360,   326,   394,   124,   262,   407,   362,   327,   207,
+     121,     0,    80,     0,     0,     0,     0,   207,     0,   207,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   374,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    81,     0,    82,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   171,     0,     0,     0,     0,     0,   172,
+     173,   174,   175,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   176,   177,   178,    12,    13,    14,
+      15,    16,    17,   152,   153,   154,     0,   155,   156,   157,
+     158,   159,   160,   161,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,     0,    31,     0,
+      32,     0,    33,    34,    35,    36,    37,    38,    39,    40,
+      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
+      51,    52,    53,    54,    55,    56,    57,    58,    59,    60,
+      61,    62,    63,    64,    65,    66,    67,    68,    69,   162,
+     163,   164,   165,   166,   167,   168,     0,     0,   169,   170,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    71,    72,    73,
+      74,     0,    75,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    80,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    81,     0,
+      82,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   171,     0,     0,     0,     0,
+       0,   172,   173,   174,   175,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   176,   177,   261,    12,
+      13,    14,    15,    16,    17,   152,   153,   154,     0,   155,
+     156,   157,   158,   159,   160,   161,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,     0,
+      31,     0,    32,     0,    33,    34,    35,    36,    37,    38,
+      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
+      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
+      59,    60,    61,    62,    63,    64,    65,    66,    67,    68,
+      69,   162,   163,   164,   165,   166,   167,   168,     0,     0,
+     169,   170,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    71,
+      72,    73,    74,     0,    75,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    80,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      81,     0,    82,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   171,     0,     0,
+       0,     0,     0,   172,   173,   174,   175,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   176,   177,
+     308,    12,    13,    14,    15,    16,    17,   152,   153,   154,
+       0,   155,   156,   157,   158,   159,   160,   161,    18,    19,
+      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,     0,    31,     0,    32,     0,    33,    34,    35,    36,
+      37,    38,    39,    40,    41,    42,    43,    44,    45,    46,
+      47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
+      57,    58,    59,    60,    61,    62,    63,    64,    65,    66,
+      67,    68,    69,   162,   163,   164,   165,   166,   167,   168,
+       0,     0,   169,   170,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,    71,    72,    73,    74,     0,    75,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    80,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    81,     0,    82,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   171,
+       0,     0,     0,     0,     0,   172,   173,   174,   175,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     176,   177,   337,    12,    13,    14,    15,    16,    17,   152,
+     153,   154,     0,   155,   156,   157,   158,   159,   160,   161,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,     0,    31,     0,    32,     0,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,   162,   163,   164,   165,   166,
+     167,   168,     0,     0,   169,   170,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    71,    72,    73,    74,     0,    75,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      80,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    81,     0,    82,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   171,     0,     0,     0,     0,     0,   172,   173,   174,
+     175,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   176,   177,    12,    13,    14,    15,    16,    17,
+     152,   153,   154,     0,   155,   396,   157,   158,   159,   160,
+     161,    18,    19,    20,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,     0,    31,     0,    32,     0,    33,
+      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
+      44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,    66,    67,    68,    69,   162,   163,   164,   165,
+     166,   167,   168,     0,     0,   169,   170,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    71,    72,    73,    74,     0,    75,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,    80,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    81,     0,    82,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   171,     0,     0,     0,     0,     0,   172,   173,
+     174,   175,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   176,   123,    12,    13,    14,    15,    16,
+      17,   152,   153,   154,     0,   155,   396,   157,   158,   159,
+     160,   161,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,     0,    31,     0,    32,     0,
+      33,    34,    35,    36,    37,    38,    39,    40,    41,    42,
+      43,    44,    45,    46,    47,    48,    49,    50,    51,    52,
+      53,    54,    55,    56,    57,    58,    59,    60,    61,    62,
+      63,    64,    65,    66,    67,    68,    69,   162,   163,   164,
+     165,   166,   167,   168,     0,     0,   169,   170,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    71,    72,    73,    74,     0,
+      75,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    80,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    81,     0,    82,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   171,     0,     0,     0,     0,     0,   172,
+     173,   174,   175,    12,    13,    14,    15,    16,    17,     0,
+       0,     0,     0,     0,   176,   177,     0,     0,     0,     0,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,     0,    31,     0,    32,     0,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,     0,   163,   164,   165,   166,
+     167,   168,     0,     0,   169,   170,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    71,    72,    73,    74,     0,    75,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      80,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    81,     0,    82,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   171,     0,     0,     0,     0,     0,   172,   173,   174,
+     175,    12,    13,    14,    15,    16,    17,     0,     0,     0,
+       0,     0,   176,     0,     0,     0,     0,     0,    18,    19,
+      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,     0,    31,     0,    32,     0,    33,    34,    35,    36,
+      37,    38,    39,    40,    41,    42,    43,    44,    45,    46,
+      47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
+      57,    58,    59,    60,    61,    62,    63,    64,    65,    66,
+      67,    68,    69,     0,   163,   164,   165,   166,   167,   168,
+       0,     0,   169,   170,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   113,    72,    73,    74,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    80,    14,
+      15,    16,    17,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,     0,     0,     0,     0,
+       0,     0,    81,     0,    82,    36,    37,    38,    39,    40,
+      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
+      51,    52,    53,    54,    55,    56,    57,    58,    59,    60,
+      61,    62,    63,    64,    65,    66,    67,    68,    69,   171,
+      70,     0,     0,     0,     0,   172,   173,   174,   175,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+    -267,     0,     0,     0,     0,     0,     0,     0,    72,    73,
+      74,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    14,    15,    16,    17,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,     0,     0,     0,     0,     0,     0,    81,     0,
+      82,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,     0,    70,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   241,     0,
+       0,     0,     0,     0,    72,    73,    74,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,    14,    15,    16,    17,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,     0,     0,
+       0,     0,     0,     0,    81,     0,    82,    36,    37,    38,
+      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
+      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
+      59,    60,    61,    62,    63,    64,    65,    66,    67,    68,
+      69,     0,   163,   164,   165,   166,   167,   168,     0,     0,
+     169,   170,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   320,     0,     0,     0,     0,     0,
+      72,    73,    74,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      81,     0,    82,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   171,     0,     0,
+       0,     0,     0,   172,   173,   174,   175,    12,    13,    14,
+      15,    16,    17,     0,     0,     0,     0,     0,   252,     0,
+       0,     0,     0,     0,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,     0,    31,     0,
+      32,     0,    33,    34,    35,    36,    37,    38,    39,    40,
+      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
+      51,    52,    53,    54,    55,    56,    57,    58,    59,    60,
+      61,    62,    63,    64,    65,    66,    67,    68,    69,     0,
+     163,   164,   165,   166,   167,   168,     0,     0,   169,   170,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   113,    72,    73,
+      74,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    80,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    81,     0,
+      82,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      14,    15,    16,    17,     0,   171,     0,     0,     0,     0,
+       0,   172,   173,   174,   175,    18,    19,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    36,    37,    38,    39,
+      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
+      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
+      60,    61,    62,    63,    64,    65,    66,    67,    68,    69,
+       0,   163,   164,   165,   166,   167,   168,     0,     0,   169,
+     170,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    72,
+      73,    74,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    81,
+       0,    82,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,    14,    15,    16,    17,     0,   171,     0,     0,   231,
+       0,     0,   172,   173,   174,   175,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    36,    37,    38,
+      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
+      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
+      59,    60,    61,    62,    63,    64,    65,    66,    67,    68,
+      69,     0,   163,   164,   165,   166,   167,   168,     0,     0,
+     169,   170,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      72,    73,    74,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      81,     0,    82,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    14,    15,    16,    17,     0,   171,     0,     0,
+     315,     0,     0,   172,   173,   174,   175,    18,    19,    20,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    36,    37,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,     0,   163,   164,   165,   166,   167,   168,     0,
+       0,   169,   170,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,    72,    73,    74,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,    81,     0,    82,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    14,    15,    16,    17,     0,   171,     0,
+       0,   366,     0,     0,   172,   173,   174,   175,    18,    19,
+      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    36,
+      37,    38,    39,    40,    41,    42,    43,    44,    45,    46,
+      47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
+      57,    58,    59,    60,    61,    62,    63,    64,    65,    66,
+      67,    68,    69,     0,   163,   164,   165,   166,   167,   168,
+       0,     0,   169,   170,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    72,    73,    74,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    81,     0,    82,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    14,    15,    16,    17,     0,   171,
+       0,     0,     0,     0,     0,   172,   173,   174,   175,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
+      46,    47,    48,    49,    50,    51,    52,    53,    54,    55,
+      56,    57,    58,    59,    60,    61,    62,    63,    64,    65,
+      66,    67,    68,   270,     0,   163,   164,   165,   166,   167,
+     168,     0,     0,   169,   170,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    72,    73,    74,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    81,     0,    82,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      -3,     0,     0,    12,    13,    14,    15,    16,    17,     0,
+     171,     0,     0,     0,     0,     0,   172,   173,   174,   175,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,     0,    31,     0,    32,     0,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,     0,    70,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    71,    72,    73,    74,     0,    75,     0,
+       0,     0,     0,     0,     0,     0,    76,    77,    78,    79,
+      80,     0,    12,    13,    14,    15,    16,    17,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,     0,    31,    81,    32,    82,    33,    34,    35,
+      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
+      46,    47,    48,    49,    50,    51,    52,    53,    54,    55,
+      56,    57,    58,    59,    60,    61,    62,    63,    64,    65,
+      66,    67,    68,    69,     0,    70,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    71,    72,    73,    74,     0,    75,     0,     0,
+       0,     0,     0,     0,     0,    76,    77,    78,    79,    80,
+      14,    15,    16,    17,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    18,    19,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,     0,     0,     0,
+       0,     0,     0,    81,     0,    82,    36,    37,    38,    39,
+      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
+      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
+      60,    61,    62,    63,    64,    65,    66,    67,    68,    69,
+       0,   340,    14,    15,    16,    17,   168,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    18,    19,    20,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    72,
+      73,    74,     0,     0,     0,     0,     0,     0,    36,    37,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,     0,    70,    14,    15,    16,    17,     0,    81,
+       0,    82,     0,     0,     0,     0,     0,     0,     0,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    72,    73,    74,     0,     0,     0,     0,     0,     0,
+      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
+      46,    47,    48,    49,    50,    51,    52,    53,    54,    55,
+      56,    57,    58,    59,    60,    61,    62,    63,    64,    65,
+      66,    67,    68,    69,     0,    70,     0,     0,     0,     0,
+       0,    81,     0,    82,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    81,     0,    82
+};
+
+static const yytype_int16 yycheck[] =
+{
+       9,    76,    86,    87,   158,   229,   160,     4,    91,    76,
+     146,   154,   257,   102,   380,   212,   213,   171,    84,    85,
+       9,   109,   377,     9,     0,   391,   115,   141,    71,   191,
+     141,   193,     3,     4,   187,   377,    33,    34,    35,    93,
+      94,    95,    96,    97,    98,    99,   100,   101,   102,   211,
+     196,     4,    95,   408,   193,     3,     4,    78,   169,   170,
+     113,    32,   196,    34,   210,    36,   408,    38,    39,    40,
+     113,   214,   211,   314,   416,    84,   418,   230,   212,   190,
+      33,    34,    35,   328,    32,    76,    34,    96,    36,   313,
+      38,    39,    40,   196,   196,    84,   250,   321,    84,   196,
+     254,   237,   111,   257,    33,    76,   196,   110,    37,   212,
+     212,   265,   112,   210,   123,   229,   269,   113,   229,   262,
+     204,   205,   212,   132,   191,   113,   209,   193,   369,   195,
+     192,   284,   103,   113,   196,   144,   192,   146,   213,   113,
+     196,   365,   191,   384,   192,   154,   387,   192,   196,   120,
+     196,   305,   192,   306,   395,   103,   196,   211,    76,    33,
+      34,   314,   403,    37,   193,   192,   192,   192,   177,   196,
+     196,   196,   120,    76,   328,   286,   287,   288,   289,   290,
+     291,   292,   293,   294,   295,   296,   297,   298,   299,   300,
+     301,   302,   303,   304,   213,   192,   104,   105,   106,   313,
+      82,    83,   313,   197,   198,   214,    76,   321,    88,    89,
+     321,   293,   294,   295,   296,    76,   369,   226,   113,   373,
+      33,    34,    35,   201,   202,   203,   289,   290,   237,   382,
+      76,   384,   291,   292,   387,   212,   390,   297,   298,   212,
+     249,   191,   395,   212,   191,   212,   191,   210,   257,   191,
+     403,   365,   192,   262,   365,   191,   410,   206,    90,    92,
+     212,   207,    76,   191,   208,    75,   192,   194,   193,   193,
+     211,   194,   191,    76,   196,   192,   191,   211,   194,   211,
+     194,   194,   212,   192,   194,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,   191,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,   213,    34,   211,    36,   328,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    80,    81,   211,    12,    84,    85,   377,   212,
+      12,   380,   303,   266,   226,   126,   133,   226,   299,   245,
+     300,    75,   391,   144,   322,   103,   104,   105,   106,   301,
+     108,   302,   249,   378,    86,   177,   391,   304,   249,   408,
+      84,    -1,   120,    -1,    -1,    -1,    -1,   416,    -1,   418,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   328,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   154,    -1,   156,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   191,    -1,    -1,    -1,    -1,    -1,   197,
+     198,   199,   200,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   212,   213,   214,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,    -1,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    -1,    34,    -1,
+      36,    -1,    38,    39,    40,    41,    42,    43,    44,    45,
+      46,    47,    48,    49,    50,    51,    52,    53,    54,    55,
+      56,    57,    58,    59,    60,    61,    62,    63,    64,    65,
+      66,    67,    68,    69,    70,    71,    72,    73,    74,    75,
+      76,    77,    78,    79,    80,    81,    -1,    -1,    84,    85,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   103,   104,   105,
+     106,    -1,   108,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   120,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   154,    -1,
+     156,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   191,    -1,    -1,    -1,    -1,
+      -1,   197,   198,   199,   200,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   212,   213,   214,     3,
+       4,     5,     6,     7,     8,     9,    10,    11,    -1,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    -1,
+      34,    -1,    36,    -1,    38,    39,    40,    41,    42,    43,
+      44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,    66,    67,    68,    69,    70,    71,    72,    73,
+      74,    75,    76,    77,    78,    79,    80,    81,    -1,    -1,
+      84,    85,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   103,
+     104,   105,   106,    -1,   108,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   120,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     154,    -1,   156,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   191,    -1,    -1,
+      -1,    -1,    -1,   197,   198,   199,   200,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   212,   213,
+     214,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+      -1,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    -1,    34,    -1,    36,    -1,    38,    39,    40,    41,
+      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
+      52,    53,    54,    55,    56,    57,    58,    59,    60,    61,
+      62,    63,    64,    65,    66,    67,    68,    69,    70,    71,
+      72,    73,    74,    75,    76,    77,    78,    79,    80,    81,
+      -1,    -1,    84,    85,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   103,   104,   105,   106,    -1,   108,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   120,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   154,    -1,   156,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   191,
+      -1,    -1,    -1,    -1,    -1,   197,   198,   199,   200,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     212,   213,   214,     3,     4,     5,     6,     7,     8,     9,
+      10,    11,    -1,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    -1,    34,    -1,    36,    -1,    38,    39,
+      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
+      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
+      60,    61,    62,    63,    64,    65,    66,    67,    68,    69,
+      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
+      80,    81,    -1,    -1,    84,    85,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   103,   104,   105,   106,    -1,   108,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     120,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   154,    -1,   156,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   191,    -1,    -1,    -1,    -1,    -1,   197,   198,   199,
+     200,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   212,   213,     3,     4,     5,     6,     7,     8,
+       9,    10,    11,    -1,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    32,    -1,    34,    -1,    36,    -1,    38,
+      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
+      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
+      59,    60,    61,    62,    63,    64,    65,    66,    67,    68,
+      69,    70,    71,    72,    73,    74,    75,    76,    77,    78,
+      79,    80,    81,    -1,    -1,    84,    85,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   103,   104,   105,   106,    -1,   108,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   120,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   154,    -1,   156,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   191,    -1,    -1,    -1,    -1,    -1,   197,   198,
+     199,   200,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   212,   213,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    -1,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    -1,    34,    -1,    36,    -1,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    80,    81,    -1,    -1,    84,    85,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   103,   104,   105,   106,    -1,
+     108,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   120,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   154,    -1,   156,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   191,    -1,    -1,    -1,    -1,    -1,   197,
+     198,   199,   200,     3,     4,     5,     6,     7,     8,    -1,
+      -1,    -1,    -1,    -1,   212,   213,    -1,    -1,    -1,    -1,
+      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    -1,    34,    -1,    36,    -1,    38,    39,
+      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
+      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
+      60,    61,    62,    63,    64,    65,    66,    67,    68,    69,
+      70,    71,    72,    73,    74,    -1,    76,    77,    78,    79,
+      80,    81,    -1,    -1,    84,    85,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   103,   104,   105,   106,    -1,   108,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     120,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   154,    -1,   156,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   191,    -1,    -1,    -1,    -1,    -1,   197,   198,   199,
+     200,     3,     4,     5,     6,     7,     8,    -1,    -1,    -1,
+      -1,    -1,   212,    -1,    -1,    -1,    -1,    -1,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    -1,    34,    -1,    36,    -1,    38,    39,    40,    41,
+      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
+      52,    53,    54,    55,    56,    57,    58,    59,    60,    61,
+      62,    63,    64,    65,    66,    67,    68,    69,    70,    71,
+      72,    73,    74,    -1,    76,    77,    78,    79,    80,    81,
+      -1,    -1,    84,    85,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   103,   104,   105,   106,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   120,     5,
+       6,     7,     8,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    -1,    -1,    -1,    -1,
+      -1,    -1,   154,    -1,   156,    41,    42,    43,    44,    45,
+      46,    47,    48,    49,    50,    51,    52,    53,    54,    55,
+      56,    57,    58,    59,    60,    61,    62,    63,    64,    65,
+      66,    67,    68,    69,    70,    71,    72,    73,    74,   191,
+      76,    -1,    -1,    -1,    -1,   197,   198,   199,   200,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     212,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   104,   105,
+     106,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,     5,     6,     7,     8,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    -1,    -1,    -1,    -1,    -1,    -1,   154,    -1,
+     156,    41,    42,    43,    44,    45,    46,    47,    48,    49,
+      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
+      60,    61,    62,    63,    64,    65,    66,    67,    68,    69,
+      70,    71,    72,    73,    74,    -1,    76,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   214,    -1,
+      -1,    -1,    -1,    -1,   104,   105,   106,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,     5,     6,     7,     8,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    -1,    -1,
+      -1,    -1,    -1,    -1,   154,    -1,   156,    41,    42,    43,
+      44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,    66,    67,    68,    69,    70,    71,    72,    73,
+      74,    -1,    76,    77,    78,    79,    80,    81,    -1,    -1,
+      84,    85,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   214,    -1,    -1,    -1,    -1,    -1,
+     104,   105,   106,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     154,    -1,   156,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   191,    -1,    -1,
+      -1,    -1,    -1,   197,   198,   199,   200,     3,     4,     5,
+       6,     7,     8,    -1,    -1,    -1,    -1,    -1,   212,    -1,
+      -1,    -1,    -1,    -1,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    -1,    34,    -1,
+      36,    -1,    38,    39,    40,    41,    42,    43,    44,    45,
+      46,    47,    48,    49,    50,    51,    52,    53,    54,    55,
+      56,    57,    58,    59,    60,    61,    62,    63,    64,    65,
+      66,    67,    68,    69,    70,    71,    72,    73,    74,    -1,
+      76,    77,    78,    79,    80,    81,    -1,    -1,    84,    85,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   103,   104,   105,
+     106,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   120,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   154,    -1,
+     156,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+       5,     6,     7,     8,    -1,   191,    -1,    -1,    -1,    -1,
+      -1,   197,   198,   199,   200,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      -1,    76,    77,    78,    79,    80,    81,    -1,    -1,    84,
+      85,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   104,
+     105,   106,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   154,
+      -1,   156,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,     5,     6,     7,     8,    -1,   191,    -1,    -1,   194,
+      -1,    -1,   197,   198,   199,   200,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    41,    42,    43,
+      44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,    66,    67,    68,    69,    70,    71,    72,    73,
+      74,    -1,    76,    77,    78,    79,    80,    81,    -1,    -1,
+      84,    85,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     104,   105,   106,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     154,    -1,   156,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,     5,     6,     7,     8,    -1,   191,    -1,    -1,
+     194,    -1,    -1,   197,   198,   199,   200,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    41,    42,
+      43,    44,    45,    46,    47,    48,    49,    50,    51,    52,
+      53,    54,    55,    56,    57,    58,    59,    60,    61,    62,
+      63,    64,    65,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,    -1,    76,    77,    78,    79,    80,    81,    -1,
+      -1,    84,    85,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   104,   105,   106,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   154,    -1,   156,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,     5,     6,     7,     8,    -1,   191,    -1,
+      -1,   194,    -1,    -1,   197,   198,   199,   200,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    41,
+      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
+      52,    53,    54,    55,    56,    57,    58,    59,    60,    61,
+      62,    63,    64,    65,    66,    67,    68,    69,    70,    71,
+      72,    73,    74,    -1,    76,    77,    78,    79,    80,    81,
+      -1,    -1,    84,    85,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   104,   105,   106,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   154,    -1,   156,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,     5,     6,     7,     8,    -1,   191,
+      -1,    -1,    -1,    -1,    -1,   197,   198,   199,   200,    20,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
+      51,    52,    53,    54,    55,    56,    57,    58,    59,    60,
+      61,    62,    63,    64,    65,    66,    67,    68,    69,    70,
+      71,    72,    73,    74,    -1,    76,    77,    78,    79,    80,
+      81,    -1,    -1,    84,    85,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   104,   105,   106,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   154,    -1,   156,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+       0,    -1,    -1,     3,     4,     5,     6,     7,     8,    -1,
+     191,    -1,    -1,    -1,    -1,    -1,   197,   198,   199,   200,
+      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    -1,    34,    -1,    36,    -1,    38,    39,
+      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
+      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
+      60,    61,    62,    63,    64,    65,    66,    67,    68,    69,
+      70,    71,    72,    73,    74,    -1,    76,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   103,   104,   105,   106,    -1,   108,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   116,   117,   118,   119,
+     120,    -1,     3,     4,     5,     6,     7,     8,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    20,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,    32,    -1,    34,   154,    36,   156,    38,    39,    40,
+      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
+      51,    52,    53,    54,    55,    56,    57,    58,    59,    60,
+      61,    62,    63,    64,    65,    66,    67,    68,    69,    70,
+      71,    72,    73,    74,    -1,    76,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   103,   104,   105,   106,    -1,   108,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   116,   117,   118,   119,   120,
+       5,     6,     7,     8,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    -1,    -1,    -1,
+      -1,    -1,    -1,   154,    -1,   156,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      -1,    76,     5,     6,     7,     8,    81,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,   104,
+     105,   106,    -1,    -1,    -1,    -1,    -1,    -1,    41,    42,
+      43,    44,    45,    46,    47,    48,    49,    50,    51,    52,
+      53,    54,    55,    56,    57,    58,    59,    60,    61,    62,
+      63,    64,    65,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,    -1,    76,     5,     6,     7,     8,    -1,   154,
+      -1,   156,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    20,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,   104,   105,   106,    -1,    -1,    -1,    -1,    -1,    -1,
+      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
+      51,    52,    53,    54,    55,    56,    57,    58,    59,    60,
+      61,    62,    63,    64,    65,    66,    67,    68,    69,    70,
+      71,    72,    73,    74,    -1,    76,    -1,    -1,    -1,    -1,
+      -1,   154,    -1,   156,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   154,    -1,   156
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const yytype_uint16 yystos[] =
+{
+       0,   109,   216,   218,    78,     0,   220,   113,   110,   217,
+     221,    76,     3,     4,     5,     6,     7,     8,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    34,    36,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      76,   103,   104,   105,   106,   108,   116,   117,   118,   119,
+     120,   154,   156,   219,   222,   252,   253,   254,   255,   256,
+     261,   262,   263,   264,   265,   268,   270,   271,   272,   273,
+     274,   275,   276,   277,   303,   304,   112,    33,    34,    37,
+      76,   213,    76,   103,   270,   276,   113,   113,   113,   113,
+     191,   303,   212,   213,   290,   192,   196,     4,    33,    34,
+      35,   258,   259,   269,   196,   212,    76,    33,    37,   270,
+     272,   193,   273,    76,   213,   272,   278,   279,   273,    76,
+     266,   267,     9,    10,    11,    13,    14,    15,    16,    17,
+      18,    19,    75,    76,    77,    78,    79,    80,    81,    84,
+      85,   191,   197,   198,   199,   200,   212,   213,   214,   223,
+     224,   225,   227,   228,   229,   230,   231,   232,   233,   234,
+     235,   236,   237,   238,   239,   240,   241,   242,   243,   244,
+     245,   246,   247,   248,   250,   252,   253,   272,   283,   284,
+     285,   286,   287,   288,   291,   292,   293,   294,   296,   297,
+     298,   302,   258,   257,   260,   272,   259,    76,   191,   193,
+     211,   194,   234,   247,   251,   272,   113,   278,    76,   280,
+     281,   214,   279,   212,   192,   196,   212,   212,   284,   191,
+     191,   212,   212,   250,   191,   250,   210,   191,   234,   234,
+     250,   214,   291,    84,    85,   193,   195,   192,   192,   196,
+      74,   248,   191,    93,    94,    95,    96,    97,    98,    99,
+     100,   101,   102,   211,   249,   234,   201,   202,   203,   197,
+     198,    82,    83,    86,    87,   204,   205,    88,    89,   206,
+     207,   208,    90,    92,    91,   209,   196,   212,   214,   284,
+      76,   257,   260,   193,   211,   194,   251,   248,   282,   194,
+     214,   193,   196,   212,   267,    75,   283,   292,   299,   250,
+     212,   250,   210,   250,   263,   295,   192,   214,   226,   250,
+      76,   229,   248,   248,   234,   234,   234,   236,   236,   237,
+     237,   238,   238,   238,   238,   239,   239,   240,   241,   242,
+     243,   244,   245,   250,   248,   193,   194,   251,   282,   211,
+     194,   251,   281,   191,   295,   300,   301,   192,   192,    76,
+     192,   194,   210,   251,   211,   194,   282,   211,   194,   250,
+     212,   192,   285,   286,   288,   211,    14,   287,   289,   290,
+     248,   194,   282,   211,   282,   192,   250,   289,    12,   282,
+     191,   282,   212,   285,   286,   250,   192,   285,    12
+};
+
+#define yyerrok                (yyerrstatus = 0)
+#define yyclearin      (yychar = YYEMPTY)
+#define YYEMPTY                (-2)
+#define YYEOF          0
+
+#define YYACCEPT       goto yyacceptlab
+#define YYABORT                goto yyabortlab
+#define YYERROR                goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL         goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                 \
+do                                                             \
+  if (yychar == YYEMPTY && yylen == 1)                         \
+    {                                                          \
+      yychar = (Token);                                                \
+      yylval = (Value);                                                \
+      yytoken = YYTRANSLATE (yychar);                          \
+      YYPOPSTACK (1);                                          \
+      goto yybackup;                                           \
+    }                                                          \
+  else                                                         \
+    {                                                          \
+      yyerror (&yylloc, state, YY_("syntax error: cannot back up")); \
+      YYERROR;                                                 \
+    }                                                          \
+while (YYID (0))
+
+
+#define YYTERROR       1
+#define YYERRCODE      256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)                               \
+    do                                                                 \
+      if (YYID (N))                                                    \
+       {                                                               \
+         (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
+         (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
+         (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
+         (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
+       }                                                               \
+      else                                                             \
+       {                                                               \
+         (Current).first_line   = (Current).last_line   =              \
+           YYRHSLOC (Rhs, 0).last_line;                                \
+         (Current).first_column = (Current).last_column =              \
+           YYRHSLOC (Rhs, 0).last_column;                              \
+       }                                                               \
+    while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)                 \
+     fprintf (File, "%d.%d-%d.%d",                     \
+             (Loc).first_line, (Loc).first_column,     \
+             (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval, &yylloc, scanner)
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                       \
+do {                                           \
+  if (yydebug)                                 \
+    YYFPRINTF Args;                            \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                   \
+do {                                                                     \
+  if (yydebug)                                                           \
+    {                                                                    \
+      YYFPRINTF (stderr, "%s ", Title);                                          \
+      yy_symbol_print (stderr,                                           \
+                 Type, Value, Location, state); \
+      YYFPRINTF (stderr, "\n");                                                  \
+    }                                                                    \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct _mesa_glsl_parse_state *state)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, state)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    YYLTYPE const * const yylocationp;
+    struct _mesa_glsl_parse_state *state;
+#endif
+{
+  if (!yyvaluep)
+    return;
+  YYUSE (yylocationp);
+  YYUSE (state);
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+       break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct _mesa_glsl_parse_state *state)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, state)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    YYLTYPE const * const yylocationp;
+    struct _mesa_glsl_parse_state *state;
+#endif
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  YY_LOCATION_PRINT (yyoutput, *yylocationp);
+  YYFPRINTF (yyoutput, ": ");
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, state);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+    yytype_int16 *yybottom;
+    yytype_int16 *yytop;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                           \
+do {                                                           \
+  if (yydebug)                                                 \
+    yy_stack_print ((Bottom), (Top));                          \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, struct _mesa_glsl_parse_state *state)
+#else
+static void
+yy_reduce_print (yyvsp, yylsp, yyrule, state)
+    YYSTYPE *yyvsp;
+    YYLTYPE *yylsp;
+    int yyrule;
+    struct _mesa_glsl_parse_state *state;
+#endif
+{
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+            yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+                      &(yyvsp[(yyi + 1) - (yynrhs)])
+                      , &(yylsp[(yyi + 1) - (yynrhs)])                , state);
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)         \
+do {                                   \
+  if (yydebug)                         \
+    yy_reduce_print (yyvsp, yylsp, Rule, state); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef        YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+\f
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+    const char *yystr;
+#endif
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+    char *yydest;
+    const char *yysrc;
+#endif
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+       switch (*++yyp)
+         {
+         case '\'':
+         case ',':
+           goto do_not_strip_quotes;
+
+         case '\\':
+           if (*++yyp != '\\')
+             goto do_not_strip_quotes;
+           /* Fall through.  */
+         default:
+           if (yyres)
+             yyres[yyn] = *yyp;
+           yyn++;
+           break;
+
+         case '"':
+           if (yyres)
+             yyres[yyn] = '\0';
+           return yyn;
+         }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+  int yyn = yypact[yystate];
+
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+        constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+                   + sizeof yyexpecting - 1
+                   + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+                      * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+        YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+       if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+         {
+           if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+             {
+               yycount = 1;
+               yysize = yysize0;
+               yyformat[sizeof yyunexpected - 1] = '\0';
+               break;
+             }
+           yyarg[yycount++] = yytname[yyx];
+           yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+           yysize_overflow |= (yysize1 < yysize);
+           yysize = yysize1;
+           yyfmt = yystpcpy (yyfmt, yyprefix);
+           yyprefix = yyor;
+         }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+       return YYSIZE_MAXIMUM;
+
+      if (yyresult)
+       {
+         /* Avoid sprintf, as that infringes on the user's name space.
+            Don't have undefined behavior even if the translation
+            produced a string with the wrong number of "%s"s.  */
+         char *yyp = yyresult;
+         int yyi = 0;
+         while ((*yyp = *yyf) != '\0')
+           {
+             if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+               {
+                 yyp += yytnamerr (yyp, yyarg[yyi++]);
+                 yyf += 2;
+               }
+             else
+               {
+                 yyp++;
+                 yyf++;
+               }
+           }
+       }
+      return yysize;
+    }
+}
+#endif /* YYERROR_VERBOSE */
+\f
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, struct _mesa_glsl_parse_state *state)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, yylocationp, state)
+    const char *yymsg;
+    int yytype;
+    YYSTYPE *yyvaluep;
+    YYLTYPE *yylocationp;
+    struct _mesa_glsl_parse_state *state;
+#endif
+{
+  YYUSE (yyvaluep);
+  YYUSE (yylocationp);
+  YYUSE (state);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+
+      default:
+       break;
+    }
+}
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (struct _mesa_glsl_parse_state *state);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse.  |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+    void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (struct _mesa_glsl_parse_state *state)
+#else
+int
+yyparse (state)
+    struct _mesa_glsl_parse_state *state;
+#endif
+#endif
+{
+/* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+
+/* Location data for the lookahead symbol.  */
+YYLTYPE yylloc;
+
+    /* Number of syntax errors so far.  */
+    int yynerrs;
+
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       `yyss': related to states.
+       `yyvs': related to semantic values.
+       `yyls': related to locations.
+
+       Refer to the stacks thru separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    /* The location stack.  */
+    YYLTYPE yylsa[YYINITDEPTH];
+    YYLTYPE *yyls;
+    YYLTYPE *yylsp;
+
+    /* The locations where the error started and ended.  */
+    YYLTYPE yyerror_range[2];
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+  YYLTYPE yyloc;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yytoken = 0;
+  yyss = yyssa;
+  yyvs = yyvsa;
+  yyls = yylsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+  yyssp = yyss;
+  yyvsp = yyvs;
+  yylsp = yyls;
+
+#if YYLTYPE_IS_TRIVIAL
+  /* Initialize the default location before parsing starts.  */
+  yylloc.first_line   = yylloc.last_line   = 1;
+  yylloc.first_column = yylloc.last_column = 1;
+#endif
+
+/* User initialization code.  */
+
+/* Line 1242 of yacc.c  */
+#line 41 "glsl_parser.ypp"
+{
+   yylloc.first_line = 1;
+   yylloc.first_column = 1;
+   yylloc.last_line = 1;
+   yylloc.last_column = 1;
+   yylloc.source = 0;
+}
+
+/* Line 1242 of yacc.c  */
+#line 2705 "glsl_parser.cpp"
+  yylsp[0] = yylloc;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+       /* Give user a chance to reallocate the stack.  Use copies of
+          these so that the &'s don't force the real ones into
+          memory.  */
+       YYSTYPE *yyvs1 = yyvs;
+       yytype_int16 *yyss1 = yyss;
+       YYLTYPE *yyls1 = yyls;
+
+       /* Each stack pointer address is followed by the size of the
+          data in use in that stack, in bytes.  This used to be a
+          conditional around just the two extra args, but that might
+          be undefined if yyoverflow is a macro.  */
+       yyoverflow (YY_("memory exhausted"),
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+                   &yyls1, yysize * sizeof (*yylsp),
+                   &yystacksize);
+
+       yyls = yyls1;
+       yyss = yyss1;
+       yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+       goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+       yystacksize = YYMAXDEPTH;
+
+      {
+       yytype_int16 *yyss1 = yyss;
+       union yyalloc *yyptr =
+         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+       if (! yyptr)
+         goto yyexhaustedlab;
+       YYSTACK_RELOCATE (yyss_alloc, yyss);
+       YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+       YYSTACK_RELOCATE (yyls_alloc, yyls);
+#  undef YYSTACK_RELOCATE
+       if (yyss1 != yyssa)
+         YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+      yylsp = yyls + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                 (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+       YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+       goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  *++yyvsp = yylval;
+  *++yylsp = yylloc;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+  /* Default location.  */
+  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 2:
+
+/* Line 1455 of yacc.c  */
+#line 211 "glsl_parser.ypp"
+    {
+          _mesa_glsl_initialize_types(state);
+       ;}
+    break;
+
+  case 4:
+
+/* Line 1455 of yacc.c  */
+#line 219 "glsl_parser.ypp"
+    {
+          state->language_version = 110;
+          state->symbols->language_version = 110;
+       ;}
+    break;
+
+  case 5:
+
+/* Line 1455 of yacc.c  */
+#line 224 "glsl_parser.ypp"
+    {
+          switch ((yyvsp[(2) - (3)].n)) {
+          case 110:
+          case 120:
+          case 130:
+             /* FINISHME: Check against implementation support versions. */
+             state->language_version = (yyvsp[(2) - (3)].n);
+             state->symbols->language_version = (yyvsp[(2) - (3)].n);
+             break;
+          default:
+             _mesa_glsl_error(& (yylsp[(2) - (3)]), state, "Shading language version"
+                              "%u is not supported\n", (yyvsp[(2) - (3)].n));
+             break;
+          }
+       ;}
+    break;
+
+  case 12:
+
+/* Line 1455 of yacc.c  */
+#line 255 "glsl_parser.ypp"
+    {
+          if (!_mesa_glsl_process_extension((yyvsp[(2) - (5)].identifier), & (yylsp[(2) - (5)]), (yyvsp[(4) - (5)].identifier), & (yylsp[(4) - (5)]), state)) {
+             YYERROR;
+          }
+       ;}
+    break;
+
+  case 13:
+
+/* Line 1455 of yacc.c  */
+#line 264 "glsl_parser.ypp"
+    {
+          /* FINISHME: The NULL test is only required because 'precision'
+           * FINISHME: statements are not yet supported.
+           */
+          if ((yyvsp[(1) - (1)].node) != NULL)
+             state->translation_unit.push_tail(& (yyvsp[(1) - (1)].node)->link);
+       ;}
+    break;
+
+  case 14:
+
+/* Line 1455 of yacc.c  */
+#line 272 "glsl_parser.ypp"
+    {
+          /* FINISHME: The NULL test is only required because 'precision'
+           * FINISHME: statements are not yet supported.
+           */
+          if ((yyvsp[(2) - (2)].node) != NULL)
+             state->translation_unit.push_tail(& (yyvsp[(2) - (2)].node)->link);
+       ;}
+    break;
+
+  case 16:
+
+/* Line 1455 of yacc.c  */
+#line 287 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression(ast_identifier, NULL, NULL, NULL);
+          (yyval.expression)->set_location(yylloc);
+          (yyval.expression)->primary_expression.identifier = (yyvsp[(1) - (1)].identifier);
+       ;}
+    break;
+
+  case 17:
+
+/* Line 1455 of yacc.c  */
+#line 294 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression(ast_int_constant, NULL, NULL, NULL);
+          (yyval.expression)->set_location(yylloc);
+          (yyval.expression)->primary_expression.int_constant = (yyvsp[(1) - (1)].n);
+       ;}
+    break;
+
+  case 18:
+
+/* Line 1455 of yacc.c  */
+#line 301 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression(ast_uint_constant, NULL, NULL, NULL);
+          (yyval.expression)->set_location(yylloc);
+          (yyval.expression)->primary_expression.uint_constant = (yyvsp[(1) - (1)].n);
+       ;}
+    break;
+
+  case 19:
+
+/* Line 1455 of yacc.c  */
+#line 308 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression(ast_float_constant, NULL, NULL, NULL);
+          (yyval.expression)->set_location(yylloc);
+          (yyval.expression)->primary_expression.float_constant = (yyvsp[(1) - (1)].real);
+       ;}
+    break;
+
+  case 20:
+
+/* Line 1455 of yacc.c  */
+#line 315 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression(ast_bool_constant, NULL, NULL, NULL);
+          (yyval.expression)->set_location(yylloc);
+          (yyval.expression)->primary_expression.bool_constant = (yyvsp[(1) - (1)].n);
+       ;}
+    break;
+
+  case 21:
+
+/* Line 1455 of yacc.c  */
+#line 322 "glsl_parser.ypp"
+    {
+          (yyval.expression) = (yyvsp[(2) - (3)].expression);
+       ;}
+    break;
+
+  case 23:
+
+/* Line 1455 of yacc.c  */
+#line 330 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression(ast_array_index, (yyvsp[(1) - (4)].expression), (yyvsp[(3) - (4)].expression), NULL);
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 24:
+
+/* Line 1455 of yacc.c  */
+#line 336 "glsl_parser.ypp"
+    {
+          (yyval.expression) = (yyvsp[(1) - (1)].expression);
+       ;}
+    break;
+
+  case 25:
+
+/* Line 1455 of yacc.c  */
+#line 340 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression(ast_field_selection, (yyvsp[(1) - (3)].expression), NULL, NULL);
+          (yyval.expression)->set_location(yylloc);
+          (yyval.expression)->primary_expression.identifier = (yyvsp[(3) - (3)].identifier);
+       ;}
+    break;
+
+  case 26:
+
+/* Line 1455 of yacc.c  */
+#line 347 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression(ast_post_inc, (yyvsp[(1) - (2)].expression), NULL, NULL);
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 27:
+
+/* Line 1455 of yacc.c  */
+#line 353 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression(ast_post_dec, (yyvsp[(1) - (2)].expression), NULL, NULL);
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 31:
+
+/* Line 1455 of yacc.c  */
+#line 371 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression(ast_field_selection, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression), NULL);
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 36:
+
+/* Line 1455 of yacc.c  */
+#line 390 "glsl_parser.ypp"
+    {
+          (yyval.expression) = (yyvsp[(1) - (2)].expression);
+          (yyval.expression)->set_location(yylloc);
+          (yyval.expression)->expressions.push_tail(& (yyvsp[(2) - (2)].expression)->link);
+       ;}
+    break;
+
+  case 37:
+
+/* Line 1455 of yacc.c  */
+#line 396 "glsl_parser.ypp"
+    {
+          (yyval.expression) = (yyvsp[(1) - (3)].expression);
+          (yyval.expression)->set_location(yylloc);
+          (yyval.expression)->expressions.push_tail(& (yyvsp[(3) - (3)].expression)->link);
+       ;}
+    break;
+
+  case 39:
+
+/* Line 1455 of yacc.c  */
+#line 412 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_function_expression((yyvsp[(1) - (1)].type_specifier));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 40:
+
+/* Line 1455 of yacc.c  */
+#line 418 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_expression *callee = new(ctx) ast_expression((yyvsp[(1) - (1)].identifier));
+          (yyval.expression) = new(ctx) ast_function_expression(callee);
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 41:
+
+/* Line 1455 of yacc.c  */
+#line 425 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_expression *callee = new(ctx) ast_expression((yyvsp[(1) - (1)].identifier));
+          (yyval.expression) = new(ctx) ast_function_expression(callee);
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 43:
+
+/* Line 1455 of yacc.c  */
+#line 437 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression(ast_pre_inc, (yyvsp[(2) - (2)].expression), NULL, NULL);
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 44:
+
+/* Line 1455 of yacc.c  */
+#line 443 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression(ast_pre_dec, (yyvsp[(2) - (2)].expression), NULL, NULL);
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 45:
+
+/* Line 1455 of yacc.c  */
+#line 449 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression((yyvsp[(1) - (2)].n), (yyvsp[(2) - (2)].expression), NULL, NULL);
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 46:
+
+/* Line 1455 of yacc.c  */
+#line 458 "glsl_parser.ypp"
+    { (yyval.n) = ast_plus; ;}
+    break;
+
+  case 47:
+
+/* Line 1455 of yacc.c  */
+#line 459 "glsl_parser.ypp"
+    { (yyval.n) = ast_neg; ;}
+    break;
+
+  case 48:
+
+/* Line 1455 of yacc.c  */
+#line 460 "glsl_parser.ypp"
+    { (yyval.n) = ast_logic_not; ;}
+    break;
+
+  case 49:
+
+/* Line 1455 of yacc.c  */
+#line 461 "glsl_parser.ypp"
+    { (yyval.n) = ast_bit_not; ;}
+    break;
+
+  case 51:
+
+/* Line 1455 of yacc.c  */
+#line 467 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_mul, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 52:
+
+/* Line 1455 of yacc.c  */
+#line 473 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_div, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 53:
+
+/* Line 1455 of yacc.c  */
+#line 479 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_mod, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 55:
+
+/* Line 1455 of yacc.c  */
+#line 489 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_add, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 56:
+
+/* Line 1455 of yacc.c  */
+#line 495 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_sub, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 58:
+
+/* Line 1455 of yacc.c  */
+#line 505 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_lshift, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 59:
+
+/* Line 1455 of yacc.c  */
+#line 511 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_rshift, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 61:
+
+/* Line 1455 of yacc.c  */
+#line 521 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_less, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 62:
+
+/* Line 1455 of yacc.c  */
+#line 527 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_greater, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 63:
+
+/* Line 1455 of yacc.c  */
+#line 533 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_lequal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 64:
+
+/* Line 1455 of yacc.c  */
+#line 539 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_gequal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 66:
+
+/* Line 1455 of yacc.c  */
+#line 549 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_equal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 67:
+
+/* Line 1455 of yacc.c  */
+#line 555 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_nequal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 69:
+
+/* Line 1455 of yacc.c  */
+#line 565 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_bit_or, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 71:
+
+/* Line 1455 of yacc.c  */
+#line 575 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_bit_xor, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 73:
+
+/* Line 1455 of yacc.c  */
+#line 585 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_bit_or, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 75:
+
+/* Line 1455 of yacc.c  */
+#line 595 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_logic_and, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 77:
+
+/* Line 1455 of yacc.c  */
+#line 605 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_logic_xor, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 79:
+
+/* Line 1455 of yacc.c  */
+#line 615 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression_bin(ast_logic_or, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 81:
+
+/* Line 1455 of yacc.c  */
+#line 625 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression(ast_conditional, (yyvsp[(1) - (5)].expression), (yyvsp[(3) - (5)].expression), (yyvsp[(5) - (5)].expression));
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 83:
+
+/* Line 1455 of yacc.c  */
+#line 635 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.expression) = new(ctx) ast_expression((yyvsp[(2) - (3)].n), (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression), NULL);
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 84:
+
+/* Line 1455 of yacc.c  */
+#line 643 "glsl_parser.ypp"
+    { (yyval.n) = ast_assign; ;}
+    break;
+
+  case 85:
+
+/* Line 1455 of yacc.c  */
+#line 644 "glsl_parser.ypp"
+    { (yyval.n) = ast_mul_assign; ;}
+    break;
+
+  case 86:
+
+/* Line 1455 of yacc.c  */
+#line 645 "glsl_parser.ypp"
+    { (yyval.n) = ast_div_assign; ;}
+    break;
+
+  case 87:
+
+/* Line 1455 of yacc.c  */
+#line 646 "glsl_parser.ypp"
+    { (yyval.n) = ast_mod_assign; ;}
+    break;
+
+  case 88:
+
+/* Line 1455 of yacc.c  */
+#line 647 "glsl_parser.ypp"
+    { (yyval.n) = ast_add_assign; ;}
+    break;
+
+  case 89:
+
+/* Line 1455 of yacc.c  */
+#line 648 "glsl_parser.ypp"
+    { (yyval.n) = ast_sub_assign; ;}
+    break;
+
+  case 90:
+
+/* Line 1455 of yacc.c  */
+#line 649 "glsl_parser.ypp"
+    { (yyval.n) = ast_ls_assign; ;}
+    break;
+
+  case 91:
+
+/* Line 1455 of yacc.c  */
+#line 650 "glsl_parser.ypp"
+    { (yyval.n) = ast_rs_assign; ;}
+    break;
+
+  case 92:
+
+/* Line 1455 of yacc.c  */
+#line 651 "glsl_parser.ypp"
+    { (yyval.n) = ast_and_assign; ;}
+    break;
+
+  case 93:
+
+/* Line 1455 of yacc.c  */
+#line 652 "glsl_parser.ypp"
+    { (yyval.n) = ast_xor_assign; ;}
+    break;
+
+  case 94:
+
+/* Line 1455 of yacc.c  */
+#line 653 "glsl_parser.ypp"
+    { (yyval.n) = ast_or_assign; ;}
+    break;
+
+  case 95:
+
+/* Line 1455 of yacc.c  */
+#line 658 "glsl_parser.ypp"
+    {
+          (yyval.expression) = (yyvsp[(1) - (1)].expression);
+       ;}
+    break;
+
+  case 96:
+
+/* Line 1455 of yacc.c  */
+#line 662 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          if ((yyvsp[(1) - (3)].expression)->oper != ast_sequence) {
+             (yyval.expression) = new(ctx) ast_expression(ast_sequence, NULL, NULL, NULL);
+             (yyval.expression)->set_location(yylloc);
+             (yyval.expression)->expressions.push_tail(& (yyvsp[(1) - (3)].expression)->link);
+          } else {
+             (yyval.expression) = (yyvsp[(1) - (3)].expression);
+          }
+
+          (yyval.expression)->expressions.push_tail(& (yyvsp[(3) - (3)].expression)->link);
+       ;}
+    break;
+
+  case 98:
+
+/* Line 1455 of yacc.c  */
+#line 682 "glsl_parser.ypp"
+    {
+          (yyval.node) = (yyvsp[(1) - (2)].function);
+       ;}
+    break;
+
+  case 99:
+
+/* Line 1455 of yacc.c  */
+#line 686 "glsl_parser.ypp"
+    {
+          (yyval.node) = (yyvsp[(1) - (2)].declarator_list);
+       ;}
+    break;
+
+  case 100:
+
+/* Line 1455 of yacc.c  */
+#line 690 "glsl_parser.ypp"
+    {
+          if (((yyvsp[(3) - (4)].type_specifier)->type_specifier != ast_float)
+              && ((yyvsp[(3) - (4)].type_specifier)->type_specifier != ast_int)) {
+             _mesa_glsl_error(& (yylsp[(3) - (4)]), state, "global precision qualifier can "
+                              "only be applied to `int' or `float'\n");
+             YYERROR;
+          }
+
+          (yyval.node) = NULL; /* FINISHME */
+       ;}
+    break;
+
+  case 104:
+
+/* Line 1455 of yacc.c  */
+#line 713 "glsl_parser.ypp"
+    {
+          (yyval.function) = (yyvsp[(1) - (2)].function);
+          (yyval.function)->parameters.push_tail(& (yyvsp[(2) - (2)].parameter_declarator)->link);
+       ;}
+    break;
+
+  case 105:
+
+/* Line 1455 of yacc.c  */
+#line 718 "glsl_parser.ypp"
+    {
+          (yyval.function) = (yyvsp[(1) - (3)].function);
+          (yyval.function)->parameters.push_tail(& (yyvsp[(3) - (3)].parameter_declarator)->link);
+       ;}
+    break;
+
+  case 106:
+
+/* Line 1455 of yacc.c  */
+#line 726 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.function) = new(ctx) ast_function();
+          (yyval.function)->set_location(yylloc);
+          (yyval.function)->return_type = (yyvsp[(1) - (3)].fully_specified_type);
+          (yyval.function)->identifier = (yyvsp[(2) - (3)].identifier);
+       ;}
+    break;
+
+  case 107:
+
+/* Line 1455 of yacc.c  */
+#line 737 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.parameter_declarator) = new(ctx) ast_parameter_declarator();
+          (yyval.parameter_declarator)->set_location(yylloc);
+          (yyval.parameter_declarator)->type = new(ctx) ast_fully_specified_type();
+          (yyval.parameter_declarator)->type->set_location(yylloc);
+          (yyval.parameter_declarator)->type->specifier = (yyvsp[(1) - (2)].type_specifier);
+          (yyval.parameter_declarator)->identifier = (yyvsp[(2) - (2)].identifier);
+       ;}
+    break;
+
+  case 108:
+
+/* Line 1455 of yacc.c  */
+#line 747 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.parameter_declarator) = new(ctx) ast_parameter_declarator();
+          (yyval.parameter_declarator)->set_location(yylloc);
+          (yyval.parameter_declarator)->type = new(ctx) ast_fully_specified_type();
+          (yyval.parameter_declarator)->type->set_location(yylloc);
+          (yyval.parameter_declarator)->type->specifier = (yyvsp[(1) - (5)].type_specifier);
+          (yyval.parameter_declarator)->identifier = (yyvsp[(2) - (5)].identifier);
+          (yyval.parameter_declarator)->is_array = true;
+          (yyval.parameter_declarator)->array_size = (yyvsp[(4) - (5)].expression);
+       ;}
+    break;
+
+  case 109:
+
+/* Line 1455 of yacc.c  */
+#line 762 "glsl_parser.ypp"
+    {
+          (yyvsp[(1) - (3)].type_qualifier).i |= (yyvsp[(2) - (3)].type_qualifier).i;
+
+          (yyval.parameter_declarator) = (yyvsp[(3) - (3)].parameter_declarator);
+          (yyval.parameter_declarator)->type->qualifier = (yyvsp[(1) - (3)].type_qualifier).q;
+       ;}
+    break;
+
+  case 110:
+
+/* Line 1455 of yacc.c  */
+#line 769 "glsl_parser.ypp"
+    {
+          (yyval.parameter_declarator) = (yyvsp[(2) - (2)].parameter_declarator);
+          (yyval.parameter_declarator)->type->qualifier = (yyvsp[(1) - (2)].type_qualifier).q;
+       ;}
+    break;
+
+  case 111:
+
+/* Line 1455 of yacc.c  */
+#line 774 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyvsp[(1) - (3)].type_qualifier).i |= (yyvsp[(2) - (3)].type_qualifier).i;
+
+          (yyval.parameter_declarator) = new(ctx) ast_parameter_declarator();
+          (yyval.parameter_declarator)->set_location(yylloc);
+          (yyval.parameter_declarator)->type = new(ctx) ast_fully_specified_type();
+          (yyval.parameter_declarator)->type->qualifier = (yyvsp[(1) - (3)].type_qualifier).q;
+          (yyval.parameter_declarator)->type->specifier = (yyvsp[(3) - (3)].type_specifier);
+       ;}
+    break;
+
+  case 112:
+
+/* Line 1455 of yacc.c  */
+#line 785 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.parameter_declarator) = new(ctx) ast_parameter_declarator();
+          (yyval.parameter_declarator)->set_location(yylloc);
+          (yyval.parameter_declarator)->type = new(ctx) ast_fully_specified_type();
+          (yyval.parameter_declarator)->type->qualifier = (yyvsp[(1) - (2)].type_qualifier).q;
+          (yyval.parameter_declarator)->type->specifier = (yyvsp[(2) - (2)].type_specifier);
+       ;}
+    break;
+
+  case 113:
+
+/* Line 1455 of yacc.c  */
+#line 796 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; ;}
+    break;
+
+  case 114:
+
+/* Line 1455 of yacc.c  */
+#line 797 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.in = 1; ;}
+    break;
+
+  case 115:
+
+/* Line 1455 of yacc.c  */
+#line 798 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.out = 1; ;}
+    break;
+
+  case 116:
+
+/* Line 1455 of yacc.c  */
+#line 799 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.in = 1; (yyval.type_qualifier).q.out = 1; ;}
+    break;
+
+  case 119:
+
+/* Line 1455 of yacc.c  */
+#line 809 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (3)].identifier), false, NULL, NULL);
+          decl->set_location(yylloc);
+
+          (yyval.declarator_list) = (yyvsp[(1) - (3)].declarator_list);
+          (yyval.declarator_list)->declarations.push_tail(&decl->link);
+       ;}
+    break;
+
+  case 120:
+
+/* Line 1455 of yacc.c  */
+#line 818 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (5)].identifier), true, NULL, NULL);
+          decl->set_location(yylloc);
+
+          (yyval.declarator_list) = (yyvsp[(1) - (5)].declarator_list);
+          (yyval.declarator_list)->declarations.push_tail(&decl->link);
+       ;}
+    break;
+
+  case 121:
+
+/* Line 1455 of yacc.c  */
+#line 827 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (6)].identifier), true, (yyvsp[(5) - (6)].expression), NULL);
+          decl->set_location(yylloc);
+
+          (yyval.declarator_list) = (yyvsp[(1) - (6)].declarator_list);
+          (yyval.declarator_list)->declarations.push_tail(&decl->link);
+       ;}
+    break;
+
+  case 122:
+
+/* Line 1455 of yacc.c  */
+#line 836 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (7)].identifier), true, NULL, (yyvsp[(7) - (7)].expression));
+          decl->set_location(yylloc);
+
+          (yyval.declarator_list) = (yyvsp[(1) - (7)].declarator_list);
+          (yyval.declarator_list)->declarations.push_tail(&decl->link);
+       ;}
+    break;
+
+  case 123:
+
+/* Line 1455 of yacc.c  */
+#line 845 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (8)].identifier), true, (yyvsp[(5) - (8)].expression), (yyvsp[(8) - (8)].expression));
+          decl->set_location(yylloc);
+
+          (yyval.declarator_list) = (yyvsp[(1) - (8)].declarator_list);
+          (yyval.declarator_list)->declarations.push_tail(&decl->link);
+       ;}
+    break;
+
+  case 124:
+
+/* Line 1455 of yacc.c  */
+#line 854 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (5)].identifier), false, NULL, (yyvsp[(5) - (5)].expression));
+          decl->set_location(yylloc);
+
+          (yyval.declarator_list) = (yyvsp[(1) - (5)].declarator_list);
+          (yyval.declarator_list)->declarations.push_tail(&decl->link);
+       ;}
+    break;
+
+  case 125:
+
+/* Line 1455 of yacc.c  */
+#line 867 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          if ((yyvsp[(1) - (1)].fully_specified_type)->specifier->type_specifier != ast_struct) {
+             _mesa_glsl_error(& (yylsp[(1) - (1)]), state, "empty declaration list\n");
+             YYERROR;
+          } else {
+             (yyval.declarator_list) = new(ctx) ast_declarator_list((yyvsp[(1) - (1)].fully_specified_type));
+             (yyval.declarator_list)->set_location(yylloc);
+          }
+       ;}
+    break;
+
+  case 126:
+
+/* Line 1455 of yacc.c  */
+#line 878 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (2)].identifier), false, NULL, NULL);
+
+          (yyval.declarator_list) = new(ctx) ast_declarator_list((yyvsp[(1) - (2)].fully_specified_type));
+          (yyval.declarator_list)->set_location(yylloc);
+          (yyval.declarator_list)->declarations.push_tail(&decl->link);
+       ;}
+    break;
+
+  case 127:
+
+/* Line 1455 of yacc.c  */
+#line 887 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (4)].identifier), true, NULL, NULL);
+
+          (yyval.declarator_list) = new(ctx) ast_declarator_list((yyvsp[(1) - (4)].fully_specified_type));
+          (yyval.declarator_list)->set_location(yylloc);
+          (yyval.declarator_list)->declarations.push_tail(&decl->link);
+       ;}
+    break;
+
+  case 128:
+
+/* Line 1455 of yacc.c  */
+#line 896 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (5)].identifier), true, (yyvsp[(4) - (5)].expression), NULL);
+
+          (yyval.declarator_list) = new(ctx) ast_declarator_list((yyvsp[(1) - (5)].fully_specified_type));
+          (yyval.declarator_list)->set_location(yylloc);
+          (yyval.declarator_list)->declarations.push_tail(&decl->link);
+       ;}
+    break;
+
+  case 129:
+
+/* Line 1455 of yacc.c  */
+#line 905 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (6)].identifier), true, NULL, (yyvsp[(6) - (6)].expression));
+
+          (yyval.declarator_list) = new(ctx) ast_declarator_list((yyvsp[(1) - (6)].fully_specified_type));
+          (yyval.declarator_list)->set_location(yylloc);
+          (yyval.declarator_list)->declarations.push_tail(&decl->link);
+       ;}
+    break;
+
+  case 130:
+
+/* Line 1455 of yacc.c  */
+#line 914 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (7)].identifier), true, (yyvsp[(4) - (7)].expression), (yyvsp[(7) - (7)].expression));
+
+          (yyval.declarator_list) = new(ctx) ast_declarator_list((yyvsp[(1) - (7)].fully_specified_type));
+          (yyval.declarator_list)->set_location(yylloc);
+          (yyval.declarator_list)->declarations.push_tail(&decl->link);
+       ;}
+    break;
+
+  case 131:
+
+/* Line 1455 of yacc.c  */
+#line 923 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (4)].identifier), false, NULL, (yyvsp[(4) - (4)].expression));
+
+          (yyval.declarator_list) = new(ctx) ast_declarator_list((yyvsp[(1) - (4)].fully_specified_type));
+          (yyval.declarator_list)->set_location(yylloc);
+          (yyval.declarator_list)->declarations.push_tail(&decl->link);
+       ;}
+    break;
+
+  case 132:
+
+/* Line 1455 of yacc.c  */
+#line 932 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (2)].identifier), false, NULL, NULL);
+
+          (yyval.declarator_list) = new(ctx) ast_declarator_list(NULL);
+          (yyval.declarator_list)->set_location(yylloc);
+          (yyval.declarator_list)->invariant = true;
+
+          (yyval.declarator_list)->declarations.push_tail(&decl->link);
+       ;}
+    break;
+
+  case 133:
+
+/* Line 1455 of yacc.c  */
+#line 946 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.fully_specified_type) = new(ctx) ast_fully_specified_type();
+          (yyval.fully_specified_type)->set_location(yylloc);
+          (yyval.fully_specified_type)->specifier = (yyvsp[(1) - (1)].type_specifier);
+       ;}
+    break;
+
+  case 134:
+
+/* Line 1455 of yacc.c  */
+#line 953 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.fully_specified_type) = new(ctx) ast_fully_specified_type();
+          (yyval.fully_specified_type)->set_location(yylloc);
+          (yyval.fully_specified_type)->qualifier = (yyvsp[(1) - (2)].type_qualifier).q;
+          (yyval.fully_specified_type)->specifier = (yyvsp[(2) - (2)].type_specifier);
+       ;}
+    break;
+
+  case 135:
+
+/* Line 1455 of yacc.c  */
+#line 963 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; ;}
+    break;
+
+  case 137:
+
+/* Line 1455 of yacc.c  */
+#line 969 "glsl_parser.ypp"
+    {
+         (yyval.type_qualifier) = (yyvsp[(3) - (4)].type_qualifier);
+       ;}
+    break;
+
+  case 139:
+
+/* Line 1455 of yacc.c  */
+#line 977 "glsl_parser.ypp"
+    {
+          (yyval.type_qualifier).i = (yyvsp[(1) - (3)].type_qualifier).i | (yyvsp[(3) - (3)].type_qualifier).i;
+       ;}
+    break;
+
+  case 140:
+
+/* Line 1455 of yacc.c  */
+#line 984 "glsl_parser.ypp"
+    {
+          (yyval.type_qualifier).i = 0;
+
+          if (state->ARB_fragment_coord_conventions_enable) {
+             bool got_one = false;
+
+             if (strcmp((yyvsp[(1) - (1)].identifier), "origin_upper_left") == 0) {
+                got_one = true;
+                (yyval.type_qualifier).q.origin_upper_left = 1;
+             } else if (strcmp((yyvsp[(1) - (1)].identifier), "pixel_center_integer") == 0) {
+                got_one = true;
+                (yyval.type_qualifier).q.pixel_center_integer = 1;
+             }
+
+             if (state->ARB_fragment_coord_conventions_warn && got_one) {
+                _mesa_glsl_warning(& (yylsp[(1) - (1)]), state,
+                                   "GL_ARB_fragment_coord_conventions layout "
+                                   "identifier `%s' used\n", (yyvsp[(1) - (1)].identifier));
+             }
+          }
+
+          /* If the identifier didn't match any known layout identifiers,
+           * emit an error.
+           */
+          if ((yyval.type_qualifier).i == 0) {
+             _mesa_glsl_error(& (yylsp[(1) - (1)]), state, "unrecognized layout identifier "
+                              "`%s'\n", (yyvsp[(1) - (1)].identifier));
+             YYERROR;
+          }
+       ;}
+    break;
+
+  case 141:
+
+/* Line 1455 of yacc.c  */
+#line 1017 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.smooth = 1; ;}
+    break;
+
+  case 142:
+
+/* Line 1455 of yacc.c  */
+#line 1018 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.flat = 1; ;}
+    break;
+
+  case 143:
+
+/* Line 1455 of yacc.c  */
+#line 1019 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.noperspective = 1; ;}
+    break;
+
+  case 144:
+
+/* Line 1455 of yacc.c  */
+#line 1023 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.constant = 1; ;}
+    break;
+
+  case 146:
+
+/* Line 1455 of yacc.c  */
+#line 1029 "glsl_parser.ypp"
+    {
+          (yyval.type_qualifier).i = (yyvsp[(1) - (2)].type_qualifier).i | (yyvsp[(2) - (2)].type_qualifier).i;
+       ;}
+    break;
+
+  case 147:
+
+/* Line 1455 of yacc.c  */
+#line 1033 "glsl_parser.ypp"
+    {
+          (yyval.type_qualifier) = (yyvsp[(2) - (2)].type_qualifier);
+          (yyval.type_qualifier).q.invariant = 1;
+       ;}
+    break;
+
+  case 148:
+
+/* Line 1455 of yacc.c  */
+#line 1040 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.constant = 1; ;}
+    break;
+
+  case 149:
+
+/* Line 1455 of yacc.c  */
+#line 1041 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.attribute = 1; ;}
+    break;
+
+  case 150:
+
+/* Line 1455 of yacc.c  */
+#line 1042 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = (yyvsp[(1) - (2)].type_qualifier).i; (yyval.type_qualifier).q.varying = 1; ;}
+    break;
+
+  case 151:
+
+/* Line 1455 of yacc.c  */
+#line 1043 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.centroid = 1; (yyval.type_qualifier).q.varying = 1; ;}
+    break;
+
+  case 152:
+
+/* Line 1455 of yacc.c  */
+#line 1044 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.in = 1; ;}
+    break;
+
+  case 153:
+
+/* Line 1455 of yacc.c  */
+#line 1045 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.out = 1; ;}
+    break;
+
+  case 154:
+
+/* Line 1455 of yacc.c  */
+#line 1046 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.centroid = 1; (yyval.type_qualifier).q.in = 1; ;}
+    break;
+
+  case 155:
+
+/* Line 1455 of yacc.c  */
+#line 1047 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.centroid = 1; (yyval.type_qualifier).q.out = 1; ;}
+    break;
+
+  case 156:
+
+/* Line 1455 of yacc.c  */
+#line 1048 "glsl_parser.ypp"
+    { (yyval.type_qualifier).i = 0; (yyval.type_qualifier).q.uniform = 1; ;}
+    break;
+
+  case 158:
+
+/* Line 1455 of yacc.c  */
+#line 1054 "glsl_parser.ypp"
+    {
+          (yyval.type_specifier) = (yyvsp[(2) - (2)].type_specifier);
+          (yyval.type_specifier)->precision = (yyvsp[(1) - (2)].n);
+       ;}
+    break;
+
+  case 160:
+
+/* Line 1455 of yacc.c  */
+#line 1063 "glsl_parser.ypp"
+    {
+          (yyval.type_specifier) = (yyvsp[(1) - (3)].type_specifier);
+          (yyval.type_specifier)->is_array = true;
+          (yyval.type_specifier)->array_size = NULL;
+       ;}
+    break;
+
+  case 161:
+
+/* Line 1455 of yacc.c  */
+#line 1069 "glsl_parser.ypp"
+    {
+          (yyval.type_specifier) = (yyvsp[(1) - (4)].type_specifier);
+          (yyval.type_specifier)->is_array = true;
+          (yyval.type_specifier)->array_size = (yyvsp[(3) - (4)].expression);
+       ;}
+    break;
+
+  case 162:
+
+/* Line 1455 of yacc.c  */
+#line 1078 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.type_specifier) = new(ctx) ast_type_specifier((yyvsp[(1) - (1)].n));
+          (yyval.type_specifier)->set_location(yylloc);
+       ;}
+    break;
+
+  case 163:
+
+/* Line 1455 of yacc.c  */
+#line 1084 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.type_specifier) = new(ctx) ast_type_specifier((yyvsp[(1) - (1)].struct_specifier));
+          (yyval.type_specifier)->set_location(yylloc);
+       ;}
+    break;
+
+  case 164:
+
+/* Line 1455 of yacc.c  */
+#line 1090 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.type_specifier) = new(ctx) ast_type_specifier((yyvsp[(1) - (1)].identifier));
+          (yyval.type_specifier)->set_location(yylloc);
+       ;}
+    break;
+
+  case 165:
+
+/* Line 1455 of yacc.c  */
+#line 1098 "glsl_parser.ypp"
+    { (yyval.n) = ast_void; ;}
+    break;
+
+  case 166:
+
+/* Line 1455 of yacc.c  */
+#line 1099 "glsl_parser.ypp"
+    { (yyval.n) = ast_float; ;}
+    break;
+
+  case 167:
+
+/* Line 1455 of yacc.c  */
+#line 1100 "glsl_parser.ypp"
+    { (yyval.n) = ast_int; ;}
+    break;
+
+  case 168:
+
+/* Line 1455 of yacc.c  */
+#line 1101 "glsl_parser.ypp"
+    { (yyval.n) = ast_uint; ;}
+    break;
+
+  case 169:
+
+/* Line 1455 of yacc.c  */
+#line 1102 "glsl_parser.ypp"
+    { (yyval.n) = ast_bool; ;}
+    break;
+
+  case 170:
+
+/* Line 1455 of yacc.c  */
+#line 1103 "glsl_parser.ypp"
+    { (yyval.n) = ast_vec2; ;}
+    break;
+
+  case 171:
+
+/* Line 1455 of yacc.c  */
+#line 1104 "glsl_parser.ypp"
+    { (yyval.n) = ast_vec3; ;}
+    break;
+
+  case 172:
+
+/* Line 1455 of yacc.c  */
+#line 1105 "glsl_parser.ypp"
+    { (yyval.n) = ast_vec4; ;}
+    break;
+
+  case 173:
+
+/* Line 1455 of yacc.c  */
+#line 1106 "glsl_parser.ypp"
+    { (yyval.n) = ast_bvec2; ;}
+    break;
+
+  case 174:
+
+/* Line 1455 of yacc.c  */
+#line 1107 "glsl_parser.ypp"
+    { (yyval.n) = ast_bvec3; ;}
+    break;
+
+  case 175:
+
+/* Line 1455 of yacc.c  */
+#line 1108 "glsl_parser.ypp"
+    { (yyval.n) = ast_bvec4; ;}
+    break;
+
+  case 176:
+
+/* Line 1455 of yacc.c  */
+#line 1109 "glsl_parser.ypp"
+    { (yyval.n) = ast_ivec2; ;}
+    break;
+
+  case 177:
+
+/* Line 1455 of yacc.c  */
+#line 1110 "glsl_parser.ypp"
+    { (yyval.n) = ast_ivec3; ;}
+    break;
+
+  case 178:
+
+/* Line 1455 of yacc.c  */
+#line 1111 "glsl_parser.ypp"
+    { (yyval.n) = ast_ivec4; ;}
+    break;
+
+  case 179:
+
+/* Line 1455 of yacc.c  */
+#line 1112 "glsl_parser.ypp"
+    { (yyval.n) = ast_uvec2; ;}
+    break;
+
+  case 180:
+
+/* Line 1455 of yacc.c  */
+#line 1113 "glsl_parser.ypp"
+    { (yyval.n) = ast_uvec3; ;}
+    break;
+
+  case 181:
+
+/* Line 1455 of yacc.c  */
+#line 1114 "glsl_parser.ypp"
+    { (yyval.n) = ast_uvec4; ;}
+    break;
+
+  case 182:
+
+/* Line 1455 of yacc.c  */
+#line 1115 "glsl_parser.ypp"
+    { (yyval.n) = ast_mat2; ;}
+    break;
+
+  case 183:
+
+/* Line 1455 of yacc.c  */
+#line 1116 "glsl_parser.ypp"
+    { (yyval.n) = ast_mat2x3; ;}
+    break;
+
+  case 184:
+
+/* Line 1455 of yacc.c  */
+#line 1117 "glsl_parser.ypp"
+    { (yyval.n) = ast_mat2x4; ;}
+    break;
+
+  case 185:
+
+/* Line 1455 of yacc.c  */
+#line 1118 "glsl_parser.ypp"
+    { (yyval.n) = ast_mat3x2; ;}
+    break;
+
+  case 186:
+
+/* Line 1455 of yacc.c  */
+#line 1119 "glsl_parser.ypp"
+    { (yyval.n) = ast_mat3; ;}
+    break;
+
+  case 187:
+
+/* Line 1455 of yacc.c  */
+#line 1120 "glsl_parser.ypp"
+    { (yyval.n) = ast_mat3x4; ;}
+    break;
+
+  case 188:
+
+/* Line 1455 of yacc.c  */
+#line 1121 "glsl_parser.ypp"
+    { (yyval.n) = ast_mat4x2; ;}
+    break;
+
+  case 189:
+
+/* Line 1455 of yacc.c  */
+#line 1122 "glsl_parser.ypp"
+    { (yyval.n) = ast_mat4x3; ;}
+    break;
+
+  case 190:
+
+/* Line 1455 of yacc.c  */
+#line 1123 "glsl_parser.ypp"
+    { (yyval.n) = ast_mat4; ;}
+    break;
+
+  case 191:
+
+/* Line 1455 of yacc.c  */
+#line 1124 "glsl_parser.ypp"
+    { (yyval.n) = ast_sampler1d; ;}
+    break;
+
+  case 192:
+
+/* Line 1455 of yacc.c  */
+#line 1125 "glsl_parser.ypp"
+    { (yyval.n) = ast_sampler2d; ;}
+    break;
+
+  case 193:
+
+/* Line 1455 of yacc.c  */
+#line 1126 "glsl_parser.ypp"
+    { (yyval.n) = ast_sampler2drect; ;}
+    break;
+
+  case 194:
+
+/* Line 1455 of yacc.c  */
+#line 1127 "glsl_parser.ypp"
+    { (yyval.n) = ast_sampler3d; ;}
+    break;
+
+  case 195:
+
+/* Line 1455 of yacc.c  */
+#line 1128 "glsl_parser.ypp"
+    { (yyval.n) = ast_samplercube; ;}
+    break;
+
+  case 196:
+
+/* Line 1455 of yacc.c  */
+#line 1129 "glsl_parser.ypp"
+    { (yyval.n) = ast_sampler1dshadow; ;}
+    break;
+
+  case 197:
+
+/* Line 1455 of yacc.c  */
+#line 1130 "glsl_parser.ypp"
+    { (yyval.n) = ast_sampler2dshadow; ;}
+    break;
+
+  case 198:
+
+/* Line 1455 of yacc.c  */
+#line 1131 "glsl_parser.ypp"
+    { (yyval.n) = ast_sampler2drectshadow; ;}
+    break;
+
+  case 199:
+
+/* Line 1455 of yacc.c  */
+#line 1132 "glsl_parser.ypp"
+    { (yyval.n) = ast_samplercubeshadow; ;}
+    break;
+
+  case 200:
+
+/* Line 1455 of yacc.c  */
+#line 1133 "glsl_parser.ypp"
+    { (yyval.n) = ast_sampler1darray; ;}
+    break;
+
+  case 201:
+
+/* Line 1455 of yacc.c  */
+#line 1134 "glsl_parser.ypp"
+    { (yyval.n) = ast_sampler2darray; ;}
+    break;
+
+  case 202:
+
+/* Line 1455 of yacc.c  */
+#line 1135 "glsl_parser.ypp"
+    { (yyval.n) = ast_sampler1darrayshadow; ;}
+    break;
+
+  case 203:
+
+/* Line 1455 of yacc.c  */
+#line 1136 "glsl_parser.ypp"
+    { (yyval.n) = ast_sampler2darrayshadow; ;}
+    break;
+
+  case 204:
+
+/* Line 1455 of yacc.c  */
+#line 1137 "glsl_parser.ypp"
+    { (yyval.n) = ast_isampler1d; ;}
+    break;
+
+  case 205:
+
+/* Line 1455 of yacc.c  */
+#line 1138 "glsl_parser.ypp"
+    { (yyval.n) = ast_isampler2d; ;}
+    break;
+
+  case 206:
+
+/* Line 1455 of yacc.c  */
+#line 1139 "glsl_parser.ypp"
+    { (yyval.n) = ast_isampler3d; ;}
+    break;
+
+  case 207:
+
+/* Line 1455 of yacc.c  */
+#line 1140 "glsl_parser.ypp"
+    { (yyval.n) = ast_isamplercube; ;}
+    break;
+
+  case 208:
+
+/* Line 1455 of yacc.c  */
+#line 1141 "glsl_parser.ypp"
+    { (yyval.n) = ast_isampler1darray; ;}
+    break;
+
+  case 209:
+
+/* Line 1455 of yacc.c  */
+#line 1142 "glsl_parser.ypp"
+    { (yyval.n) = ast_isampler2darray; ;}
+    break;
+
+  case 210:
+
+/* Line 1455 of yacc.c  */
+#line 1143 "glsl_parser.ypp"
+    { (yyval.n) = ast_usampler1d; ;}
+    break;
+
+  case 211:
+
+/* Line 1455 of yacc.c  */
+#line 1144 "glsl_parser.ypp"
+    { (yyval.n) = ast_usampler2d; ;}
+    break;
+
+  case 212:
+
+/* Line 1455 of yacc.c  */
+#line 1145 "glsl_parser.ypp"
+    { (yyval.n) = ast_usampler3d; ;}
+    break;
+
+  case 213:
+
+/* Line 1455 of yacc.c  */
+#line 1146 "glsl_parser.ypp"
+    { (yyval.n) = ast_usamplercube; ;}
+    break;
+
+  case 214:
+
+/* Line 1455 of yacc.c  */
+#line 1147 "glsl_parser.ypp"
+    { (yyval.n) = ast_usampler1darray; ;}
+    break;
+
+  case 215:
+
+/* Line 1455 of yacc.c  */
+#line 1148 "glsl_parser.ypp"
+    { (yyval.n) = ast_usampler2darray; ;}
+    break;
+
+  case 216:
+
+/* Line 1455 of yacc.c  */
+#line 1152 "glsl_parser.ypp"
+    {
+                          if (state->language_version < 130)
+                             _mesa_glsl_error(& (yylsp[(1) - (1)]), state,
+                                              "precision qualifier forbidden "
+                                              "in GLSL %d.%d (1.30 or later "
+                                              "required)\n",
+                                              state->language_version / 100,
+                                              state->language_version % 100);
+
+                          (yyval.n) = ast_precision_high;
+                       ;}
+    break;
+
+  case 217:
+
+/* Line 1455 of yacc.c  */
+#line 1163 "glsl_parser.ypp"
+    {
+                          if (state->language_version < 130)
+                             _mesa_glsl_error(& (yylsp[(1) - (1)]), state,
+                                              "precision qualifier forbidden "
+                                              "in GLSL %d.%d (1.30 or later "
+                                              "required)\n",
+                                              state->language_version / 100,
+                                              state->language_version % 100);
+
+                          (yyval.n) = ast_precision_medium;
+                       ;}
+    break;
+
+  case 218:
+
+/* Line 1455 of yacc.c  */
+#line 1174 "glsl_parser.ypp"
+    {
+                          if (state->language_version < 130)
+                             _mesa_glsl_error(& (yylsp[(1) - (1)]), state,
+                                              "precision qualifier forbidden "
+                                              "in GLSL %d.%d (1.30 or later "
+                                              "required)\n",
+                                              state->language_version / 100,
+                                              state->language_version % 100);
+
+                          (yyval.n) = ast_precision_low;
+                       ;}
+    break;
+
+  case 219:
+
+/* Line 1455 of yacc.c  */
+#line 1189 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.struct_specifier) = new(ctx) ast_struct_specifier((yyvsp[(2) - (5)].identifier), (yyvsp[(4) - (5)].node));
+          (yyval.struct_specifier)->set_location(yylloc);
+       ;}
+    break;
+
+  case 220:
+
+/* Line 1455 of yacc.c  */
+#line 1195 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.struct_specifier) = new(ctx) ast_struct_specifier(NULL, (yyvsp[(3) - (4)].node));
+          (yyval.struct_specifier)->set_location(yylloc);
+       ;}
+    break;
+
+  case 221:
+
+/* Line 1455 of yacc.c  */
+#line 1204 "glsl_parser.ypp"
+    {
+          (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].declarator_list);
+          (yyvsp[(1) - (1)].declarator_list)->link.self_link();
+       ;}
+    break;
+
+  case 222:
+
+/* Line 1455 of yacc.c  */
+#line 1209 "glsl_parser.ypp"
+    {
+          (yyval.node) = (ast_node *) (yyvsp[(1) - (2)].node);
+          (yyval.node)->link.insert_before(& (yyvsp[(2) - (2)].declarator_list)->link);
+       ;}
+    break;
+
+  case 223:
+
+/* Line 1455 of yacc.c  */
+#line 1217 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_fully_specified_type *type = new(ctx) ast_fully_specified_type();
+          type->set_location(yylloc);
+
+          type->specifier = (yyvsp[(1) - (3)].type_specifier);
+          (yyval.declarator_list) = new(ctx) ast_declarator_list(type);
+          (yyval.declarator_list)->set_location(yylloc);
+
+          (yyval.declarator_list)->declarations.push_degenerate_list_at_head(& (yyvsp[(2) - (3)].declaration)->link);
+       ;}
+    break;
+
+  case 224:
+
+/* Line 1455 of yacc.c  */
+#line 1232 "glsl_parser.ypp"
+    {
+          (yyval.declaration) = (yyvsp[(1) - (1)].declaration);
+          (yyvsp[(1) - (1)].declaration)->link.self_link();
+       ;}
+    break;
+
+  case 225:
+
+/* Line 1455 of yacc.c  */
+#line 1237 "glsl_parser.ypp"
+    {
+          (yyval.declaration) = (yyvsp[(1) - (3)].declaration);
+          (yyval.declaration)->link.insert_before(& (yyvsp[(3) - (3)].declaration)->link);
+       ;}
+    break;
+
+  case 226:
+
+/* Line 1455 of yacc.c  */
+#line 1245 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.declaration) = new(ctx) ast_declaration((yyvsp[(1) - (1)].identifier), false, NULL, NULL);
+          (yyval.declaration)->set_location(yylloc);
+       ;}
+    break;
+
+  case 227:
+
+/* Line 1455 of yacc.c  */
+#line 1251 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.declaration) = new(ctx) ast_declaration((yyvsp[(1) - (4)].identifier), true, (yyvsp[(3) - (4)].expression), NULL);
+          (yyval.declaration)->set_location(yylloc);
+       ;}
+    break;
+
+  case 232:
+
+/* Line 1455 of yacc.c  */
+#line 1274 "glsl_parser.ypp"
+    { (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].compound_statement); ;}
+    break;
+
+  case 238:
+
+/* Line 1455 of yacc.c  */
+#line 1286 "glsl_parser.ypp"
+    { (yyval.node) = NULL; ;}
+    break;
+
+  case 239:
+
+/* Line 1455 of yacc.c  */
+#line 1287 "glsl_parser.ypp"
+    { (yyval.node) = NULL; ;}
+    break;
+
+  case 242:
+
+/* Line 1455 of yacc.c  */
+#line 1294 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.compound_statement) = new(ctx) ast_compound_statement(true, NULL);
+          (yyval.compound_statement)->set_location(yylloc);
+       ;}
+    break;
+
+  case 243:
+
+/* Line 1455 of yacc.c  */
+#line 1300 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.compound_statement) = new(ctx) ast_compound_statement(true, (yyvsp[(2) - (3)].node));
+          (yyval.compound_statement)->set_location(yylloc);
+       ;}
+    break;
+
+  case 244:
+
+/* Line 1455 of yacc.c  */
+#line 1308 "glsl_parser.ypp"
+    { (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].compound_statement); ;}
+    break;
+
+  case 246:
+
+/* Line 1455 of yacc.c  */
+#line 1314 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.compound_statement) = new(ctx) ast_compound_statement(false, NULL);
+          (yyval.compound_statement)->set_location(yylloc);
+       ;}
+    break;
+
+  case 247:
+
+/* Line 1455 of yacc.c  */
+#line 1320 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.compound_statement) = new(ctx) ast_compound_statement(false, (yyvsp[(2) - (3)].node));
+          (yyval.compound_statement)->set_location(yylloc);
+       ;}
+    break;
+
+  case 248:
+
+/* Line 1455 of yacc.c  */
+#line 1329 "glsl_parser.ypp"
+    {
+          if ((yyvsp[(1) - (1)].node) == NULL) {
+             _mesa_glsl_error(& (yylsp[(1) - (1)]), state, "<nil> statement\n");
+             assert((yyvsp[(1) - (1)].node) != NULL);
+          }
+
+          (yyval.node) = (yyvsp[(1) - (1)].node);
+          (yyval.node)->link.self_link();
+       ;}
+    break;
+
+  case 249:
+
+/* Line 1455 of yacc.c  */
+#line 1339 "glsl_parser.ypp"
+    {
+          if ((yyvsp[(2) - (2)].node) == NULL) {
+             _mesa_glsl_error(& (yylsp[(2) - (2)]), state, "<nil> statement\n");
+             assert((yyvsp[(2) - (2)].node) != NULL);
+          }
+          (yyval.node) = (yyvsp[(1) - (2)].node);
+          (yyval.node)->link.insert_before(& (yyvsp[(2) - (2)].node)->link);
+       ;}
+    break;
+
+  case 250:
+
+/* Line 1455 of yacc.c  */
+#line 1351 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.node) = new(ctx) ast_expression_statement(NULL);
+          (yyval.node)->set_location(yylloc);
+       ;}
+    break;
+
+  case 251:
+
+/* Line 1455 of yacc.c  */
+#line 1357 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.node) = new(ctx) ast_expression_statement((yyvsp[(1) - (2)].expression));
+          (yyval.node)->set_location(yylloc);
+       ;}
+    break;
+
+  case 252:
+
+/* Line 1455 of yacc.c  */
+#line 1366 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.node) = new(ctx) ast_selection_statement((yyvsp[(3) - (7)].expression), (yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node));
+          (yyval.node)->set_location(yylloc);
+       ;}
+    break;
+
+  case 253:
+
+/* Line 1455 of yacc.c  */
+#line 1375 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.node) = new(ctx) ast_selection_statement((yyvsp[(3) - (5)].expression), (yyvsp[(5) - (5)].node), NULL);
+          (yyval.node)->set_location(yylloc);
+       ;}
+    break;
+
+  case 254:
+
+/* Line 1455 of yacc.c  */
+#line 1381 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.node) = new(ctx) ast_selection_statement((yyvsp[(3) - (5)].expression), (yyvsp[(5) - (5)].node), NULL);
+          (yyval.node)->set_location(yylloc);
+       ;}
+    break;
+
+  case 255:
+
+/* Line 1455 of yacc.c  */
+#line 1387 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.node) = new(ctx) ast_selection_statement((yyvsp[(3) - (7)].expression), (yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node));
+          (yyval.node)->set_location(yylloc);
+       ;}
+    break;
+
+  case 256:
+
+/* Line 1455 of yacc.c  */
+#line 1396 "glsl_parser.ypp"
+    {
+          (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].expression);
+       ;}
+    break;
+
+  case 257:
+
+/* Line 1455 of yacc.c  */
+#line 1400 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (4)].identifier), false, NULL, (yyvsp[(4) - (4)].expression));
+          ast_declarator_list *declarator = new(ctx) ast_declarator_list((yyvsp[(1) - (4)].fully_specified_type));
+          decl->set_location(yylloc);
+          declarator->set_location(yylloc);
+
+          declarator->declarations.push_tail(&decl->link);
+          (yyval.node) = declarator;
+       ;}
+    break;
+
+  case 261:
+
+/* Line 1455 of yacc.c  */
+#line 1423 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.node) = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_while,
+                                                   NULL, (yyvsp[(3) - (5)].node), NULL, (yyvsp[(5) - (5)].node));
+          (yyval.node)->set_location(yylloc);
+       ;}
+    break;
+
+  case 262:
+
+/* Line 1455 of yacc.c  */
+#line 1430 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.node) = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_do_while,
+                                                   NULL, (yyvsp[(5) - (7)].expression), NULL, (yyvsp[(2) - (7)].node));
+          (yyval.node)->set_location(yylloc);
+       ;}
+    break;
+
+  case 263:
+
+/* Line 1455 of yacc.c  */
+#line 1437 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.node) = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_for,
+                                                   (yyvsp[(3) - (6)].node), (yyvsp[(4) - (6)].for_rest_statement).cond, (yyvsp[(4) - (6)].for_rest_statement).rest, (yyvsp[(6) - (6)].node));
+          (yyval.node)->set_location(yylloc);
+       ;}
+    break;
+
+  case 267:
+
+/* Line 1455 of yacc.c  */
+#line 1453 "glsl_parser.ypp"
+    {
+          (yyval.node) = NULL;
+       ;}
+    break;
+
+  case 268:
+
+/* Line 1455 of yacc.c  */
+#line 1460 "glsl_parser.ypp"
+    {
+          (yyval.for_rest_statement).cond = (yyvsp[(1) - (2)].node);
+          (yyval.for_rest_statement).rest = NULL;
+       ;}
+    break;
+
+  case 269:
+
+/* Line 1455 of yacc.c  */
+#line 1465 "glsl_parser.ypp"
+    {
+          (yyval.for_rest_statement).cond = (yyvsp[(1) - (3)].node);
+          (yyval.for_rest_statement).rest = (yyvsp[(3) - (3)].expression);
+       ;}
+    break;
+
+  case 270:
+
+/* Line 1455 of yacc.c  */
+#line 1474 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_continue, NULL);
+          (yyval.node)->set_location(yylloc);
+       ;}
+    break;
+
+  case 271:
+
+/* Line 1455 of yacc.c  */
+#line 1480 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_break, NULL);
+          (yyval.node)->set_location(yylloc);
+       ;}
+    break;
+
+  case 272:
+
+/* Line 1455 of yacc.c  */
+#line 1486 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, NULL);
+          (yyval.node)->set_location(yylloc);
+       ;}
+    break;
+
+  case 273:
+
+/* Line 1455 of yacc.c  */
+#line 1492 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, (yyvsp[(2) - (3)].expression));
+          (yyval.node)->set_location(yylloc);
+       ;}
+    break;
+
+  case 274:
+
+/* Line 1455 of yacc.c  */
+#line 1498 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_discard, NULL);
+          (yyval.node)->set_location(yylloc);
+       ;}
+    break;
+
+  case 275:
+
+/* Line 1455 of yacc.c  */
+#line 1506 "glsl_parser.ypp"
+    { (yyval.node) = (yyvsp[(1) - (1)].function_definition); ;}
+    break;
+
+  case 276:
+
+/* Line 1455 of yacc.c  */
+#line 1507 "glsl_parser.ypp"
+    { (yyval.node) = (yyvsp[(1) - (1)].node); ;}
+    break;
+
+  case 277:
+
+/* Line 1455 of yacc.c  */
+#line 1508 "glsl_parser.ypp"
+    { (yyval.node) = NULL; ;}
+    break;
+
+  case 278:
+
+/* Line 1455 of yacc.c  */
+#line 1513 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          (yyval.function_definition) = new(ctx) ast_function_definition();
+          (yyval.function_definition)->set_location(yylloc);
+          (yyval.function_definition)->prototype = (yyvsp[(1) - (2)].function);
+          (yyval.function_definition)->body = (yyvsp[(2) - (2)].compound_statement);
+       ;}
+    break;
+
+
+
+/* Line 1455 of yacc.c  */
+#line 5052 "glsl_parser.cpp"
+      default: break;
+    }
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+  *++yylsp = yyloc;
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (&yylloc, state, YY_("syntax error"));
+#else
+      {
+       YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+       if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+         {
+           YYSIZE_T yyalloc = 2 * yysize;
+           if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+             yyalloc = YYSTACK_ALLOC_MAXIMUM;
+           if (yymsg != yymsgbuf)
+             YYSTACK_FREE (yymsg);
+           yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+           if (yymsg)
+             yymsg_alloc = yyalloc;
+           else
+             {
+               yymsg = yymsgbuf;
+               yymsg_alloc = sizeof yymsgbuf;
+             }
+         }
+
+       if (0 < yysize && yysize <= yymsg_alloc)
+         {
+           (void) yysyntax_error (yymsg, yystate, yychar);
+           yyerror (&yylloc, state, yymsg);
+         }
+       else
+         {
+           yyerror (&yylloc, state, YY_("syntax error"));
+           if (yysize != 0)
+             goto yyexhaustedlab;
+         }
+      }
+#endif
+    }
+
+  yyerror_range[0] = yylloc;
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+        error, discard it.  */
+
+      if (yychar <= YYEOF)
+       {
+         /* Return failure if at end of input.  */
+         if (yychar == YYEOF)
+           YYABORT;
+       }
+      else
+       {
+         yydestruct ("Error: discarding",
+                     yytoken, &yylval, &yylloc, state);
+         yychar = YYEMPTY;
+       }
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  yyerror_range[0] = yylsp[1-yylen];
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;     /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+       {
+         yyn += YYTERROR;
+         if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+           {
+             yyn = yytable[yyn];
+             if (0 < yyn)
+               break;
+           }
+       }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+       YYABORT;
+
+      yyerror_range[0] = *yylsp;
+      yydestruct ("Error: popping",
+                 yystos[yystate], yyvsp, yylsp, state);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  *++yyvsp = yylval;
+
+  yyerror_range[1] = yylloc;
+  /* Using YYLLOC is tempting, but would change the location of
+     the lookahead.  YYLOC is available though.  */
+  YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
+  *++yylsp = yyloc;
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (&yylloc, state, YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+                yytoken, &yylval, &yylloc, state);
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                 yystos[*yyssp], yyvsp, yylsp, state);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+
diff --git a/src/glsl/glsl_parser.h b/src/glsl/glsl_parser.h
new file mode 100644 (file)
index 0000000..3ed9085
--- /dev/null
@@ -0,0 +1,294 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1.  */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+   
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+   
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     ATTRIBUTE = 258,
+     CONST_TOK = 259,
+     BOOL_TOK = 260,
+     FLOAT_TOK = 261,
+     INT_TOK = 262,
+     UINT_TOK = 263,
+     BREAK = 264,
+     CONTINUE = 265,
+     DO = 266,
+     ELSE = 267,
+     FOR = 268,
+     IF = 269,
+     DISCARD = 270,
+     RETURN = 271,
+     SWITCH = 272,
+     CASE = 273,
+     DEFAULT = 274,
+     BVEC2 = 275,
+     BVEC3 = 276,
+     BVEC4 = 277,
+     IVEC2 = 278,
+     IVEC3 = 279,
+     IVEC4 = 280,
+     UVEC2 = 281,
+     UVEC3 = 282,
+     UVEC4 = 283,
+     VEC2 = 284,
+     VEC3 = 285,
+     VEC4 = 286,
+     CENTROID = 287,
+     IN_TOK = 288,
+     OUT_TOK = 289,
+     INOUT_TOK = 290,
+     UNIFORM = 291,
+     VARYING = 292,
+     NOPERSPECTIVE = 293,
+     FLAT = 294,
+     SMOOTH = 295,
+     MAT2X2 = 296,
+     MAT2X3 = 297,
+     MAT2X4 = 298,
+     MAT3X2 = 299,
+     MAT3X3 = 300,
+     MAT3X4 = 301,
+     MAT4X2 = 302,
+     MAT4X3 = 303,
+     MAT4X4 = 304,
+     SAMPLER1D = 305,
+     SAMPLER2D = 306,
+     SAMPLER3D = 307,
+     SAMPLERCUBE = 308,
+     SAMPLER1DSHADOW = 309,
+     SAMPLER2DSHADOW = 310,
+     SAMPLERCUBESHADOW = 311,
+     SAMPLER1DARRAY = 312,
+     SAMPLER2DARRAY = 313,
+     SAMPLER1DARRAYSHADOW = 314,
+     SAMPLER2DARRAYSHADOW = 315,
+     ISAMPLER1D = 316,
+     ISAMPLER2D = 317,
+     ISAMPLER3D = 318,
+     ISAMPLERCUBE = 319,
+     ISAMPLER1DARRAY = 320,
+     ISAMPLER2DARRAY = 321,
+     USAMPLER1D = 322,
+     USAMPLER2D = 323,
+     USAMPLER3D = 324,
+     USAMPLERCUBE = 325,
+     USAMPLER1DARRAY = 326,
+     USAMPLER2DARRAY = 327,
+     STRUCT = 328,
+     VOID_TOK = 329,
+     WHILE = 330,
+     IDENTIFIER = 331,
+     FLOATCONSTANT = 332,
+     INTCONSTANT = 333,
+     UINTCONSTANT = 334,
+     BOOLCONSTANT = 335,
+     FIELD_SELECTION = 336,
+     LEFT_OP = 337,
+     RIGHT_OP = 338,
+     INC_OP = 339,
+     DEC_OP = 340,
+     LE_OP = 341,
+     GE_OP = 342,
+     EQ_OP = 343,
+     NE_OP = 344,
+     AND_OP = 345,
+     OR_OP = 346,
+     XOR_OP = 347,
+     MUL_ASSIGN = 348,
+     DIV_ASSIGN = 349,
+     ADD_ASSIGN = 350,
+     MOD_ASSIGN = 351,
+     LEFT_ASSIGN = 352,
+     RIGHT_ASSIGN = 353,
+     AND_ASSIGN = 354,
+     XOR_ASSIGN = 355,
+     OR_ASSIGN = 356,
+     SUB_ASSIGN = 357,
+     INVARIANT = 358,
+     LOWP = 359,
+     MEDIUMP = 360,
+     HIGHP = 361,
+     SUPERP = 362,
+     PRECISION = 363,
+     VERSION = 364,
+     EXTENSION = 365,
+     LINE = 366,
+     COLON = 367,
+     EOL = 368,
+     INTERFACE = 369,
+     OUTPUT = 370,
+     PRAGMA_DEBUG_ON = 371,
+     PRAGMA_DEBUG_OFF = 372,
+     PRAGMA_OPTIMIZE_ON = 373,
+     PRAGMA_OPTIMIZE_OFF = 374,
+     LAYOUT_TOK = 375,
+     ASM = 376,
+     CLASS = 377,
+     UNION = 378,
+     ENUM = 379,
+     TYPEDEF = 380,
+     TEMPLATE = 381,
+     THIS = 382,
+     PACKED_TOK = 383,
+     GOTO = 384,
+     INLINE_TOK = 385,
+     NOINLINE = 386,
+     VOLATILE = 387,
+     PUBLIC_TOK = 388,
+     STATIC = 389,
+     EXTERN = 390,
+     EXTERNAL = 391,
+     LONG_TOK = 392,
+     SHORT_TOK = 393,
+     DOUBLE_TOK = 394,
+     HALF = 395,
+     FIXED_TOK = 396,
+     UNSIGNED = 397,
+     INPUT_TOK = 398,
+     OUPTUT = 399,
+     HVEC2 = 400,
+     HVEC3 = 401,
+     HVEC4 = 402,
+     DVEC2 = 403,
+     DVEC3 = 404,
+     DVEC4 = 405,
+     FVEC2 = 406,
+     FVEC3 = 407,
+     FVEC4 = 408,
+     SAMPLER2DRECT = 409,
+     SAMPLER3DRECT = 410,
+     SAMPLER2DRECTSHADOW = 411,
+     SIZEOF = 412,
+     CAST = 413,
+     NAMESPACE = 414,
+     USING = 415,
+     ERROR_TOK = 416,
+     COMMON = 417,
+     PARTITION = 418,
+     ACTIVE = 419,
+     SAMPLERBUFFER = 420,
+     FILTER = 421,
+     IMAGE1D = 422,
+     IMAGE2D = 423,
+     IMAGE3D = 424,
+     IMAGECUBE = 425,
+     IMAGE1DARRAY = 426,
+     IMAGE2DARRAY = 427,
+     IIMAGE1D = 428,
+     IIMAGE2D = 429,
+     IIMAGE3D = 430,
+     IIMAGECUBE = 431,
+     IIMAGE1DARRAY = 432,
+     IIMAGE2DARRAY = 433,
+     UIMAGE1D = 434,
+     UIMAGE2D = 435,
+     UIMAGE3D = 436,
+     UIMAGECUBE = 437,
+     UIMAGE1DARRAY = 438,
+     UIMAGE2DARRAY = 439,
+     IMAGE1DSHADOW = 440,
+     IMAGE2DSHADOW = 441,
+     IMAGEBUFFER = 442,
+     IIMAGEBUFFER = 443,
+     UIMAGEBUFFER = 444,
+     ROW_MAJOR = 445
+   };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 1676 of yacc.c  */
+#line 52 "glsl_parser.ypp"
+
+   int n;
+   float real;
+   char *identifier;
+
+   union {
+      struct ast_type_qualifier q;
+      unsigned i;
+   } type_qualifier;
+
+   ast_node *node;
+   ast_type_specifier *type_specifier;
+   ast_fully_specified_type *fully_specified_type;
+   ast_function *function;
+   ast_parameter_declarator *parameter_declarator;
+   ast_function_definition *function_definition;
+   ast_compound_statement *compound_statement;
+   ast_expression *expression;
+   ast_declarator_list *declarator_list;
+   ast_struct_specifier *struct_specifier;
+   ast_declaration *declaration;
+
+   struct {
+      ast_node *cond;
+      ast_expression *rest;
+   } for_rest_statement;
+
+
+
+/* Line 1676 of yacc.c  */
+#line 272 "glsl_parser.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+
diff --git a/src/glsl/glsl_parser.ypp b/src/glsl/glsl_parser.ypp
new file mode 100644 (file)
index 0000000..6d99c52
--- /dev/null
@@ -0,0 +1,1520 @@
+%{
+/*
+ * Copyright Â© 2008, 2009 Intel Corporation
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <assert.h>
+    
+#include "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_types.h"
+
+#define YYLEX_PARAM state->scanner
+
+%}
+
+%pure-parser
+%error-verbose
+
+%locations
+%initial-action {
+   @$.first_line = 1;
+   @$.first_column = 1;
+   @$.last_line = 1;
+   @$.last_column = 1;
+   @$.source = 0;
+}
+
+%lex-param   {void *scanner}
+%parse-param {struct _mesa_glsl_parse_state *state}
+
+%union {
+   int n;
+   float real;
+   char *identifier;
+
+   union {
+      struct ast_type_qualifier q;
+      unsigned i;
+   } type_qualifier;
+
+   ast_node *node;
+   ast_type_specifier *type_specifier;
+   ast_fully_specified_type *fully_specified_type;
+   ast_function *function;
+   ast_parameter_declarator *parameter_declarator;
+   ast_function_definition *function_definition;
+   ast_compound_statement *compound_statement;
+   ast_expression *expression;
+   ast_declarator_list *declarator_list;
+   ast_struct_specifier *struct_specifier;
+   ast_declaration *declaration;
+
+   struct {
+      ast_node *cond;
+      ast_expression *rest;
+   } for_rest_statement;
+}
+
+%token ATTRIBUTE CONST_TOK BOOL_TOK FLOAT_TOK INT_TOK UINT_TOK
+%token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
+%token BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 UVEC2 UVEC3 UVEC4 VEC2 VEC3 VEC4
+%token CENTROID IN_TOK OUT_TOK INOUT_TOK UNIFORM VARYING
+%token NOPERSPECTIVE FLAT SMOOTH
+%token MAT2X2 MAT2X3 MAT2X4
+%token MAT3X2 MAT3X3 MAT3X4
+%token MAT4X2 MAT4X3 MAT4X4
+%token SAMPLER1D SAMPLER2D SAMPLER3D SAMPLERCUBE SAMPLER1DSHADOW SAMPLER2DSHADOW
+%token SAMPLERCUBESHADOW SAMPLER1DARRAY SAMPLER2DARRAY SAMPLER1DARRAYSHADOW
+%token SAMPLER2DARRAYSHADOW ISAMPLER1D ISAMPLER2D ISAMPLER3D ISAMPLERCUBE
+%token ISAMPLER1DARRAY ISAMPLER2DARRAY USAMPLER1D USAMPLER2D USAMPLER3D
+%token USAMPLERCUBE USAMPLER1DARRAY USAMPLER2DARRAY
+%token STRUCT VOID_TOK WHILE
+%token <identifier> IDENTIFIER
+%token <real> FLOATCONSTANT
+%token <n> INTCONSTANT UINTCONSTANT BOOLCONSTANT
+%token <identifier> FIELD_SELECTION
+%token LEFT_OP RIGHT_OP
+%token INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
+%token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
+%token MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
+%token SUB_ASSIGN
+%token INVARIANT
+%token LOWP MEDIUMP HIGHP SUPERP PRECISION
+
+%token VERSION EXTENSION LINE COLON EOL INTERFACE OUTPUT
+%token PRAGMA_DEBUG_ON PRAGMA_DEBUG_OFF
+%token PRAGMA_OPTIMIZE_ON PRAGMA_OPTIMIZE_OFF
+%token LAYOUT_TOK
+
+   /* Reserved words that are not actually used in the grammar.
+    */
+%token ASM CLASS UNION ENUM TYPEDEF TEMPLATE THIS PACKED_TOK GOTO
+%token INLINE_TOK NOINLINE VOLATILE PUBLIC_TOK STATIC EXTERN EXTERNAL
+%token LONG_TOK SHORT_TOK DOUBLE_TOK HALF FIXED_TOK UNSIGNED INPUT_TOK OUPTUT
+%token HVEC2 HVEC3 HVEC4 DVEC2 DVEC3 DVEC4 FVEC2 FVEC3 FVEC4
+%token SAMPLER2DRECT SAMPLER3DRECT SAMPLER2DRECTSHADOW
+%token SIZEOF CAST NAMESPACE USING
+
+%token ERROR_TOK
+
+%token COMMON PARTITION ACTIVE SAMPLERBUFFER FILTER
+%token  IMAGE1D  IMAGE2D  IMAGE3D  IMAGECUBE  IMAGE1DARRAY  IMAGE2DARRAY
+%token IIMAGE1D IIMAGE2D IIMAGE3D IIMAGECUBE IIMAGE1DARRAY IIMAGE2DARRAY
+%token UIMAGE1D UIMAGE2D UIMAGE3D UIMAGECUBE UIMAGE1DARRAY UIMAGE2DARRAY
+%token IMAGE1DSHADOW IMAGE2DSHADOW IMAGEBUFFER IIMAGEBUFFER UIMAGEBUFFER
+%token ROW_MAJOR
+
+%type <identifier> variable_identifier
+%type <node> statement
+%type <node> statement_list
+%type <node> simple_statement
+%type <node> statement_matched
+%type <node> statement_unmatched
+%type <n> precision_qualifier
+%type <type_qualifier> type_qualifier
+%type <type_qualifier> storage_qualifier
+%type <type_qualifier> interpolation_qualifier
+%type <type_qualifier> opt_layout_qualifier layout_qualifier
+%type <type_qualifier> layout_qualifier_id_list layout_qualifier_id
+%type <type_specifier> type_specifier
+%type <type_specifier> type_specifier_no_prec
+%type <type_specifier> type_specifier_nonarray
+%type <n> basic_type_specifier_nonarray
+%type <fully_specified_type> fully_specified_type
+%type <function> function_prototype
+%type <function> function_header
+%type <function> function_header_with_parameters
+%type <function> function_declarator
+%type <parameter_declarator> parameter_declarator
+%type <parameter_declarator> parameter_declaration
+%type <type_qualifier> parameter_qualifier
+%type <type_qualifier> parameter_type_qualifier
+%type <type_specifier> parameter_type_specifier
+%type <function_definition> function_definition
+%type <compound_statement> compound_statement_no_new_scope
+%type <compound_statement> compound_statement
+%type <node> statement_no_new_scope
+%type <node> expression_statement
+%type <expression> expression
+%type <expression> primary_expression
+%type <expression> assignment_expression
+%type <expression> conditional_expression
+%type <expression> logical_or_expression
+%type <expression> logical_xor_expression
+%type <expression> logical_and_expression
+%type <expression> inclusive_or_expression
+%type <expression> exclusive_or_expression
+%type <expression> and_expression
+%type <expression> equality_expression
+%type <expression> relational_expression
+%type <expression> shift_expression
+%type <expression> additive_expression
+%type <expression> multiplicative_expression
+%type <expression> unary_expression
+%type <expression> constant_expression
+%type <expression> integer_expression
+%type <expression> postfix_expression
+%type <expression> function_call_header_with_parameters
+%type <expression> function_call_header_no_parameters
+%type <expression> function_call_header
+%type <expression> function_call_generic
+%type <expression> function_call_or_method
+%type <expression> function_call
+%type <n> assignment_operator
+%type <n> unary_operator
+%type <expression> function_identifier
+%type <node> external_declaration
+%type <declarator_list> init_declarator_list
+%type <declarator_list> single_declaration
+%type <expression> initializer
+%type <node> declaration
+%type <node> declaration_statement
+%type <node> jump_statement
+%type <struct_specifier> struct_specifier
+%type <node> struct_declaration_list
+%type <declarator_list> struct_declaration
+%type <declaration> struct_declarator
+%type <declaration> struct_declarator_list
+%type <node> selection_statement_matched
+%type <node> selection_statement_unmatched
+%type <node> iteration_statement
+%type <node> condition
+%type <node> conditionopt
+%type <node> for_init_statement
+%type <for_rest_statement> for_rest_statement
+%%
+
+translation_unit: 
+       version_statement extension_statement_list
+       {
+          _mesa_glsl_initialize_types(state);
+       }
+       external_declaration_list
+       ;
+
+version_statement:
+       /* blank - no #version specified */
+       {
+          state->language_version = 110;
+          state->symbols->language_version = 110;
+       }
+       | VERSION INTCONSTANT EOL
+       {
+          switch ($2) {
+          case 110:
+          case 120:
+          case 130:
+             /* FINISHME: Check against implementation support versions. */
+             state->language_version = $2;
+             state->symbols->language_version = $2;
+             break;
+          default:
+             _mesa_glsl_error(& @2, state, "Shading language version"
+                              "%u is not supported\n", $2);
+             break;
+          }
+       }
+       ;
+
+pragma_statement:
+       PRAGMA_DEBUG_ON EOL
+       | PRAGMA_DEBUG_OFF EOL
+       | PRAGMA_OPTIMIZE_ON EOL
+       | PRAGMA_OPTIMIZE_OFF EOL
+       ;
+
+extension_statement_list:
+
+       | extension_statement_list extension_statement
+       ;
+
+extension_statement:
+       EXTENSION IDENTIFIER COLON IDENTIFIER EOL
+       {
+          if (!_mesa_glsl_process_extension($2, & @2, $4, & @4, state)) {
+             YYERROR;
+          }
+       }
+       ;
+
+external_declaration_list:
+       external_declaration
+       {
+          /* FINISHME: The NULL test is only required because 'precision'
+           * FINISHME: statements are not yet supported.
+           */
+          if ($1 != NULL)
+             state->translation_unit.push_tail(& $1->link);
+       }
+       | external_declaration_list external_declaration
+       {
+          /* FINISHME: The NULL test is only required because 'precision'
+           * FINISHME: statements are not yet supported.
+           */
+          if ($2 != NULL)
+             state->translation_unit.push_tail(& $2->link);
+       }
+       ;
+
+variable_identifier:
+       IDENTIFIER
+       ;
+
+primary_expression:
+       variable_identifier
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression(ast_identifier, NULL, NULL, NULL);
+          $$->set_location(yylloc);
+          $$->primary_expression.identifier = $1;
+       }
+       | INTCONSTANT
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression(ast_int_constant, NULL, NULL, NULL);
+          $$->set_location(yylloc);
+          $$->primary_expression.int_constant = $1;
+       }
+       | UINTCONSTANT
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression(ast_uint_constant, NULL, NULL, NULL);
+          $$->set_location(yylloc);
+          $$->primary_expression.uint_constant = $1;
+       }
+       | FLOATCONSTANT
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression(ast_float_constant, NULL, NULL, NULL);
+          $$->set_location(yylloc);
+          $$->primary_expression.float_constant = $1;
+       }
+       | BOOLCONSTANT
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression(ast_bool_constant, NULL, NULL, NULL);
+          $$->set_location(yylloc);
+          $$->primary_expression.bool_constant = $1;
+       }
+       | '(' expression ')'
+       {
+          $$ = $2;
+       }
+       ;
+
+postfix_expression:
+       primary_expression
+       | postfix_expression '[' integer_expression ']'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression(ast_array_index, $1, $3, NULL);
+          $$->set_location(yylloc);
+       }
+       | function_call
+       {
+          $$ = $1;
+       }
+       | postfix_expression '.' IDENTIFIER
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression(ast_field_selection, $1, NULL, NULL);
+          $$->set_location(yylloc);
+          $$->primary_expression.identifier = $3;
+       }
+       | postfix_expression INC_OP
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression(ast_post_inc, $1, NULL, NULL);
+          $$->set_location(yylloc);
+       }
+       | postfix_expression DEC_OP
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression(ast_post_dec, $1, NULL, NULL);
+          $$->set_location(yylloc);
+       }
+       ;
+
+integer_expression:
+       expression
+       ;
+
+function_call:
+       function_call_or_method
+       ;
+
+function_call_or_method:
+       function_call_generic
+       | postfix_expression '.' function_call_generic
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression(ast_field_selection, $1, $3, NULL);
+          $$->set_location(yylloc);
+       }
+       ;
+
+function_call_generic:
+       function_call_header_with_parameters ')'
+       | function_call_header_no_parameters ')'
+       ;
+
+function_call_header_no_parameters:
+       function_call_header VOID_TOK
+       | function_call_header
+       ;
+
+function_call_header_with_parameters:
+       function_call_header assignment_expression
+       {
+          $$ = $1;
+          $$->set_location(yylloc);
+          $$->expressions.push_tail(& $2->link);
+       }
+       | function_call_header_with_parameters ',' assignment_expression
+       {
+          $$ = $1;
+          $$->set_location(yylloc);
+          $$->expressions.push_tail(& $3->link);
+       }
+       ;
+
+       // Grammar Note: Constructors look like functions, but lexical 
+       // analysis recognized most of them as keywords. They are now
+       // recognized through "type_specifier".
+function_call_header:
+       function_identifier '('
+       ;
+
+function_identifier:
+       type_specifier
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_function_expression($1);
+          $$->set_location(yylloc);
+       }
+       | IDENTIFIER
+       {
+          void *ctx = state;
+          ast_expression *callee = new(ctx) ast_expression($1);
+          $$ = new(ctx) ast_function_expression(callee);
+          $$->set_location(yylloc);
+       }
+       | FIELD_SELECTION
+       {
+          void *ctx = state;
+          ast_expression *callee = new(ctx) ast_expression($1);
+          $$ = new(ctx) ast_function_expression(callee);
+          $$->set_location(yylloc);
+       }
+       ;
+
+       // Grammar Note: No traditional style type casts.
+unary_expression:
+       postfix_expression
+       | INC_OP unary_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression(ast_pre_inc, $2, NULL, NULL);
+          $$->set_location(yylloc);
+       }
+       | DEC_OP unary_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression(ast_pre_dec, $2, NULL, NULL);
+          $$->set_location(yylloc);
+       }
+       | unary_operator unary_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression($1, $2, NULL, NULL);
+          $$->set_location(yylloc);
+       }
+       ;
+
+       // Grammar Note: No '*' or '&' unary ops. Pointers are not supported.
+unary_operator:
+       '+'     { $$ = ast_plus; }
+       | '-'   { $$ = ast_neg; }
+       | '!'   { $$ = ast_logic_not; }
+       | '~'   { $$ = ast_bit_not; }
+       ;
+
+multiplicative_expression:
+       unary_expression
+       | multiplicative_expression '*' unary_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_mul, $1, $3);
+          $$->set_location(yylloc);
+       }
+       | multiplicative_expression '/' unary_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_div, $1, $3);
+          $$->set_location(yylloc);
+       }
+       | multiplicative_expression '%' unary_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_mod, $1, $3);
+          $$->set_location(yylloc);
+       }
+       ;
+
+additive_expression:
+       multiplicative_expression
+       | additive_expression '+' multiplicative_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_add, $1, $3);
+          $$->set_location(yylloc);
+       }
+       | additive_expression '-' multiplicative_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_sub, $1, $3);
+          $$->set_location(yylloc);
+       }
+       ;
+
+shift_expression:
+       additive_expression
+       | shift_expression LEFT_OP additive_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_lshift, $1, $3);
+          $$->set_location(yylloc);
+       }
+       | shift_expression RIGHT_OP additive_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_rshift, $1, $3);
+          $$->set_location(yylloc);
+       }
+       ;
+
+relational_expression:
+       shift_expression
+       | relational_expression '<' shift_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_less, $1, $3);
+          $$->set_location(yylloc);
+       }
+       | relational_expression '>' shift_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_greater, $1, $3);
+          $$->set_location(yylloc);
+       }
+       | relational_expression LE_OP shift_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_lequal, $1, $3);
+          $$->set_location(yylloc);
+       }
+       | relational_expression GE_OP shift_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_gequal, $1, $3);
+          $$->set_location(yylloc);
+       }
+       ;
+
+equality_expression:
+       relational_expression
+       | equality_expression EQ_OP relational_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_equal, $1, $3);
+          $$->set_location(yylloc);
+       }
+       | equality_expression NE_OP relational_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_nequal, $1, $3);
+          $$->set_location(yylloc);
+       }
+       ;
+
+and_expression:
+       equality_expression
+       | and_expression '&' equality_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_bit_or, $1, $3);
+          $$->set_location(yylloc);
+       }
+       ;
+
+exclusive_or_expression:
+       and_expression
+       | exclusive_or_expression '^' and_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_bit_xor, $1, $3);
+          $$->set_location(yylloc);
+       }
+       ;
+
+inclusive_or_expression:
+       exclusive_or_expression
+       | inclusive_or_expression '|' exclusive_or_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_bit_or, $1, $3);
+          $$->set_location(yylloc);
+       }
+       ;
+
+logical_and_expression:
+       inclusive_or_expression
+       | logical_and_expression AND_OP inclusive_or_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_logic_and, $1, $3);
+          $$->set_location(yylloc);
+       }
+       ;
+
+logical_xor_expression:
+       logical_and_expression
+       | logical_xor_expression XOR_OP logical_and_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_logic_xor, $1, $3);
+          $$->set_location(yylloc);
+       }
+       ;
+
+logical_or_expression:
+       logical_xor_expression
+       | logical_or_expression OR_OP logical_xor_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_bin(ast_logic_or, $1, $3);
+          $$->set_location(yylloc);
+       }
+       ;
+
+conditional_expression:
+       logical_or_expression
+       | logical_or_expression '?' expression ':' assignment_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression(ast_conditional, $1, $3, $5);
+          $$->set_location(yylloc);
+       }
+       ;
+
+assignment_expression:
+       conditional_expression
+       | unary_expression assignment_operator assignment_expression
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression($2, $1, $3, NULL);
+          $$->set_location(yylloc);
+       }
+       ;
+
+assignment_operator:
+       '='             { $$ = ast_assign; }
+       | MUL_ASSIGN    { $$ = ast_mul_assign; }
+       | DIV_ASSIGN    { $$ = ast_div_assign; }
+       | MOD_ASSIGN    { $$ = ast_mod_assign; }
+       | ADD_ASSIGN    { $$ = ast_add_assign; }
+       | SUB_ASSIGN    { $$ = ast_sub_assign; }
+       | LEFT_ASSIGN   { $$ = ast_ls_assign; }
+       | RIGHT_ASSIGN  { $$ = ast_rs_assign; }
+       | AND_ASSIGN    { $$ = ast_and_assign; }
+       | XOR_ASSIGN    { $$ = ast_xor_assign; }
+       | OR_ASSIGN     { $$ = ast_or_assign; }
+       ;
+
+expression:
+       assignment_expression
+       {
+          $$ = $1;
+       }
+       | expression ',' assignment_expression
+       {
+          void *ctx = state;
+          if ($1->oper != ast_sequence) {
+             $$ = new(ctx) ast_expression(ast_sequence, NULL, NULL, NULL);
+             $$->set_location(yylloc);
+             $$->expressions.push_tail(& $1->link);
+          } else {
+             $$ = $1;
+          }
+
+          $$->expressions.push_tail(& $3->link);
+       }
+       ;
+
+constant_expression:
+       conditional_expression
+       ;
+
+declaration:
+       function_prototype ';'
+       {
+          $$ = $1;
+       }
+       | init_declarator_list ';'
+       {
+          $$ = $1;
+       }
+       | PRECISION precision_qualifier type_specifier_no_prec ';'
+       {
+          if (($3->type_specifier != ast_float)
+              && ($3->type_specifier != ast_int)) {
+             _mesa_glsl_error(& @3, state, "global precision qualifier can "
+                              "only be applied to `int' or `float'\n");
+             YYERROR;
+          }
+
+          $$ = NULL; /* FINISHME */
+       }
+       ;
+
+function_prototype:
+       function_declarator ')'
+       ;
+
+function_declarator:
+       function_header
+       | function_header_with_parameters
+       ;
+
+function_header_with_parameters:
+       function_header parameter_declaration
+       {
+          $$ = $1;
+          $$->parameters.push_tail(& $2->link);
+       }
+       | function_header_with_parameters ',' parameter_declaration
+       {
+          $$ = $1;
+          $$->parameters.push_tail(& $3->link);
+       }
+       ;
+
+function_header:
+       fully_specified_type IDENTIFIER '('
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_function();
+          $$->set_location(yylloc);
+          $$->return_type = $1;
+          $$->identifier = $2;
+       }
+       ;
+
+parameter_declarator:
+       type_specifier IDENTIFIER
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_parameter_declarator();
+          $$->set_location(yylloc);
+          $$->type = new(ctx) ast_fully_specified_type();
+          $$->type->set_location(yylloc);
+          $$->type->specifier = $1;
+          $$->identifier = $2;
+       }
+       | type_specifier IDENTIFIER '[' constant_expression ']'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_parameter_declarator();
+          $$->set_location(yylloc);
+          $$->type = new(ctx) ast_fully_specified_type();
+          $$->type->set_location(yylloc);
+          $$->type->specifier = $1;
+          $$->identifier = $2;
+          $$->is_array = true;
+          $$->array_size = $4;
+       }
+       ;
+
+parameter_declaration:
+       parameter_type_qualifier parameter_qualifier parameter_declarator
+       {
+          $1.i |= $2.i;
+
+          $$ = $3;
+          $$->type->qualifier = $1.q;
+       }
+       | parameter_qualifier parameter_declarator
+       {
+          $$ = $2;
+          $$->type->qualifier = $1.q;
+       }
+       | parameter_type_qualifier parameter_qualifier parameter_type_specifier
+       {
+          void *ctx = state;
+          $1.i |= $2.i;
+
+          $$ = new(ctx) ast_parameter_declarator();
+          $$->set_location(yylloc);
+          $$->type = new(ctx) ast_fully_specified_type();
+          $$->type->qualifier = $1.q;
+          $$->type->specifier = $3;
+       }
+       | parameter_qualifier parameter_type_specifier
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_parameter_declarator();
+          $$->set_location(yylloc);
+          $$->type = new(ctx) ast_fully_specified_type();
+          $$->type->qualifier = $1.q;
+          $$->type->specifier = $2;
+       }
+       ;
+
+parameter_qualifier:
+       /* empty */     { $$.i = 0; }
+       | IN_TOK        { $$.i = 0; $$.q.in = 1; }
+       | OUT_TOK       { $$.i = 0; $$.q.out = 1; }
+       | INOUT_TOK     { $$.i = 0; $$.q.in = 1; $$.q.out = 1; }
+       ;
+
+parameter_type_specifier:
+       type_specifier
+       ;
+
+init_declarator_list:
+       single_declaration
+       | init_declarator_list ',' IDENTIFIER
+       {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration($3, false, NULL, NULL);
+          decl->set_location(yylloc);
+
+          $$ = $1;
+          $$->declarations.push_tail(&decl->link);
+       }
+       | init_declarator_list ',' IDENTIFIER '[' ']'
+       {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, NULL);
+          decl->set_location(yylloc);
+
+          $$ = $1;
+          $$->declarations.push_tail(&decl->link);
+       }
+       | init_declarator_list ',' IDENTIFIER '[' constant_expression ']'
+       {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, NULL);
+          decl->set_location(yylloc);
+
+          $$ = $1;
+          $$->declarations.push_tail(&decl->link);
+       }
+       | init_declarator_list ',' IDENTIFIER '[' ']' '=' initializer
+       {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, $7);
+          decl->set_location(yylloc);
+
+          $$ = $1;
+          $$->declarations.push_tail(&decl->link);
+       }
+       | init_declarator_list ',' IDENTIFIER '[' constant_expression ']' '=' initializer
+       {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, $8);
+          decl->set_location(yylloc);
+
+          $$ = $1;
+          $$->declarations.push_tail(&decl->link);
+       }
+       | init_declarator_list ',' IDENTIFIER '=' initializer
+       {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration($3, false, NULL, $5);
+          decl->set_location(yylloc);
+
+          $$ = $1;
+          $$->declarations.push_tail(&decl->link);
+       }
+       ;
+
+       // Grammar Note: No 'enum', or 'typedef'.
+single_declaration:
+       fully_specified_type
+       {
+          void *ctx = state;
+          if ($1->specifier->type_specifier != ast_struct) {
+             _mesa_glsl_error(& @1, state, "empty declaration list\n");
+             YYERROR;
+          } else {
+             $$ = new(ctx) ast_declarator_list($1);
+             $$->set_location(yylloc);
+          }
+       }
+       | fully_specified_type IDENTIFIER
+       {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, NULL);
+
+          $$ = new(ctx) ast_declarator_list($1);
+          $$->set_location(yylloc);
+          $$->declarations.push_tail(&decl->link);
+       }
+       | fully_specified_type IDENTIFIER '[' ']'
+       {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, NULL);
+
+          $$ = new(ctx) ast_declarator_list($1);
+          $$->set_location(yylloc);
+          $$->declarations.push_tail(&decl->link);
+       }
+       | fully_specified_type IDENTIFIER '[' constant_expression ']'
+       {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, NULL);
+
+          $$ = new(ctx) ast_declarator_list($1);
+          $$->set_location(yylloc);
+          $$->declarations.push_tail(&decl->link);
+       }
+       | fully_specified_type IDENTIFIER '[' ']' '=' initializer
+       {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, $6);
+
+          $$ = new(ctx) ast_declarator_list($1);
+          $$->set_location(yylloc);
+          $$->declarations.push_tail(&decl->link);
+       }
+       | fully_specified_type IDENTIFIER '[' constant_expression ']' '=' initializer
+       {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, $7);
+
+          $$ = new(ctx) ast_declarator_list($1);
+          $$->set_location(yylloc);
+          $$->declarations.push_tail(&decl->link);
+       }
+       | fully_specified_type IDENTIFIER '=' initializer
+       {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, $4);
+
+          $$ = new(ctx) ast_declarator_list($1);
+          $$->set_location(yylloc);
+          $$->declarations.push_tail(&decl->link);
+       }
+       | INVARIANT IDENTIFIER // Vertex only.
+       {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, NULL);
+
+          $$ = new(ctx) ast_declarator_list(NULL);
+          $$->set_location(yylloc);
+          $$->invariant = true;
+
+          $$->declarations.push_tail(&decl->link);
+       }
+       ;
+
+fully_specified_type:
+       type_specifier
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_fully_specified_type();
+          $$->set_location(yylloc);
+          $$->specifier = $1;
+       }
+       | type_qualifier type_specifier
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_fully_specified_type();
+          $$->set_location(yylloc);
+          $$->qualifier = $1.q;
+          $$->specifier = $2;
+       }
+       ;
+
+opt_layout_qualifier:
+       { $$.i = 0; }
+       |  layout_qualifier
+       ;
+
+layout_qualifier:
+       LAYOUT_TOK '(' layout_qualifier_id_list ')'
+       {
+         $$ = $3;
+       }
+       ;
+
+layout_qualifier_id_list:
+       layout_qualifier_id
+       | layout_qualifier_id_list ',' layout_qualifier_id
+       {
+          $$.i = $1.i | $3.i;
+       }
+       ;
+
+layout_qualifier_id:
+       IDENTIFIER
+       {
+          $$.i = 0;
+
+          if (state->ARB_fragment_coord_conventions_enable) {
+             bool got_one = false;
+
+             if (strcmp($1, "origin_upper_left") == 0) {
+                got_one = true;
+                $$.q.origin_upper_left = 1;
+             } else if (strcmp($1, "pixel_center_integer") == 0) {
+                got_one = true;
+                $$.q.pixel_center_integer = 1;
+             }
+
+             if (state->ARB_fragment_coord_conventions_warn && got_one) {
+                _mesa_glsl_warning(& @1, state,
+                                   "GL_ARB_fragment_coord_conventions layout "
+                                   "identifier `%s' used\n", $1);
+             }
+          }
+
+          /* If the identifier didn't match any known layout identifiers,
+           * emit an error.
+           */
+          if ($$.i == 0) {
+             _mesa_glsl_error(& @1, state, "unrecognized layout identifier "
+                              "`%s'\n", $1);
+             YYERROR;
+          }
+       }
+       ;
+
+interpolation_qualifier:
+       SMOOTH          { $$.i = 0; $$.q.smooth = 1; }
+       | FLAT          { $$.i = 0; $$.q.flat = 1; }
+       | NOPERSPECTIVE { $$.i = 0; $$.q.noperspective = 1; }
+       ;
+
+parameter_type_qualifier:
+       CONST_TOK       { $$.i = 0; $$.q.constant = 1; }
+       ;
+
+type_qualifier:
+       storage_qualifier
+       | interpolation_qualifier type_qualifier
+       {
+          $$.i = $1.i | $2.i;
+       }
+       | INVARIANT type_qualifier
+       {
+          $$ = $2;
+          $$.q.invariant = 1;
+       }
+       ;
+
+storage_qualifier:
+       CONST_TOK               { $$.i = 0; $$.q.constant = 1; }
+       | ATTRIBUTE             { $$.i = 0; $$.q.attribute = 1; }
+       | opt_layout_qualifier VARYING  { $$.i = $1.i; $$.q.varying = 1; }
+       | CENTROID VARYING      { $$.i = 0; $$.q.centroid = 1; $$.q.varying = 1; }
+       | opt_layout_qualifier IN_TOK   { $$.i = 0; $$.q.in = 1; }
+       | OUT_TOK               { $$.i = 0; $$.q.out = 1; }
+       | CENTROID IN_TOK       { $$.i = 0; $$.q.centroid = 1; $$.q.in = 1; }
+       | CENTROID OUT_TOK      { $$.i = 0; $$.q.centroid = 1; $$.q.out = 1; }
+       | UNIFORM               { $$.i = 0; $$.q.uniform = 1; }
+       ;
+
+type_specifier:
+       type_specifier_no_prec
+       | precision_qualifier type_specifier_no_prec
+       {
+          $$ = $2;
+          $$->precision = $1;
+       }
+       ;
+
+type_specifier_no_prec:
+       type_specifier_nonarray
+       | type_specifier_nonarray '[' ']'
+       {
+          $$ = $1;
+          $$->is_array = true;
+          $$->array_size = NULL;
+       }
+       | type_specifier_nonarray '[' constant_expression ']'
+       {
+          $$ = $1;
+          $$->is_array = true;
+          $$->array_size = $3;
+       }
+       ;
+
+type_specifier_nonarray:
+       basic_type_specifier_nonarray
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_type_specifier($1);
+          $$->set_location(yylloc);
+       }
+       | struct_specifier
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_type_specifier($1);
+          $$->set_location(yylloc);
+       }
+       | IDENTIFIER
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_type_specifier($1);
+          $$->set_location(yylloc);
+       }
+       ;
+
+basic_type_specifier_nonarray:
+       VOID_TOK                { $$ = ast_void; }
+       | FLOAT_TOK             { $$ = ast_float; }
+       | INT_TOK               { $$ = ast_int; }
+       | UINT_TOK              { $$ = ast_uint; }
+       | BOOL_TOK              { $$ = ast_bool; }
+       | VEC2                  { $$ = ast_vec2; }
+       | VEC3                  { $$ = ast_vec3; }
+       | VEC4                  { $$ = ast_vec4; }
+       | BVEC2                 { $$ = ast_bvec2; }
+       | BVEC3                 { $$ = ast_bvec3; }
+       | BVEC4                 { $$ = ast_bvec4; }
+       | IVEC2                 { $$ = ast_ivec2; }
+       | IVEC3                 { $$ = ast_ivec3; }
+       | IVEC4                 { $$ = ast_ivec4; }
+       | UVEC2                 { $$ = ast_uvec2; }
+       | UVEC3                 { $$ = ast_uvec3; }
+       | UVEC4                 { $$ = ast_uvec4; }
+       | MAT2X2                { $$ = ast_mat2; }
+       | MAT2X3                { $$ = ast_mat2x3; }
+       | MAT2X4                { $$ = ast_mat2x4; }
+       | MAT3X2                { $$ = ast_mat3x2; }
+       | MAT3X3                { $$ = ast_mat3; }
+       | MAT3X4                { $$ = ast_mat3x4; }
+       | MAT4X2                { $$ = ast_mat4x2; }
+       | MAT4X3                { $$ = ast_mat4x3; }
+       | MAT4X4                { $$ = ast_mat4; }
+       | SAMPLER1D             { $$ = ast_sampler1d; }
+       | SAMPLER2D             { $$ = ast_sampler2d; }
+       | SAMPLER2DRECT         { $$ = ast_sampler2drect; }
+       | SAMPLER3D             { $$ = ast_sampler3d; }
+       | SAMPLERCUBE           { $$ = ast_samplercube; }
+       | SAMPLER1DSHADOW       { $$ = ast_sampler1dshadow; }
+       | SAMPLER2DSHADOW       { $$ = ast_sampler2dshadow; }
+       | SAMPLER2DRECTSHADOW   { $$ = ast_sampler2drectshadow; }
+       | SAMPLERCUBESHADOW     { $$ = ast_samplercubeshadow; }
+       | SAMPLER1DARRAY        { $$ = ast_sampler1darray; }
+       | SAMPLER2DARRAY        { $$ = ast_sampler2darray; }
+       | SAMPLER1DARRAYSHADOW  { $$ = ast_sampler1darrayshadow; }
+       | SAMPLER2DARRAYSHADOW  { $$ = ast_sampler2darrayshadow; }
+       | ISAMPLER1D            { $$ = ast_isampler1d; }
+       | ISAMPLER2D            { $$ = ast_isampler2d; }
+       | ISAMPLER3D            { $$ = ast_isampler3d; }
+       | ISAMPLERCUBE          { $$ = ast_isamplercube; }
+       | ISAMPLER1DARRAY       { $$ = ast_isampler1darray; }
+       | ISAMPLER2DARRAY       { $$ = ast_isampler2darray; }
+       | USAMPLER1D            { $$ = ast_usampler1d; }
+       | USAMPLER2D            { $$ = ast_usampler2d; }
+       | USAMPLER3D            { $$ = ast_usampler3d; }
+       | USAMPLERCUBE          { $$ = ast_usamplercube; }
+       | USAMPLER1DARRAY       { $$ = ast_usampler1darray; }
+       | USAMPLER2DARRAY       { $$ = ast_usampler2darray; }
+       ;
+
+precision_qualifier:
+       HIGHP           {
+                          if (state->language_version < 130)
+                             _mesa_glsl_error(& @1, state,
+                                              "precision qualifier forbidden "
+                                              "in GLSL %d.%d (1.30 or later "
+                                              "required)\n",
+                                              state->language_version / 100,
+                                              state->language_version % 100);
+
+                          $$ = ast_precision_high;
+                       }
+       | MEDIUMP       {
+                          if (state->language_version < 130)
+                             _mesa_glsl_error(& @1, state,
+                                              "precision qualifier forbidden "
+                                              "in GLSL %d.%d (1.30 or later "
+                                              "required)\n",
+                                              state->language_version / 100,
+                                              state->language_version % 100);
+
+                          $$ = ast_precision_medium;
+                       }
+       | LOWP          {
+                          if (state->language_version < 130)
+                             _mesa_glsl_error(& @1, state,
+                                              "precision qualifier forbidden "
+                                              "in GLSL %d.%d (1.30 or later "
+                                              "required)\n",
+                                              state->language_version / 100,
+                                              state->language_version % 100);
+
+                          $$ = ast_precision_low;
+                       }
+       ;
+
+struct_specifier:
+       STRUCT IDENTIFIER '{' struct_declaration_list '}'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_struct_specifier($2, $4);
+          $$->set_location(yylloc);
+       }
+       | STRUCT '{' struct_declaration_list '}'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_struct_specifier(NULL, $3);
+          $$->set_location(yylloc);
+       }
+       ;
+
+struct_declaration_list:
+       struct_declaration
+       {
+          $$ = (ast_node *) $1;
+          $1->link.self_link();
+       }
+       | struct_declaration_list struct_declaration
+       {
+          $$ = (ast_node *) $1;
+          $$->link.insert_before(& $2->link);
+       }
+       ;
+
+struct_declaration:
+       type_specifier struct_declarator_list ';'
+       {
+          void *ctx = state;
+          ast_fully_specified_type *type = new(ctx) ast_fully_specified_type();
+          type->set_location(yylloc);
+
+          type->specifier = $1;
+          $$ = new(ctx) ast_declarator_list(type);
+          $$->set_location(yylloc);
+
+          $$->declarations.push_degenerate_list_at_head(& $2->link);
+       }
+       ;
+
+struct_declarator_list:
+       struct_declarator
+       {
+          $$ = $1;
+          $1->link.self_link();
+       }
+       | struct_declarator_list ',' struct_declarator
+       {
+          $$ = $1;
+          $$->link.insert_before(& $3->link);
+       }
+       ;
+
+struct_declarator:
+       IDENTIFIER
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_declaration($1, false, NULL, NULL);
+          $$->set_location(yylloc);
+       }
+       | IDENTIFIER '[' constant_expression ']'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_declaration($1, true, $3, NULL);
+          $$->set_location(yylloc);
+       }
+       ;
+
+initializer:
+       assignment_expression
+       ;
+
+declaration_statement:
+       declaration
+       ;
+
+       // Grammar Note: labeled statements for SWITCH only; 'goto' is not
+       // supported.
+statement:
+       statement_matched
+       | statement_unmatched
+       ;
+
+statement_matched:
+       compound_statement      { $$ = (ast_node *) $1; }
+       | simple_statement
+       ;
+
+statement_unmatched:
+       selection_statement_unmatched
+       ;
+
+simple_statement:
+       declaration_statement
+       | expression_statement
+       | selection_statement_matched
+       | switch_statement              { $$ = NULL; }
+       | case_label                    { $$ = NULL; }
+       | iteration_statement
+       | jump_statement
+       ;
+
+compound_statement:
+       '{' '}'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_compound_statement(true, NULL);
+          $$->set_location(yylloc);
+       }
+       | '{' statement_list '}'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_compound_statement(true, $2);
+          $$->set_location(yylloc);
+       }
+       ;
+
+statement_no_new_scope:
+       compound_statement_no_new_scope { $$ = (ast_node *) $1; }
+       | simple_statement
+       ;
+
+compound_statement_no_new_scope:
+       '{' '}'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_compound_statement(false, NULL);
+          $$->set_location(yylloc);
+       }
+       | '{' statement_list '}'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_compound_statement(false, $2);
+          $$->set_location(yylloc);
+       }
+       ;
+
+statement_list:
+       statement
+       {
+          if ($1 == NULL) {
+             _mesa_glsl_error(& @1, state, "<nil> statement\n");
+             assert($1 != NULL);
+          }
+
+          $$ = $1;
+          $$->link.self_link();
+       }
+       | statement_list statement
+       {
+          if ($2 == NULL) {
+             _mesa_glsl_error(& @2, state, "<nil> statement\n");
+             assert($2 != NULL);
+          }
+          $$ = $1;
+          $$->link.insert_before(& $2->link);
+       }
+       ;
+
+expression_statement:
+       ';'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_statement(NULL);
+          $$->set_location(yylloc);
+       }
+       | expression ';'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_expression_statement($1);
+          $$->set_location(yylloc);
+       }
+       ;
+
+selection_statement_matched:
+       IF '(' expression ')' statement_matched ELSE statement_matched
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_selection_statement($3, $5, $7);
+          $$->set_location(yylloc);
+       }
+       ;
+
+selection_statement_unmatched:
+       IF '(' expression ')' statement_matched
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_selection_statement($3, $5, NULL);
+          $$->set_location(yylloc);
+       }
+       | IF '(' expression ')' statement_unmatched
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_selection_statement($3, $5, NULL);
+          $$->set_location(yylloc);
+       }
+       | IF '(' expression ')' statement_matched ELSE statement_unmatched
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_selection_statement($3, $5, $7);
+          $$->set_location(yylloc);
+       }
+       ;
+
+condition:
+       expression
+       {
+          $$ = (ast_node *) $1;
+       }
+       | fully_specified_type IDENTIFIER '=' initializer
+       {
+          void *ctx = state;
+          ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, $4);
+          ast_declarator_list *declarator = new(ctx) ast_declarator_list($1);
+          decl->set_location(yylloc);
+          declarator->set_location(yylloc);
+
+          declarator->declarations.push_tail(&decl->link);
+          $$ = declarator;
+       }
+       ;
+
+switch_statement:
+       SWITCH '(' expression ')' compound_statement
+       ;
+
+case_label:
+       CASE expression ':'
+       | DEFAULT ':'
+       ;
+
+iteration_statement:
+       WHILE '(' condition ')' statement_no_new_scope
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_while,
+                                                   NULL, $3, NULL, $5);
+          $$->set_location(yylloc);
+       }
+       | DO statement WHILE '(' expression ')' ';'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_do_while,
+                                                   NULL, $5, NULL, $2);
+          $$->set_location(yylloc);
+       }
+       | FOR '(' for_init_statement for_rest_statement ')' statement_no_new_scope
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_for,
+                                                   $3, $4.cond, $4.rest, $6);
+          $$->set_location(yylloc);
+       }
+       ;
+
+for_init_statement:
+       expression_statement
+       | declaration_statement
+       ;
+
+conditionopt:
+       condition
+       | /* empty */
+       {
+          $$ = NULL;
+       }
+       ;
+
+for_rest_statement:
+       conditionopt ';'
+       {
+          $$.cond = $1;
+          $$.rest = NULL;
+       }
+       | conditionopt ';' expression
+       {
+          $$.cond = $1;
+          $$.rest = $3;
+       }
+       ;
+
+       // Grammar Note: No 'goto'. Gotos are not supported.
+jump_statement:
+       CONTINUE ';' 
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_continue, NULL);
+          $$->set_location(yylloc);
+       }
+       | BREAK ';'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_break, NULL);
+          $$->set_location(yylloc);
+       }
+       | RETURN ';'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, NULL);
+          $$->set_location(yylloc);
+       }
+       | RETURN expression ';'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, $2);
+          $$->set_location(yylloc);
+       }
+       | DISCARD ';' // Fragment shader only.
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_discard, NULL);
+          $$->set_location(yylloc);
+       }
+       ;
+
+external_declaration:
+       function_definition     { $$ = $1; }
+       | declaration           { $$ = $1; }
+       | pragma_statement      { $$ = NULL; }
+       ;
+
+function_definition:
+       function_prototype compound_statement_no_new_scope
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_function_definition();
+          $$->set_location(yylloc);
+          $$->prototype = $1;
+          $$->body = $2;
+       }
+       ;
diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
new file mode 100644 (file)
index 0000000..bc56e4f
--- /dev/null
@@ -0,0 +1,773 @@
+/*
+ * Copyright Â© 2008, 2009 Intel Corporation
+ *
+ * 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 <stdarg.h>
+#include <string.h>
+#include <assert.h>
+
+extern "C" {
+#include <talloc.h>
+#include "main/core.h" /* for struct __GLcontextRec */
+}
+
+#include "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_parser.h"
+#include "ir_optimization.h"
+
+_mesa_glsl_parse_state::_mesa_glsl_parse_state(struct __GLcontextRec *ctx,
+                                              GLenum target, void *mem_ctx)
+{
+   switch (target) {
+   case GL_VERTEX_SHADER:   this->target = vertex_shader; break;
+   case GL_FRAGMENT_SHADER: this->target = fragment_shader; break;
+   case GL_GEOMETRY_SHADER: this->target = geometry_shader; break;
+   }
+
+   this->scanner = NULL;
+   this->translation_unit.make_empty();
+   this->symbols = new(mem_ctx) glsl_symbol_table;
+   this->info_log = talloc_strdup(mem_ctx, "");
+   this->error = false;
+   this->loop_or_switch_nesting = NULL;
+   this->ARB_texture_rectangle_enable = true;
+
+   if (ctx != NULL) {
+      this->extensions = &ctx->Extensions;
+
+      this->Const.MaxLights = ctx->Const.MaxLights;
+      this->Const.MaxClipPlanes = ctx->Const.MaxClipPlanes;
+      this->Const.MaxTextureUnits = ctx->Const.MaxTextureUnits;
+      this->Const.MaxTextureCoords = ctx->Const.MaxTextureCoordUnits;
+      this->Const.MaxVertexAttribs = ctx->Const.VertexProgram.MaxAttribs;
+      this->Const.MaxVertexUniformComponents = ctx->Const.VertexProgram.MaxUniformComponents;
+      this->Const.MaxVaryingFloats = ctx->Const.MaxVarying * 4;
+      this->Const.MaxVertexTextureImageUnits = ctx->Const.MaxVertexTextureImageUnits;
+      this->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxCombinedTextureImageUnits;
+      this->Const.MaxTextureImageUnits = ctx->Const.MaxTextureImageUnits;
+      this->Const.MaxFragmentUniformComponents = ctx->Const.FragmentProgram.MaxUniformComponents;
+
+      this->Const.MaxDrawBuffers = ctx->Const.MaxDrawBuffers;
+   } else {
+      /* If there is no GL context (standalone compiler), fill in constants
+       * with the minimum required values.
+       */
+      static struct gl_extensions null_extensions;
+
+      memset(&null_extensions, 0, sizeof(null_extensions));
+      null_extensions.ARB_draw_buffers = GL_TRUE;
+      null_extensions.ARB_fragment_coord_conventions = GL_TRUE;
+      null_extensions.EXT_texture_array = GL_TRUE;
+      null_extensions.NV_texture_rectangle = GL_TRUE;
+
+      this->extensions = &null_extensions;
+
+      /* 1.10 minimums. */
+      this->Const.MaxLights = 8;
+      this->Const.MaxClipPlanes = 8;
+      this->Const.MaxTextureUnits = 2;
+
+      /* More than the 1.10 minimum to appease parser tests taken from
+       * apps that (hopefully) already checked the number of coords.
+       */
+      this->Const.MaxTextureCoords = 4;
+
+      this->Const.MaxVertexAttribs = 16;
+      this->Const.MaxVertexUniformComponents = 512;
+      this->Const.MaxVaryingFloats = 32;
+      this->Const.MaxVertexTextureImageUnits = 0;
+      this->Const.MaxCombinedTextureImageUnits = 2;
+      this->Const.MaxTextureImageUnits = 2;
+      this->Const.MaxFragmentUniformComponents = 64;
+
+      this->Const.MaxDrawBuffers = 2;
+   }
+}
+
+const char *
+_mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target)
+{
+   switch (target) {
+   case vertex_shader:   return "vertex";
+   case fragment_shader: return "fragment";
+   case geometry_shader: return "geometry";
+   case ir_shader:       break;
+   }
+
+   assert(!"Should not get here.");
+   return "unknown";
+}
+
+
+void
+_mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
+                const char *fmt, ...)
+{
+   va_list ap;
+
+   state->error = true;
+
+   assert(state->info_log != NULL);
+   state->info_log = talloc_asprintf_append(state->info_log,
+                                           "%u:%u(%u): error: ",
+                                           locp->source,
+                                           locp->first_line,
+                                           locp->first_column);
+   va_start(ap, fmt);
+   state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap);
+   va_end(ap);
+   state->info_log = talloc_strdup_append(state->info_log, "\n");
+}
+
+
+void
+_mesa_glsl_warning(const YYLTYPE *locp, _mesa_glsl_parse_state *state,
+                  const char *fmt, ...)
+{
+   va_list ap;
+
+   assert(state->info_log != NULL);
+   state->info_log = talloc_asprintf_append(state->info_log,
+                                           "%u:%u(%u): warning: ",
+                                           locp->source,
+                                           locp->first_line,
+                                           locp->first_column);
+   va_start(ap, fmt);
+   state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap);
+   va_end(ap);
+   state->info_log = talloc_strdup_append(state->info_log, "\n");
+}
+
+
+bool
+_mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
+                            const char *behavior, YYLTYPE *behavior_locp,
+                            _mesa_glsl_parse_state *state)
+{
+   enum {
+      extension_disable,
+      extension_enable,
+      extension_require,
+      extension_warn
+   } ext_mode;
+
+   if (strcmp(behavior, "warn") == 0) {
+      ext_mode = extension_warn;
+   } else if (strcmp(behavior, "require") == 0) {
+      ext_mode = extension_require;
+   } else if (strcmp(behavior, "enable") == 0) {
+      ext_mode = extension_enable;
+   } else if (strcmp(behavior, "disable") == 0) {
+      ext_mode = extension_disable;
+   } else {
+      _mesa_glsl_error(behavior_locp, state,
+                      "Unknown extension behavior `%s'",
+                      behavior);
+      return false;
+   }
+
+   bool unsupported = false;
+
+   if (strcmp(name, "all") == 0) {
+      if ((ext_mode == extension_enable) || (ext_mode == extension_require)) {
+        _mesa_glsl_error(name_locp, state, "Cannot %s all extensions",
+                         (ext_mode == extension_enable)
+                         ? "enable" : "require");
+        return false;
+      }
+   } else if (strcmp(name, "GL_ARB_draw_buffers") == 0) {
+      /* This extension is only supported in fragment shaders.
+       */
+      if (state->target != fragment_shader) {
+        unsupported = true;
+      } else {
+        state->ARB_draw_buffers_enable = (ext_mode != extension_disable);
+        state->ARB_draw_buffers_warn = (ext_mode == extension_warn);
+      }
+   } else if (strcmp(name, "GL_ARB_fragment_coord_conventions") == 0) {
+      state->ARB_fragment_coord_conventions_enable =
+        (ext_mode != extension_disable);
+      state->ARB_fragment_coord_conventions_warn =
+        (ext_mode == extension_warn);
+
+      unsupported = !state->extensions->ARB_fragment_coord_conventions;
+   } else if (strcmp(name, "GL_ARB_texture_rectangle") == 0) {
+      state->ARB_texture_rectangle_enable = (ext_mode != extension_disable);
+      state->ARB_texture_rectangle_warn = (ext_mode == extension_warn);
+   } else if (strcmp(name, "GL_EXT_texture_array") == 0) {
+      state->EXT_texture_array_enable = (ext_mode != extension_disable);
+      state->EXT_texture_array_warn = (ext_mode == extension_warn);
+
+      unsupported = !state->extensions->EXT_texture_array;
+   } else {
+      unsupported = true;
+   }
+
+   if (unsupported) {
+      static const char *const fmt = "extension `%s' unsupported in %s shader";
+
+      if (ext_mode == extension_require) {
+        _mesa_glsl_error(name_locp, state, fmt,
+                         name, _mesa_glsl_shader_target_name(state->target));
+        return false;
+      } else {
+        _mesa_glsl_warning(name_locp, state, fmt,
+                           name, _mesa_glsl_shader_target_name(state->target));
+      }
+   }
+
+   return true;
+}
+
+void
+_mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
+{
+   if (q->constant)
+      printf("const ");
+
+   if (q->invariant)
+      printf("invariant ");
+
+   if (q->attribute)
+      printf("attribute ");
+
+   if (q->varying)
+      printf("varying ");
+
+   if (q->in && q->out) 
+      printf("inout ");
+   else {
+      if (q->in)
+        printf("in ");
+
+      if (q->out)
+        printf("out ");
+   }
+
+   if (q->centroid)
+      printf("centroid ");
+   if (q->uniform)
+      printf("uniform ");
+   if (q->smooth)
+      printf("smooth ");
+   if (q->flat)
+      printf("flat ");
+   if (q->noperspective)
+      printf("noperspective ");
+}
+
+
+void
+ast_node::print(void) const
+{
+   printf("unhandled node ");
+}
+
+
+ast_node::ast_node(void)
+{
+   this->location.source = 0;
+   this->location.line = 0;
+   this->location.column = 0;
+}
+
+
+static void
+ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
+{
+   if (is_array) {
+      printf("[ ");
+
+      if (array_size)
+        array_size->print();
+
+      printf("] ");
+   }
+}
+
+
+void
+ast_compound_statement::print(void) const
+{
+   printf("{\n");
+   
+   foreach_list_const(n, &this->statements) {
+      ast_node *ast = exec_node_data(ast_node, n, link);
+      ast->print();
+   }
+
+   printf("}\n");
+}
+
+
+ast_compound_statement::ast_compound_statement(int new_scope,
+                                              ast_node *statements)
+{
+   this->new_scope = new_scope;
+
+   if (statements != NULL) {
+      this->statements.push_degenerate_list_at_head(&statements->link);
+   }
+}
+
+
+void
+ast_expression::print(void) const
+{
+   switch (oper) {
+   case ast_assign:
+   case ast_mul_assign:
+   case ast_div_assign:
+   case ast_mod_assign:
+   case ast_add_assign:
+   case ast_sub_assign:
+   case ast_ls_assign:
+   case ast_rs_assign:
+   case ast_and_assign:
+   case ast_xor_assign:
+   case ast_or_assign:
+      subexpressions[0]->print();
+      printf("%s ", operator_string(oper));
+      subexpressions[1]->print();
+      break;
+
+   case ast_field_selection:
+      subexpressions[0]->print();
+      printf(". %s ", primary_expression.identifier);
+      break;
+
+   case ast_plus:
+   case ast_neg:
+   case ast_bit_not:
+   case ast_logic_not:
+   case ast_pre_inc:
+   case ast_pre_dec:
+      printf("%s ", operator_string(oper));
+      subexpressions[0]->print();
+      break;
+
+   case ast_post_inc:
+   case ast_post_dec:
+      subexpressions[0]->print();
+      printf("%s ", operator_string(oper));
+      break;
+
+   case ast_conditional:
+      subexpressions[0]->print();
+      printf("? ");
+      subexpressions[1]->print();
+      printf(": ");
+      subexpressions[1]->print();
+      break;
+
+   case ast_array_index:
+      subexpressions[0]->print();
+      printf("[ ");
+      subexpressions[1]->print();
+      printf("] ");
+      break;
+
+   case ast_function_call: {
+      subexpressions[0]->print();
+      printf("( ");
+
+      foreach_list_const (n, &this->expressions) {
+        if (n != this->expressions.get_head())
+           printf(", ");
+
+        ast_node *ast = exec_node_data(ast_node, n, link);
+        ast->print();
+      }
+
+      printf(") ");
+      break;
+   }
+
+   case ast_identifier:
+      printf("%s ", primary_expression.identifier);
+      break;
+
+   case ast_int_constant:
+      printf("%d ", primary_expression.int_constant);
+      break;
+
+   case ast_uint_constant:
+      printf("%u ", primary_expression.uint_constant);
+      break;
+
+   case ast_float_constant:
+      printf("%f ", primary_expression.float_constant);
+      break;
+
+   case ast_bool_constant:
+      printf("%s ",
+            primary_expression.bool_constant
+            ? "true" : "false");
+      break;
+
+   case ast_sequence: {
+      printf("( ");
+      foreach_list_const(n, & this->expressions) {
+        if (n != this->expressions.get_head())
+           printf(", ");
+
+        ast_node *ast = exec_node_data(ast_node, n, link);
+        ast->print();
+      }
+      printf(") ");
+      break;
+   }
+
+   default:
+      assert(0);
+      break;
+   }
+}
+
+ast_expression::ast_expression(int oper,
+                              ast_expression *ex0,
+                              ast_expression *ex1,
+                              ast_expression *ex2)
+{
+   this->oper = ast_operators(oper);
+   this->subexpressions[0] = ex0;
+   this->subexpressions[1] = ex1;
+   this->subexpressions[2] = ex2;
+}
+
+
+void
+ast_expression_statement::print(void) const
+{
+   if (expression)
+      expression->print();
+
+   printf("; ");
+}
+
+
+ast_expression_statement::ast_expression_statement(ast_expression *ex) :
+   expression(ex)
+{
+   /* empty */
+}
+
+
+void
+ast_function::print(void) const
+{
+   return_type->print();
+   printf(" %s (", identifier);
+
+   foreach_list_const(n, & this->parameters) {
+      ast_node *ast = exec_node_data(ast_node, n, link);
+      ast->print();
+   }
+
+   printf(")");
+}
+
+
+ast_function::ast_function(void)
+   : is_definition(false), signature(NULL)
+{
+   /* empty */
+}
+
+
+void
+ast_fully_specified_type::print(void) const
+{
+   _mesa_ast_type_qualifier_print(& qualifier);
+   specifier->print();
+}
+
+
+void
+ast_parameter_declarator::print(void) const
+{
+   type->print();
+   if (identifier)
+      printf("%s ", identifier);
+   ast_opt_array_size_print(is_array, array_size);
+}
+
+
+void
+ast_function_definition::print(void) const
+{
+   prototype->print();
+   body->print();
+}
+
+
+void
+ast_declaration::print(void) const
+{
+   printf("%s ", identifier);
+   ast_opt_array_size_print(is_array, array_size);
+
+   if (initializer) {
+      printf("= ");
+      initializer->print();
+   }
+}
+
+
+ast_declaration::ast_declaration(char *identifier, int is_array,
+                                ast_expression *array_size,
+                                ast_expression *initializer)
+{
+   this->identifier = identifier;
+   this->is_array = is_array;
+   this->array_size = array_size;
+   this->initializer = initializer;
+}
+
+
+void
+ast_declarator_list::print(void) const
+{
+   assert(type || invariant);
+
+   if (type)
+      type->print();
+   else
+      printf("invariant ");
+
+   foreach_list_const (ptr, & this->declarations) {
+      if (ptr != this->declarations.get_head())
+        printf(", ");
+
+      ast_node *ast = exec_node_data(ast_node, ptr, link);
+      ast->print();
+   }
+
+   printf("; ");
+}
+
+
+ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
+{
+   this->type = type;
+   this->invariant = false;
+}
+
+void
+ast_jump_statement::print(void) const
+{
+   switch (mode) {
+   case ast_continue:
+      printf("continue; ");
+      break;
+   case ast_break:
+      printf("break; ");
+      break;
+   case ast_return:
+      printf("return ");
+      if (opt_return_value)
+        opt_return_value->print();
+
+      printf("; ");
+      break;
+   case ast_discard:
+      printf("discard; ");
+      break;
+   }
+}
+
+
+ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value)
+{
+   this->mode = ast_jump_modes(mode);
+
+   if (mode == ast_return)
+      opt_return_value = return_value;
+}
+
+
+void
+ast_selection_statement::print(void) const
+{
+   printf("if ( ");
+   condition->print();
+   printf(") ");
+
+   then_statement->print();
+
+   if (else_statement) {
+      printf("else ");
+      else_statement->print();
+   }
+   
+}
+
+
+ast_selection_statement::ast_selection_statement(ast_expression *condition,
+                                                ast_node *then_statement,
+                                                ast_node *else_statement)
+{
+   this->condition = condition;
+   this->then_statement = then_statement;
+   this->else_statement = else_statement;
+}
+
+
+void
+ast_iteration_statement::print(void) const
+{
+   switch (mode) {
+   case ast_for:
+      printf("for( ");
+      if (init_statement)
+        init_statement->print();
+      printf("; ");
+
+      if (condition)
+        condition->print();
+      printf("; ");
+
+      if (rest_expression)
+        rest_expression->print();
+      printf(") ");
+
+      body->print();
+      break;
+
+   case ast_while:
+      printf("while ( ");
+      if (condition)
+        condition->print();
+      printf(") ");
+      body->print();
+      break;
+
+   case ast_do_while:
+      printf("do ");
+      body->print();
+      printf("while ( ");
+      if (condition)
+        condition->print();
+      printf("); ");
+      break;
+   }
+}
+
+
+ast_iteration_statement::ast_iteration_statement(int mode,
+                                                ast_node *init,
+                                                ast_node *condition,
+                                                ast_expression *rest_expression,
+                                                ast_node *body)
+{
+   this->mode = ast_iteration_modes(mode);
+   this->init_statement = init;
+   this->condition = condition;
+   this->rest_expression = rest_expression;
+   this->body = body;
+}
+
+
+void
+ast_struct_specifier::print(void) const
+{
+   printf("struct %s { ", name);
+   foreach_list_const(n, &this->declarations) {
+      ast_node *ast = exec_node_data(ast_node, n, link);
+      ast->print();
+   }
+   printf("} ");
+}
+
+
+ast_struct_specifier::ast_struct_specifier(char *identifier,
+                                          ast_node *declarator_list)
+{
+   name = identifier;
+   this->declarations.push_degenerate_list_at_head(&declarator_list->link);
+}
+
+bool
+do_common_optimization(exec_list *ir, bool linked)
+{
+   GLboolean progress = GL_FALSE;
+
+   progress = do_sub_to_add_neg(ir) || progress;
+
+   if (linked) {
+      progress = do_function_inlining(ir) || progress;
+      progress = do_dead_functions(ir) || progress;
+   }
+   progress = do_structure_splitting(ir) || progress;
+   progress = do_if_simplification(ir) || progress;
+   progress = do_copy_propagation(ir) || progress;
+   if (linked)
+      progress = do_dead_code(ir) || progress;
+   else
+      progress = do_dead_code_unlinked(ir) || progress;
+   progress = do_dead_code_local(ir) || progress;
+   progress = do_tree_grafting(ir) || progress;
+   progress = do_constant_propagation(ir) || progress;
+   if (linked)
+      progress = do_constant_variable(ir) || progress;
+   else
+      progress = do_constant_variable_unlinked(ir) || progress;
+   progress = do_constant_folding(ir) || progress;
+   progress = do_algebraic(ir) || progress;
+   progress = do_if_return(ir) || progress;
+   progress = do_vec_index_to_swizzle(ir) || progress;
+   progress = do_swizzle_swizzle(ir) || progress;
+   progress = do_noop_swizzle(ir) || progress;
+
+   return progress;
+}
+
+extern "C" {
+
+/**
+ * To be called at GL teardown time, this frees compiler datastructures.
+ *
+ * After calling this, any previously compiled shaders and shader
+ * programs would be invalid.  So this should happen at approximately
+ * program exit.
+ */
+void
+_mesa_destroy_shader_compiler(void)
+{
+   _mesa_destroy_shader_compiler_caches();
+
+   _mesa_glsl_release_types();
+}
+
+/**
+ * Releases compiler caches to trade off performance for memory.
+ *
+ * Intended to be used with glReleaseShaderCompiler().
+ */
+void
+_mesa_destroy_shader_compiler_caches(void)
+{
+   _mesa_glsl_release_functions();
+}
+
+}
diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h
new file mode 100644 (file)
index 0000000..3ccdab4
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+#pragma once
+#ifndef GLSL_PARSER_EXTRAS_H
+#define GLSL_PARSER_EXTRAS_H
+
+/*
+ * Most of the definitions here only apply to C++
+ */
+#ifdef __cplusplus
+
+
+#include <cstdlib>
+#include "glsl_symbol_table.h"
+
+enum _mesa_glsl_parser_targets {
+   vertex_shader,
+   geometry_shader,
+   fragment_shader,
+   ir_shader
+};
+
+struct __GLcontextRec;
+
+struct _mesa_glsl_parse_state {
+   _mesa_glsl_parse_state(struct __GLcontextRec *ctx, GLenum target,
+                         void *mem_ctx);
+
+   /* Callers of this talloc-based new need not call delete. It's
+    * easier to just talloc_free 'ctx' (or any of its ancestors). */
+   static void* operator new(size_t size, void *ctx)
+   {
+      void *mem = talloc_zero_size(ctx, size);
+      assert(mem != NULL);
+
+      return mem;
+   }
+
+   /* If the user *does* call delete, that's OK, we will just
+    * talloc_free in that case. */
+   static void operator delete(void *mem)
+   {
+      talloc_free(mem);
+   }
+
+   void *scanner;
+   exec_list translation_unit;
+   glsl_symbol_table *symbols;
+
+   unsigned language_version;
+   enum _mesa_glsl_parser_targets target;
+
+   /**
+    * Implementation defined limits that affect built-in variables, etc.
+    *
+    * \sa struct gl_constants (in mtypes.h)
+    */
+   struct {
+      /* 1.10 */
+      unsigned MaxLights;
+      unsigned MaxClipPlanes;
+      unsigned MaxTextureUnits;
+      unsigned MaxTextureCoords;
+      unsigned MaxVertexAttribs;
+      unsigned MaxVertexUniformComponents;
+      unsigned MaxVaryingFloats;
+      unsigned MaxVertexTextureImageUnits;
+      unsigned MaxCombinedTextureImageUnits;
+      unsigned MaxTextureImageUnits;
+      unsigned MaxFragmentUniformComponents;
+
+      /* ARB_draw_buffers */
+      unsigned MaxDrawBuffers;
+   } Const;
+
+   /**
+    * During AST to IR conversion, pointer to current IR function
+    *
+    * Will be \c NULL whenever the AST to IR conversion is not inside a
+    * function definition.
+    */
+   class ir_function_signature *current_function;
+
+   /** Have we found a return statement in this function? */
+   bool found_return;
+
+   /** Was there an error during compilation? */
+   bool error;
+
+   /** Loop or switch statement containing the current instructions. */
+   class ir_instruction *loop_or_switch_nesting;
+   class ast_iteration_statement *loop_or_switch_nesting_ast;
+
+   /** List of structures defined in user code. */
+   const glsl_type **user_structures;
+   unsigned num_user_structures;
+
+   char *info_log;
+
+   /**
+    * \name Enable bits for GLSL extensions
+    */
+   /*@{*/
+   unsigned ARB_draw_buffers_enable:1;
+   unsigned ARB_draw_buffers_warn:1;
+   unsigned ARB_fragment_coord_conventions_enable:1;
+   unsigned ARB_fragment_coord_conventions_warn:1;
+   unsigned ARB_texture_rectangle_enable:1;
+   unsigned ARB_texture_rectangle_warn:1;
+   unsigned EXT_texture_array_enable:1;
+   unsigned EXT_texture_array_warn:1;
+   /*@}*/
+
+   /** Extensions supported by the OpenGL implementation. */
+   const struct gl_extensions *extensions;
+
+   /** Shaders containing built-in functions that are used for linking. */
+   struct gl_shader *builtins_to_link[16];
+   unsigned num_builtins_to_link;
+};
+
+typedef struct YYLTYPE {
+   int first_line;
+   int first_column;
+   int last_line;
+   int last_column;
+   unsigned source;
+} YYLTYPE;
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+
+# define YYLLOC_DEFAULT(Current, Rhs, N)                       \
+do {                                                           \
+   if (N)                                                      \
+   {                                                           \
+      (Current).first_line   = YYRHSLOC(Rhs, 1).first_line;    \
+      (Current).first_column = YYRHSLOC(Rhs, 1).first_column;  \
+      (Current).last_line    = YYRHSLOC(Rhs, N).last_line;     \
+      (Current).last_column  = YYRHSLOC(Rhs, N).last_column;   \
+   }                                                           \
+   else                                                                \
+   {                                                           \
+      (Current).first_line   = (Current).last_line =           \
+        YYRHSLOC(Rhs, 0).last_line;                            \
+      (Current).first_column = (Current).last_column =         \
+        YYRHSLOC(Rhs, 0).last_column;                          \
+   }                                                           \
+   (Current).source = 0;                                       \
+} while (0)
+
+extern void _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
+                            const char *fmt, ...);
+
+/**
+ * Emit a warning to the shader log
+ *
+ * \sa _mesa_glsl_error
+ */
+extern void _mesa_glsl_warning(const YYLTYPE *locp,
+                              _mesa_glsl_parse_state *state,
+                              const char *fmt, ...);
+
+extern void _mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state,
+                                 const char *string);
+
+extern void _mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state);
+
+union YYSTYPE;
+extern int _mesa_glsl_lex(union YYSTYPE *yylval, YYLTYPE *yylloc, 
+                         void *scanner);
+
+extern int _mesa_glsl_parse(struct _mesa_glsl_parse_state *);
+
+/**
+ * Process elements of the #extension directive
+ *
+ * \return
+ * If \c name and \c behavior are valid, \c true is returned.  Otherwise
+ * \c false is returned.
+ */
+extern bool _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
+                                        const char *behavior,
+                                        YYLTYPE *behavior_locp,
+                                        _mesa_glsl_parse_state *state);
+
+/**
+ * Get the textual name of the specified shader target
+ */
+extern const char *
+_mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target);
+
+
+#endif /* __cplusplus */
+
+
+/*
+ * These definitions apply to C and C++
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int preprocess(void *ctx, const char **shader, char **info_log,
+                      const struct gl_extensions *extensions);
+
+extern void _mesa_destroy_shader_compiler();
+extern void _mesa_destroy_shader_compiler_caches();
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* GLSL_PARSER_EXTRAS_H */
diff --git a/src/glsl/glsl_symbol_table.cpp b/src/glsl/glsl_symbol_table.cpp
new file mode 100644 (file)
index 0000000..e9bf89b
--- /dev/null
@@ -0,0 +1,160 @@
+/* -*- c++ -*- */
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 "glsl_symbol_table.h"
+
+class symbol_table_entry {
+public:
+   /* Callers of this talloc-based new need not call delete. It's
+    * easier to just talloc_free 'ctx' (or any of its ancestors). */
+   static void* operator new(size_t size, void *ctx)
+   {
+      void *entry = talloc_size(ctx, size);
+      assert(entry != NULL);
+      return entry;
+   }
+
+   /* If the user *does* call delete, that's OK, we will just
+    * talloc_free in that case. Here, C++ will have already called the
+    * destructor so tell talloc not to do that again. */
+   static void operator delete(void *table)
+   {
+      talloc_set_destructor(table, NULL);
+      talloc_free(table);
+   }
+
+   symbol_table_entry(ir_variable *v)                     : v(v), f(0), t(0) {}
+   symbol_table_entry(ir_function *f)                     : v(0), f(f), t(0) {}
+   symbol_table_entry(const glsl_type *t)                 : v(0), f(0), t(t) {}
+
+   ir_variable *v;
+   ir_function *f;
+   const glsl_type *t;
+};
+
+glsl_symbol_table::glsl_symbol_table()
+{
+   this->language_version = 120;
+   this->table = _mesa_symbol_table_ctor();
+   this->mem_ctx = talloc_init("symbol table entries");
+}
+
+glsl_symbol_table::~glsl_symbol_table()
+{
+   _mesa_symbol_table_dtor(table);
+   talloc_free(mem_ctx);
+}
+
+void glsl_symbol_table::push_scope()
+{
+   _mesa_symbol_table_push_scope(table);
+}
+
+void glsl_symbol_table::pop_scope()
+{
+   _mesa_symbol_table_pop_scope(table);
+}
+
+bool glsl_symbol_table::name_declared_this_scope(const char *name)
+{
+   return _mesa_symbol_table_symbol_scope(table, -1, name) == 0;
+}
+
+bool glsl_symbol_table::add_variable(const char *name, ir_variable *v)
+{
+   if (this->language_version == 110) {
+      /* In 1.10, functions and variables have separate namespaces. */
+      symbol_table_entry *existing = get_entry(name);
+      if (name_declared_this_scope(name)) {
+        /* If there's already an existing function (not a constructor!) in
+         * the current scope, just update the existing entry to include 'v'.
+         */
+        if (existing->v == NULL && existing->t == NULL) {
+           existing->v = v;
+           return true;
+        }
+      } else {
+        /* If not declared at this scope, add a new entry.  But if an existing
+         * entry includes a function, propagate that to this block - otherwise
+         * the new variable declaration would shadow the function.
+         */
+        symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(v);
+        if (existing != NULL)
+           entry->f = existing->f;
+        int added = _mesa_symbol_table_add_symbol(table, -1, name, entry);
+        assert(added == 0);
+        (void)added;
+        return true;
+      }
+      return false;
+   }
+
+   /* 1.20+ rules: */
+   symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(v);
+   return _mesa_symbol_table_add_symbol(table, -1, name, entry) == 0;
+}
+
+bool glsl_symbol_table::add_type(const char *name, const glsl_type *t)
+{
+   symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(t);
+   return _mesa_symbol_table_add_symbol(table, -1, name, entry) == 0;
+}
+
+bool glsl_symbol_table::add_function(const char *name, ir_function *f)
+{
+   if (this->language_version == 110 && name_declared_this_scope(name)) {
+      /* In 1.10, functions and variables have separate namespaces. */
+      symbol_table_entry *existing = get_entry(name);
+      if ((existing->f == NULL) && (existing->t == NULL)) {
+        existing->f = f;
+        return true;
+      }
+   }
+   symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(f);
+   return _mesa_symbol_table_add_symbol(table, -1, name, entry) == 0;
+}
+
+ir_variable *glsl_symbol_table::get_variable(const char *name)
+{
+   symbol_table_entry *entry = get_entry(name);
+   return entry != NULL ? entry->v : NULL;
+}
+
+const glsl_type *glsl_symbol_table::get_type(const char *name)
+{
+   symbol_table_entry *entry = get_entry(name);
+   return entry != NULL ? entry->t : NULL;
+}
+
+ir_function *glsl_symbol_table::get_function(const char *name)
+{
+   symbol_table_entry *entry = get_entry(name);
+   return entry != NULL ? entry->f : NULL;
+}
+
+symbol_table_entry *glsl_symbol_table::get_entry(const char *name)
+{
+   return (symbol_table_entry *)
+      _mesa_symbol_table_find_symbol(table, -1, name);
+}
diff --git a/src/glsl/glsl_symbol_table.h b/src/glsl/glsl_symbol_table.h
new file mode 100644 (file)
index 0000000..f26de52
--- /dev/null
@@ -0,0 +1,121 @@
+/* -*- c++ -*- */
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+#pragma once
+#ifndef GLSL_SYMBOL_TABLE
+#define GLSL_SYMBOL_TABLE
+
+#include <new>
+
+extern "C" {
+#include "program/symbol_table.h"
+}
+#include "ir.h"
+#include "glsl_types.h"
+
+class symbol_table_entry;
+
+/**
+ * Facade class for _mesa_symbol_table
+ *
+ * Wraps the existing \c _mesa_symbol_table data structure to enforce some
+ * type safe and some symbol table invariants.
+ */
+struct glsl_symbol_table {
+private:
+   static int
+   _glsl_symbol_table_destructor (glsl_symbol_table *table)
+   {
+      table->~glsl_symbol_table();
+
+      return 0;
+   }
+
+public:
+   /* Callers of this talloc-based new need not call delete. It's
+    * easier to just talloc_free 'ctx' (or any of its ancestors). */
+   static void* operator new(size_t size, void *ctx)
+   {
+      void *table;
+
+      table = talloc_size(ctx, size);
+      assert(table != NULL);
+
+      talloc_set_destructor(table, (int (*)(void*)) _glsl_symbol_table_destructor);
+
+      return table;
+   }
+
+   /* If the user *does* call delete, that's OK, we will just
+    * talloc_free in that case. Here, C++ will have already called the
+    * destructor so tell talloc not to do that again. */
+   static void operator delete(void *table)
+   {
+      talloc_set_destructor(table, NULL);
+      talloc_free(table);
+   }
+   
+   glsl_symbol_table();
+   ~glsl_symbol_table();
+
+   unsigned int language_version;
+
+   void push_scope();
+   void pop_scope();
+
+   /**
+    * Determine whether a name was declared at the current scope
+    */
+   bool name_declared_this_scope(const char *name);
+
+   /**
+    * \name Methods to add symbols to the table
+    *
+    * There is some temptation to rename all these functions to \c add_symbol
+    * or similar.  However, this breaks symmetry with the getter functions and
+    * reduces the clarity of the intention of code that uses these methods.
+    */
+   /*@{*/
+   bool add_variable(const char *name, ir_variable *v);
+   bool add_type(const char *name, const glsl_type *t);
+   bool add_function(const char *name, ir_function *f);
+   /*@}*/
+
+   /**
+    * \name Methods to get symbols from the table
+    */
+   /*@{*/
+   ir_variable *get_variable(const char *name);
+   const glsl_type *get_type(const char *name);
+   ir_function *get_function(const char *name);
+   /*@}*/
+
+private:
+   symbol_table_entry *get_entry(const char *name);
+
+   struct _mesa_symbol_table *table;
+   void *mem_ctx;
+};
+
+#endif /* GLSL_SYMBOL_TABLE */
diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp
new file mode 100644 (file)
index 0000000..92ad3ef
--- /dev/null
@@ -0,0 +1,484 @@
+/*
+ * Copyright Â© 2009 Intel Corporation
+ *
+ * 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 <cstdio>
+#include <stdlib.h>
+#include "main/core.h" /* for Elements */
+#include "glsl_symbol_table.h"
+#include "glsl_parser_extras.h"
+#include "glsl_types.h"
+#include "builtin_types.h"
+extern "C" {
+#include "program/hash_table.h"
+}
+
+hash_table *glsl_type::array_types = NULL;
+hash_table *glsl_type::record_types = NULL;
+void *glsl_type::mem_ctx = NULL;
+
+void
+glsl_type::init_talloc_type_ctx(void)
+{
+   if (glsl_type::mem_ctx == NULL) {
+      glsl_type::mem_ctx = talloc_autofree_context();
+      assert(glsl_type::mem_ctx != NULL);
+   }
+}
+
+glsl_type::glsl_type(GLenum gl_type,
+                    unsigned base_type, unsigned vector_elements,
+                    unsigned matrix_columns, const char *name) :
+   gl_type(gl_type),
+   base_type(base_type),
+   sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
+   sampler_type(0),
+   vector_elements(vector_elements), matrix_columns(matrix_columns),
+   length(0)
+{
+   init_talloc_type_ctx();
+   this->name = talloc_strdup(this->mem_ctx, name);
+   /* Neither dimension is zero or both dimensions are zero.
+    */
+   assert((vector_elements == 0) == (matrix_columns == 0));
+   memset(& fields, 0, sizeof(fields));
+}
+
+glsl_type::glsl_type(GLenum gl_type,
+                    enum glsl_sampler_dim dim, bool shadow, bool array,
+                    unsigned type, const char *name) :
+   gl_type(gl_type),
+   base_type(GLSL_TYPE_SAMPLER),
+   sampler_dimensionality(dim), sampler_shadow(shadow),
+   sampler_array(array), sampler_type(type),
+   vector_elements(0), matrix_columns(0),
+   length(0)
+{
+   init_talloc_type_ctx();
+   this->name = talloc_strdup(this->mem_ctx, name);
+   memset(& fields, 0, sizeof(fields));
+}
+
+glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
+                    const char *name) :
+   base_type(GLSL_TYPE_STRUCT),
+   sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
+   sampler_type(0),
+   vector_elements(0), matrix_columns(0),
+   length(num_fields)
+{
+   unsigned int i;
+
+   init_talloc_type_ctx();
+   this->name = talloc_strdup(this->mem_ctx, name);
+   this->fields.structure = talloc_array(this->mem_ctx,
+                                        glsl_struct_field, length);
+   for (i = 0; i < length; i++) {
+      this->fields.structure[i].type = fields[i].type;
+      this->fields.structure[i].name = talloc_strdup(this->fields.structure,
+                                                    fields[i].name);
+   }
+}
+
+static void
+add_types_to_symbol_table(glsl_symbol_table *symtab,
+                         const struct glsl_type *types,
+                         unsigned num_types, bool warn)
+{
+   (void) warn;
+
+   for (unsigned i = 0; i < num_types; i++) {
+      symtab->add_type(types[i].name, & types[i]);
+   }
+}
+
+
+void
+glsl_type::generate_110_types(glsl_symbol_table *symtab)
+{
+   add_types_to_symbol_table(symtab, builtin_core_types,
+                            Elements(builtin_core_types),
+                            false);
+   add_types_to_symbol_table(symtab, builtin_structure_types,
+                            Elements(builtin_structure_types),
+                            false);
+   add_types_to_symbol_table(symtab, builtin_110_deprecated_structure_types,
+                            Elements(builtin_110_deprecated_structure_types),
+                            false);
+   add_types_to_symbol_table(symtab, & void_type, 1, false);
+}
+
+
+void
+glsl_type::generate_120_types(glsl_symbol_table *symtab)
+{
+   generate_110_types(symtab);
+
+   add_types_to_symbol_table(symtab, builtin_120_types,
+                            Elements(builtin_120_types), false);
+}
+
+
+void
+glsl_type::generate_130_types(glsl_symbol_table *symtab)
+{
+   generate_120_types(symtab);
+
+   add_types_to_symbol_table(symtab, builtin_130_types,
+                            Elements(builtin_130_types), false);
+   generate_EXT_texture_array_types(symtab, false);
+}
+
+
+void
+glsl_type::generate_ARB_texture_rectangle_types(glsl_symbol_table *symtab,
+                                               bool warn)
+{
+   add_types_to_symbol_table(symtab, builtin_ARB_texture_rectangle_types,
+                            Elements(builtin_ARB_texture_rectangle_types),
+                            warn);
+}
+
+
+void
+glsl_type::generate_EXT_texture_array_types(glsl_symbol_table *symtab,
+                                           bool warn)
+{
+   add_types_to_symbol_table(symtab, builtin_EXT_texture_array_types,
+                            Elements(builtin_EXT_texture_array_types),
+                            warn);
+}
+
+
+void
+_mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state)
+{
+   switch (state->language_version) {
+   case 110:
+      glsl_type::generate_110_types(state->symbols);
+      break;
+   case 120:
+      glsl_type::generate_120_types(state->symbols);
+      break;
+   case 130:
+      glsl_type::generate_130_types(state->symbols);
+      break;
+   default:
+      /* error */
+      break;
+   }
+
+   if (state->ARB_texture_rectangle_enable) {
+      glsl_type::generate_ARB_texture_rectangle_types(state->symbols,
+                                          state->ARB_texture_rectangle_warn);
+   }
+
+   if (state->EXT_texture_array_enable && state->language_version < 130) {
+      // These are already included in 130; don't create twice.
+      glsl_type::generate_EXT_texture_array_types(state->symbols,
+                                      state->EXT_texture_array_warn);
+   }
+}
+
+
+const glsl_type *glsl_type::get_base_type() const
+{
+   switch (base_type) {
+   case GLSL_TYPE_UINT:
+      return uint_type;
+   case GLSL_TYPE_INT:
+      return int_type;
+   case GLSL_TYPE_FLOAT:
+      return float_type;
+   case GLSL_TYPE_BOOL:
+      return bool_type;
+   default:
+      return error_type;
+   }
+}
+
+
+void
+_mesa_glsl_release_types(void)
+{
+   if (glsl_type::array_types != NULL) {
+      hash_table_dtor(glsl_type::array_types);
+      glsl_type::array_types = NULL;
+   }
+
+   if (glsl_type::record_types != NULL) {
+      hash_table_dtor(glsl_type::record_types);
+      glsl_type::record_types = NULL;
+   }
+}
+
+
+glsl_type::glsl_type(const glsl_type *array, unsigned length) :
+   base_type(GLSL_TYPE_ARRAY),
+   sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
+   sampler_type(0),
+   vector_elements(0), matrix_columns(0),
+   name(NULL), length(length)
+{
+   this->fields.array = array;
+   /* Inherit the gl type of the base. The GL type is used for
+    * uniform/statevar handling in Mesa and the arrayness of the type
+    * is represented by the size rather than the type.
+    */
+   this->gl_type = array->gl_type;
+
+   /* Allow a maximum of 10 characters for the array size.  This is enough
+    * for 32-bits of ~0.  The extra 3 are for the '[', ']', and terminating
+    * NUL.
+    */
+   const unsigned name_length = strlen(array->name) + 10 + 3;
+   char *const n = (char *) talloc_size(this->mem_ctx, name_length);
+
+   if (length == 0)
+      snprintf(n, name_length, "%s[]", array->name);
+   else
+      snprintf(n, name_length, "%s[%u]", array->name, length);
+
+   this->name = n;
+}
+
+
+const glsl_type *
+glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns)
+{
+   if (base_type == GLSL_TYPE_VOID)
+      return &void_type;
+
+   if ((rows < 1) || (rows > 4) || (columns < 1) || (columns > 4))
+      return error_type;
+
+   /* Treat GLSL vectors as Nx1 matrices.
+    */
+   if (columns == 1) {
+      switch (base_type) {
+      case GLSL_TYPE_UINT:
+        return uint_type + (rows - 1);
+      case GLSL_TYPE_INT:
+        return int_type + (rows - 1);
+      case GLSL_TYPE_FLOAT:
+        return float_type + (rows - 1);
+      case GLSL_TYPE_BOOL:
+        return bool_type + (rows - 1);
+      default:
+        return error_type;
+      }
+   } else {
+      if ((base_type != GLSL_TYPE_FLOAT) || (rows == 1))
+        return error_type;
+
+      /* GLSL matrix types are named mat{COLUMNS}x{ROWS}.  Only the following
+       * combinations are valid:
+       *
+       *   1 2 3 4
+       * 1
+       * 2   x x x
+       * 3   x x x
+       * 4   x x x
+       */
+#define IDX(c,r) (((c-1)*3) + (r-1))
+
+      switch (IDX(columns, rows)) {
+      case IDX(2,2): return mat2_type;
+      case IDX(2,3): return mat2x3_type;
+      case IDX(2,4): return mat2x4_type;
+      case IDX(3,2): return mat3x2_type;
+      case IDX(3,3): return mat3_type;
+      case IDX(3,4): return mat3x4_type;
+      case IDX(4,2): return mat4x2_type;
+      case IDX(4,3): return mat4x3_type;
+      case IDX(4,4): return mat4_type;
+      default: return error_type;
+      }
+   }
+
+   assert(!"Should not get here.");
+   return error_type;
+}
+
+
+const glsl_type *
+glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
+{
+
+   if (array_types == NULL) {
+      array_types = hash_table_ctor(64, hash_table_string_hash,
+                                   hash_table_string_compare);
+   }
+
+   /* Generate a name using the base type pointer in the key.  This is
+    * done because the name of the base type may not be unique across
+    * shaders.  For example, two shaders may have different record types
+    * named 'foo'.
+    */
+   char key[128];
+   snprintf(key, sizeof(key), "%p[%u]", (void *) base, array_size);
+
+   const glsl_type *t = (glsl_type *) hash_table_find(array_types, key);
+   if (t == NULL) {
+      t = new glsl_type(base, array_size);
+
+      hash_table_insert(array_types, (void *) t, talloc_strdup(mem_ctx, key));
+   }
+
+   assert(t->base_type == GLSL_TYPE_ARRAY);
+   assert(t->length == array_size);
+   assert(t->fields.array == base);
+
+   return t;
+}
+
+
+int
+glsl_type::record_key_compare(const void *a, const void *b)
+{
+   const glsl_type *const key1 = (glsl_type *) a;
+   const glsl_type *const key2 = (glsl_type *) b;
+
+   /* Return zero is the types match (there is zero difference) or non-zero
+    * otherwise.
+    */
+   if (strcmp(key1->name, key2->name) != 0)
+      return 1;
+
+   if (key1->length != key2->length)
+      return 1;
+
+   for (unsigned i = 0; i < key1->length; i++) {
+      if (key1->fields.structure[i].type != key2->fields.structure[i].type)
+        return 1;
+      if (strcmp(key1->fields.structure[i].name,
+                key2->fields.structure[i].name) != 0)
+        return 1;
+   }
+
+   return 0;
+}
+
+
+unsigned
+glsl_type::record_key_hash(const void *a)
+{
+   const glsl_type *const key = (glsl_type *) a;
+   char hash_key[128];
+   unsigned size = 0;
+
+   size = snprintf(hash_key, sizeof(hash_key), "%08x", key->length);
+
+   for (unsigned i = 0; i < key->length; i++) {
+      if (size >= sizeof(hash_key))
+        break;
+
+      size += snprintf(& hash_key[size], sizeof(hash_key) - size,
+                      "%p", (void *) key->fields.structure[i].type);
+   }
+
+   return hash_table_string_hash(& hash_key);
+}
+
+
+const glsl_type *
+glsl_type::get_record_instance(const glsl_struct_field *fields,
+                              unsigned num_fields,
+                              const char *name)
+{
+   const glsl_type key(fields, num_fields, name);
+
+   if (record_types == NULL) {
+      record_types = hash_table_ctor(64, record_key_hash, record_key_compare);
+   }
+
+   const glsl_type *t = (glsl_type *) hash_table_find(record_types, & key);
+   if (t == NULL) {
+      t = new glsl_type(fields, num_fields, name);
+
+      hash_table_insert(record_types, (void *) t, t);
+   }
+
+   assert(t->base_type == GLSL_TYPE_STRUCT);
+   assert(t->length == num_fields);
+   assert(strcmp(t->name, name) == 0);
+
+   return t;
+}
+
+
+const glsl_type *
+glsl_type::field_type(const char *name) const
+{
+   if (this->base_type != GLSL_TYPE_STRUCT)
+      return error_type;
+
+   for (unsigned i = 0; i < this->length; i++) {
+      if (strcmp(name, this->fields.structure[i].name) == 0)
+        return this->fields.structure[i].type;
+   }
+
+   return error_type;
+}
+
+
+int
+glsl_type::field_index(const char *name) const
+{
+   if (this->base_type != GLSL_TYPE_STRUCT)
+      return -1;
+
+   for (unsigned i = 0; i < this->length; i++) {
+      if (strcmp(name, this->fields.structure[i].name) == 0)
+        return i;
+   }
+
+   return -1;
+}
+
+
+unsigned
+glsl_type::component_slots() const
+{
+   switch (this->base_type) {
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_FLOAT:
+   case GLSL_TYPE_BOOL:
+      return this->components();
+
+   case GLSL_TYPE_STRUCT: {
+      unsigned size = 0;
+
+      for (unsigned i = 0; i < this->length; i++)
+        size += this->fields.structure[i].type->component_slots();
+
+      return size;
+   }
+
+   case GLSL_TYPE_ARRAY:
+      return this->length * this->fields.array->component_slots();
+
+   default:
+      return 0;
+   }
+}
diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h
new file mode 100644 (file)
index 0000000..b4e83c9
--- /dev/null
@@ -0,0 +1,476 @@
+/* -*- c++ -*- */
+/*
+ * Copyright Â© 2009 Intel Corporation
+ *
+ * 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.
+ */
+
+#pragma once
+#ifndef GLSL_TYPES_H
+#define GLSL_TYPES_H
+
+#include <cstring>
+#include <cassert>
+
+extern "C" {
+#include "GL/gl.h"
+#include <talloc.h>
+}
+
+struct _mesa_glsl_parse_state;
+struct glsl_symbol_table;
+
+extern "C" void
+_mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state);
+
+extern "C" void
+_mesa_glsl_release_types(void);
+
+#define GLSL_TYPE_UINT          0
+#define GLSL_TYPE_INT           1
+#define GLSL_TYPE_FLOAT         2
+#define GLSL_TYPE_BOOL          3
+#define GLSL_TYPE_SAMPLER       4
+#define GLSL_TYPE_STRUCT        5
+#define GLSL_TYPE_ARRAY         6
+#define GLSL_TYPE_FUNCTION      7
+#define GLSL_TYPE_VOID          8
+#define GLSL_TYPE_ERROR         9
+
+enum glsl_sampler_dim {
+   GLSL_SAMPLER_DIM_1D = 0,
+   GLSL_SAMPLER_DIM_2D,
+   GLSL_SAMPLER_DIM_3D,
+   GLSL_SAMPLER_DIM_CUBE,
+   GLSL_SAMPLER_DIM_RECT,
+   GLSL_SAMPLER_DIM_BUF
+};
+
+
+struct glsl_type {
+   GLenum gl_type;
+   unsigned base_type:4;
+
+   unsigned sampler_dimensionality:3;
+   unsigned sampler_shadow:1;
+   unsigned sampler_array:1;
+   unsigned sampler_type:2;    /**< Type of data returned using this sampler.
+                               * only \c GLSL_TYPE_FLOAT, \c GLSL_TYPE_INT,
+                               * and \c GLSL_TYPE_UINT are valid.
+                               */
+
+   /* Callers of this talloc-based new need not call delete. It's
+    * easier to just talloc_free 'mem_ctx' (or any of its ancestors). */
+   static void* operator new(size_t size)
+   {
+      if (glsl_type::mem_ctx == NULL) {
+        glsl_type::mem_ctx = talloc_init("glsl_type");
+        assert(glsl_type::mem_ctx != NULL);
+      }
+
+      void *type;
+
+      type = talloc_size(glsl_type::mem_ctx, size);
+      assert(type != NULL);
+
+      return type;
+   }
+
+   /* If the user *does* call delete, that's OK, we will just
+    * talloc_free in that case. */
+   static void operator delete(void *type)
+   {
+      talloc_free(type);
+   }
+
+   /**
+    * \name Vector and matrix element counts
+    *
+    * For scalars, each of these values will be 1.  For non-numeric types
+    * these will be 0.
+    */
+   /*@{*/
+   unsigned vector_elements:3; /**< 1, 2, 3, or 4 vector elements. */
+   unsigned matrix_columns:3;  /**< 1, 2, 3, or 4 matrix columns. */
+   /*@}*/
+
+   /**
+    * Name of the data type
+    *
+    * This may be \c NULL for anonymous structures, for arrays, or for
+    * function types.
+    */
+   const char *name;
+
+   /**
+    * For \c GLSL_TYPE_ARRAY, this is the length of the array.  For
+    * \c GLSL_TYPE_STRUCT, it is the number of elements in the structure and
+    * the number of values pointed to by \c fields.structure (below).
+    *
+    * For \c GLSL_TYPE_FUNCTION, it is the number of parameters to the
+    * function.  The return value from a function is implicitly the first
+    * parameter.  The types of the parameters are stored in
+    * \c fields.parameters (below).
+    */
+   unsigned length;
+
+   /**
+    * Subtype of composite data types.
+    */
+   union {
+      const struct glsl_type *array;            /**< Type of array elements. */
+      const struct glsl_type *parameters;       /**< Parameters to function. */
+      struct glsl_struct_field *structure;      /**< List of struct fields. */
+   } fields;
+
+
+   /**
+    * \name Pointers to various public type singletons
+    */
+   /*@{*/
+   static const glsl_type *const error_type;
+   static const glsl_type *const int_type;
+   static const glsl_type *const ivec4_type;
+   static const glsl_type *const uint_type;
+   static const glsl_type *const uvec4_type;
+   static const glsl_type *const float_type;
+   static const glsl_type *const vec2_type;
+   static const glsl_type *const vec3_type;
+   static const glsl_type *const vec4_type;
+   static const glsl_type *const bool_type;
+   static const glsl_type *const mat2_type;
+   static const glsl_type *const mat2x3_type;
+   static const glsl_type *const mat2x4_type;
+   static const glsl_type *const mat3x2_type;
+   static const glsl_type *const mat3_type;
+   static const glsl_type *const mat3x4_type;
+   static const glsl_type *const mat4x2_type;
+   static const glsl_type *const mat4x3_type;
+   static const glsl_type *const mat4_type;
+   /*@}*/
+
+
+   /**
+    * For numeric and boolean derrived types returns the basic scalar type
+    *
+    * If the type is a numeric or boolean scalar, vector, or matrix type,
+    * this function gets the scalar type of the individual components.  For
+    * all other types, including arrays of numeric or boolean types, the
+    * error type is returned.
+    */
+   const glsl_type *get_base_type() const;
+
+   /**
+    * Query the type of elements in an array
+    *
+    * \return
+    * Pointer to the type of elements in the array for array types, or \c NULL
+    * for non-array types.
+    */
+   const glsl_type *element_type() const
+   {
+      return is_array() ? fields.array : NULL;
+   }
+
+   /**
+    * Get the instance of a built-in scalar, vector, or matrix type
+    */
+   static const glsl_type *get_instance(unsigned base_type, unsigned rows,
+                                       unsigned columns);
+
+   /**
+    * Get the instance of an array type
+    */
+   static const glsl_type *get_array_instance(const glsl_type *base,
+                                             unsigned elements);
+
+   /**
+    * Get the instance of a record type
+    */
+   static const glsl_type *get_record_instance(const glsl_struct_field *fields,
+                                              unsigned num_fields,
+                                              const char *name);
+
+   /**
+    * Query the total number of scalars that make up a scalar, vector or matrix
+    */
+   unsigned components() const
+   {
+      return vector_elements * matrix_columns;
+   }
+
+   /**
+    * Calculate the number of components slots required to hold this type
+    *
+    * This is used to determine how many uniform or varying locations a type
+    * might occupy.
+    */
+   unsigned component_slots() const;
+
+
+   /**
+    * Query whether or not a type is a scalar (non-vector and non-matrix).
+    */
+   bool is_scalar() const
+   {
+      return (vector_elements == 1)
+        && (base_type >= GLSL_TYPE_UINT)
+        && (base_type <= GLSL_TYPE_BOOL);
+   }
+
+   /**
+    * Query whether or not a type is a vector
+    */
+   bool is_vector() const
+   {
+      return (vector_elements > 1)
+        && (matrix_columns == 1)
+        && (base_type >= GLSL_TYPE_UINT)
+        && (base_type <= GLSL_TYPE_BOOL);
+   }
+
+   /**
+    * Query whether or not a type is a matrix
+    */
+   bool is_matrix() const
+   {
+      /* GLSL only has float matrices. */
+      return (matrix_columns > 1) && (base_type == GLSL_TYPE_FLOAT);
+   }
+
+   /**
+    * Query whether or not a type is a non-array numeric type
+    */
+   bool is_numeric() const
+   {
+      return (base_type >= GLSL_TYPE_UINT) && (base_type <= GLSL_TYPE_FLOAT);
+   }
+
+   /**
+    * Query whether or not a type is an integral type
+    */
+   bool is_integer() const
+   {
+      return (base_type == GLSL_TYPE_UINT) || (base_type == GLSL_TYPE_INT);
+   }
+
+   /**
+    * Query whether or not a type is a float type
+    */
+   bool is_float() const
+   {
+      return base_type == GLSL_TYPE_FLOAT;
+   }
+
+   /**
+    * Query whether or not a type is a non-array boolean type
+    */
+   bool is_boolean() const
+   {
+      return base_type == GLSL_TYPE_BOOL;
+   }
+
+   /**
+    * Query whether or not a type is a sampler
+    */
+   bool is_sampler() const
+   {
+      return base_type == GLSL_TYPE_SAMPLER;
+   }
+
+   /**
+    * Query whether or not a type is an array
+    */
+   bool is_array() const
+   {
+      return base_type == GLSL_TYPE_ARRAY;
+   }
+
+   /**
+    * Query whether or not a type is a record
+    */
+   bool is_record() const
+   {
+      return base_type == GLSL_TYPE_STRUCT;
+   }
+
+   /**
+    * Query whether or not a type is the void type singleton.
+    */
+   bool is_void() const
+   {
+      return base_type == GLSL_TYPE_VOID;
+   }
+
+   /**
+    * Query whether or not a type is the error type singleton.
+    */
+   bool is_error() const
+   {
+      return base_type == GLSL_TYPE_ERROR;
+   }
+
+   /**
+    * Query the full type of a matrix row
+    *
+    * \return
+    * If the type is not a matrix, \c glsl_type::error_type is returned.
+    * Otherwise a type matching the rows of the matrix is returned.
+    */
+   const glsl_type *row_type() const
+   {
+      return is_matrix()
+        ? get_instance(base_type, matrix_columns, 1)
+        : error_type;
+   }
+
+   /**
+    * Query the full type of a matrix column
+    *
+    * \return
+    * If the type is not a matrix, \c glsl_type::error_type is returned.
+    * Otherwise a type matching the columns of the matrix is returned.
+    */
+   const glsl_type *column_type() const
+   {
+      return is_matrix()
+        ? get_instance(base_type, vector_elements, 1)
+        : error_type;
+   }
+
+
+   /**
+    * Get the type of a structure field
+    *
+    * \return
+    * Pointer to the type of the named field.  If the type is not a structure
+    * or the named field does not exist, \c glsl_type::error_type is returned.
+    */
+   const glsl_type *field_type(const char *name) const;
+
+
+   /**
+    * Get the location of a filed within a record type
+    */
+   int field_index(const char *name) const;
+
+
+   /**
+    * Query the number of elements in an array type
+    *
+    * \return
+    * The number of elements in the array for array types or -1 for non-array
+    * types.  If the number of elements in the array has not yet been declared,
+    * zero is returned.
+    */
+   int array_size() const
+   {
+      return is_array() ? length : -1;
+   }
+
+private:
+   /**
+    * talloc context for all glsl_type allocations
+    *
+    * Set on the first call to \c glsl_type::new.
+    */
+   static void *mem_ctx;
+
+   void init_talloc_type_ctx(void);
+
+   /** Constructor for vector and matrix types */
+   glsl_type(GLenum gl_type,
+            unsigned base_type, unsigned vector_elements,
+            unsigned matrix_columns, const char *name);
+
+   /** Constructor for sampler types */
+   glsl_type(GLenum gl_type,
+            enum glsl_sampler_dim dim, bool shadow, bool array,
+            unsigned type, const char *name);
+
+   /** Constructor for record types */
+   glsl_type(const glsl_struct_field *fields, unsigned num_fields,
+            const char *name);
+
+   /** Constructor for array types */
+   glsl_type(const glsl_type *array, unsigned length);
+
+   /** Hash table containing the known array types. */
+   static struct hash_table *array_types;
+
+   /** Hash table containing the known record types. */
+   static struct hash_table *record_types;
+
+   static int record_key_compare(const void *a, const void *b);
+   static unsigned record_key_hash(const void *key);
+
+   /**
+    * \name Pointers to various type singletons
+    */
+   /*@{*/
+   static const glsl_type _error_type;
+   static const glsl_type void_type;
+   static const glsl_type builtin_core_types[];
+   static const glsl_type builtin_structure_types[];
+   static const glsl_type builtin_110_deprecated_structure_types[];
+   static const glsl_type builtin_120_types[];
+   static const glsl_type builtin_130_types[];
+   static const glsl_type builtin_ARB_texture_rectangle_types[];
+   static const glsl_type builtin_EXT_texture_array_types[];
+   static const glsl_type builtin_EXT_texture_buffer_object_types[];
+   /*@}*/
+
+   /**
+    * \name Methods to populate a symbol table with built-in types.
+    *
+    * \internal
+    * This is one of the truely annoying things about C++.  Methods that are
+    * completely internal and private to a type still have to be advertised to
+    * the world in a public header file.
+    */
+   /*@{*/
+   static void generate_110_types(glsl_symbol_table *);
+   static void generate_120_types(glsl_symbol_table *);
+   static void generate_130_types(glsl_symbol_table *);
+   static void generate_ARB_texture_rectangle_types(glsl_symbol_table *,
+                                                   bool);
+   static void generate_EXT_texture_array_types(glsl_symbol_table *,
+                                               bool);
+   /*@}*/
+
+   /**
+    * \name Friend functions.
+    *
+    * These functions are friends because they must have C linkage and the
+    * need to call various private methods or access various private static
+    * data.
+    */
+   /*@{*/
+   friend void _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *);
+   friend void _mesa_glsl_release_types(void);
+   /*@}*/
+};
+
+struct glsl_struct_field {
+   const struct glsl_type *type;
+   const char *name;
+};
+
+#endif /* GLSL_TYPES_H */
diff --git a/src/glsl/hir_field_selection.cpp b/src/glsl/hir_field_selection.cpp
new file mode 100644 (file)
index 0000000..3c33127
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 "ir.h"
+#include "program/symbol_table.h"
+#include "glsl_parser_extras.h"
+#include "ast.h"
+#include "glsl_types.h"
+
+ir_rvalue *
+_mesa_ast_field_selection_to_hir(const ast_expression *expr,
+                                exec_list *instructions,
+                                struct _mesa_glsl_parse_state *state)
+{
+   void *ctx = state;
+   ir_rvalue *result = NULL;
+   ir_rvalue *op;
+
+   op = expr->subexpressions[0]->hir(instructions, state);
+
+   /* There are two kinds of field selection.  There is the selection of a
+    * specific field from a structure, and there is the selection of a
+    * swizzle / mask from a vector.  Which is which is determined entirely
+    * by the base type of the thing to which the field selection operator is
+    * being applied.
+    */
+   YYLTYPE loc = expr->get_location();
+   if (op->type->is_error()) {
+      /* silently propagate the error */
+   } else if (op->type->is_vector()) {
+      ir_swizzle *swiz = ir_swizzle::create(op,
+                                           expr->primary_expression.identifier,
+                                           op->type->vector_elements);
+      if (swiz != NULL) {
+        result = swiz;
+      } else {
+        /* FINISHME: Logging of error messages should be moved into
+         * FINISHME: ir_swizzle::create.  This allows the generation of more
+         * FINISHME: specific error messages.
+         */
+        _mesa_glsl_error(& loc, state, "Invalid swizzle / mask `%s'",
+                         expr->primary_expression.identifier);
+      }
+   } else if (op->type->base_type == GLSL_TYPE_STRUCT) {
+      result = new(ctx) ir_dereference_record(op,
+                                             expr->primary_expression.identifier);
+
+      if (result->type->is_error()) {
+        _mesa_glsl_error(& loc, state, "Cannot access field `%s' of "
+                         "structure",
+                         expr->primary_expression.identifier);
+      }
+   } else if (expr->subexpressions[1] != NULL) {
+      /* Handle "method calls" in GLSL 1.20 - namely, array.length() */
+      if (state->language_version < 120)
+        _mesa_glsl_error(&loc, state, "Methods not supported in GLSL 1.10.");
+
+      ast_expression *call = expr->subexpressions[1];
+      assert(call->oper == ast_function_call);
+
+      const char *method;
+      method = call->subexpressions[0]->primary_expression.identifier;
+
+      if (op->type->is_array() && strcmp(method, "length") == 0) {
+        if (!call->expressions.is_empty())
+           _mesa_glsl_error(&loc, state, "length method takes no arguments.");
+
+        if (op->type->array_size() == 0)
+           _mesa_glsl_error(&loc, state, "length called on unsized array.");
+
+        result = new(ctx) ir_constant(op->type->array_size());
+      } else {
+        _mesa_glsl_error(&loc, state, "Unknown method: `%s'.", method);
+      }
+   } else {
+      _mesa_glsl_error(& loc, state, "Cannot access field `%s' of "
+                      "non-structure / non-vector.",
+                      expr->primary_expression.identifier);
+   }
+
+   return result ? result : ir_call::get_error_instruction(ctx);
+}
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
new file mode 100644 (file)
index 0000000..68ad512
--- /dev/null
@@ -0,0 +1,1175 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 <string.h>
+#include "main/core.h" /* for MAX2 */
+#include "ir.h"
+#include "ir_visitor.h"
+#include "glsl_types.h"
+
+ir_rvalue::ir_rvalue()
+{
+   this->type = glsl_type::error_type;
+}
+
+/**
+ * Modify the swizzle make to move one component to another
+ *
+ * \param m    IR swizzle to be modified
+ * \param from Component in the RHS that is to be swizzled
+ * \param to   Desired swizzle location of \c from
+ */
+static void
+update_rhs_swizzle(ir_swizzle_mask &m, unsigned from, unsigned to)
+{
+   switch (to) {
+   case 0: m.x = from; break;
+   case 1: m.y = from; break;
+   case 2: m.z = from; break;
+   case 3: m.w = from; break;
+   default: assert(!"Should not get here.");
+   }
+
+   m.num_components = MAX2(m.num_components, (to + 1));
+}
+
+void
+ir_assignment::set_lhs(ir_rvalue *lhs)
+{
+   while (lhs != NULL) {
+      ir_swizzle *swiz = lhs->as_swizzle();
+
+      if (swiz == NULL)
+        break;
+
+      unsigned write_mask = 0;
+      ir_swizzle_mask rhs_swiz = { 0, 0, 0, 0, 0, 0 };
+
+      for (unsigned i = 0; i < swiz->mask.num_components; i++) {
+        unsigned c = 0;
+
+        switch (i) {
+        case 0: c = swiz->mask.x; break;
+        case 1: c = swiz->mask.y; break;
+        case 2: c = swiz->mask.z; break;
+        case 3: c = swiz->mask.w; break;
+        default: assert(!"Should not get here.");
+        }
+
+        write_mask |= (((this->write_mask >> i) & 1) << c);
+        update_rhs_swizzle(rhs_swiz, i, c);
+      }
+
+      this->write_mask = write_mask;
+      lhs = swiz->val;
+
+      this->rhs = new(this) ir_swizzle(this->rhs, rhs_swiz);
+   }
+
+   assert((lhs == NULL) || lhs->as_dereference());
+
+   this->lhs = (ir_dereference *) lhs;
+}
+
+ir_variable *
+ir_assignment::whole_variable_written()
+{
+   ir_variable *v = this->lhs->whole_variable_referenced();
+
+   if (v == NULL)
+      return NULL;
+
+   if (v->type->is_scalar())
+      return v;
+
+   if (v->type->is_vector()) {
+      const unsigned mask = (1U << v->type->vector_elements) - 1;
+
+      if (mask != this->write_mask)
+        return NULL;
+   }
+
+   /* Either all the vector components are assigned or the variable is some
+    * composite type (and the whole thing is assigned.
+    */
+   return v;
+}
+
+ir_assignment::ir_assignment(ir_dereference *lhs, ir_rvalue *rhs,
+                            ir_rvalue *condition, unsigned write_mask)
+{
+   this->ir_type = ir_type_assignment;
+   this->condition = condition;
+   this->rhs = rhs;
+   this->lhs = lhs;
+   this->write_mask = write_mask;
+}
+
+ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs,
+                            ir_rvalue *condition)
+{
+   this->ir_type = ir_type_assignment;
+   this->condition = condition;
+   this->rhs = rhs;
+
+   /* If the RHS is a vector type, assume that all components of the vector
+    * type are being written to the LHS.  The write mask comes from the RHS
+    * because we can have a case where the LHS is a vec4 and the RHS is a
+    * vec3.  In that case, the assignment is:
+    *
+    *     (assign (...) (xyz) (var_ref lhs) (var_ref rhs))
+    */
+   if (rhs->type->is_vector())
+      this->write_mask = (1U << rhs->type->vector_elements) - 1;
+   else if (rhs->type->is_scalar())
+      this->write_mask = 1;
+   else
+      this->write_mask = 0;
+
+   this->set_lhs(lhs);
+}
+
+
+ir_expression::ir_expression(int op, const struct glsl_type *type,
+                            ir_rvalue *op0, ir_rvalue *op1)
+{
+   this->ir_type = ir_type_expression;
+   this->type = type;
+   this->operation = ir_expression_operation(op);
+   this->operands[0] = op0;
+   this->operands[1] = op1;
+}
+
+unsigned int
+ir_expression::get_num_operands(ir_expression_operation op)
+{
+/* Update ir_print_visitor.cpp when updating this list. */
+   const int num_operands[] = {
+      1, /* ir_unop_bit_not */
+      1, /* ir_unop_logic_not */
+      1, /* ir_unop_neg */
+      1, /* ir_unop_abs */
+      1, /* ir_unop_sign */
+      1, /* ir_unop_rcp */
+      1, /* ir_unop_rsq */
+      1, /* ir_unop_sqrt */
+      1, /* ir_unop_exp */
+      1, /* ir_unop_log */
+      1, /* ir_unop_exp2 */
+      1, /* ir_unop_log2 */
+      1, /* ir_unop_f2i */
+      1, /* ir_unop_i2f */
+      1, /* ir_unop_f2b */
+      1, /* ir_unop_b2f */
+      1, /* ir_unop_i2b */
+      1, /* ir_unop_b2i */
+      1, /* ir_unop_u2f */
+      1, /* ir_unop_any */
+
+      1, /* ir_unop_trunc */
+      1, /* ir_unop_ceil */
+      1, /* ir_unop_floor */
+      1, /* ir_unop_fract */
+
+      1, /* ir_unop_sin */
+      1, /* ir_unop_cos */
+
+      1, /* ir_unop_dFdx */
+      1, /* ir_unop_dFdy */
+
+      2, /* ir_binop_add */
+      2, /* ir_binop_sub */
+      2, /* ir_binop_mul */
+      2, /* ir_binop_div */
+      2, /* ir_binop_mod */
+
+      2, /* ir_binop_less */
+      2, /* ir_binop_greater */
+      2, /* ir_binop_lequal */
+      2, /* ir_binop_gequal */
+      2, /* ir_binop_equal */
+      2, /* ir_binop_nequal */
+
+      2, /* ir_binop_lshift */
+      2, /* ir_binop_rshift */
+      2, /* ir_binop_bit_and */
+      2, /* ir_binop_bit_xor */
+      2, /* ir_binop_bit_or */
+
+      2, /* ir_binop_logic_and */
+      2, /* ir_binop_logic_xor */
+      2, /* ir_binop_logic_or */
+
+      2, /* ir_binop_dot */
+      2, /* ir_binop_cross */
+      2, /* ir_binop_min */
+      2, /* ir_binop_max */
+
+      2, /* ir_binop_pow */
+   };
+
+   assert(sizeof(num_operands) / sizeof(num_operands[0]) == ir_binop_pow + 1);
+
+   return num_operands[op];
+}
+
+static const char *const operator_strs[] = {
+   "~",
+   "!",
+   "neg",
+   "abs",
+   "sign",
+   "rcp",
+   "rsq",
+   "sqrt",
+   "exp",
+   "log",
+   "exp2",
+   "log2",
+   "f2i",
+   "i2f",
+   "f2b",
+   "b2f",
+   "i2b",
+   "b2i",
+   "u2f",
+   "any",
+   "trunc",
+   "ceil",
+   "floor",
+   "fract",
+   "sin",
+   "cos",
+   "dFdx",
+   "dFdy",
+   "+",
+   "-",
+   "*",
+   "/",
+   "%",
+   "<",
+   ">",
+   "<=",
+   ">=",
+   "==",
+   "!=",
+   "<<",
+   ">>",
+   "&",
+   "^",
+   "|",
+   "&&",
+   "^^",
+   "||",
+   "dot",
+   "cross",
+   "min",
+   "max",
+   "pow",
+};
+
+const char *ir_expression::operator_string()
+{
+   assert((unsigned int) operation <=
+         sizeof(operator_strs) / sizeof(operator_strs[0]));
+   return operator_strs[operation];
+}
+
+ir_expression_operation
+ir_expression::get_operator(const char *str)
+{
+   const int operator_count = sizeof(operator_strs) / sizeof(operator_strs[0]);
+   for (int op = 0; op < operator_count; op++) {
+      if (strcmp(str, operator_strs[op]) == 0)
+        return (ir_expression_operation) op;
+   }
+   return (ir_expression_operation) -1;
+}
+
+ir_constant::ir_constant()
+{
+   this->ir_type = ir_type_constant;
+}
+
+ir_constant::ir_constant(const struct glsl_type *type,
+                        const ir_constant_data *data)
+{
+   assert((type->base_type >= GLSL_TYPE_UINT)
+         && (type->base_type <= GLSL_TYPE_BOOL));
+
+   this->ir_type = ir_type_constant;
+   this->type = type;
+   memcpy(& this->value, data, sizeof(this->value));
+}
+
+ir_constant::ir_constant(float f)
+{
+   this->ir_type = ir_type_constant;
+   this->type = glsl_type::float_type;
+   this->value.f[0] = f;
+   for (int i = 1; i < 16; i++)  {
+      this->value.f[i] = 0;
+   }
+}
+
+ir_constant::ir_constant(unsigned int u)
+{
+   this->ir_type = ir_type_constant;
+   this->type = glsl_type::uint_type;
+   this->value.u[0] = u;
+   for (int i = 1; i < 16; i++) {
+      this->value.u[i] = 0;
+   }
+}
+
+ir_constant::ir_constant(int i)
+{
+   this->ir_type = ir_type_constant;
+   this->type = glsl_type::int_type;
+   this->value.i[0] = i;
+   for (int i = 1; i < 16; i++) {
+      this->value.i[i] = 0;
+   }
+}
+
+ir_constant::ir_constant(bool b)
+{
+   this->ir_type = ir_type_constant;
+   this->type = glsl_type::bool_type;
+   this->value.b[0] = b;
+   for (int i = 1; i < 16; i++) {
+      this->value.b[i] = false;
+   }
+}
+
+ir_constant::ir_constant(const ir_constant *c, unsigned i)
+{
+   this->ir_type = ir_type_constant;
+   this->type = c->type->get_base_type();
+
+   switch (this->type->base_type) {
+   case GLSL_TYPE_UINT:  this->value.u[0] = c->value.u[i]; break;
+   case GLSL_TYPE_INT:   this->value.i[0] = c->value.i[i]; break;
+   case GLSL_TYPE_FLOAT: this->value.f[0] = c->value.f[i]; break;
+   case GLSL_TYPE_BOOL:  this->value.b[0] = c->value.b[i]; break;
+   default:              assert(!"Should not get here."); break;
+   }
+}
+
+ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
+{
+   this->ir_type = ir_type_constant;
+   this->type = type;
+
+   assert(type->is_scalar() || type->is_vector() || type->is_matrix()
+         || type->is_record() || type->is_array());
+
+   if (type->is_array()) {
+      this->array_elements = talloc_array(this, ir_constant *, type->length);
+      unsigned i = 0;
+      foreach_list(node, value_list) {
+        ir_constant *value = (ir_constant *) node;
+        assert(value->as_constant() != NULL);
+
+        this->array_elements[i++] = value;
+      }
+      return;
+   }
+
+   /* If the constant is a record, the types of each of the entries in
+    * value_list must be a 1-for-1 match with the structure components.  Each
+    * entry must also be a constant.  Just move the nodes from the value_list
+    * to the list in the ir_constant.
+    */
+   /* FINISHME: Should there be some type checking and / or assertions here? */
+   /* FINISHME: Should the new constant take ownership of the nodes from
+    * FINISHME: value_list, or should it make copies?
+    */
+   if (type->is_record()) {
+      value_list->move_nodes_to(& this->components);
+      return;
+   }
+
+   for (unsigned i = 0; i < 16; i++) {
+      this->value.u[i] = 0;
+   }
+
+   ir_constant *value = (ir_constant *) (value_list->head);
+
+   /* Constructors with exactly one scalar argument are special for vectors
+    * and matrices.  For vectors, the scalar value is replicated to fill all
+    * the components.  For matrices, the scalar fills the components of the
+    * diagonal while the rest is filled with 0.
+    */
+   if (value->type->is_scalar() && value->next->is_tail_sentinel()) {
+      if (type->is_matrix()) {
+        /* Matrix - fill diagonal (rest is already set to 0) */
+        assert(type->base_type == GLSL_TYPE_FLOAT);
+        for (unsigned i = 0; i < type->matrix_columns; i++)
+           this->value.f[i * type->vector_elements + i] = value->value.f[0];
+      } else {
+        /* Vector or scalar - fill all components */
+        switch (type->base_type) {
+        case GLSL_TYPE_UINT:
+        case GLSL_TYPE_INT:
+           for (unsigned i = 0; i < type->components(); i++)
+              this->value.u[i] = value->value.u[0];
+           break;
+        case GLSL_TYPE_FLOAT:
+           for (unsigned i = 0; i < type->components(); i++)
+              this->value.f[i] = value->value.f[0];
+           break;
+        case GLSL_TYPE_BOOL:
+           for (unsigned i = 0; i < type->components(); i++)
+              this->value.b[i] = value->value.b[0];
+           break;
+        default:
+           assert(!"Should not get here.");
+           break;
+        }
+      }
+      return;
+   }
+
+   if (type->is_matrix() && value->type->is_matrix()) {
+      assert(value->next->is_tail_sentinel());
+
+      /* From section 5.4.2 of the GLSL 1.20 spec:
+       * "If a matrix is constructed from a matrix, then each component
+       *  (column i, row j) in the result that has a corresponding component
+       *  (column i, row j) in the argument will be initialized from there."
+       */
+      unsigned cols = MIN2(type->matrix_columns, value->type->matrix_columns);
+      unsigned rows = MIN2(type->vector_elements, value->type->vector_elements);
+      for (unsigned i = 0; i < cols; i++) {
+        for (unsigned j = 0; j < rows; j++) {
+           const unsigned src = i * value->type->vector_elements + j;
+           const unsigned dst = i * type->vector_elements + j;
+           this->value.f[dst] = value->value.f[src];
+        }
+      }
+
+      /* "All other components will be initialized to the identity matrix." */
+      for (unsigned i = cols; i < type->matrix_columns; i++)
+        this->value.f[i * type->vector_elements + i] = 1.0;
+
+      return;
+   }
+
+   /* Use each component from each entry in the value_list to initialize one
+    * component of the constant being constructed.
+    */
+   for (unsigned i = 0; i < type->components(); /* empty */) {
+      assert(value->as_constant() != NULL);
+      assert(!value->is_tail_sentinel());
+
+      for (unsigned j = 0; j < value->type->components(); j++) {
+        switch (type->base_type) {
+        case GLSL_TYPE_UINT:
+           this->value.u[i] = value->get_uint_component(j);
+           break;
+        case GLSL_TYPE_INT:
+           this->value.i[i] = value->get_int_component(j);
+           break;
+        case GLSL_TYPE_FLOAT:
+           this->value.f[i] = value->get_float_component(j);
+           break;
+        case GLSL_TYPE_BOOL:
+           this->value.b[i] = value->get_bool_component(j);
+           break;
+        default:
+           /* FINISHME: What to do?  Exceptions are not the answer.
+            */
+           break;
+        }
+
+        i++;
+        if (i >= type->components())
+           break;
+      }
+
+      value = (ir_constant *) value->next;
+   }
+}
+
+ir_constant *
+ir_constant::zero(void *mem_ctx, const glsl_type *type)
+{
+   assert(type->is_numeric() || type->is_boolean());
+
+   ir_constant *c = new(mem_ctx) ir_constant;
+   c->type = type;
+   memset(&c->value, 0, sizeof(c->value));
+
+   return c;
+}
+
+bool
+ir_constant::get_bool_component(unsigned i) const
+{
+   switch (this->type->base_type) {
+   case GLSL_TYPE_UINT:  return this->value.u[i] != 0;
+   case GLSL_TYPE_INT:   return this->value.i[i] != 0;
+   case GLSL_TYPE_FLOAT: return ((int)this->value.f[i]) != 0;
+   case GLSL_TYPE_BOOL:  return this->value.b[i];
+   default:              assert(!"Should not get here."); break;
+   }
+
+   /* Must return something to make the compiler happy.  This is clearly an
+    * error case.
+    */
+   return false;
+}
+
+float
+ir_constant::get_float_component(unsigned i) const
+{
+   switch (this->type->base_type) {
+   case GLSL_TYPE_UINT:  return (float) this->value.u[i];
+   case GLSL_TYPE_INT:   return (float) this->value.i[i];
+   case GLSL_TYPE_FLOAT: return this->value.f[i];
+   case GLSL_TYPE_BOOL:  return this->value.b[i] ? 1.0 : 0.0;
+   default:              assert(!"Should not get here."); break;
+   }
+
+   /* Must return something to make the compiler happy.  This is clearly an
+    * error case.
+    */
+   return 0.0;
+}
+
+int
+ir_constant::get_int_component(unsigned i) const
+{
+   switch (this->type->base_type) {
+   case GLSL_TYPE_UINT:  return this->value.u[i];
+   case GLSL_TYPE_INT:   return this->value.i[i];
+   case GLSL_TYPE_FLOAT: return (int) this->value.f[i];
+   case GLSL_TYPE_BOOL:  return this->value.b[i] ? 1 : 0;
+   default:              assert(!"Should not get here."); break;
+   }
+
+   /* Must return something to make the compiler happy.  This is clearly an
+    * error case.
+    */
+   return 0;
+}
+
+unsigned
+ir_constant::get_uint_component(unsigned i) const
+{
+   switch (this->type->base_type) {
+   case GLSL_TYPE_UINT:  return this->value.u[i];
+   case GLSL_TYPE_INT:   return this->value.i[i];
+   case GLSL_TYPE_FLOAT: return (unsigned) this->value.f[i];
+   case GLSL_TYPE_BOOL:  return this->value.b[i] ? 1 : 0;
+   default:              assert(!"Should not get here."); break;
+   }
+
+   /* Must return something to make the compiler happy.  This is clearly an
+    * error case.
+    */
+   return 0;
+}
+
+ir_constant *
+ir_constant::get_array_element(unsigned i) const
+{
+   assert(this->type->is_array());
+
+   /* From page 35 (page 41 of the PDF) of the GLSL 1.20 spec:
+    *
+    *     "Behavior is undefined if a shader subscripts an array with an index
+    *     less than 0 or greater than or equal to the size the array was
+    *     declared with."
+    *
+    * Most out-of-bounds accesses are removed before things could get this far.
+    * There are cases where non-constant array index values can get constant
+    * folded.
+    */
+   if (int(i) < 0)
+      i = 0;
+   else if (i >= this->type->length)
+      i = this->type->length - 1;
+
+   return array_elements[i];
+}
+
+ir_constant *
+ir_constant::get_record_field(const char *name)
+{
+   int idx = this->type->field_index(name);
+
+   if (idx < 0)
+      return NULL;
+
+   if (this->components.is_empty())
+      return NULL;
+
+   exec_node *node = this->components.head;
+   for (int i = 0; i < idx; i++) {
+      node = node->next;
+
+      /* If the end of the list is encountered before the element matching the
+       * requested field is found, return NULL.
+       */
+      if (node->is_tail_sentinel())
+        return NULL;
+   }
+
+   return (ir_constant *) node;
+}
+
+
+bool
+ir_constant::has_value(const ir_constant *c) const
+{
+   if (this->type != c->type)
+      return false;
+
+   if (this->type->is_array()) {
+      for (unsigned i = 0; i < this->type->length; i++) {
+        if (this->array_elements[i]->has_value(c->array_elements[i]))
+           return false;
+      }
+      return true;
+   }
+
+   if (this->type->base_type == GLSL_TYPE_STRUCT) {
+      const exec_node *a_node = this->components.head;
+      const exec_node *b_node = c->components.head;
+
+      while (!a_node->is_tail_sentinel()) {
+        assert(!b_node->is_tail_sentinel());
+
+        const ir_constant *const a_field = (ir_constant *) a_node;
+        const ir_constant *const b_field = (ir_constant *) b_node;
+
+        if (!a_field->has_value(b_field))
+           return false;
+
+        a_node = a_node->next;
+        b_node = b_node->next;
+      }
+
+      return true;
+   }
+
+   for (unsigned i = 0; i < this->type->components(); i++) {
+      switch (this->type->base_type) {
+      case GLSL_TYPE_UINT:
+        if (this->value.u[i] != c->value.u[i])
+           return false;
+        break;
+      case GLSL_TYPE_INT:
+        if (this->value.i[i] != c->value.i[i])
+           return false;
+        break;
+      case GLSL_TYPE_FLOAT:
+        if (this->value.f[i] != c->value.f[i])
+           return false;
+        break;
+      case GLSL_TYPE_BOOL:
+        if (this->value.b[i] != c->value.b[i])
+           return false;
+        break;
+      default:
+        assert(!"Should not get here.");
+        return false;
+      }
+   }
+
+   return true;
+}
+
+ir_dereference_variable::ir_dereference_variable(ir_variable *var)
+{
+   this->ir_type = ir_type_dereference_variable;
+   this->var = var;
+   this->type = (var != NULL) ? var->type : glsl_type::error_type;
+}
+
+
+ir_dereference_array::ir_dereference_array(ir_rvalue *value,
+                                          ir_rvalue *array_index)
+{
+   this->ir_type = ir_type_dereference_array;
+   this->array_index = array_index;
+   this->set_array(value);
+}
+
+
+ir_dereference_array::ir_dereference_array(ir_variable *var,
+                                          ir_rvalue *array_index)
+{
+   void *ctx = talloc_parent(var);
+
+   this->ir_type = ir_type_dereference_array;
+   this->array_index = array_index;
+   this->set_array(new(ctx) ir_dereference_variable(var));
+}
+
+
+void
+ir_dereference_array::set_array(ir_rvalue *value)
+{
+   this->array = value;
+   this->type = glsl_type::error_type;
+
+   if (this->array != NULL) {
+      const glsl_type *const vt = this->array->type;
+
+      if (vt->is_array()) {
+        type = vt->element_type();
+      } else if (vt->is_matrix()) {
+        type = vt->column_type();
+      } else if (vt->is_vector()) {
+        type = vt->get_base_type();
+      }
+   }
+}
+
+
+ir_dereference_record::ir_dereference_record(ir_rvalue *value,
+                                            const char *field)
+{
+   this->ir_type = ir_type_dereference_record;
+   this->record = value;
+   this->field = talloc_strdup(this, field);
+   this->type = (this->record != NULL)
+      ? this->record->type->field_type(field) : glsl_type::error_type;
+}
+
+
+ir_dereference_record::ir_dereference_record(ir_variable *var,
+                                            const char *field)
+{
+   void *ctx = talloc_parent(var);
+
+   this->ir_type = ir_type_dereference_record;
+   this->record = new(ctx) ir_dereference_variable(var);
+   this->field = talloc_strdup(this, field);
+   this->type = (this->record != NULL)
+      ? this->record->type->field_type(field) : glsl_type::error_type;
+}
+
+bool type_contains_sampler(const glsl_type *type)
+{
+   if (type->is_array()) {
+      return type_contains_sampler(type->fields.array);
+   } else if (type->is_record()) {
+      for (unsigned int i = 0; i < type->length; i++) {
+        if (type_contains_sampler(type->fields.structure[i].type))
+           return true;
+      }
+      return false;
+   } else {
+      return type->is_sampler();
+   }
+}
+
+bool
+ir_dereference::is_lvalue()
+{
+   ir_variable *var = this->variable_referenced();
+
+   /* Every l-value derference chain eventually ends in a variable.
+    */
+   if ((var == NULL) || var->read_only)
+      return false;
+
+   if (this->type->is_array() && !var->array_lvalue)
+      return false;
+
+   /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec:
+    *
+    *    "Samplers cannot be treated as l-values; hence cannot be used
+    *     as out or inout function parameters, nor can they be
+    *     assigned into."
+    */
+   if (type_contains_sampler(this->type))
+      return false;
+
+   return true;
+}
+
+
+const char *tex_opcode_strs[] = { "tex", "txb", "txl", "txd", "txf" };
+
+const char *ir_texture::opcode_string()
+{
+   assert((unsigned int) op <=
+         sizeof(tex_opcode_strs) / sizeof(tex_opcode_strs[0]));
+   return tex_opcode_strs[op];
+}
+
+ir_texture_opcode
+ir_texture::get_opcode(const char *str)
+{
+   const int count = sizeof(tex_opcode_strs) / sizeof(tex_opcode_strs[0]);
+   for (int op = 0; op < count; op++) {
+      if (strcmp(str, tex_opcode_strs[op]) == 0)
+        return (ir_texture_opcode) op;
+   }
+   return (ir_texture_opcode) -1;
+}
+
+
+void
+ir_texture::set_sampler(ir_dereference *sampler)
+{
+   assert(sampler != NULL);
+   this->sampler = sampler;
+
+   switch (sampler->type->sampler_type) {
+   case GLSL_TYPE_FLOAT:
+      this->type = glsl_type::vec4_type;
+      break;
+   case GLSL_TYPE_INT:
+      this->type = glsl_type::ivec4_type;
+      break;
+   case GLSL_TYPE_UINT:
+      this->type = glsl_type::uvec4_type;
+      break;
+   }
+}
+
+
+void
+ir_swizzle::init_mask(const unsigned *comp, unsigned count)
+{
+   assert((count >= 1) && (count <= 4));
+
+   memset(&this->mask, 0, sizeof(this->mask));
+   this->mask.num_components = count;
+
+   unsigned dup_mask = 0;
+   switch (count) {
+   case 4:
+      assert(comp[3] <= 3);
+      dup_mask |= (1U << comp[3])
+        & ((1U << comp[0]) | (1U << comp[1]) | (1U << comp[2]));
+      this->mask.w = comp[3];
+
+   case 3:
+      assert(comp[2] <= 3);
+      dup_mask |= (1U << comp[2])
+        & ((1U << comp[0]) | (1U << comp[1]));
+      this->mask.z = comp[2];
+
+   case 2:
+      assert(comp[1] <= 3);
+      dup_mask |= (1U << comp[1])
+        & ((1U << comp[0]));
+      this->mask.y = comp[1];
+
+   case 1:
+      assert(comp[0] <= 3);
+      this->mask.x = comp[0];
+   }
+
+   this->mask.has_duplicates = dup_mask != 0;
+
+   /* Based on the number of elements in the swizzle and the base type
+    * (i.e., float, int, unsigned, or bool) of the vector being swizzled,
+    * generate the type of the resulting value.
+    */
+   type = glsl_type::get_instance(val->type->base_type, mask.num_components, 1);
+}
+
+ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z,
+                      unsigned w, unsigned count)
+   : val(val)
+{
+   const unsigned components[4] = { x, y, z, w };
+   this->ir_type = ir_type_swizzle;
+   this->init_mask(components, count);
+}
+
+ir_swizzle::ir_swizzle(ir_rvalue *val, const unsigned *comp,
+                      unsigned count)
+   : val(val)
+{
+   this->ir_type = ir_type_swizzle;
+   this->init_mask(comp, count);
+}
+
+ir_swizzle::ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask)
+{
+   this->ir_type = ir_type_swizzle;
+   this->val = val;
+   this->mask = mask;
+   this->type = glsl_type::get_instance(val->type->base_type,
+                                       mask.num_components, 1);
+}
+
+#define X 1
+#define R 5
+#define S 9
+#define I 13
+
+ir_swizzle *
+ir_swizzle::create(ir_rvalue *val, const char *str, unsigned vector_length)
+{
+   void *ctx = talloc_parent(val);
+
+   /* For each possible swizzle character, this table encodes the value in
+    * \c idx_map that represents the 0th element of the vector.  For invalid
+    * swizzle characters (e.g., 'k'), a special value is used that will allow
+    * detection of errors.
+    */
+   static const unsigned char base_idx[26] = {
+   /* a  b  c  d  e  f  g  h  i  j  k  l  m */
+      R, R, I, I, I, I, R, I, I, I, I, I, I,
+   /* n  o  p  q  r  s  t  u  v  w  x  y  z */
+      I, I, S, S, R, S, S, I, I, X, X, X, X
+   };
+
+   /* Each valid swizzle character has an entry in the previous table.  This
+    * table encodes the base index encoded in the previous table plus the actual
+    * index of the swizzle character.  When processing swizzles, the first
+    * character in the string is indexed in the previous table.  Each character
+    * in the string is indexed in this table, and the value found there has the
+    * value form the first table subtracted.  The result must be on the range
+    * [0,3].
+    *
+    * For example, the string "wzyx" will get X from the first table.  Each of
+    * the charcaters will get X+3, X+2, X+1, and X+0 from this table.  After
+    * subtraction, the swizzle values are { 3, 2, 1, 0 }.
+    *
+    * The string "wzrg" will get X from the first table.  Each of the characters
+    * will get X+3, X+2, R+0, and R+1 from this table.  After subtraction, the
+    * swizzle values are { 3, 2, 4, 5 }.  Since 4 and 5 are outside the range
+    * [0,3], the error is detected.
+    */
+   static const unsigned char idx_map[26] = {
+   /* a    b    c    d    e    f    g    h    i    j    k    l    m */
+      R+3, R+2, 0,   0,   0,   0,   R+1, 0,   0,   0,   0,   0,   0,
+   /* n    o    p    q    r    s    t    u    v    w    x    y    z */
+      0,   0,   S+2, S+3, R+0, S+0, S+1, 0,   0,   X+3, X+0, X+1, X+2
+   };
+
+   int swiz_idx[4] = { 0, 0, 0, 0 };
+   unsigned i;
+
+
+   /* Validate the first character in the swizzle string and look up the base
+    * index value as described above.
+    */
+   if ((str[0] < 'a') || (str[0] > 'z'))
+      return NULL;
+
+   const unsigned base = base_idx[str[0] - 'a'];
+
+
+   for (i = 0; (i < 4) && (str[i] != '\0'); i++) {
+      /* Validate the next character, and, as described above, convert it to a
+       * swizzle index.
+       */
+      if ((str[i] < 'a') || (str[i] > 'z'))
+        return NULL;
+
+      swiz_idx[i] = idx_map[str[i] - 'a'] - base;
+      if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length))
+        return NULL;
+   }
+
+   if (str[i] != '\0')
+        return NULL;
+
+   return new(ctx) ir_swizzle(val, swiz_idx[0], swiz_idx[1], swiz_idx[2],
+                             swiz_idx[3], i);
+}
+
+#undef X
+#undef R
+#undef S
+#undef I
+
+ir_variable *
+ir_swizzle::variable_referenced()
+{
+   return this->val->variable_referenced();
+}
+
+
+ir_variable::ir_variable(const struct glsl_type *type, const char *name,
+                        ir_variable_mode mode)
+   : max_array_access(0), read_only(false), centroid(false), invariant(false),
+     mode(mode), interpolation(ir_var_smooth), array_lvalue(false)
+{
+   this->ir_type = ir_type_variable;
+   this->type = type;
+   this->name = talloc_strdup(this, name);
+   this->location = -1;
+   this->warn_extension = NULL;
+   this->constant_value = NULL;
+   this->origin_upper_left = false;
+   this->pixel_center_integer = false;
+
+   if (type && type->base_type == GLSL_TYPE_SAMPLER)
+      this->read_only = true;
+}
+
+
+const char *
+ir_variable::interpolation_string() const
+{
+   switch (this->interpolation) {
+   case ir_var_smooth:        return "smooth";
+   case ir_var_flat:          return "flat";
+   case ir_var_noperspective: return "noperspective";
+   }
+
+   assert(!"Should not get here.");
+   return "";
+}
+
+
+unsigned
+ir_variable::component_slots() const
+{
+   /* FINISHME: Sparsely accessed arrays require fewer slots. */
+   return this->type->component_slots();
+}
+
+
+ir_function_signature::ir_function_signature(const glsl_type *return_type)
+   : return_type(return_type), is_defined(false), _function(NULL)
+{
+   this->ir_type = ir_type_function_signature;
+}
+
+
+const char *
+ir_function_signature::qualifiers_match(exec_list *params)
+{
+   exec_list_iterator iter_a = parameters.iterator();
+   exec_list_iterator iter_b = params->iterator();
+
+   /* check that the qualifiers match. */
+   while (iter_a.has_next()) {
+      ir_variable *a = (ir_variable *)iter_a.get();
+      ir_variable *b = (ir_variable *)iter_b.get();
+
+      if (a->read_only != b->read_only ||
+         a->mode != b->mode ||
+         a->interpolation != b->interpolation ||
+         a->centroid != b->centroid) {
+
+        /* parameter a's qualifiers don't match */
+        return a->name;
+      }
+
+      iter_a.next();
+      iter_b.next();
+   }
+   return NULL;
+}
+
+
+void
+ir_function_signature::replace_parameters(exec_list *new_params)
+{
+   /* Destroy all of the previous parameter information.  If the previous
+    * parameter information comes from the function prototype, it may either
+    * specify incorrect parameter names or not have names at all.
+    */
+   foreach_iter(exec_list_iterator, iter, parameters) {
+      assert(((ir_instruction *) iter.get())->as_variable() != NULL);
+
+      iter.remove();
+   }
+
+   new_params->move_nodes_to(&parameters);
+}
+
+
+ir_function::ir_function(const char *name)
+{
+   this->ir_type = ir_type_function;
+   this->name = talloc_strdup(this, name);
+   this->is_builtin = false;
+}
+
+
+ir_call *
+ir_call::get_error_instruction(void *ctx)
+{
+   ir_call *call = new(ctx) ir_call;
+
+   call->type = glsl_type::error_type;
+   return call;
+}
+
+void
+ir_call::set_callee(ir_function_signature *sig)
+{
+   assert((this->type == NULL) || (this->type == sig->return_type));
+
+   this->callee = sig;
+}
+
+void
+visit_exec_list(exec_list *list, ir_visitor *visitor)
+{
+   foreach_iter(exec_list_iterator, iter, *list) {
+      ((ir_instruction *)iter.get())->accept(visitor);
+   }
+}
+
+
+static void
+steal_memory(ir_instruction *ir, void *new_ctx)
+{
+   ir_variable *var = ir->as_variable();
+   ir_constant *constant = ir->as_constant();
+   if (var != NULL && var->constant_value != NULL)
+      steal_memory(var->constant_value, ir);
+
+   /* The components of aggregate constants are not visited by the normal
+    * visitor, so steal their values by hand.
+    */
+   if (constant != NULL) {
+      if (constant->type->is_record()) {
+        foreach_iter(exec_list_iterator, iter, constant->components) {
+           ir_constant *field = (ir_constant *)iter.get();
+           steal_memory(field, ir);
+        }
+      } else if (constant->type->is_array()) {
+        for (unsigned int i = 0; i < constant->type->length; i++) {
+           steal_memory(constant->array_elements[i], ir);
+        }
+      }
+   }
+
+   talloc_steal(new_ctx, ir);
+}
+
+
+void
+reparent_ir(exec_list *list, void *mem_ctx)
+{
+   foreach_list(node, list) {
+      visit_tree((ir_instruction *) node, steal_memory, mem_ctx);
+   }
+}
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
new file mode 100644 (file)
index 0000000..0f887a9
--- /dev/null
@@ -0,0 +1,1399 @@
+/* -*- c++ -*- */
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+#pragma once
+#ifndef IR_H
+#define IR_H
+
+#include <cstdio>
+#include <cstdlib>
+
+extern "C" {
+#include <talloc.h>
+}
+
+#include "list.h"
+#include "ir_visitor.h"
+#include "ir_hierarchical_visitor.h"
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+#endif
+
+enum ir_node_type {
+   ir_type_unset,
+   ir_type_variable,
+   ir_type_assignment,
+   ir_type_call,
+   ir_type_constant,
+   ir_type_dereference_array,
+   ir_type_dereference_record,
+   ir_type_dereference_variable,
+   ir_type_discard,
+   ir_type_expression,
+   ir_type_function,
+   ir_type_function_signature,
+   ir_type_if,
+   ir_type_loop,
+   ir_type_loop_jump,
+   ir_type_return,
+   ir_type_swizzle,
+   ir_type_texture,
+   ir_type_max /**< maximum ir_type enum number, for validation */
+};
+
+/**
+ * Base class of all IR instructions
+ */
+class ir_instruction : public exec_node {
+public:
+   enum ir_node_type ir_type;
+   const struct glsl_type *type;
+
+   /** ir_print_visitor helper for debugging. */
+   void print(void) const;
+
+   virtual void accept(ir_visitor *) = 0;
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *) = 0;
+   virtual ir_instruction *clone(void *mem_ctx,
+                                struct hash_table *ht) const = 0;
+
+   /**
+    * \name IR instruction downcast functions
+    *
+    * These functions either cast the object to a derived class or return
+    * \c NULL if the object's type does not match the specified derived class.
+    * Additional downcast functions will be added as needed.
+    */
+   /*@{*/
+   virtual class ir_variable *          as_variable()         { return NULL; }
+   virtual class ir_function *          as_function()         { return NULL; }
+   virtual class ir_dereference *       as_dereference()      { return NULL; }
+   virtual class ir_dereference_array *        as_dereference_array() { return NULL; }
+   virtual class ir_dereference_variable *as_dereference_variable() { return NULL; }
+   virtual class ir_expression *        as_expression()       { return NULL; }
+   virtual class ir_rvalue *            as_rvalue()           { return NULL; }
+   virtual class ir_loop *              as_loop()             { return NULL; }
+   virtual class ir_assignment *        as_assignment()       { return NULL; }
+   virtual class ir_call *              as_call()             { return NULL; }
+   virtual class ir_return *            as_return()           { return NULL; }
+   virtual class ir_if *                as_if()               { return NULL; }
+   virtual class ir_swizzle *           as_swizzle()          { return NULL; }
+   virtual class ir_constant *          as_constant()         { return NULL; }
+   /*@}*/
+
+protected:
+   ir_instruction()
+   {
+      ir_type = ir_type_unset;
+      type = NULL;
+   }
+};
+
+
+class ir_rvalue : public ir_instruction {
+public:
+   virtual ir_rvalue *clone(void *mem_ctx, struct hash_table *) const = 0;
+
+   virtual ir_constant *constant_expression_value() = 0;
+
+   virtual ir_rvalue * as_rvalue()
+   {
+      return this;
+   }
+
+   virtual bool is_lvalue()
+   {
+      return false;
+   }
+
+   /**
+    * Get the variable that is ultimately referenced by an r-value
+    */
+   virtual ir_variable *variable_referenced()
+   {
+      return NULL;
+   }
+
+
+   /**
+    * If an r-value is a reference to a whole variable, get that variable
+    *
+    * \return
+    * Pointer to a variable that is completely dereferenced by the r-value.  If
+    * the r-value is not a dereference or the dereference does not access the
+    * entire variable (i.e., it's just one array element, struct field), \c NULL
+    * is returned.
+    */
+   virtual ir_variable *whole_variable_referenced()
+   {
+      return NULL;
+   }
+
+protected:
+   ir_rvalue();
+};
+
+
+enum ir_variable_mode {
+   ir_var_auto = 0,
+   ir_var_uniform,
+   ir_var_in,
+   ir_var_out,
+   ir_var_inout,
+   ir_var_temporary    /**< Temporary variable generated during compilation. */
+};
+
+enum ir_variable_interpolation {
+   ir_var_smooth = 0,
+   ir_var_flat,
+   ir_var_noperspective
+};
+
+
+class ir_variable : public ir_instruction {
+public:
+   ir_variable(const struct glsl_type *, const char *, ir_variable_mode);
+
+   virtual ir_variable *clone(void *mem_ctx, struct hash_table *ht) const;
+
+   virtual ir_variable *as_variable()
+   {
+      return this;
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+
+   /**
+    * Get the string value for the interpolation qualifier
+    *
+    * \return The string that would be used in a shader to specify \c
+    * mode will be returned.
+    *
+    * This function should only be used on a shader input or output variable.
+    */
+   const char *interpolation_string() const;
+
+   /**
+    * Calculate the number of slots required to hold this variable
+    *
+    * This is used to determine how many uniform or varying locations a variable
+    * occupies.  The count is in units of floating point components.
+    */
+   unsigned component_slots() const;
+
+   const char *name;
+
+   /**
+    * Highest element accessed with a constant expression array index
+    *
+    * Not used for non-array variables.
+    */
+   unsigned max_array_access;
+
+   unsigned read_only:1;
+   unsigned centroid:1;
+   unsigned invariant:1;
+
+   unsigned mode:3;
+   unsigned interpolation:2;
+
+   /**
+    * Flag that the whole array is assignable
+    *
+    * In GLSL 1.20 and later whole arrays are assignable (and comparable for
+    * equality).  This flag enables this behavior.
+    */
+   unsigned array_lvalue:1;
+
+   /* ARB_fragment_coord_conventions */
+   unsigned origin_upper_left:1;
+   unsigned pixel_center_integer:1;
+
+   /**
+    * Storage location of the base of this variable
+    *
+    * The precise meaning of this field depends on the nature of the variable.
+    *
+    *   - Vertex shader input: one of the values from \c gl_vert_attrib.
+    *   - Vertex shader output: one of the values from \c gl_vert_result.
+    *   - Fragment shader input: one of the values from \c gl_frag_attrib.
+    *   - Fragment shader output: one of the values from \c gl_frag_result.
+    *   - Uniforms: Per-stage uniform slot number.
+    *   - Other: This field is not currently used.
+    *
+    * If the variable is a uniform, shader input, or shader output, and the
+    * slot has not been assigned, the value will be -1.
+    */
+   int location;
+
+   /**
+    * Emit a warning if this variable is accessed.
+    */
+   const char *warn_extension;
+
+   /**
+    * Value assigned in the initializer of a variable declared "const"
+    */
+   ir_constant *constant_value;
+};
+
+
+/*@{*/
+/**
+ * The representation of a function instance; may be the full definition or
+ * simply a prototype.
+ */
+class ir_function_signature : public ir_instruction {
+   /* An ir_function_signature will be part of the list of signatures in
+    * an ir_function.
+    */
+public:
+   ir_function_signature(const glsl_type *return_type);
+
+   virtual ir_function_signature *clone(void *mem_ctx,
+                                       struct hash_table *ht) const;
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   /**
+    * Get the name of the function for which this is a signature
+    */
+   const char *function_name() const;
+
+   /**
+    * Get a handle to the function for which this is a signature
+    *
+    * There is no setter function, this function returns a \c const pointer,
+    * and \c ir_function_signature::_function is private for a reason.  The
+    * only way to make a connection between a function and function signature
+    * is via \c ir_function::add_signature.  This helps ensure that certain
+    * invariants (i.e., a function signature is in the list of signatures for
+    * its \c _function) are met.
+    *
+    * \sa ir_function::add_signature
+    */
+   inline const class ir_function *function() const
+   {
+      return this->_function;
+   }
+
+   /**
+    * Check whether the qualifiers match between this signature's parameters
+    * and the supplied parameter list.  If not, returns the name of the first
+    * parameter with mismatched qualifiers (for use in error messages).
+    */
+   const char *qualifiers_match(exec_list *params);
+
+   /**
+    * Replace the current parameter list with the given one.  This is useful
+    * if the current information came from a prototype, and either has invalid
+    * or missing parameter names.
+    */
+   void replace_parameters(exec_list *new_params);
+
+   /**
+    * Function return type.
+    *
+    * \note This discards the optional precision qualifier.
+    */
+   const struct glsl_type *return_type;
+
+   /**
+    * List of ir_variable of function parameters.
+    *
+    * This represents the storage.  The paramaters passed in a particular
+    * call will be in ir_call::actual_paramaters.
+    */
+   struct exec_list parameters;
+
+   /** Whether or not this function has a body (which may be empty). */
+   unsigned is_defined:1;
+
+   /** Body of instructions in the function. */
+   struct exec_list body;
+
+private:
+   /** Function of which this signature is one overload. */
+   class ir_function *_function;
+
+   friend class ir_function;
+};
+
+
+/**
+ * Header for tracking multiple overloaded functions with the same name.
+ * Contains a list of ir_function_signatures representing each of the
+ * actual functions.
+ */
+class ir_function : public ir_instruction {
+public:
+   ir_function(const char *name);
+
+   virtual ir_function *clone(void *mem_ctx, struct hash_table *ht) const;
+
+   virtual ir_function *as_function()
+   {
+      return this;
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   void add_signature(ir_function_signature *sig)
+   {
+      sig->_function = this;
+      this->signatures.push_tail(sig);
+   }
+
+   /**
+    * Get an iterator for the set of function signatures
+    */
+   exec_list_iterator iterator()
+   {
+      return signatures.iterator();
+   }
+
+   /**
+    * Find a signature that matches a set of actual parameters, taking implicit
+    * conversions into account.
+    */
+   ir_function_signature *matching_signature(const exec_list *actual_param);
+
+   /**
+    * Find a signature that exactly matches a set of actual parameters without
+    * any implicit type conversions.
+    */
+   ir_function_signature *exact_matching_signature(const exec_list *actual_ps);
+
+   /**
+    * Name of the function.
+    */
+   const char *name;
+
+   /** Whether or not this function is a built-in. */
+   unsigned is_builtin:1;
+
+   /**
+    * List of ir_function_signature for each overloaded function with this name.
+    */
+   struct exec_list signatures;
+};
+
+inline const char *ir_function_signature::function_name() const
+{
+   return this->_function->name;
+}
+/*@}*/
+
+
+/**
+ * IR instruction representing high-level if-statements
+ */
+class ir_if : public ir_instruction {
+public:
+   ir_if(ir_rvalue *condition)
+      : condition(condition)
+   {
+      ir_type = ir_type_if;
+   }
+
+   virtual ir_if *clone(void *mem_ctx, struct hash_table *ht) const;
+
+   virtual ir_if *as_if()
+   {
+      return this;
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   ir_rvalue *condition;
+   /** List of ir_instruction for the body of the then branch */
+   exec_list  then_instructions;
+   /** List of ir_instruction for the body of the else branch */
+   exec_list  else_instructions;
+};
+
+
+/**
+ * IR instruction representing a high-level loop structure.
+ */
+class ir_loop : public ir_instruction {
+public:
+   ir_loop() : from(NULL), to(NULL), increment(NULL), counter(NULL)
+   {
+      ir_type = ir_type_loop;
+   }
+
+   virtual ir_loop *clone(void *mem_ctx, struct hash_table *ht) const;
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   virtual ir_loop *as_loop()
+   {
+      return this;
+   }
+
+   /**
+    * Get an iterator for the instructions of the loop body
+    */
+   exec_list_iterator iterator()
+   {
+      return body_instructions.iterator();
+   }
+
+   /** List of ir_instruction that make up the body of the loop. */
+   exec_list body_instructions;
+
+   /**
+    * \name Loop counter and controls
+    */
+   /*@{*/
+   ir_rvalue *from;
+   ir_rvalue *to;
+   ir_rvalue *increment;
+   ir_variable *counter;
+   /*@}*/
+};
+
+
+class ir_assignment : public ir_instruction {
+public:
+   ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition);
+
+   /**
+    * Construct an assignment with an explicit write mask
+    *
+    * \note
+    * Since a write mask is supplied, the LHS must already be a bare
+    * \c ir_dereference.  The cannot be any swizzles in the LHS.
+    */
+   ir_assignment(ir_dereference *lhs, ir_rvalue *rhs, ir_rvalue *condition,
+                unsigned write_mask);
+
+   virtual ir_assignment *clone(void *mem_ctx, struct hash_table *ht) const;
+
+   virtual ir_constant *constant_expression_value();
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   virtual ir_assignment * as_assignment()
+   {
+      return this;
+   }
+
+   /**
+    * Get a whole variable written by an assignment
+    *
+    * If the LHS of the assignment writes a whole variable, the variable is
+    * returned.  Otherwise \c NULL is returned.  Examples of whole-variable
+    * assignment are:
+    *
+    *  - Assigning to a scalar
+    *  - Assigning to all components of a vector
+    *  - Whole array (or matrix) assignment
+    *  - Whole structure assignment
+    */
+   ir_variable *whole_variable_written();
+
+   /**
+    * Set the LHS of an assignment
+    */
+   void set_lhs(ir_rvalue *lhs);
+
+   /**
+    * Left-hand side of the assignment.
+    *
+    * This should be treated as read only.  If you need to set the LHS of an
+    * assignment, use \c ir_assignment::set_lhs.
+    */
+   ir_dereference *lhs;
+
+   /**
+    * Value being assigned
+    */
+   ir_rvalue *rhs;
+
+   /**
+    * Optional condition for the assignment.
+    */
+   ir_rvalue *condition;
+
+
+   /**
+    * Component mask written
+    *
+    * For non-vector types in the LHS, this field will be zero.  For vector
+    * types, a bit will be set for each component that is written.  Note that
+    * for \c vec2 and \c vec3 types only the lower bits will ever be set.
+    */
+   unsigned write_mask:4;
+};
+
+/* Update ir_expression::num_operands() and operator_strs when
+ * updating this list.
+ */
+enum ir_expression_operation {
+   ir_unop_bit_not,
+   ir_unop_logic_not,
+   ir_unop_neg,
+   ir_unop_abs,
+   ir_unop_sign,
+   ir_unop_rcp,
+   ir_unop_rsq,
+   ir_unop_sqrt,
+   ir_unop_exp,      /**< Log base e on gentype */
+   ir_unop_log,             /**< Natural log on gentype */
+   ir_unop_exp2,
+   ir_unop_log2,
+   ir_unop_f2i,      /**< Float-to-integer conversion. */
+   ir_unop_i2f,      /**< Integer-to-float conversion. */
+   ir_unop_f2b,      /**< Float-to-boolean conversion */
+   ir_unop_b2f,      /**< Boolean-to-float conversion */
+   ir_unop_i2b,      /**< int-to-boolean conversion */
+   ir_unop_b2i,      /**< Boolean-to-int conversion */
+   ir_unop_u2f,      /**< Unsigned-to-float conversion. */
+   ir_unop_any,
+
+   /**
+    * \name Unary floating-point rounding operations.
+    */
+   /*@{*/
+   ir_unop_trunc,
+   ir_unop_ceil,
+   ir_unop_floor,
+   ir_unop_fract,
+   /*@}*/
+
+   /**
+    * \name Trigonometric operations.
+    */
+   /*@{*/
+   ir_unop_sin,
+   ir_unop_cos,
+   /*@}*/
+
+   /**
+    * \name Partial derivatives.
+    */
+   /*@{*/
+   ir_unop_dFdx,
+   ir_unop_dFdy,
+   /*@}*/
+
+   ir_binop_add,
+   ir_binop_sub,
+   ir_binop_mul,
+   ir_binop_div,
+
+   /**
+    * Takes one of two combinations of arguments:
+    *
+    * - mod(vecN, vecN)
+    * - mod(vecN, float)
+    *
+    * Does not take integer types.
+    */
+   ir_binop_mod,
+
+   /**
+    * \name Binary comparison operators
+    */
+   /*@{*/
+   ir_binop_less,
+   ir_binop_greater,
+   ir_binop_lequal,
+   ir_binop_gequal,
+   /**
+    * Returns single boolean for whether all components of operands[0]
+    * equal the components of operands[1].
+    */
+   ir_binop_equal,
+   /**
+    * Returns single boolean for whether any component of operands[0]
+    * is not equal to the corresponding component of operands[1].
+    */
+   ir_binop_nequal,
+   /*@}*/
+
+   /**
+    * \name Bit-wise binary operations.
+    */
+   /*@{*/
+   ir_binop_lshift,
+   ir_binop_rshift,
+   ir_binop_bit_and,
+   ir_binop_bit_xor,
+   ir_binop_bit_or,
+   /*@}*/
+
+   ir_binop_logic_and,
+   ir_binop_logic_xor,
+   ir_binop_logic_or,
+
+   ir_binop_dot,
+   ir_binop_cross,
+   ir_binop_min,
+   ir_binop_max,
+
+   ir_binop_pow
+};
+
+class ir_expression : public ir_rvalue {
+public:
+   ir_expression(int op, const struct glsl_type *type,
+                ir_rvalue *, ir_rvalue *);
+
+   virtual ir_expression *as_expression()
+   {
+      return this;
+   }
+
+   virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const;
+
+   virtual ir_constant *constant_expression_value();
+
+   static unsigned int get_num_operands(ir_expression_operation);
+   unsigned int get_num_operands() const
+   {
+      return get_num_operands(operation);
+   }
+
+   /**
+    * Return a string representing this expression's operator.
+    */
+   const char *operator_string();
+
+   /**
+    * Do a reverse-lookup to translate the given string into an operator.
+    */
+   static ir_expression_operation get_operator(const char *);
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   ir_expression_operation operation;
+   ir_rvalue *operands[2];
+};
+
+
+/**
+ * IR instruction representing a function call
+ */
+class ir_call : public ir_rvalue {
+public:
+   ir_call(ir_function_signature *callee, exec_list *actual_parameters)
+      : callee(callee)
+   {
+      ir_type = ir_type_call;
+      assert(callee->return_type != NULL);
+      type = callee->return_type;
+      actual_parameters->move_nodes_to(& this->actual_parameters);
+   }
+
+   virtual ir_call *clone(void *mem_ctx, struct hash_table *ht) const;
+
+   virtual ir_constant *constant_expression_value();
+
+   virtual ir_call *as_call()
+   {
+      return this;
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   /**
+    * Get a generic ir_call object when an error occurs
+    *
+    * Any allocation will be performed with 'ctx' as talloc owner.
+    */
+   static ir_call *get_error_instruction(void *ctx);
+
+   /**
+    * Get an iterator for the set of acutal parameters
+    */
+   exec_list_iterator iterator()
+   {
+      return actual_parameters.iterator();
+   }
+
+   /**
+    * Get the name of the function being called.
+    */
+   const char *callee_name() const
+   {
+      return callee->function_name();
+   }
+
+   ir_function_signature *get_callee()
+   {
+      return callee;
+   }
+
+   /**
+    * Set the function call target
+    */
+   void set_callee(ir_function_signature *sig);
+
+   /**
+    * Generates an inline version of the function before @ir,
+    * returning the return value of the function.
+    */
+   ir_rvalue *generate_inline(ir_instruction *ir);
+
+   /* List of ir_rvalue of paramaters passed in this call. */
+   exec_list actual_parameters;
+
+private:
+   ir_call()
+      : callee(NULL)
+   {
+      this->ir_type = ir_type_call;
+   }
+
+   ir_function_signature *callee;
+};
+
+
+/**
+ * \name Jump-like IR instructions.
+ *
+ * These include \c break, \c continue, \c return, and \c discard.
+ */
+/*@{*/
+class ir_jump : public ir_instruction {
+protected:
+   ir_jump()
+   {
+      ir_type = ir_type_unset;
+   }
+};
+
+class ir_return : public ir_jump {
+public:
+   ir_return()
+      : value(NULL)
+   {
+      this->ir_type = ir_type_return;
+   }
+
+   ir_return(ir_rvalue *value)
+      : value(value)
+   {
+      this->ir_type = ir_type_return;
+   }
+
+   virtual ir_return *clone(void *mem_ctx, struct hash_table *) const;
+
+   virtual ir_return *as_return()
+   {
+      return this;
+   }
+
+   ir_rvalue *get_value() const
+   {
+      return value;
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   ir_rvalue *value;
+};
+
+
+/**
+ * Jump instructions used inside loops
+ *
+ * These include \c break and \c continue.  The \c break within a loop is
+ * different from the \c break within a switch-statement.
+ *
+ * \sa ir_switch_jump
+ */
+class ir_loop_jump : public ir_jump {
+public:
+   enum jump_mode {
+      jump_break,
+      jump_continue
+   };
+
+   ir_loop_jump(jump_mode mode)
+   {
+      this->ir_type = ir_type_loop_jump;
+      this->mode = mode;
+      this->loop = loop;
+   }
+
+   virtual ir_loop_jump *clone(void *mem_ctx, struct hash_table *) const;
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   bool is_break() const
+   {
+      return mode == jump_break;
+   }
+
+   bool is_continue() const
+   {
+      return mode == jump_continue;
+   }
+
+   /** Mode selector for the jump instruction. */
+   enum jump_mode mode;
+private:
+   /** Loop containing this break instruction. */
+   ir_loop *loop;
+};
+
+/**
+ * IR instruction representing discard statements.
+ */
+class ir_discard : public ir_jump {
+public:
+   ir_discard()
+   {
+      this->ir_type = ir_type_discard;
+      this->condition = NULL;
+   }
+
+   ir_discard(ir_rvalue *cond)
+   {
+      this->ir_type = ir_type_discard;
+      this->condition = cond;
+   }
+
+   virtual ir_discard *clone(void *mem_ctx, struct hash_table *ht) const;
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   ir_rvalue *condition;
+};
+/*@}*/
+
+
+/**
+ * Texture sampling opcodes used in ir_texture
+ */
+enum ir_texture_opcode {
+   ir_tex,             /* Regular texture look-up */
+   ir_txb,             /* Texture look-up with LOD bias */
+   ir_txl,             /* Texture look-up with explicit LOD */
+   ir_txd,             /* Texture look-up with partial derivatvies */
+   ir_txf              /* Texel fetch with explicit LOD */
+};
+
+
+/**
+ * IR instruction to sample a texture
+ *
+ * The specific form of the IR instruction depends on the \c mode value
+ * selected from \c ir_texture_opcodes.  In the printed IR, these will
+ * appear as:
+ *
+ *                              Texel offset
+ *                              |       Projection divisor
+ *                              |       |   Shadow comparitor
+ *                              |       |   |
+ *                              v       v   v
+ * (tex (sampler) (coordinate) (0 0 0) (1) ( ))
+ * (txb (sampler) (coordinate) (0 0 0) (1) ( ) (bias))
+ * (txl (sampler) (coordinate) (0 0 0) (1) ( ) (lod))
+ * (txd (sampler) (coordinate) (0 0 0) (1) ( ) (dPdx dPdy))
+ * (txf (sampler) (coordinate) (0 0 0)         (lod))
+ */
+class ir_texture : public ir_rvalue {
+public:
+   ir_texture(enum ir_texture_opcode op)
+      : op(op), projector(NULL), shadow_comparitor(NULL)
+   {
+      this->ir_type = ir_type_texture;
+   }
+
+   virtual ir_texture *clone(void *mem_ctx, struct hash_table *) const;
+
+   virtual ir_constant *constant_expression_value();
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   /**
+    * Return a string representing the ir_texture_opcode.
+    */
+   const char *opcode_string();
+
+   /** Set the sampler and infer the type. */
+   void set_sampler(ir_dereference *sampler);
+
+   /**
+    * Do a reverse-lookup to translate a string into an ir_texture_opcode.
+    */
+   static ir_texture_opcode get_opcode(const char *);
+
+   enum ir_texture_opcode op;
+
+   /** Sampler to use for the texture access. */
+   ir_dereference *sampler;
+
+   /** Texture coordinate to sample */
+   ir_rvalue *coordinate;
+
+   /**
+    * Value used for projective divide.
+    *
+    * If there is no projective divide (the common case), this will be
+    * \c NULL.  Optimization passes should check for this to point to a constant
+    * of 1.0 and replace that with \c NULL.
+    */
+   ir_rvalue *projector;
+
+   /**
+    * Coordinate used for comparison on shadow look-ups.
+    *
+    * If there is no shadow comparison, this will be \c NULL.  For the
+    * \c ir_txf opcode, this *must* be \c NULL.
+    */
+   ir_rvalue *shadow_comparitor;
+
+   /** Explicit texel offsets. */
+   signed char offsets[3];
+
+   union {
+      ir_rvalue *lod;          /**< Floating point LOD */
+      ir_rvalue *bias;         /**< Floating point LOD bias */
+      struct {
+        ir_rvalue *dPdx;       /**< Partial derivative of coordinate wrt X */
+        ir_rvalue *dPdy;       /**< Partial derivative of coordinate wrt Y */
+      } grad;
+   } lod_info;
+};
+
+
+struct ir_swizzle_mask {
+   unsigned x:2;
+   unsigned y:2;
+   unsigned z:2;
+   unsigned w:2;
+
+   /**
+    * Number of components in the swizzle.
+    */
+   unsigned num_components:3;
+
+   /**
+    * Does the swizzle contain duplicate components?
+    *
+    * L-value swizzles cannot contain duplicate components.
+    */
+   unsigned has_duplicates:1;
+};
+
+
+class ir_swizzle : public ir_rvalue {
+public:
+   ir_swizzle(ir_rvalue *, unsigned x, unsigned y, unsigned z, unsigned w,
+              unsigned count);
+
+   ir_swizzle(ir_rvalue *val, const unsigned *components, unsigned count);
+
+   ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask);
+
+   virtual ir_swizzle *clone(void *mem_ctx, struct hash_table *) const;
+
+   virtual ir_constant *constant_expression_value();
+
+   virtual ir_swizzle *as_swizzle()
+   {
+      return this;
+   }
+
+   /**
+    * Construct an ir_swizzle from the textual representation.  Can fail.
+    */
+   static ir_swizzle *create(ir_rvalue *, const char *, unsigned vector_length);
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   bool is_lvalue()
+   {
+      return val->is_lvalue() && !mask.has_duplicates;
+   }
+
+   /**
+    * Get the variable that is ultimately referenced by an r-value
+    */
+   virtual ir_variable *variable_referenced();
+
+   ir_rvalue *val;
+   ir_swizzle_mask mask;
+
+private:
+   /**
+    * Initialize the mask component of a swizzle
+    *
+    * This is used by the \c ir_swizzle constructors.
+    */
+   void init_mask(const unsigned *components, unsigned count);
+};
+
+
+class ir_dereference : public ir_rvalue {
+public:
+   virtual ir_dereference *clone(void *mem_ctx, struct hash_table *) const = 0;
+
+   virtual ir_dereference *as_dereference()
+   {
+      return this;
+   }
+
+   bool is_lvalue();
+
+   /**
+    * Get the variable that is ultimately referenced by an r-value
+    */
+   virtual ir_variable *variable_referenced() = 0;
+};
+
+
+class ir_dereference_variable : public ir_dereference {
+public:
+   ir_dereference_variable(ir_variable *var);
+
+   virtual ir_dereference_variable *clone(void *mem_ctx,
+                                         struct hash_table *) const;
+
+   virtual ir_constant *constant_expression_value();
+
+   virtual ir_dereference_variable *as_dereference_variable()
+   {
+      return this;
+   }
+
+   /**
+    * Get the variable that is ultimately referenced by an r-value
+    */
+   virtual ir_variable *variable_referenced()
+   {
+      return this->var;
+   }
+
+   virtual ir_variable *whole_variable_referenced()
+   {
+      /* ir_dereference_variable objects always dereference the entire
+       * variable.  However, if this dereference is dereferenced by anything
+       * else, the complete deferefernce chain is not a whole-variable
+       * dereference.  This method should only be called on the top most
+       * ir_rvalue in a dereference chain.
+       */
+      return this->var;
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   /**
+    * Object being dereferenced.
+    */
+   ir_variable *var;
+};
+
+
+class ir_dereference_array : public ir_dereference {
+public:
+   ir_dereference_array(ir_rvalue *value, ir_rvalue *array_index);
+
+   ir_dereference_array(ir_variable *var, ir_rvalue *array_index);
+
+   virtual ir_dereference_array *clone(void *mem_ctx,
+                                      struct hash_table *) const;
+
+   virtual ir_constant *constant_expression_value();
+
+   virtual ir_dereference_array *as_dereference_array()
+   {
+      return this;
+   }
+
+   /**
+    * Get the variable that is ultimately referenced by an r-value
+    */
+   virtual ir_variable *variable_referenced()
+   {
+      return this->array->variable_referenced();
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   ir_rvalue *array;
+   ir_rvalue *array_index;
+
+private:
+   void set_array(ir_rvalue *value);
+};
+
+
+class ir_dereference_record : public ir_dereference {
+public:
+   ir_dereference_record(ir_rvalue *value, const char *field);
+
+   ir_dereference_record(ir_variable *var, const char *field);
+
+   virtual ir_dereference_record *clone(void *mem_ctx,
+                                       struct hash_table *) const;
+
+   virtual ir_constant *constant_expression_value();
+
+   /**
+    * Get the variable that is ultimately referenced by an r-value
+    */
+   virtual ir_variable *variable_referenced()
+   {
+      return this->record->variable_referenced();
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   ir_rvalue *record;
+   const char *field;
+};
+
+
+/**
+ * Data stored in an ir_constant
+ */
+union ir_constant_data {
+      unsigned u[16];
+      int i[16];
+      float f[16];
+      bool b[16];
+};
+
+
+class ir_constant : public ir_rvalue {
+public:
+   ir_constant(const struct glsl_type *type, const ir_constant_data *data);
+   ir_constant(bool b);
+   ir_constant(unsigned int u);
+   ir_constant(int i);
+   ir_constant(float f);
+
+   /**
+    * Construct an ir_constant from a list of ir_constant values
+    */
+   ir_constant(const struct glsl_type *type, exec_list *values);
+
+   /**
+    * Construct an ir_constant from a scalar component of another ir_constant
+    *
+    * The new \c ir_constant inherits the type of the component from the
+    * source constant.
+    *
+    * \note
+    * In the case of a matrix constant, the new constant is a scalar, \b not
+    * a vector.
+    */
+   ir_constant(const ir_constant *c, unsigned i);
+
+   /**
+    * Return a new ir_constant of the specified type containing all zeros.
+    */
+   static ir_constant *zero(void *mem_ctx, const glsl_type *type);
+
+   virtual ir_constant *clone(void *mem_ctx, struct hash_table *) const;
+
+   virtual ir_constant *constant_expression_value();
+
+   virtual ir_constant *as_constant()
+   {
+      return this;
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+   /**
+    * Get a particular component of a constant as a specific type
+    *
+    * This is useful, for example, to get a value from an integer constant
+    * as a float or bool.  This appears frequently when constructors are
+    * called with all constant parameters.
+    */
+   /*@{*/
+   bool get_bool_component(unsigned i) const;
+   float get_float_component(unsigned i) const;
+   int get_int_component(unsigned i) const;
+   unsigned get_uint_component(unsigned i) const;
+   /*@}*/
+
+   ir_constant *get_array_element(unsigned i) const;
+
+   ir_constant *get_record_field(const char *name);
+
+   /**
+    * Determine whether a constant has the same value as another constant
+    */
+   bool has_value(const ir_constant *) const;
+
+   /**
+    * Value of the constant.
+    *
+    * The field used to back the values supplied by the constant is determined
+    * by the type associated with the \c ir_instruction.  Constants may be
+    * scalars, vectors, or matrices.
+    */
+   union ir_constant_data value;
+
+   /* Array elements */
+   ir_constant **array_elements;
+
+   /* Structure fields */
+   exec_list components;
+
+private:
+   /**
+    * Parameterless constructor only used by the clone method
+    */
+   ir_constant(void);
+};
+
+void
+visit_exec_list(exec_list *list, ir_visitor *visitor);
+
+void validate_ir_tree(exec_list *instructions);
+
+/**
+ * Make a clone of each IR instruction in a list
+ *
+ * \param in   List of IR instructions that are to be cloned
+ * \param out  List to hold the cloned instructions
+ */
+void
+clone_ir_list(void *mem_ctx, exec_list *out, const exec_list *in);
+
+extern void
+_mesa_glsl_initialize_variables(exec_list *instructions,
+                               struct _mesa_glsl_parse_state *state);
+
+extern void
+_mesa_glsl_initialize_functions(exec_list *instructions,
+                               struct _mesa_glsl_parse_state *state);
+
+extern void
+_mesa_glsl_release_functions(void);
+
+extern void
+reparent_ir(exec_list *list, void *mem_ctx);
+
+struct glsl_symbol_table;
+
+extern void
+import_prototypes(const exec_list *source, exec_list *dest,
+                 struct glsl_symbol_table *symbols, void *mem_ctx);
+
+extern bool
+ir_has_call(ir_instruction *ir);
+
+extern void
+do_set_program_inouts(exec_list *instructions, struct gl_program *prog);
+
+#endif /* IR_H */
diff --git a/src/glsl/ir_algebraic.cpp b/src/glsl/ir_algebraic.cpp
new file mode 100644 (file)
index 0000000..ff81563
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_algebraic.cpp
+ *
+ * Takes advantage of association, commutivity, and other algebraic
+ * properties to simplify expressions.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_rvalue_visitor.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+/**
+ * Visitor class for replacing expressions with ir_constant values.
+ */
+
+class ir_algebraic_visitor : public ir_rvalue_visitor {
+public:
+   ir_algebraic_visitor()
+   {
+      this->progress = false;
+      this->mem_ctx = NULL;
+   }
+
+   virtual ~ir_algebraic_visitor()
+   {
+   }
+
+   ir_rvalue *handle_expression(ir_expression *ir);
+   void handle_rvalue(ir_rvalue **rvalue);
+   bool reassociate_constant(ir_expression *ir1,
+                            int const_index,
+                            ir_constant *constant,
+                            ir_expression *ir2);
+   void reassociate_operands(ir_expression *ir1,
+                            int op1,
+                            ir_expression *ir2,
+                            int op2);
+   ir_rvalue *swizzle_if_required(ir_expression *expr,
+                                 ir_rvalue *operand);
+
+   void *mem_ctx;
+
+   bool progress;
+};
+
+static bool
+is_vec_zero(ir_constant *ir)
+{
+   int c;
+
+   if (!ir)
+      return false;
+   if (!ir->type->is_scalar() &&
+       !ir->type->is_vector())
+      return false;
+
+   for (c = 0; c < ir->type->vector_elements; c++) {
+      switch (ir->type->base_type) {
+      case GLSL_TYPE_FLOAT:
+        if (ir->value.f[c] != 0.0)
+           return false;
+        break;
+      case GLSL_TYPE_INT:
+        if (ir->value.i[c] != 0)
+           return false;
+        break;
+      case GLSL_TYPE_UINT:
+        if (ir->value.u[c] != 0)
+           return false;
+        break;
+      case GLSL_TYPE_BOOL:
+        if (ir->value.b[c] != false)
+           return false;
+        break;
+      default:
+        assert(!"bad base type");
+        return false;
+      }
+   }
+
+   return true;
+}
+
+static bool
+is_vec_one(ir_constant *ir)
+{
+   int c;
+
+   if (!ir)
+      return false;
+   if (!ir->type->is_scalar() &&
+       !ir->type->is_vector())
+      return false;
+
+   for (c = 0; c < ir->type->vector_elements; c++) {
+      switch (ir->type->base_type) {
+      case GLSL_TYPE_FLOAT:
+        if (ir->value.f[c] != 1.0)
+           return false;
+        break;
+      case GLSL_TYPE_INT:
+        if (ir->value.i[c] != 1)
+           return false;
+        break;
+      case GLSL_TYPE_UINT:
+        if (ir->value.u[c] != 1)
+           return false;
+        break;
+      case GLSL_TYPE_BOOL:
+        if (ir->value.b[c] != true)
+           return false;
+        break;
+      default:
+        assert(!"bad base type");
+        return false;
+      }
+   }
+
+   return true;
+}
+
+static void
+update_type(ir_expression *ir)
+{
+   if (ir->operands[0]->type->is_vector())
+      ir->type = ir->operands[0]->type;
+   else
+      ir->type = ir->operands[1]->type;
+}
+
+void
+ir_algebraic_visitor::reassociate_operands(ir_expression *ir1,
+                                          int op1,
+                                          ir_expression *ir2,
+                                          int op2)
+{
+   ir_rvalue *temp = ir2->operands[op2];
+   ir2->operands[op2] = ir1->operands[op1];
+   ir1->operands[op1] = temp;
+
+   /* Update the type of ir2.  The type of ir1 won't have changed --
+    * base types matched, and at least one of the operands of the 2
+    * binops is still a vector if any of them were.
+    */
+   update_type(ir2);
+
+   this->progress = true;
+}
+
+/**
+ * Reassociates a constant down a tree of adds or multiplies.
+ *
+ * Consider (2 * (a * (b * 0.5))).  We want to send up with a * b.
+ */
+bool
+ir_algebraic_visitor::reassociate_constant(ir_expression *ir1, int const_index,
+                                          ir_constant *constant,
+                                          ir_expression *ir2)
+{
+   if (!ir2 || ir1->operation != ir2->operation)
+      return false;
+
+   /* Don't want to even think about matrices. */
+   if (ir1->operands[0]->type->is_matrix() ||
+       ir1->operands[0]->type->is_matrix() ||
+       ir2->operands[1]->type->is_matrix() ||
+       ir2->operands[1]->type->is_matrix())
+      return false;
+
+   ir_constant *ir2_const[2];
+   ir2_const[0] = ir2->operands[0]->constant_expression_value();
+   ir2_const[1] = ir2->operands[1]->constant_expression_value();
+
+   if (ir2_const[0] && ir2_const[1])
+      return false;
+
+   if (ir2_const[0]) {
+      reassociate_operands(ir1, const_index, ir2, 1);
+      return true;
+   } else if (ir2_const[1]) {
+      reassociate_operands(ir1, const_index, ir2, 0);
+      return true;
+   }
+
+   if (reassociate_constant(ir1, const_index, constant,
+                           ir2->operands[0]->as_expression())) {
+      update_type(ir2);
+      return true;
+   }
+
+   if (reassociate_constant(ir1, const_index, constant,
+                           ir2->operands[1]->as_expression())) {
+      update_type(ir2);
+      return true;
+   }
+
+   return false;
+}
+
+/* When eliminating an expression and just returning one of its operands,
+ * we may need to swizzle that operand out to a vector if the expression was
+ * vector type.
+ */
+ir_rvalue *
+ir_algebraic_visitor::swizzle_if_required(ir_expression *expr,
+                                         ir_rvalue *operand)
+{
+   if (expr->type->is_vector() && operand->type->is_scalar()) {
+      return new(mem_ctx) ir_swizzle(operand, 0, 0, 0, 0,
+                                    expr->type->vector_elements);
+   } else
+      return operand;
+}
+
+ir_rvalue *
+ir_algebraic_visitor::handle_expression(ir_expression *ir)
+{
+   ir_constant *op_const[2] = {NULL, NULL};
+   ir_expression *op_expr[2] = {NULL, NULL};
+   ir_expression *temp;
+   unsigned int i;
+
+   for (i = 0; i < ir->get_num_operands(); i++) {
+      if (ir->operands[i]->type->is_matrix())
+        return ir;
+
+      op_const[i] = ir->operands[i]->constant_expression_value();
+      op_expr[i] = ir->operands[i]->as_expression();
+   }
+
+   if (this->mem_ctx == NULL)
+      this->mem_ctx = talloc_parent(ir);
+
+   switch (ir->operation) {
+   case ir_unop_logic_not: {
+      enum ir_expression_operation new_op = ir_unop_logic_not;
+
+      if (op_expr[0] == NULL)
+        break;
+
+      switch (op_expr[0]->operation) {
+      case ir_binop_less:    new_op = ir_binop_gequal;  break;
+      case ir_binop_greater: new_op = ir_binop_lequal;  break;
+      case ir_binop_lequal:  new_op = ir_binop_greater; break;
+      case ir_binop_gequal:  new_op = ir_binop_less;    break;
+      case ir_binop_equal:   new_op = ir_binop_nequal;  break;
+      case ir_binop_nequal:  new_op = ir_binop_equal;   break;
+
+      default:
+        /* The default case handler is here to silence a warning from GCC.
+         */
+        break;
+      }
+
+      if (new_op != ir_unop_logic_not) {
+        this->progress = true;
+        return new(mem_ctx) ir_expression(new_op,
+                                          ir->type,
+                                          op_expr[0]->operands[0],
+                                          op_expr[0]->operands[1]);
+      }
+
+      break;
+   }
+
+   case ir_binop_add:
+      if (is_vec_zero(op_const[0])) {
+        this->progress = true;
+        return swizzle_if_required(ir, ir->operands[1]);
+      }
+      if (is_vec_zero(op_const[1])) {
+        this->progress = true;
+        return swizzle_if_required(ir, ir->operands[0]);
+      }
+
+      /* Reassociate addition of constants so that we can do constant
+       * folding.
+       */
+      if (op_const[0] && !op_const[1])
+        reassociate_constant(ir, 0, op_const[0],
+                             ir->operands[1]->as_expression());
+      if (op_const[1] && !op_const[0])
+        reassociate_constant(ir, 1, op_const[1],
+                             ir->operands[0]->as_expression());
+      break;
+
+   case ir_binop_sub:
+      if (is_vec_zero(op_const[0])) {
+        this->progress = true;
+        temp = new(mem_ctx) ir_expression(ir_unop_neg,
+                                          ir->operands[1]->type,
+                                          ir->operands[1],
+                                          NULL);
+        return swizzle_if_required(ir, temp);
+      }
+      if (is_vec_zero(op_const[1])) {
+        this->progress = true;
+        return swizzle_if_required(ir, ir->operands[0]);
+      }
+      break;
+
+   case ir_binop_mul:
+      if (is_vec_one(op_const[0])) {
+        this->progress = true;
+        return swizzle_if_required(ir, ir->operands[1]);
+      }
+      if (is_vec_one(op_const[1])) {
+        this->progress = true;
+        return swizzle_if_required(ir, ir->operands[0]);
+      }
+
+      if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
+        this->progress = true;
+        return ir_constant::zero(ir, ir->type);
+      }
+
+      /* Reassociate multiplication of constants so that we can do
+       * constant folding.
+       */
+      if (op_const[0] && !op_const[1])
+        reassociate_constant(ir, 0, op_const[0],
+                             ir->operands[1]->as_expression());
+      if (op_const[1] && !op_const[0])
+        reassociate_constant(ir, 1, op_const[1],
+                             ir->operands[0]->as_expression());
+
+      break;
+
+   case ir_binop_div:
+      if (is_vec_one(op_const[0]) && ir->type->base_type == GLSL_TYPE_FLOAT) {
+        this->progress = true;
+        temp = new(mem_ctx) ir_expression(ir_unop_rcp,
+                                          ir->operands[1]->type,
+                                          ir->operands[1],
+                                          NULL);
+        return swizzle_if_required(ir, temp);
+      }
+      if (is_vec_one(op_const[1])) {
+        this->progress = true;
+        return swizzle_if_required(ir, ir->operands[0]);
+      }
+      break;
+
+   case ir_binop_logic_and:
+      /* FINISHME: Also simplify (a && a) to (a). */
+      if (is_vec_one(op_const[0])) {
+        this->progress = true;
+        return ir->operands[1];
+      } else if (is_vec_one(op_const[1])) {
+        this->progress = true;
+        return ir->operands[0];
+      } else if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
+        this->progress = true;
+        return ir_constant::zero(mem_ctx, ir->type);
+      }
+      break;
+
+   case ir_binop_logic_xor:
+      /* FINISHME: Also simplify (a ^^ a) to (false). */
+      if (is_vec_zero(op_const[0])) {
+        this->progress = true;
+        return ir->operands[1];
+      } else if (is_vec_zero(op_const[1])) {
+        this->progress = true;
+        return ir->operands[0];
+      } else if (is_vec_one(op_const[0])) {
+        this->progress = true;
+        return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type,
+                                          ir->operands[1], NULL);
+      } else if (is_vec_one(op_const[1])) {
+        this->progress = true;
+        return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type,
+                                          ir->operands[0], NULL);
+      }
+      break;
+
+   case ir_binop_logic_or:
+      /* FINISHME: Also simplify (a || a) to (a). */
+      if (is_vec_zero(op_const[0])) {
+        this->progress = true;
+        return ir->operands[1];
+      } else if (is_vec_zero(op_const[1])) {
+        this->progress = true;
+        return ir->operands[0];
+      } else if (is_vec_one(op_const[0]) || is_vec_one(op_const[1])) {
+        ir_constant_data data;
+
+        for (unsigned i = 0; i < 16; i++)
+           data.b[i] = true;
+
+        this->progress = true;
+        return new(mem_ctx) ir_constant(ir->type, &data);
+      }
+      break;
+
+   case ir_unop_rcp:
+      if (op_expr[0] && op_expr[0]->operation == ir_unop_rcp) {
+        this->progress = true;
+        return op_expr[0]->operands[0];
+      }
+
+      /* FINISHME: We should do rcp(rsq(x)) -> sqrt(x) for some
+       * backends, except that some backends will have done sqrt ->
+       * rcp(rsq(x)) and we don't want to undo it for them.
+       */
+
+      /* As far as we know, all backends are OK with rsq. */
+      if (op_expr[0] && op_expr[0]->operation == ir_unop_sqrt) {
+        this->progress = true;
+        temp = new(mem_ctx) ir_expression(ir_unop_rsq,
+                                          op_expr[0]->operands[0]->type,
+                                          op_expr[0]->operands[0],
+                                          NULL);
+        return swizzle_if_required(ir, temp);
+      }
+
+      break;
+
+   default:
+      break;
+   }
+
+   return ir;
+}
+
+void
+ir_algebraic_visitor::handle_rvalue(ir_rvalue **rvalue)
+{
+   if (!*rvalue)
+      return;
+
+   ir_expression *expr = (*rvalue)->as_expression();
+   if (!expr)
+      return;
+
+   *rvalue = handle_expression(expr);
+}
+
+bool
+do_algebraic(exec_list *instructions)
+{
+   ir_algebraic_visitor v;
+
+   visit_list_elements(&v, instructions);
+
+   return v.progress;
+}
diff --git a/src/glsl/ir_basic_block.cpp b/src/glsl/ir_basic_block.cpp
new file mode 100644 (file)
index 0000000..a833825
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_basic_block.cpp
+ *
+ * Basic block analysis of instruction streams.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_basic_block.h"
+#include "glsl_types.h"
+
+class ir_has_call_visitor : public ir_hierarchical_visitor {
+public:
+   ir_has_call_visitor()
+   {
+      has_call = false;
+   }
+
+   virtual ir_visitor_status visit_enter(ir_call *ir)
+   {
+      (void) ir;
+      has_call = true;
+      return visit_stop;
+   }
+
+   bool has_call;
+};
+
+bool
+ir_has_call(ir_instruction *ir)
+{
+   ir_has_call_visitor v;
+   ir->accept(&v);
+   return v.has_call;
+}
+
+/**
+ * Calls a user function for every basic block in the instruction stream.
+ *
+ * Basic block analysis is pretty easy in our IR thanks to the lack of
+ * unstructured control flow.  We've got:
+ *
+ * ir_loop (for () {}, while () {}, do {} while ())
+ * ir_loop_jump (
+ * ir_if () {}
+ * ir_return
+ * ir_call()
+ *
+ * Note that the basic blocks returned by this don't encompass all
+ * operations performed by the program -- for example, if conditions
+ * don't get returned, nor do the assignments that will be generated
+ * for ir_call parameters.
+ */
+void call_for_basic_blocks(exec_list *instructions,
+                          void (*callback)(ir_instruction *first,
+                                           ir_instruction *last,
+                                           void *data),
+                          void *data)
+{
+   ir_instruction *leader = NULL;
+   ir_instruction *last = NULL;
+
+   foreach_iter(exec_list_iterator, iter, *instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      ir_if *ir_if;
+      ir_loop *ir_loop;
+      ir_function *ir_function;
+
+      if (!leader)
+        leader = ir;
+
+      if ((ir_if = ir->as_if())) {
+        callback(leader, ir, data);
+        leader = NULL;
+
+        call_for_basic_blocks(&ir_if->then_instructions, callback, data);
+        call_for_basic_blocks(&ir_if->else_instructions, callback, data);
+      } else if ((ir_loop = ir->as_loop())) {
+        callback(leader, ir, data);
+        leader = NULL;
+        call_for_basic_blocks(&ir_loop->body_instructions, callback, data);
+      } else if (ir->as_return() || ir->as_call()) {
+        callback(leader, ir, data);
+        leader = NULL;
+      } else if ((ir_function = ir->as_function())) {
+        /* A function definition doesn't interrupt our basic block
+         * since execution doesn't go into it.  We should process the
+         * bodies of its signatures for BBs, though.
+         *
+         * Note that we miss an opportunity for producing more
+         * maximal BBs between the instructions that precede main()
+         * and the body of main().  Perhaps those instructions ought
+         * to live inside of main().
+         */
+        foreach_iter(exec_list_iterator, fun_iter, *ir_function) {
+           ir_function_signature *ir_sig;
+
+           ir_sig = (ir_function_signature *)fun_iter.get();
+
+           call_for_basic_blocks(&ir_sig->body, callback, data);
+        }
+      } else if (ir->as_assignment()) {
+        /* If there's a call in the expression tree being assigned,
+         * then that ends the BB too.
+         *
+         * The assumption is that any consumer of the basic block
+         * walker is fine with the fact that the call is somewhere in
+         * the tree even if portions of the tree may be evaluated
+         * after the call.
+         *
+         * A consumer that has an issue with this could not process
+         * the last instruction of the basic block.  If doing so,
+         * expression flattener may be useful before using the basic
+         * block finder to get more maximal basic blocks out.
+         */
+        if (ir_has_call(ir)) {
+           callback(leader, ir, data);
+           leader = NULL;
+        }
+      }
+      last = ir;
+   }
+   if (leader) {
+      callback(leader, last, data);
+   }
+}
diff --git a/src/glsl/ir_basic_block.h b/src/glsl/ir_basic_block.h
new file mode 100644 (file)
index 0000000..dbd678b
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+void call_for_basic_blocks(exec_list *instructions,
+                          void (*callback)(ir_instruction *first,
+                                           ir_instruction *last,
+                                           void *data),
+                          void *data);
diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp
new file mode 100644 (file)
index 0000000..1d690a4
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 <string.h>
+#include "ir.h"
+#include "glsl_types.h"
+extern "C" {
+#include "program/hash_table.h"
+}
+
+/**
+ * Duplicate an IR variable
+ *
+ * \note
+ * This will probably be made \c virtual and moved to the base class
+ * eventually.
+ */
+ir_variable *
+ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   ir_variable *var = new(mem_ctx) ir_variable(this->type, this->name,
+                                              (ir_variable_mode) this->mode);
+
+   var->max_array_access = this->max_array_access;
+   var->read_only = this->read_only;
+   var->centroid = this->centroid;
+   var->invariant = this->invariant;
+   var->interpolation = this->interpolation;
+   var->array_lvalue = this->array_lvalue;
+   var->location = this->location;
+   var->warn_extension = this->warn_extension;
+   var->origin_upper_left = this->origin_upper_left;
+   var->pixel_center_integer = this->pixel_center_integer;
+
+   if (this->constant_value)
+      var->constant_value = this->constant_value->clone(mem_ctx, ht);
+
+   if (ht) {
+      hash_table_insert(ht, var, (void *)const_cast<ir_variable *>(this));
+   }
+
+   return var;
+}
+
+ir_swizzle *
+ir_swizzle::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   return new(mem_ctx) ir_swizzle(this->val->clone(mem_ctx, ht), this->mask);
+}
+
+ir_return *
+ir_return::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   ir_rvalue *new_value = NULL;
+
+   if (this->value)
+      new_value = this->value->clone(mem_ctx, ht);
+
+   return new(mem_ctx) ir_return(new_value);
+}
+
+ir_discard *
+ir_discard::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   ir_rvalue *new_condition = NULL;
+
+   if (this->condition != NULL)
+      new_condition = this->condition->clone(mem_ctx, ht);
+
+   return new(mem_ctx) ir_discard(new_condition);
+}
+
+ir_loop_jump *
+ir_loop_jump::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   (void)ht;
+
+   return new(mem_ctx) ir_loop_jump(this->mode);
+}
+
+ir_if *
+ir_if::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   ir_if *new_if = new(mem_ctx) ir_if(this->condition->clone(mem_ctx, ht));
+
+   foreach_iter(exec_list_iterator, iter, this->then_instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      new_if->then_instructions.push_tail(ir->clone(mem_ctx, ht));
+   }
+
+   foreach_iter(exec_list_iterator, iter, this->else_instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      new_if->else_instructions.push_tail(ir->clone(mem_ctx, ht));
+   }
+
+   return new_if;
+}
+
+ir_loop *
+ir_loop::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   ir_loop *new_loop = new(mem_ctx) ir_loop();
+
+   if (this->from)
+      new_loop->from = this->from->clone(mem_ctx, ht);
+   if (this->to)
+      new_loop->to = this->to->clone(mem_ctx, ht);
+   if (this->increment)
+      new_loop->increment = this->increment->clone(mem_ctx, ht);
+   new_loop->counter = counter;
+
+   foreach_iter(exec_list_iterator, iter, this->body_instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      new_loop->body_instructions.push_tail(ir->clone(mem_ctx, ht));
+   }
+
+   return new_loop;
+}
+
+ir_call *
+ir_call::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   exec_list new_parameters;
+
+   foreach_iter(exec_list_iterator, iter, this->actual_parameters) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      new_parameters.push_tail(ir->clone(mem_ctx, ht));
+   }
+
+   return new(mem_ctx) ir_call(this->callee, &new_parameters);
+}
+
+ir_expression *
+ir_expression::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   ir_rvalue *op[2] = {NULL, NULL};
+   unsigned int i;
+
+   for (i = 0; i < get_num_operands(); i++) {
+      op[i] = this->operands[i]->clone(mem_ctx, ht);
+   }
+
+   return new(mem_ctx) ir_expression(this->operation, this->type, op[0], op[1]);
+}
+
+ir_dereference_variable *
+ir_dereference_variable::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   ir_variable *new_var;
+
+   if (ht) {
+      new_var = (ir_variable *)hash_table_find(ht, this->var);
+      if (!new_var)
+        new_var = this->var;
+   } else {
+      new_var = this->var;
+   }
+
+   return new(mem_ctx) ir_dereference_variable(new_var);
+}
+
+ir_dereference_array *
+ir_dereference_array::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   return new(mem_ctx) ir_dereference_array(this->array->clone(mem_ctx, ht),
+                                           this->array_index->clone(mem_ctx,
+                                                                    ht));
+}
+
+ir_dereference_record *
+ir_dereference_record::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   return new(mem_ctx) ir_dereference_record(this->record->clone(mem_ctx, ht),
+                                            this->field);
+}
+
+ir_texture *
+ir_texture::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   ir_texture *new_tex = new(mem_ctx) ir_texture(this->op);
+   new_tex->type = this->type;
+
+   new_tex->sampler = this->sampler->clone(mem_ctx, ht);
+   new_tex->coordinate = this->coordinate->clone(mem_ctx, ht);
+   if (this->projector)
+      new_tex->projector = this->projector->clone(mem_ctx, ht);
+   if (this->shadow_comparitor) {
+      new_tex->shadow_comparitor = this->shadow_comparitor->clone(mem_ctx, ht);
+   }
+
+   for (int i = 0; i < 3; i++)
+      new_tex->offsets[i] = this->offsets[i];
+
+   switch (this->op) {
+   case ir_tex:
+      break;
+   case ir_txb:
+      new_tex->lod_info.bias = this->lod_info.bias->clone(mem_ctx, ht);
+      break;
+   case ir_txl:
+   case ir_txf:
+      new_tex->lod_info.lod = this->lod_info.lod->clone(mem_ctx, ht);
+      break;
+   case ir_txd:
+      new_tex->lod_info.grad.dPdx = this->lod_info.grad.dPdx->clone(mem_ctx, ht);
+      new_tex->lod_info.grad.dPdy = this->lod_info.grad.dPdy->clone(mem_ctx, ht);
+      break;
+   }
+
+   return new_tex;
+}
+
+ir_assignment *
+ir_assignment::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   ir_rvalue *new_condition = NULL;
+
+   if (this->condition)
+      new_condition = this->condition->clone(mem_ctx, ht);
+
+   return new(mem_ctx) ir_assignment(this->lhs->clone(mem_ctx, ht),
+                                    this->rhs->clone(mem_ctx, ht),
+                                    new_condition,
+                                    this->write_mask);
+}
+
+ir_function *
+ir_function::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   ir_function *copy = new(mem_ctx) ir_function(this->name);
+
+   copy->is_builtin = this->is_builtin;
+
+   foreach_list_const(node, &this->signatures) {
+      const ir_function_signature *const sig =
+        (const ir_function_signature *const) node;
+
+      ir_function_signature *sig_copy = sig->clone(mem_ctx, ht);
+      copy->add_signature(sig_copy);
+
+      if (ht != NULL)
+        hash_table_insert(ht, sig_copy,
+                          (void *)const_cast<ir_function_signature *>(sig));
+   }
+
+   return copy;
+}
+
+ir_function_signature *
+ir_function_signature::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   ir_function_signature *copy =
+      new(mem_ctx) ir_function_signature(this->return_type);
+
+   copy->is_defined = this->is_defined;
+
+   /* Clone the parameter list.
+    */
+   foreach_list_const(node, &this->parameters) {
+      const ir_variable *const param = (const ir_variable *) node;
+
+      assert(const_cast<ir_variable *>(param)->as_variable() != NULL);
+
+      ir_variable *const param_copy = param->clone(mem_ctx, ht);
+      copy->parameters.push_tail(param_copy);
+   }
+
+   /* Clone the instruction list.
+    */
+   foreach_list_const(node, &this->body) {
+      const ir_instruction *const inst = (const ir_instruction *) node;
+
+      ir_instruction *const inst_copy = inst->clone(mem_ctx, ht);
+      copy->body.push_tail(inst_copy);
+   }
+
+   return copy;
+}
+
+ir_constant *
+ir_constant::clone(void *mem_ctx, struct hash_table *ht) const
+{
+   (void)ht;
+
+   switch (this->type->base_type) {
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_FLOAT:
+   case GLSL_TYPE_BOOL:
+      return new(mem_ctx) ir_constant(this->type, &this->value);
+
+   case GLSL_TYPE_STRUCT: {
+      ir_constant *c = new(mem_ctx) ir_constant;
+
+      c->type = this->type;
+      for (exec_node *node = this->components.head
+             ; !node->is_tail_sentinel()
+             ; node = node->next) {
+        ir_constant *const orig = (ir_constant *) node;
+
+        c->components.push_tail(orig->clone(mem_ctx, NULL));
+      }
+
+      return c;
+   }
+
+   case GLSL_TYPE_ARRAY: {
+      ir_constant *c = new(mem_ctx) ir_constant;
+
+      c->type = this->type;
+      c->array_elements = talloc_array(c, ir_constant *, this->type->length);
+      for (unsigned i = 0; i < this->type->length; i++) {
+        c->array_elements[i] = this->array_elements[i]->clone(mem_ctx, NULL);
+      }
+      return c;
+   }
+
+   default:
+      assert(!"Should not get here.");
+      return NULL;
+   }
+}
+
+
+class fixup_ir_call_visitor : public ir_hierarchical_visitor {
+public:
+   fixup_ir_call_visitor(struct hash_table *ht)
+   {
+      this->ht = ht;
+   }
+
+   virtual ir_visitor_status visit_enter(ir_call *ir)
+   {
+      /* Try to find the function signature referenced by the ir_call in the
+       * table.  If it is found, replace it with the value from the table.
+       */
+      ir_function_signature *sig =
+        (ir_function_signature *) hash_table_find(this->ht, ir->get_callee());
+      if (sig != NULL)
+        ir->set_callee(sig);
+
+      /* Since this may be used before function call parameters are flattened,
+       * the children also need to be processed.
+       */
+      return visit_continue;
+   }
+
+private:
+   struct hash_table *ht;
+};
+
+
+static void
+fixup_function_calls(struct hash_table *ht, exec_list *instructions)
+{
+   fixup_ir_call_visitor v(ht);
+   v.run(instructions);
+}
+
+
+void
+clone_ir_list(void *mem_ctx, exec_list *out, const exec_list *in)
+{
+   struct hash_table *ht =
+      hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare);
+
+   foreach_list_const(node, in) {
+      const ir_instruction *const original = (ir_instruction *) node;
+      ir_instruction *copy = original->clone(mem_ctx, ht);
+
+      out->push_tail(copy);
+   }
+
+   /* Make a pass over the cloned tree to fix up ir_call nodes to point to the
+    * cloned ir_function_signature nodes.  This cannot be done automatically
+    * during cloning because the ir_call might be a forward reference (i.e.,
+    * the function signature that it references may not have been cloned yet).
+    */
+   fixup_function_calls(ht, out);
+
+   hash_table_dtor(ht);
+}
diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp
new file mode 100644 (file)
index 0000000..458dca7
--- /dev/null
@@ -0,0 +1,1159 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_constant_expression.cpp
+ * Evaluate and process constant valued expressions
+ *
+ * In GLSL, constant valued expressions are used in several places.  These
+ * must be processed and evaluated very early in the compilation process.
+ *
+ *    * Sizes of arrays
+ *    * Initializers for uniforms
+ *    * Initializers for \c const variables
+ */
+
+#include <math.h>
+#include "main/core.h" /* for MAX2, MIN2, CLAMP */
+#include "ir.h"
+#include "ir_visitor.h"
+#include "glsl_types.h"
+
+static float
+dot(ir_constant *op0, ir_constant *op1)
+{
+   assert(op0->type->is_float() && op1->type->is_float());
+
+   float result = 0;
+   for (unsigned c = 0; c < op0->type->components(); c++)
+      result += op0->value.f[c] * op1->value.f[c];
+
+   return result;
+}
+
+ir_constant *
+ir_expression::constant_expression_value()
+{
+   ir_constant *op[2] = { NULL, NULL };
+   ir_constant_data data;
+
+   memset(&data, 0, sizeof(data));
+
+   for (unsigned operand = 0; operand < this->get_num_operands(); operand++) {
+      op[operand] = this->operands[operand]->constant_expression_value();
+      if (!op[operand])
+        return NULL;
+   }
+
+   if (op[1] != NULL)
+      assert(op[0]->type->base_type == op[1]->type->base_type);
+
+   bool op0_scalar = op[0]->type->is_scalar();
+   bool op1_scalar = op[1] != NULL && op[1]->type->is_scalar();
+
+   /* When iterating over a vector or matrix's components, we want to increase
+    * the loop counter.  However, for scalars, we want to stay at 0.
+    */
+   unsigned c0_inc = op0_scalar ? 0 : 1;
+   unsigned c1_inc = op1_scalar ? 0 : 1;
+   unsigned components;
+   if (op1_scalar || !op[1]) {
+      components = op[0]->type->components();
+   } else {
+      components = op[1]->type->components();
+   }
+
+   void *ctx = talloc_parent(this);
+
+   /* Handle array operations here, rather than below. */
+   if (op[0]->type->is_array()) {
+      assert(op[1] != NULL && op[1]->type->is_array());
+      switch (this->operation) {
+      case ir_binop_equal:
+        return new(ctx) ir_constant(op[0]->has_value(op[1]));
+      case ir_binop_nequal:
+        return new(ctx) ir_constant(!op[0]->has_value(op[1]));
+      default:
+        break;
+      }
+      return NULL;
+   }
+
+   switch (this->operation) {
+   case ir_unop_logic_not:
+      assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.b[c] = !op[0]->value.b[c];
+      break;
+
+   case ir_unop_f2i:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.i[c] = op[0]->value.f[c];
+      }
+      break;
+   case ir_unop_i2f:
+      assert(op[0]->type->base_type == GLSL_TYPE_INT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = op[0]->value.i[c];
+      }
+      break;
+   case ir_unop_u2f:
+      assert(op[0]->type->base_type == GLSL_TYPE_UINT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = op[0]->value.u[c];
+      }
+      break;
+   case ir_unop_b2f:
+      assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = op[0]->value.b[c] ? 1.0 : 0.0;
+      }
+      break;
+   case ir_unop_f2b:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.b[c] = bool(op[0]->value.f[c]);
+      }
+      break;
+   case ir_unop_b2i:
+      assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.u[c] = op[0]->value.b[c] ? 1 : 0;
+      }
+      break;
+   case ir_unop_i2b:
+      assert(op[0]->type->is_integer());
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.b[c] = bool(op[0]->value.u[c]);
+      }
+      break;
+
+   case ir_unop_any:
+      assert(op[0]->type->is_boolean());
+      data.b[0] = false;
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        if (op[0]->value.b[c])
+           data.b[0] = true;
+      }
+      break;
+
+   case ir_unop_trunc:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = truncf(op[0]->value.f[c]);
+      }
+      break;
+
+   case ir_unop_ceil:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = ceilf(op[0]->value.f[c]);
+      }
+      break;
+
+   case ir_unop_floor:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = floorf(op[0]->value.f[c]);
+      }
+      break;
+
+   case ir_unop_fract:
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        switch (this->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.u[c] = 0;
+           break;
+        case GLSL_TYPE_INT:
+           data.i[c] = 0;
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.f[c] = op[0]->value.f[c] - floor(op[0]->value.f[c]);
+           break;
+        default:
+           assert(0);
+        }
+      }
+      break;
+
+   case ir_unop_sin:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = sinf(op[0]->value.f[c]);
+      }
+      break;
+
+   case ir_unop_cos:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = cosf(op[0]->value.f[c]);
+      }
+      break;
+
+   case ir_unop_neg:
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        switch (this->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.u[c] = -op[0]->value.u[c];
+           break;
+        case GLSL_TYPE_INT:
+           data.i[c] = -op[0]->value.i[c];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.f[c] = -op[0]->value.f[c];
+           break;
+        default:
+           assert(0);
+        }
+      }
+      break;
+
+   case ir_unop_abs:
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        switch (this->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.u[c] = op[0]->value.u[c];
+           break;
+        case GLSL_TYPE_INT:
+           data.i[c] = op[0]->value.i[c];
+           if (data.i[c] < 0)
+              data.i[c] = -data.i[c];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.f[c] = fabs(op[0]->value.f[c]);
+           break;
+        default:
+           assert(0);
+        }
+      }
+      break;
+
+   case ir_unop_sign:
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        switch (this->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.u[c] = op[0]->value.i[c] > 0;
+           break;
+        case GLSL_TYPE_INT:
+           data.i[c] = (op[0]->value.i[c] > 0) - (op[0]->value.i[c] < 0);
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.f[c] = float((op[0]->value.f[c] > 0)-(op[0]->value.f[c] < 0));
+           break;
+        default:
+           assert(0);
+        }
+      }
+      break;
+
+   case ir_unop_rcp:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        switch (this->type->base_type) {
+        case GLSL_TYPE_UINT:
+           if (op[0]->value.u[c] != 0.0)
+              data.u[c] = 1 / op[0]->value.u[c];
+           break;
+        case GLSL_TYPE_INT:
+           if (op[0]->value.i[c] != 0.0)
+              data.i[c] = 1 / op[0]->value.i[c];
+           break;
+        case GLSL_TYPE_FLOAT:
+           if (op[0]->value.f[c] != 0.0)
+              data.f[c] = 1.0 / op[0]->value.f[c];
+           break;
+        default:
+           assert(0);
+        }
+      }
+      break;
+
+   case ir_unop_rsq:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = 1.0 / sqrtf(op[0]->value.f[c]);
+      }
+      break;
+
+   case ir_unop_sqrt:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = sqrtf(op[0]->value.f[c]);
+      }
+      break;
+
+   case ir_unop_exp:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = expf(op[0]->value.f[c]);
+      }
+      break;
+
+   case ir_unop_exp2:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = exp2f(op[0]->value.f[c]);
+      }
+      break;
+
+   case ir_unop_log:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = logf(op[0]->value.f[c]);
+      }
+      break;
+
+   case ir_unop_log2:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = log2f(op[0]->value.f[c]);
+      }
+      break;
+
+   case ir_unop_dFdx:
+   case ir_unop_dFdy:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = 0.0;
+      }
+      break;
+
+   case ir_binop_pow:
+      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        data.f[c] = powf(op[0]->value.f[c], op[1]->value.f[c]);
+      }
+      break;
+
+   case ir_binop_dot:
+      data.f[0] = dot(op[0], op[1]);
+      break;
+
+   case ir_binop_min:
+      assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
+      for (unsigned c = 0, c0 = 0, c1 = 0;
+          c < components;
+          c0 += c0_inc, c1 += c1_inc, c++) {
+
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.u[c] = MIN2(op[0]->value.u[c0], op[1]->value.u[c1]);
+           break;
+        case GLSL_TYPE_INT:
+           data.i[c] = MIN2(op[0]->value.i[c0], op[1]->value.i[c1]);
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.f[c] = MIN2(op[0]->value.f[c0], op[1]->value.f[c1]);
+           break;
+        default:
+           assert(0);
+        }
+      }
+
+      break;
+   case ir_binop_max:
+      assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
+      for (unsigned c = 0, c0 = 0, c1 = 0;
+          c < components;
+          c0 += c0_inc, c1 += c1_inc, c++) {
+
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.u[c] = MAX2(op[0]->value.u[c0], op[1]->value.u[c1]);
+           break;
+        case GLSL_TYPE_INT:
+           data.i[c] = MAX2(op[0]->value.i[c0], op[1]->value.i[c1]);
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.f[c] = MAX2(op[0]->value.f[c0], op[1]->value.f[c1]);
+           break;
+        default:
+           assert(0);
+        }
+      }
+      break;
+
+   case ir_binop_cross:
+      assert(op[0]->type == glsl_type::vec3_type);
+      assert(op[1]->type == glsl_type::vec3_type);
+      data.f[0] = (op[0]->value.f[1] * op[1]->value.f[2] -
+                  op[1]->value.f[1] * op[0]->value.f[2]);
+      data.f[1] = (op[0]->value.f[2] * op[1]->value.f[0] -
+                  op[1]->value.f[2] * op[0]->value.f[0]);
+      data.f[2] = (op[0]->value.f[0] * op[1]->value.f[1] -
+                  op[1]->value.f[0] * op[0]->value.f[1]);
+      break;
+
+   case ir_binop_add:
+      assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
+      for (unsigned c = 0, c0 = 0, c1 = 0;
+          c < components;
+          c0 += c0_inc, c1 += c1_inc, c++) {
+
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.u[c] = op[0]->value.u[c0] + op[1]->value.u[c1];
+           break;
+        case GLSL_TYPE_INT:
+           data.i[c] = op[0]->value.i[c0] + op[1]->value.i[c1];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.f[c] = op[0]->value.f[c0] + op[1]->value.f[c1];
+           break;
+        default:
+           assert(0);
+        }
+      }
+
+      break;
+   case ir_binop_sub:
+      assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
+      for (unsigned c = 0, c0 = 0, c1 = 0;
+          c < components;
+          c0 += c0_inc, c1 += c1_inc, c++) {
+
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.u[c] = op[0]->value.u[c0] - op[1]->value.u[c1];
+           break;
+        case GLSL_TYPE_INT:
+           data.i[c] = op[0]->value.i[c0] - op[1]->value.i[c1];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.f[c] = op[0]->value.f[c0] - op[1]->value.f[c1];
+           break;
+        default:
+           assert(0);
+        }
+      }
+
+      break;
+   case ir_binop_mul:
+      /* Check for equal types, or unequal types involving scalars */
+      if ((op[0]->type == op[1]->type && !op[0]->type->is_matrix())
+         || op0_scalar || op1_scalar) {
+        for (unsigned c = 0, c0 = 0, c1 = 0;
+             c < components;
+             c0 += c0_inc, c1 += c1_inc, c++) {
+
+           switch (op[0]->type->base_type) {
+           case GLSL_TYPE_UINT:
+              data.u[c] = op[0]->value.u[c0] * op[1]->value.u[c1];
+              break;
+           case GLSL_TYPE_INT:
+              data.i[c] = op[0]->value.i[c0] * op[1]->value.i[c1];
+              break;
+           case GLSL_TYPE_FLOAT:
+              data.f[c] = op[0]->value.f[c0] * op[1]->value.f[c1];
+              break;
+           default:
+              assert(0);
+           }
+        }
+      } else {
+        assert(op[0]->type->is_matrix() || op[1]->type->is_matrix());
+
+        /* Multiply an N-by-M matrix with an M-by-P matrix.  Since either
+         * matrix can be a GLSL vector, either N or P can be 1.
+         *
+         * For vec*mat, the vector is treated as a row vector.  This
+         * means the vector is a 1-row x M-column matrix.
+         *
+         * For mat*vec, the vector is treated as a column vector.  Since
+         * matrix_columns is 1 for vectors, this just works.
+         */
+        const unsigned n = op[0]->type->is_vector()
+           ? 1 : op[0]->type->vector_elements;
+        const unsigned m = op[1]->type->vector_elements;
+        const unsigned p = op[1]->type->matrix_columns;
+        for (unsigned j = 0; j < p; j++) {
+           for (unsigned i = 0; i < n; i++) {
+              for (unsigned k = 0; k < m; k++) {
+                 data.f[i+n*j] += op[0]->value.f[i+n*k]*op[1]->value.f[k+m*j];
+              }
+           }
+        }
+      }
+
+      break;
+   case ir_binop_div:
+      assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
+      for (unsigned c = 0, c0 = 0, c1 = 0;
+          c < components;
+          c0 += c0_inc, c1 += c1_inc, c++) {
+
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.u[c] = op[0]->value.u[c0] / op[1]->value.u[c1];
+           break;
+        case GLSL_TYPE_INT:
+           data.i[c] = op[0]->value.i[c0] / op[1]->value.i[c1];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.f[c] = op[0]->value.f[c0] / op[1]->value.f[c1];
+           break;
+        default:
+           assert(0);
+        }
+      }
+
+      break;
+   case ir_binop_mod:
+      assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
+      for (unsigned c = 0, c0 = 0, c1 = 0;
+          c < components;
+          c0 += c0_inc, c1 += c1_inc, c++) {
+
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.u[c] = op[0]->value.u[c0] % op[1]->value.u[c1];
+           break;
+        case GLSL_TYPE_INT:
+           data.i[c] = op[0]->value.i[c0] % op[1]->value.i[c1];
+           break;
+        case GLSL_TYPE_FLOAT:
+           /* We don't use fmod because it rounds toward zero; GLSL specifies
+            * the use of floor.
+            */
+           data.f[c] = op[0]->value.f[c0] - op[1]->value.f[c1]
+              * floorf(op[0]->value.f[c0] / op[1]->value.f[c1]);
+           break;
+        default:
+           assert(0);
+        }
+      }
+
+      break;
+
+   case ir_binop_logic_and:
+      assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.b[c] = op[0]->value.b[c] && op[1]->value.b[c];
+      break;
+   case ir_binop_logic_xor:
+      assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.b[c] = op[0]->value.b[c] ^ op[1]->value.b[c];
+      break;
+   case ir_binop_logic_or:
+      assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.b[c] = op[0]->value.b[c] || op[1]->value.b[c];
+      break;
+
+   case ir_binop_less:
+      switch (op[0]->type->base_type) {
+      case GLSL_TYPE_UINT:
+        data.b[0] = op[0]->value.u[0] < op[1]->value.u[0];
+        break;
+      case GLSL_TYPE_INT:
+        data.b[0] = op[0]->value.i[0] < op[1]->value.i[0];
+        break;
+      case GLSL_TYPE_FLOAT:
+        data.b[0] = op[0]->value.f[0] < op[1]->value.f[0];
+        break;
+      default:
+        assert(0);
+      }
+      break;
+   case ir_binop_greater:
+      switch (op[0]->type->base_type) {
+      case GLSL_TYPE_UINT:
+        data.b[0] = op[0]->value.u[0] > op[1]->value.u[0];
+        break;
+      case GLSL_TYPE_INT:
+        data.b[0] = op[0]->value.i[0] > op[1]->value.i[0];
+        break;
+      case GLSL_TYPE_FLOAT:
+        data.b[0] = op[0]->value.f[0] > op[1]->value.f[0];
+        break;
+      default:
+        assert(0);
+      }
+      break;
+   case ir_binop_lequal:
+      switch (op[0]->type->base_type) {
+      case GLSL_TYPE_UINT:
+        data.b[0] = op[0]->value.u[0] <= op[1]->value.u[0];
+        break;
+      case GLSL_TYPE_INT:
+        data.b[0] = op[0]->value.i[0] <= op[1]->value.i[0];
+        break;
+      case GLSL_TYPE_FLOAT:
+        data.b[0] = op[0]->value.f[0] <= op[1]->value.f[0];
+        break;
+      default:
+        assert(0);
+      }
+      break;
+   case ir_binop_gequal:
+      switch (op[0]->type->base_type) {
+      case GLSL_TYPE_UINT:
+        data.b[0] = op[0]->value.u[0] >= op[1]->value.u[0];
+        break;
+      case GLSL_TYPE_INT:
+        data.b[0] = op[0]->value.i[0] >= op[1]->value.i[0];
+        break;
+      case GLSL_TYPE_FLOAT:
+        data.b[0] = op[0]->value.f[0] >= op[1]->value.f[0];
+        break;
+      default:
+        assert(0);
+      }
+      break;
+
+   case ir_binop_equal:
+      data.b[0] = op[0]->has_value(op[1]);
+      break;
+   case ir_binop_nequal:
+      data.b[0] = !op[0]->has_value(op[1]);
+      break;
+
+   default:
+      /* FINISHME: Should handle all expression types. */
+      return NULL;
+   }
+
+   return new(ctx) ir_constant(this->type, &data);
+}
+
+
+ir_constant *
+ir_texture::constant_expression_value()
+{
+   /* texture lookups aren't constant expressions */
+   return NULL;
+}
+
+
+ir_constant *
+ir_swizzle::constant_expression_value()
+{
+   ir_constant *v = this->val->constant_expression_value();
+
+   if (v != NULL) {
+      ir_constant_data data = { { 0 } };
+
+      const unsigned swiz_idx[4] = {
+        this->mask.x, this->mask.y, this->mask.z, this->mask.w
+      };
+
+      for (unsigned i = 0; i < this->mask.num_components; i++) {
+        switch (v->type->base_type) {
+        case GLSL_TYPE_UINT:
+        case GLSL_TYPE_INT:   data.u[i] = v->value.u[swiz_idx[i]]; break;
+        case GLSL_TYPE_FLOAT: data.f[i] = v->value.f[swiz_idx[i]]; break;
+        case GLSL_TYPE_BOOL:  data.b[i] = v->value.b[swiz_idx[i]]; break;
+        default:              assert(!"Should not get here."); break;
+        }
+      }
+
+      void *ctx = talloc_parent(this);
+      return new(ctx) ir_constant(this->type, &data);
+   }
+   return NULL;
+}
+
+
+ir_constant *
+ir_dereference_variable::constant_expression_value()
+{
+   /* This may occur during compile and var->type is glsl_type::error_type */
+   if (!var)
+      return NULL;
+
+   /* The constant_value of a uniform variable is its initializer,
+    * not the lifetime constant value of the uniform.
+    */
+   if (var->mode == ir_var_uniform)
+      return NULL;
+
+   if (!var->constant_value)
+      return NULL;
+
+   return var->constant_value->clone(talloc_parent(var), NULL);
+}
+
+
+ir_constant *
+ir_dereference_array::constant_expression_value()
+{
+   ir_constant *array = this->array->constant_expression_value();
+   ir_constant *idx = this->array_index->constant_expression_value();
+
+   if ((array != NULL) && (idx != NULL)) {
+      void *ctx = talloc_parent(this);
+      if (array->type->is_matrix()) {
+        /* Array access of a matrix results in a vector.
+         */
+        const unsigned column = idx->value.u[0];
+
+        const glsl_type *const column_type = array->type->column_type();
+
+        /* Offset in the constant matrix to the first element of the column
+         * to be extracted.
+         */
+        const unsigned mat_idx = column * column_type->vector_elements;
+
+        ir_constant_data data;
+
+        switch (column_type->base_type) {
+        case GLSL_TYPE_UINT:
+        case GLSL_TYPE_INT:
+           for (unsigned i = 0; i < column_type->vector_elements; i++)
+              data.u[i] = array->value.u[mat_idx + i];
+
+           break;
+
+        case GLSL_TYPE_FLOAT:
+           for (unsigned i = 0; i < column_type->vector_elements; i++)
+              data.f[i] = array->value.f[mat_idx + i];
+
+           break;
+
+        default:
+           assert(!"Should not get here.");
+           break;
+        }
+
+        return new(ctx) ir_constant(column_type, &data);
+      } else if (array->type->is_vector()) {
+        const unsigned component = idx->value.u[0];
+
+        return new(ctx) ir_constant(array, component);
+      } else {
+        const unsigned index = idx->value.u[0];
+        return array->get_array_element(index)->clone(ctx, NULL);
+      }
+   }
+   return NULL;
+}
+
+
+ir_constant *
+ir_dereference_record::constant_expression_value()
+{
+   ir_constant *v = this->record->constant_expression_value();
+
+   return (v != NULL) ? v->get_record_field(this->field) : NULL;
+}
+
+
+ir_constant *
+ir_assignment::constant_expression_value()
+{
+   /* FINISHME: Handle CEs involving assignment (return RHS) */
+   return NULL;
+}
+
+
+ir_constant *
+ir_constant::constant_expression_value()
+{
+   return this;
+}
+
+
+ir_constant *
+ir_call::constant_expression_value()
+{
+   if (this->type == glsl_type::error_type)
+      return NULL;
+
+   /* From the GLSL 1.20 spec, page 23:
+    * "Function calls to user-defined functions (non-built-in functions)
+    *  cannot be used to form constant expressions."
+    */
+   if (!this->callee->function()->is_builtin)
+      return NULL;
+
+   unsigned num_parameters = 0;
+
+   /* Check if all parameters are constant */
+   ir_constant *op[3];
+   foreach_list(n, &this->actual_parameters) {
+      ir_constant *constant = ((ir_rvalue *) n)->constant_expression_value();
+      if (constant == NULL)
+        return NULL;
+
+      op[num_parameters] = constant;
+
+      assert(num_parameters < 3);
+      num_parameters++;
+   }
+
+   /* Individual cases below can either:
+    * - Assign "expr" a new ir_expression to evaluate (for basic opcodes)
+    * - Fill "data" with appopriate constant data
+    * - Return an ir_constant directly.
+    */
+   void *mem_ctx = talloc_parent(this);
+   ir_expression *expr = NULL;
+
+   ir_constant_data data;
+   memset(&data, 0, sizeof(data));
+
+   const char *callee = this->callee_name();
+   if (strcmp(callee, "abs") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_unop_abs, type, op[0], NULL);
+   } else if (strcmp(callee, "all") == 0) {
+      assert(op[0]->type->is_boolean());
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        if (!op[0]->value.b[c])
+           return new(mem_ctx) ir_constant(false);
+      }
+      return new(mem_ctx) ir_constant(true);
+   } else if (strcmp(callee, "any") == 0) {
+      assert(op[0]->type->is_boolean());
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        if (op[0]->value.b[c])
+           return new(mem_ctx) ir_constant(true);
+      }
+      return new(mem_ctx) ir_constant(false);
+   } else if (strcmp(callee, "acos") == 0) {
+      assert(op[0]->type->is_float());
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.f[c] = acosf(op[0]->value.f[c]);
+   } else if (strcmp(callee, "asin") == 0) {
+      assert(op[0]->type->is_float());
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.f[c] = asinf(op[0]->value.f[c]);
+   } else if (strcmp(callee, "atan") == 0) {
+      assert(op[0]->type->is_float());
+      if (num_parameters == 2) {
+        assert(op[1]->type->is_float());
+        for (unsigned c = 0; c < op[0]->type->components(); c++)
+           data.f[c] = atan2f(op[0]->value.f[c], op[1]->value.f[c]);
+      } else {
+        for (unsigned c = 0; c < op[0]->type->components(); c++)
+           data.f[c] = atanf(op[0]->value.f[c]);
+      }
+   } else if (strcmp(callee, "dFdx") == 0 || strcmp(callee, "dFdy") == 0) {
+      return ir_constant::zero(mem_ctx, this->type);
+   } else if (strcmp(callee, "ceil") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_unop_ceil, type, op[0], NULL);
+   } else if (strcmp(callee, "clamp") == 0) {
+      assert(num_parameters == 3);
+      unsigned c1_inc = op[1]->type->is_scalar() ? 0 : 1;
+      unsigned c2_inc = op[2]->type->is_scalar() ? 0 : 1;
+      for (unsigned c = 0, c1 = 0, c2 = 0;
+          c < op[0]->type->components();
+          c1 += c1_inc, c2 += c2_inc, c++) {
+
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.u[c] = CLAMP(op[0]->value.u[c], op[1]->value.u[c1],
+                             op[2]->value.u[c2]);
+           break;
+        case GLSL_TYPE_INT:
+           data.i[c] = CLAMP(op[0]->value.i[c], op[1]->value.i[c1],
+                             op[2]->value.i[c2]);
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.f[c] = CLAMP(op[0]->value.f[c], op[1]->value.f[c1],
+                             op[2]->value.f[c2]);
+           break;
+        default:
+           assert(!"Should not get here.");
+        }
+      }
+   } else if (strcmp(callee, "cos") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_unop_cos, type, op[0], NULL);
+   } else if (strcmp(callee, "cosh") == 0) {
+      assert(op[0]->type->is_float());
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.f[c] = coshf(op[0]->value.f[c]);
+   } else if (strcmp(callee, "cross") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_binop_cross, type, op[0], op[1]);
+   } else if (strcmp(callee, "degrees") == 0) {
+      assert(op[0]->type->is_float());
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.f[c] = 180.0/M_PI * op[0]->value.f[c];
+   } else if (strcmp(callee, "distance") == 0) {
+      assert(op[0]->type->is_float() && op[1]->type->is_float());
+      float length_squared = 0.0;
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        float t = op[0]->value.f[c] - op[1]->value.f[c];
+        length_squared += t * t;
+      }
+      return new(mem_ctx) ir_constant(sqrtf(length_squared));
+   } else if (strcmp(callee, "dot") == 0) {
+      return new(mem_ctx) ir_constant(dot(op[0], op[1]));
+   } else if (strcmp(callee, "equal") == 0) {
+      assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.b[c] = op[0]->value.u[c] == op[1]->value.u[c];
+           break;
+        case GLSL_TYPE_INT:
+           data.b[c] = op[0]->value.i[c] == op[1]->value.i[c];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.b[c] = op[0]->value.f[c] == op[1]->value.f[c];
+           break;
+        case GLSL_TYPE_BOOL:
+           data.b[c] = op[0]->value.b[c] == op[1]->value.b[c];
+           break;
+        default:
+           assert(!"Should not get here.");
+        }
+      }
+   } else if (strcmp(callee, "exp") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_unop_exp, type, op[0], NULL);
+   } else if (strcmp(callee, "exp2") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_unop_exp2, type, op[0], NULL);
+   } else if (strcmp(callee, "faceforward") == 0) {
+      if (dot(op[2], op[1]) < 0)
+        return op[0];
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.f[c] = -op[0]->value.f[c];
+   } else if (strcmp(callee, "floor") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_unop_floor, type, op[0], NULL);
+   } else if (strcmp(callee, "fract") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_unop_fract, type, op[0], NULL);
+   } else if (strcmp(callee, "fwidth") == 0) {
+      return ir_constant::zero(mem_ctx, this->type);
+   } else if (strcmp(callee, "greaterThan") == 0) {
+      assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.b[c] = op[0]->value.u[c] > op[1]->value.u[c];
+           break;
+        case GLSL_TYPE_INT:
+           data.b[c] = op[0]->value.i[c] > op[1]->value.i[c];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.b[c] = op[0]->value.f[c] > op[1]->value.f[c];
+           break;
+        default:
+           assert(!"Should not get here.");
+        }
+      }
+   } else if (strcmp(callee, "greaterThanEqual") == 0) {
+      assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.b[c] = op[0]->value.u[c] >= op[1]->value.u[c];
+           break;
+        case GLSL_TYPE_INT:
+           data.b[c] = op[0]->value.i[c] >= op[1]->value.i[c];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.b[c] = op[0]->value.f[c] >= op[1]->value.f[c];
+           break;
+        default:
+           assert(!"Should not get here.");
+        }
+      }
+   } else if (strcmp(callee, "inversesqrt") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_unop_rsq, type, op[0], NULL);
+   } else if (strcmp(callee, "length") == 0) {
+      return new(mem_ctx) ir_constant(sqrtf(dot(op[0], op[0])));
+   } else if (strcmp(callee, "lessThan") == 0) {
+      assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.b[c] = op[0]->value.u[c] < op[1]->value.u[c];
+           break;
+        case GLSL_TYPE_INT:
+           data.b[c] = op[0]->value.i[c] < op[1]->value.i[c];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.b[c] = op[0]->value.f[c] < op[1]->value.f[c];
+           break;
+        default:
+           assert(!"Should not get here.");
+        }
+      }
+   } else if (strcmp(callee, "lessThanEqual") == 0) {
+      assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.b[c] = op[0]->value.u[c] <= op[1]->value.u[c];
+           break;
+        case GLSL_TYPE_INT:
+           data.b[c] = op[0]->value.i[c] <= op[1]->value.i[c];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.b[c] = op[0]->value.f[c] <= op[1]->value.f[c];
+           break;
+        default:
+           assert(!"Should not get here.");
+        }
+      }
+   } else if (strcmp(callee, "log") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_unop_log, type, op[0], NULL);
+   } else if (strcmp(callee, "log2") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_unop_log2, type, op[0], NULL);
+   } else if (strcmp(callee, "matrixCompMult") == 0) {
+      assert(op[0]->type->is_float() && op[1]->type->is_float());
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.f[c] = op[0]->value.f[c] * op[1]->value.f[c];
+   } else if (strcmp(callee, "max") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_binop_max, type, op[0], op[1]);
+   } else if (strcmp(callee, "min") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_binop_min, type, op[0], op[1]);
+   } else if (strcmp(callee, "mix") == 0) {
+      assert(op[0]->type->is_float() && op[1]->type->is_float());
+      if (op[2]->type->is_float()) {
+        unsigned c2_inc = op[2]->type->is_scalar() ? 0 : 1;
+        unsigned components = op[0]->type->components();
+        for (unsigned c = 0, c2 = 0; c < components; c2 += c2_inc, c++) {
+           data.f[c] = op[0]->value.f[c] * (1 - op[2]->value.f[c2]) +
+                       op[1]->value.f[c] * op[2]->value.f[c2];
+        }
+      } else {
+        assert(op[2]->type->is_boolean());
+        for (unsigned c = 0; c < op[0]->type->components(); c++)
+           data.f[c] = op[op[2]->value.b[c] ? 1 : 0]->value.f[c];
+      }
+   } else if (strcmp(callee, "mod") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_binop_mod, type, op[0], op[1]);
+   } else if (strcmp(callee, "normalize") == 0) {
+      assert(op[0]->type->is_float());
+      float length = sqrtf(dot(op[0], op[0]));
+
+      if (length == 0)
+        return ir_constant::zero(mem_ctx, this->type);
+
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.f[c] = op[0]->value.f[c] / length;
+   } else if (strcmp(callee, "not") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_unop_logic_not, type, op[0], NULL);
+   } else if (strcmp(callee, "notEqual") == 0) {
+      assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
+      for (unsigned c = 0; c < op[0]->type->components(); c++) {
+        switch (op[0]->type->base_type) {
+        case GLSL_TYPE_UINT:
+           data.b[c] = op[0]->value.u[c] != op[1]->value.u[c];
+           break;
+        case GLSL_TYPE_INT:
+           data.b[c] = op[0]->value.i[c] != op[1]->value.i[c];
+           break;
+        case GLSL_TYPE_FLOAT:
+           data.b[c] = op[0]->value.f[c] != op[1]->value.f[c];
+           break;
+        case GLSL_TYPE_BOOL:
+           data.b[c] = op[0]->value.b[c] != op[1]->value.b[c];
+           break;
+        default:
+           assert(!"Should not get here.");
+        }
+      }
+   } else if (strcmp(callee, "outerProduct") == 0) {
+      assert(op[0]->type->is_vector() && op[1]->type->is_vector());
+      const unsigned m = op[0]->type->vector_elements;
+      const unsigned n = op[1]->type->vector_elements;
+      for (unsigned j = 0; j < n; j++) {
+        for (unsigned i = 0; i < m; i++) {
+           data.f[i+m*j] = op[0]->value.f[i] * op[1]->value.f[j];
+        }
+      }
+   } else if (strcmp(callee, "pow") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_binop_pow, type, op[0], op[1]);
+   } else if (strcmp(callee, "radians") == 0) {
+      assert(op[0]->type->is_float());
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.f[c] = M_PI/180.0 * op[0]->value.f[c];
+   } else if (strcmp(callee, "reflect") == 0) {
+      assert(op[0]->type->is_float());
+      float dot_NI = dot(op[1], op[0]);
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.f[c] = op[0]->value.f[c] - 2 * dot_NI * op[1]->value.f[c];
+   } else if (strcmp(callee, "refract") == 0) {
+      const float eta = op[2]->value.f[0];
+      const float dot_NI = dot(op[1], op[0]);
+      const float k = 1.0 - eta * eta * (1.0 - dot_NI * dot_NI);
+      if (k < 0.0) {
+        return ir_constant::zero(mem_ctx, this->type);
+      } else {
+        for (unsigned c = 0; c < type->components(); c++) {
+           data.f[c] = eta * op[0]->value.f[c] - (eta * dot_NI + sqrtf(k))
+                           * op[1]->value.f[c];
+        }
+      }
+   } else if (strcmp(callee, "sign") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_unop_sign, type, op[0], NULL);
+   } else if (strcmp(callee, "sin") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_unop_sin, type, op[0], NULL);
+   } else if (strcmp(callee, "sinh") == 0) {
+      assert(op[0]->type->is_float());
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.f[c] = sinhf(op[0]->value.f[c]);
+   } else if (strcmp(callee, "smoothstep") == 0) {
+      assert(num_parameters == 3);
+      assert(op[1]->type == op[0]->type);
+      unsigned edge_inc = op[0]->type->is_scalar() ? 0 : 1;
+      for (unsigned c = 0, e = 0; c < type->components(); e += edge_inc, c++) {
+        const float edge0 = op[0]->value.f[e];
+        const float edge1 = op[1]->value.f[e];
+        if (edge0 == edge1) {
+           data.f[c] = 0.0; /* Avoid a crash - results are undefined anyway */
+        } else {
+           const float numerator = op[2]->value.f[c] - edge0;
+           const float denominator = edge1 - edge0;
+           const float t = CLAMP(numerator/denominator, 0, 1);
+           data.f[c] = t * t * (3 - 2 * t);
+        }
+      }
+   } else if (strcmp(callee, "sqrt") == 0) {
+      expr = new(mem_ctx) ir_expression(ir_unop_sqrt, type, op[0], NULL);
+   } else if (strcmp(callee, "step") == 0) {
+      assert(op[0]->type->is_float() && op[1]->type->is_float());
+      /* op[0] (edge) may be either a scalar or a vector */
+      const unsigned c0_inc = op[0]->type->is_scalar() ? 0 : 1;
+      for (unsigned c = 0, c0 = 0; c < type->components(); c0 += c0_inc, c++)
+        data.f[c] = (op[1]->value.f[c] < op[0]->value.f[c0]) ? 0.0 : 1.0;
+   } else if (strcmp(callee, "tan") == 0) {
+      assert(op[0]->type->is_float());
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.f[c] = tanf(op[0]->value.f[c]);
+   } else if (strcmp(callee, "tanh") == 0) {
+      assert(op[0]->type->is_float());
+      for (unsigned c = 0; c < op[0]->type->components(); c++)
+        data.f[c] = tanhf(op[0]->value.f[c]);
+   } else if (strcmp(callee, "transpose") == 0) {
+      assert(op[0]->type->is_matrix());
+      const unsigned n = op[0]->type->vector_elements;
+      const unsigned m = op[0]->type->matrix_columns;
+      for (unsigned j = 0; j < m; j++) {
+        for (unsigned i = 0; i < n; i++) {
+           data.f[m*i+j] += op[0]->value.f[i+n*j];
+        }
+      }
+   } else {
+      /* Unsupported builtin - some are not allowed in constant expressions. */
+      return NULL;
+   }
+
+   if (expr != NULL)
+      return expr->constant_expression_value();
+
+   return new(mem_ctx) ir_constant(this->type, &data);
+}
diff --git a/src/glsl/ir_constant_folding.cpp b/src/glsl/ir_constant_folding.cpp
new file mode 100644 (file)
index 0000000..554c54f
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_constant_folding.cpp
+ * Replace constant-valued expressions with references to constant values.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_rvalue_visitor.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+/**
+ * Visitor class for replacing expressions with ir_constant values.
+ */
+
+class ir_constant_folding_visitor : public ir_rvalue_visitor {
+public:
+   ir_constant_folding_visitor()
+   {
+      this->progress = false;
+   }
+
+   virtual ~ir_constant_folding_visitor()
+   {
+      /* empty */
+   }
+
+   virtual ir_visitor_status visit_enter(ir_assignment *ir);
+   virtual ir_visitor_status visit_enter(ir_call *ir);
+
+   virtual void handle_rvalue(ir_rvalue **rvalue);
+
+   bool progress;
+};
+
+void
+ir_constant_folding_visitor::handle_rvalue(ir_rvalue **rvalue)
+{
+   if (*rvalue == NULL || (*rvalue)->ir_type == ir_type_constant)
+      return;
+
+   /* Note that we do rvalue visitoring on leaving.  So if an
+    * expression has a non-constant operand, no need to go looking
+    * down it to find if it's constant.  This cuts the time of this
+    * pass down drastically.
+    */
+   ir_expression *expr = (*rvalue)->as_expression();
+   if (expr) {
+      for (unsigned int i = 0; i < expr->get_num_operands(); i++) {
+        if (!expr->operands[i]->as_constant())
+           return;
+      }
+   }
+
+   ir_constant *constant = (*rvalue)->constant_expression_value();
+   if (constant) {
+      *rvalue = constant;
+      this->progress = true;
+   } else {
+      (*rvalue)->accept(this);
+   }
+}
+
+ir_visitor_status
+ir_constant_folding_visitor::visit_enter(ir_assignment *ir)
+{
+   ir->rhs->accept(this);
+   handle_rvalue(&ir->rhs);
+
+   if (ir->condition) {
+      ir->condition->accept(this);
+      handle_rvalue(&ir->condition);
+
+      ir_constant *const_val = ir->condition->as_constant();
+      /* If the condition is constant, either remove the condition or
+       * remove the never-executed assignment.
+       */
+      if (const_val) {
+        if (const_val->value.b[0])
+           ir->condition = NULL;
+        else
+           ir->remove();
+        this->progress = true;
+      }
+   }
+
+   /* Don't descend into the LHS because we want it to stay as a
+    * variable dereference.  FINISHME: We probably should to get array
+    * indices though.
+    */
+   return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_constant_folding_visitor::visit_enter(ir_call *ir)
+{
+   exec_list_iterator sig_iter = ir->get_callee()->parameters.iterator();
+   foreach_iter(exec_list_iterator, iter, *ir) {
+      ir_rvalue *param_rval = (ir_rvalue *)iter.get();
+      ir_variable *sig_param = (ir_variable *)sig_iter.get();
+
+      if (sig_param->mode == ir_var_in) {
+        ir_rvalue *new_param = param_rval;
+
+        handle_rvalue(&new_param);
+        if (new_param != param_rval) {
+           param_rval->replace_with(new_param);
+        }
+      }
+      sig_iter.next();
+   }
+
+   return visit_continue_with_parent;
+}
+
+bool
+do_constant_folding(exec_list *instructions)
+{
+   ir_constant_folding_visitor constant_folding;
+
+   visit_list_elements(&constant_folding, instructions);
+
+   return constant_folding.progress;
+}
diff --git a/src/glsl/ir_constant_propagation.cpp b/src/glsl/ir_constant_propagation.cpp
new file mode 100644 (file)
index 0000000..76c1ce7
--- /dev/null
@@ -0,0 +1,435 @@
+/*
+ * Constantright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * constant of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, constant, 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 constantright 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 CONSTANTRIGHT 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.
+ */
+
+/**
+ * \file ir_constant_propagation.cpp
+ *
+ * Tracks assignments of constants to channels of variables, and
+ * usage of those constant channels with direct usage of the constants.
+ *
+ * This can lead to constant folding and algebraic optimizations in
+ * those later expressions, while causing no increase in instruction
+ * count (due to constants being generally free to load from a
+ * constant push buffer or as instruction immediate values) and
+ * possibly reducing register pressure.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_rvalue_visitor.h"
+#include "ir_basic_block.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+class acp_entry : public exec_node
+{
+public:
+   acp_entry(ir_variable *var, unsigned write_mask, ir_constant *constant)
+   {
+      assert(var);
+      assert(constant);
+      this->var = var;
+      this->write_mask = write_mask;
+      this->constant = constant;
+   }
+
+   ir_variable *var;
+   ir_constant *constant;
+   unsigned write_mask;
+};
+
+
+class kill_entry : public exec_node
+{
+public:
+   kill_entry(ir_variable *var, unsigned write_mask)
+   {
+      assert(var);
+      this->var = var;
+      this->write_mask = write_mask;
+   }
+
+   ir_variable *var;
+   unsigned write_mask;
+};
+
+class ir_constant_propagation_visitor : public ir_rvalue_visitor {
+public:
+   ir_constant_propagation_visitor()
+   {
+      progress = false;
+      mem_ctx = talloc_new(0);
+      this->acp = new(mem_ctx) exec_list;
+      this->kills = new(mem_ctx) exec_list;
+   }
+   ~ir_constant_propagation_visitor()
+   {
+      talloc_free(mem_ctx);
+   }
+
+   virtual ir_visitor_status visit_enter(class ir_loop *);
+   virtual ir_visitor_status visit_enter(class ir_function_signature *);
+   virtual ir_visitor_status visit_enter(class ir_function *);
+   virtual ir_visitor_status visit_enter(class ir_assignment *);
+   virtual ir_visitor_status visit_enter(class ir_call *);
+   virtual ir_visitor_status visit_enter(class ir_if *);
+
+   void add_constant(ir_assignment *ir);
+   void kill(ir_variable *ir, unsigned write_mask);
+   void handle_if_block(exec_list *instructions);
+   void handle_rvalue(ir_rvalue **rvalue);
+
+   /** List of acp_entry: The available constants to propagate */
+   exec_list *acp;
+
+   /**
+    * List of kill_entry: The masks of variables whose values were
+    * killed in this block.
+    */
+   exec_list *kills;
+
+   bool progress;
+
+   bool killed_all;
+
+   void *mem_ctx;
+};
+
+
+void
+ir_constant_propagation_visitor::handle_rvalue(ir_rvalue **rvalue)
+{
+   if (!*rvalue)
+      return;
+
+   const glsl_type *type = (*rvalue)->type;
+   if (!type->is_scalar() && !type->is_vector())
+      return;
+
+   ir_swizzle *swiz = NULL;
+   ir_dereference_variable *deref = (*rvalue)->as_dereference_variable();
+   if (!deref) {
+      swiz = (*rvalue)->as_swizzle();
+      if (!swiz)
+        return;
+
+      deref = swiz->val->as_dereference_variable();
+      if (!deref)
+        return;
+   }
+
+   ir_constant_data data;
+   memset(&data, 0, sizeof(data));
+
+   for (unsigned int i = 0; i < type->components(); i++) {
+      int channel;
+      acp_entry *found = NULL;
+
+      if (swiz) {
+        switch (i) {
+        case 0: channel = swiz->mask.x; break;
+        case 1: channel = swiz->mask.y; break;
+        case 2: channel = swiz->mask.z; break;
+        case 3: channel = swiz->mask.w; break;
+        default: assert(!"shouldn't be reached"); channel = 0; break;
+        }
+      } else {
+        channel = i;
+      }
+
+      foreach_iter(exec_list_iterator, iter, *this->acp) {
+        acp_entry *entry = (acp_entry *)iter.get();
+        if (entry->var == deref->var && entry->write_mask & (1 << channel)) {
+           found = entry;
+           break;
+        }
+      }
+
+      if (!found)
+        return;
+
+      switch (type->base_type) {
+      case GLSL_TYPE_FLOAT:
+        data.f[i] = found->constant->value.f[channel];
+        break;
+      case GLSL_TYPE_INT:
+        data.i[i] = found->constant->value.i[channel];
+        break;
+      case GLSL_TYPE_UINT:
+        data.u[i] = found->constant->value.u[channel];
+        break;
+      case GLSL_TYPE_BOOL:
+        data.b[i] = found->constant->value.b[channel];
+        break;
+      default:
+        assert(!"not reached");
+        break;
+      }
+   }
+
+   *rvalue = new(talloc_parent(deref)) ir_constant(type, &data);
+   this->progress = true;
+}
+
+ir_visitor_status
+ir_constant_propagation_visitor::visit_enter(ir_function_signature *ir)
+{
+   /* Treat entry into a function signature as a completely separate
+    * block.  Any instructions at global scope will be shuffled into
+    * main() at link time, so they're irrelevant to us.
+    */
+   exec_list *orig_acp = this->acp;
+   exec_list *orig_kills = this->kills;
+   bool orig_killed_all = this->killed_all;
+
+   this->acp = new(mem_ctx) exec_list;
+   this->kills = new(mem_ctx) exec_list;
+   this->killed_all = false;
+
+   visit_list_elements(this, &ir->body);
+
+   this->kills = orig_kills;
+   this->acp = orig_acp;
+   this->killed_all = orig_killed_all;
+
+   return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_constant_propagation_visitor::visit_enter(ir_assignment *ir)
+{
+   /* Inline accepting children, skipping the LHS. */
+   ir->rhs->accept(this);
+   handle_rvalue(&ir->rhs);
+
+   if (ir->condition) {
+      ir->condition->accept(this);
+      handle_rvalue(&ir->condition);
+   }
+
+   kill(ir->lhs->variable_referenced(), ir->write_mask);
+
+   add_constant(ir);
+
+   return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_constant_propagation_visitor::visit_enter(ir_function *ir)
+{
+   (void) ir;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_constant_propagation_visitor::visit_enter(ir_call *ir)
+{
+   /* Do constant propagation on call parameters, but skip any out params */
+   exec_list_iterator sig_param_iter = ir->get_callee()->parameters.iterator();
+   foreach_iter(exec_list_iterator, iter, ir->actual_parameters) {
+      ir_variable *sig_param = (ir_variable *)sig_param_iter.get();
+      ir_rvalue *param = (ir_rvalue *)iter.get();
+      if (sig_param->mode != ir_var_out && sig_param->mode != ir_var_inout) {
+        ir_rvalue *new_param = param;
+        handle_rvalue(&new_param);
+         if (new_param != param)
+           param->replace_with(new_param);
+        else
+           param->accept(this);
+      }
+      sig_param_iter.next();
+   }
+
+   /* Since we're unlinked, we don't (necssarily) know the side effects of
+    * this call.  So kill all copies.
+    */
+   acp->make_empty();
+   this->killed_all = true;
+
+   return visit_continue_with_parent;
+}
+
+void
+ir_constant_propagation_visitor::handle_if_block(exec_list *instructions)
+{
+   exec_list *orig_acp = this->acp;
+   exec_list *orig_kills = this->kills;
+   bool orig_killed_all = this->killed_all;
+
+   this->acp = new(mem_ctx) exec_list;
+   this->kills = new(mem_ctx) exec_list;
+   this->killed_all = false;
+
+   /* Populate the initial acp with a constant of the original */
+   foreach_iter(exec_list_iterator, iter, *orig_acp) {
+      acp_entry *a = (acp_entry *)iter.get();
+      this->acp->push_tail(new(this->mem_ctx) acp_entry(a->var, a->write_mask,
+                                                       a->constant));
+   }
+
+   visit_list_elements(this, instructions);
+
+   if (this->killed_all) {
+      orig_acp->make_empty();
+   }
+
+   exec_list *new_kills = this->kills;
+   this->kills = orig_kills;
+   this->acp = orig_acp;
+   this->killed_all = this->killed_all || orig_killed_all;
+
+   foreach_iter(exec_list_iterator, iter, *new_kills) {
+      kill_entry *k = (kill_entry *)iter.get();
+      kill(k->var, k->write_mask);
+   }
+}
+
+ir_visitor_status
+ir_constant_propagation_visitor::visit_enter(ir_if *ir)
+{
+   ir->condition->accept(this);
+   handle_rvalue(&ir->condition);
+
+   handle_if_block(&ir->then_instructions);
+   handle_if_block(&ir->else_instructions);
+
+   /* handle_if_block() already descended into the children. */
+   return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_constant_propagation_visitor::visit_enter(ir_loop *ir)
+{
+   exec_list *orig_acp = this->acp;
+   exec_list *orig_kills = this->kills;
+   bool orig_killed_all = this->killed_all;
+
+   /* FINISHME: For now, the initial acp for loops is totally empty.
+    * We could go through once, then go through again with the acp
+    * cloned minus the killed entries after the first run through.
+    */
+   this->acp = new(mem_ctx) exec_list;
+   this->kills = new(mem_ctx) exec_list;
+   this->killed_all = false;
+
+   visit_list_elements(this, &ir->body_instructions);
+
+   if (this->killed_all) {
+      orig_acp->make_empty();
+   }
+
+   exec_list *new_kills = this->kills;
+   this->kills = orig_kills;
+   this->acp = orig_acp;
+   this->killed_all = this->killed_all || orig_killed_all;
+
+   foreach_iter(exec_list_iterator, iter, *new_kills) {
+      kill_entry *k = (kill_entry *)iter.get();
+      kill(k->var, k->write_mask);
+   }
+
+   /* already descended into the children. */
+   return visit_continue_with_parent;
+}
+
+void
+ir_constant_propagation_visitor::kill(ir_variable *var, unsigned write_mask)
+{
+   assert(var != NULL);
+
+   /* We don't track non-vectors. */
+   if (!var->type->is_vector() && !var->type->is_scalar())
+      return;
+
+   /* Remove any entries currently in the ACP for this kill. */
+   foreach_iter(exec_list_iterator, iter, *this->acp) {
+      acp_entry *entry = (acp_entry *)iter.get();
+
+      if (entry->var == var) {
+        entry->write_mask &= ~write_mask;
+        if (entry->write_mask == 0)
+           entry->remove();
+      }
+   }
+
+   /* Add this writemask of the variable to the list of killed
+    * variables in this block.
+    */
+   foreach_iter(exec_list_iterator, iter, *this->kills) {
+      kill_entry *entry = (kill_entry *)iter.get();
+
+      if (entry->var == var) {
+        entry->write_mask |= write_mask;
+        return;
+      }
+   }
+   /* Not already in the list.  Make new entry. */
+   this->kills->push_tail(new(this->mem_ctx) kill_entry(var, write_mask));
+}
+
+/**
+ * Adds an entry to the available constant list if it's a plain assignment
+ * of a variable to a variable.
+ */
+void
+ir_constant_propagation_visitor::add_constant(ir_assignment *ir)
+{
+   acp_entry *entry;
+
+   if (ir->condition) {
+      ir_constant *condition = ir->condition->as_constant();
+      if (!condition || !condition->value.b[0])
+        return;
+   }
+
+   if (!ir->write_mask)
+      return;
+
+   ir_dereference_variable *deref = ir->lhs->as_dereference_variable();
+   ir_constant *constant = ir->rhs->as_constant();
+
+   if (!deref || !constant)
+      return;
+
+   /* Only do constant propagation on vectors.  Constant matrices,
+    * arrays, or structures would require more work elsewhere.
+    */
+   if (!deref->var->type->is_vector() && !deref->var->type->is_scalar())
+      return;
+
+   entry = new(this->mem_ctx) acp_entry(deref->var, ir->write_mask, constant);
+   this->acp->push_tail(entry);
+}
+
+/**
+ * Does a constant propagation pass on the code present in the instruction stream.
+ */
+bool
+do_constant_propagation(exec_list *instructions)
+{
+   ir_constant_propagation_visitor v;
+
+   visit_list_elements(&v, instructions);
+
+   return v.progress;
+}
diff --git a/src/glsl/ir_constant_variable.cpp b/src/glsl/ir_constant_variable.cpp
new file mode 100644 (file)
index 0000000..1fb73e7
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_constant_variable.cpp
+ *
+ * Marks variables assigned a single constant value over the course
+ * of the program as constant.
+ *
+ * The goal here is to trigger further constant folding and then dead
+ * code elimination.  This is common with vector/matrix constructors
+ * and calls to builtin functions.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+struct assignment_entry {
+   exec_node link;
+   int assignment_count;
+   ir_variable *var;
+   ir_constant *constval;
+   bool our_scope;
+};
+
+class ir_constant_variable_visitor : public ir_hierarchical_visitor {
+public:
+   virtual ir_visitor_status visit_enter(ir_dereference_variable *);
+   virtual ir_visitor_status visit(ir_variable *);
+   virtual ir_visitor_status visit_enter(ir_assignment *);
+   virtual ir_visitor_status visit_enter(ir_call *);
+
+   exec_list list;
+};
+
+static struct assignment_entry *
+get_assignment_entry(ir_variable *var, exec_list *list)
+{
+   struct assignment_entry *entry;
+
+   foreach_list_typed(struct assignment_entry, entry, link, list) {
+      if (entry->var == var)
+        return entry;
+   }
+
+   entry = (struct assignment_entry *)calloc(1, sizeof(*entry));
+   entry->var = var;
+   list->push_head(&entry->link);
+   return entry;
+}
+
+ir_visitor_status
+ir_constant_variable_visitor::visit(ir_variable *ir)
+{
+   struct assignment_entry *entry = get_assignment_entry(ir, &this->list);
+   entry->our_scope = true;
+   return visit_continue;
+}
+
+/* Skip derefs of variables so that we can detect declarations. */
+ir_visitor_status
+ir_constant_variable_visitor::visit_enter(ir_dereference_variable *ir)
+{
+   (void)ir;
+   return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_constant_variable_visitor::visit_enter(ir_assignment *ir)
+{
+   ir_constant *constval;
+   struct assignment_entry *entry;
+
+   entry = get_assignment_entry(ir->lhs->variable_referenced(), &this->list);
+   assert(entry);
+   entry->assignment_count++;
+
+   /* If it's already constant, don't do the work. */
+   if (entry->var->constant_value)
+      return visit_continue;
+
+   /* OK, now find if we actually have all the right conditions for
+    * this to be a constant value assigned to the var.
+    */
+   if (ir->condition) {
+      constval = ir->condition->constant_expression_value();
+      if (!constval || !constval->value.b[0])
+        return visit_continue;
+   }
+
+   ir_variable *var = ir->whole_variable_written();
+   if (!var)
+      return visit_continue;
+
+   constval = ir->rhs->constant_expression_value();
+   if (!constval)
+      return visit_continue;
+
+   /* Mark this entry as having a constant assignment (if the
+    * assignment count doesn't go >1).  do_constant_variable will fix
+    * up the variable with the constant value later.
+    */
+   entry->constval = constval;
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_constant_variable_visitor::visit_enter(ir_call *ir)
+{
+   exec_list_iterator sig_iter = ir->get_callee()->parameters.iterator();
+   foreach_iter(exec_list_iterator, iter, *ir) {
+      ir_rvalue *param_rval = (ir_rvalue *)iter.get();
+      ir_variable *param = (ir_variable *)sig_iter.get();
+
+      if (param->mode == ir_var_out ||
+         param->mode == ir_var_inout) {
+        ir_variable *var = param_rval->variable_referenced();
+        struct assignment_entry *entry;
+
+        assert(var);
+        entry = get_assignment_entry(var, &this->list);
+        entry->assignment_count++;
+      }
+      sig_iter.next();
+   }
+   return visit_continue;
+}
+
+/**
+ * Does a copy propagation pass on the code present in the instruction stream.
+ */
+bool
+do_constant_variable(exec_list *instructions)
+{
+   bool progress = false;
+   ir_constant_variable_visitor v;
+
+   v.run(instructions);
+
+   while (!v.list.is_empty()) {
+
+      struct assignment_entry *entry;
+      entry = exec_node_data(struct assignment_entry, v.list.head, link);
+
+      if (entry->assignment_count == 1 && entry->constval && entry->our_scope) {
+        entry->var->constant_value = entry->constval;
+        progress = true;
+      }
+      entry->link.remove();
+      free(entry);
+   }
+
+   return progress;
+}
+
+bool
+do_constant_variable_unlinked(exec_list *instructions)
+{
+   bool progress = false;
+
+   foreach_iter(exec_list_iterator, iter, *instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      ir_function *f = ir->as_function();
+      if (f) {
+        foreach_iter(exec_list_iterator, sigiter, *f) {
+           ir_function_signature *sig =
+              (ir_function_signature *) sigiter.get();
+           if (do_constant_variable(&sig->body))
+              progress = true;
+        }
+      }
+   }
+
+   return progress;
+}
diff --git a/src/glsl/ir_copy_propagation.cpp b/src/glsl/ir_copy_propagation.cpp
new file mode 100644 (file)
index 0000000..6c211f0
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_copy_propagation.cpp
+ *
+ * Moves usage of recently-copied variables to the previous copy of
+ * the variable.
+ *
+ * This should reduce the number of MOV instructions in the generated
+ * programs unless copy propagation is also done on the LIR, and may
+ * help anyway by triggering other optimizations that live in the HIR.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_basic_block.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+class acp_entry : public exec_node
+{
+public:
+   acp_entry(ir_variable *lhs, ir_variable *rhs)
+   {
+      assert(lhs);
+      assert(rhs);
+      this->lhs = lhs;
+      this->rhs = rhs;
+   }
+
+   ir_variable *lhs;
+   ir_variable *rhs;
+};
+
+
+class kill_entry : public exec_node
+{
+public:
+   kill_entry(ir_variable *var)
+   {
+      assert(var);
+      this->var = var;
+   }
+
+   ir_variable *var;
+};
+
+class ir_copy_propagation_visitor : public ir_hierarchical_visitor {
+public:
+   ir_copy_propagation_visitor()
+   {
+      progress = false;
+      mem_ctx = talloc_new(0);
+      this->acp = new(mem_ctx) exec_list;
+      this->kills = new(mem_ctx) exec_list;
+   }
+   ~ir_copy_propagation_visitor()
+   {
+      talloc_free(mem_ctx);
+   }
+
+   virtual ir_visitor_status visit(class ir_dereference_variable *);
+   virtual ir_visitor_status visit_enter(class ir_loop *);
+   virtual ir_visitor_status visit_enter(class ir_function_signature *);
+   virtual ir_visitor_status visit_enter(class ir_function *);
+   virtual ir_visitor_status visit_enter(class ir_assignment *);
+   virtual ir_visitor_status visit_enter(class ir_call *);
+   virtual ir_visitor_status visit_enter(class ir_if *);
+
+   void add_copy(ir_assignment *ir);
+   void kill(ir_variable *ir);
+   void handle_if_block(exec_list *instructions);
+
+   /** List of acp_entry: The available copies to propagate */
+   exec_list *acp;
+   /**
+    * List of kill_entry: The variables whose values were killed in this
+    * block.
+    */
+   exec_list *kills;
+
+   bool progress;
+
+   bool killed_all;
+
+   void *mem_ctx;
+};
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_function_signature *ir)
+{
+   /* Treat entry into a function signature as a completely separate
+    * block.  Any instructions at global scope will be shuffled into
+    * main() at link time, so they're irrelevant to us.
+    */
+   exec_list *orig_acp = this->acp;
+   exec_list *orig_kills = this->kills;
+   bool orig_killed_all = this->killed_all;
+
+   this->acp = new(mem_ctx) exec_list;
+   this->kills = new(mem_ctx) exec_list;
+   this->killed_all = false;
+
+   visit_list_elements(this, &ir->body);
+
+   this->kills = orig_kills;
+   this->acp = orig_acp;
+   this->killed_all = orig_killed_all;
+
+   return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_assignment *ir)
+{
+   ir_visitor_status s;
+
+   /* ir_assignment::accept(ir_hv *v), skipping the LHS so that we can
+    * avoid copy propagating into the LHS.
+    *
+    * Note that this means we won't copy propagate into the derefs of
+    * an array index.  Oh well.
+    */
+
+   s = ir->rhs->accept(this);
+   assert(s == visit_continue);
+
+   if (ir->condition) {
+      s = ir->condition->accept(this);
+      assert(s == visit_continue);
+   }
+
+   kill(ir->lhs->variable_referenced());
+
+   add_copy(ir);
+
+   return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_function *ir)
+{
+   (void) ir;
+   return visit_continue;
+}
+
+/**
+ * Replaces dereferences of ACP RHS variables with ACP LHS variables.
+ *
+ * This is where the actual copy propagation occurs.  Note that the
+ * rewriting of ir_dereference means that the ir_dereference instance
+ * must not be shared by multiple IR operations!
+ */
+ir_visitor_status
+ir_copy_propagation_visitor::visit(ir_dereference_variable *ir)
+{
+   ir_variable *var = ir->var;
+
+   foreach_iter(exec_list_iterator, iter, *this->acp) {
+      acp_entry *entry = (acp_entry *)iter.get();
+
+      if (var == entry->lhs) {
+        ir->var = entry->rhs;
+        this->progress = true;
+        break;
+      }
+   }
+
+   return visit_continue;
+}
+
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_call *ir)
+{
+   /* Do copy propagation on call parameters, but skip any out params */
+   exec_list_iterator sig_param_iter = ir->get_callee()->parameters.iterator();
+   foreach_iter(exec_list_iterator, iter, ir->actual_parameters) {
+      ir_variable *sig_param = (ir_variable *)sig_param_iter.get();
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      if (sig_param->mode != ir_var_out && sig_param->mode != ir_var_inout) {
+         ir->accept(this);
+      }
+      sig_param_iter.next();
+   }
+
+   /* Since we're unlinked, we don't (necssarily) know the side effects of
+    * this call.  So kill all copies.
+    */
+   acp->make_empty();
+   this->killed_all = true;
+
+   return visit_continue_with_parent;
+}
+
+void
+ir_copy_propagation_visitor::handle_if_block(exec_list *instructions)
+{
+   exec_list *orig_acp = this->acp;
+   exec_list *orig_kills = this->kills;
+   bool orig_killed_all = this->killed_all;
+
+   this->acp = new(mem_ctx) exec_list;
+   this->kills = new(mem_ctx) exec_list;
+   this->killed_all = false;
+
+   /* Populate the initial acp with a copy of the original */
+   foreach_iter(exec_list_iterator, iter, *orig_acp) {
+      acp_entry *a = (acp_entry *)iter.get();
+      this->acp->push_tail(new(this->mem_ctx) acp_entry(a->lhs, a->rhs));
+   }
+
+   visit_list_elements(this, instructions);
+
+   if (this->killed_all) {
+      orig_acp->make_empty();
+   }
+
+   exec_list *new_kills = this->kills;
+   this->kills = orig_kills;
+   this->acp = orig_acp;
+   this->killed_all = this->killed_all || orig_killed_all;
+
+   foreach_iter(exec_list_iterator, iter, *new_kills) {
+      kill_entry *k = (kill_entry *)iter.get();
+      kill(k->var);
+   }
+}
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_if *ir)
+{
+   ir->condition->accept(this);
+
+   handle_if_block(&ir->then_instructions);
+   handle_if_block(&ir->else_instructions);
+
+   /* handle_if_block() already descended into the children. */
+   return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_loop *ir)
+{
+   exec_list *orig_acp = this->acp;
+   exec_list *orig_kills = this->kills;
+   bool orig_killed_all = this->killed_all;
+
+   /* FINISHME: For now, the initial acp for loops is totally empty.
+    * We could go through once, then go through again with the acp
+    * cloned minus the killed entries after the first run through.
+    */
+   this->acp = new(mem_ctx) exec_list;
+   this->kills = new(mem_ctx) exec_list;
+   this->killed_all = false;
+
+   visit_list_elements(this, &ir->body_instructions);
+
+   if (this->killed_all) {
+      orig_acp->make_empty();
+   }
+
+   exec_list *new_kills = this->kills;
+   this->kills = orig_kills;
+   this->acp = orig_acp;
+   this->killed_all = this->killed_all || orig_killed_all;
+
+   foreach_iter(exec_list_iterator, iter, *new_kills) {
+      kill_entry *k = (kill_entry *)iter.get();
+      kill(k->var);
+   }
+
+   /* already descended into the children. */
+   return visit_continue_with_parent;
+}
+
+void
+ir_copy_propagation_visitor::kill(ir_variable *var)
+{
+   assert(var != NULL);
+
+   /* Remove any entries currently in the ACP for this kill. */
+   foreach_iter(exec_list_iterator, iter, *acp) {
+      acp_entry *entry = (acp_entry *)iter.get();
+
+      if (entry->lhs == var || entry->rhs == var) {
+        entry->remove();
+      }
+   }
+
+   /* Add the LHS variable to the list of killed variables in this block.
+    */
+   this->kills->push_tail(new(this->mem_ctx) kill_entry(var));
+}
+
+/**
+ * Adds an entry to the available copy list if it's a plain assignment
+ * of a variable to a variable.
+ */
+void
+ir_copy_propagation_visitor::add_copy(ir_assignment *ir)
+{
+   acp_entry *entry;
+
+   if (ir->condition) {
+      ir_constant *condition = ir->condition->as_constant();
+      if (!condition || !condition->value.b[0])
+        return;
+   }
+
+   ir_variable *lhs_var = ir->whole_variable_written();
+   ir_variable *rhs_var = ir->rhs->whole_variable_referenced();
+
+   if ((lhs_var != NULL) && (rhs_var != NULL)) {
+      if (lhs_var == rhs_var) {
+        /* This is a dumb assignment, but we've conveniently noticed
+         * it here.  Removing it now would mess up the loop iteration
+         * calling us.  Just flag it to not execute, and someone else
+         * will clean up the mess.
+         */
+        ir->condition = new(talloc_parent(ir)) ir_constant(false);
+        this->progress = true;
+      } else {
+        entry = new(this->mem_ctx) acp_entry(lhs_var, rhs_var);
+        this->acp->push_tail(entry);
+      }
+   }
+}
+
+/**
+ * Does a copy propagation pass on the code present in the instruction stream.
+ */
+bool
+do_copy_propagation(exec_list *instructions)
+{
+   ir_copy_propagation_visitor v;
+
+   visit_list_elements(&v, instructions);
+
+   return v.progress;
+}
diff --git a/src/glsl/ir_dead_code.cpp b/src/glsl/ir_dead_code.cpp
new file mode 100644 (file)
index 0000000..5cf5e99
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_dead_code.cpp
+ *
+ * Eliminates dead assignments and variable declarations from the code.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_variable_refcount.h"
+#include "glsl_types.h"
+
+static bool debug = false;
+
+/**
+ * Do a dead code pass over instructions and everything that instructions
+ * references.
+ *
+ * Note that this will remove assignments to globals, so it is not suitable
+ * for usage on an unlinked instruction stream.
+ */
+bool
+do_dead_code(exec_list *instructions)
+{
+   ir_variable_refcount_visitor v;
+   bool progress = false;
+
+   v.run(instructions);
+
+   foreach_iter(exec_list_iterator, iter, v.variable_list) {
+      variable_entry *entry = (variable_entry *)iter.get();
+
+      /* Since each assignment is a reference, the refereneced count must be
+       * greater than or equal to the assignment count.  If they are equal,
+       * then all of the references are assignments, and the variable is
+       * dead.
+       *
+       * Note that if the variable is neither assigned nor referenced, both
+       * counts will be zero and will be caught by the equality test.
+       */
+      assert(entry->referenced_count >= entry->assigned_count);
+
+      if (debug) {
+        printf("%s@%p: %d refs, %d assigns, %sdeclared in our scope\n",
+               entry->var->name, (void *) entry->var,
+               entry->referenced_count, entry->assigned_count,
+               entry->declaration ? "" : "not ");
+      }
+
+      if ((entry->referenced_count > entry->assigned_count)
+         || !entry->declaration)
+        continue;
+
+      if (entry->assign) {
+        /* Remove a single dead assignment to the variable we found.
+         * Don't do so if it's a shader output, though.
+         */
+        if (entry->var->mode != ir_var_out &&
+            entry->var->mode != ir_var_inout &&
+            !ir_has_call(entry->assign)) {
+           entry->assign->remove();
+           progress = true;
+
+           if (debug) {
+              printf("Removed assignment to %s@%p\n",
+                     entry->var->name, (void *) entry->var);
+           }
+        }
+      } else {
+        /* If there are no assignments or references to the variable left,
+         * then we can remove its declaration.
+         */
+
+        /* uniform initializers are precious, and could get used by another
+         * stage.
+         */
+        if (entry->var->mode == ir_var_uniform &&
+            entry->var->constant_value)
+           continue;
+
+        entry->var->remove();
+        progress = true;
+
+        if (debug) {
+           printf("Removed declaration of %s@%p\n",
+                  entry->var->name, (void *) entry->var);
+        }
+      }
+   }
+
+   return progress;
+}
+
+/**
+ * Does a dead code pass on the functions present in the instruction stream.
+ *
+ * This is suitable for use while the program is not linked, as it will
+ * ignore variable declarations (and the assignments to them) for variables
+ * with global scope.
+ */
+bool
+do_dead_code_unlinked(exec_list *instructions)
+{
+   bool progress = false;
+
+   foreach_iter(exec_list_iterator, iter, *instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      ir_function *f = ir->as_function();
+      if (f) {
+        foreach_iter(exec_list_iterator, sigiter, *f) {
+           ir_function_signature *sig =
+              (ir_function_signature *) sigiter.get();
+           if (do_dead_code(&sig->body))
+              progress = true;
+        }
+      }
+   }
+
+   return progress;
+}
diff --git a/src/glsl/ir_dead_code_local.cpp b/src/glsl/ir_dead_code_local.cpp
new file mode 100644 (file)
index 0000000..4bbedf0
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_dead_code_local.cpp
+ *
+ * Eliminates local dead assignments from the code.
+ *
+ * This operates on basic blocks, tracking assignments and finding if
+ * they're used before the variable is completely reassigned.
+ *
+ * Compare this to ir_dead_code.cpp, which operates globally looking
+ * for assignments to variables that are never read.
+ */
+
+#include "ir.h"
+#include "ir_basic_block.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+static bool debug = false;
+
+class assignment_entry : public exec_node
+{
+public:
+   assignment_entry(ir_variable *lhs, ir_instruction *ir)
+   {
+      assert(lhs);
+      assert(ir);
+      this->lhs = lhs;
+      this->ir = ir;
+   }
+
+   ir_variable *lhs;
+   ir_instruction *ir;
+};
+
+class kill_for_derefs_visitor : public ir_hierarchical_visitor {
+public:
+   kill_for_derefs_visitor(exec_list *assignments)
+   {
+      this->assignments = assignments;
+   }
+
+   virtual ir_visitor_status visit(ir_dereference_variable *ir)
+   {
+      ir_variable *const var = ir->variable_referenced();
+
+      foreach_iter(exec_list_iterator, iter, *this->assignments) {
+        assignment_entry *entry = (assignment_entry *)iter.get();
+
+        if (entry->lhs == var) {
+           if (debug)
+              printf("kill %s\n", entry->lhs->name);
+           entry->remove();
+        }
+      }
+
+      return visit_continue;
+   }
+
+private:
+   exec_list *assignments;
+};
+
+class array_index_visit : public ir_hierarchical_visitor {
+public:
+   array_index_visit(ir_hierarchical_visitor *v)
+   {
+      this->visitor = v;
+   }
+
+   virtual ir_visitor_status visit_enter(class ir_dereference_array *ir)
+   {
+      ir->array_index->accept(visitor);
+      return visit_continue;
+   }
+
+   static void run(ir_instruction *ir, ir_hierarchical_visitor *v)
+   {
+      array_index_visit top_visit(v);
+      ir->accept(& top_visit);
+   }
+
+   ir_hierarchical_visitor *visitor;
+};
+
+
+/**
+ * Adds an entry to the available copy list if it's a plain assignment
+ * of a variable to a variable.
+ */
+static bool
+process_assignment(void *ctx, ir_assignment *ir, exec_list *assignments)
+{
+   ir_variable *var = NULL;
+   bool progress = false;
+   kill_for_derefs_visitor v(assignments);
+
+   /* Kill assignment entries for things used to produce this assignment. */
+   ir->rhs->accept(&v);
+   if (ir->condition) {
+      ir->condition->accept(&v);
+   }
+
+   /* Kill assignment enties used as array indices.
+    */
+   array_index_visit::run(ir->lhs, &v);
+   var = ir->lhs->variable_referenced();
+   assert(var);
+
+   bool always_assign = true;
+   if (ir->condition) {
+      ir_constant *condition = ir->condition->as_constant();
+      if (!condition || !condition->value.b[0])
+        always_assign = false;
+   }
+
+   /* Now, check if we did a whole-variable assignment. */
+   if (always_assign && (ir->whole_variable_written() != NULL)) {
+      /* We did a whole-variable assignment.  So, any instruction in
+       * the assignment list with the same LHS is dead.
+       */
+      if (debug)
+        printf("looking for %s to remove\n", var->name);
+      foreach_iter(exec_list_iterator, iter, *assignments) {
+        assignment_entry *entry = (assignment_entry *)iter.get();
+
+        if (entry->lhs == var) {
+           if (debug)
+              printf("removing %s\n", var->name);
+           entry->ir->remove();
+           entry->remove();
+           progress = true;
+        }
+      }
+   }
+
+   /* Add this instruction to the assignment list available to be removed.
+    * But not if the assignment has other side effects.
+    */
+   if (ir_has_call(ir))
+      return progress;
+
+   assignment_entry *entry = new(ctx) assignment_entry(var, ir);
+   assignments->push_tail(entry);
+
+   if (debug) {
+      printf("add %s\n", var->name);
+
+      printf("current entries\n");
+      foreach_iter(exec_list_iterator, iter, *assignments) {
+        assignment_entry *entry = (assignment_entry *)iter.get();
+
+        printf("    %s\n", entry->lhs->name);
+      }
+   }
+
+   return progress;
+}
+
+static void
+dead_code_local_basic_block(ir_instruction *first,
+                            ir_instruction *last,
+                            void *data)
+{
+   ir_instruction *ir, *ir_next;
+   /* List of avaialble_copy */
+   exec_list assignments;
+   bool *out_progress = (bool *)data;
+   bool progress = false;
+
+   void *ctx = talloc_new(NULL);
+   /* Safe looping, since process_assignment */
+   for (ir = first, ir_next = (ir_instruction *)first->next;;
+       ir = ir_next, ir_next = (ir_instruction *)ir->next) {
+      ir_assignment *ir_assign = ir->as_assignment();
+
+      if (debug) {
+        ir->print();
+        printf("\n");
+      }
+
+      if (ir_assign) {
+        progress = process_assignment(ctx, ir_assign, &assignments) || progress;
+      } else {
+        kill_for_derefs_visitor kill(&assignments);
+        ir->accept(&kill);
+      }
+
+      if (ir == last)
+        break;
+   }
+   *out_progress = progress;
+   talloc_free(ctx);
+}
+
+/**
+ * Does a copy propagation pass on the code present in the instruction stream.
+ */
+bool
+do_dead_code_local(exec_list *instructions)
+{
+   bool progress = false;
+
+   call_for_basic_blocks(instructions, dead_code_local_basic_block, &progress);
+
+   return progress;
+}
diff --git a/src/glsl/ir_dead_functions.cpp b/src/glsl/ir_dead_functions.cpp
new file mode 100644 (file)
index 0000000..2655444
--- /dev/null
@@ -0,0 +1,151 @@
+ /*
+  * Copyright Â© 2010 Intel Corporation
+  *
+  * 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.
+  */
+
+ /**
+  * \file ir_dead_functions.cpp
+  *
+  * Eliminates unused functions from the linked program.
+  */
+
+ #include "ir.h"
+ #include "ir_visitor.h"
+ #include "ir_expression_flattening.h"
+ #include "glsl_types.h"
+
+ class signature_entry : public exec_node
+ {
+ public:
+    signature_entry(ir_function_signature *sig)
+    {
+       this->signature = sig;
+       this->used = false;
+    }
+
+    ir_function_signature *signature;
+    bool used;
+ };
+
+ class ir_dead_functions_visitor : public ir_hierarchical_visitor {
+ public:
+    ir_dead_functions_visitor()
+    {
+       this->mem_ctx = talloc_new(NULL);
+    }
+
+    ~ir_dead_functions_visitor()
+    {
+       talloc_free(this->mem_ctx);
+    }
+
+    virtual ir_visitor_status visit_enter(ir_function_signature *);
+    virtual ir_visitor_status visit_enter(ir_call *);
+
+    signature_entry *get_signature_entry(ir_function_signature *var);
+
+    bool (*predicate)(ir_instruction *ir);
+
+    /* List of signature_entry */
+    exec_list signature_list;
+    void *mem_ctx;
+ };
+
+
+ signature_entry *
+ ir_dead_functions_visitor::get_signature_entry(ir_function_signature *sig)
+ {
+    foreach_iter(exec_list_iterator, iter, this->signature_list) {
+       signature_entry *entry = (signature_entry *)iter.get();
+       if (entry->signature == sig)
+         return entry;
+    }
+
+    signature_entry *entry = new(mem_ctx) signature_entry(sig);
+    this->signature_list.push_tail(entry);
+    return entry;
+ }
+
+
+ ir_visitor_status
+ ir_dead_functions_visitor::visit_enter(ir_function_signature *ir)
+ {
+    signature_entry *entry = this->get_signature_entry(ir);
+
+    if (strcmp(ir->function_name(), "main") == 0) {
+       entry->used = true;
+    }
+
+    return visit_continue;
+ }
+
+
+ ir_visitor_status
+ ir_dead_functions_visitor::visit_enter(ir_call *ir)
+ {
+    signature_entry *entry = this->get_signature_entry(ir->get_callee());
+
+    entry->used = true;
+
+   return visit_continue;
+}
+
+bool
+do_dead_functions(exec_list *instructions)
+{
+   ir_dead_functions_visitor v;
+   bool progress = false;
+
+   visit_list_elements(&v, instructions);
+
+   /* Now that we've figured out which function signatures are used, remove
+    * the unused ones, and remove function definitions that have no more
+    * signatures.
+    */
+    foreach_iter(exec_list_iterator, iter, v.signature_list) {
+      signature_entry *entry = (signature_entry *)iter.get();
+
+      if (!entry->used) {
+        entry->signature->remove();
+        progress = true;
+      }
+      delete(entry);
+   }
+
+   /* We don't just do this above when we nuked a signature because of
+    * const pointers.
+    */
+   foreach_iter(exec_list_iterator, iter, *instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      ir_function *func = ir->as_function();
+
+      if (func && func->signatures.is_empty()) {
+        /* At this point (post-linking), the symbol table is no
+         * longer in use, so not removing the function from the
+         * symbol table should be OK.
+         */
+        func->remove();
+        progress = true;
+      }
+   }
+
+   return progress;
+}
diff --git a/src/glsl/ir_div_to_mul_rcp.cpp b/src/glsl/ir_div_to_mul_rcp.cpp
new file mode 100644 (file)
index 0000000..640d5d6
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_div_to_mul_rcp.cpp
+ *
+ * Breaks an ir_unop_div expression down to op0 * (rcp(op1)).
+ *
+ * Many GPUs don't have a divide instruction (945 and 965 included),
+ * but they do have an RCP instruction to compute an approximate
+ * reciprocal.  By breaking the operation down, constant reciprocals
+ * can get constant folded.
+ */
+
+#include "ir.h"
+#include "glsl_types.h"
+
+class ir_div_to_mul_rcp_visitor : public ir_hierarchical_visitor {
+public:
+   ir_div_to_mul_rcp_visitor()
+   {
+      this->made_progress = false;
+   }
+
+   ir_visitor_status visit_leave(ir_expression *);
+
+   bool made_progress;
+};
+
+bool
+do_div_to_mul_rcp(exec_list *instructions)
+{
+   ir_div_to_mul_rcp_visitor v;
+
+   visit_list_elements(&v, instructions);
+   return v.made_progress;
+}
+
+ir_visitor_status
+ir_div_to_mul_rcp_visitor::visit_leave(ir_expression *ir)
+{
+   if (ir->operation != ir_binop_div)
+      return visit_continue;
+
+   if (ir->operands[1]->type->base_type != GLSL_TYPE_INT &&
+       ir->operands[1]->type->base_type != GLSL_TYPE_UINT) {
+      /* New expression for the 1.0 / op1 */
+      ir_rvalue *expr;
+      expr = new(ir) ir_expression(ir_unop_rcp,
+                                  ir->operands[1]->type,
+                                  ir->operands[1],
+                                  NULL);
+
+      /* op0 / op1 -> op0 * (1.0 / op1) */
+      ir->operation = ir_binop_mul;
+      ir->operands[1] = expr;
+   } else {
+      /* Be careful with integer division -- we need to do it as a
+       * float and re-truncate, since rcp(n > 1) of an integer would
+       * just be 0.
+       */
+      ir_rvalue *op0, *op1;
+      const struct glsl_type *vec_type;
+
+      vec_type = glsl_type::get_instance(GLSL_TYPE_FLOAT,
+                                        ir->operands[1]->type->vector_elements,
+                                        ir->operands[1]->type->matrix_columns);
+
+      if (ir->operands[1]->type->base_type == GLSL_TYPE_INT)
+        op1 = new(ir) ir_expression(ir_unop_i2f, vec_type, ir->operands[1], NULL);
+      else
+        op1 = new(ir) ir_expression(ir_unop_u2f, vec_type, ir->operands[1], NULL);
+
+      op1 = new(ir) ir_expression(ir_unop_rcp, op1->type, op1, NULL);
+
+      vec_type = glsl_type::get_instance(GLSL_TYPE_FLOAT,
+                                        ir->operands[0]->type->vector_elements,
+                                        ir->operands[0]->type->matrix_columns);
+
+      if (ir->operands[0]->type->base_type == GLSL_TYPE_INT)
+        op0 = new(ir) ir_expression(ir_unop_i2f, vec_type, ir->operands[0], NULL);
+      else
+        op0 = new(ir) ir_expression(ir_unop_u2f, vec_type, ir->operands[0], NULL);
+
+      op0 = new(ir) ir_expression(ir_binop_mul, vec_type, op0, op1);
+
+      ir->operation = ir_unop_f2i;
+      ir->operands[0] = op0;
+      ir->operands[1] = NULL;
+   }
+
+   this->made_progress = true;
+
+   return visit_continue;
+}
diff --git a/src/glsl/ir_explog_to_explog2.cpp b/src/glsl/ir_explog_to_explog2.cpp
new file mode 100644 (file)
index 0000000..78694a2
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_explog_to_explog2.cpp
+ *
+ * Many GPUs don't have a base e log or exponent instruction, but they
+ * do have base 2 versions, so this pass converts exp and log to exp2
+ * and log2 operations.
+ */
+
+#include "main/core.h" /* for log2f on MSVC */
+#include "ir.h"
+#include "glsl_types.h"
+
+class ir_explog_to_explog2_visitor : public ir_hierarchical_visitor {
+public:
+   ir_explog_to_explog2_visitor()
+   {
+      this->progress = false;
+   }
+
+   ir_visitor_status visit_leave(ir_expression *);
+
+   bool progress;
+};
+
+bool
+do_explog_to_explog2(exec_list *instructions)
+{
+   ir_explog_to_explog2_visitor v;
+
+   visit_list_elements(&v, instructions);
+   return v.progress;
+}
+
+ir_visitor_status
+ir_explog_to_explog2_visitor::visit_leave(ir_expression *ir)
+{
+   if (ir->operation == ir_unop_exp) {
+      void *mem_ctx = talloc_parent(ir);
+      ir_constant *log2_e = new(mem_ctx) ir_constant(log2f(M_E));
+
+      ir->operation = ir_unop_exp2;
+      ir->operands[0] = new(mem_ctx) ir_expression(ir_binop_mul,
+                                                  ir->operands[0]->type,
+                                                  ir->operands[0],
+                                                  log2_e);
+      this->progress = true;
+   }
+
+   if (ir->operation == ir_unop_log) {
+      void *mem_ctx = talloc_parent(ir);
+
+      ir->operation = ir_binop_mul;
+      ir->operands[0] = new(mem_ctx) ir_expression(ir_unop_log2,
+                                                  ir->operands[0]->type,
+                                                  ir->operands[0],
+                                                  NULL);
+      ir->operands[1] = new(mem_ctx) ir_constant(1.0f / log2f(M_E));
+      this->progress = true;
+   }
+
+   return visit_continue;
+}
diff --git a/src/glsl/ir_expression_flattening.cpp b/src/glsl/ir_expression_flattening.cpp
new file mode 100644 (file)
index 0000000..7b1b8db
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_expression_flattening.cpp
+ *
+ * Takes the leaves of expression trees and makes them dereferences of
+ * assignments of the leaves to temporaries, according to a predicate.
+ *
+ * This is used for automatic function inlining, where we want to take
+ * an expression containing a call and move the call out to its own
+ * assignment so that we can inline it at the appropriate place in the
+ * instruction stream.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_rvalue_visitor.h"
+#include "ir_expression_flattening.h"
+#include "glsl_types.h"
+
+class ir_expression_flattening_visitor : public ir_rvalue_visitor {
+public:
+   ir_expression_flattening_visitor(bool (*predicate)(ir_instruction *ir))
+   {
+      this->predicate = predicate;
+   }
+
+   virtual ~ir_expression_flattening_visitor()
+   {
+      /* empty */
+   }
+
+   void handle_rvalue(ir_rvalue **rvalue);
+   bool (*predicate)(ir_instruction *ir);
+};
+
+void
+do_expression_flattening(exec_list *instructions,
+                        bool (*predicate)(ir_instruction *ir))
+{
+   ir_expression_flattening_visitor v(predicate);
+
+   foreach_iter(exec_list_iterator, iter, *instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+
+      ir->accept(&v);
+   }
+}
+
+void
+ir_expression_flattening_visitor::handle_rvalue(ir_rvalue **rvalue)
+{
+   ir_variable *var;
+   ir_assignment *assign;
+   ir_rvalue *ir = *rvalue;
+
+   if (!ir || !this->predicate(ir))
+      return;
+
+   void *ctx = talloc_parent(ir);
+
+   var = new(ctx) ir_variable(ir->type, "flattening_tmp", ir_var_temporary);
+   base_ir->insert_before(var);
+
+   assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
+                                  ir,
+                                  NULL);
+   base_ir->insert_before(assign);
+
+   *rvalue = new(ctx) ir_dereference_variable(var);
+}
diff --git a/src/glsl/ir_expression_flattening.h b/src/glsl/ir_expression_flattening.h
new file mode 100644 (file)
index 0000000..2eda159
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+
+/**
+ * \file ir_expression_flattening.h
+ *
+ * Takes the leaves of expression trees and makes them dereferences of
+ * assignments of the leaves to temporaries, according to a predicate.
+ *
+ * This is used for automatic function inlining, where we want to take
+ * an expression containing a call and move the call out to its own
+ * assignment so that we can inline it at the appropriate place in the
+ * instruction stream.
+ */
+
+void do_expression_flattening(exec_list *instructions,
+                             bool (*predicate)(ir_instruction *ir));
diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp
new file mode 100644 (file)
index 0000000..dfdec14
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 "glsl_types.h"
+#include "ir.h"
+
+int
+type_compare(const glsl_type *a, const glsl_type *b)
+{
+   /* If the types are the same, they trivially match.
+    */
+   if (a == b)
+      return 0;
+
+   switch (a->base_type) {
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_BOOL:
+      /* There is no implicit conversion to or from integer types or bool.
+       */
+      if ((a->is_integer() != b->is_integer())
+         || (a->is_boolean() != b->is_boolean()))
+        return -1;
+
+      /* FALLTHROUGH */
+
+   case GLSL_TYPE_FLOAT:
+      if ((a->vector_elements != b->vector_elements)
+         || (a->matrix_columns != b->matrix_columns))
+        return -1;
+
+      return 1;
+
+   case GLSL_TYPE_SAMPLER:
+   case GLSL_TYPE_STRUCT:
+      /* Samplers and structures must match exactly.
+       */
+      return -1;
+
+   case GLSL_TYPE_ARRAY:
+      if ((b->base_type != GLSL_TYPE_ARRAY)
+         || (a->length != b->length))
+        return -1;
+
+      /* From GLSL 1.50 spec, page 27 (page 33 of the PDF):
+       *    "There are no implicit array or structure conversions."
+       *
+       * If the comparison of the array element types detects that a conversion
+       * would be required, the array types do not match.
+       */
+      return (type_compare(a->fields.array, b->fields.array) == 0) ? 0 : -1;
+
+   case GLSL_TYPE_FUNCTION:
+   case GLSL_TYPE_VOID:
+   case GLSL_TYPE_ERROR:
+   default:
+      /* These are all error conditions.  It is invalid for a parameter to
+       * a function to be declared as error, void, or a function.
+       */
+      return -1;
+   }
+
+   /* This point should be unreachable.
+    */
+   assert(0);
+}
+
+
+static int
+parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
+{
+   const exec_node *node_a = list_a->head;
+   const exec_node *node_b = list_b->head;
+   int total_score = 0;
+
+   for (/* empty */
+       ; !node_a->is_tail_sentinel()
+       ; node_a = node_a->next, node_b = node_b->next) {
+      /* If all of the parameters from the other parameter list have been
+       * exhausted, the lists have different length and, by definition,
+       * do not match.
+       */
+      if (node_b->is_tail_sentinel())
+        return -1;
+
+
+      const ir_variable *const param = (ir_variable *) node_a;
+      const ir_instruction *const actual = (ir_instruction *) node_b;
+
+      /* Determine whether or not the types match.  If the types are an
+       * exact match, the match score is zero.  If the types don't match
+       * but the actual parameter can be coerced to the type of the declared
+       * parameter, the match score is one.
+       */
+      int score;
+      switch ((enum ir_variable_mode)(param->mode)) {
+      case ir_var_auto:
+      case ir_var_uniform:
+      case ir_var_temporary:
+        /* These are all error conditions.  It is invalid for a parameter to
+         * a function to be declared as auto (not in, out, or inout) or
+         * as uniform.
+         */
+        assert(0);
+        return -1;
+
+      case ir_var_in:
+        score = type_compare(param->type, actual->type);
+        break;
+
+      case ir_var_out:
+        score = type_compare(actual->type, param->type);
+        break;
+
+      case ir_var_inout:
+        /* Since there are no bi-directional automatic conversions (e.g.,
+         * there is int -> float but no float -> int), inout parameters must
+         * be exact matches.
+         */
+        score = (type_compare(actual->type, param->type) == 0) ? 0 : -1;
+        break;
+
+      default:
+        assert(false);
+      }
+
+      if (score < 0)
+        return -1;
+
+      total_score += score;
+   }
+
+   /* If all of the parameters from the other parameter list have been
+    * exhausted, the lists have different length and, by definition, do not
+    * match.
+    */
+   if (!node_b->is_tail_sentinel())
+      return -1;
+
+   return total_score;
+}
+
+
+ir_function_signature *
+ir_function::matching_signature(const exec_list *actual_parameters)
+{
+   ir_function_signature *match = NULL;
+
+   foreach_iter(exec_list_iterator, iter, signatures) {
+      ir_function_signature *const sig =
+        (ir_function_signature *) iter.get();
+
+      const int score = parameter_lists_match(& sig->parameters,
+                                             actual_parameters);
+
+      if (score == 0)
+        return sig;
+
+      if (score > 0) {
+        if (match != NULL)
+           return NULL;
+
+        match = sig;
+      }
+   }
+
+   return match;
+}
+
+
+static bool
+parameter_lists_match_exact(const exec_list *list_a, const exec_list *list_b)
+{
+   const exec_node *node_a = list_a->head;
+   const exec_node *node_b = list_b->head;
+
+   for (/* empty */
+       ; !node_a->is_tail_sentinel() && !node_b->is_tail_sentinel()
+       ; node_a = node_a->next, node_b = node_b->next) {
+      ir_variable *a = (ir_variable *) node_a;
+      ir_variable *b = (ir_variable *) node_b;
+
+      /* If the types of the parameters do not match, the parameters lists
+       * are different.
+       */
+      if (a->type != b->type)
+         return false;
+   }
+
+   /* Unless both lists are exhausted, they differ in length and, by
+    * definition, do not match.
+    */
+   return (node_a->is_tail_sentinel() == node_b->is_tail_sentinel());
+}
+
+ir_function_signature *
+ir_function::exact_matching_signature(const exec_list *actual_parameters)
+{
+   foreach_iter(exec_list_iterator, iter, signatures) {
+      ir_function_signature *const sig =
+        (ir_function_signature *) iter.get();
+
+      if (parameter_lists_match_exact(&sig->parameters, actual_parameters))
+        return sig;
+   }
+   return NULL;
+}
diff --git a/src/glsl/ir_function_can_inline.cpp b/src/glsl/ir_function_can_inline.cpp
new file mode 100644 (file)
index 0000000..8bb8e0d
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_function_can_inline.cpp
+ *
+ * Determines if we can inline a function call using ir_function_inlining.cpp.
+ *
+ * The primary restriction is that we can't return from the function
+ * other than as the last instruction.  We could potentially work
+ * around this for some constructs by flattening control flow and
+ * moving the return to the end, or by using breaks from a do {} while
+ * (0) loop surrounding the function body.
+ */
+
+#include "ir.h"
+
+class ir_function_can_inline_visitor : public ir_hierarchical_visitor {
+public:
+   ir_function_can_inline_visitor()
+   {
+      this->num_returns = 0;
+   }
+
+   virtual ir_visitor_status visit_enter(ir_return *);
+
+   int num_returns;
+};
+
+ir_visitor_status
+ir_function_can_inline_visitor::visit_enter(ir_return *ir)
+{
+   (void) ir;
+   this->num_returns++;
+   return visit_continue;
+}
+
+bool
+can_inline(ir_call *call)
+{
+   ir_function_can_inline_visitor v;
+   const ir_function_signature *callee = call->get_callee();
+
+   v.run((exec_list *) &callee->body);
+
+   ir_instruction *last = (ir_instruction *)callee->body.get_tail();
+   if (last && !last->as_return())
+      v.num_returns++;
+
+   return v.num_returns == 1;
+}
diff --git a/src/glsl/ir_function_inlining.cpp b/src/glsl/ir_function_inlining.cpp
new file mode 100644 (file)
index 0000000..874602c
--- /dev/null
@@ -0,0 +1,417 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_function_inlining.cpp
+ *
+ * Replaces calls to functions with the body of the function.
+ */
+
+#include <inttypes.h>
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_function_inlining.h"
+#include "ir_expression_flattening.h"
+#include "glsl_types.h"
+#include "program/hash_table.h"
+
+static void
+do_sampler_replacement(exec_list *instructions,
+                      ir_variable *sampler,
+                      ir_dereference *deref);
+
+class ir_function_inlining_visitor : public ir_hierarchical_visitor {
+public:
+   ir_function_inlining_visitor()
+   {
+      progress = false;
+   }
+
+   virtual ~ir_function_inlining_visitor()
+   {
+      /* empty */
+   }
+
+   virtual ir_visitor_status visit_enter(ir_expression *);
+   virtual ir_visitor_status visit_enter(ir_call *);
+   virtual ir_visitor_status visit_enter(ir_assignment *);
+   virtual ir_visitor_status visit_enter(ir_return *);
+   virtual ir_visitor_status visit_enter(ir_texture *);
+   virtual ir_visitor_status visit_enter(ir_swizzle *);
+
+   bool progress;
+};
+
+
+bool
+automatic_inlining_predicate(ir_instruction *ir)
+{
+   ir_call *call = ir->as_call();
+
+   if (call && can_inline(call))
+      return true;
+
+   return false;
+}
+
+bool
+do_function_inlining(exec_list *instructions)
+{
+   ir_function_inlining_visitor v;
+
+   do_expression_flattening(instructions, automatic_inlining_predicate);
+
+   v.run(instructions);
+
+   return v.progress;
+}
+
+static void
+replace_return_with_assignment(ir_instruction *ir, void *data)
+{
+   void *ctx = talloc_parent(ir);
+   ir_variable *retval = (ir_variable *)data;
+   ir_return *ret = ir->as_return();
+
+   if (ret) {
+      if (ret->value) {
+        ir_rvalue *lhs = new(ctx) ir_dereference_variable(retval);
+        ret->replace_with(new(ctx) ir_assignment(lhs, ret->value, NULL));
+      } else {
+        /* un-valued return has to be the last return, or we shouldn't
+         * have reached here. (see can_inline()).
+         */
+        assert(ret->next->is_tail_sentinel());
+        ret->remove();
+      }
+   }
+}
+
+ir_rvalue *
+ir_call::generate_inline(ir_instruction *next_ir)
+{
+   void *ctx = talloc_parent(this);
+   ir_variable **parameters;
+   int num_parameters;
+   int i;
+   ir_variable *retval = NULL;
+   struct hash_table *ht;
+
+   ht = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare);
+
+   num_parameters = 0;
+   foreach_iter(exec_list_iterator, iter_sig, this->callee->parameters)
+      num_parameters++;
+
+   parameters = new ir_variable *[num_parameters];
+
+   /* Generate storage for the return value. */
+   if (this->callee->return_type) {
+      retval = new(ctx) ir_variable(this->callee->return_type, "_ret_val",
+                                   ir_var_auto);
+      next_ir->insert_before(retval);
+   }
+
+   /* Generate the declarations for the parameters to our inlined code,
+    * and set up the mapping of real function body variables to ours.
+    */
+   i = 0;
+   exec_list_iterator sig_param_iter = this->callee->parameters.iterator();
+   exec_list_iterator param_iter = this->actual_parameters.iterator();
+   for (i = 0; i < num_parameters; i++) {
+      ir_variable *sig_param = (ir_variable *) sig_param_iter.get();
+      ir_rvalue *param = (ir_rvalue *) param_iter.get();
+
+      /* Generate a new variable for the parameter. */
+      if (sig_param->type->base_type == GLSL_TYPE_SAMPLER) {
+        /* For samplers, we want the inlined sampler references
+         * referencing the passed in sampler variable, since that
+         * will have the location information, which an assignment of
+         * a sampler wouldn't.  Fix it up below.
+         */
+        parameters[i] = NULL;
+      } else {
+        parameters[i] = sig_param->clone(ctx, ht);
+        parameters[i]->mode = ir_var_auto;
+        next_ir->insert_before(parameters[i]);
+      }
+
+      /* Move the actual param into our param variable if it's an 'in' type. */
+      if (parameters[i] && (sig_param->mode == ir_var_in ||
+                           sig_param->mode == ir_var_inout)) {
+        ir_assignment *assign;
+
+        assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(parameters[i]),
+                                        param, NULL);
+        next_ir->insert_before(assign);
+      }
+
+      sig_param_iter.next();
+      param_iter.next();
+   }
+
+   exec_list new_instructions;
+
+   /* Generate the inlined body of the function to a new list */
+   foreach_iter(exec_list_iterator, iter, callee->body) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      ir_instruction *new_ir = ir->clone(ctx, ht);
+
+      new_instructions.push_tail(new_ir);
+      visit_tree(new_ir, replace_return_with_assignment, retval);
+   }
+
+   /* If any samplers were passed in, replace any deref of the sampler
+    * with a deref of the sampler argument.
+    */
+   param_iter = this->actual_parameters.iterator();
+   sig_param_iter = this->callee->parameters.iterator();
+   for (i = 0; i < num_parameters; i++) {
+      ir_instruction *const param = (ir_instruction *) param_iter.get();
+      ir_variable *sig_param = (ir_variable *) sig_param_iter.get();
+
+      if (sig_param->type->base_type == GLSL_TYPE_SAMPLER) {
+        ir_dereference *deref = param->as_dereference();
+
+        assert(deref);
+        do_sampler_replacement(&new_instructions, sig_param, deref);
+      }
+      param_iter.next();
+      sig_param_iter.next();
+   }
+
+   /* Now push those new instructions in. */
+   foreach_iter(exec_list_iterator, iter, new_instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      next_ir->insert_before(ir);
+   }
+
+   /* Copy back the value of any 'out' parameters from the function body
+    * variables to our own.
+    */
+   i = 0;
+   param_iter = this->actual_parameters.iterator();
+   sig_param_iter = this->callee->parameters.iterator();
+   for (i = 0; i < num_parameters; i++) {
+      ir_instruction *const param = (ir_instruction *) param_iter.get();
+      const ir_variable *const sig_param = (ir_variable *) sig_param_iter.get();
+
+      /* Move our param variable into the actual param if it's an 'out' type. */
+      if (parameters[i] && (sig_param->mode == ir_var_out ||
+                           sig_param->mode == ir_var_inout)) {
+        ir_assignment *assign;
+
+        assign = new(ctx) ir_assignment(param->clone(ctx, NULL)->as_rvalue(),
+                                        new(ctx) ir_dereference_variable(parameters[i]),
+                                        NULL);
+        next_ir->insert_before(assign);
+      }
+
+      param_iter.next();
+      sig_param_iter.next();
+   }
+
+   delete [] parameters;
+
+   hash_table_dtor(ht);
+
+   if (retval)
+      return new(ctx) ir_dereference_variable(retval);
+   else
+      return NULL;
+}
+
+
+ir_visitor_status
+ir_function_inlining_visitor::visit_enter(ir_expression *ir)
+{
+   (void) ir;
+   return visit_continue_with_parent;
+}
+
+
+ir_visitor_status
+ir_function_inlining_visitor::visit_enter(ir_return *ir)
+{
+   (void) ir;
+   return visit_continue_with_parent;
+}
+
+
+ir_visitor_status
+ir_function_inlining_visitor::visit_enter(ir_texture *ir)
+{
+   (void) ir;
+   return visit_continue_with_parent;
+}
+
+
+ir_visitor_status
+ir_function_inlining_visitor::visit_enter(ir_swizzle *ir)
+{
+   (void) ir;
+   return visit_continue_with_parent;
+}
+
+
+ir_visitor_status
+ir_function_inlining_visitor::visit_enter(ir_call *ir)
+{
+   if (can_inline(ir)) {
+      /* If the call was part of some tree, then it should have been
+       * flattened out or we shouldn't have seen it because of a
+       * visit_continue_with_parent in this visitor.
+       */
+      assert(ir == base_ir);
+
+      (void) ir->generate_inline(ir);
+      ir->remove();
+      this->progress = true;
+   }
+
+   return visit_continue;
+}
+
+
+ir_visitor_status
+ir_function_inlining_visitor::visit_enter(ir_assignment *ir)
+{
+   ir_call *call = ir->rhs->as_call();
+   if (!call || !can_inline(call))
+      return visit_continue;
+
+   /* generates the parameter setup, function body, and returns the return
+    * value of the function
+    */
+   ir_rvalue *rhs = call->generate_inline(ir);
+   assert(rhs);
+
+   ir->rhs = rhs;
+   this->progress = true;
+
+   return visit_continue;
+}
+
+/**
+ * Replaces references to the "sampler" variable with a clone of "deref."
+ *
+ * From the spec, samplers can appear in the tree as function
+ * (non-out) parameters and as the result of array indexing and
+ * structure field selection.  In our builtin implementation, they
+ * also appear in the sampler field of an ir_tex instruction.
+ */
+
+class ir_sampler_replacement_visitor : public ir_hierarchical_visitor {
+public:
+   ir_sampler_replacement_visitor(ir_variable *sampler, ir_dereference *deref)
+   {
+      this->sampler = sampler;
+      this->deref = deref;
+   }
+
+   virtual ~ir_sampler_replacement_visitor()
+   {
+   }
+
+   virtual ir_visitor_status visit_leave(ir_call *);
+   virtual ir_visitor_status visit_leave(ir_dereference_array *);
+   virtual ir_visitor_status visit_leave(ir_dereference_record *);
+   virtual ir_visitor_status visit_leave(ir_texture *);
+
+   void replace_deref(ir_dereference **deref);
+   void replace_rvalue(ir_rvalue **rvalue);
+
+   ir_variable *sampler;
+   ir_dereference *deref;
+};
+
+void
+ir_sampler_replacement_visitor::replace_deref(ir_dereference **deref)
+{
+   ir_dereference_variable *deref_var = (*deref)->as_dereference_variable();
+   if (deref_var && deref_var->var == this->sampler) {
+      *deref = this->deref->clone(talloc_parent(*deref), NULL);
+   }
+}
+
+void
+ir_sampler_replacement_visitor::replace_rvalue(ir_rvalue **rvalue)
+{
+   if (!*rvalue)
+      return;
+
+   ir_dereference *deref = (*rvalue)->as_dereference();
+
+   if (!deref)
+      return;
+
+   replace_deref(&deref);
+   *rvalue = deref;
+}
+
+ir_visitor_status
+ir_sampler_replacement_visitor::visit_leave(ir_texture *ir)
+{
+   replace_deref(&ir->sampler);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_sampler_replacement_visitor::visit_leave(ir_dereference_array *ir)
+{
+   replace_rvalue(&ir->array);
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_sampler_replacement_visitor::visit_leave(ir_dereference_record *ir)
+{
+   replace_rvalue(&ir->record);
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_sampler_replacement_visitor::visit_leave(ir_call *ir)
+{
+   foreach_iter(exec_list_iterator, iter, *ir) {
+      ir_rvalue *param = (ir_rvalue *)iter.get();
+      ir_rvalue *new_param = param;
+      replace_rvalue(&new_param);
+
+      if (new_param != param) {
+        param->replace_with(new_param);
+      }
+   }
+   return visit_continue;
+}
+
+static void
+do_sampler_replacement(exec_list *instructions,
+                      ir_variable *sampler,
+                      ir_dereference *deref)
+{
+   ir_sampler_replacement_visitor v(sampler, deref);
+
+   visit_list_elements(&v, instructions);
+}
diff --git a/src/glsl/ir_function_inlining.h b/src/glsl/ir_function_inlining.h
new file mode 100644 (file)
index 0000000..6db011b
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_function_inlining.h
+ *
+ * Replaces calls to functions with the body of the function.
+ */
+
+bool can_inline(ir_call *call);
diff --git a/src/glsl/ir_hierarchical_visitor.cpp b/src/glsl/ir_hierarchical_visitor.cpp
new file mode 100644 (file)
index 0000000..809b08e
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 "ir.h"
+#include "ir_hierarchical_visitor.h"
+
+ir_hierarchical_visitor::ir_hierarchical_visitor()
+{
+   this->base_ir = NULL;
+   this->callback = NULL;
+   this->data = NULL;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit(ir_variable *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit(ir_constant *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit(ir_loop_jump *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit(ir_dereference_variable *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_loop *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_loop *ir)
+{
+   (void) ir;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_function_signature *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_function_signature *ir)
+{
+   (void) ir;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_function *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_function *ir)
+{
+   (void) ir;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_expression *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_expression *ir)
+{
+   (void) ir;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_texture *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_texture *ir)
+{
+   (void) ir;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_swizzle *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_swizzle *ir)
+{
+   (void) ir;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_dereference_array *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_dereference_array *ir)
+{
+   (void) ir;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_dereference_record *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_dereference_record *ir)
+{
+   (void) ir;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_assignment *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_assignment *ir)
+{
+   (void) ir;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_call *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_call *ir)
+{
+   (void) ir;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_return *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_return *ir)
+{
+   (void) ir;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_discard *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_discard *ir)
+{
+   (void) ir;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_if *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_if *ir)
+{
+   (void) ir;
+   return visit_continue;
+}
+
+void
+ir_hierarchical_visitor::run(exec_list *instructions)
+{
+   visit_list_elements(this, instructions);
+}
+
+
+void
+visit_tree(ir_instruction *ir,
+          void (*callback)(class ir_instruction *ir, void *data),
+          void *data)
+{
+   ir_hierarchical_visitor v;
+
+   v.callback = callback;
+   v.data = data;
+
+   ir->accept(&v);
+}
diff --git a/src/glsl/ir_hierarchical_visitor.h b/src/glsl/ir_hierarchical_visitor.h
new file mode 100644 (file)
index 0000000..afa780d
--- /dev/null
@@ -0,0 +1,176 @@
+/* -*- c++ -*- */
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+#pragma once
+#ifndef IR_HIERARCHICAL_VISITOR_H
+#define IR_HIERARCHICAL_VISITOR_H
+
+/**
+ * Enumeration values returned by visit methods to guide processing
+ */
+enum ir_visitor_status {
+   visit_continue,             /**< Continue visiting as normal. */
+   visit_continue_with_parent, /**< Don't visit siblings, continue w/parent. */
+   visit_stop                  /**< Stop visiting immediately. */
+};
+
+
+/**
+ * Base class of hierarchical visitors of IR instruction trees
+ *
+ * Hierarchical visitors differ from traditional visitors in a couple of
+ * important ways.  Rather than having a single \c visit method for each
+ * subclass in the composite, there are three kinds of visit methods.
+ * Leaf-node classes have a traditional \c visit method.  Internal-node
+ * classes have a \c visit_enter method, which is invoked just before
+ * processing child nodes, and a \c visit_leave method which is invoked just
+ * after processing child nodes.
+ *
+ * In addition, each visit method and the \c accept methods in the composite
+ * have a return value which guides the navigation.  Any of the visit methods
+ * can choose to continue visiting the tree as normal (by returning \c
+ * visit_continue), terminate visiting any further nodes immediately (by
+ * returning \c visit_stop), or stop visiting sibling nodes (by returning \c
+ * visit_continue_with_parent).
+ *
+ * These two changes combine to allow nagivation of children to be implemented
+ * in the composite's \c accept method.  The \c accept method for a leaf-node
+ * class will simply call the \c visit method, as usual, and pass its return
+ * value on.  The \c accept method for internal-node classes will call the \c
+ * visit_enter method, call the \c accpet method of each child node, and,
+ * finally, call the \c visit_leave method.  If any of these return a value
+ * other that \c visit_continue, the correct action must be taken.
+ *
+ * The final benefit is that the hierarchical visitor base class need not be
+ * abstract.  Default implementations of every \c visit, \c visit_enter, and
+ * \c visit_leave method can be provided.  By default each of these methods
+ * simply returns \c visit_continue.  This allows a significant reduction in
+ * derived class code.
+ *
+ * For more information about hierarchical visitors, see:
+ *
+ *    http://c2.com/cgi/wiki?HierarchicalVisitorPattern
+ *    http://c2.com/cgi/wiki?HierarchicalVisitorDiscussion
+ */
+
+class ir_hierarchical_visitor {
+public:
+   ir_hierarchical_visitor();
+
+   /**
+    * \name Visit methods for leaf-node classes
+    */
+   /*@{*/
+   virtual ir_visitor_status visit(class ir_variable *);
+   virtual ir_visitor_status visit(class ir_constant *);
+   virtual ir_visitor_status visit(class ir_loop_jump *);
+
+   /**
+    * ir_dereference_variable isn't technically a leaf, but it is treated as a
+    * leaf here for a couple reasons.  By not automatically visiting the one
+    * child ir_variable node from the ir_dereference_variable, ir_variable
+    * nodes can always be handled as variable declarations.  Code that used
+    * non-hierarchical visitors had to set an "in a dereference" flag to
+    * determine how to handle an ir_variable.  By forcing the visitor to
+    * handle the ir_variable within the ir_dereference_variable visitor, this
+    * kludge can be avoided.
+    *
+    * In addition, I can envision no use for having separate enter and leave
+    * methods.  Anything that could be done in the enter and leave methods
+    * that couldn't just be done in the visit method.
+    */
+   virtual ir_visitor_status visit(class ir_dereference_variable *);
+   /*@}*/
+
+   /**
+    * \name Visit methods for internal-node classes
+    */
+   /*@{*/
+   virtual ir_visitor_status visit_enter(class ir_loop *);
+   virtual ir_visitor_status visit_leave(class ir_loop *);
+   virtual ir_visitor_status visit_enter(class ir_function_signature *);
+   virtual ir_visitor_status visit_leave(class ir_function_signature *);
+   virtual ir_visitor_status visit_enter(class ir_function *);
+   virtual ir_visitor_status visit_leave(class ir_function *);
+   virtual ir_visitor_status visit_enter(class ir_expression *);
+   virtual ir_visitor_status visit_leave(class ir_expression *);
+   virtual ir_visitor_status visit_enter(class ir_texture *);
+   virtual ir_visitor_status visit_leave(class ir_texture *);
+   virtual ir_visitor_status visit_enter(class ir_swizzle *);
+   virtual ir_visitor_status visit_leave(class ir_swizzle *);
+   virtual ir_visitor_status visit_enter(class ir_dereference_array *);
+   virtual ir_visitor_status visit_leave(class ir_dereference_array *);
+   virtual ir_visitor_status visit_enter(class ir_dereference_record *);
+   virtual ir_visitor_status visit_leave(class ir_dereference_record *);
+   virtual ir_visitor_status visit_enter(class ir_assignment *);
+   virtual ir_visitor_status visit_leave(class ir_assignment *);
+   virtual ir_visitor_status visit_enter(class ir_call *);
+   virtual ir_visitor_status visit_leave(class ir_call *);
+   virtual ir_visitor_status visit_enter(class ir_return *);
+   virtual ir_visitor_status visit_leave(class ir_return *);
+   virtual ir_visitor_status visit_enter(class ir_discard *);
+   virtual ir_visitor_status visit_leave(class ir_discard *);
+   virtual ir_visitor_status visit_enter(class ir_if *);
+   virtual ir_visitor_status visit_leave(class ir_if *);
+   /*@}*/
+
+
+   /**
+    * Utility function to process a linked list of instructions with a visitor
+    */
+   void run(struct exec_list *instructions);
+
+   /* Some visitors may need to insert new variable declarations and
+    * assignments for portions of a subtree, which means they need a
+    * pointer to the current instruction in the stream, not just their
+    * node in the tree rooted at that instruction.
+    *
+    * This is implemented by visit_list_elements -- if the visitor is
+    * not called by it, nothing good will happen.
+    */
+   class ir_instruction *base_ir;
+
+   /**
+    * Callback function that is invoked on entry to each node visited.
+    *
+    * \warning
+    * Visitor classes derived from \c ir_hierarchical_visitor \b may \b not
+    * invoke this function.  This can be used, for example, to cause the
+    * callback to be invoked on every node type execpt one.
+    */
+   void (*callback)(class ir_instruction *ir, void *data);
+
+   /**
+    * Extra data parameter passed to the per-node callback function
+    */
+   void *data;
+};
+
+void visit_tree(ir_instruction *ir,
+               void (*callback)(class ir_instruction *ir, void *data),
+               void *data);
+
+ir_visitor_status visit_list_elements(ir_hierarchical_visitor *v, exec_list *l);
+
+#endif /* IR_HIERARCHICAL_VISITOR_H */
diff --git a/src/glsl/ir_hv_accept.cpp b/src/glsl/ir_hv_accept.cpp
new file mode 100644 (file)
index 0000000..6dae4ed
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 "ir.h"
+
+/**
+ * \file ir_hv_accept.cpp
+ * Implementations of all hierarchical visitor accept methods for IR
+ * instructions.
+ */
+
+/**
+ * Process a list of nodes using a hierarchical vistor
+ *
+ * \warning
+ * This function will operate correctly if a node being processed is removed
+ * from the list.  However, if nodes are added to the list after the node being
+ * processed, some of the added nodes may not be processed.
+ */
+ir_visitor_status
+visit_list_elements(ir_hierarchical_visitor *v, exec_list *l)
+{
+   ir_instruction *prev_base_ir = v->base_ir;
+
+   foreach_list_safe(n, l) {
+      ir_instruction *const ir = (ir_instruction *) n;
+      v->base_ir = ir;
+      ir_visitor_status s = ir->accept(v);
+
+      if (s != visit_continue)
+        return s;
+   }
+   v->base_ir = prev_base_ir;
+
+   return visit_continue;
+}
+
+
+ir_visitor_status
+ir_variable::accept(ir_hierarchical_visitor *v)
+{
+   return v->visit(this);
+}
+
+
+ir_visitor_status
+ir_loop::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = visit_list_elements(v, &this->body_instructions);
+   if (s == visit_stop)
+      return s;
+
+   if (s != visit_continue_with_parent) {
+      if (this->from) {
+        s = this->from->accept(v);
+        if (s != visit_continue)
+           return (s == visit_continue_with_parent) ? visit_continue : s;
+      }
+
+      if (this->to) {
+        s = this->to->accept(v);
+        if (s != visit_continue)
+           return (s == visit_continue_with_parent) ? visit_continue : s;
+      }
+
+      if (this->increment) {
+        s = this->increment->accept(v);
+        if (s != visit_continue)
+           return (s == visit_continue_with_parent) ? visit_continue : s;
+      }
+   }
+
+   return v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_loop_jump::accept(ir_hierarchical_visitor *v)
+{
+   return v->visit(this);
+}
+
+
+ir_visitor_status
+ir_function_signature::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = visit_list_elements(v, &this->parameters);
+   if (s == visit_stop)
+      return s;
+
+   s = visit_list_elements(v, &this->body);
+   return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_function::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = visit_list_elements(v, &this->signatures);
+   return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_expression::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   for (unsigned i = 0; i < this->get_num_operands(); i++) {
+      switch (this->operands[i]->accept(v)) {
+      case visit_continue:
+        break;
+
+      case visit_continue_with_parent:
+        // I wish for Java's labeled break-statement here.
+        goto done;
+
+      case visit_stop:
+        return s;
+      }
+   }
+
+done:
+   return v->visit_leave(this);
+}
+
+ir_visitor_status
+ir_texture::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = this->sampler->accept(v);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = this->coordinate->accept(v);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   if (this->projector) {
+      s = this->projector->accept(v);
+      if (s != visit_continue)
+        return (s == visit_continue_with_parent) ? visit_continue : s;
+   }
+
+   if (this->shadow_comparitor) {
+      s = this->shadow_comparitor->accept(v);
+      if (s != visit_continue)
+        return (s == visit_continue_with_parent) ? visit_continue : s;
+   }
+
+   switch (this->op) {
+   case ir_tex:
+      break;
+   case ir_txb:
+      s = this->lod_info.bias->accept(v);
+      if (s != visit_continue)
+        return (s == visit_continue_with_parent) ? visit_continue : s;
+      break;
+   case ir_txl:
+   case ir_txf:
+      s = this->lod_info.lod->accept(v);
+      if (s != visit_continue)
+        return (s == visit_continue_with_parent) ? visit_continue : s;
+      break;
+   case ir_txd:
+      s = this->lod_info.grad.dPdx->accept(v);
+      if (s != visit_continue)
+        return (s == visit_continue_with_parent) ? visit_continue : s;
+
+      s = this->lod_info.grad.dPdy->accept(v);
+      if (s != visit_continue)
+        return (s == visit_continue_with_parent) ? visit_continue : s;
+      break;
+   }
+
+   return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_swizzle::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = this->val->accept(v);
+   return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_dereference_variable::accept(ir_hierarchical_visitor *v)
+{
+   return v->visit(this);
+}
+
+
+ir_visitor_status
+ir_dereference_array::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = this->array_index->accept(v);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = this->array->accept(v);
+   return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_dereference_record::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = this->record->accept(v);
+   return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_assignment::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = this->lhs->accept(v);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = this->rhs->accept(v);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   if (this->condition)
+      s = this->condition->accept(v);
+
+   return (s == visit_stop) ? s : v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_constant::accept(ir_hierarchical_visitor *v)
+{
+   return v->visit(this);
+}
+
+
+ir_visitor_status
+ir_call::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = visit_list_elements(v, &this->actual_parameters);
+   if (s == visit_stop)
+      return s;
+
+   return v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_return::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   ir_rvalue *val = this->get_value();
+   if (val) {
+      s = val->accept(v);
+      if (s != visit_continue)
+        return (s == visit_continue_with_parent) ? visit_continue : s;
+   }
+
+   return v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_discard::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   if (this->condition != NULL) {
+      s = this->condition->accept(v);
+      if (s != visit_continue)
+        return (s == visit_continue_with_parent) ? visit_continue : s;
+   }
+
+   return v->visit_leave(this);
+}
+
+
+ir_visitor_status
+ir_if::accept(ir_hierarchical_visitor *v)
+{
+   ir_visitor_status s = v->visit_enter(this);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = this->condition->accept(v);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   if (s != visit_continue_with_parent) {
+      s = visit_list_elements(v, &this->then_instructions);
+      if (s == visit_stop)
+        return s;
+   }
+
+   if (s != visit_continue_with_parent) {
+      s = visit_list_elements(v, &this->else_instructions);
+      if (s == visit_stop)
+        return s;
+   }
+
+   return v->visit_leave(this);
+}
diff --git a/src/glsl/ir_if_return.cpp b/src/glsl/ir_if_return.cpp
new file mode 100644 (file)
index 0000000..5ab8759
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_if_return.cpp
+ *
+ * This pass tries to normalize functions to always return from one
+ * place by moving around blocks of code in if statements.
+ *
+ * This helps on hardware with no branching support, and may even be a
+ * useful transform on hardware supporting control flow by turning
+ * masked returns into normal returns.
+ */
+
+#include <string.h>
+#include "glsl_types.h"
+#include "ir.h"
+
+class ir_if_return_visitor : public ir_hierarchical_visitor {
+public:
+   ir_if_return_visitor()
+   {
+      this->progress = false;
+   }
+
+   ir_visitor_status visit_enter(ir_function_signature *);
+   ir_visitor_status visit_leave(ir_if *);
+
+   ir_visitor_status move_outer_block_inside(ir_instruction *ir,
+                                            exec_list *inner_block);
+   void move_returns_after_block(ir_instruction *ir,
+                                ir_return *then_return,
+                                ir_return *else_return);
+   bool progress;
+};
+
+bool
+do_if_return(exec_list *instructions)
+{
+   ir_if_return_visitor v;
+
+   do {
+      v.progress = false;
+      visit_list_elements(&v, instructions);
+   } while (v.progress);
+
+   return v.progress;
+}
+
+/**
+ * Removes any instructions after a (unconditional) return, since they will
+ * never be executed.
+ */
+static void
+truncate_after_instruction(ir_instruction *ir)
+{
+   if (!ir)
+      return;
+
+   while (!ir->get_next()->is_tail_sentinel())
+      ((ir_instruction *)ir->get_next())->remove();
+}
+
+/**
+ * Returns an ir_instruction of the first ir_return in the exec_list, or NULL.
+ */
+static ir_return *
+find_return_in_block(exec_list *instructions)
+{
+   foreach_iter(exec_list_iterator, iter, *instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      if (ir->ir_type == ir_type_return)
+        return (ir_return *)ir;
+   }
+
+   return NULL;
+}
+
+void
+ir_if_return_visitor::move_returns_after_block(ir_instruction *ir,
+                                              ir_return *then_return,
+                                              ir_return *else_return)
+{
+
+   if (!then_return->value) {
+      then_return->remove();
+      else_return->remove();
+      ir->insert_after(new(ir) ir_return(NULL));
+   } else {
+      ir_assignment *assign;
+      ir_variable *new_var = new(ir) ir_variable(then_return->value->type,
+                                                "if_return_tmp",
+                                                ir_var_temporary);
+      ir->insert_before(new_var);
+
+      assign = new(ir) ir_assignment(new(ir) ir_dereference_variable(new_var),
+                                    then_return->value, NULL);
+      then_return->replace_with(assign);
+
+      assign = new(ir) ir_assignment(new(ir) ir_dereference_variable(new_var),
+                                    else_return->value, NULL);
+      else_return->replace_with(assign);
+
+      ir_dereference_variable *deref = new(ir) ir_dereference_variable(new_var);
+      ir->insert_after(new(ir) ir_return(deref));
+   }
+   this->progress = true;
+}
+
+ir_visitor_status
+ir_if_return_visitor::move_outer_block_inside(ir_instruction *ir,
+                                             exec_list *inner_block)
+{
+   if (!ir->get_next()->is_tail_sentinel()) {
+      while (!ir->get_next()->is_tail_sentinel()) {
+        ir_instruction *move_ir = (ir_instruction *)ir->get_next();
+
+        move_ir->remove();
+        inner_block->push_tail(move_ir);
+      }
+
+      /* If we move the instructions following ir inside the block, it
+       * will confuse the exec_list iteration in the parent that visited
+       * us.  So stop the visit at this point.
+       */
+      return visit_stop;
+   } else {
+      return visit_continue;
+   }
+}
+
+/* Normalize a function to always have a return statement at the end.
+ *
+ * This avoids the ir_if handler needing to know whether it is at the
+ * top level of the function to know if there's an implicit return at
+ * the end of the outer block.
+ */
+ir_visitor_status
+ir_if_return_visitor::visit_enter(ir_function_signature *ir)
+{
+   ir_return *ret;
+
+   if (!ir->is_defined)
+      return visit_continue_with_parent;
+   if (strcmp(ir->function_name(), "main") == 0)
+      return visit_continue_with_parent;
+
+   ret = find_return_in_block(&ir->body);
+
+   if (ret) {
+      truncate_after_instruction(ret);
+   } else {
+      if (ir->return_type->is_void()) {
+        ir->body.push_tail(new(ir) ir_return(NULL));
+      } else {
+        /* Probably, if we've got a function with a return value
+         * hitting this point, it's something like:
+         *
+         * float reduce_below_half(float val)
+         * {
+         *         while () {
+         *                 if (val >= 0.5)
+         *                         val /= 2.0;
+         *                 else
+         *                         return val;
+         *         }
+         * }
+         *
+         * So we gain a junk return statement of an undefined value
+         * at the end that never gets executed.  However, a backend
+         * using this pass is probably desperate to get rid of
+         * function calls, so go ahead and do it for their sake in
+         * case it fixes apps.
+         */
+        ir_variable *undef = new(ir) ir_variable(ir->return_type,
+                                                 "if_return_undef",
+                                                 ir_var_temporary);
+        ir->body.push_tail(undef);
+
+        ir_dereference_variable *deref = new(ir) ir_dereference_variable(undef);
+        ir->body.push_tail(new(ir) ir_return(deref));
+      }
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_if_return_visitor::visit_leave(ir_if *ir)
+{
+   ir_return *then_return;
+   ir_return *else_return;
+
+   then_return = find_return_in_block(&ir->then_instructions);
+   else_return = find_return_in_block(&ir->else_instructions);
+   if (!then_return && !else_return)
+      return visit_continue;
+
+   /* Trim off any trailing instructions after the return statements
+    * on both sides.
+    */
+   truncate_after_instruction(then_return);
+   truncate_after_instruction(else_return);
+
+   /* If both sides return, then we can move the returns to a single
+    * one outside the if statement.
+    */
+   if (then_return && else_return) {
+      move_returns_after_block(ir, then_return, else_return);
+      return visit_continue;
+   }
+
+   /* If only one side returns, then the block of code after the "if"
+    * is only executed by the other side, so those instructions don't
+    * need to be anywhere but that other side.
+    *
+    * This will usually pull a return statement up into the other
+    * side, so we'll trigger the above case on the next pass.
+    */
+   if (then_return) {
+      return move_outer_block_inside(ir, &ir->else_instructions);
+   } else {
+      assert(else_return);
+      return move_outer_block_inside(ir, &ir->then_instructions);
+   }
+}
diff --git a/src/glsl/ir_if_simplification.cpp b/src/glsl/ir_if_simplification.cpp
new file mode 100644 (file)
index 0000000..6882ef7
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_function_inlining.cpp
+ *
+ * Moves constant branches of if statements out to the surrounding
+ * instruction stream.
+ */
+
+#include "ir.h"
+
+class ir_if_simplification_visitor : public ir_hierarchical_visitor {
+public:
+   ir_if_simplification_visitor()
+   {
+      this->made_progress = false;
+   }
+
+   ir_visitor_status visit_leave(ir_if *);
+
+   bool made_progress;
+};
+
+bool
+do_if_simplification(exec_list *instructions)
+{
+   ir_if_simplification_visitor v;
+
+   v.run(instructions);
+   return v.made_progress;
+}
+
+
+ir_visitor_status
+ir_if_simplification_visitor::visit_leave(ir_if *ir)
+{
+   /* FINISHME: Ideally there would be a way to note that the condition results
+    * FINISHME: in a constant before processing both of the other subtrees.
+    * FINISHME: This can probably be done with some flags, but it would take
+    * FINISHME: some work to get right.
+    */
+   ir_constant *condition_constant = ir->condition->constant_expression_value();
+   if (condition_constant) {
+      /* Move the contents of the one branch of the conditional
+       * that matters out.
+       */
+      if (condition_constant->value.b[0]) {
+        foreach_iter(exec_list_iterator, then_iter, ir->then_instructions) {
+           ir_instruction *then_ir = (ir_instruction *)then_iter.get();
+           ir->insert_before(then_ir);
+        }
+      } else {
+        foreach_iter(exec_list_iterator, else_iter, ir->else_instructions) {
+           ir_instruction *else_ir = (ir_instruction *)else_iter.get();
+           ir->insert_before(else_ir);
+        }
+      }
+      ir->remove();
+      this->made_progress = true;
+   }
+
+   return visit_continue;
+}
diff --git a/src/glsl/ir_if_to_cond_assign.cpp b/src/glsl/ir_if_to_cond_assign.cpp
new file mode 100644 (file)
index 0000000..0b87413
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_if_to_cond_assign.cpp
+ *
+ * This attempts to flatten all if statements to conditional
+ * assignments for GPUs that don't do control flow.
+ *
+ * It can't handle other control flow being inside of its block, such
+ * as calls or loops.  Hopefully loop unrolling and inlining will take
+ * care of those.
+ */
+
+#include "glsl_types.h"
+#include "ir.h"
+
+class ir_if_to_cond_assign_visitor : public ir_hierarchical_visitor {
+public:
+   ir_if_to_cond_assign_visitor()
+   {
+      this->progress = false;
+   }
+
+   ir_visitor_status visit_leave(ir_if *);
+
+   bool progress;
+};
+
+bool
+do_if_to_cond_assign(exec_list *instructions)
+{
+   ir_if_to_cond_assign_visitor v;
+
+   visit_list_elements(&v, instructions);
+
+   return v.progress;
+}
+
+void
+check_control_flow(ir_instruction *ir, void *data)
+{
+   bool *found_control_flow = (bool *)data;
+   switch (ir->ir_type) {
+   case ir_type_call:
+   case ir_type_discard:
+   case ir_type_loop:
+   case ir_type_loop_jump:
+   case ir_type_return:
+      *found_control_flow = true;
+      break;
+   default:
+      break;
+   }
+}
+
+void
+move_block_to_cond_assign(void *mem_ctx,
+                         ir_if *if_ir, ir_variable *cond_var, bool then)
+{
+   exec_list *instructions;
+
+   if (then) {
+      instructions = &if_ir->then_instructions;
+   } else {
+      instructions = &if_ir->else_instructions;
+   }
+
+   foreach_iter(exec_list_iterator, iter, *instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+
+      if (ir->ir_type == ir_type_assignment) {
+        ir_assignment *assign = (ir_assignment *)ir;
+        ir_rvalue *cond_expr;
+        ir_dereference *deref = new(mem_ctx) ir_dereference_variable(cond_var);
+
+        if (then) {
+           cond_expr = deref;
+        } else {
+           cond_expr = new(mem_ctx) ir_expression(ir_unop_logic_not,
+                                                  glsl_type::bool_type,
+                                                  deref,
+                                                  NULL);
+        }
+
+        if (!assign->condition) {
+           assign->condition = cond_expr;
+        } else {
+           assign->condition = new(mem_ctx) ir_expression(ir_binop_logic_and,
+                                                          glsl_type::bool_type,
+                                                          cond_expr,
+                                                          assign->condition);
+        }
+      }
+
+      /* Now, move from the if block to the block surrounding it. */
+      ir->remove();
+      if_ir->insert_before(ir);
+   }
+}
+
+ir_visitor_status
+ir_if_to_cond_assign_visitor::visit_leave(ir_if *ir)
+{
+   bool found_control_flow = false;
+   ir_variable *cond_var;
+   ir_assignment *assign;
+   ir_dereference_variable *deref;
+
+   /* Check that both blocks don't contain anything we can't support. */
+   foreach_iter(exec_list_iterator, then_iter, ir->then_instructions) {
+      ir_instruction *then_ir = (ir_instruction *)then_iter.get();
+      visit_tree(then_ir, check_control_flow, &found_control_flow);
+   }
+   foreach_iter(exec_list_iterator, else_iter, ir->else_instructions) {
+      ir_instruction *else_ir = (ir_instruction *)else_iter.get();
+      visit_tree(else_ir, check_control_flow, &found_control_flow);
+   }
+   if (found_control_flow)
+      return visit_continue;
+
+   void *mem_ctx = talloc_parent(ir);
+
+   /* Store the condition to a variable so the assignment conditions are
+    * simpler.
+    */
+   cond_var = new(mem_ctx) ir_variable(glsl_type::bool_type,
+                                      "if_to_cond_assign_condition",
+                                      ir_var_temporary);
+   ir->insert_before(cond_var);
+
+   deref = new(mem_ctx) ir_dereference_variable(cond_var);
+   assign = new(mem_ctx) ir_assignment(deref,
+                                      ir->condition, NULL);
+   ir->insert_before(assign);
+
+   /* Now, move all of the instructions out of the if blocks, putting
+    * conditions on assignments.
+    */
+   move_block_to_cond_assign(mem_ctx, ir, cond_var, true);
+   move_block_to_cond_assign(mem_ctx, ir, cond_var, false);
+
+   ir->remove();
+
+   this->progress = true;
+
+   return visit_continue;
+}
diff --git a/src/glsl/ir_import_prototypes.cpp b/src/glsl/ir_import_prototypes.cpp
new file mode 100644 (file)
index 0000000..a39b384
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_import_prototypes.cpp
+ * Import function prototypes from one IR tree into another.
+ *
+ * \author Ian Romanick
+ */
+#include <cstdio>
+#include "ir.h"
+#include "glsl_symbol_table.h"
+
+/**
+ * Visitor used to import function prototypes
+ *
+ * Normally the \c clone method of either \c ir_function or
+ * \c ir_function_signature could be used.  However, we don't want a complete
+ * clone of the \c ir_function_signature.  We want everything \b except the
+ * body of the function.
+ */
+class import_prototype_visitor : public ir_hierarchical_visitor {
+public:
+   /**
+    */
+   import_prototype_visitor(exec_list *list, glsl_symbol_table *symbols,
+                           void *mem_ctx)
+   {
+      this->mem_ctx = mem_ctx;
+      this->list = list;
+      this->symbols = symbols;
+      this->function = NULL;
+   }
+
+   virtual ir_visitor_status visit_enter(ir_function *ir)
+   {
+      assert(this->function == NULL);
+
+      this->function = this->symbols->get_function(ir->name);
+      if (!this->function) {
+        this->function = new(this->mem_ctx) ir_function(ir->name);
+        this->function->is_builtin = ir->is_builtin;
+
+        list->push_tail(this->function);
+
+        /* Add the new function to the symbol table.
+         */
+        this->symbols->add_function(this->function->name, this->function);
+      }
+      return visit_continue;
+   }
+
+   virtual ir_visitor_status visit_leave(ir_function *ir)
+   {
+      (void) ir;
+      assert(this->function != NULL);
+
+      this->function = NULL;
+      return visit_continue;
+   }
+
+   ir_visitor_status visit_enter(ir_function_signature *ir)
+   {
+      assert(this->function != NULL);
+
+      ir_function_signature *copy =
+        new(mem_ctx) ir_function_signature(ir->return_type);
+
+      copy->is_defined = false;
+
+      /* Clone the parameter list, but NOT the body.
+       */
+      foreach_list_const(node, &ir->parameters) {
+        const ir_variable *const param = (const ir_variable *) node;
+
+        assert(const_cast<ir_variable *>(param)->as_variable() != NULL);
+
+        ir_variable *const param_copy = param->clone(mem_ctx, NULL);
+        copy->parameters.push_tail(param_copy);
+      }
+
+      this->function->add_signature(copy);
+
+      /* Do not process child nodes of the ir_function_signature.  There can
+       * never be any nodes inside the ir_function_signature that we care
+       * about.  Instead continue with the next sibling.
+       */
+      return visit_continue_with_parent;
+   }
+
+private:
+   exec_list *list;
+   ir_function *function;
+   glsl_symbol_table *symbols;
+   void *mem_ctx;
+};
+
+
+/**
+ * Import function prototypes from one IR tree into another
+ *
+ * \param source   Source instruction stream containing functions whose
+ *                 prototypes are to be imported
+ * \param dest     Destination instruction stream where new \c ir_function and
+ *                 \c ir_function_signature nodes will be stored
+ * \param symbols  Symbol table where new functions will be stored
+ * \param mem_ctx  talloc memory context used for new allocations
+ */
+void
+import_prototypes(const exec_list *source, exec_list *dest,
+                 glsl_symbol_table *symbols, void *mem_ctx)
+{
+   import_prototype_visitor v(dest, symbols, mem_ctx);
+
+   /* Making source be const is just extra documentation.
+    */
+   v.run(const_cast<exec_list *>(source));
+}
diff --git a/src/glsl/ir_mat_op_to_vec.cpp b/src/glsl/ir_mat_op_to_vec.cpp
new file mode 100644 (file)
index 0000000..da6de94
--- /dev/null
@@ -0,0 +1,491 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_mat_op_to_vec.cpp
+ *
+ * Breaks matrix operation expressions down to a series of vector operations.
+ *
+ * Generally this is how we have to codegen matrix operations for a
+ * GPU, so this gives us the chance to constant fold operations on a
+ * column or row.
+ */
+
+#include "ir.h"
+#include "ir_expression_flattening.h"
+#include "glsl_types.h"
+
+class ir_mat_op_to_vec_visitor : public ir_hierarchical_visitor {
+public:
+   ir_mat_op_to_vec_visitor()
+   {
+      this->made_progress = false;
+      this->mem_ctx = NULL;
+   }
+
+   ir_visitor_status visit_leave(ir_assignment *);
+
+   ir_dereference *get_column(ir_variable *var, int col);
+   ir_rvalue *get_element(ir_variable *var, int col, int row);
+
+   void do_mul_mat_mat(ir_variable *result_var,
+                      ir_variable *a_var, ir_variable *b_var);
+   void do_mul_mat_vec(ir_variable *result_var,
+                      ir_variable *a_var, ir_variable *b_var);
+   void do_mul_vec_mat(ir_variable *result_var,
+                      ir_variable *a_var, ir_variable *b_var);
+   void do_mul_mat_scalar(ir_variable *result_var,
+                         ir_variable *a_var, ir_variable *b_var);
+   void do_equal_mat_mat(ir_variable *result_var, ir_variable *a_var,
+                        ir_variable *b_var, bool test_equal);
+
+   void *mem_ctx;
+   bool made_progress;
+};
+
+static bool
+mat_op_to_vec_predicate(ir_instruction *ir)
+{
+   ir_expression *expr = ir->as_expression();
+   unsigned int i;
+
+   if (!expr)
+      return false;
+
+   for (i = 0; i < expr->get_num_operands(); i++) {
+      if (expr->operands[i]->type->is_matrix())
+        return true;
+   }
+
+   return false;
+}
+
+bool
+do_mat_op_to_vec(exec_list *instructions)
+{
+   ir_mat_op_to_vec_visitor v;
+
+   /* Pull out any matrix expression to a separate assignment to a
+    * temp.  This will make our handling of the breakdown to
+    * operations on the matrix's vector components much easier.
+    */
+   do_expression_flattening(instructions, mat_op_to_vec_predicate);
+
+   visit_list_elements(&v, instructions);
+
+   return v.made_progress;
+}
+
+ir_rvalue *
+ir_mat_op_to_vec_visitor::get_element(ir_variable *var, int col, int row)
+{
+   ir_dereference *deref;
+
+   deref = new(mem_ctx) ir_dereference_variable(var);
+
+   if (var->type->is_matrix()) {
+      deref = new(mem_ctx) ir_dereference_array(var,
+                                               new(mem_ctx) ir_constant(col));
+   } else {
+      assert(col == 0);
+   }
+
+   return new(mem_ctx) ir_swizzle(deref, row, 0, 0, 0, 1);
+}
+
+ir_dereference *
+ir_mat_op_to_vec_visitor::get_column(ir_variable *var, int row)
+{
+   ir_dereference *deref;
+
+   if (!var->type->is_matrix()) {
+      deref = new(mem_ctx) ir_dereference_variable(var);
+   } else {
+      deref = new(mem_ctx) ir_dereference_variable(var);
+      deref = new(mem_ctx) ir_dereference_array(deref,
+                                               new(mem_ctx) ir_constant(row));
+   }
+
+   return deref;
+}
+
+void
+ir_mat_op_to_vec_visitor::do_mul_mat_mat(ir_variable *result_var,
+                                        ir_variable *a_var,
+                                        ir_variable *b_var)
+{
+   int b_col, i;
+   ir_assignment *assign;
+   ir_expression *expr;
+
+   for (b_col = 0; b_col < b_var->type->matrix_columns; b_col++) {
+      ir_rvalue *a = get_column(a_var, 0);
+      ir_rvalue *b = get_element(b_var, b_col, 0);
+
+      /* first column */
+      expr = new(mem_ctx) ir_expression(ir_binop_mul,
+                                       a->type,
+                                       a,
+                                       b);
+
+      /* following columns */
+      for (i = 1; i < a_var->type->matrix_columns; i++) {
+        ir_expression *mul_expr;
+
+        a = get_column(a_var, i);
+        b = get_element(b_var, b_col, i);
+
+        mul_expr = new(mem_ctx) ir_expression(ir_binop_mul,
+                                              a->type,
+                                              a,
+                                              b);
+        expr = new(mem_ctx) ir_expression(ir_binop_add,
+                                          a->type,
+                                          expr,
+                                          mul_expr);
+      }
+
+      ir_rvalue *result = get_column(result_var, b_col);
+      assign = new(mem_ctx) ir_assignment(result,
+                                         expr,
+                                         NULL);
+      base_ir->insert_before(assign);
+   }
+}
+
+void
+ir_mat_op_to_vec_visitor::do_mul_mat_vec(ir_variable *result_var,
+                                        ir_variable *a_var,
+                                        ir_variable *b_var)
+{
+   int i;
+   ir_rvalue *a = get_column(a_var, 0);
+   ir_rvalue *b = get_element(b_var, 0, 0);
+   ir_assignment *assign;
+   ir_expression *expr;
+
+   /* first column */
+   expr = new(mem_ctx) ir_expression(ir_binop_mul,
+                                    result_var->type,
+                                    a,
+                                    b);
+
+   /* following columns */
+   for (i = 1; i < a_var->type->matrix_columns; i++) {
+      ir_expression *mul_expr;
+
+      a = get_column(a_var, i);
+      b = get_element(b_var, 0, i);
+
+      mul_expr = new(mem_ctx) ir_expression(ir_binop_mul,
+                                           result_var->type,
+                                           a,
+                                           b);
+      expr = new(mem_ctx) ir_expression(ir_binop_add,
+                                       result_var->type,
+                                       expr,
+                                       mul_expr);
+   }
+
+   ir_rvalue *result = new(mem_ctx) ir_dereference_variable(result_var);
+   assign = new(mem_ctx) ir_assignment(result,
+                                      expr,
+                                      NULL);
+   base_ir->insert_before(assign);
+}
+
+void
+ir_mat_op_to_vec_visitor::do_mul_vec_mat(ir_variable *result_var,
+                                        ir_variable *a_var,
+                                        ir_variable *b_var)
+{
+   int i;
+
+   for (i = 0; i < b_var->type->matrix_columns; i++) {
+      ir_rvalue *a = new(mem_ctx) ir_dereference_variable(a_var);
+      ir_rvalue *b = get_column(b_var, i);
+      ir_rvalue *result;
+      ir_expression *column_expr;
+      ir_assignment *column_assign;
+
+      result = new(mem_ctx) ir_dereference_variable(result_var);
+      result = new(mem_ctx) ir_swizzle(result, i, 0, 0, 0, 1);
+
+      column_expr = new(mem_ctx) ir_expression(ir_binop_dot,
+                                              result->type,
+                                              a,
+                                              b);
+
+      column_assign = new(mem_ctx) ir_assignment(result,
+                                                column_expr,
+                                                NULL);
+      base_ir->insert_before(column_assign);
+   }
+}
+
+void
+ir_mat_op_to_vec_visitor::do_mul_mat_scalar(ir_variable *result_var,
+                                           ir_variable *a_var,
+                                           ir_variable *b_var)
+{
+   int i;
+
+   for (i = 0; i < a_var->type->matrix_columns; i++) {
+      ir_rvalue *a = get_column(a_var, i);
+      ir_rvalue *b = new(mem_ctx) ir_dereference_variable(b_var);
+      ir_rvalue *result = get_column(result_var, i);
+      ir_expression *column_expr;
+      ir_assignment *column_assign;
+
+      column_expr = new(mem_ctx) ir_expression(ir_binop_mul,
+                                              result->type,
+                                              a,
+                                              b);
+
+      column_assign = new(mem_ctx) ir_assignment(result,
+                                                column_expr,
+                                                NULL);
+      base_ir->insert_before(column_assign);
+   }
+}
+
+void
+ir_mat_op_to_vec_visitor::do_equal_mat_mat(ir_variable *result_var,
+                                          ir_variable *a_var,
+                                          ir_variable *b_var,
+                                          bool test_equal)
+{
+   /* This essentially implements the following GLSL:
+    *
+    * bool equal(mat4 a, mat4 b)
+    * {
+    *   return !any(bvec4(a[0] != b[0],
+    *                     a[1] != b[1],
+    *                     a[2] != b[2],
+    *                     a[3] != b[3]);
+    * }
+    *
+    * bool nequal(mat4 a, mat4 b)
+    * {
+    *   return any(bvec4(a[0] != b[0],
+    *                    a[1] != b[1],
+    *                    a[2] != b[2],
+    *                    a[3] != b[3]);
+    * }
+    */
+   const unsigned columns = a_var->type->matrix_columns;
+   const glsl_type *const bvec_type =
+      glsl_type::get_instance(GLSL_TYPE_BOOL, columns, 1);
+
+   ir_variable *const tmp_bvec =
+      new(this->mem_ctx) ir_variable(bvec_type, "mat_cmp_bvec",
+                                    ir_var_temporary);
+   this->base_ir->insert_before(tmp_bvec);
+
+   for (unsigned i = 0; i < columns; i++) {
+      ir_dereference *const op0 = get_column(a_var, i);
+      ir_dereference *const op1 = get_column(b_var, i);
+
+      ir_expression *const cmp =
+        new(this->mem_ctx) ir_expression(ir_binop_nequal,
+                                         glsl_type::bool_type, op0, op1);
+
+      ir_rvalue *const swiz =
+        new(this->mem_ctx) ir_swizzle(cmp, i, i, i, i, columns);
+
+      ir_dereference *const lhs =
+        new(this->mem_ctx) ir_dereference_variable(tmp_bvec);
+
+      ir_assignment *const assign =
+        new(this->mem_ctx) ir_assignment(lhs, swiz, NULL, (1U << i));
+
+      this->base_ir->insert_before(assign);
+   }
+
+   ir_rvalue *const val =
+      new(this->mem_ctx) ir_dereference_variable(tmp_bvec);
+
+   ir_expression *any =
+      new(this->mem_ctx) ir_expression(ir_unop_any, glsl_type::bool_type,
+                                      val, NULL);
+
+   if (test_equal)
+      any = new(this->mem_ctx) ir_expression(ir_unop_logic_not,
+                                            glsl_type::bool_type,
+                                            any, NULL);
+
+   ir_rvalue *const result =
+      new(this->mem_ctx) ir_dereference_variable(result_var);
+
+   ir_assignment *const assign =
+        new(mem_ctx) ir_assignment(result, any, NULL);
+   base_ir->insert_before(assign);
+}
+
+static bool
+has_matrix_operand(const ir_expression *expr, unsigned &columns)
+{
+   for (unsigned i = 0; i < expr->get_num_operands(); i++) {
+      if (expr->operands[i]->type->is_matrix()) {
+        columns = expr->operands[i]->type->matrix_columns;
+        return true;
+      }
+   }
+
+   return false;
+}
+
+
+ir_visitor_status
+ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *orig_assign)
+{
+   ir_expression *orig_expr = orig_assign->rhs->as_expression();
+   unsigned int i, matrix_columns = 1;
+   ir_variable *op_var[2];
+
+   if (!orig_expr)
+      return visit_continue;
+
+   if (!has_matrix_operand(orig_expr, matrix_columns))
+      return visit_continue;
+
+   mem_ctx = talloc_parent(orig_assign);
+
+   ir_dereference_variable *lhs_deref =
+      orig_assign->lhs->as_dereference_variable();
+   assert(lhs_deref);
+
+   ir_variable *result_var = lhs_deref->var;
+
+   /* Store the expression operands in temps so we can use them
+    * multiple times.
+    */
+   for (i = 0; i < orig_expr->get_num_operands(); i++) {
+      ir_assignment *assign;
+
+      op_var[i] = new(mem_ctx) ir_variable(orig_expr->operands[i]->type,
+                                          "mat_op_to_vec",
+                                          ir_var_temporary);
+      base_ir->insert_before(op_var[i]);
+
+      lhs_deref = new(mem_ctx) ir_dereference_variable(op_var[i]);
+      assign = new(mem_ctx) ir_assignment(lhs_deref,
+                                         orig_expr->operands[i],
+                                         NULL);
+      base_ir->insert_before(assign);
+   }
+
+   /* OK, time to break down this matrix operation. */
+   switch (orig_expr->operation) {
+   case ir_unop_neg: {
+      const unsigned mask = (1U << result_var->type->vector_elements) - 1;
+
+      /* Apply the operation to each column.*/
+      for (i = 0; i < matrix_columns; i++) {
+        ir_rvalue *op0 = get_column(op_var[0], i);
+        ir_dereference *result = get_column(result_var, i);
+        ir_expression *column_expr;
+        ir_assignment *column_assign;
+
+        column_expr = new(mem_ctx) ir_expression(orig_expr->operation,
+                                                 result->type,
+                                                 op0,
+                                                 NULL);
+
+        column_assign = new(mem_ctx) ir_assignment(result,
+                                                   column_expr,
+                                                   NULL,
+                                                   mask);
+        assert(column_assign->write_mask != 0);
+        base_ir->insert_before(column_assign);
+      }
+      break;
+   }
+   case ir_binop_add:
+   case ir_binop_sub:
+   case ir_binop_div:
+   case ir_binop_mod: {
+      const unsigned mask = (1U << result_var->type->vector_elements) - 1;
+
+      /* For most operations, the matrix version is just going
+       * column-wise through and applying the operation to each column
+       * if available.
+       */
+      for (i = 0; i < matrix_columns; i++) {
+        ir_rvalue *op0 = get_column(op_var[0], i);
+        ir_rvalue *op1 = get_column(op_var[1], i);
+        ir_dereference *result = get_column(result_var, i);
+        ir_expression *column_expr;
+        ir_assignment *column_assign;
+
+        column_expr = new(mem_ctx) ir_expression(orig_expr->operation,
+                                                 result->type,
+                                                 op0,
+                                                 op1);
+
+        column_assign = new(mem_ctx) ir_assignment(result,
+                                                   column_expr,
+                                                   NULL,
+                                                   mask);
+        assert(column_assign->write_mask != 0);
+        base_ir->insert_before(column_assign);
+      }
+      break;
+   }
+   case ir_binop_mul:
+      if (op_var[0]->type->is_matrix()) {
+        if (op_var[1]->type->is_matrix()) {
+           do_mul_mat_mat(result_var, op_var[0], op_var[1]);
+        } else if (op_var[1]->type->is_vector()) {
+           do_mul_mat_vec(result_var, op_var[0], op_var[1]);
+        } else {
+           assert(op_var[1]->type->is_scalar());
+           do_mul_mat_scalar(result_var, op_var[0], op_var[1]);
+        }
+      } else {
+        assert(op_var[1]->type->is_matrix());
+        if (op_var[0]->type->is_vector()) {
+           do_mul_vec_mat(result_var, op_var[0], op_var[1]);
+        } else {
+           assert(op_var[0]->type->is_scalar());
+           do_mul_mat_scalar(result_var, op_var[1], op_var[0]);
+        }
+      }
+      break;
+
+   case ir_binop_equal:
+   case ir_binop_nequal:
+      do_equal_mat_mat(result_var, op_var[1], op_var[0],
+                      (orig_expr->operation == ir_binop_equal));
+      break;
+
+   default:
+      printf("FINISHME: Handle matrix operation for %s\n",
+            orig_expr->operator_string());
+      abort();
+   }
+   orig_assign->remove();
+   this->made_progress = true;
+
+   return visit_continue;
+}
diff --git a/src/glsl/ir_mod_to_fract.cpp b/src/glsl/ir_mod_to_fract.cpp
new file mode 100644 (file)
index 0000000..71c9472
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_mod_to_floor.cpp
+ *
+ * Breaks an ir_unop_mod expression down to (op1 * fract(op0 / op1))
+ *
+ * Many GPUs don't have a MOD instruction (945 and 965 included), and
+ * if we have to break it down like this anyway, it gives an
+ * opportunity to do things like constant fold the (1.0 / op1) easily.
+ */
+
+#include "ir.h"
+
+class ir_mod_to_fract_visitor : public ir_hierarchical_visitor {
+public:
+   ir_mod_to_fract_visitor()
+   {
+      this->made_progress = false;
+   }
+
+   ir_visitor_status visit_leave(ir_expression *);
+
+   bool made_progress;
+};
+
+bool
+do_mod_to_fract(exec_list *instructions)
+{
+   ir_mod_to_fract_visitor v;
+
+   visit_list_elements(&v, instructions);
+   return v.made_progress;
+}
+
+ir_visitor_status
+ir_mod_to_fract_visitor::visit_leave(ir_expression *ir)
+{
+   if (ir->operation != ir_binop_mod)
+      return visit_continue;
+
+   ir_variable *temp = new(ir) ir_variable(ir->operands[1]->type, "mod_b",
+                                          ir_var_temporary);
+   this->base_ir->insert_before(temp);
+
+   ir_assignment *assign;
+   ir_rvalue *expr;
+
+   assign = new(ir) ir_assignment(new(ir) ir_dereference_variable(temp),
+                                 ir->operands[1], NULL);
+   this->base_ir->insert_before(assign);
+
+   expr = new(ir) ir_expression(ir_binop_div,
+                               ir->operands[0]->type,
+                               ir->operands[0],
+                               new(ir) ir_dereference_variable(temp));
+
+   expr = new(ir) ir_expression(ir_unop_fract,
+                               ir->operands[0]->type,
+                               expr,
+                               NULL);
+
+   ir->operation = ir_binop_mul;
+   ir->operands[0] = new(ir) ir_dereference_variable(temp);
+   ir->operands[1] = expr;
+   this->made_progress = true;
+
+   return visit_continue;
+}
diff --git a/src/glsl/ir_noop_swizzle.cpp b/src/glsl/ir_noop_swizzle.cpp
new file mode 100644 (file)
index 0000000..b78c87b
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_noop_swizzle.cpp
+ *
+ * If a swizzle doesn't change the order or count of components, then
+ * remove the swizzle so that other optimization passes see the value
+ * behind it.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_rvalue_visitor.h"
+#include "ir_print_visitor.h"
+#include "glsl_types.h"
+
+class ir_noop_swizzle_visitor : public ir_rvalue_visitor {
+public:
+   ir_noop_swizzle_visitor()
+   {
+      this->progress = false;
+   }
+
+   void handle_rvalue(ir_rvalue **rvalue);
+   bool progress;
+};
+
+void
+ir_noop_swizzle_visitor::handle_rvalue(ir_rvalue **rvalue)
+{
+   if (!*rvalue)
+      return;
+
+   ir_swizzle *swiz = (*rvalue)->as_swizzle();
+   if (!swiz || swiz->type != swiz->val->type)
+      return;
+
+   int elems = swiz->val->type->vector_elements;
+   if (swiz->mask.x != 0)
+      return;
+   if (elems >= 2 && swiz->mask.y != 1)
+      return;
+   if (elems >= 3 && swiz->mask.z != 1)
+      return;
+   if (elems >= 4 && swiz->mask.w != 1)
+      return;
+
+   this->progress = true;
+   *rvalue = swiz->val;
+}
+
+bool
+do_noop_swizzle(exec_list *instructions)
+{
+   ir_noop_swizzle_visitor v;
+   visit_list_elements(&v, instructions);
+
+   return v.progress;
+}
diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h
new file mode 100644 (file)
index 0000000..33f4bc7
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+
+/**
+ * \file ir_optimization.h
+ *
+ * Prototypes for optimization passes to be called by the compiler and drivers.
+ */
+
+bool do_common_optimization(exec_list *ir, bool linked);
+
+bool do_algebraic(exec_list *instructions);
+bool do_constant_folding(exec_list *instructions);
+bool do_constant_variable(exec_list *instructions);
+bool do_constant_variable_unlinked(exec_list *instructions);
+bool do_copy_propagation(exec_list *instructions);
+bool do_constant_propagation(exec_list *instructions);
+bool do_dead_code(exec_list *instructions);
+bool do_dead_code_local(exec_list *instructions);
+bool do_dead_code_unlinked(exec_list *instructions);
+bool do_dead_functions(exec_list *instructions);
+bool do_div_to_mul_rcp(exec_list *instructions);
+bool do_explog_to_explog2(exec_list *instructions);
+bool do_function_inlining(exec_list *instructions);
+bool do_if_return(exec_list *instructions);
+bool do_if_simplification(exec_list *instructions);
+bool do_if_to_cond_assign(exec_list *instructions);
+bool do_mat_op_to_vec(exec_list *instructions);
+bool do_mod_to_fract(exec_list *instructions);
+bool do_noop_swizzle(exec_list *instructions);
+bool do_structure_splitting(exec_list *instructions);
+bool do_sub_to_add_neg(exec_list *instructions);
+bool do_swizzle_swizzle(exec_list *instructions);
+bool do_tree_grafting(exec_list *instructions);
+bool do_vec_index_to_cond_assign(exec_list *instructions);
+bool do_vec_index_to_swizzle(exec_list *instructions);
diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp
new file mode 100644 (file)
index 0000000..f47ad87
--- /dev/null
@@ -0,0 +1,459 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 "ir_print_visitor.h"
+#include "glsl_types.h"
+#include "glsl_parser_extras.h"
+
+static void print_type(const glsl_type *t);
+
+void
+ir_instruction::print(void) const
+{
+   ir_instruction *deconsted = const_cast<ir_instruction *>(this);
+
+   ir_print_visitor v;
+   deconsted->accept(&v);
+}
+
+void
+_mesa_print_ir(exec_list *instructions,
+              struct _mesa_glsl_parse_state *state)
+{
+   if (state) {
+      for (unsigned i = 0; i < state->num_user_structures; i++) {
+        const glsl_type *const s = state->user_structures[i];
+
+        printf("(structure (%s) (%s@%p) (%u) (\n",
+               s->name, s->name, (void *) s, s->length);
+
+        for (unsigned j = 0; j < s->length; j++) {
+           printf("\t((");
+           print_type(s->fields.structure[j].type);
+           printf(")(%s))\n", s->fields.structure[j].name);
+        }
+
+        printf(")\n");
+      }
+   }
+
+   printf("(\n");
+   foreach_iter(exec_list_iterator, iter, *instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      ir->print();
+      if (ir->ir_type != ir_type_function)
+        printf("\n");
+   }
+   printf("\n)");
+}
+
+
+void ir_print_visitor::indent(void)
+{
+   for (int i = 0; i < indentation; i++)
+      printf("  ");
+}
+
+static void
+print_type(const glsl_type *t)
+{
+   if (t->base_type == GLSL_TYPE_ARRAY) {
+      printf("(array ");
+      print_type(t->fields.array);
+      printf(" %u)", t->length);
+   } else if ((t->base_type == GLSL_TYPE_STRUCT)
+             && (strncmp("gl_", t->name, 3) != 0)) {
+      printf("%s@%p", t->name, (void *) t);
+   } else {
+      printf("%s", t->name);
+   }
+}
+
+
+void ir_print_visitor::visit(ir_variable *ir)
+{
+   printf("(declare ");
+
+   const char *const cent = (ir->centroid) ? "centroid " : "";
+   const char *const inv = (ir->invariant) ? "invariant " : "";
+   const char *const mode[] = { "", "uniform ", "in ", "out ", "inout ",
+                               "temporary " };
+   const char *const interp[] = { "", "flat", "noperspective" };
+
+   printf("(%s%s%s%s) ",
+         cent, inv, mode[ir->mode], interp[ir->interpolation]);
+
+   print_type(ir->type);
+   printf(" %s@%p)", ir->name, (void *) ir);
+}
+
+
+void ir_print_visitor::visit(ir_function_signature *ir)
+{
+   printf("(signature ");
+   indentation++;
+
+   print_type(ir->return_type);
+   printf("\n");
+   indent();
+
+   printf("(parameters\n");
+   indentation++;
+
+   foreach_iter(exec_list_iterator, iter, ir->parameters) {
+      ir_variable *const inst = (ir_variable *) iter.get();
+
+      indent();
+      inst->accept(this);
+      printf("\n");
+   }
+   indentation--;
+
+   indent();
+   printf(")\n");
+
+   indent();
+
+   printf("(\n");
+   indentation++;
+
+   foreach_iter(exec_list_iterator, iter, ir->body) {
+      ir_instruction *const inst = (ir_instruction *) iter.get();
+
+      indent();
+      inst->accept(this);
+      printf("\n");
+   }
+   indentation--;
+   indent();
+   printf("))\n");
+   indentation--;
+}
+
+
+void ir_print_visitor::visit(ir_function *ir)
+{
+   /* Don't print built-in functions as part of the IR. */
+   if (ir->is_builtin)
+      return;
+
+   printf("(function %s\n", ir->name);
+   indentation++;
+   foreach_iter(exec_list_iterator, iter, *ir) {
+      ir_function_signature *const sig = (ir_function_signature *) iter.get();
+
+      indent();
+      sig->accept(this);
+      printf("\n");
+   }
+   indentation--;
+   indent();
+   printf(")\n\n");
+}
+
+
+void ir_print_visitor::visit(ir_expression *ir)
+{
+   printf("(expression ");
+
+   print_type(ir->type);
+
+   printf(" %s ", ir->operator_string());
+
+   if (ir->operands[0])
+      ir->operands[0]->accept(this);
+
+   if (ir->operands[1])
+      ir->operands[1]->accept(this);
+   printf(") ");
+}
+
+
+void ir_print_visitor::visit(ir_texture *ir)
+{
+   printf("(%s ", ir->opcode_string());
+
+   ir->sampler->accept(this);
+   printf(" ");
+
+   ir->coordinate->accept(this);
+
+   printf(" (%d %d %d) ", ir->offsets[0], ir->offsets[1], ir->offsets[2]);
+
+   if (ir->op != ir_txf) {
+      if (ir->projector)
+        ir->projector->accept(this);
+      else
+        printf("1");
+
+      if (ir->shadow_comparitor) {
+        printf(" ");
+        ir->shadow_comparitor->accept(this);
+      } else {
+        printf(" ()");
+      }
+   }
+
+   printf(" ");
+   switch (ir->op)
+   {
+   case ir_tex:
+      break;
+   case ir_txb:
+      ir->lod_info.bias->accept(this);
+      break;
+   case ir_txl:
+   case ir_txf:
+      ir->lod_info.lod->accept(this);
+      break;
+   case ir_txd:
+      printf("(");
+      ir->lod_info.grad.dPdx->accept(this);
+      printf(" ");
+      ir->lod_info.grad.dPdy->accept(this);
+      printf(")");
+      break;
+   };
+   printf(")");
+}
+
+
+void ir_print_visitor::visit(ir_swizzle *ir)
+{
+   const unsigned swiz[4] = {
+      ir->mask.x,
+      ir->mask.y,
+      ir->mask.z,
+      ir->mask.w,
+   };
+
+   printf("(swiz ");
+   for (unsigned i = 0; i < ir->mask.num_components; i++) {
+      printf("%c", "xyzw"[swiz[i]]);
+   }
+   printf(" ");
+   ir->val->accept(this);
+   printf(")");
+}
+
+
+void ir_print_visitor::visit(ir_dereference_variable *ir)
+{
+   ir_variable *var = ir->variable_referenced();
+   printf("(var_ref %s@%p) ", var->name, (void *) var);
+}
+
+
+void ir_print_visitor::visit(ir_dereference_array *ir)
+{
+   printf("(array_ref ");
+   ir->array->accept(this);
+   ir->array_index->accept(this);
+   printf(") ");
+}
+
+
+void ir_print_visitor::visit(ir_dereference_record *ir)
+{
+   printf("(record_ref ");
+   ir->record->accept(this);
+   printf(" %s) ", ir->field);
+}
+
+
+void ir_print_visitor::visit(ir_assignment *ir)
+{
+   printf("(assign ");
+
+   if (ir->condition)
+      ir->condition->accept(this);
+   else
+      printf("(constant bool (1))");
+
+
+   char mask[5];
+   unsigned j = 0;
+
+   for (unsigned i = 0; i < 4; i++) {
+      if ((ir->write_mask & (1 << i)) != 0) {
+        mask[j] = "xyzw"[i];
+        j++;
+      }
+   }
+   mask[j] = '\0';
+
+   printf(" (%s) ", mask);
+
+   ir->lhs->accept(this);
+
+   printf(" ");
+
+   ir->rhs->accept(this);
+   printf(") ");
+}
+
+
+void ir_print_visitor::visit(ir_constant *ir)
+{
+   const glsl_type *const base_type = ir->type->get_base_type();
+
+   printf("(constant ");
+   print_type(ir->type);
+   printf(" (");
+
+   if (ir->type->is_array()) {
+      for (unsigned i = 0; i < ir->type->length; i++)
+        ir->get_array_element(i)->accept(this);
+   } else {
+      for (unsigned i = 0; i < ir->type->components(); i++) {
+        if (i != 0)
+           printf(" ");
+        switch (base_type->base_type) {
+        case GLSL_TYPE_UINT:  printf("%u", ir->value.u[i]); break;
+        case GLSL_TYPE_INT:   printf("%d", ir->value.i[i]); break;
+        case GLSL_TYPE_FLOAT: printf("%f", ir->value.f[i]); break;
+        case GLSL_TYPE_BOOL:  printf("%d", ir->value.b[i]); break;
+        default: assert(0);
+        }
+      }
+   }
+   printf(")) ");
+}
+
+
+void
+ir_print_visitor::visit(ir_call *ir)
+{
+   printf("(call %s (", ir->callee_name());
+   foreach_iter(exec_list_iterator, iter, *ir) {
+      ir_instruction *const inst = (ir_instruction *) iter.get();
+
+      inst->accept(this);
+   }
+   printf("))\n");
+}
+
+
+void
+ir_print_visitor::visit(ir_return *ir)
+{
+   printf("(return");
+
+   ir_rvalue *const value = ir->get_value();
+   if (value) {
+      printf(" ");
+      value->accept(this);
+   }
+
+   printf(")");
+}
+
+
+void
+ir_print_visitor::visit(ir_discard *ir)
+{
+   printf("(discard ");
+
+   if (ir->condition != NULL) {
+      printf(" ");
+      ir->condition->accept(this);
+   }
+
+   printf(")");
+}
+
+
+void
+ir_print_visitor::visit(ir_if *ir)
+{
+   printf("(if ");
+   ir->condition->accept(this);
+
+   printf("(\n");
+   indentation++;
+
+   foreach_iter(exec_list_iterator, iter, ir->then_instructions) {
+      ir_instruction *const inst = (ir_instruction *) iter.get();
+
+      indent();
+      inst->accept(this);
+      printf("\n");
+   }
+
+   indentation--;
+   indent();
+   printf(")\n");
+
+   indent();
+   printf("(\n");
+   indentation++;
+
+   foreach_iter(exec_list_iterator, iter, ir->else_instructions) {
+      ir_instruction *const inst = (ir_instruction *) iter.get();
+
+      indent();
+      inst->accept(this);
+      printf("\n");
+   }
+   indentation--;
+   indent();
+   printf("))\n");
+}
+
+
+void
+ir_print_visitor::visit(ir_loop *ir)
+{
+   printf("(loop (");
+   if (ir->counter != NULL)
+      ir->counter->accept(this);
+   printf(") (");
+   if (ir->from != NULL)
+      ir->from->accept(this);
+   printf(") (");
+   if (ir->to != NULL)
+      ir->to->accept(this);
+   printf(") (");
+   if (ir->increment != NULL)
+      ir->increment->accept(this);
+   printf(") (\n");
+   indentation++;
+
+   foreach_iter(exec_list_iterator, iter, ir->body_instructions) {
+      ir_instruction *const inst = (ir_instruction *) iter.get();
+
+      indent();
+      inst->accept(this);
+      printf("\n");
+   }
+   indentation--;
+   indent();
+   printf("))\n");
+}
+
+
+void
+ir_print_visitor::visit(ir_loop_jump *ir)
+{
+   printf("%s", ir->is_break() ? "break" : "continue");
+}
diff --git a/src/glsl/ir_print_visitor.h b/src/glsl/ir_print_visitor.h
new file mode 100644 (file)
index 0000000..4feeb8c
--- /dev/null
@@ -0,0 +1,83 @@
+/* -*- c++ -*- */
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+#pragma once
+#ifndef IR_PRINT_VISITOR_H
+#define IR_PRINT_VISITOR_H
+
+#include "ir.h"
+#include "ir_visitor.h"
+
+extern void _mesa_print_ir(exec_list *instructions,
+                          struct _mesa_glsl_parse_state *state);
+
+/**
+ * Abstract base class of visitors of IR instruction trees
+ */
+class ir_print_visitor : public ir_visitor {
+public:
+   ir_print_visitor()
+   {
+      indentation = 0;
+   }
+
+   virtual ~ir_print_visitor()
+   {
+      /* empty */
+   }
+
+   void indent(void);
+
+   /**
+    * \name Visit methods
+    *
+    * As typical for the visitor pattern, there must be one \c visit method for
+    * each concrete subclass of \c ir_instruction.  Virtual base classes within
+    * the hierarchy should not have \c visit methods.
+    */
+   /*@{*/
+   virtual void visit(ir_variable *);
+   virtual void visit(ir_function_signature *);
+   virtual void visit(ir_function *);
+   virtual void visit(ir_expression *);
+   virtual void visit(ir_texture *);
+   virtual void visit(ir_swizzle *);
+   virtual void visit(ir_dereference_variable *);
+   virtual void visit(ir_dereference_array *);
+   virtual void visit(ir_dereference_record *);
+   virtual void visit(ir_assignment *);
+   virtual void visit(ir_constant *);
+   virtual void visit(ir_call *);
+   virtual void visit(ir_return *);
+   virtual void visit(ir_discard *);
+   virtual void visit(ir_if *);
+   virtual void visit(ir_loop *);
+   virtual void visit(ir_loop_jump *);
+   /*@}*/
+
+private:
+   int indentation;
+};
+
+#endif /* IR_PRINT_VISITOR_H */
diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp
new file mode 100644 (file)
index 0000000..e57e03c
--- /dev/null
@@ -0,0 +1,1088 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 <cstdarg>
+
+extern "C" {
+#include <talloc.h>
+}
+
+#include "ir_reader.h"
+#include "glsl_parser_extras.h"
+#include "glsl_types.h"
+#include "s_expression.h"
+
+static void ir_read_error(_mesa_glsl_parse_state *, s_expression *,
+                         const char *fmt, ...);
+static const glsl_type *read_type(_mesa_glsl_parse_state *, s_expression *);
+
+static void scan_for_prototypes(_mesa_glsl_parse_state *, exec_list *,
+                               s_expression *);
+static ir_function *read_function(_mesa_glsl_parse_state *, s_list *,
+                                 bool skip_body);
+static void read_function_sig(_mesa_glsl_parse_state *, ir_function *,
+                             s_list *, bool skip_body);
+
+static void read_instructions(_mesa_glsl_parse_state *, exec_list *,
+                             s_expression *, ir_loop *);
+static ir_instruction *read_instruction(_mesa_glsl_parse_state *,
+                                       s_expression *, ir_loop *);
+static ir_variable *read_declaration(_mesa_glsl_parse_state *, s_list *);
+static ir_if *read_if(_mesa_glsl_parse_state *, s_list *, ir_loop *);
+static ir_loop *read_loop(_mesa_glsl_parse_state *st, s_list *list);
+static ir_return *read_return(_mesa_glsl_parse_state *, s_list *);
+
+static ir_rvalue *read_rvalue(_mesa_glsl_parse_state *, s_expression *);
+static ir_assignment *read_assignment(_mesa_glsl_parse_state *, s_list *);
+static ir_expression *read_expression(_mesa_glsl_parse_state *, s_list *);
+static ir_call *read_call(_mesa_glsl_parse_state *, s_list *);
+static ir_swizzle *read_swizzle(_mesa_glsl_parse_state *, s_list *);
+static ir_constant *read_constant(_mesa_glsl_parse_state *, s_list *);
+static ir_texture *read_texture(_mesa_glsl_parse_state *, s_list *);
+
+static ir_dereference *read_dereference(_mesa_glsl_parse_state *,
+                                       s_expression *);
+static ir_dereference *read_var_ref(_mesa_glsl_parse_state *, s_list *);
+static ir_dereference *read_array_ref(_mesa_glsl_parse_state *, s_list *);
+static ir_dereference *read_record_ref(_mesa_glsl_parse_state *, s_list *);
+
+void
+_mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions,
+                  const char *src, bool scan_for_protos)
+{
+   s_expression *expr = s_expression::read_expression(state, src);
+   if (expr == NULL) {
+      ir_read_error(state, NULL, "couldn't parse S-Expression.");
+      return;
+   }
+   
+   if (scan_for_protos) {
+      scan_for_prototypes(state, instructions, expr);
+      if (state->error)
+        return;
+   }
+
+   read_instructions(state, instructions, expr, NULL);
+   talloc_free(expr);
+}
+
+static void
+ir_read_error(_mesa_glsl_parse_state *state, s_expression *expr,
+             const char *fmt, ...)
+{
+   va_list ap;
+
+   state->error = true;
+
+   state->info_log = talloc_strdup_append(state->info_log, "error: ");
+
+   va_start(ap, fmt);
+   state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap);
+   va_end(ap);
+   state->info_log = talloc_strdup_append(state->info_log, "\n");
+
+   if (expr != NULL) {
+      state->info_log = talloc_strdup_append(state->info_log,
+                                            "...in this context:\n   ");
+      expr->print();
+      state->info_log = talloc_strdup_append(state->info_log, "\n\n");
+   }
+}
+
+static const glsl_type *
+read_type(_mesa_glsl_parse_state *st, s_expression *expr)
+{
+   s_list *list = SX_AS_LIST(expr);
+   if (list != NULL) {
+      s_symbol *type_sym = SX_AS_SYMBOL(list->subexpressions.get_head());
+      if (type_sym == NULL) {
+        ir_read_error(st, expr, "expected type (array ...) or (struct ...)");
+        return NULL;
+      }
+      if (strcmp(type_sym->value(), "array") == 0) {
+        if (list->length() != 3) {
+           ir_read_error(st, expr, "expected type (array <type> <int>)");
+           return NULL;
+        }
+
+        // Read base type
+        s_expression *base_expr = (s_expression*) type_sym->next;
+        const glsl_type *base_type = read_type(st, base_expr);
+        if (base_type == NULL) {
+           ir_read_error(st, NULL, "when reading base type of array");
+           return NULL;
+        }
+
+        // Read array size
+        s_int *size = SX_AS_INT(base_expr->next);
+        if (size == NULL) {
+           ir_read_error(st, expr, "found non-integer array size");
+           return NULL;
+        }
+
+        return glsl_type::get_array_instance(base_type, size->value());
+      } else if (strcmp(type_sym->value(), "struct") == 0) {
+        assert(false); // FINISHME
+      } else {
+        ir_read_error(st, expr, "expected (array ...) or (struct ...); "
+                                "found (%s ...)", type_sym->value());
+        return NULL;
+      }
+   }
+   
+   s_symbol *type_sym = SX_AS_SYMBOL(expr);
+   if (type_sym == NULL) {
+      ir_read_error(st, expr, "expected <type> (symbol or list)");
+      return NULL;
+   }
+
+   const glsl_type *type = st->symbols->get_type(type_sym->value());
+   if (type == NULL)
+      ir_read_error(st, expr, "invalid type: %s", type_sym->value());
+
+   return type;
+}
+
+
+static void
+scan_for_prototypes(_mesa_glsl_parse_state *st, exec_list *instructions,
+                   s_expression *expr)
+{
+   s_list *list = SX_AS_LIST(expr);
+   if (list == NULL) {
+      ir_read_error(st, expr, "Expected (<instruction> ...); found an atom.");
+      return;
+   }
+
+   foreach_iter(exec_list_iterator, it, list->subexpressions) {
+      s_list *sub = SX_AS_LIST(it.get());
+      if (sub == NULL)
+        continue; // not a (function ...); ignore it.
+
+      s_symbol *tag = SX_AS_SYMBOL(sub->subexpressions.get_head());
+      if (tag == NULL || strcmp(tag->value(), "function") != 0)
+        continue; // not a (function ...); ignore it.
+
+      ir_function *f = read_function(st, sub, true);
+      if (f == NULL)
+        return;
+      instructions->push_tail(f);
+   }
+}
+
+static ir_function *
+read_function(_mesa_glsl_parse_state *st, s_list *list, bool skip_body)
+{
+   void *ctx = st;
+   bool added = false;
+   if (list->length() < 3) {
+      ir_read_error(st, list, "Expected (function <name> (signature ...) ...)");
+      return NULL;
+   }
+
+   s_symbol *name = SX_AS_SYMBOL(list->subexpressions.head->next);
+   if (name == NULL) {
+      ir_read_error(st, list, "Expected (function <name> ...)");
+      return NULL;
+   }
+
+   ir_function *f = st->symbols->get_function(name->value());
+   if (f == NULL) {
+      f = new(ctx) ir_function(name->value());
+      f->is_builtin = true;
+      added = st->symbols->add_function(f->name, f);
+      assert(added);
+   }
+
+   exec_list_iterator it = list->subexpressions.iterator();
+   it.next(); // skip "function" tag
+   it.next(); // skip function name
+   for (/* nothing */; it.has_next(); it.next()) {
+      s_list *siglist = SX_AS_LIST(it.get());
+      if (siglist == NULL) {
+        ir_read_error(st, list, "Expected (function (signature ...) ...)");
+        return NULL;
+      }
+
+      s_symbol *tag = SX_AS_SYMBOL(siglist->subexpressions.get_head());
+      if (tag == NULL || strcmp(tag->value(), "signature") != 0) {
+        ir_read_error(st, siglist, "Expected (signature ...)");
+        return NULL;
+      }
+
+      read_function_sig(st, f, siglist, skip_body);
+   }
+   return added ? f : NULL;
+}
+
+static void
+read_function_sig(_mesa_glsl_parse_state *st, ir_function *f, s_list *list,
+                 bool skip_body)
+{
+   void *ctx = st;
+   if (list->length() != 4) {
+      ir_read_error(st, list, "Expected (signature <type> (parameters ...) "
+                             "(<instruction> ...))");
+      return;
+   }
+
+   s_expression *type_expr = (s_expression*) list->subexpressions.head->next;
+   const glsl_type *return_type = read_type(st, type_expr);
+   if (return_type == NULL)
+      return;
+
+   s_list *paramlist = SX_AS_LIST(type_expr->next);
+   s_list *body_list = SX_AS_LIST(paramlist->next);
+   if (paramlist == NULL || body_list == NULL) {
+      ir_read_error(st, list, "Expected (signature <type> (parameters ...) "
+                             "(<instruction> ...))");
+      return;
+   }
+   s_symbol *paramtag = SX_AS_SYMBOL(paramlist->subexpressions.get_head());
+   if (paramtag == NULL || strcmp(paramtag->value(), "parameters") != 0) {
+      ir_read_error(st, paramlist, "Expected (parameters ...)");
+      return;
+   }
+
+   // Read the parameters list into a temporary place.
+   exec_list hir_parameters;
+   st->symbols->push_scope();
+
+   exec_list_iterator it = paramlist->subexpressions.iterator();
+   for (it.next() /* skip "parameters" */; it.has_next(); it.next()) {
+      s_list *decl = SX_AS_LIST(it.get());
+      ir_variable *var = read_declaration(st, decl);
+      if (var == NULL)
+        return;
+
+      hir_parameters.push_tail(var);
+   }
+
+   ir_function_signature *sig = f->exact_matching_signature(&hir_parameters);
+   if (sig == NULL && skip_body) {
+      /* If scanning for prototypes, generate a new signature. */
+      sig = new(ctx) ir_function_signature(return_type);
+      f->add_signature(sig);
+   } else if (sig != NULL) {
+      const char *badvar = sig->qualifiers_match(&hir_parameters);
+      if (badvar != NULL) {
+        ir_read_error(st, list, "function `%s' parameter `%s' qualifiers "
+                      "don't match prototype", f->name, badvar);
+        return;
+      }
+
+      if (sig->return_type != return_type) {
+        ir_read_error(st, list, "function `%s' return type doesn't "
+                      "match prototype", f->name);
+        return;
+      }
+   } else {
+      /* No prototype for this body exists - skip it. */
+      st->symbols->pop_scope();
+      return;
+   }
+   assert(sig != NULL);
+
+   sig->replace_parameters(&hir_parameters);
+
+   if (!skip_body && !body_list->subexpressions.is_empty()) {
+      if (sig->is_defined) {
+        ir_read_error(st, list, "function %s redefined", f->name);
+        return;
+      }
+      read_instructions(st, &sig->body, body_list, NULL);
+      sig->is_defined = true;
+   }
+
+   st->symbols->pop_scope();
+}
+
+static void
+read_instructions(_mesa_glsl_parse_state *st, exec_list *instructions,
+                 s_expression *expr, ir_loop *loop_ctx)
+{
+   // Read in a list of instructions
+   s_list *list = SX_AS_LIST(expr);
+   if (list == NULL) {
+      ir_read_error(st, expr, "Expected (<instruction> ...); found an atom.");
+      return;
+   }
+
+   foreach_iter(exec_list_iterator, it, list->subexpressions) {
+      s_expression *sub = (s_expression*) it.get();
+      ir_instruction *ir = read_instruction(st, sub, loop_ctx);
+      if (ir != NULL)
+        instructions->push_tail(ir);
+   }
+}
+
+
+static ir_instruction *
+read_instruction(_mesa_glsl_parse_state *st, s_expression *expr,
+                ir_loop *loop_ctx)
+{
+   void *ctx = st;
+   s_symbol *symbol = SX_AS_SYMBOL(expr);
+   if (symbol != NULL) {
+      if (strcmp(symbol->value(), "break") == 0 && loop_ctx != NULL)
+        return new(ctx) ir_loop_jump(ir_loop_jump::jump_break);
+      if (strcmp(symbol->value(), "continue") == 0 && loop_ctx != NULL)
+        return new(ctx) ir_loop_jump(ir_loop_jump::jump_continue);
+   }
+
+   s_list *list = SX_AS_LIST(expr);
+   if (list == NULL || list->subexpressions.is_empty()) {
+      ir_read_error(st, expr, "Invalid instruction.\n");
+      return NULL;
+   }
+
+   s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head());
+   if (tag == NULL) {
+      ir_read_error(st, expr, "expected instruction tag");
+      return NULL;
+   }
+
+   ir_instruction *inst = NULL;
+   if (strcmp(tag->value(), "declare") == 0) {
+      inst = read_declaration(st, list);
+   } else if (strcmp(tag->value(), "assign") == 0) {
+      inst = read_assignment(st, list);
+   } else if (strcmp(tag->value(), "if") == 0) {
+      inst = read_if(st, list, loop_ctx);
+   } else if (strcmp(tag->value(), "loop") == 0) {
+      inst = read_loop(st, list);
+   } else if (strcmp(tag->value(), "return") == 0) {
+      inst = read_return(st, list);
+   } else if (strcmp(tag->value(), "function") == 0) {
+      inst = read_function(st, list, false);
+   } else {
+      inst = read_rvalue(st, list);
+      if (inst == NULL)
+        ir_read_error(st, NULL, "when reading instruction");
+   }
+   return inst;
+}
+
+
+static ir_variable *
+read_declaration(_mesa_glsl_parse_state *st, s_list *list)
+{
+   void *ctx = st;
+   if (list->length() != 4) {
+      ir_read_error(st, list, "expected (declare (<qualifiers>) <type> "
+                             "<name>)");
+      return NULL;
+   }
+
+   s_list *quals = SX_AS_LIST(list->subexpressions.head->next);
+   if (quals == NULL) {
+      ir_read_error(st, list, "expected a list of variable qualifiers");
+      return NULL;
+   }
+
+   s_expression *type_expr = (s_expression*) quals->next;
+   const glsl_type *type = read_type(st, type_expr);
+   if (type == NULL)
+      return NULL;
+
+   s_symbol *var_name = SX_AS_SYMBOL(type_expr->next);
+   if (var_name == NULL) {
+      ir_read_error(st, list, "expected variable name, found non-symbol");
+      return NULL;
+   }
+
+   ir_variable *var = new(ctx) ir_variable(type, var_name->value(),
+                                          ir_var_auto);
+
+   foreach_iter(exec_list_iterator, it, quals->subexpressions) {
+      s_symbol *qualifier = SX_AS_SYMBOL(it.get());
+      if (qualifier == NULL) {
+        ir_read_error(st, list, "qualifier list must contain only symbols");
+        delete var;
+        return NULL;
+      }
+
+      // FINISHME: Check for duplicate/conflicting qualifiers.
+      if (strcmp(qualifier->value(), "centroid") == 0) {
+        var->centroid = 1;
+      } else if (strcmp(qualifier->value(), "invariant") == 0) {
+        var->invariant = 1;
+      } else if (strcmp(qualifier->value(), "uniform") == 0) {
+        var->mode = ir_var_uniform;
+      } else if (strcmp(qualifier->value(), "auto") == 0) {
+        var->mode = ir_var_auto;
+      } else if (strcmp(qualifier->value(), "in") == 0) {
+        var->mode = ir_var_in;
+      } else if (strcmp(qualifier->value(), "out") == 0) {
+        var->mode = ir_var_out;
+      } else if (strcmp(qualifier->value(), "inout") == 0) {
+        var->mode = ir_var_inout;
+      } else if (strcmp(qualifier->value(), "smooth") == 0) {
+        var->interpolation = ir_var_smooth;
+      } else if (strcmp(qualifier->value(), "flat") == 0) {
+        var->interpolation = ir_var_flat;
+      } else if (strcmp(qualifier->value(), "noperspective") == 0) {
+        var->interpolation = ir_var_noperspective;
+      } else {
+        ir_read_error(st, list, "unknown qualifier: %s", qualifier->value());
+        delete var;
+        return NULL;
+      }
+   }
+
+   // Add the variable to the symbol table
+   st->symbols->add_variable(var->name, var);
+
+   return var;
+}
+
+
+static ir_if *
+read_if(_mesa_glsl_parse_state *st, s_list *list, ir_loop *loop_ctx)
+{
+   void *ctx = st;
+   if (list->length() != 4) {
+      ir_read_error(st, list, "expected (if <condition> (<then> ...) "
+                          "(<else> ...))");
+      return NULL;
+   }
+
+   s_expression *cond_expr = (s_expression*) list->subexpressions.head->next;
+   ir_rvalue *condition = read_rvalue(st, cond_expr);
+   if (condition == NULL) {
+      ir_read_error(st, NULL, "when reading condition of (if ...)");
+      return NULL;
+   }
+
+   s_expression *then_expr = (s_expression*) cond_expr->next;
+   s_expression *else_expr = (s_expression*) then_expr->next;
+
+   ir_if *iff = new(ctx) ir_if(condition);
+
+   read_instructions(st, &iff->then_instructions, then_expr, loop_ctx);
+   read_instructions(st, &iff->else_instructions, else_expr, loop_ctx);
+   if (st->error) {
+      delete iff;
+      iff = NULL;
+   }
+   return iff;
+}
+
+
+static ir_loop *
+read_loop(_mesa_glsl_parse_state *st, s_list *list)
+{
+   void *ctx = st;
+   if (list->length() != 6) {
+      ir_read_error(st, list, "expected (loop <counter> <from> <to> "
+                             "<increment> <body>)");
+      return NULL;
+   }
+
+   s_expression *count_expr = (s_expression*) list->subexpressions.head->next;
+   s_expression *from_expr  = (s_expression*) count_expr->next;
+   s_expression *to_expr    = (s_expression*) from_expr->next;
+   s_expression *inc_expr   = (s_expression*) to_expr->next;
+   s_expression *body_expr  = (s_expression*) inc_expr->next;
+
+   // FINISHME: actually read the count/from/to fields.
+
+   ir_loop *loop = new(ctx) ir_loop;
+   read_instructions(st, &loop->body_instructions, body_expr, loop);
+   if (st->error) {
+      delete loop;
+      loop = NULL;
+   }
+   return loop;
+}
+
+
+static ir_return *
+read_return(_mesa_glsl_parse_state *st, s_list *list)
+{
+   void *ctx = st;
+   if (list->length() != 2) {
+      ir_read_error(st, list, "expected (return <rvalue>)");
+      return NULL;
+   }
+
+   s_expression *expr = (s_expression*) list->subexpressions.head->next;
+
+   ir_rvalue *retval = read_rvalue(st, expr);
+   if (retval == NULL) {
+      ir_read_error(st, NULL, "when reading return value");
+      return NULL;
+   }
+
+   return new(ctx) ir_return(retval);
+}
+
+
+static ir_rvalue *
+read_rvalue(_mesa_glsl_parse_state *st, s_expression *expr)
+{
+   s_list *list = SX_AS_LIST(expr);
+   if (list == NULL || list->subexpressions.is_empty())
+      return NULL;
+
+   s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head());
+   if (tag == NULL) {
+      ir_read_error(st, expr, "expected rvalue tag");
+      return NULL;
+   }
+
+   ir_rvalue *rvalue = read_dereference(st, list);
+   if (rvalue != NULL || st->error)
+      return rvalue;
+   else if (strcmp(tag->value(), "swiz") == 0) {
+      rvalue = read_swizzle(st, list);
+   } else if (strcmp(tag->value(), "expression") == 0) {
+      rvalue = read_expression(st, list);
+   } else if (strcmp(tag->value(), "call") == 0) {
+      rvalue = read_call(st, list);
+   } else if (strcmp(tag->value(), "constant") == 0) {
+      rvalue = read_constant(st, list);
+   } else {
+      rvalue = read_texture(st, list);
+      if (rvalue == NULL && !st->error)
+        ir_read_error(st, expr, "unrecognized rvalue tag: %s", tag->value());
+   }
+
+   return rvalue;
+}
+
+static ir_assignment *
+read_assignment(_mesa_glsl_parse_state *st, s_list *list)
+{
+   void *ctx = st;
+   if (list->length() != 4) {
+      ir_read_error(st, list, "expected (assign <condition> <lhs> <rhs>)");
+      return NULL;
+   }
+
+   s_expression *cond_expr = (s_expression*) list->subexpressions.head->next;
+   s_expression *lhs_expr  = (s_expression*) cond_expr->next;
+   s_expression *rhs_expr  = (s_expression*) lhs_expr->next;
+
+   // FINISHME: Deal with "true" condition
+   ir_rvalue *condition = read_rvalue(st, cond_expr);
+   if (condition == NULL) {
+      ir_read_error(st, NULL, "when reading condition of assignment");
+      return NULL;
+   }
+
+   ir_rvalue *lhs = read_rvalue(st, lhs_expr);
+   if (lhs == NULL) {
+      ir_read_error(st, NULL, "when reading left-hand side of assignment");
+      return NULL;
+   }
+
+   ir_rvalue *rhs = read_rvalue(st, rhs_expr);
+   if (rhs == NULL) {
+      ir_read_error(st, NULL, "when reading right-hand side of assignment");
+      return NULL;
+   }
+
+   return new(ctx) ir_assignment(lhs, rhs, condition);
+}
+
+static ir_call *
+read_call(_mesa_glsl_parse_state *st, s_list *list)
+{
+   void *ctx = st;
+   if (list->length() != 3) {
+      ir_read_error(st, list, "expected (call <name> (<param> ...))");
+      return NULL;
+   }
+
+   s_symbol *name = SX_AS_SYMBOL(list->subexpressions.head->next);
+   s_list *params = SX_AS_LIST(name->next);
+   if (name == NULL || params == NULL) {
+      ir_read_error(st, list, "expected (call <name> (<param> ...))");
+      return NULL;
+   }
+
+   exec_list parameters;
+
+   foreach_iter(exec_list_iterator, it, params->subexpressions) {
+      s_expression *expr = (s_expression*) it.get();
+      ir_rvalue *param = read_rvalue(st, expr);
+      if (param == NULL) {
+        ir_read_error(st, list, "when reading parameter to function call");
+        return NULL;
+      }
+      parameters.push_tail(param);
+   }
+
+   ir_function *f = st->symbols->get_function(name->value());
+   if (f == NULL) {
+      ir_read_error(st, list, "found call to undefined function %s",
+                   name->value());
+      return NULL;
+   }
+
+   ir_function_signature *callee = f->matching_signature(&parameters);
+   if (callee == NULL) {
+      ir_read_error(st, list, "couldn't find matching signature for function "
+                    "%s", name->value());
+      return NULL;
+   }
+
+   return new(ctx) ir_call(callee, &parameters);
+}
+
+static ir_expression *
+read_expression(_mesa_glsl_parse_state *st, s_list *list)
+{
+   void *ctx = st;
+   const unsigned list_length = list->length();
+   if (list_length < 4) {
+      ir_read_error(st, list, "expected (expression <type> <operator> "
+                             "<operand> [<operand>])");
+      return NULL;
+   }
+
+   s_expression *type_expr = (s_expression*) list->subexpressions.head->next;
+   const glsl_type *type = read_type(st, type_expr);
+   if (type == NULL)
+      return NULL;
+
+   /* Read the operator */
+   s_symbol *op_sym = SX_AS_SYMBOL(type_expr->next);
+   if (op_sym == NULL) {
+      ir_read_error(st, list, "expected operator, found non-symbol");
+      return NULL;
+   }
+
+   ir_expression_operation op = ir_expression::get_operator(op_sym->value());
+   if (op == (ir_expression_operation) -1) {
+      ir_read_error(st, list, "invalid operator: %s", op_sym->value());
+      return NULL;
+   }
+    
+   /* Now that we know the operator, check for the right number of operands */ 
+   if (ir_expression::get_num_operands(op) == 2) {
+      if (list_length != 5) {
+        ir_read_error(st, list, "expected (expression <type> %s <operand> "
+                                " <operand>)", op_sym->value());
+        return NULL;
+      }
+   } else {
+      if (list_length != 4) {
+        ir_read_error(st, list, "expected (expression <type> %s <operand>)",
+                      op_sym->value());
+        return NULL;
+      }
+   }
+
+   s_expression *exp1 = (s_expression*) (op_sym->next);
+   ir_rvalue *arg1 = read_rvalue(st, exp1);
+   if (arg1 == NULL) {
+      ir_read_error(st, NULL, "when reading first operand of %s",
+                   op_sym->value());
+      return NULL;
+   }
+
+   ir_rvalue *arg2 = NULL;
+   if (ir_expression::get_num_operands(op) == 2) {
+      s_expression *exp2 = (s_expression*) (exp1->next);
+      arg2 = read_rvalue(st, exp2);
+      if (arg2 == NULL) {
+        ir_read_error(st, NULL, "when reading second operand of %s",
+                      op_sym->value());
+        return NULL;
+      }
+   }
+
+   return new(ctx) ir_expression(op, type, arg1, arg2);
+}
+
+static ir_swizzle *
+read_swizzle(_mesa_glsl_parse_state *st, s_list *list)
+{
+   if (list->length() != 3) {
+      ir_read_error(st, list, "expected (swiz <swizzle> <rvalue>)");
+      return NULL;
+   }
+
+   s_symbol *swiz = SX_AS_SYMBOL(list->subexpressions.head->next);
+   if (swiz == NULL) {
+      ir_read_error(st, list, "expected a valid swizzle; found non-symbol");
+      return NULL;
+   }
+
+   if (strlen(swiz->value()) > 4) {
+      ir_read_error(st, list, "expected a valid swizzle; found %s",
+                   swiz->value());
+      return NULL;
+   }
+
+   s_expression *sub = (s_expression*) swiz->next;
+   if (sub == NULL) {
+      ir_read_error(st, list, "expected rvalue: (swizzle %s <rvalue>)",
+                   swiz->value());
+      return NULL;
+   }
+
+   ir_rvalue *rvalue = read_rvalue(st, sub);
+   if (rvalue == NULL)
+      return NULL;
+
+   ir_swizzle *ir = ir_swizzle::create(rvalue, swiz->value(),
+                                      rvalue->type->vector_elements);
+   if (ir == NULL)
+      ir_read_error(st, list, "invalid swizzle");
+
+   return ir;
+}
+
+static ir_constant *
+read_constant(_mesa_glsl_parse_state *st, s_list *list)
+{
+   void *ctx = st;
+   if (list->length() != 3) {
+      ir_read_error(st, list, "expected (constant <type> (...))");
+      return NULL;
+   }
+
+   s_expression *type_expr = (s_expression*) list->subexpressions.head->next;
+   const glsl_type *type = read_type(st, type_expr);
+   if (type == NULL)
+      return NULL;
+
+   s_list *values = SX_AS_LIST(type_expr->next);
+   if (values == NULL) {
+      ir_read_error(st, list, "expected (constant <type> (...))");
+      return NULL;
+   }
+
+   if (type->is_array()) {
+      const unsigned elements_supplied = values->length();
+      if (elements_supplied != type->length) {
+        ir_read_error(st, values, "expected exactly %u array elements, "
+                      "given %u", type->length, elements_supplied);
+        return NULL;
+      }
+
+      exec_list elements;
+      foreach_iter(exec_list_iterator, it, values->subexpressions) {
+        s_expression *expr = (s_expression *) it.get();
+        s_list *elt = SX_AS_LIST(expr);
+        if (elt == NULL) {
+           ir_read_error(st, expr, "expected (constant ...) array element");
+           return NULL;
+        }
+
+        ir_constant *ir_elt = read_constant(st, elt);
+        if (ir_elt == NULL)
+           return NULL;
+        elements.push_tail(ir_elt);
+      }
+      return new(ctx) ir_constant(type, &elements);
+   }
+
+   const glsl_type *const base_type = type->get_base_type();
+
+   ir_constant_data data = { { 0 } };
+
+   // Read in list of values (at most 16).
+   int k = 0;
+   foreach_iter(exec_list_iterator, it, values->subexpressions) {
+      if (k >= 16) {
+        ir_read_error(st, values, "expected at most 16 numbers");
+        return NULL;
+      }
+
+      s_expression *expr = (s_expression*) it.get();
+
+      if (base_type->base_type == GLSL_TYPE_FLOAT) {
+        s_number *value = SX_AS_NUMBER(expr);
+        if (value == NULL) {
+           ir_read_error(st, values, "expected numbers");
+           return NULL;
+        }
+        data.f[k] = value->fvalue();
+      } else {
+        s_int *value = SX_AS_INT(expr);
+        if (value == NULL) {
+           ir_read_error(st, values, "expected integers");
+           return NULL;
+        }
+
+        switch (base_type->base_type) {
+        case GLSL_TYPE_UINT: {
+           data.u[k] = value->value();
+           break;
+        }
+        case GLSL_TYPE_INT: {
+           data.i[k] = value->value();
+           break;
+        }
+        case GLSL_TYPE_BOOL: {
+           data.b[k] = value->value();
+           break;
+        }
+        default:
+           ir_read_error(st, values, "unsupported constant type");
+           return NULL;
+        }
+      }
+      ++k;
+   }
+
+   return new(ctx) ir_constant(type, &data);
+}
+
+static ir_dereference *
+read_dereference(_mesa_glsl_parse_state *st, s_expression *expr)
+{
+   s_list *list = SX_AS_LIST(expr);
+   if (list == NULL || list->subexpressions.is_empty())
+      return NULL;
+
+   s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.head);
+   assert(tag != NULL);
+
+   if (strcmp(tag->value(), "var_ref") == 0)
+      return read_var_ref(st, list);
+   if (strcmp(tag->value(), "array_ref") == 0)
+      return read_array_ref(st, list);
+   if (strcmp(tag->value(), "record_ref") == 0)
+      return read_record_ref(st, list);
+   return NULL;
+}
+
+static ir_dereference *
+read_var_ref(_mesa_glsl_parse_state *st, s_list *list)
+{
+   void *ctx = st;
+   if (list->length() != 2) {
+      ir_read_error(st, list, "expected (var_ref <variable name>)");
+      return NULL;
+   }
+   s_symbol *var_name = SX_AS_SYMBOL(list->subexpressions.head->next);
+   if (var_name == NULL) {
+      ir_read_error(st, list, "expected (var_ref <variable name>)");
+      return NULL;
+   }
+
+   ir_variable *var = st->symbols->get_variable(var_name->value());
+   if (var == NULL) {
+      ir_read_error(st, list, "undeclared variable: %s", var_name->value());
+      return NULL;
+   }
+
+   return new(ctx) ir_dereference_variable(var);
+}
+
+static ir_dereference *
+read_array_ref(_mesa_glsl_parse_state *st, s_list *list)
+{
+   void *ctx = st;
+   if (list->length() != 3) {
+      ir_read_error(st, list, "expected (array_ref <rvalue> <index>)");
+      return NULL;
+   }
+
+   s_expression *subj_expr = (s_expression*) list->subexpressions.head->next;
+   ir_rvalue *subject = read_rvalue(st, subj_expr);
+   if (subject == NULL) {
+      ir_read_error(st, NULL, "when reading the subject of an array_ref");
+      return NULL;
+   }
+
+   s_expression *idx_expr = (s_expression*) subj_expr->next;
+   ir_rvalue *idx = read_rvalue(st, idx_expr);
+   return new(ctx) ir_dereference_array(subject, idx);
+}
+
+static ir_dereference *
+read_record_ref(_mesa_glsl_parse_state *st, s_list *list)
+{
+   void *ctx = st;
+   if (list->length() != 3) {
+      ir_read_error(st, list, "expected (record_ref <rvalue> <field>)");
+      return NULL;
+   }
+
+   s_expression *subj_expr = (s_expression*) list->subexpressions.head->next;
+   ir_rvalue *subject = read_rvalue(st, subj_expr);
+   if (subject == NULL) {
+      ir_read_error(st, NULL, "when reading the subject of a record_ref");
+      return NULL;
+   }
+
+   s_symbol *field = SX_AS_SYMBOL(subj_expr->next);
+   if (field == NULL) {
+      ir_read_error(st, list, "expected (record_ref ... <field name>)");
+      return NULL;
+   }
+   return new(ctx) ir_dereference_record(subject, field->value());
+}
+
+static bool
+valid_texture_list_length(ir_texture_opcode op, s_list *list)
+{
+   unsigned required_length = 7;
+   if (op == ir_txf)
+      required_length = 5;
+   else if (op == ir_tex)
+      required_length = 6;
+
+   return list->length() == required_length;
+}
+
+static ir_texture *
+read_texture(_mesa_glsl_parse_state *st, s_list *list)
+{
+   void *ctx = st;
+   s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.head);
+   assert(tag != NULL);
+
+   ir_texture_opcode op = ir_texture::get_opcode(tag->value());
+   if (op == (ir_texture_opcode) -1)
+      return NULL;
+
+   if (!valid_texture_list_length(op, list)) {
+      ir_read_error(st, NULL, "invalid list size in (%s ...)", tag->value());
+      return NULL;
+   }
+
+   ir_texture *tex = new(ctx) ir_texture(op);
+
+   // Read sampler (must be a deref)
+   s_expression *sampler_expr = (s_expression *) tag->next;
+   ir_dereference *sampler = read_dereference(st, sampler_expr);
+   if (sampler == NULL) {
+      ir_read_error(st, NULL, "when reading sampler in (%s ...)", tag->value());
+      return NULL;
+   }
+   tex->set_sampler(sampler);
+
+   // Read coordinate (any rvalue)
+   s_expression *coordinate_expr = (s_expression *) sampler_expr->next;
+   tex->coordinate = read_rvalue(st, coordinate_expr);
+   if (tex->coordinate == NULL) {
+      ir_read_error(st, NULL, "when reading coordinate in (%s ...)",
+                   tag->value());
+      return NULL;
+   }
+
+   // Read texel offset, i.e. (0 0 0)
+   s_list *offset_list = SX_AS_LIST(coordinate_expr->next);
+   if (offset_list == NULL || offset_list->length() != 3) {
+      ir_read_error(st, offset_list, "expected (<int> <int> <int>)");
+      return NULL;
+   }
+   s_int *offset_x = SX_AS_INT(offset_list->subexpressions.head);
+   s_int *offset_y = SX_AS_INT(offset_x->next);
+   s_int *offset_z = SX_AS_INT(offset_y->next);
+   if (offset_x == NULL || offset_y == NULL || offset_z == NULL) {
+      ir_read_error(st, offset_list, "expected (<int> <int> <int>)");
+      return NULL;
+   }
+   tex->offsets[0] = offset_x->value();
+   tex->offsets[1] = offset_y->value();
+   tex->offsets[2] = offset_z->value();
+
+   if (op == ir_txf) {
+      s_expression *lod_expr = (s_expression *) offset_list->next;
+      tex->lod_info.lod = read_rvalue(st, lod_expr);
+      if (tex->lod_info.lod == NULL) {
+        ir_read_error(st, NULL, "when reading LOD in (txf ...)");
+        return NULL;
+      }
+   } else {
+      s_expression *proj_expr = (s_expression *) offset_list->next;
+      s_int *proj_as_int = SX_AS_INT(proj_expr);
+      if (proj_as_int && proj_as_int->value() == 1) {
+        tex->projector = NULL;
+      } else {
+        tex->projector = read_rvalue(st, proj_expr);
+        if (tex->projector == NULL) {
+           ir_read_error(st, NULL, "when reading projective divide in (%s ..)",
+                         tag->value());
+           return NULL;
+        }
+      }
+
+      s_list *shadow_list = SX_AS_LIST(proj_expr->next);
+      if (shadow_list == NULL) {
+        ir_read_error(st, NULL, "shadow comparitor must be a list");
+        return NULL;
+      }
+      if (shadow_list->subexpressions.is_empty()) {
+        tex->shadow_comparitor= NULL;
+      } else {
+        tex->shadow_comparitor = read_rvalue(st, shadow_list);
+        if (tex->shadow_comparitor == NULL) {
+           ir_read_error(st, NULL, "when reading shadow comparitor in (%s ..)",
+                         tag->value());
+           return NULL;
+        }
+      }
+      s_expression *lod_expr = (s_expression *) shadow_list->next;
+
+      switch (op) {
+      case ir_txb:
+        tex->lod_info.bias = read_rvalue(st, lod_expr);
+        if (tex->lod_info.bias == NULL) {
+           ir_read_error(st, NULL, "when reading LOD bias in (txb ...)");
+           return NULL;
+        }
+        break;
+      case ir_txl:
+        tex->lod_info.lod = read_rvalue(st, lod_expr);
+        if (tex->lod_info.lod == NULL) {
+           ir_read_error(st, NULL, "when reading LOD in (txl ...)");
+           return NULL;
+        }
+        break;
+      case ir_txd: {
+        s_list *lod_list = SX_AS_LIST(lod_expr);
+        if (lod_list->length() != 2) {
+           ir_read_error(st, lod_expr, "expected (dPdx dPdy) in (txd ...)");
+           return NULL;
+        }
+        s_expression *dx_expr = (s_expression *) lod_list->subexpressions.head;
+        s_expression *dy_expr = (s_expression *) dx_expr->next;
+
+        tex->lod_info.grad.dPdx = read_rvalue(st, dx_expr);
+        if (tex->lod_info.grad.dPdx == NULL) {
+           ir_read_error(st, NULL, "when reading dPdx in (txd ...)");
+           return NULL;
+        }
+        tex->lod_info.grad.dPdy = read_rvalue(st, dy_expr);
+        if (tex->lod_info.grad.dPdy == NULL) {
+           ir_read_error(st, NULL, "when reading dPdy in (txd ...)");
+           return NULL;
+        }
+        break;
+      }
+      default:
+        // tex doesn't have any extra parameters and txf was handled earlier.
+        break;
+      };
+   }
+   return tex;
+}
diff --git a/src/glsl/ir_reader.h b/src/glsl/ir_reader.h
new file mode 100644 (file)
index 0000000..aef2ca2
--- /dev/null
@@ -0,0 +1,34 @@
+/* -*- c++ -*- */
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+#pragma once
+#ifndef IR_READER_H
+#define IR_READER_H
+
+#include "ir.h"
+
+void _mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions,
+                       const char *src, bool scan_for_prototypes);
+
+#endif /* IR_READER_H */
diff --git a/src/glsl/ir_rvalue_visitor.cpp b/src/glsl/ir_rvalue_visitor.cpp
new file mode 100644 (file)
index 0000000..613b07c
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_rvalue_visitor.cpp
+ *
+ * Generic class to implement the common pattern we have of wanting to
+ * visit each ir_rvalue * and possibly change that node to a different
+ * class.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_rvalue_visitor.h"
+#include "ir_print_visitor.h"
+#include "glsl_types.h"
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_expression *ir)
+{
+   unsigned int operand;
+
+   for (operand = 0; operand < ir->get_num_operands(); operand++) {
+      handle_rvalue(&ir->operands[operand]);
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_texture *ir)
+{
+   handle_rvalue(&ir->coordinate);
+   handle_rvalue(&ir->projector);
+   handle_rvalue(&ir->shadow_comparitor);
+
+   switch (ir->op) {
+   case ir_tex:
+      break;
+   case ir_txb:
+      handle_rvalue(&ir->lod_info.bias);
+      break;
+   case ir_txf:
+   case ir_txl:
+      handle_rvalue(&ir->lod_info.lod);
+      break;
+   case ir_txd:
+      handle_rvalue(&ir->lod_info.grad.dPdx);
+      handle_rvalue(&ir->lod_info.grad.dPdy);
+      break;
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_swizzle *ir)
+{
+   handle_rvalue(&ir->val);
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_dereference_array *ir)
+{
+   handle_rvalue(&ir->array_index);
+   handle_rvalue(&ir->array);
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_dereference_record *ir)
+{
+   handle_rvalue(&ir->record);
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_assignment *ir)
+{
+   handle_rvalue(&ir->rhs);
+   handle_rvalue(&ir->condition);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_call *ir)
+{
+   foreach_iter(exec_list_iterator, iter, *ir) {
+      ir_rvalue *param = (ir_rvalue *)iter.get();
+      ir_rvalue *new_param = param;
+      handle_rvalue(&new_param);
+
+      if (new_param != param) {
+        param->replace_with(new_param);
+      }
+   }
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_return *ir)
+{
+   handle_rvalue(&ir->value);;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_if *ir)
+{
+   handle_rvalue(&ir->condition);
+   return visit_continue;
+}
diff --git a/src/glsl/ir_rvalue_visitor.h b/src/glsl/ir_rvalue_visitor.h
new file mode 100644 (file)
index 0000000..31a56be
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_rvalue_visitor.h
+ *
+ * Generic class to implement the common pattern we have of wanting to
+ * visit each ir_rvalue * and possibly change that node to a different
+ * class.  Just implement handle_rvalue() and you will be called with
+ * a pointer to each rvalue in the tree.
+ */
+
+class ir_rvalue_visitor : public ir_hierarchical_visitor {
+public:
+
+   virtual ir_visitor_status visit_leave(ir_assignment *);
+   virtual ir_visitor_status visit_leave(ir_call *);
+   virtual ir_visitor_status visit_leave(ir_dereference_array *);
+   virtual ir_visitor_status visit_leave(ir_dereference_record *);
+   virtual ir_visitor_status visit_leave(ir_expression *);
+   virtual ir_visitor_status visit_leave(ir_if *);
+   virtual ir_visitor_status visit_leave(ir_return *);
+   virtual ir_visitor_status visit_leave(ir_swizzle *);
+   virtual ir_visitor_status visit_leave(ir_texture *);
+
+   virtual void handle_rvalue(ir_rvalue **rvalue) = 0;
+};
diff --git a/src/glsl/ir_set_program_inouts.cpp b/src/glsl/ir_set_program_inouts.cpp
new file mode 100644 (file)
index 0000000..b3f1cc0
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_set_program_inouts.cpp
+ *
+ * Sets the InputsRead and OutputsWritten of Mesa programs.
+ *
+ * Mesa programs (gl_program, not gl_shader_program) have a set of
+ * flags indicating which varyings are read and written.  Computing
+ * which are actually read from some sort of backend code can be
+ * tricky when variable array indexing involved.  So this pass
+ * provides support for setting InputsRead and OutputsWritten right
+ * from the GLSL IR.
+ */
+
+extern "C" {
+#include "main/core.h" /* for struct gl_program */
+#include "program/hash_table.h"
+}
+#include "ir.h"
+#include "ir_visitor.h"
+#include "glsl_types.h"
+
+class ir_set_program_inouts_visitor : public ir_hierarchical_visitor {
+public:
+   ir_set_program_inouts_visitor(struct gl_program *prog)
+   {
+      this->prog = prog;
+      this->ht = hash_table_ctor(0,
+                                hash_table_pointer_hash,
+                                hash_table_pointer_compare);
+   }
+   ~ir_set_program_inouts_visitor()
+   {
+      hash_table_dtor(this->ht);
+   }
+
+   virtual ir_visitor_status visit_enter(ir_dereference_array *);
+   virtual ir_visitor_status visit_enter(ir_function_signature *);
+   virtual ir_visitor_status visit(ir_dereference_variable *);
+   virtual ir_visitor_status visit(ir_variable *);
+
+   struct gl_program *prog;
+   struct hash_table *ht;
+};
+
+static void
+mark(struct gl_program *prog, ir_variable *var, int index)
+{
+   /* As of GLSL 1.20, varyings can only be floats, floating-point
+    * vectors or matrices, or arrays of them.  For Mesa programs using
+    * InputsRead/OutputsWritten, everything but matrices uses one
+    * slot, while matrices use a slot per column.  Presumably
+    * something doing a more clever packing would use something other
+    * than InputsRead/OutputsWritten.
+    */
+   const glsl_type *element_type;
+   int element_size;
+
+   if (var->type->is_array())
+      element_type = var->type->fields.array;
+   else
+      element_type = var->type;
+
+   if (element_type->is_matrix())
+      element_size = element_type->matrix_columns;
+   else
+      element_size = 1;
+
+   index *= element_size;
+   for (int i = 0; i < element_size; i++) {
+      if (var->mode == ir_var_in)
+        prog->InputsRead |= BITFIELD64_BIT(var->location + index + i);
+      else
+        prog->OutputsWritten |= BITFIELD64_BIT(var->location + index + i);
+   }
+}
+
+/* Default handler: Mark all the locations in the variable as used. */
+ir_visitor_status
+ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir)
+{
+   if (hash_table_find(this->ht, ir->var) == NULL)
+      return visit_continue;
+
+   if (ir->type->is_array()) {
+      for (unsigned int i = 0; i < ir->type->length; i++) {
+        mark(this->prog, ir->var, i);
+      }
+   } else {
+      mark(this->prog, ir->var, 0);
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
+{
+   ir_dereference_variable *deref_var;
+   ir_constant *index = ir->array_index->as_constant();
+   deref_var = ir->array->as_dereference_variable();
+   ir_variable *var = NULL;
+
+   /* Check that we're dereferencing a shader in or out */
+   if (deref_var)
+      var = (ir_variable *)hash_table_find(this->ht, deref_var->var);
+
+   if (index && var) {
+      mark(this->prog, var, index->value.i[0]);
+      return visit_continue_with_parent;
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_set_program_inouts_visitor::visit(ir_variable *ir)
+{
+   if (ir->mode == ir_var_in ||
+       ir->mode == ir_var_out) {
+      hash_table_insert(this->ht, ir, ir);
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_set_program_inouts_visitor::visit_enter(ir_function_signature *ir)
+{
+   /* We don't want to descend into the function parameters and
+    * consider them as shader inputs or outputs.
+    */
+   visit_list_elements(this, &ir->body);
+   return visit_continue_with_parent;
+}
+
+void
+do_set_program_inouts(exec_list *instructions, struct gl_program *prog)
+{
+   ir_set_program_inouts_visitor v(prog);
+
+   prog->InputsRead = 0;
+   prog->OutputsWritten = 0;
+   visit_list_elements(&v, instructions);
+}
diff --git a/src/glsl/ir_structure_splitting.cpp b/src/glsl/ir_structure_splitting.cpp
new file mode 100644 (file)
index 0000000..ff3ec93
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_structure_splitting.cpp
+ *
+ * If a structure is only ever referenced by its components, then
+ * split those components out to individual variables so they can be
+ * handled normally by other optimization passes.
+ *
+ * This skips structures like uniforms, which need to be accessible as
+ * structures for their access by the GL.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_print_visitor.h"
+#include "ir_rvalue_visitor.h"
+#include "glsl_types.h"
+
+static bool debug = false;
+
+// XXX using variable_entry2 here to avoid collision (MSVC multiply-defined
+// function) with the variable_entry class seen in ir_variable_refcount.h
+// Perhaps we can use the one in ir_variable_refcount.h and make this class
+// here go away?
+class variable_entry2 : public exec_node
+{
+public:
+   variable_entry2(ir_variable *var)
+   {
+      this->var = var;
+      this->whole_structure_access = 0;
+      this->declaration = false;
+      this->components = NULL;
+      this->mem_ctx = NULL;
+   }
+
+   ir_variable *var; /* The key: the variable's pointer. */
+
+   /** Number of times the variable is referenced, including assignments. */
+   unsigned whole_structure_access;
+
+   bool declaration; /* If the variable had a decl in the instruction stream */
+
+   ir_variable **components;
+
+   /** talloc_parent(this->var) -- the shader's talloc context. */
+   void *mem_ctx;
+};
+
+
+class ir_structure_reference_visitor : public ir_hierarchical_visitor {
+public:
+   ir_structure_reference_visitor(void)
+   {
+      this->mem_ctx = talloc_new(NULL);
+      this->variable_list.make_empty();
+   }
+
+   ~ir_structure_reference_visitor(void)
+   {
+      talloc_free(mem_ctx);
+   }
+
+   virtual ir_visitor_status visit(ir_variable *);
+   virtual ir_visitor_status visit(ir_dereference_variable *);
+   virtual ir_visitor_status visit_enter(ir_dereference_record *);
+   virtual ir_visitor_status visit_enter(ir_assignment *);
+   virtual ir_visitor_status visit_enter(ir_function_signature *);
+
+   variable_entry2 *get_variable_entry2(ir_variable *var);
+
+   /* List of variable_entry */
+   exec_list variable_list;
+
+   void *mem_ctx;
+};
+
+variable_entry2 *
+ir_structure_reference_visitor::get_variable_entry2(ir_variable *var)
+{
+   assert(var);
+
+   if (!var->type->is_record() || var->mode == ir_var_uniform)
+      return NULL;
+
+   foreach_iter(exec_list_iterator, iter, this->variable_list) {
+      variable_entry2 *entry = (variable_entry2 *)iter.get();
+      if (entry->var == var)
+        return entry;
+   }
+
+   variable_entry2 *entry = new(mem_ctx) variable_entry2(var);
+   this->variable_list.push_tail(entry);
+   return entry;
+}
+
+
+ir_visitor_status
+ir_structure_reference_visitor::visit(ir_variable *ir)
+{
+   variable_entry2 *entry = this->get_variable_entry2(ir);
+
+   if (entry)
+      entry->declaration = true;
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_structure_reference_visitor::visit(ir_dereference_variable *ir)
+{
+   ir_variable *const var = ir->variable_referenced();
+   variable_entry2 *entry = this->get_variable_entry2(var);
+
+   if (entry)
+      entry->whole_structure_access++;
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_structure_reference_visitor::visit_enter(ir_dereference_record *ir)
+{
+   (void) ir;
+   /* Don't descend into the ir_dereference_variable below. */
+   return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_structure_reference_visitor::visit_enter(ir_assignment *ir)
+{
+   if (ir->lhs->as_dereference_variable() &&
+       ir->rhs->as_dereference_variable() &&
+       !ir->condition) {
+      /* We'll split copies of a structure to copies of components, so don't
+       * descend to the ir_dereference_variables.
+       */
+      return visit_continue_with_parent;
+   }
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_structure_reference_visitor::visit_enter(ir_function_signature *ir)
+{
+   /* We don't want to descend into the function parameters and
+    * dead-code eliminate them, so just accept the body here.
+    */
+   visit_list_elements(this, &ir->body);
+   return visit_continue_with_parent;
+}
+
+class ir_structure_splitting_visitor : public ir_rvalue_visitor {
+public:
+   ir_structure_splitting_visitor(exec_list *vars)
+   {
+      this->variable_list = vars;
+   }
+
+   virtual ~ir_structure_splitting_visitor()
+   {
+   }
+
+   virtual ir_visitor_status visit_leave(ir_assignment *);
+
+   void split_deref(ir_dereference **deref);
+   void handle_rvalue(ir_rvalue **rvalue);
+   variable_entry2 *get_splitting_entry(ir_variable *var);
+
+   exec_list *variable_list;
+   void *mem_ctx;
+};
+
+variable_entry2 *
+ir_structure_splitting_visitor::get_splitting_entry(ir_variable *var)
+{
+   assert(var);
+
+   if (!var->type->is_record())
+      return NULL;
+
+   foreach_iter(exec_list_iterator, iter, *this->variable_list) {
+      variable_entry2 *entry = (variable_entry2 *)iter.get();
+      if (entry->var == var) {
+        return entry;
+      }
+   }
+
+   return NULL;
+}
+
+void
+ir_structure_splitting_visitor::split_deref(ir_dereference **deref)
+{
+   if ((*deref)->ir_type != ir_type_dereference_record)
+      return;
+
+   ir_dereference_record *deref_record = (ir_dereference_record *)*deref;
+   ir_dereference_variable *deref_var = deref_record->record->as_dereference_variable();
+   if (!deref_var)
+      return;
+
+   variable_entry2 *entry = get_splitting_entry(deref_var->var);
+   if (!entry)
+      return;
+
+   unsigned int i;
+   for (i = 0; i < entry->var->type->length; i++) {
+      if (strcmp(deref_record->field,
+                entry->var->type->fields.structure[i].name) == 0)
+        break;
+   }
+   assert(i != entry->var->type->length);
+
+   *deref = new(entry->mem_ctx) ir_dereference_variable(entry->components[i]);
+}
+
+void
+ir_structure_splitting_visitor::handle_rvalue(ir_rvalue **rvalue)
+{
+   if (!*rvalue)
+      return;
+
+   ir_dereference *deref = (*rvalue)->as_dereference();
+
+   if (!deref)
+      return;
+
+   split_deref(&deref);
+   *rvalue = deref;
+}
+
+ir_visitor_status
+ir_structure_splitting_visitor::visit_leave(ir_assignment *ir)
+{
+   ir_dereference_variable *lhs_deref = ir->lhs->as_dereference_variable();
+   ir_dereference_variable *rhs_deref = ir->rhs->as_dereference_variable();
+   variable_entry2 *lhs_entry = lhs_deref ? get_splitting_entry(lhs_deref->var) : NULL;
+   variable_entry2 *rhs_entry = rhs_deref ? get_splitting_entry(rhs_deref->var) : NULL;
+   const glsl_type *type = ir->rhs->type;
+
+   if ((lhs_entry || rhs_entry) && !ir->condition) {
+      for (unsigned int i = 0; i < type->length; i++) {
+        ir_dereference *new_lhs, *new_rhs;
+        void *mem_ctx = lhs_entry ? lhs_entry->mem_ctx : rhs_entry->mem_ctx;
+
+        if (lhs_entry) {
+           new_lhs = new(mem_ctx) ir_dereference_variable(lhs_entry->components[i]);
+        } else {
+           new_lhs = new(mem_ctx)
+              ir_dereference_record(ir->lhs->clone(mem_ctx, NULL),
+                                    type->fields.structure[i].name);
+        }
+
+        if (rhs_entry) {
+           new_rhs = new(mem_ctx) ir_dereference_variable(rhs_entry->components[i]);
+        } else {
+           new_rhs = new(mem_ctx)
+              ir_dereference_record(ir->rhs->clone(mem_ctx, NULL),
+                                    type->fields.structure[i].name);
+        }
+
+        ir->insert_before(new(mem_ctx) ir_assignment(new_lhs,
+                                                     new_rhs,
+                                                     NULL));
+      }
+      ir->remove();
+   } else {
+      handle_rvalue(&ir->rhs);
+      split_deref(&ir->lhs);
+   }
+
+   handle_rvalue(&ir->condition);
+
+   return visit_continue;
+}
+
+bool
+do_structure_splitting(exec_list *instructions)
+{
+   ir_structure_reference_visitor refs;
+
+   visit_list_elements(&refs, instructions);
+
+   /* Trim out variables we can't split. */
+   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
+      variable_entry2 *entry = (variable_entry2 *)iter.get();
+
+      if (debug) {
+        printf("structure %s@%p: decl %d, whole_access %d\n",
+               entry->var->name, (void *) entry->var, entry->declaration,
+               entry->whole_structure_access);
+      }
+
+      if (!entry->declaration || entry->whole_structure_access) {
+        entry->remove();
+      }
+   }
+
+   if (refs.variable_list.is_empty())
+      return false;
+
+   void *mem_ctx = talloc_new(NULL);
+
+   /* Replace the decls of the structures to be split with their split
+    * components.
+    */
+   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
+      variable_entry2 *entry = (variable_entry2 *)iter.get();
+      const struct glsl_type *type = entry->var->type;
+
+      entry->mem_ctx = talloc_parent(entry->var);
+
+      entry->components = talloc_array(mem_ctx,
+                                      ir_variable *,
+                                      type->length);
+
+      for (unsigned int i = 0; i < entry->var->type->length; i++) {
+        const char *name = talloc_asprintf(mem_ctx, "%s_%s",
+                                           entry->var->name,
+                                           type->fields.structure[i].name);
+
+        entry->components[i] =
+           new(entry->mem_ctx) ir_variable(type->fields.structure[i].type,
+                                           name,
+                                           ir_var_temporary);
+        entry->var->insert_before(entry->components[i]);
+      }
+
+      entry->var->remove();
+   }
+
+   ir_structure_splitting_visitor split(&refs.variable_list);
+   visit_list_elements(&split, instructions);
+
+   talloc_free(mem_ctx);
+
+   return true;
+}
diff --git a/src/glsl/ir_sub_to_add_neg.cpp b/src/glsl/ir_sub_to_add_neg.cpp
new file mode 100644 (file)
index 0000000..7ed8c14
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_sub_to_add_neg.cpp
+ *
+ * Breaks an ir_binop_sub expression down to add(op0, neg(op1))
+ *
+ * This simplifies expression reassociation, and for many backends
+ * there is no subtract operation separate from adding the negation.
+ * For backends with native subtract operations, they will probably
+ * want to recognize add(op0, neg(op1)) or the other way around to
+ * produce a subtract anyway.
+ */
+
+#include "ir.h"
+
+class ir_sub_to_add_neg_visitor : public ir_hierarchical_visitor {
+public:
+   ir_sub_to_add_neg_visitor()
+   {
+      this->progress = false;
+   }
+
+   ir_visitor_status visit_leave(ir_expression *);
+
+   bool progress;
+};
+
+bool
+do_sub_to_add_neg(exec_list *instructions)
+{
+   ir_sub_to_add_neg_visitor v;
+
+   visit_list_elements(&v, instructions);
+   return v.progress;
+}
+
+ir_visitor_status
+ir_sub_to_add_neg_visitor::visit_leave(ir_expression *ir)
+{
+   if (ir->operation != ir_binop_sub)
+      return visit_continue;
+
+   void *mem_ctx = talloc_parent(ir);
+
+   ir->operation = ir_binop_add;
+   ir->operands[1] = new(mem_ctx) ir_expression(ir_unop_neg,
+                                               ir->operands[1]->type,
+                                               ir->operands[1],
+                                               NULL);
+
+   this->progress = true;
+
+   return visit_continue;
+}
diff --git a/src/glsl/ir_swizzle_swizzle.cpp b/src/glsl/ir_swizzle_swizzle.cpp
new file mode 100644 (file)
index 0000000..0ffb4fa
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_swizzle_swizzle.cpp
+ *
+ * Eliminates the second swizzle in a swizzle chain.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+class ir_swizzle_swizzle_visitor : public ir_hierarchical_visitor {
+public:
+   ir_swizzle_swizzle_visitor()
+   {
+      progress = false;
+   }
+
+   virtual ir_visitor_status visit_enter(ir_swizzle *);
+
+   bool progress;
+};
+
+ir_visitor_status
+ir_swizzle_swizzle_visitor::visit_enter(ir_swizzle *ir)
+{
+   int mask2[4];
+
+   ir_swizzle *swiz2 = ir->val->as_swizzle();
+   if (!swiz2)
+      return visit_continue;
+
+   memset(&mask2, 0, sizeof(mask2));
+   if (swiz2->mask.num_components >= 1)
+      mask2[0] = swiz2->mask.x;
+   if (swiz2->mask.num_components >= 2)
+      mask2[1] = swiz2->mask.y;
+   if (swiz2->mask.num_components >= 3)
+      mask2[2] = swiz2->mask.z;
+   if (swiz2->mask.num_components >= 4)
+      mask2[3] = swiz2->mask.w;
+
+   if (ir->mask.num_components >= 1)
+      ir->mask.x = mask2[ir->mask.x];
+   if (ir->mask.num_components >= 2)
+      ir->mask.y = mask2[ir->mask.y];
+   if (ir->mask.num_components >= 3)
+      ir->mask.z = mask2[ir->mask.z];
+   if (ir->mask.num_components >= 4)
+      ir->mask.w = mask2[ir->mask.w];
+
+   ir->val = swiz2->val;
+
+   this->progress = true;
+
+   return visit_continue;
+}
+
+/**
+ * Does a copy propagation pass on the code present in the instruction stream.
+ */
+bool
+do_swizzle_swizzle(exec_list *instructions)
+{
+   ir_swizzle_swizzle_visitor v;
+
+   v.run(instructions);
+
+   return v.progress;
+}
diff --git a/src/glsl/ir_tree_grafting.cpp b/src/glsl/ir_tree_grafting.cpp
new file mode 100644 (file)
index 0000000..9b569b8
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_tree_grafting.cpp
+ *
+ * Takes assignments to variables that are dereferenced only once and
+ * pastes the RHS expression into where the variable is dereferenced.
+ *
+ * In the process of various operations like function inlining and
+ * tertiary op handling, we'll end up with our expression trees having
+ * been chopped up into a series of assignments of short expressions
+ * to temps.  Other passes like ir_algebraic.cpp would prefer to see
+ * the deepest expression trees they can to try to optimize them.
+ *
+ * This is a lot like copy propagaton.  In comparison, copy
+ * propagation only acts on plain copies, not arbitrary expressions on
+ * the RHS.  Generally, we wouldn't want to go pasting some
+ * complicated expression everywhere it got used, though, so we don't
+ * handle expressions in that pass.
+ *
+ * The hard part is making sure we don't move an expression across
+ * some other assignments that would change the value of the
+ * expression.  So we split this into two passes: First, find the
+ * variables in our scope which are written to once and read once, and
+ * then go through basic blocks seeing if we find an opportunity to
+ * move those expressions safely.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_variable_refcount.h"
+#include "ir_basic_block.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+static bool debug = false;
+
+class ir_tree_grafting_visitor : public ir_hierarchical_visitor {
+public:
+   ir_tree_grafting_visitor(ir_assignment *graft_assign,
+                           ir_variable *graft_var)
+   {
+      this->progress = false;
+      this->graft_assign = graft_assign;
+      this->graft_var = graft_var;
+   }
+
+   virtual ir_visitor_status visit_leave(class ir_assignment *);
+   virtual ir_visitor_status visit_enter(class ir_call *);
+   virtual ir_visitor_status visit_enter(class ir_expression *);
+   virtual ir_visitor_status visit_enter(class ir_function *);
+   virtual ir_visitor_status visit_enter(class ir_function_signature *);
+   virtual ir_visitor_status visit_enter(class ir_if *);
+   virtual ir_visitor_status visit_enter(class ir_loop *);
+   virtual ir_visitor_status visit_enter(class ir_swizzle *);
+   virtual ir_visitor_status visit_enter(class ir_texture *);
+
+   bool do_graft(ir_rvalue **rvalue);
+
+   bool progress;
+   ir_variable *graft_var;
+   ir_assignment *graft_assign;
+};
+
+struct find_deref_info {
+   ir_variable *var;
+   bool found;
+};
+
+void
+dereferences_variable_callback(ir_instruction *ir, void *data)
+{
+   struct find_deref_info *info = (struct find_deref_info *)data;
+   ir_dereference_variable *deref = ir->as_dereference_variable();
+
+   if (deref && deref->var == info->var)
+      info->found = true;
+}
+
+static bool
+dereferences_variable(ir_instruction *ir, ir_variable *var)
+{
+   struct find_deref_info info;
+
+   info.var = var;
+   info.found = false;
+
+   visit_tree(ir, dereferences_variable_callback, &info);
+
+   return info.found;
+}
+
+bool
+ir_tree_grafting_visitor::do_graft(ir_rvalue **rvalue)
+{
+   if (!*rvalue)
+      return false;
+
+   ir_dereference_variable *deref = (*rvalue)->as_dereference_variable();
+
+   if (!deref || deref->var != this->graft_var)
+      return false;
+
+   if (debug) {
+      printf("GRAFTING:\n");
+      this->graft_assign->print();
+      printf("\n");
+      printf("TO:\n");
+      (*rvalue)->print();
+      printf("\n");
+   }
+
+   this->graft_assign->remove();
+   *rvalue = this->graft_assign->rhs;
+
+   this->progress = true;
+   return true;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_loop *ir)
+{
+   (void)ir;
+   /* Do not traverse into the body of the loop since that is a
+    * different basic block.
+    */
+   return visit_stop;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_leave(ir_assignment *ir)
+{
+   if (do_graft(&ir->rhs) ||
+       do_graft(&ir->condition))
+      return visit_stop;
+
+   /* If this assignment updates a variable used in the assignment
+    * we're trying to graft, then we're done.
+    */
+   if (dereferences_variable(this->graft_assign->rhs,
+                            ir->lhs->variable_referenced())) {
+      if (debug) {
+        printf("graft killed by: ");
+        ir->print();
+        printf("\n");
+      }
+      return visit_stop;
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_function *ir)
+{
+   (void) ir;
+   return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_function_signature *ir)
+{
+   (void)ir;
+   return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_call *ir)
+{
+   exec_list_iterator sig_iter = ir->get_callee()->parameters.iterator();
+   /* Reminder: iterating ir_call iterates its parameters. */
+   foreach_iter(exec_list_iterator, iter, *ir) {
+      ir_variable *sig_param = (ir_variable *)sig_iter.get();
+      ir_rvalue *ir = (ir_rvalue *)iter.get();
+      ir_rvalue *new_ir = ir;
+
+      if (sig_param->mode != ir_var_in)
+        continue;
+
+      if (do_graft(&new_ir)) {
+        ir->replace_with(new_ir);
+        return visit_stop;
+      }
+      sig_iter.next();
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_expression *ir)
+{
+   for (unsigned int i = 0; i < ir->get_num_operands(); i++) {
+      if (do_graft(&ir->operands[i]))
+        return visit_stop;
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_if *ir)
+{
+   if (do_graft(&ir->condition))
+      return visit_stop;
+
+   /* Do not traverse into the body of the if-statement since that is a
+    * different basic block.
+    */
+   return visit_continue_with_parent;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_swizzle *ir)
+{
+   if (do_graft(&ir->val))
+      return visit_stop;
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_tree_grafting_visitor::visit_enter(ir_texture *ir)
+{
+   if (do_graft(&ir->coordinate) ||
+       do_graft(&ir->projector) ||
+       do_graft(&ir->shadow_comparitor))
+        return visit_stop;
+
+   switch (ir->op) {
+   case ir_tex:
+      break;
+   case ir_txb:
+      if (do_graft(&ir->lod_info.bias))
+        return visit_stop;
+      break;
+   case ir_txf:
+   case ir_txl:
+      if (do_graft(&ir->lod_info.lod))
+        return visit_stop;
+      break;
+   case ir_txd:
+      if (do_graft(&ir->lod_info.grad.dPdx) ||
+         do_graft(&ir->lod_info.grad.dPdy))
+        return visit_stop;
+      break;
+   }
+
+   return visit_continue;
+}
+
+struct tree_grafting_info {
+   ir_variable_refcount_visitor *refs;
+   bool progress;
+};
+
+static bool
+try_tree_grafting(ir_assignment *start,
+                 ir_variable *lhs_var,
+                 ir_instruction *bb_last)
+{
+   ir_tree_grafting_visitor v(start, lhs_var);
+
+   if (debug) {
+      printf("trying to graft: ");
+      lhs_var->print();
+      printf("\n");
+   }
+
+   for (ir_instruction *ir = (ir_instruction *)start->next;
+       ir != bb_last->next;
+       ir = (ir_instruction *)ir->next) {
+
+      if (debug) {
+        printf("- ");
+        ir->print();
+        printf("\n");
+      }
+
+      ir_visitor_status s = ir->accept(&v);
+      if (s == visit_stop)
+        return v.progress;
+   }
+
+   return false;
+}
+
+static void
+tree_grafting_basic_block(ir_instruction *bb_first,
+                         ir_instruction *bb_last,
+                         void *data)
+{
+   struct tree_grafting_info *info = (struct tree_grafting_info *)data;
+   ir_instruction *ir, *next;
+
+   for (ir = bb_first, next = (ir_instruction *)ir->next;
+       ir != bb_last->next;
+       ir = next, next = (ir_instruction *)ir->next) {
+      ir_assignment *assign = ir->as_assignment();
+
+      if (!assign)
+        continue;
+
+      ir_variable *lhs_var = assign->whole_variable_written();
+      if (!lhs_var)
+        continue;
+
+      if (lhs_var->mode == ir_var_out ||
+         lhs_var->mode == ir_var_inout)
+        continue;
+
+      variable_entry *entry = info->refs->get_variable_entry(lhs_var);
+
+      if (!entry->declaration ||
+         entry->assigned_count != 1 ||
+         entry->referenced_count != 2)
+        continue;
+
+      assert(assign == entry->assign);
+
+      /* Found a possibly graftable assignment.  Now, walk through the
+       * rest of the BB seeing if the deref is here, and if nothing interfered with
+       * pasting its expression's values in between.
+       */
+      info->progress |= try_tree_grafting(assign, lhs_var, bb_last);
+   }
+}
+
+/**
+ * Does a copy propagation pass on the code present in the instruction stream.
+ */
+bool
+do_tree_grafting(exec_list *instructions)
+{
+   ir_variable_refcount_visitor refs;
+   struct tree_grafting_info info;
+
+   info.progress = false;
+   info.refs = &refs;
+
+   visit_list_elements(info.refs, instructions);
+
+   call_for_basic_blocks(instructions, tree_grafting_basic_block, &info);
+
+   return info.progress;
+}
diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp
new file mode 100644 (file)
index 0000000..9ea11dd
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_validate.cpp
+ *
+ * Attempts to verify that various invariants of the IR tree are true.
+ *
+ * In particular, at the moment it makes sure that no single
+ * ir_instruction node except for ir_variable appears multiple times
+ * in the ir tree.  ir_variable does appear multiple times: Once as a
+ * declaration in an exec_list, and multiple times as the endpoint of
+ * a dereference chain.
+ */
+
+#include <inttypes.h>
+#include "ir.h"
+#include "ir_hierarchical_visitor.h"
+#include "program/hash_table.h"
+#include "glsl_types.h"
+
+class ir_validate : public ir_hierarchical_visitor {
+public:
+   ir_validate()
+   {
+      this->ht = hash_table_ctor(0, hash_table_pointer_hash,
+                                hash_table_pointer_compare);
+
+      this->current_function = NULL;
+
+      this->callback = ir_validate::validate_ir;
+      this->data = ht;
+   }
+
+   ~ir_validate()
+   {
+      hash_table_dtor(this->ht);
+   }
+
+   virtual ir_visitor_status visit(ir_variable *v);
+   virtual ir_visitor_status visit(ir_dereference_variable *ir);
+   virtual ir_visitor_status visit(ir_if *ir);
+
+   virtual ir_visitor_status visit_enter(ir_function *ir);
+   virtual ir_visitor_status visit_leave(ir_function *ir);
+   virtual ir_visitor_status visit_enter(ir_function_signature *ir);
+
+   virtual ir_visitor_status visit_leave(ir_expression *ir);
+
+   virtual ir_visitor_status visit_enter(ir_assignment *ir);
+
+   static void validate_ir(ir_instruction *ir, void *data);
+
+   ir_function *current_function;
+
+   struct hash_table *ht;
+};
+
+
+ir_visitor_status
+ir_validate::visit(ir_dereference_variable *ir)
+{
+   if ((ir->var == NULL) || (ir->var->as_variable() == NULL)) {
+      printf("ir_dereference_variable @ %p does not specify a variable %p\n",
+            (void *) ir, (void *) ir->var);
+      abort();
+   }
+
+   if (hash_table_find(ht, ir->var) == NULL) {
+      printf("ir_dereference_variable @ %p specifies undeclared variable "
+            "`%s' @ %p\n",
+            (void *) ir, ir->var->name, (void *) ir->var);
+      abort();
+   }
+
+   this->validate_ir(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit(ir_if *ir)
+{
+   if (ir->condition->type != glsl_type::bool_type) {
+      printf("ir_if condition %s type instead of bool.\n",
+            ir->condition->type->name);
+      ir->print();
+      printf("\n");
+      abort();
+   }
+
+   return visit_continue;
+}
+
+
+ir_visitor_status
+ir_validate::visit_enter(ir_function *ir)
+{
+   /* Function definitions cannot be nested.
+    */
+   if (this->current_function != NULL) {
+      printf("Function definition nested inside another function "
+            "definition:\n");
+      printf("%s %p inside %s %p\n",
+            ir->name, (void *) ir,
+            this->current_function->name, (void *) this->current_function);
+      abort();
+   }
+
+   /* Store the current function hierarchy being traversed.  This is used
+    * by the function signature visitor to ensure that the signatures are
+    * linked with the correct functions.
+    */
+   this->current_function = ir;
+
+   this->validate_ir(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit_leave(ir_function *ir)
+{
+   assert(talloc_parent(ir->name) == ir);
+
+   this->current_function = NULL;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit_enter(ir_function_signature *ir)
+{
+   if (this->current_function != ir->function()) {
+      printf("Function signature nested inside wrong function "
+            "definition:\n");
+      printf("%p inside %s %p instead of %s %p\n",
+            (void *) ir,
+            this->current_function->name, (void *) this->current_function,
+            ir->function_name(), (void *) ir->function());
+      abort();
+   }
+
+   this->validate_ir(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit_leave(ir_expression *ir)
+{
+   switch (ir->operation) {
+   case ir_unop_bit_not:
+      assert(ir->operands[0]->type == ir->type);
+      break;
+   case ir_unop_logic_not:
+      assert(ir->type->base_type == GLSL_TYPE_BOOL);
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
+      break;
+
+   case ir_unop_neg:
+   case ir_unop_abs:
+   case ir_unop_sign:
+   case ir_unop_rcp:
+   case ir_unop_rsq:
+   case ir_unop_sqrt:
+      assert(ir->type == ir->operands[0]->type);
+      break;
+
+   case ir_unop_exp:
+   case ir_unop_log:
+   case ir_unop_exp2:
+   case ir_unop_log2:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+      assert(ir->type == ir->operands[0]->type);
+      break;
+
+   case ir_unop_f2i:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+      assert(ir->type->base_type == GLSL_TYPE_INT);
+      break;
+   case ir_unop_i2f:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
+      assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+      break;
+   case ir_unop_f2b:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+      assert(ir->type->base_type == GLSL_TYPE_BOOL);
+      break;
+   case ir_unop_b2f:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
+      assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+      break;
+   case ir_unop_i2b:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
+      assert(ir->type->base_type == GLSL_TYPE_BOOL);
+      break;
+   case ir_unop_b2i:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
+      assert(ir->type->base_type == GLSL_TYPE_INT);
+      break;
+   case ir_unop_u2f:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT);
+      assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+      break;
+
+   case ir_unop_any:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
+      assert(ir->type == glsl_type::bool_type);
+      break;
+
+   case ir_unop_trunc:
+   case ir_unop_ceil:
+   case ir_unop_floor:
+   case ir_unop_fract:
+   case ir_unop_sin:
+   case ir_unop_cos:
+   case ir_unop_dFdx:
+   case ir_unop_dFdy:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+      assert(ir->operands[0]->type == ir->type);
+      break;
+
+   case ir_binop_add:
+   case ir_binop_sub:
+   case ir_binop_mul:
+   case ir_binop_div:
+   case ir_binop_mod:
+   case ir_binop_min:
+   case ir_binop_max:
+   case ir_binop_pow:
+      if (ir->operands[0]->type->is_scalar())
+        assert(ir->operands[1]->type == ir->type);
+      else if (ir->operands[1]->type->is_scalar())
+        assert(ir->operands[0]->type == ir->type);
+      else if (ir->operands[0]->type->is_vector() &&
+              ir->operands[1]->type->is_vector()) {
+        assert(ir->operands[0]->type == ir->operands[1]->type);
+        assert(ir->operands[0]->type == ir->type);
+      }
+      break;
+   case ir_binop_less:
+   case ir_binop_greater:
+   case ir_binop_lequal:
+   case ir_binop_gequal:
+      /* GLSL < > <= >= operators take scalar floats/ints, but in the
+       * IR we may want to do them for vectors instead to support the
+       * lessEqual() and friends builtins.
+       */
+      assert(ir->type == glsl_type::bool_type);
+      assert(ir->operands[0]->type == ir->operands[1]->type);
+      break;
+
+   case ir_binop_equal:
+   case ir_binop_nequal:
+      /* GLSL == and != operate on vectors and return a bool, and the
+       * IR matches that.  We may want to switch up the IR to work on
+       * vectors and return a bvec and make the operators break down
+       * to ANDing/ORing the results of the vector comparison.
+       */
+      assert(ir->type == glsl_type::bool_type);
+      assert(ir->operands[0]->type == ir->operands[1]->type);
+      break;
+
+   case ir_binop_lshift:
+   case ir_binop_rshift:
+   case ir_binop_bit_and:
+   case ir_binop_bit_xor:
+   case ir_binop_bit_or:
+      assert(ir->operands[0]->type == ir->operands[1]->type);
+      assert(ir->type == ir->operands[0]->type);
+      assert(ir->type->base_type == GLSL_TYPE_INT ||
+            ir->type->base_type == GLSL_TYPE_UINT);
+      break;
+
+   case ir_binop_logic_and:
+   case ir_binop_logic_xor:
+   case ir_binop_logic_or:
+      assert(ir->type == glsl_type::bool_type);
+      assert(ir->operands[0]->type == glsl_type::bool_type);
+      assert(ir->operands[1]->type == glsl_type::bool_type);
+      break;
+
+   case ir_binop_dot:
+      assert(ir->type == glsl_type::float_type);
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+      assert(ir->operands[0]->type == ir->operands[1]->type);
+      break;
+
+   case ir_binop_cross:
+      assert(ir->operands[0]->type == glsl_type::vec3_type);
+      assert(ir->operands[1]->type == glsl_type::vec3_type);
+      assert(ir->type == glsl_type::vec3_type);
+      break;
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit(ir_variable *ir)
+{
+   /* An ir_variable is the one thing that can (and will) appear multiple times
+    * in an IR tree.  It is added to the hashtable so that it can be used
+    * in the ir_dereference_variable handler to ensure that a variable is
+    * declared before it is dereferenced.
+    */
+   if (ir->name)
+      assert(talloc_parent(ir->name) == ir);
+
+   hash_table_insert(ht, ir, ir);
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit_enter(ir_assignment *ir)
+{
+   const ir_dereference *const lhs = ir->lhs;
+   if (lhs->type->is_scalar() || lhs->type->is_vector()) {
+      if (ir->write_mask == 0) {
+        printf("Assignment LHS is %s, but write mask is 0:\n",
+               lhs->type->is_scalar() ? "scalar" : "vector");
+        ir->print();
+        abort();
+      }
+
+      /* Mask of fields that do not exist in the destination.  These should
+       * not be written by the assignment.
+       */
+      const unsigned invalid_mask = ~((1U << lhs->type->components()) - 1);
+
+      if ((invalid_mask & ir->write_mask) != 0) {
+        printf("Assignment write mask enables invalid components for "
+               "type %s:\n", lhs->type->name);
+        ir->print();
+        abort();
+      }
+   }
+
+   this->validate_ir(ir, this->data);
+
+   return visit_continue;
+}
+
+void
+ir_validate::validate_ir(ir_instruction *ir, void *data)
+{
+   struct hash_table *ht = (struct hash_table *) data;
+
+   if (hash_table_find(ht, ir)) {
+      printf("Instruction node present twice in ir tree:\n");
+      ir->print();
+      printf("\n");
+      abort();
+   }
+   hash_table_insert(ht, ir, ir);
+}
+
+void
+check_node_type(ir_instruction *ir, void *data)
+{
+   (void) data;
+
+   if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) {
+      printf("Instruction node with unset type\n");
+      ir->print(); printf("\n");
+   }
+   assert(ir->type != glsl_type::error_type);
+}
+
+void
+validate_ir_tree(exec_list *instructions)
+{
+   ir_validate v;
+
+   v.run(instructions);
+
+   foreach_iter(exec_list_iterator, iter, *instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+
+      visit_tree(ir, check_node_type, NULL);
+   }
+}
diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp
new file mode 100644 (file)
index 0000000..e638c96
--- /dev/null
@@ -0,0 +1,415 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 "ir.h"
+#include "glsl_parser_extras.h"
+#include "glsl_symbol_table.h"
+#include "builtin_variables.h"
+
+static void generate_ARB_draw_buffers_variables(exec_list *,
+                                               struct _mesa_glsl_parse_state *,
+                                               bool, _mesa_glsl_parser_targets);
+
+static ir_variable *
+add_variable(const char *name, enum ir_variable_mode mode, int slot,
+            const glsl_type *type, exec_list *instructions,
+                    glsl_symbol_table *symtab)
+{
+   ir_variable *var = new(symtab) ir_variable(type, name, mode);
+
+   switch (var->mode) {
+   case ir_var_auto:
+   case ir_var_in:
+   case ir_var_uniform:
+      var->read_only = true;
+      break;
+   case ir_var_inout:
+   case ir_var_out:
+      break;
+   default:
+      assert(0);
+      break;
+   }
+
+   var->location = slot;
+
+   /* Once the variable is created an initialized, add it to the symbol table
+    * and add the declaration to the IR stream.
+    */
+   instructions->push_tail(var);
+
+   symtab->add_variable(var->name, var);
+   return var;
+}
+
+static ir_variable *
+add_uniform(exec_list *instructions,
+           struct _mesa_glsl_parse_state *state,
+           const char *name, const glsl_type *type)
+{
+   return add_variable(name, ir_var_uniform, -1, type, instructions,
+                      state->symbols);
+}
+
+static void
+add_builtin_variable(const builtin_variable *proto, exec_list *instructions,
+                    glsl_symbol_table *symtab)
+{
+   /* Create a new variable declaration from the description supplied by
+    * the caller.
+    */
+   const glsl_type *const type = symtab->get_type(proto->type);
+
+   assert(type != NULL);
+
+   add_variable(proto->name, proto->mode, proto->slot, type, instructions,
+               symtab);
+}
+
+static void
+add_builtin_constant(exec_list *instructions,
+                    struct _mesa_glsl_parse_state *state,
+                    const char *name, int value)
+{
+   ir_variable *const var = add_variable(name, ir_var_auto,
+                                        -1, glsl_type::int_type,
+                                        instructions, state->symbols);
+   var->constant_value = new(var) ir_constant(value);
+}
+
+static void
+generate_110_uniforms(exec_list *instructions,
+                     struct _mesa_glsl_parse_state *state)
+{
+   for (unsigned i = 0
+          ; i < Elements(builtin_110_deprecated_uniforms)
+          ; i++) {
+      add_builtin_variable(& builtin_110_deprecated_uniforms[i],
+                          instructions, state->symbols);
+   }
+
+   add_builtin_constant(instructions, state, "gl_MaxLights",
+                       state->Const.MaxLights);
+   add_builtin_constant(instructions, state, "gl_MaxClipPlanes",
+                       state->Const.MaxClipPlanes);
+   add_builtin_constant(instructions, state, "gl_MaxTextureUnits",
+                       state->Const.MaxTextureUnits);
+   add_builtin_constant(instructions, state, "gl_MaxTextureCoords",
+                       state->Const.MaxTextureCoords);
+   add_builtin_constant(instructions, state, "gl_MaxVertexAttribs",
+                       state->Const.MaxVertexAttribs);
+   add_builtin_constant(instructions, state, "gl_MaxVertexUniformComponents",
+                       state->Const.MaxVertexUniformComponents);
+   add_builtin_constant(instructions, state, "gl_MaxVaryingFloats",
+                       state->Const.MaxVaryingFloats);
+   add_builtin_constant(instructions, state, "gl_MaxVertexTextureImageUnits",
+                       state->Const.MaxVertexTextureImageUnits);
+   add_builtin_constant(instructions, state, "gl_MaxCombinedTextureImageUnits",
+                       state->Const.MaxCombinedTextureImageUnits);
+   add_builtin_constant(instructions, state, "gl_MaxTextureImageUnits",
+                       state->Const.MaxTextureImageUnits);
+   add_builtin_constant(instructions, state, "gl_MaxFragmentUniformComponents",
+                       state->Const.MaxFragmentUniformComponents);
+
+   const glsl_type *const mat4_array_type =
+      glsl_type::get_array_instance(glsl_type::mat4_type,
+                                   state->Const.MaxTextureCoords);
+
+   add_uniform(instructions, state, "gl_TextureMatrix", mat4_array_type);
+
+   add_uniform(instructions, state, "gl_DepthRange",
+               state->symbols->get_type("gl_DepthRangeParameters"));
+
+   add_uniform(instructions, state, "gl_ClipPlane",
+              glsl_type::get_array_instance(glsl_type::vec4_type,
+                                            state->Const.MaxClipPlanes));
+   add_uniform(instructions, state, "gl_Point",
+              state->symbols->get_type("gl_PointParameters"));
+
+   const glsl_type *const material_parameters_type =
+      state->symbols->get_type("gl_MaterialParameters");
+   add_uniform(instructions, state, "gl_FrontMaterial", material_parameters_type);
+   add_uniform(instructions, state, "gl_BackMaterial", material_parameters_type);
+
+   const glsl_type *const light_source_array_type =
+      glsl_type::get_array_instance(state->symbols->get_type("gl_LightSourceParameters"), state->Const.MaxLights);
+
+   add_uniform(instructions, state, "gl_LightSource", light_source_array_type);
+
+   const glsl_type *const light_model_products_type =
+      state->symbols->get_type("gl_LightModelProducts");
+   add_uniform(instructions, state, "gl_FrontLightModelProduct",
+              light_model_products_type);
+   add_uniform(instructions, state, "gl_BackLightModelProduct",
+              light_model_products_type);
+
+   const glsl_type *const light_products_type =
+      glsl_type::get_array_instance(state->symbols->get_type("gl_LightProducts"),
+                                   state->Const.MaxLights);
+   add_uniform(instructions, state, "gl_FrontLightProduct", light_products_type);
+   add_uniform(instructions, state, "gl_BackLightProduct", light_products_type);
+
+   add_uniform(instructions, state, "gl_TextureEnvColor",
+              glsl_type::get_array_instance(glsl_type::vec4_type,
+                                            state->Const.MaxTextureUnits));
+
+   const glsl_type *const texcoords_vec4 =
+      glsl_type::get_array_instance(glsl_type::vec4_type,
+                                   state->Const.MaxTextureCoords);
+   add_uniform(instructions, state, "gl_EyePlaneS", texcoords_vec4);
+   add_uniform(instructions, state, "gl_EyePlaneT", texcoords_vec4);
+   add_uniform(instructions, state, "gl_EyePlaneR", texcoords_vec4);
+   add_uniform(instructions, state, "gl_EyePlaneQ", texcoords_vec4);
+   add_uniform(instructions, state, "gl_ObjectPlaneS", texcoords_vec4);
+   add_uniform(instructions, state, "gl_ObjectPlaneT", texcoords_vec4);
+   add_uniform(instructions, state, "gl_ObjectPlaneR", texcoords_vec4);
+   add_uniform(instructions, state, "gl_ObjectPlaneQ", texcoords_vec4);
+
+   add_uniform(instructions, state, "gl_Fog",
+              state->symbols->get_type("gl_FogParameters"));
+}
+
+static void
+generate_110_vs_variables(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state)
+{
+   for (unsigned i = 0; i < Elements(builtin_core_vs_variables); i++) {
+      add_builtin_variable(& builtin_core_vs_variables[i],
+                          instructions, state->symbols);
+   }
+
+   for (unsigned i = 0
+          ; i < Elements(builtin_110_deprecated_vs_variables)
+          ; i++) {
+      add_builtin_variable(& builtin_110_deprecated_vs_variables[i],
+                          instructions, state->symbols);
+   }
+   generate_110_uniforms(instructions, state);
+
+   /* From page 54 (page 60 of the PDF) of the GLSL 1.20 spec:
+    *
+    *     "As with all arrays, indices used to subscript gl_TexCoord must
+    *     either be an integral constant expressions, or this array must be
+    *     re-declared by the shader with a size. The size can be at most
+    *     gl_MaxTextureCoords. Using indexes close to 0 may aid the
+    *     implementation in preserving varying resources."
+    */
+   const glsl_type *const vec4_array_type =
+      glsl_type::get_array_instance(glsl_type::vec4_type, 0);
+
+   add_variable("gl_TexCoord", ir_var_out, VERT_RESULT_TEX0, vec4_array_type,
+               instructions, state->symbols);
+
+   generate_ARB_draw_buffers_variables(instructions, state, false,
+                                      vertex_shader);
+}
+
+
+static void
+generate_120_vs_variables(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state)
+{
+   /* GLSL version 1.20 did not add any built-in variables in the vertex
+    * shader.
+    */
+   generate_110_vs_variables(instructions, state);
+}
+
+
+static void
+generate_130_vs_variables(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state)
+{
+   generate_120_vs_variables(instructions, state);
+
+   for (unsigned i = 0; i < Elements(builtin_130_vs_variables); i++) {
+      add_builtin_variable(& builtin_130_vs_variables[i],
+                          instructions, state->symbols);
+   }
+
+   const glsl_type *const clip_distance_array_type =
+      glsl_type::get_array_instance(glsl_type::float_type,
+                                   state->Const.MaxClipPlanes);
+
+   /* FINISHME: gl_ClipDistance needs a real location assigned. */
+   add_variable("gl_ClipDistance", ir_var_out, -1, clip_distance_array_type,
+               instructions, state->symbols);
+
+}
+
+
+static void
+initialize_vs_variables(exec_list *instructions,
+                       struct _mesa_glsl_parse_state *state)
+{
+
+   switch (state->language_version) {
+   case 110:
+      generate_110_vs_variables(instructions, state);
+      break;
+   case 120:
+      generate_120_vs_variables(instructions, state);
+      break;
+   case 130:
+      generate_130_vs_variables(instructions, state);
+      break;
+   }
+}
+
+static void
+generate_110_fs_variables(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state)
+{
+   for (unsigned i = 0; i < Elements(builtin_core_fs_variables); i++) {
+      add_builtin_variable(& builtin_core_fs_variables[i],
+                          instructions, state->symbols);
+   }
+
+   for (unsigned i = 0
+          ; i < Elements(builtin_110_deprecated_fs_variables)
+          ; i++) {
+      add_builtin_variable(& builtin_110_deprecated_fs_variables[i],
+                          instructions, state->symbols);
+   }
+   generate_110_uniforms(instructions, state);
+
+   /* From page 54 (page 60 of the PDF) of the GLSL 1.20 spec:
+    *
+    *     "As with all arrays, indices used to subscript gl_TexCoord must
+    *     either be an integral constant expressions, or this array must be
+    *     re-declared by the shader with a size. The size can be at most
+    *     gl_MaxTextureCoords. Using indexes close to 0 may aid the
+    *     implementation in preserving varying resources."
+    */
+   const glsl_type *const vec4_array_type =
+      glsl_type::get_array_instance(glsl_type::vec4_type, 0);
+
+   add_variable("gl_TexCoord", ir_var_in, FRAG_ATTRIB_TEX0, vec4_array_type,
+               instructions, state->symbols);
+
+   generate_ARB_draw_buffers_variables(instructions, state, false,
+                                      fragment_shader);
+}
+
+
+static void
+generate_ARB_draw_buffers_variables(exec_list *instructions,
+                                   struct _mesa_glsl_parse_state *state,
+                                   bool warn, _mesa_glsl_parser_targets target)
+{
+   /* gl_MaxDrawBuffers is available in all shader stages.
+    */
+   ir_variable *const mdb =
+      add_variable("gl_MaxDrawBuffers", ir_var_auto, -1,
+                  glsl_type::int_type, instructions, state->symbols);
+
+   if (warn)
+      mdb->warn_extension = "GL_ARB_draw_buffers";
+
+   mdb->constant_value = new(mdb)
+      ir_constant(int(state->Const.MaxDrawBuffers));
+
+
+   /* gl_FragData is only available in the fragment shader.
+    */
+   if (target == fragment_shader) {
+      const glsl_type *const vec4_array_type =
+        glsl_type::get_array_instance(glsl_type::vec4_type,
+                                      state->Const.MaxDrawBuffers);
+
+      ir_variable *const fd =
+        add_variable("gl_FragData", ir_var_out, FRAG_RESULT_DATA0,
+                     vec4_array_type, instructions, state->symbols);
+
+      if (warn)
+        fd->warn_extension = "GL_ARB_draw_buffers";
+   }
+}
+
+
+static void
+generate_120_fs_variables(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state)
+{
+   generate_110_fs_variables(instructions, state);
+
+   for (unsigned i = 0
+          ; i < Elements(builtin_120_fs_variables)
+          ; i++) {
+      add_builtin_variable(& builtin_120_fs_variables[i],
+                          instructions, state->symbols);
+   }
+}
+
+static void
+generate_130_fs_variables(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state)
+{
+   generate_120_fs_variables(instructions, state);
+
+   const glsl_type *const clip_distance_array_type =
+      glsl_type::get_array_instance(glsl_type::float_type,
+                                   state->Const.MaxClipPlanes);
+
+   /* FINISHME: gl_ClipDistance needs a real location assigned. */
+   add_variable("gl_ClipDistance", ir_var_in, -1, clip_distance_array_type,
+               instructions, state->symbols);
+}
+
+static void
+initialize_fs_variables(exec_list *instructions,
+                       struct _mesa_glsl_parse_state *state)
+{
+
+   switch (state->language_version) {
+   case 110:
+      generate_110_fs_variables(instructions, state);
+      break;
+   case 120:
+      generate_120_fs_variables(instructions, state);
+      break;
+   case 130:
+      generate_130_fs_variables(instructions, state);
+      break;
+   }
+}
+
+void
+_mesa_glsl_initialize_variables(exec_list *instructions,
+                               struct _mesa_glsl_parse_state *state)
+{
+   switch (state->target) {
+   case vertex_shader:
+      initialize_vs_variables(instructions, state);
+      break;
+   case geometry_shader:
+      break;
+   case fragment_shader:
+      initialize_fs_variables(instructions, state);
+      break;
+   case ir_shader:
+      fprintf(stderr, "ir reader has no builtin variables");
+      exit(1);
+      break;
+   }
+}
diff --git a/src/glsl/ir_variable_refcount.cpp b/src/glsl/ir_variable_refcount.cpp
new file mode 100644 (file)
index 0000000..7d39abb
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_variable_refcount.cpp
+ *
+ * Provides a visitor which produces a list of variables referenced,
+ * how many times they were referenced and assigned, and whether they
+ * were defined in the scope.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_variable_refcount.h"
+#include "glsl_types.h"
+
+
+// constructor
+variable_entry::variable_entry(ir_variable *var)
+{
+   this->var = var;
+   assign = NULL;
+   assigned_count = 0;
+   declaration = false;
+   referenced_count = 0;
+}
+
+
+variable_entry *
+ir_variable_refcount_visitor::get_variable_entry(ir_variable *var)
+{
+   assert(var);
+   foreach_iter(exec_list_iterator, iter, this->variable_list) {
+      variable_entry *entry = (variable_entry *)iter.get();
+      if (entry->var == var)
+        return entry;
+   }
+
+   variable_entry *entry = new(mem_ctx) variable_entry(var);
+   assert(entry->referenced_count == 0);
+   this->variable_list.push_tail(entry);
+   return entry;
+}
+
+
+ir_visitor_status
+ir_variable_refcount_visitor::visit(ir_variable *ir)
+{
+   variable_entry *entry = this->get_variable_entry(ir);
+   if (entry)
+      entry->declaration = true;
+
+   return visit_continue;
+}
+
+
+ir_visitor_status
+ir_variable_refcount_visitor::visit(ir_dereference_variable *ir)
+{
+   ir_variable *const var = ir->variable_referenced();
+   variable_entry *entry = this->get_variable_entry(var);
+
+   if (entry)
+      entry->referenced_count++;
+
+   return visit_continue;
+}
+
+
+ir_visitor_status
+ir_variable_refcount_visitor::visit_enter(ir_function_signature *ir)
+{
+   /* We don't want to descend into the function parameters and
+    * dead-code eliminate them, so just accept the body here.
+    */
+   visit_list_elements(this, &ir->body);
+   return visit_continue_with_parent;
+}
+
+
+ir_visitor_status
+ir_variable_refcount_visitor::visit_leave(ir_assignment *ir)
+{
+   variable_entry *entry;
+   entry = this->get_variable_entry(ir->lhs->variable_referenced());
+   if (entry) {
+      entry->assigned_count++;
+      if (entry->assign == NULL)
+        entry->assign = ir;
+   }
+
+   return visit_continue;
+}
diff --git a/src/glsl/ir_variable_refcount.h b/src/glsl/ir_variable_refcount.h
new file mode 100644 (file)
index 0000000..8b43bad
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_variable_refcount.h
+ *
+ * Provides a visitor which produces a list of variables referenced,
+ * how many times they were referenced and assigned, and whether they
+ * were defined in the scope.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "glsl_types.h"
+
+class variable_entry : public exec_node
+{
+public:
+   variable_entry(ir_variable *var);
+
+   ir_variable *var; /* The key: the variable's pointer. */
+   ir_assignment *assign; /* An assignment to the variable, if any */
+
+   /** Number of times the variable is referenced, including assignments. */
+   unsigned referenced_count;
+
+   /** Number of times the variable is assigned. */
+   unsigned assigned_count;
+
+   bool declaration; /* If the variable had a decl in the instruction stream */
+};
+
+class ir_variable_refcount_visitor : public ir_hierarchical_visitor {
+public:
+   ir_variable_refcount_visitor(void)
+   {
+      this->mem_ctx = talloc_new(NULL);
+      this->variable_list.make_empty();
+   }
+
+   ~ir_variable_refcount_visitor(void)
+   {
+      talloc_free(this->mem_ctx);
+   }
+
+   virtual ir_visitor_status visit(ir_variable *);
+   virtual ir_visitor_status visit(ir_dereference_variable *);
+
+   virtual ir_visitor_status visit_enter(ir_function_signature *);
+   virtual ir_visitor_status visit_leave(ir_assignment *);
+
+   variable_entry *get_variable_entry(ir_variable *var);
+
+   /* List of variable_entry */
+   exec_list variable_list;
+
+   void *mem_ctx;
+};
diff --git a/src/glsl/ir_vec_index_to_cond_assign.cpp b/src/glsl/ir_vec_index_to_cond_assign.cpp
new file mode 100644 (file)
index 0000000..cd8dedf
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_vec_index_to_cond_assign.cpp
+ *
+ * Turns indexing into vector types to a series of conditional moves
+ * of each channel's swizzle into a temporary.
+ *
+ * Most GPUs don't have a native way to do this operation, and this
+ * works around that.  For drivers using both this pass and
+ * ir_vec_index_to_swizzle, there's a risk that this pass will happen
+ * before sufficient constant folding to find that the array index is
+ * constant.  However, we hope that other optimization passes,
+ * particularly constant folding of assignment conditions and copy
+ * propagation, will result in the same code in the end.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+/**
+ * Visitor class for replacing expressions with ir_constant values.
+ */
+
+class ir_vec_index_to_cond_assign_visitor : public ir_hierarchical_visitor {
+public:
+   ir_vec_index_to_cond_assign_visitor()
+   {
+      progress = false;
+   }
+
+   ir_rvalue *convert_vec_index_to_cond_assign(ir_rvalue *val);
+
+   virtual ir_visitor_status visit_enter(ir_expression *);
+   virtual ir_visitor_status visit_enter(ir_swizzle *);
+   virtual ir_visitor_status visit_leave(ir_assignment *);
+   virtual ir_visitor_status visit_enter(ir_return *);
+   virtual ir_visitor_status visit_enter(ir_call *);
+   virtual ir_visitor_status visit_enter(ir_if *);
+
+   bool progress;
+};
+
+ir_rvalue *
+ir_vec_index_to_cond_assign_visitor::convert_vec_index_to_cond_assign(ir_rvalue *ir)
+{
+   ir_dereference_array *orig_deref = ir->as_dereference_array();
+   ir_assignment *assign;
+   ir_variable *index, *var;
+   ir_dereference *deref;
+   ir_expression *condition;
+   ir_swizzle *swizzle;
+   int i;
+
+   if (!orig_deref)
+      return ir;
+
+   if (orig_deref->array->type->is_matrix() ||
+       orig_deref->array->type->is_array())
+      return ir;
+
+   void *mem_ctx = talloc_parent(ir);
+
+   assert(orig_deref->array_index->type->base_type == GLSL_TYPE_INT);
+
+   /* Store the index to a temporary to avoid reusing its tree. */
+   index = new(base_ir) ir_variable(glsl_type::int_type,
+                                   "vec_index_tmp_i",
+                                   ir_var_temporary);
+   base_ir->insert_before(index);
+   deref = new(base_ir) ir_dereference_variable(index);
+   assign = new(base_ir) ir_assignment(deref, orig_deref->array_index, NULL);
+   base_ir->insert_before(assign);
+
+   /* Temporary where we store whichever value we swizzle out. */
+   var = new(base_ir) ir_variable(ir->type, "vec_index_tmp_v",
+                                 ir_var_temporary);
+   base_ir->insert_before(var);
+
+   /* Generate a conditional move of each vector element to the temp. */
+   for (i = 0; i < orig_deref->array->type->vector_elements; i++) {
+      deref = new(base_ir) ir_dereference_variable(index);
+      condition = new(base_ir) ir_expression(ir_binop_equal,
+                                            glsl_type::bool_type,
+                                            deref,
+                                            new(base_ir) ir_constant(i));
+
+      /* Just clone the rest of the deref chain when trying to get at the
+       * underlying variable.
+       */
+      swizzle = new(base_ir) ir_swizzle(orig_deref->array->clone(mem_ctx, NULL),
+                                       i, 0, 0, 0, 1);
+
+      deref = new(base_ir) ir_dereference_variable(var);
+      assign = new(base_ir) ir_assignment(deref, swizzle, condition);
+      base_ir->insert_before(assign);
+   }
+
+   this->progress = true;
+   return new(base_ir) ir_dereference_variable(var);
+}
+
+ir_visitor_status
+ir_vec_index_to_cond_assign_visitor::visit_enter(ir_expression *ir)
+{
+   unsigned int i;
+
+   for (i = 0; i < ir->get_num_operands(); i++) {
+      ir->operands[i] = convert_vec_index_to_cond_assign(ir->operands[i]);
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_cond_assign_visitor::visit_enter(ir_swizzle *ir)
+{
+   /* Can't be hit from normal GLSL, since you can't swizzle a scalar (which
+    * the result of indexing a vector is.  But maybe at some point we'll end up
+    * using swizzling of scalars for vector construction.
+    */
+   ir->val = convert_vec_index_to_cond_assign(ir->val);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_cond_assign_visitor::visit_leave(ir_assignment *ir)
+{
+   ir_variable *index, *var;
+   ir_dereference_variable *deref;
+   ir_assignment *assign;
+   int i;
+
+   ir->rhs = convert_vec_index_to_cond_assign(ir->rhs);
+   if (ir->condition)
+      ir->condition = convert_vec_index_to_cond_assign(ir->condition);
+
+   /* Last, handle the LHS */
+   ir_dereference_array *orig_deref = ir->lhs->as_dereference_array();
+
+   if (!orig_deref ||
+       orig_deref->array->type->is_matrix() ||
+       orig_deref->array->type->is_array())
+      return visit_continue;
+
+   void *mem_ctx = talloc_parent(ir);
+
+   assert(orig_deref->array_index->type->base_type == GLSL_TYPE_INT);
+
+   /* Store the index to a temporary to avoid reusing its tree. */
+   index = new(ir) ir_variable(glsl_type::int_type, "vec_index_tmp_i",
+                              ir_var_temporary);
+   ir->insert_before(index);
+   deref = new(ir) ir_dereference_variable(index);
+   assign = new(ir) ir_assignment(deref, orig_deref->array_index, NULL);
+   ir->insert_before(assign);
+
+   /* Store the RHS to a temporary to avoid reusing its tree. */
+   var = new(ir) ir_variable(ir->rhs->type, "vec_index_tmp_v",
+                            ir_var_temporary);
+   ir->insert_before(var);
+   deref = new(ir) ir_dereference_variable(var);
+   assign = new(ir) ir_assignment(deref, ir->rhs, NULL);
+   ir->insert_before(assign);
+
+   /* Generate a conditional move of each vector element to the temp. */
+   for (i = 0; i < orig_deref->array->type->vector_elements; i++) {
+      ir_rvalue *condition, *swizzle;
+
+      deref = new(ir) ir_dereference_variable(index);
+      condition = new(ir) ir_expression(ir_binop_equal,
+                                       glsl_type::bool_type,
+                                       deref,
+                                       new(ir) ir_constant(i));
+
+      /* Just clone the rest of the deref chain when trying to get at the
+       * underlying variable.
+       */
+      swizzle = new(ir) ir_swizzle(orig_deref->array->clone(mem_ctx, NULL),
+                                  i, 0, 0, 0, 1);
+
+      deref = new(ir) ir_dereference_variable(var);
+      assign = new(ir) ir_assignment(swizzle, deref, condition);
+      ir->insert_before(assign);
+   }
+   ir->remove();
+
+   this->progress = true;
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_cond_assign_visitor::visit_enter(ir_call *ir)
+{
+   foreach_iter(exec_list_iterator, iter, *ir) {
+      ir_rvalue *param = (ir_rvalue *)iter.get();
+      ir_rvalue *new_param = convert_vec_index_to_cond_assign(param);
+
+      if (new_param != param) {
+        param->replace_with(new_param);
+      }
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_cond_assign_visitor::visit_enter(ir_return *ir)
+{
+   if (ir->value) {
+      ir->value = convert_vec_index_to_cond_assign(ir->value);
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_cond_assign_visitor::visit_enter(ir_if *ir)
+{
+   ir->condition = convert_vec_index_to_cond_assign(ir->condition);
+
+   return visit_continue;
+}
+
+bool
+do_vec_index_to_cond_assign(exec_list *instructions)
+{
+   ir_vec_index_to_cond_assign_visitor v;
+
+   visit_list_elements(&v, instructions);
+
+   return v.progress;
+}
diff --git a/src/glsl/ir_vec_index_to_swizzle.cpp b/src/glsl/ir_vec_index_to_swizzle.cpp
new file mode 100644 (file)
index 0000000..969dc8f
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_vec_index_to_swizzle.cpp
+ *
+ * Turns constant indexing into vector types to swizzles.  This will
+ * let other swizzle-aware optimization passes catch these constructs,
+ * and codegen backends not have to worry about this case.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+/**
+ * Visitor class for replacing expressions with ir_constant values.
+ */
+
+class ir_vec_index_to_swizzle_visitor : public ir_hierarchical_visitor {
+public:
+   ir_vec_index_to_swizzle_visitor()
+   {
+      progress = false;
+   }
+
+   ir_rvalue *convert_vec_index_to_swizzle(ir_rvalue *val);
+
+   virtual ir_visitor_status visit_enter(ir_expression *);
+   virtual ir_visitor_status visit_enter(ir_swizzle *);
+   virtual ir_visitor_status visit_enter(ir_assignment *);
+   virtual ir_visitor_status visit_enter(ir_return *);
+   virtual ir_visitor_status visit_enter(ir_call *);
+   virtual ir_visitor_status visit_enter(ir_if *);
+
+   bool progress;
+};
+
+ir_rvalue *
+ir_vec_index_to_swizzle_visitor::convert_vec_index_to_swizzle(ir_rvalue *ir)
+{
+   ir_dereference_array *deref = ir->as_dereference_array();
+   ir_constant *ir_constant;
+
+   if (!deref)
+      return ir;
+
+   if (deref->array->type->is_matrix() || deref->array->type->is_array())
+      return ir;
+
+   assert(deref->array_index->type->base_type == GLSL_TYPE_INT);
+   ir_constant = deref->array_index->constant_expression_value();
+   if (!ir_constant)
+      return ir;
+
+   void *ctx = talloc_parent(ir);
+   this->progress = true;
+   return new(ctx) ir_swizzle(deref->array,
+                             ir_constant->value.i[0], 0, 0, 0, 1);
+}
+
+ir_visitor_status
+ir_vec_index_to_swizzle_visitor::visit_enter(ir_expression *ir)
+{
+   unsigned int i;
+
+   for (i = 0; i < ir->get_num_operands(); i++) {
+      ir->operands[i] = convert_vec_index_to_swizzle(ir->operands[i]);
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_swizzle_visitor::visit_enter(ir_swizzle *ir)
+{
+   /* Can't be hit from normal GLSL, since you can't swizzle a scalar (which
+    * the result of indexing a vector is.  But maybe at some point we'll end up
+    * using swizzling of scalars for vector construction.
+    */
+   ir->val = convert_vec_index_to_swizzle(ir->val);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_swizzle_visitor::visit_enter(ir_assignment *ir)
+{
+   ir->set_lhs(convert_vec_index_to_swizzle(ir->lhs));
+   ir->rhs = convert_vec_index_to_swizzle(ir->rhs);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_swizzle_visitor::visit_enter(ir_call *ir)
+{
+   foreach_iter(exec_list_iterator, iter, *ir) {
+      ir_rvalue *param = (ir_rvalue *)iter.get();
+      ir_rvalue *new_param = convert_vec_index_to_swizzle(param);
+
+      if (new_param != param) {
+        param->replace_with(new_param);
+      }
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_swizzle_visitor::visit_enter(ir_return *ir)
+{
+   if (ir->value) {
+      ir->value = convert_vec_index_to_swizzle(ir->value);
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_vec_index_to_swizzle_visitor::visit_enter(ir_if *ir)
+{
+   ir->condition = convert_vec_index_to_swizzle(ir->condition);
+
+   return visit_continue;
+}
+
+bool
+do_vec_index_to_swizzle(exec_list *instructions)
+{
+   ir_vec_index_to_swizzle_visitor v;
+
+   v.run(instructions);
+
+   return v.progress;
+}
diff --git a/src/glsl/ir_visitor.h b/src/glsl/ir_visitor.h
new file mode 100644 (file)
index 0000000..b87d737
--- /dev/null
@@ -0,0 +1,67 @@
+/* -*- c++ -*- */
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+#pragma once
+#ifndef IR_VISITOR_H
+#define IR_VISITOR_H
+
+/**
+ * Abstract base class of visitors of IR instruction trees
+ */
+class ir_visitor {
+public:
+   virtual ~ir_visitor()
+   {
+      /* empty */
+   }
+
+   /**
+    * \name Visit methods
+    *
+    * As typical for the visitor pattern, there must be one \c visit method for
+    * each concrete subclass of \c ir_instruction.  Virtual base classes within
+    * the hierarchy should not have \c visit methods.
+    */
+   /*@{*/
+   virtual void visit(class ir_variable *) = 0;
+   virtual void visit(class ir_function_signature *) = 0;
+   virtual void visit(class ir_function *) = 0;
+   virtual void visit(class ir_expression *) = 0;
+   virtual void visit(class ir_texture *) = 0;
+   virtual void visit(class ir_swizzle *) = 0;
+   virtual void visit(class ir_dereference_variable *) = 0;
+   virtual void visit(class ir_dereference_array *) = 0;
+   virtual void visit(class ir_dereference_record *) = 0;
+   virtual void visit(class ir_assignment *) = 0;
+   virtual void visit(class ir_constant *) = 0;
+   virtual void visit(class ir_call *) = 0;
+   virtual void visit(class ir_return *) = 0;
+   virtual void visit(class ir_discard *) = 0;
+   virtual void visit(class ir_if *) = 0;
+   virtual void visit(class ir_loop *) = 0;
+   virtual void visit(class ir_loop_jump *) = 0;
+   /*@}*/
+};
+
+#endif /* IR_VISITOR_H */
diff --git a/src/glsl/link_functions.cpp b/src/glsl/link_functions.cpp
new file mode 100644 (file)
index 0000000..78c8b48
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 <cstdlib>
+#include <cstdio>
+#include <cstdarg>
+
+extern "C" {
+#include <talloc.h>
+}
+
+#include "main/core.h"
+#include "glsl_symbol_table.h"
+#include "glsl_parser_extras.h"
+#include "ir.h"
+#include "program.h"
+#include "program/hash_table.h"
+#include "linker.h"
+
+static ir_function_signature *
+find_matching_signature(const char *name, const exec_list *actual_parameters,
+                       gl_shader **shader_list, unsigned num_shaders);
+
+class call_link_visitor : public ir_hierarchical_visitor {
+public:
+   call_link_visitor(gl_shader_program *prog, gl_shader *linked,
+                    gl_shader **shader_list, unsigned num_shaders)
+   {
+      this->prog = prog;
+      this->shader_list = shader_list;
+      this->num_shaders = num_shaders;
+      this->success = true;
+      this->linked = linked;
+
+      this->locals = hash_table_ctor(0, hash_table_pointer_hash,
+                                    hash_table_pointer_compare);
+   }
+
+   ~call_link_visitor()
+   {
+      hash_table_dtor(this->locals);
+   }
+
+   virtual ir_visitor_status visit(ir_variable *ir)
+   {
+      hash_table_insert(locals, ir, ir);
+      return visit_continue;
+   }
+
+   virtual ir_visitor_status visit_enter(ir_call *ir)
+   {
+      /* If ir is an ir_call from a function that was imported from another
+       * shader callee will point to an ir_function_signature in the original
+       * shader.  In this case the function signature MUST NOT BE MODIFIED.
+       * Doing so will modify the original shader.  This may prevent that
+       * shader from being linkable in other programs.
+       */
+      const ir_function_signature *const callee = ir->get_callee();
+      assert(callee != NULL);
+      const char *const name = callee->function_name();
+
+      /* Determine if the requested function signature already exists in the
+       * final linked shader.  If it does, use it as the target of the call.
+       */
+      ir_function_signature *sig =
+        find_matching_signature(name, &callee->parameters, &linked, 1);
+      if (sig != NULL) {
+        ir->set_callee(sig);
+        return visit_continue;
+      }
+
+      /* Try to find the signature in one of the other shaders that is being
+       * linked.  If it's not found there, return an error.
+       */
+      sig = find_matching_signature(name, &ir->actual_parameters, shader_list,
+                                   num_shaders);
+      if (sig == NULL) {
+        /* FINISHME: Log the full signature of unresolved function.
+         */
+        linker_error_printf(this->prog, "unresolved reference to function "
+                            "`%s'\n", name);
+        this->success = false;
+        return visit_stop;
+      }
+
+      /* Find the prototype information in the linked shader.  Generate any
+       * details that may be missing.
+       */
+      ir_function *f = linked->symbols->get_function(name);
+      if (f == NULL)
+        f = new(linked) ir_function(name);
+
+      ir_function_signature *linked_sig =
+        f->exact_matching_signature(&callee->parameters);
+      if (linked_sig == NULL) {
+        linked_sig = new(linked) ir_function_signature(callee->return_type);
+        f->add_signature(linked_sig);
+      }
+
+      /* At this point linked_sig and called may be the same.  If ir is an
+       * ir_call from linked then linked_sig and callee will be
+       * ir_function_signatures that have no definitions (is_defined is false).
+       */
+      assert(!linked_sig->is_defined);
+      assert(linked_sig->body.is_empty());
+
+      /* Create an in-place clone of the function definition.  This multistep
+       * process introduces some complexity here, but it has some advantages.
+       * The parameter list and the and function body are cloned separately.
+       * The clone of the parameter list is used to prime the hashtable used
+       * to replace variable references in the cloned body.
+       *
+       * The big advantage is that the ir_function_signature does not change.
+       * This means that we don't have to process the rest of the IR tree to
+       * patch ir_call nodes.  In addition, there is no way to remove or
+       * replace signature stored in a function.  One could easily be added,
+       * but this avoids the need.
+       */
+      struct hash_table *ht = hash_table_ctor(0, hash_table_pointer_hash,
+                                             hash_table_pointer_compare);
+      exec_list formal_parameters;
+      foreach_list_const(node, &sig->parameters) {
+        const ir_instruction *const original = (ir_instruction *) node;
+        assert(const_cast<ir_instruction *>(original)->as_variable());
+
+        ir_instruction *copy = original->clone(linked, ht);
+        formal_parameters.push_tail(copy);
+      }
+
+      linked_sig->replace_parameters(&formal_parameters);
+
+      foreach_list_const(node, &sig->body) {
+        const ir_instruction *const original = (ir_instruction *) node;
+
+        ir_instruction *copy = original->clone(linked, ht);
+        linked_sig->body.push_tail(copy);
+      }
+
+      linked_sig->is_defined = true;
+      hash_table_dtor(ht);
+
+      /* Patch references inside the function to things outside the function
+       * (i.e., function calls and global variables).
+       */
+      linked_sig->accept(this);
+
+      ir->set_callee(linked_sig);
+
+      return visit_continue;
+   }
+
+   virtual ir_visitor_status visit(ir_dereference_variable *ir)
+   {
+      if (hash_table_find(locals, ir->var) == NULL) {
+        /* The non-function variable must be a global, so try to find the
+         * variable in the shader's symbol table.  If the variable is not
+         * found, then it's a global that *MUST* be defined in the original
+         * shader.
+         */
+        ir_variable *var = linked->symbols->get_variable(ir->var->name);
+        if (var == NULL) {
+           /* Clone the ir_variable that the dereference already has and add
+            * it to the linked shader.
+            */
+           var = ir->var->clone(linked, NULL);
+           linked->symbols->add_variable(var->name, var);
+           linked->ir->push_head(var);
+        }
+
+        ir->var = var;
+      }
+
+      return visit_continue;
+   }
+
+   /** Was function linking successful? */
+   bool success;
+
+private:
+   /**
+    * Shader program being linked
+    *
+    * This is only used for logging error messages.
+    */
+   gl_shader_program *prog;
+
+   /** List of shaders available for linking. */
+   gl_shader **shader_list;
+
+   /** Number of shaders available for linking. */
+   unsigned num_shaders;
+
+   /**
+    * Final linked shader
+    *
+    * This is used two ways.  It is used to find global variables in the
+    * linked shader that are accessed by the function.  It is also used to add
+    * global variables from the shader where the function originated.
+    */
+   gl_shader *linked;
+
+   /**
+    * Table of variables local to the function.
+    */
+   hash_table *locals;
+};
+
+
+/**
+ * Searches a list of shaders for a particular function definition
+ */
+ir_function_signature *
+find_matching_signature(const char *name, const exec_list *actual_parameters,
+                       gl_shader **shader_list, unsigned num_shaders)
+{
+   for (unsigned i = 0; i < num_shaders; i++) {
+      ir_function *const f = shader_list[i]->symbols->get_function(name);
+
+      if (f == NULL)
+        continue;
+
+      ir_function_signature *sig = f->matching_signature(actual_parameters);
+
+      if ((sig == NULL) || !sig->is_defined)
+        continue;
+
+      return sig;
+   }
+
+   return NULL;
+}
+
+
+bool
+link_function_calls(gl_shader_program *prog, gl_shader *main,
+                   gl_shader **shader_list, unsigned num_shaders)
+{
+   call_link_visitor v(prog, main, shader_list, num_shaders);
+
+   v.run(main->ir);
+   return v.success;
+}
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
new file mode 100644 (file)
index 0000000..e0823c3
--- /dev/null
@@ -0,0 +1,1501 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file linker.cpp
+ * GLSL linker implementation
+ *
+ * Given a set of shaders that are to be linked to generate a final program,
+ * there are three distinct stages.
+ *
+ * In the first stage shaders are partitioned into groups based on the shader
+ * type.  All shaders of a particular type (e.g., vertex shaders) are linked
+ * together.
+ *
+ *   - Undefined references in each shader are resolve to definitions in
+ *     another shader.
+ *   - Types and qualifiers of uniforms, outputs, and global variables defined
+ *     in multiple shaders with the same name are verified to be the same.
+ *   - Initializers for uniforms and global variables defined
+ *     in multiple shaders with the same name are verified to be the same.
+ *
+ * The result, in the terminology of the GLSL spec, is a set of shader
+ * executables for each processing unit.
+ *
+ * After the first stage is complete, a series of semantic checks are performed
+ * on each of the shader executables.
+ *
+ *   - Each shader executable must define a \c main function.
+ *   - Each vertex shader executable must write to \c gl_Position.
+ *   - Each fragment shader executable must write to either \c gl_FragData or
+ *     \c gl_FragColor.
+ *
+ * In the final stage individual shader executables are linked to create a
+ * complete exectuable.
+ *
+ *   - Types of uniforms defined in multiple shader stages with the same name
+ *     are verified to be the same.
+ *   - Initializers for uniforms defined in multiple shader stages with the
+ *     same name are verified to be the same.
+ *   - Types and qualifiers of outputs defined in one stage are verified to
+ *     be the same as the types and qualifiers of inputs defined with the same
+ *     name in a later stage.
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+#include <cstdlib>
+#include <cstdio>
+#include <cstdarg>
+#include <climits>
+
+extern "C" {
+#include <talloc.h>
+}
+
+#include "main/core.h"
+#include "glsl_symbol_table.h"
+#include "ir.h"
+#include "program.h"
+#include "program/hash_table.h"
+#include "linker.h"
+#include "ir_optimization.h"
+
+/**
+ * Visitor that determines whether or not a variable is ever written.
+ */
+class find_assignment_visitor : public ir_hierarchical_visitor {
+public:
+   find_assignment_visitor(const char *name)
+      : name(name), found(false)
+   {
+      /* empty */
+   }
+
+   virtual ir_visitor_status visit_enter(ir_assignment *ir)
+   {
+      ir_variable *const var = ir->lhs->variable_referenced();
+
+      if (strcmp(name, var->name) == 0) {
+        found = true;
+        return visit_stop;
+      }
+
+      return visit_continue_with_parent;
+   }
+
+   virtual ir_visitor_status visit_enter(ir_call *ir)
+   {
+      exec_list_iterator sig_iter = ir->get_callee()->parameters.iterator();
+      foreach_iter(exec_list_iterator, iter, *ir) {
+        ir_rvalue *param_rval = (ir_rvalue *)iter.get();
+        ir_variable *sig_param = (ir_variable *)sig_iter.get();
+
+        if (sig_param->mode == ir_var_out ||
+            sig_param->mode == ir_var_inout) {
+           ir_variable *var = param_rval->variable_referenced();
+           if (var && strcmp(name, var->name) == 0) {
+              found = true;
+              return visit_stop;
+           }
+        }
+        sig_iter.next();
+      }
+
+      return visit_continue_with_parent;
+   }
+
+   bool variable_found()
+   {
+      return found;
+   }
+
+private:
+   const char *name;       /**< Find writes to a variable with this name. */
+   bool found;             /**< Was a write to the variable found? */
+};
+
+
+/**
+ * Visitor that determines whether or not a variable is ever read.
+ */
+class find_deref_visitor : public ir_hierarchical_visitor {
+public:
+   find_deref_visitor(const char *name)
+      : name(name), found(false)
+   {
+      /* empty */
+   }
+
+   virtual ir_visitor_status visit(ir_dereference_variable *ir)
+   {
+      if (strcmp(this->name, ir->var->name) == 0) {
+        this->found = true;
+        return visit_stop;
+      }
+
+      return visit_continue;
+   }
+
+   bool variable_found() const
+   {
+      return this->found;
+   }
+
+private:
+   const char *name;       /**< Find writes to a variable with this name. */
+   bool found;             /**< Was a write to the variable found? */
+};
+
+
+void
+linker_error_printf(gl_shader_program *prog, const char *fmt, ...)
+{
+   va_list ap;
+
+   prog->InfoLog = talloc_strdup_append(prog->InfoLog, "error: ");
+   va_start(ap, fmt);
+   prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, ap);
+   va_end(ap);
+}
+
+
+void
+invalidate_variable_locations(gl_shader *sh, enum ir_variable_mode mode,
+                             int generic_base)
+{
+   foreach_list(node, sh->ir) {
+      ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+      if ((var == NULL) || (var->mode != (unsigned) mode))
+        continue;
+
+      /* Only assign locations for generic attributes / varyings / etc.
+       */
+      if (var->location >= generic_base)
+         var->location = -1;
+   }
+}
+
+
+/**
+ * Determine the number of attribute slots required for a particular type
+ *
+ * This code is here because it implements the language rules of a specific
+ * GLSL version.  Since it's a property of the language and not a property of
+ * types in general, it doesn't really belong in glsl_type.
+ */
+unsigned
+count_attribute_slots(const glsl_type *t)
+{
+   /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec:
+    *
+    *     "A scalar input counts the same amount against this limit as a vec4,
+    *     so applications may want to consider packing groups of four
+    *     unrelated float inputs together into a vector to better utilize the
+    *     capabilities of the underlying hardware. A matrix input will use up
+    *     multiple locations.  The number of locations used will equal the
+    *     number of columns in the matrix."
+    *
+    * The spec does not explicitly say how arrays are counted.  However, it
+    * should be safe to assume the total number of slots consumed by an array
+    * is the number of entries in the array multiplied by the number of slots
+    * consumed by a single element of the array.
+    */
+
+   if (t->is_array())
+      return t->array_size() * count_attribute_slots(t->element_type());
+
+   if (t->is_matrix())
+      return t->matrix_columns;
+
+   return 1;
+}
+
+
+/**
+ * Verify that a vertex shader executable meets all semantic requirements
+ *
+ * \param shader  Vertex shader executable to be verified
+ */
+bool
+validate_vertex_shader_executable(struct gl_shader_program *prog,
+                                 struct gl_shader *shader)
+{
+   if (shader == NULL)
+      return true;
+
+   find_assignment_visitor find("gl_Position");
+   find.run(shader->ir);
+   if (!find.variable_found()) {
+      linker_error_printf(prog,
+                         "vertex shader does not write to `gl_Position'\n");
+      return false;
+   }
+
+   return true;
+}
+
+
+/**
+ * Verify that a fragment shader executable meets all semantic requirements
+ *
+ * \param shader  Fragment shader executable to be verified
+ */
+bool
+validate_fragment_shader_executable(struct gl_shader_program *prog,
+                                   struct gl_shader *shader)
+{
+   if (shader == NULL)
+      return true;
+
+   find_assignment_visitor frag_color("gl_FragColor");
+   find_assignment_visitor frag_data("gl_FragData");
+
+   frag_color.run(shader->ir);
+   frag_data.run(shader->ir);
+
+   if (frag_color.variable_found() && frag_data.variable_found()) {
+      linker_error_printf(prog,  "fragment shader writes to both "
+                         "`gl_FragColor' and `gl_FragData'\n");
+      return false;
+   }
+
+   return true;
+}
+
+
+/**
+ * Generate a string describing the mode of a variable
+ */
+static const char *
+mode_string(const ir_variable *var)
+{
+   switch (var->mode) {
+   case ir_var_auto:
+      return (var->read_only) ? "global constant" : "global variable";
+
+   case ir_var_uniform: return "uniform";
+   case ir_var_in:      return "shader input";
+   case ir_var_out:     return "shader output";
+   case ir_var_inout:   return "shader inout";
+
+   case ir_var_temporary:
+   default:
+      assert(!"Should not get here.");
+      return "invalid variable";
+   }
+}
+
+
+/**
+ * Perform validation of global variables used across multiple shaders
+ */
+bool
+cross_validate_globals(struct gl_shader_program *prog,
+                      struct gl_shader **shader_list,
+                      unsigned num_shaders,
+                      bool uniforms_only)
+{
+   /* Examine all of the uniforms in all of the shaders and cross validate
+    * them.
+    */
+   glsl_symbol_table variables;
+   for (unsigned i = 0; i < num_shaders; i++) {
+      foreach_list(node, shader_list[i]->ir) {
+        ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+        if (var == NULL)
+           continue;
+
+        if (uniforms_only && (var->mode != ir_var_uniform))
+           continue;
+
+        /* Don't cross validate temporaries that are at global scope.  These
+         * will eventually get pulled into the shaders 'main'.
+         */
+        if (var->mode == ir_var_temporary)
+           continue;
+
+        /* If a global with this name has already been seen, verify that the
+         * new instance has the same type.  In addition, if the globals have
+         * initializers, the values of the initializers must be the same.
+         */
+        ir_variable *const existing = variables.get_variable(var->name);
+        if (existing != NULL) {
+           if (var->type != existing->type) {
+              /* Consider the types to be "the same" if both types are arrays
+               * of the same type and one of the arrays is implicitly sized.
+               * In addition, set the type of the linked variable to the
+               * explicitly sized array.
+               */
+              if (var->type->is_array()
+                  && existing->type->is_array()
+                  && (var->type->fields.array == existing->type->fields.array)
+                  && ((var->type->length == 0)
+                      || (existing->type->length == 0))) {
+                 if (existing->type->length == 0)
+                    existing->type = var->type;
+              } else {
+                 linker_error_printf(prog, "%s `%s' declared as type "
+                                     "`%s' and type `%s'\n",
+                                     mode_string(var),
+                                     var->name, var->type->name,
+                                     existing->type->name);
+                 return false;
+              }
+           }
+
+           /* FINISHME: Handle non-constant initializers.
+            */
+           if (var->constant_value != NULL) {
+              if (existing->constant_value != NULL) {
+                 if (!var->constant_value->has_value(existing->constant_value)) {
+                    linker_error_printf(prog, "initializers for %s "
+                                        "`%s' have differing values\n",
+                                        mode_string(var), var->name);
+                    return false;
+                 }
+              } else
+                 /* If the first-seen instance of a particular uniform did not
+                  * have an initializer but a later instance does, copy the
+                  * initializer to the version stored in the symbol table.
+                  */
+                 /* FINISHME: This is wrong.  The constant_value field should
+                  * FINISHME: not be modified!  Imagine a case where a shader
+                  * FINISHME: without an initializer is linked in two different
+                  * FINISHME: programs with shaders that have differing
+                  * FINISHME: initializers.  Linking with the first will
+                  * FINISHME: modify the shader, and linking with the second
+                  * FINISHME: will fail.
+                  */
+                 existing->constant_value =
+                    var->constant_value->clone(talloc_parent(existing), NULL);
+           }
+        } else
+           variables.add_variable(var->name, var);
+      }
+   }
+
+   return true;
+}
+
+
+/**
+ * Perform validation of uniforms used across multiple shader stages
+ */
+bool
+cross_validate_uniforms(struct gl_shader_program *prog)
+{
+   return cross_validate_globals(prog, prog->_LinkedShaders,
+                                prog->_NumLinkedShaders, true);
+}
+
+
+/**
+ * Validate that outputs from one stage match inputs of another
+ */
+bool
+cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
+                                gl_shader *producer, gl_shader *consumer)
+{
+   glsl_symbol_table parameters;
+   /* FINISHME: Figure these out dynamically. */
+   const char *const producer_stage = "vertex";
+   const char *const consumer_stage = "fragment";
+
+   /* Find all shader outputs in the "producer" stage.
+    */
+   foreach_list(node, producer->ir) {
+      ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+      /* FINISHME: For geometry shaders, this should also look for inout
+       * FINISHME: variables.
+       */
+      if ((var == NULL) || (var->mode != ir_var_out))
+        continue;
+
+      parameters.add_variable(var->name, var);
+   }
+
+
+   /* Find all shader inputs in the "consumer" stage.  Any variables that have
+    * matching outputs already in the symbol table must have the same type and
+    * qualifiers.
+    */
+   foreach_list(node, consumer->ir) {
+      ir_variable *const input = ((ir_instruction *) node)->as_variable();
+
+      /* FINISHME: For geometry shaders, this should also look for inout
+       * FINISHME: variables.
+       */
+      if ((input == NULL) || (input->mode != ir_var_in))
+        continue;
+
+      ir_variable *const output = parameters.get_variable(input->name);
+      if (output != NULL) {
+        /* Check that the types match between stages.
+         */
+        if (input->type != output->type) {
+           linker_error_printf(prog,
+                               "%s shader output `%s' delcared as "
+                               "type `%s', but %s shader input declared "
+                               "as type `%s'\n",
+                               producer_stage, output->name,
+                               output->type->name,
+                               consumer_stage, input->type->name);
+           return false;
+        }
+
+        /* Check that all of the qualifiers match between stages.
+         */
+        if (input->centroid != output->centroid) {
+           linker_error_printf(prog,
+                               "%s shader output `%s' %s centroid qualifier, "
+                               "but %s shader input %s centroid qualifier\n",
+                               producer_stage,
+                               output->name,
+                               (output->centroid) ? "has" : "lacks",
+                               consumer_stage,
+                               (input->centroid) ? "has" : "lacks");
+           return false;
+        }
+
+        if (input->invariant != output->invariant) {
+           linker_error_printf(prog,
+                               "%s shader output `%s' %s invariant qualifier, "
+                               "but %s shader input %s invariant qualifier\n",
+                               producer_stage,
+                               output->name,
+                               (output->invariant) ? "has" : "lacks",
+                               consumer_stage,
+                               (input->invariant) ? "has" : "lacks");
+           return false;
+        }
+
+        if (input->interpolation != output->interpolation) {
+           linker_error_printf(prog,
+                               "%s shader output `%s' specifies %s "
+                               "interpolation qualifier, "
+                               "but %s shader input specifies %s "
+                               "interpolation qualifier\n",
+                               producer_stage,
+                               output->name,
+                               output->interpolation_string(),
+                               consumer_stage,
+                               input->interpolation_string());
+           return false;
+        }
+      }
+   }
+
+   return true;
+}
+
+
+/**
+ * Populates a shaders symbol table with all global declarations
+ */
+static void
+populate_symbol_table(gl_shader *sh)
+{
+   sh->symbols = new(sh) glsl_symbol_table;
+
+   foreach_list(node, sh->ir) {
+      ir_instruction *const inst = (ir_instruction *) node;
+      ir_variable *var;
+      ir_function *func;
+
+      if ((func = inst->as_function()) != NULL) {
+        sh->symbols->add_function(func->name, func);
+      } else if ((var = inst->as_variable()) != NULL) {
+        sh->symbols->add_variable(var->name, var);
+      }
+   }
+}
+
+
+/**
+ * Remap variables referenced in an instruction tree
+ *
+ * This is used when instruction trees are cloned from one shader and placed in
+ * another.  These trees will contain references to \c ir_variable nodes that
+ * do not exist in the target shader.  This function finds these \c ir_variable
+ * references and replaces the references with matching variables in the target
+ * shader.
+ *
+ * If there is no matching variable in the target shader, a clone of the
+ * \c ir_variable is made and added to the target shader.  The new variable is
+ * added to \b both the instruction stream and the symbol table.
+ *
+ * \param inst         IR tree that is to be processed.
+ * \param symbols      Symbol table containing global scope symbols in the
+ *                     linked shader.
+ * \param instructions Instruction stream where new variable declarations
+ *                     should be added.
+ */
+void
+remap_variables(ir_instruction *inst, struct gl_shader *target,
+               hash_table *temps)
+{
+   class remap_visitor : public ir_hierarchical_visitor {
+   public:
+        remap_visitor(struct gl_shader *target,
+                   hash_table *temps)
+      {
+        this->target = target;
+        this->symbols = target->symbols;
+        this->instructions = target->ir;
+        this->temps = temps;
+      }
+
+      virtual ir_visitor_status visit(ir_dereference_variable *ir)
+      {
+        if (ir->var->mode == ir_var_temporary) {
+           ir_variable *var = (ir_variable *) hash_table_find(temps, ir->var);
+
+           assert(var != NULL);
+           ir->var = var;
+           return visit_continue;
+        }
+
+        ir_variable *const existing =
+           this->symbols->get_variable(ir->var->name);
+        if (existing != NULL)
+           ir->var = existing;
+        else {
+           ir_variable *copy = ir->var->clone(this->target, NULL);
+
+           this->symbols->add_variable(copy->name, copy);
+           this->instructions->push_head(copy);
+           ir->var = copy;
+        }
+
+        return visit_continue;
+      }
+
+   private:
+      struct gl_shader *target;
+      glsl_symbol_table *symbols;
+      exec_list *instructions;
+      hash_table *temps;
+   };
+
+   remap_visitor v(target, temps);
+
+   inst->accept(&v);
+}
+
+
+/**
+ * Move non-declarations from one instruction stream to another
+ *
+ * The intended usage pattern of this function is to pass the pointer to the
+ * head sentinel of a list (i.e., a pointer to the list cast to an \c exec_node
+ * pointer) for \c last and \c false for \c make_copies on the first
+ * call.  Successive calls pass the return value of the previous call for
+ * \c last and \c true for \c make_copies.
+ *
+ * \param instructions Source instruction stream
+ * \param last         Instruction after which new instructions should be
+ *                     inserted in the target instruction stream
+ * \param make_copies  Flag selecting whether instructions in \c instructions
+ *                     should be copied (via \c ir_instruction::clone) into the
+ *                     target list or moved.
+ *
+ * \return
+ * The new "last" instruction in the target instruction stream.  This pointer
+ * is suitable for use as the \c last parameter of a later call to this
+ * function.
+ */
+exec_node *
+move_non_declarations(exec_list *instructions, exec_node *last,
+                     bool make_copies, gl_shader *target)
+{
+   hash_table *temps = NULL;
+
+   if (make_copies)
+      temps = hash_table_ctor(0, hash_table_pointer_hash,
+                             hash_table_pointer_compare);
+
+   foreach_list_safe(node, instructions) {
+      ir_instruction *inst = (ir_instruction *) node;
+
+      if (inst->as_function())
+        continue;
+
+      ir_variable *var = inst->as_variable();
+      if ((var != NULL) && (var->mode != ir_var_temporary))
+        continue;
+
+      assert(inst->as_assignment()
+            || ((var != NULL) && (var->mode == ir_var_temporary)));
+
+      if (make_copies) {
+        inst = inst->clone(target, NULL);
+
+        if (var != NULL)
+           hash_table_insert(temps, inst, var);
+        else
+           remap_variables(inst, target, temps);
+      } else {
+        inst->remove();
+      }
+
+      last->insert_after(inst);
+      last = inst;
+   }
+
+   if (make_copies)
+      hash_table_dtor(temps);
+
+   return last;
+}
+
+/**
+ * Get the function signature for main from a shader
+ */
+static ir_function_signature *
+get_main_function_signature(gl_shader *sh)
+{
+   ir_function *const f = sh->symbols->get_function("main");
+   if (f != NULL) {
+      exec_list void_parameters;
+
+      /* Look for the 'void main()' signature and ensure that it's defined.
+       * This keeps the linker from accidentally pick a shader that just
+       * contains a prototype for main.
+       *
+       * We don't have to check for multiple definitions of main (in multiple
+       * shaders) because that would have already been caught above.
+       */
+      ir_function_signature *sig = f->matching_signature(&void_parameters);
+      if ((sig != NULL) && sig->is_defined) {
+        return sig;
+      }
+   }
+
+   return NULL;
+}
+
+
+/**
+ * Combine a group of shaders for a single stage to generate a linked shader
+ *
+ * \note
+ * If this function is supplied a single shader, it is cloned, and the new
+ * shader is returned.
+ */
+static struct gl_shader *
+link_intrastage_shaders(GLcontext *ctx,
+                       struct gl_shader_program *prog,
+                       struct gl_shader **shader_list,
+                       unsigned num_shaders)
+{
+   /* Check that global variables defined in multiple shaders are consistent.
+    */
+   if (!cross_validate_globals(prog, shader_list, num_shaders, false))
+      return NULL;
+
+   /* Check that there is only a single definition of each function signature
+    * across all shaders.
+    */
+   for (unsigned i = 0; i < (num_shaders - 1); i++) {
+      foreach_list(node, shader_list[i]->ir) {
+        ir_function *const f = ((ir_instruction *) node)->as_function();
+
+        if (f == NULL)
+           continue;
+
+        for (unsigned j = i + 1; j < num_shaders; j++) {
+           ir_function *const other =
+              shader_list[j]->symbols->get_function(f->name);
+
+           /* If the other shader has no function (and therefore no function
+            * signatures) with the same name, skip to the next shader.
+            */
+           if (other == NULL)
+              continue;
+
+           foreach_iter (exec_list_iterator, iter, *f) {
+              ir_function_signature *sig =
+                 (ir_function_signature *) iter.get();
+
+              if (!sig->is_defined || f->is_builtin)
+                 continue;
+
+              ir_function_signature *other_sig =
+                 other->exact_matching_signature(& sig->parameters);
+
+              if ((other_sig != NULL) && other_sig->is_defined
+                  && !other_sig->function()->is_builtin) {
+                 linker_error_printf(prog,
+                                     "function `%s' is multiply defined",
+                                     f->name);
+                 return NULL;
+              }
+           }
+        }
+      }
+   }
+
+   /* Find the shader that defines main, and make a clone of it.
+    *
+    * Starting with the clone, search for undefined references.  If one is
+    * found, find the shader that defines it.  Clone the reference and add
+    * it to the shader.  Repeat until there are no undefined references or
+    * until a reference cannot be resolved.
+    */
+   gl_shader *main = NULL;
+   for (unsigned i = 0; i < num_shaders; i++) {
+      if (get_main_function_signature(shader_list[i]) != NULL) {
+        main = shader_list[i];
+        break;
+      }
+   }
+
+   if (main == NULL) {
+      linker_error_printf(prog, "%s shader lacks `main'\n",
+                         (shader_list[0]->Type == GL_VERTEX_SHADER)
+                         ? "vertex" : "fragment");
+      return NULL;
+   }
+
+   gl_shader *const linked = ctx->Driver.NewShader(NULL, 0, main->Type);
+   linked->ir = new(linked) exec_list;
+   clone_ir_list(linked, linked->ir, main->ir);
+
+   populate_symbol_table(linked);
+
+   /* The a pointer to the main function in the final linked shader (i.e., the
+    * copy of the original shader that contained the main function).
+    */
+   ir_function_signature *const main_sig = get_main_function_signature(linked);
+
+   /* Move any instructions other than variable declarations or function
+    * declarations into main.
+    */
+   exec_node *insertion_point =
+      move_non_declarations(linked->ir, (exec_node *) &main_sig->body, false,
+                           linked);
+
+   for (unsigned i = 0; i < num_shaders; i++) {
+      if (shader_list[i] == main)
+        continue;
+
+      insertion_point = move_non_declarations(shader_list[i]->ir,
+                                             insertion_point, true, linked);
+   }
+
+   /* Resolve initializers for global variables in the linked shader.
+    */
+   unsigned num_linking_shaders = num_shaders;
+   for (unsigned i = 0; i < num_shaders; i++)
+      num_linking_shaders += shader_list[i]->num_builtins_to_link;
+
+   gl_shader **linking_shaders =
+      (gl_shader **) calloc(num_linking_shaders, sizeof(gl_shader *));
+
+   memcpy(linking_shaders, shader_list,
+         sizeof(linking_shaders[0]) * num_shaders);
+
+   unsigned idx = num_shaders;
+   for (unsigned i = 0; i < num_shaders; i++) {
+      memcpy(&linking_shaders[idx], shader_list[i]->builtins_to_link,
+            sizeof(linking_shaders[0]) * shader_list[i]->num_builtins_to_link);
+      idx += shader_list[i]->num_builtins_to_link;
+   }
+
+   assert(idx == num_linking_shaders);
+
+   link_function_calls(prog, linked, linking_shaders, num_linking_shaders);
+
+   free(linking_shaders);
+
+   return linked;
+}
+
+
+struct uniform_node {
+   exec_node link;
+   struct gl_uniform *u;
+   unsigned slots;
+};
+
+/**
+ * Update the sizes of linked shader uniform arrays to the maximum
+ * array index used.
+ *
+ * From page 81 (page 95 of the PDF) of the OpenGL 2.1 spec:
+ *
+ *     If one or more elements of an array are active,
+ *     GetActiveUniform will return the name of the array in name,
+ *     subject to the restrictions listed above. The type of the array
+ *     is returned in type. The size parameter contains the highest
+ *     array element index used, plus one. The compiler or linker
+ *     determines the highest index used.  There will be only one
+ *     active uniform reported by the GL per uniform array.
+
+ */
+static void
+update_uniform_array_sizes(struct gl_shader_program *prog)
+{
+   for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+      foreach_list(node, prog->_LinkedShaders[i]->ir) {
+        ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+        if ((var == NULL) || (var->mode != ir_var_uniform) ||
+            !var->type->is_array())
+           continue;
+
+        unsigned int size = var->max_array_access;
+        for (unsigned j = 0; j < prog->_NumLinkedShaders; j++) {
+           foreach_list(node2, prog->_LinkedShaders[j]->ir) {
+              ir_variable *other_var = ((ir_instruction *) node2)->as_variable();
+              if (!other_var)
+                 continue;
+
+              if (strcmp(var->name, other_var->name) == 0 &&
+                  other_var->max_array_access > size) {
+                 size = other_var->max_array_access;
+              }
+           }
+        }
+        if (size + 1 != var->type->fields.array->length) {
+           var->type = glsl_type::get_array_instance(var->type->fields.array,
+                                                     size + 1);
+           /* FINISHME: We should update the types of array
+            * dereferences of this variable now.
+            */
+        }
+      }
+   }
+}
+
+static void
+add_uniform(void *mem_ctx, exec_list *uniforms, struct hash_table *ht,
+           const char *name, const glsl_type *type, GLenum shader_type,
+           unsigned *next_shader_pos, unsigned *total_uniforms)
+{
+   if (type->is_record()) {
+      for (unsigned int i = 0; i < type->length; i++) {
+        const glsl_type *field_type = type->fields.structure[i].type;
+        char *field_name = talloc_asprintf(mem_ctx, "%s.%s", name,
+                                           type->fields.structure[i].name);
+
+        add_uniform(mem_ctx, uniforms, ht, field_name, field_type,
+                    shader_type, next_shader_pos, total_uniforms);
+      }
+   } else {
+      uniform_node *n = (uniform_node *) hash_table_find(ht, name);
+      unsigned int vec4_slots;
+      const glsl_type *array_elem_type = NULL;
+
+      if (type->is_array()) {
+        array_elem_type = type->fields.array;
+        /* Array of structures. */
+        if (array_elem_type->is_record()) {
+           for (unsigned int i = 0; i < type->length; i++) {
+              char *elem_name = talloc_asprintf(mem_ctx, "%s[%d]", name, i);
+              add_uniform(mem_ctx, uniforms, ht, elem_name, array_elem_type,
+                          shader_type, next_shader_pos, total_uniforms);
+           }
+           return;
+        }
+      }
+
+      /* Fix the storage size of samplers at 1 vec4 each. Be sure to pad out
+       * vectors to vec4 slots.
+       */
+      if (type->is_array()) {
+        if (array_elem_type->is_sampler())
+           vec4_slots = type->length;
+        else
+           vec4_slots = type->length * array_elem_type->matrix_columns;
+      } else if (type->is_sampler()) {
+        vec4_slots = 1;
+      } else {
+        vec4_slots = type->matrix_columns;
+      }
+
+      if (n == NULL) {
+        n = (uniform_node *) calloc(1, sizeof(struct uniform_node));
+        n->u = (gl_uniform *) calloc(1, sizeof(struct gl_uniform));
+        n->slots = vec4_slots;
+
+        n->u->Name = strdup(name);
+        n->u->Type = type;
+        n->u->VertPos = -1;
+        n->u->FragPos = -1;
+        n->u->GeomPos = -1;
+        (*total_uniforms)++;
+
+        hash_table_insert(ht, n, name);
+        uniforms->push_tail(& n->link);
+      }
+
+      switch (shader_type) {
+      case GL_VERTEX_SHADER:
+        n->u->VertPos = *next_shader_pos;
+        break;
+      case GL_FRAGMENT_SHADER:
+        n->u->FragPos = *next_shader_pos;
+        break;
+      case GL_GEOMETRY_SHADER:
+        n->u->GeomPos = *next_shader_pos;
+        break;
+      }
+
+      (*next_shader_pos) += vec4_slots;
+   }
+}
+
+void
+assign_uniform_locations(struct gl_shader_program *prog)
+{
+   /* */
+   exec_list uniforms;
+   unsigned total_uniforms = 0;
+   hash_table *ht = hash_table_ctor(32, hash_table_string_hash,
+                                   hash_table_string_compare);
+   void *mem_ctx = talloc_new(NULL);
+
+   update_uniform_array_sizes(prog);
+
+   for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+      unsigned next_position = 0;
+
+      foreach_list(node, prog->_LinkedShaders[i]->ir) {
+        ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+        if ((var == NULL) || (var->mode != ir_var_uniform))
+           continue;
+
+        if (strncmp(var->name, "gl_", 3) == 0) {
+           /* At the moment, we don't allocate uniform locations for
+            * builtin uniforms.  It's permitted by spec, and we'll
+            * likely switch to doing that at some point, but not yet.
+            */
+           continue;
+        }
+
+        var->location = next_position;
+        add_uniform(mem_ctx, &uniforms, ht, var->name, var->type,
+                    prog->_LinkedShaders[i]->Type,
+                    &next_position, &total_uniforms);
+      }
+   }
+
+   talloc_free(mem_ctx);
+
+   gl_uniform_list *ul = (gl_uniform_list *)
+      calloc(1, sizeof(gl_uniform_list));
+
+   ul->Size = total_uniforms;
+   ul->NumUniforms = total_uniforms;
+   ul->Uniforms = (gl_uniform *) calloc(total_uniforms, sizeof(gl_uniform));
+
+   unsigned idx = 0;
+   uniform_node *next;
+   for (uniform_node *node = (uniform_node *) uniforms.head
+          ; node->link.next != NULL
+          ; node = next) {
+      next = (uniform_node *) node->link.next;
+
+      node->link.remove();
+      memcpy(&ul->Uniforms[idx], node->u, sizeof(gl_uniform));
+      idx++;
+
+      free(node->u);
+      free(node);
+   }
+
+   hash_table_dtor(ht);
+
+   prog->Uniforms = ul;
+}
+
+
+/**
+ * Find a contiguous set of available bits in a bitmask
+ *
+ * \param used_mask     Bits representing used (1) and unused (0) locations
+ * \param needed_count  Number of contiguous bits needed.
+ *
+ * \return
+ * Base location of the available bits on success or -1 on failure.
+ */
+int
+find_available_slots(unsigned used_mask, unsigned needed_count)
+{
+   unsigned needed_mask = (1 << needed_count) - 1;
+   const int max_bit_to_test = (8 * sizeof(used_mask)) - needed_count;
+
+   /* The comparison to 32 is redundant, but without it GCC emits "warning:
+    * cannot optimize possibly infinite loops" for the loop below.
+    */
+   if ((needed_count == 0) || (max_bit_to_test < 0) || (max_bit_to_test > 32))
+      return -1;
+
+   for (int i = 0; i <= max_bit_to_test; i++) {
+      if ((needed_mask & ~used_mask) == needed_mask)
+        return i;
+
+      needed_mask <<= 1;
+   }
+
+   return -1;
+}
+
+
+bool
+assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index)
+{
+   /* Mark invalid attribute locations as being used.
+    */
+   unsigned used_locations = (max_attribute_index >= 32)
+      ? ~0 : ~((1 << max_attribute_index) - 1);
+
+   gl_shader *const sh = prog->_LinkedShaders[0];
+   assert(sh->Type == GL_VERTEX_SHADER);
+
+   /* Operate in a total of four passes.
+    *
+    * 1. Invalidate the location assignments for all vertex shader inputs.
+    *
+    * 2. Assign locations for inputs that have user-defined (via
+    *    glBindVertexAttribLocation) locatoins.
+    *
+    * 3. Sort the attributes without assigned locations by number of slots
+    *    required in decreasing order.  Fragmentation caused by attribute
+    *    locations assigned by the application may prevent large attributes
+    *    from having enough contiguous space.
+    *
+    * 4. Assign locations to any inputs without assigned locations.
+    */
+
+   invalidate_variable_locations(sh, ir_var_in, VERT_ATTRIB_GENERIC0);
+
+   if (prog->Attributes != NULL) {
+      for (unsigned i = 0; i < prog->Attributes->NumParameters; i++) {
+        ir_variable *const var =
+           sh->symbols->get_variable(prog->Attributes->Parameters[i].Name);
+
+        /* Note: attributes that occupy multiple slots, such as arrays or
+         * matrices, may appear in the attrib array multiple times.
+         */
+        if ((var == NULL) || (var->location != -1))
+           continue;
+
+        /* From page 61 of the OpenGL 4.0 spec:
+         *
+         *     "LinkProgram will fail if the attribute bindings assigned by
+         *     BindAttribLocation do not leave not enough space to assign a
+         *     location for an active matrix attribute or an active attribute
+         *     array, both of which require multiple contiguous generic
+         *     attributes."
+         *
+         * Previous versions of the spec contain similar language but omit the
+         * bit about attribute arrays.
+         *
+         * Page 61 of the OpenGL 4.0 spec also says:
+         *
+         *     "It is possible for an application to bind more than one
+         *     attribute name to the same location. This is referred to as
+         *     aliasing. This will only work if only one of the aliased
+         *     attributes is active in the executable program, or if no path
+         *     through the shader consumes more than one attribute of a set
+         *     of attributes aliased to the same location. A link error can
+         *     occur if the linker determines that every path through the
+         *     shader consumes multiple aliased attributes, but
+         *     implementations are not required to generate an error in this
+         *     case."
+         *
+         * These two paragraphs are either somewhat contradictory, or I don't
+         * fully understand one or both of them.
+         */
+        /* FINISHME: The code as currently written does not support attribute
+         * FINISHME: location aliasing (see comment above).
+         */
+        const int attr = prog->Attributes->Parameters[i].StateIndexes[0];
+        const unsigned slots = count_attribute_slots(var->type);
+
+        /* Mask representing the contiguous slots that will be used by this
+         * attribute.
+         */
+        const unsigned use_mask = (1 << slots) - 1;
+
+        /* Generate a link error if the set of bits requested for this
+         * attribute overlaps any previously allocated bits.
+         */
+        if ((~(use_mask << attr) & used_locations) != used_locations) {
+           linker_error_printf(prog,
+                               "insufficient contiguous attribute locations "
+                               "available for vertex shader input `%s'",
+                               var->name);
+           return false;
+        }
+
+        var->location = VERT_ATTRIB_GENERIC0 + attr;
+        used_locations |= (use_mask << attr);
+      }
+   }
+
+   /* Temporary storage for the set of attributes that need locations assigned.
+    */
+   struct temp_attr {
+      unsigned slots;
+      ir_variable *var;
+
+      /* Used below in the call to qsort. */
+      static int compare(const void *a, const void *b)
+      {
+        const temp_attr *const l = (const temp_attr *) a;
+        const temp_attr *const r = (const temp_attr *) b;
+
+        /* Reversed because we want a descending order sort below. */
+        return r->slots - l->slots;
+      }
+   } to_assign[16];
+
+   unsigned num_attr = 0;
+
+   foreach_list(node, sh->ir) {
+      ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+      if ((var == NULL) || (var->mode != ir_var_in))
+        continue;
+
+      /* The location was explicitly assigned, nothing to do here.
+       */
+      if (var->location != -1)
+        continue;
+
+      to_assign[num_attr].slots = count_attribute_slots(var->type);
+      to_assign[num_attr].var = var;
+      num_attr++;
+   }
+
+   /* If all of the attributes were assigned locations by the application (or
+    * are built-in attributes with fixed locations), return early.  This should
+    * be the common case.
+    */
+   if (num_attr == 0)
+      return true;
+
+   qsort(to_assign, num_attr, sizeof(to_assign[0]), temp_attr::compare);
+
+   /* VERT_ATTRIB_GENERIC0 is a psdueo-alias for VERT_ATTRIB_POS.  It can only
+    * be explicitly assigned by via glBindAttribLocation.  Mark it as reserved
+    * to prevent it from being automatically allocated below.
+    */
+   find_deref_visitor find("gl_Vertex");
+   find.run(sh->ir);
+   if (find.variable_found())
+      used_locations |= (1 << 0);
+
+   for (unsigned i = 0; i < num_attr; i++) {
+      /* Mask representing the contiguous slots that will be used by this
+       * attribute.
+       */
+      const unsigned use_mask = (1 << to_assign[i].slots) - 1;
+
+      int location = find_available_slots(used_locations, to_assign[i].slots);
+
+      if (location < 0) {
+        linker_error_printf(prog,
+                            "insufficient contiguous attribute locations "
+                            "available for vertex shader input `%s'",
+                            to_assign[i].var->name);
+        return false;
+      }
+
+      to_assign[i].var->location = VERT_ATTRIB_GENERIC0 + location;
+      used_locations |= (use_mask << location);
+   }
+
+   return true;
+}
+
+
+/**
+ * Demote shader outputs that are not read to being just plain global variables
+ */
+void
+demote_unread_shader_outputs(gl_shader *sh)
+{
+   foreach_list(node, sh->ir) {
+      ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+      if ((var == NULL) || (var->mode != ir_var_out))
+        continue;
+
+      /* An 'out' variable is only really a shader output if its value is read
+       * by the following stage.
+       */
+      if (var->location == -1) {
+        var->mode = ir_var_auto;
+      }
+   }
+}
+
+
+void
+assign_varying_locations(struct gl_shader_program *prog,
+                        gl_shader *producer, gl_shader *consumer)
+{
+   /* FINISHME: Set dynamically when geometry shader support is added. */
+   unsigned output_index = VERT_RESULT_VAR0;
+   unsigned input_index = FRAG_ATTRIB_VAR0;
+
+   /* Operate in a total of three passes.
+    *
+    * 1. Assign locations for any matching inputs and outputs.
+    *
+    * 2. Mark output variables in the producer that do not have locations as
+    *    not being outputs.  This lets the optimizer eliminate them.
+    *
+    * 3. Mark input variables in the consumer that do not have locations as
+    *    not being inputs.  This lets the optimizer eliminate them.
+    */
+
+   invalidate_variable_locations(producer, ir_var_out, VERT_RESULT_VAR0);
+   invalidate_variable_locations(consumer, ir_var_in, FRAG_ATTRIB_VAR0);
+
+   foreach_list(node, producer->ir) {
+      ir_variable *const output_var = ((ir_instruction *) node)->as_variable();
+
+      if ((output_var == NULL) || (output_var->mode != ir_var_out)
+         || (output_var->location != -1))
+        continue;
+
+      ir_variable *const input_var =
+        consumer->symbols->get_variable(output_var->name);
+
+      if ((input_var == NULL) || (input_var->mode != ir_var_in))
+        continue;
+
+      assert(input_var->location == -1);
+
+      output_var->location = output_index;
+      input_var->location = input_index;
+
+      /* FINISHME: Support for "varying" records in GLSL 1.50. */
+      assert(!output_var->type->is_record());
+
+      if (output_var->type->is_array()) {
+        const unsigned slots = output_var->type->length
+           * output_var->type->fields.array->matrix_columns;
+
+        output_index += slots;
+        input_index += slots;
+      } else {
+        const unsigned slots = output_var->type->matrix_columns;
+
+        output_index += slots;
+        input_index += slots;
+      }
+   }
+
+   demote_unread_shader_outputs(producer);
+
+   foreach_list(node, consumer->ir) {
+      ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+      if ((var == NULL) || (var->mode != ir_var_in))
+        continue;
+
+      if (var->location == -1) {
+        if (prog->Version <= 120) {
+           /* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec:
+            *
+            *     Only those varying variables used (i.e. read) in
+            *     the fragment shader executable must be written to
+            *     by the vertex shader executable; declaring
+            *     superfluous varying variables in a vertex shader is
+            *     permissible.
+            *
+            * We interpret this text as meaning that the VS must
+            * write the variable for the FS to read it.  See
+            * "glsl1-varying read but not written" in piglit.
+            */
+
+           linker_error_printf(prog, "fragment shader varying %s not written "
+                               "by vertex shader\n.", var->name);
+           prog->LinkStatus = false;
+        }
+
+        /* An 'in' variable is only really a shader input if its
+         * value is written by the previous stage.
+         */
+        var->mode = ir_var_auto;
+      }
+   }
+}
+
+
+void
+link_shaders(GLcontext *ctx, struct gl_shader_program *prog)
+{
+   prog->LinkStatus = false;
+   prog->Validated = false;
+   prog->_Used = false;
+
+   if (prog->InfoLog != NULL)
+      talloc_free(prog->InfoLog);
+
+   prog->InfoLog = talloc_strdup(NULL, "");
+
+   /* Separate the shaders into groups based on their type.
+    */
+   struct gl_shader **vert_shader_list;
+   unsigned num_vert_shaders = 0;
+   struct gl_shader **frag_shader_list;
+   unsigned num_frag_shaders = 0;
+
+   vert_shader_list = (struct gl_shader **)
+      calloc(2 * prog->NumShaders, sizeof(struct gl_shader *));
+   frag_shader_list =  &vert_shader_list[prog->NumShaders];
+
+   unsigned min_version = UINT_MAX;
+   unsigned max_version = 0;
+   for (unsigned i = 0; i < prog->NumShaders; i++) {
+      min_version = MIN2(min_version, prog->Shaders[i]->Version);
+      max_version = MAX2(max_version, prog->Shaders[i]->Version);
+
+      switch (prog->Shaders[i]->Type) {
+      case GL_VERTEX_SHADER:
+        vert_shader_list[num_vert_shaders] = prog->Shaders[i];
+        num_vert_shaders++;
+        break;
+      case GL_FRAGMENT_SHADER:
+        frag_shader_list[num_frag_shaders] = prog->Shaders[i];
+        num_frag_shaders++;
+        break;
+      case GL_GEOMETRY_SHADER:
+        /* FINISHME: Support geometry shaders. */
+        assert(prog->Shaders[i]->Type != GL_GEOMETRY_SHADER);
+        break;
+      }
+   }
+
+   /* Previous to GLSL version 1.30, different compilation units could mix and
+    * match shading language versions.  With GLSL 1.30 and later, the versions
+    * of all shaders must match.
+    */
+   assert(min_version >= 110);
+   assert(max_version <= 130);
+   if ((max_version >= 130) && (min_version != max_version)) {
+      linker_error_printf(prog, "all shaders must use same shading "
+                         "language version\n");
+      goto done;
+   }
+
+   prog->Version = max_version;
+
+   for (unsigned int i = 0; i < prog->_NumLinkedShaders; i++) {
+      ctx->Driver.DeleteShader(ctx, prog->_LinkedShaders[i]);
+   }
+
+   /* Link all shaders for a particular stage and validate the result.
+    */
+   prog->_NumLinkedShaders = 0;
+   if (num_vert_shaders > 0) {
+      gl_shader *const sh =
+        link_intrastage_shaders(ctx, prog, vert_shader_list, num_vert_shaders);
+
+      if (sh == NULL)
+        goto done;
+
+      if (!validate_vertex_shader_executable(prog, sh))
+         goto done;
+
+      prog->_LinkedShaders[prog->_NumLinkedShaders] = sh;
+      prog->_NumLinkedShaders++;
+   }
+
+   if (num_frag_shaders > 0) {
+      gl_shader *const sh =
+        link_intrastage_shaders(ctx, prog, frag_shader_list, num_frag_shaders);
+
+      if (sh == NULL)
+        goto done;
+
+      if (!validate_fragment_shader_executable(prog, sh))
+         goto done;
+
+      prog->_LinkedShaders[prog->_NumLinkedShaders] = sh;
+      prog->_NumLinkedShaders++;
+   }
+
+   /* Here begins the inter-stage linking phase.  Some initial validation is
+    * performed, then locations are assigned for uniforms, attributes, and
+    * varyings.
+    */
+   if (cross_validate_uniforms(prog)) {
+      /* Validate the inputs of each stage with the output of the preceeding
+       * stage.
+       */
+      for (unsigned i = 1; i < prog->_NumLinkedShaders; i++) {
+        if (!cross_validate_outputs_to_inputs(prog,
+                                              prog->_LinkedShaders[i - 1],
+                                              prog->_LinkedShaders[i]))
+           goto done;
+      }
+
+      prog->LinkStatus = true;
+   }
+
+   /* Do common optimization before assigning storage for attributes,
+    * uniforms, and varyings.  Later optimization could possibly make
+    * some of that unused.
+    */
+   for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+      while (do_common_optimization(prog->_LinkedShaders[i]->ir, true))
+        ;
+   }
+
+   assign_uniform_locations(prog);
+
+   if (prog->_LinkedShaders[0]->Type == GL_VERTEX_SHADER) {
+      /* FINISHME: The value of the max_attribute_index parameter is
+       * FINISHME: implementation dependent based on the value of
+       * FINISHME: GL_MAX_VERTEX_ATTRIBS.  GL_MAX_VERTEX_ATTRIBS must be
+       * FINISHME: at least 16, so hardcode 16 for now.
+       */
+      if (!assign_attribute_locations(prog, 16))
+        goto done;
+
+      if (prog->_NumLinkedShaders == 1)
+        demote_unread_shader_outputs(prog->_LinkedShaders[0]);
+   }
+
+   for (unsigned i = 1; i < prog->_NumLinkedShaders; i++)
+      assign_varying_locations(prog,
+                              prog->_LinkedShaders[i - 1],
+                              prog->_LinkedShaders[i]);
+
+   /* FINISHME: Assign fragment shader output locations. */
+
+done:
+   free(vert_shader_list);
+}
diff --git a/src/glsl/linker.h b/src/glsl/linker.h
new file mode 100644 (file)
index 0000000..a8ce16a
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+#pragma once
+#ifndef GLSL_LINKER_H
+#define GLSL_LINKER_H
+
+extern void
+linker_error_printf(gl_shader_program *prog, const char *fmt, ...);
+
+extern bool
+link_function_calls(gl_shader_program *prog, gl_shader *main,
+                   gl_shader **shader_list, unsigned num_shaders);
+
+#endif /* GLSL_LINKER_H */
diff --git a/src/glsl/list.h b/src/glsl/list.h
new file mode 100644 (file)
index 0000000..a70b79d
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ * Copyright Â© 2008, 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file list.h
+ * \brief Doubly-linked list abstract container type.
+ *
+ * Each doubly-linked list has a sentinel head and tail node.  These nodes
+ * contain no data.  The head sentinel can be identified by its \c prev
+ * pointer being \c NULL.  The tail sentinel can be identified by its
+ * \c next pointer being \c NULL.
+ *
+ * A list is empty if either the head sentinel's \c next pointer points to the
+ * tail sentinel or the tail sentinel's \c prev poiner points to the head
+ * sentinel.
+ *
+ * Instead of tracking two separate \c node structures and a \c list structure
+ * that points to them, the sentinel nodes are in a single structure.  Noting
+ * that each sentinel node always has one \c NULL pointer, the \c NULL
+ * pointers occupy the same memory location.  In the \c list structure
+ * contains a the following:
+ *
+ *   - A \c head pointer that represents the \c next pointer of the
+ *     head sentinel node.
+ *   - A \c tail pointer that represents the \c prev pointer of the head
+ *     sentinel node and the \c next pointer of the tail sentinel node.  This
+ *     pointer is \b always \c NULL.
+ *   - A \c tail_prev pointer that represents the \c prev pointer of the
+ *     tail sentinel node.
+ *
+ * Therefore, if \c head->next is \c NULL or \c tail_prev->prev is \c NULL,
+ * the list is empty.
+ *
+ * To anyone familiar with "exec lists" on the Amiga, this structure should
+ * be immediately recognizable.  See the following link for the original Amiga
+ * operating system documentation on the subject.
+ *
+ * http://www.natami.net/dev/Libraries_Manual_guide/node02D7.html
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+
+#pragma once
+#ifndef LIST_CONTAINER_H
+#define LIST_CONTAINER_H
+
+#ifndef __cplusplus
+#include <stddef.h>
+#include <talloc.h>
+#else
+extern "C" {
+#include <talloc.h>
+}
+#endif
+
+#include <assert.h>
+
+struct exec_node {
+   struct exec_node *next;
+   struct exec_node *prev;
+
+#ifdef __cplusplus
+   /* Callers of this talloc-based new need not call delete. It's
+    * easier to just talloc_free 'ctx' (or any of its ancestors). */
+   static void* operator new(size_t size, void *ctx)
+   {
+      void *node;
+
+      node = talloc_size(ctx, size);
+      assert(node != NULL);
+
+      return node;
+   }
+
+   /* If the user *does* call delete, that's OK, we will just
+    * talloc_free in that case. */
+   static void operator delete(void *node)
+   {
+      talloc_free(node);
+   }
+
+   exec_node() : next(NULL), prev(NULL)
+   {
+      /* empty */
+   }
+
+   const exec_node *get_next() const
+   {
+      return next;
+   }
+
+   exec_node *get_next()
+   {
+      return next;
+   }
+
+   const exec_node *get_prev() const
+   {
+      return prev;
+   }
+
+   exec_node *get_prev()
+   {
+      return prev;
+   }
+
+   void remove()
+   {
+      next->prev = prev;
+      prev->next = next;
+      next = NULL;
+      prev = NULL;
+   }
+
+   /**
+    * Link a node with itself
+    *
+    * This creates a sort of degenerate list that is occasionally useful.
+    */
+   void self_link()
+   {
+      next = this;
+      prev = this;
+   }
+
+   /**
+    * Insert a node in the list after the current node
+    */
+   void insert_after(exec_node *after)
+   {
+      after->next = this->next;
+      after->prev = this;
+
+      this->next->prev = after;
+      this->next = after;
+   }
+   /**
+    * Insert a node in the list before the current node
+    */
+   void insert_before(exec_node *before)
+   {
+      before->next = this;
+      before->prev = this->prev;
+
+      this->prev->next = before;
+      this->prev = before;
+   }
+   /**
+    * Replace the current node with the given node.
+    */
+   void replace_with(exec_node *replacement)
+   {
+      replacement->prev = this->prev;
+      replacement->next = this->next;
+
+      this->prev->next = replacement;
+      this->next->prev = replacement;
+   }
+
+   /**
+    * Is this the sentinel at the tail of the list?
+    */
+   bool is_tail_sentinel() const
+   {
+      return this->next == NULL;
+   }
+
+   /**
+    * Is this the sentinel at the head of the list?
+    */
+   bool is_head_sentinel() const
+   {
+      return this->prev == NULL;
+   }
+#endif
+};
+
+
+#ifdef __cplusplus
+/* This macro will not work correctly if `t' uses virtual inheritance.  If you
+ * are using virtual inheritance, you deserve a slow and painful death.  Enjoy!
+ */
+#define exec_list_offsetof(t, f, p) \
+   (((char *) &((t *) p)->f) - ((char *) p))
+#else
+#define exec_list_offsetof(t, f, p) offsetof(t, f)
+#endif
+
+/**
+ * Get a pointer to the structure containing an exec_node
+ *
+ * Given a pointer to an \c exec_node embedded in a structure, get a pointer to
+ * the containing structure.
+ *
+ * \param type  Base type of the structure containing the node
+ * \param node  Pointer to the \c exec_node
+ * \param field Name of the field in \c type that is the embedded \c exec_node
+ */
+#define exec_node_data(type, node, field) \
+   ((type *) (((char *) node) - exec_list_offsetof(type, field, node)))
+
+#ifdef __cplusplus
+struct exec_node;
+
+class iterator {
+public:
+   void next()
+   {
+   }
+
+   void *get()
+   {
+      return NULL;
+   }
+
+   bool has_next() const
+   {
+      return false;
+   }
+};
+
+class exec_list_iterator : public iterator {
+public:
+   exec_list_iterator(exec_node *n) : node(n), _next(n->next)
+   {
+      /* empty */
+   }
+
+   void next()
+   {
+      node = _next;
+      _next = node->next;
+   }
+
+   void remove()
+   {
+      node->remove();
+   }
+
+   exec_node *get()
+   {
+      return node;
+   }
+
+   bool has_next() const
+   {
+      return _next != NULL;
+   }
+
+private:
+   exec_node *node;
+   exec_node *_next;
+};
+
+#define foreach_iter(iter_type, iter, container) \
+   for (iter_type iter = (container) . iterator(); iter.has_next(); iter.next())
+#endif
+
+
+struct exec_list {
+   struct exec_node *head;
+   struct exec_node *tail;
+   struct exec_node *tail_pred;
+
+#ifdef __cplusplus
+   /* Callers of this talloc-based new need not call delete. It's
+    * easier to just talloc_free 'ctx' (or any of its ancestors). */
+   static void* operator new(size_t size, void *ctx)
+   {
+      void *node;
+
+      node = talloc_size(ctx, size);
+      assert(node != NULL);
+
+      return node;
+   }
+
+   /* If the user *does* call delete, that's OK, we will just
+    * talloc_free in that case. */
+   static void operator delete(void *node)
+   {
+      talloc_free(node);
+   }
+
+   exec_list()
+   {
+      make_empty();
+   }
+
+   void make_empty()
+   {
+      head = (exec_node *) & tail;
+      tail = NULL;
+      tail_pred = (exec_node *) & head;
+   }
+
+   bool is_empty() const
+   {
+      /* There are three ways to test whether a list is empty or not.
+       *
+       * - Check to see if the \c head points to the \c tail.
+       * - Check to see if the \c tail_pred points to the \c head.
+       * - Check to see if the \c head is the sentinel node by test whether its
+       *   \c next pointer is \c NULL.
+       *
+       * The first two methods tend to generate better code on modern systems
+       * because they save a pointer dereference.
+       */
+      return head == (exec_node *) &tail;
+   }
+
+   const exec_node *get_head() const
+   {
+      return !is_empty() ? head : NULL;
+   }
+
+   exec_node *get_head()
+   {
+      return !is_empty() ? head : NULL;
+   }
+
+   const exec_node *get_tail() const
+   {
+      return !is_empty() ? tail_pred : NULL;
+   }
+
+   exec_node *get_tail()
+   {
+      return !is_empty() ? tail_pred : NULL;
+   }
+
+   void push_head(exec_node *n)
+   {
+      n->next = head;
+      n->prev = (exec_node *) &head;
+
+      n->next->prev = n;
+      head = n;
+   }
+
+   void push_tail(exec_node *n)
+   {
+      n->next = (exec_node *) &tail;
+      n->prev = tail_pred;
+
+      n->prev->next = n;
+      tail_pred = n;
+   }
+
+   void push_degenerate_list_at_head(exec_node *n)
+   {
+      assert(n->prev->next == n);
+
+      n->prev->next = head;
+      head->prev = n->prev;
+      n->prev = (exec_node *) &head;
+      head = n;
+   }
+
+   /**
+    * Move all of the nodes from this list to the target list
+    */
+   void move_nodes_to(exec_list *target)
+   {
+      if (is_empty()) {
+        target->make_empty();
+      } else {
+        target->head = head;
+        target->tail = NULL;
+        target->tail_pred = tail_pred;
+
+        target->head->prev = (exec_node *) &target->head;
+        target->tail_pred->next = (exec_node *) &target->tail;
+
+        make_empty();
+      }
+   }
+
+   /**
+    * Append all nodes from the source list to the target list
+    */
+   void
+   append_list(exec_list *source)
+   {
+      if (source->is_empty())
+        return;
+
+      /* Link the first node of the source with the last node of the target list.
+       */
+      this->tail_pred->next = source->head;
+      source->head->prev = this->tail_pred;
+
+      /* Make the tail of the source list be the tail of the target list.
+       */
+      this->tail_pred = source->tail_pred;
+      this->tail_pred->next = (exec_node *) &this->tail;
+
+      /* Make the source list empty for good measure.
+       */
+      source->make_empty();
+   }
+
+   exec_list_iterator iterator()
+   {
+      return exec_list_iterator(head);
+   }
+
+   exec_list_iterator iterator() const
+   {
+      return exec_list_iterator((exec_node *) head);
+   }
+#endif
+};
+
+/**
+ * This version is safe even if the current node is removed.
+ */ 
+#define foreach_list_safe(__node, __list)                           \
+   for (exec_node * __node = (__list)->head, * __next = __node->next \
+       ; __next != NULL                                             \
+       ; __node = __next, __next = __next->next)
+
+#define foreach_list(__node, __list)                   \
+   for (exec_node * __node = (__list)->head            \
+       ; (__node)->next != NULL                        \
+       ; (__node) = (__node)->next)
+
+#define foreach_list_const(__node, __list)             \
+   for (const exec_node * __node = (__list)->head      \
+       ; (__node)->next != NULL                        \
+       ; (__node) = (__node)->next)
+
+#define foreach_list_typed(__type, __node, __field, __list)            \
+   for (__type * __node =                                              \
+          exec_node_data(__type, (__list)->head, __field);             \
+       (__node)->__field.next != NULL;                                 \
+       (__node) = exec_node_data(__type, (__node)->__field.next, __field))
+
+#define foreach_list_typed_const(__type, __node, __field, __list)      \
+   for (const __type * __node =                                                \
+          exec_node_data(__type, (__list)->head, __field);             \
+       (__node)->__field.next != NULL;                                 \
+       (__node) = exec_node_data(__type, (__node)->__field.next, __field))
+
+#endif /* LIST_CONTAINER_H */
diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp
new file mode 100644 (file)
index 0000000..cb9f8a5
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * Copyright Â© 2008, 2009 Intel Corporation
+ *
+ * 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 <cstdlib>
+#include <cstdio>
+#include <getopt.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "ast.h"
+#include "glsl_parser_extras.h"
+#include "glsl_parser.h"
+#include "ir_optimization.h"
+#include "ir_print_visitor.h"
+#include "program.h"
+
+extern "C" struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
+
+/* Copied from shader_api.c for the stand-alone compiler.
+ */
+struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
+{
+   struct gl_shader *shader;
+
+   (void) ctx;
+
+   assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
+   shader = talloc_zero(NULL, struct gl_shader);
+   if (shader) {
+      shader->Type = type;
+      shader->Name = name;
+      shader->RefCount = 1;
+   }
+   return shader;
+}
+
+/* Returned string will have 'ctx' as its talloc owner. */
+static char *
+load_text_file(void *ctx, const char *file_name)
+{
+       char *text = NULL;
+       struct stat st;
+       ssize_t total_read = 0;
+       int fd = open(file_name, O_RDONLY);
+
+       if (fd < 0) {
+               return NULL;
+       }
+
+       if (fstat(fd, & st) == 0) {
+          text = (char *) talloc_size(ctx, st.st_size + 1);
+               if (text != NULL) {
+                       do {
+                               ssize_t bytes = read(fd, text + total_read,
+                                                    st.st_size - total_read);
+                               if (bytes < 0) {
+                                       free(text);
+                                       text = NULL;
+                                       break;
+                               }
+
+                               if (bytes == 0) {
+                                       break;
+                               }
+
+                               total_read += bytes;
+                       } while (total_read < st.st_size);
+
+                       text[total_read] = '\0';
+               }
+       }
+
+       close(fd);
+
+       return text;
+}
+
+
+void
+usage_fail(const char *name)
+{
+      printf("%s <filename.frag|filename.vert>\n", name);
+      exit(EXIT_FAILURE);
+}
+
+
+int dump_ast = 0;
+int dump_hir = 0;
+int dump_lir = 0;
+int do_link = 0;
+
+const struct option compiler_opts[] = {
+   { "dump-ast", 0, &dump_ast, 1 },
+   { "dump-hir", 0, &dump_hir, 1 },
+   { "dump-lir", 0, &dump_lir, 1 },
+   { "link",     0, &do_link,  1 },
+   { NULL, 0, NULL, 0 }
+};
+
+void
+compile_shader(struct gl_shader *shader)
+{
+   struct _mesa_glsl_parse_state *state =
+      new(shader) _mesa_glsl_parse_state(NULL, shader->Type, shader);
+
+   const char *source = shader->Source;
+   state->error = preprocess(state, &source, &state->info_log,
+                            state->extensions);
+
+   if (!state->error) {
+      _mesa_glsl_lexer_ctor(state, source);
+      _mesa_glsl_parse(state);
+      _mesa_glsl_lexer_dtor(state);
+   }
+
+   if (dump_ast) {
+      foreach_list_const(n, &state->translation_unit) {
+        ast_node *ast = exec_node_data(ast_node, n, link);
+        ast->print();
+      }
+      printf("\n\n");
+   }
+
+   shader->ir = new(shader) exec_list;
+   if (!state->error && !state->translation_unit.is_empty())
+      _mesa_ast_to_hir(shader->ir, state);
+
+   /* Print out the unoptimized IR. */
+   if (!state->error && dump_hir) {
+      validate_ir_tree(shader->ir);
+      _mesa_print_ir(shader->ir, state);
+   }
+
+   /* Optimization passes */
+   if (!state->error && !shader->ir->is_empty()) {
+      bool progress;
+      do {
+        progress = false;
+
+        progress = do_function_inlining(shader->ir) || progress;
+        progress = do_if_simplification(shader->ir) || progress;
+        progress = do_copy_propagation(shader->ir) || progress;
+        progress = do_dead_code_local(shader->ir) || progress;
+        progress = do_dead_code_unlinked(shader->ir) || progress;
+        progress = do_tree_grafting(shader->ir) || progress;
+        progress = do_constant_propagation(shader->ir) || progress;
+        progress = do_constant_variable_unlinked(shader->ir) || progress;
+        progress = do_constant_folding(shader->ir) || progress;
+        progress = do_algebraic(shader->ir) || progress;
+        progress = do_vec_index_to_swizzle(shader->ir) || progress;
+        progress = do_vec_index_to_cond_assign(shader->ir) || progress;
+        progress = do_swizzle_swizzle(shader->ir) || progress;
+      } while (progress);
+
+      validate_ir_tree(shader->ir);
+   }
+
+
+   /* Print out the resulting IR */
+   if (!state->error && dump_lir) {
+      _mesa_print_ir(shader->ir, state);
+   }
+
+   shader->symbols = state->symbols;
+   shader->CompileStatus = !state->error;
+   shader->Version = state->language_version;
+   memcpy(shader->builtins_to_link, state->builtins_to_link,
+         sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link);
+   shader->num_builtins_to_link = state->num_builtins_to_link;
+
+   if (shader->InfoLog)
+      talloc_free(shader->InfoLog);
+
+   shader->InfoLog = state->info_log;
+
+   /* Retain any live IR, but trash the rest. */
+   reparent_ir(shader->ir, shader);
+
+   talloc_free(state);
+
+   return;
+}
+
+int
+main(int argc, char **argv)
+{
+   int status = EXIT_SUCCESS;
+   GLcontext local_ctx;
+   GLcontext *ctx = &local_ctx;
+
+   ctx->Driver.NewShader = _mesa_new_shader;
+
+   int c;
+   int idx = 0;
+   while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1)
+      /* empty */ ;
+
+
+   if (argc <= optind)
+      usage_fail(argv[0]);
+
+   struct gl_shader_program *whole_program;
+
+   whole_program = talloc_zero (NULL, struct gl_shader_program);
+   assert(whole_program != NULL);
+
+   for (/* empty */; argc > optind; optind++) {
+      whole_program->Shaders = (struct gl_shader **)
+        talloc_realloc(whole_program, whole_program->Shaders,
+                       struct gl_shader *, whole_program->NumShaders + 1);
+      assert(whole_program->Shaders != NULL);
+
+      struct gl_shader *shader = talloc_zero(whole_program, gl_shader);
+
+      whole_program->Shaders[whole_program->NumShaders] = shader;
+      whole_program->NumShaders++;
+
+      const unsigned len = strlen(argv[optind]);
+      if (len < 6)
+        usage_fail(argv[0]);
+
+      const char *const ext = & argv[optind][len - 5];
+      if (strncmp(".vert", ext, 5) == 0)
+        shader->Type = GL_VERTEX_SHADER;
+      else if (strncmp(".geom", ext, 5) == 0)
+        shader->Type = GL_GEOMETRY_SHADER;
+      else if (strncmp(".frag", ext, 5) == 0)
+        shader->Type = GL_FRAGMENT_SHADER;
+      else
+        usage_fail(argv[0]);
+
+      shader->Source = load_text_file(whole_program, argv[optind]);
+      if (shader->Source == NULL) {
+        printf("File \"%s\" does not exist.\n", argv[optind]);
+        exit(EXIT_FAILURE);
+      }
+
+      compile_shader(shader);
+
+      if (!shader->CompileStatus) {
+        printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog);
+        status = EXIT_FAILURE;
+        break;
+      }
+   }
+
+   if ((status == EXIT_SUCCESS) && do_link)  {
+      link_shaders(ctx, whole_program);
+      status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;
+
+      if (strlen(whole_program->InfoLog) > 0)
+        printf("Info log for linking:\n%s\n", whole_program->InfoLog);
+   }
+
+   for (unsigned i = 0; i < whole_program->_NumLinkedShaders; i++)
+      talloc_free(whole_program->_LinkedShaders[i]);
+
+   talloc_free(whole_program);
+   _mesa_glsl_release_types();
+   _mesa_glsl_release_functions();
+
+   return status;
+}
diff --git a/src/glsl/pp/Makefile b/src/glsl/pp/Makefile
deleted file mode 100644 (file)
index fda1c42..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#src/glsl/pp/Makefile
-
-TOP = ../../..
-
-include $(TOP)/configs/current
-
-LIBNAME = glslpp
-
-C_SOURCES = \
-       sl_pp_context.c \
-       sl_pp_define.c \
-       sl_pp_dict.c \
-       sl_pp_error.c \
-       sl_pp_expression.c \
-       sl_pp_extension.c \
-       sl_pp_if.c \
-       sl_pp_line.c \
-       sl_pp_macro.c \
-       sl_pp_pragma.c \
-       sl_pp_process.c \
-       sl_pp_purify.c \
-       sl_pp_token.c \
-       sl_pp_token_util.c \
-       sl_pp_version.c
-
-include ../Makefile.template
-
diff --git a/src/glsl/pp/sl_pp_context.c b/src/glsl/pp/sl_pp_context.c
deleted file mode 100644 (file)
index b8e1e99..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_macro.h"
-#include "sl_pp_public.h"
-#include "sl_pp_context.h"
-
-
-struct sl_pp_context *
-sl_pp_context_create(const char *input,
-                     const struct sl_pp_purify_options *options)
-{
-   struct sl_pp_context *context;
-
-   context = calloc(1, sizeof(struct sl_pp_context));
-   if (!context) {
-      return NULL;
-   }
-
-   if (sl_pp_dict_init(context)) {
-      sl_pp_context_destroy(context);
-      return NULL;
-   }
-
-   context->getc_buf_capacity = 64;
-   context->getc_buf = malloc(context->getc_buf_capacity * sizeof(char));
-   if (!context->getc_buf) {
-      sl_pp_context_destroy(context);
-      return NULL;
-   }
-
-   if (sl_pp_token_buffer_init(&context->tokens, context)) {
-      sl_pp_context_destroy(context);
-      return NULL;
-   }
-
-   context->macro_tail = &context->macro;
-   context->if_ptr = SL_PP_MAX_IF_NESTING;
-   context->if_value = 1;
-   memset(context->error_msg, 0, sizeof(context->error_msg));
-   context->error_line = 1;
-   context->line = 1;
-   context->file = 0;
-
-   sl_pp_purify_state_init(&context->pure, input, options);
-
-   memset(&context->process_state, 0, sizeof(context->process_state));
-
-   return context;
-}
-
-void
-sl_pp_context_destroy(struct sl_pp_context *context)
-{
-   if (context) {
-      free(context->cstr_pool);
-      sl_pp_macro_free(context->macro);
-      free(context->getc_buf);
-      sl_pp_token_buffer_destroy(&context->tokens);
-      free(context->process_state.out);
-      free(context);
-   }
-}
-
-const char *
-sl_pp_context_error_message(const struct sl_pp_context *context)
-{
-   return context->error_msg;
-}
-
-void
-sl_pp_context_error_position(const struct sl_pp_context *context,
-                             unsigned int *file,
-                             unsigned int *line)
-{
-   if (file) {
-      *file = 0;
-   }
-   if (line) {
-      *line = context->error_line;
-   }
-}
-
-int
-sl_pp_context_add_predefined(struct sl_pp_context *context,
-                             const char *name,
-                             const char *value)
-{
-   struct sl_pp_predefined pre;
-
-   if (context->num_predefined == SL_PP_MAX_PREDEFINED) {
-      return -1;
-   }
-
-   pre.name = sl_pp_context_add_unique_str(context, name);
-   if (pre.name == -1) {
-      return -1;
-   }
-
-   pre.value = sl_pp_context_add_unique_str(context, value);
-   if (pre.value == -1) {
-      return -1;
-   }
-
-   context->predefined[context->num_predefined++] = pre;
-   return 0;
-}
-
-int
-sl_pp_context_add_unique_str(struct sl_pp_context *context,
-                             const char *str)
-{
-   unsigned int size;
-   unsigned int offset = 0;
-
-   size = strlen(str) + 1;
-
-   /* Find out if this is a unique string. */
-   while (offset < context->cstr_pool_len) {
-      const char *str2;
-      unsigned int size2;
-
-      str2 = &context->cstr_pool[offset];
-      size2 = strlen(str2) + 1;
-      if (size == size2 && !memcmp(str, str2, size - 1)) {
-         return offset;
-      }
-
-      offset += size2;
-   }
-
-   if (context->cstr_pool_len + size > context->cstr_pool_max) {
-      context->cstr_pool_max = (context->cstr_pool_len + size + 0xffff) & ~0xffff;
-      context->cstr_pool = realloc(context->cstr_pool, context->cstr_pool_max);
-   }
-
-   if (!context->cstr_pool) {
-      strcpy(context->error_msg, "out of memory");
-      return -1;
-   }
-
-   offset = context->cstr_pool_len;
-   memcpy(&context->cstr_pool[offset], str, size);
-   context->cstr_pool_len += size;
-
-   return offset;
-}
-
-const char *
-sl_pp_context_cstr(const struct sl_pp_context *context,
-                   int offset)
-{
-   if (offset == -1) {
-      return NULL;
-   }
-   return &context->cstr_pool[offset];
-}
diff --git a/src/glsl/pp/sl_pp_context.h b/src/glsl/pp/sl_pp_context.h
deleted file mode 100644 (file)
index e6244f6..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#ifndef SL_PP_CONTEXT_H
-#define SL_PP_CONTEXT_H
-
-#include "sl_pp_dict.h"
-#include "sl_pp_process.h"
-#include "sl_pp_purify.h"
-#include "sl_pp_token_util.h"
-
-
-#define SL_PP_MAX_IF_NESTING  64
-
-#define SL_PP_MAX_ERROR_MSG   1024
-
-#define SL_PP_MAX_EXTENSIONS  16
-
-#define SL_PP_MAX_PREDEFINED  16
-
-struct sl_pp_extension {
-   int name;   /*< GL_VENDOR_extension_name */
-};
-
-struct sl_pp_predefined {
-   int name;
-   int value;
-};
-
-union sl_pp_if_state {
-   struct {
-      unsigned int condition:1;
-      unsigned int went_thru_else:1;
-      unsigned int had_true_cond:1;
-   } u;
-   unsigned int value;
-};
-
-struct sl_pp_context {
-   char *cstr_pool;
-   unsigned int cstr_pool_max;
-   unsigned int cstr_pool_len;
-   struct sl_pp_dict dict;
-
-   struct sl_pp_macro *macro;
-   struct sl_pp_macro **macro_tail;
-
-   struct sl_pp_extension extensions[SL_PP_MAX_EXTENSIONS];
-   unsigned int num_extensions;
-
-   struct sl_pp_predefined predefined[SL_PP_MAX_PREDEFINED];
-   unsigned int num_predefined;
-
-   union sl_pp_if_state if_stack[SL_PP_MAX_IF_NESTING];
-   unsigned int if_ptr;
-   unsigned int if_value;
-
-   char error_msg[SL_PP_MAX_ERROR_MSG];
-   unsigned int error_line;
-
-   unsigned int line;
-   unsigned int file;
-
-   struct sl_pp_purify_state pure;
-
-   char *getc_buf;
-   unsigned int getc_buf_size;
-   unsigned int getc_buf_capacity;
-
-   struct sl_pp_token_buffer tokens;
-
-   struct sl_pp_process_state process_state;
-};
-
-#endif /* SL_PP_CONTEXT_H */
diff --git a/src/glsl/pp/sl_pp_define.c b/src/glsl/pp/sl_pp_define.c
deleted file mode 100644 (file)
index 370e6aa..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_macro.h"
-#include "sl_pp_process.h"
-#include "sl_pp_public.h"
-#include "sl_pp_token.h"
-
-
-static void
-skip_whitespace(const struct sl_pp_token_info *input,
-                unsigned int *first,
-                unsigned int last)
-{
-   while (*first < last && input[*first].token == SL_PP_WHITESPACE) {
-      (*first)++;
-   }
-}
-
-
-static int
-_parse_formal_args(struct sl_pp_context *context,
-                   const struct sl_pp_token_info *input,
-                   unsigned int *first,
-                   unsigned int last,
-                   struct sl_pp_macro *macro)
-{
-   struct sl_pp_macro_formal_arg **arg;
-
-   macro->num_args = 0;
-
-   skip_whitespace(input, first, last);
-   if (*first < last) {
-      if (input[*first].token == SL_PP_RPAREN) {
-         (*first)++;
-         return 0;
-      }
-   } else {
-      strcpy(context->error_msg, "expected either macro formal argument or `)'");
-      return -1;
-   }
-
-   arg = &macro->arg;
-
-   for (;;) {
-      if (*first < last && input[*first].token != SL_PP_IDENTIFIER) {
-         strcpy(context->error_msg, "expected macro formal argument");
-         return -1;
-      }
-
-      *arg = malloc(sizeof(struct sl_pp_macro_formal_arg));
-      if (!*arg) {
-         strcpy(context->error_msg, "out of memory");
-         return -1;
-      }
-
-      (**arg).name = input[*first].data.identifier;
-      (*first)++;
-
-      (**arg).next = NULL;
-      arg = &(**arg).next;
-
-      macro->num_args++;
-
-      skip_whitespace(input, first, last);
-      if (*first < last) {
-         if (input[*first].token == SL_PP_COMMA) {
-            (*first)++;
-            skip_whitespace(input, first, last);
-         } else if (input[*first].token == SL_PP_RPAREN) {
-            (*first)++;
-            return 0;
-         } else {
-            strcpy(context->error_msg, "expected either `,' or `)'");
-            return -1;
-         }
-      } else {
-         strcpy(context->error_msg, "expected either `,' or `)'");
-         return -1;
-      }
-   }
-
-   /* Should not gete here. */
-}
-
-
-int
-sl_pp_process_define(struct sl_pp_context *context,
-                     const struct sl_pp_token_info *input,
-                     unsigned int first,
-                     unsigned int last)
-{
-   int macro_name = -1;
-   struct sl_pp_macro *macro;
-   unsigned int i;
-   unsigned int body_len;
-   unsigned int j;
-
-   if (first < last && input[first].token == SL_PP_IDENTIFIER) {
-      macro_name = input[first].data.identifier;
-      first++;
-   }
-   if (macro_name == -1) {
-      strcpy(context->error_msg, "expected macro name");
-      return -1;
-   }
-
-   /* Check for reserved macro names */
-   {
-      const char *name = sl_pp_context_cstr(context, macro_name);
-
-      if (strstr(name, "__")) {
-         strcpy(context->error_msg, "macro names containing `__' are reserved");
-         return 1;
-      }
-      if (name[0] == 'G' && name[1] == 'L' && name[2] == '_') {
-         strcpy(context->error_msg, "macro names prefixed with `GL_' are reserved");
-         return 1;
-      }
-   }
-
-   for (macro = context->macro; macro; macro = macro->next) {
-      if (macro->name == macro_name) {
-         break;
-      }
-   }
-
-   if (!macro) {
-      macro = sl_pp_macro_new();
-      if (!macro) {
-         strcpy(context->error_msg, "out of memory");
-         return -1;
-      }
-
-      *context->macro_tail = macro;
-      context->macro_tail = &macro->next;
-   } else {
-      sl_pp_macro_reset(macro);
-   }
-
-   macro->name = macro_name;
-
-   /*
-    * If there is no whitespace between macro name and left paren, a macro
-    * formal argument list follows. This is the only place where the presence
-    * of a whitespace matters and it's the only reason why we are dealing
-    * with whitespace at this level.
-    */
-   if (first < last && input[first].token == SL_PP_LPAREN) {
-      first++;
-      if (_parse_formal_args(context, input, &first, last, macro)) {
-         return -1;
-      }
-   }
-
-   /* Calculate body size, trim out whitespace, make room for EOF. */
-   body_len = 1;
-   for (i = first; i < last; i++) {
-      if (input[i].token != SL_PP_WHITESPACE) {
-         body_len++;
-      }
-   }
-
-   macro->body = malloc(sizeof(struct sl_pp_token_info) * body_len);
-   if (!macro->body) {
-      strcpy(context->error_msg, "out of memory");
-      return -1;
-   }
-
-   for (j = 0, i = first; i < last; i++) {
-      if (input[i].token != SL_PP_WHITESPACE) {
-         macro->body[j++] = input[i];
-      }
-   }
-   macro->body[j++].token = SL_PP_EOF;
-
-   return 0;
-}
-
-
-int
-sl_pp_process_undef(struct sl_pp_context *context,
-                    const struct sl_pp_token_info *input,
-                    unsigned int first,
-                    unsigned int last)
-{
-   int macro_name = -1;
-   struct sl_pp_macro **pmacro;
-   struct sl_pp_macro *macro;
-
-   if (first < last && input[first].token == SL_PP_IDENTIFIER) {
-      macro_name = input[first].data.identifier;
-   }
-   if (macro_name == -1) {
-      return 0;
-   }
-
-   for (pmacro = &context->macro; *pmacro; pmacro = &(**pmacro).next) {
-      if ((**pmacro).name == macro_name) {
-         break;
-      }
-   }
-   if (!*pmacro) {
-      return 0;
-   }
-
-   macro = *pmacro;
-   *pmacro = macro->next;
-   macro->next = NULL;
-   sl_pp_macro_free(macro);
-
-   return 0;
-}
diff --git a/src/glsl/pp/sl_pp_dict.c b/src/glsl/pp/sl_pp_dict.c
deleted file mode 100644 (file)
index 062139e..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include "sl_pp_public.h"
-#include "sl_pp_context.h"
-#include "sl_pp_dict.h"
-
-
-#define ADD_NAME_STR(CTX, NAME, STR)\
-   do {\
-      (CTX)->dict.NAME = sl_pp_context_add_unique_str((CTX), (STR));\
-      if ((CTX)->dict.NAME == -1) {\
-         return -1;\
-      }\
-   } while (0)
-
-#define ADD_NAME(CTX, NAME) ADD_NAME_STR(CTX, NAME, #NAME)
-
-
-int
-sl_pp_dict_init(struct sl_pp_context *context)
-{
-   ADD_NAME(context, all);
-
-   ADD_NAME(context, require);
-   ADD_NAME(context, enable);
-   ADD_NAME(context, warn);
-   ADD_NAME(context, disable);
-
-   ADD_NAME(context, defined);
-
-   ADD_NAME_STR(context, ___LINE__, "__LINE__");
-   ADD_NAME_STR(context, ___FILE__, "__FILE__");
-   ADD_NAME_STR(context, ___VERSION__, "__VERSION__");
-
-   ADD_NAME(context, optimize);
-   ADD_NAME(context, debug);
-
-   ADD_NAME(context, off);
-   ADD_NAME(context, on);
-
-   ADD_NAME(context, define);
-   ADD_NAME(context, elif);
-   ADD_NAME_STR(context, _else, "else");
-   ADD_NAME(context, endif);
-   ADD_NAME(context, error);
-   ADD_NAME(context, extension);
-   ADD_NAME_STR(context, _if, "if");
-   ADD_NAME(context, ifdef);
-   ADD_NAME(context, ifndef);
-   ADD_NAME(context, line);
-   ADD_NAME(context, pragma);
-   ADD_NAME(context, undef);
-
-   ADD_NAME(context, version);
-
-   ADD_NAME_STR(context, _0, "0");
-   ADD_NAME_STR(context, _1, "1");
-
-   return 0;
-}
diff --git a/src/glsl/pp/sl_pp_dict.h b/src/glsl/pp/sl_pp_dict.h
deleted file mode 100644 (file)
index 875217b..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#ifndef SL_PP_DICT_H
-#define SL_PP_DICT_H
-
-
-struct sl_pp_context;
-
-struct sl_pp_dict {
-   int all;
-
-   int require;
-   int enable;
-   int warn;
-   int disable;
-
-   int defined;
-
-   int ___LINE__;
-   int ___FILE__;
-   int ___VERSION__;
-
-   int optimize;
-   int debug;
-
-   int off;
-   int on;
-
-   int define;
-   int elif;
-   int _else;
-   int endif;
-   int error;
-   int extension;
-   int _if;
-   int ifdef;
-   int ifndef;
-   int line;
-   int pragma;
-   int undef;
-
-   int version;
-
-   int _0;
-   int _1;
-};
-
-
-int
-sl_pp_dict_init(struct sl_pp_context *context);
-
-#endif /* SL_PP_DICT_H */
diff --git a/src/glsl/pp/sl_pp_error.c b/src/glsl/pp/sl_pp_error.c
deleted file mode 100644 (file)
index 482b67f..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_process.h"
-#include "sl_pp_public.h"
-#include "sl_pp_token.h"
-
-
-void
-sl_pp_process_error(struct sl_pp_context *context,
-                    const struct sl_pp_token_info *input,
-                    unsigned int first,
-                    unsigned int last)
-{
-   unsigned int out_len = 0;
-   unsigned int i;
-
-   for (i = first; i < last; i++) {
-      const char *s = NULL;
-      char buf[2];
-
-      switch (input[i].token) {
-      case SL_PP_WHITESPACE:
-         s = " ";
-         break;
-
-      case SL_PP_NEWLINE:
-         s = "\n";
-         break;
-
-      case SL_PP_HASH:
-         s = "#";
-         break;
-
-      case SL_PP_COMMA:
-         s = ",";
-         break;
-
-      case SL_PP_SEMICOLON:
-         s = ";";
-         break;
-
-      case SL_PP_LBRACE:
-         s = "{";
-         break;
-
-      case SL_PP_RBRACE:
-         s = "}";
-         break;
-
-      case SL_PP_LPAREN:
-         s = "(";
-         break;
-
-      case SL_PP_RPAREN:
-         s = ")";
-         break;
-
-      case SL_PP_LBRACKET:
-         s = "[";
-         break;
-
-      case SL_PP_RBRACKET:
-         s = "]";
-         break;
-
-      case SL_PP_DOT:
-         s = ".";
-         break;
-
-      case SL_PP_INCREMENT:
-         s = "++";
-         break;
-
-      case SL_PP_ADDASSIGN:
-         s = "+=";
-         break;
-
-      case SL_PP_PLUS:
-         s = "+";
-         break;
-
-      case SL_PP_DECREMENT:
-         s = "--";
-         break;
-
-      case SL_PP_SUBASSIGN:
-         s = "-=";
-         break;
-
-      case SL_PP_MINUS:
-         s = "-";
-         break;
-
-      case SL_PP_BITNOT:
-         s = "~";
-         break;
-
-      case SL_PP_NOTEQUAL:
-         s = "!=";
-         break;
-
-      case SL_PP_NOT:
-         s = "!";
-         break;
-
-      case SL_PP_MULASSIGN:
-         s = "*=";
-         break;
-
-      case SL_PP_STAR:
-         s = "*";
-         break;
-
-      case SL_PP_DIVASSIGN:
-         s = "/=";
-         break;
-
-      case SL_PP_SLASH:
-         s = "/";
-         break;
-
-      case SL_PP_MODASSIGN:
-         s = "%=";
-         break;
-
-      case SL_PP_MODULO:
-         s = "%";
-         break;
-
-      case SL_PP_LSHIFTASSIGN:
-         s = "<<=";
-         break;
-
-      case SL_PP_LSHIFT:
-         s = "<<";
-         break;
-
-      case SL_PP_LESSEQUAL:
-         s = "<=";
-         break;
-
-      case SL_PP_LESS:
-         s = "<";
-         break;
-
-      case SL_PP_RSHIFTASSIGN:
-         s = ">>=";
-         break;
-
-      case SL_PP_RSHIFT:
-         s = ">>";
-         break;
-
-      case SL_PP_GREATEREQUAL:
-         s = ">=";
-         break;
-
-      case SL_PP_GREATER:
-         s = ">";
-         break;
-
-      case SL_PP_EQUAL:
-         s = "==";
-         break;
-
-      case SL_PP_ASSIGN:
-         s = "=";
-         break;
-
-      case SL_PP_AND:
-         s = "&&";
-         break;
-
-      case SL_PP_BITANDASSIGN:
-         s = "&=";
-         break;
-
-      case SL_PP_BITAND:
-         s = "&";
-         break;
-
-      case SL_PP_XOR:
-         s = "^^";
-         break;
-
-      case SL_PP_BITXORASSIGN:
-         s = "^=";
-         break;
-
-      case SL_PP_BITXOR:
-         s = "^";
-         break;
-
-      case SL_PP_OR:
-         s = "||";
-         break;
-
-      case SL_PP_BITORASSIGN:
-         s = "|=";
-         break;
-
-      case SL_PP_BITOR:
-         s = "|";
-         break;
-
-      case SL_PP_QUESTION:
-         s = "?";
-         break;
-
-      case SL_PP_COLON:
-         s = ":";
-         break;
-
-      case SL_PP_IDENTIFIER:
-         s = sl_pp_context_cstr(context, input[i].data.identifier);
-         break;
-
-      case SL_PP_UINT:
-         s = sl_pp_context_cstr(context, input[i].data._uint);
-         break;
-
-      case SL_PP_FLOAT:
-         s = sl_pp_context_cstr(context, input[i].data._float);
-         break;
-
-      case SL_PP_OTHER:
-         buf[0] = input[i].data.other;
-         buf[1] = '\0';
-         s = buf;
-         break;
-
-      default:
-         strcpy(context->error_msg, "internal error");
-         return;
-      }
-
-      while (*s != '\0' && out_len < sizeof(context->error_msg) - 1) {
-         context->error_msg[out_len++] = *s++;
-      }
-   }
-
-   context->error_msg[out_len] = '\0';
-}
diff --git a/src/glsl/pp/sl_pp_expression.c b/src/glsl/pp/sl_pp_expression.c
deleted file mode 100644 (file)
index c3f4835..0000000
+++ /dev/null
@@ -1,413 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_expression.h"
-#include "sl_pp_public.h"
-#include "sl_pp_token.h"
-
-
-struct parse_context {
-   struct sl_pp_context *context;
-   const struct sl_pp_token_info *input;
-};
-
-static int
-_parse_or(struct parse_context *ctx,
-          int *result);
-
-static int
-_parse_primary(struct parse_context *ctx,
-               int *result)
-{
-   if (ctx->input->token == SL_PP_UINT) {
-      *result = atoi(sl_pp_context_cstr(ctx->context, ctx->input->data._uint));
-      ctx->input++;
-   } else {
-      if (ctx->input->token != SL_PP_LPAREN) {
-         strcpy(ctx->context->error_msg, "expected `('");
-         return -1;
-      }
-      ctx->input++;
-      if (_parse_or(ctx, result)) {
-         return -1;
-      }
-      if (ctx->input->token != SL_PP_RPAREN) {
-         strcpy(ctx->context->error_msg, "expected `)'");
-         return -1;
-      }
-      ctx->input++;
-   }
-   return 0;
-}
-
-static int
-_parse_unary(struct parse_context *ctx,
-             int *result)
-{
-   if (!_parse_primary(ctx, result)) {
-      return 0;
-   }
-
-   switch (ctx->input->token) {
-   case SL_PP_PLUS:
-      ctx->input++;
-      if (_parse_unary(ctx, result)) {
-         return -1;
-      }
-      *result = +*result;
-      break;
-
-   case SL_PP_MINUS:
-      ctx->input++;
-      if (_parse_unary(ctx, result)) {
-         return -1;
-      }
-      *result = -*result;
-      break;
-
-   case SL_PP_NOT:
-      ctx->input++;
-      if (_parse_unary(ctx, result)) {
-         return -1;
-      }
-      *result = !*result;
-      break;
-
-   case SL_PP_BITNOT:
-      ctx->input++;
-      if (_parse_unary(ctx, result)) {
-         return -1;
-      }
-      *result = ~*result;
-      break;
-
-   default:
-      return -1;
-   }
-
-   return 0;
-}
-
-static int
-_parse_multiplicative(struct parse_context *ctx,
-                      int *result)
-{
-   if (_parse_unary(ctx, result)) {
-      return -1;
-   }
-   for (;;) {
-      int right;
-
-      switch (ctx->input->token) {
-      case SL_PP_STAR:
-         ctx->input++;
-         if (_parse_unary(ctx, &right)) {
-            return -1;
-         }
-         *result = *result * right;
-         break;
-
-      case SL_PP_SLASH:
-         ctx->input++;
-         if (_parse_unary(ctx, &right)) {
-            return -1;
-         }
-         *result = *result / right;
-         break;
-
-      case SL_PP_MODULO:
-         ctx->input++;
-         if (_parse_unary(ctx, &right)) {
-            return -1;
-         }
-         *result = *result % right;
-         break;
-
-      default:
-         return 0;
-      }
-   }
-}
-
-static int
-_parse_additive(struct parse_context *ctx,
-                int *result)
-{
-   if (_parse_multiplicative(ctx, result)) {
-      return -1;
-   }
-   for (;;) {
-      int right;
-
-      switch (ctx->input->token) {
-      case SL_PP_PLUS:
-         ctx->input++;
-         if (_parse_multiplicative(ctx, &right)) {
-            return -1;
-         }
-         *result = *result + right;
-         break;
-
-      case SL_PP_MINUS:
-         ctx->input++;
-         if (_parse_multiplicative(ctx, &right)) {
-            return -1;
-         }
-         *result = *result - right;
-         break;
-
-      default:
-         return 0;
-      }
-   }
-}
-
-static int
-_parse_shift(struct parse_context *ctx,
-             int *result)
-{
-   if (_parse_additive(ctx, result)) {
-      return -1;
-   }
-   for (;;) {
-      int right;
-
-      switch (ctx->input->token) {
-      case SL_PP_LSHIFT:
-         ctx->input++;
-         if (_parse_additive(ctx, &right)) {
-            return -1;
-         }
-         *result = *result << right;
-         break;
-
-      case SL_PP_RSHIFT:
-         ctx->input++;
-         if (_parse_additive(ctx, &right)) {
-            return -1;
-         }
-         *result = *result >> right;
-         break;
-
-      default:
-         return 0;
-      }
-   }
-}
-
-static int
-_parse_relational(struct parse_context *ctx,
-                  int *result)
-{
-   if (_parse_shift(ctx, result)) {
-      return -1;
-   }
-   for (;;) {
-      int right;
-
-      switch (ctx->input->token) {
-      case SL_PP_LESSEQUAL:
-         ctx->input++;
-         if (_parse_shift(ctx, &right)) {
-            return -1;
-         }
-         *result = *result <= right;
-         break;
-
-      case SL_PP_GREATEREQUAL:
-         ctx->input++;
-         if (_parse_shift(ctx, &right)) {
-            return -1;
-         }
-         *result = *result >= right;
-         break;
-
-      case SL_PP_LESS:
-         ctx->input++;
-         if (_parse_shift(ctx, &right)) {
-            return -1;
-         }
-         *result = *result < right;
-         break;
-
-      case SL_PP_GREATER:
-         ctx->input++;
-         if (_parse_shift(ctx, &right)) {
-            return -1;
-         }
-         *result = *result > right;
-         break;
-
-      default:
-         return 0;
-      }
-   }
-}
-
-static int
-_parse_equality(struct parse_context *ctx,
-                int *result)
-{
-   if (_parse_relational(ctx, result)) {
-      return -1;
-   }
-   for (;;) {
-      int right;
-
-      switch (ctx->input->token) {
-      case SL_PP_EQUAL:
-         ctx->input++;
-         if (_parse_relational(ctx, &right)) {
-            return -1;
-         }
-         *result = *result == right;
-         break;
-
-      case SL_PP_NOTEQUAL:
-         ctx->input++;
-         if (_parse_relational(ctx, &right)) {
-            return -1;
-         }
-         *result = *result != right;
-         break;
-
-      default:
-         return 0;
-      }
-   }
-}
-
-static int
-_parse_bitand(struct parse_context *ctx,
-              int *result)
-{
-   if (_parse_equality(ctx, result)) {
-      return -1;
-   }
-   while (ctx->input->token == SL_PP_BITAND) {
-      int right;
-
-      ctx->input++;
-      if (_parse_equality(ctx, &right)) {
-         return -1;
-      }
-      *result = *result & right;
-   }
-   return 0;
-}
-
-static int
-_parse_xor(struct parse_context *ctx,
-           int *result)
-{
-   if (_parse_bitand(ctx, result)) {
-      return -1;
-   }
-   while (ctx->input->token == SL_PP_XOR) {
-      int right;
-
-      ctx->input++;
-      if (_parse_bitand(ctx, &right)) {
-         return -1;
-      }
-      *result = *result ^ right;
-   }
-   return 0;
-}
-
-static int
-_parse_bitor(struct parse_context *ctx,
-             int *result)
-{
-   if (_parse_xor(ctx, result)) {
-      return -1;
-   }
-   while (ctx->input->token == SL_PP_BITOR) {
-      int right;
-
-      ctx->input++;
-      if (_parse_xor(ctx, &right)) {
-         return -1;
-      }
-      *result = *result | right;
-   }
-   return 0;
-}
-
-static int
-_parse_and(struct parse_context *ctx,
-           int *result)
-{
-   if (_parse_bitor(ctx, result)) {
-      return -1;
-   }
-   while (ctx->input->token == SL_PP_AND) {
-      int right;
-
-      ctx->input++;
-      if (_parse_bitor(ctx, &right)) {
-         return -1;
-      }
-      *result = *result && right;
-   }
-   return 0;
-}
-
-static int
-_parse_or(struct parse_context *ctx,
-          int *result)
-{
-   if (_parse_and(ctx, result)) {
-      return -1;
-   }
-   while (ctx->input->token == SL_PP_OR) {
-      int right;
-
-      ctx->input++;
-      if (_parse_and(ctx, &right)) {
-         return -1;
-      }
-      *result = *result || right;
-   }
-   return 0;
-}
-
-int
-sl_pp_execute_expression(struct sl_pp_context *context,
-                         const struct sl_pp_token_info *input,
-                         int *result)
-{
-   struct parse_context ctx;
-
-   ctx.context = context;
-   ctx.input = input;
-
-   return _parse_or(&ctx, result);
-}
diff --git a/src/glsl/pp/sl_pp_expression.h b/src/glsl/pp/sl_pp_expression.h
deleted file mode 100644 (file)
index 522263b..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#ifndef SL_PP_EXPRESSION_H
-#define SL_PP_EXPRESSION_H
-
-struct sl_pp_context;
-struct sl_pp_token_info;
-
-
-int
-sl_pp_execute_expression(struct sl_pp_context *context,
-                         const struct sl_pp_token_info *input,
-                         int *result);
-
-#endif /* SL_PP_EXPRESSION_H */
diff --git a/src/glsl/pp/sl_pp_extension.c b/src/glsl/pp/sl_pp_extension.c
deleted file mode 100644 (file)
index 00dbdcf..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_process.h"
-#include "sl_pp_public.h"
-#include "sl_pp_token.h"
-
-
-/**
- * Declare an extension to the preprocessor.  This tells the preprocessor
- * which extensions are supported by Mesa.
- * The shader still needs to have a "#extension name: behavior" line to enable
- * the extension.
- */
-int
-sl_pp_context_add_extension(struct sl_pp_context *context,
-                            const char *name)
-{
-   struct sl_pp_extension ext;
-
-   if (context->num_extensions == SL_PP_MAX_EXTENSIONS) {
-      return -1;
-   }
-
-   ext.name = sl_pp_context_add_unique_str(context, name);
-   if (ext.name == -1) {
-      return -1;
-   }
-
-   context->extensions[context->num_extensions++] = ext;
-
-   assert(context->num_extensions <= sizeof(context->extensions));
-
-   return 0;
-}
-
-
-/**
- * Process a "#extension name: behavior" directive.
- */
-int
-sl_pp_process_extension(struct sl_pp_context *context,
-                        const struct sl_pp_token_info *input,
-                        unsigned int first,
-                        unsigned int last,
-                        struct sl_pp_process_state *state)
-{
-   int extension_name = -1;
-   int behavior = -1;
-   struct sl_pp_token_info out;
-
-   /* Grab the extension name. */
-   if (first < last && input[first].token == SL_PP_IDENTIFIER) {
-      extension_name = input[first].data.identifier;
-      first++;
-   }
-   if (extension_name == -1) {
-      strcpy(context->error_msg, "expected identifier after `#extension'");
-      return -1;
-   }
-
-   /* Make sure the extension is supported. */
-   if (extension_name == context->dict.all) {
-      out.data.extension = extension_name;
-   } else {
-      unsigned int i;
-
-      out.data.extension = -1;
-      for (i = 0; i < context->num_extensions; i++) {
-         if (extension_name == context->extensions[i].name) {
-            out.data.extension = extension_name;
-            break;
-         }
-      }
-   }
-
-   /* Grab the colon separating the extension name and behavior. */
-   while (first < last && input[first].token == SL_PP_WHITESPACE) {
-      first++;
-   }
-   if (first < last && input[first].token == SL_PP_COLON) {
-      first++;
-   } else {
-      strcpy(context->error_msg, "expected `:' after extension name");
-      return -1;
-   }
-   while (first < last && input[first].token == SL_PP_WHITESPACE) {
-      first++;
-   }
-
-   /* Grab the behavior name. */
-   if (first < last && input[first].token == SL_PP_IDENTIFIER) {
-      behavior = input[first].data.identifier;
-      first++;
-   }
-   if (behavior == -1) {
-      strcpy(context->error_msg, "expected identifier after `:'");
-      return -1;
-   }
-
-   if (behavior == context->dict.require) {
-      if (out.data.extension == -1) {
-         strcpy(context->error_msg, "the required extension is not supported");
-         return -1;
-      }
-      if (out.data.extension == context->dict.all) {
-         strcpy(context->error_msg, "invalid behavior for `all' extension: `require'");
-         return -1;
-      }
-      out.token = SL_PP_EXTENSION_REQUIRE;
-   } else if (behavior == context->dict.enable) {
-      if (out.data.extension == -1) {
-         /* Warning: the extension cannot be enabled. */
-         return 0;
-      }
-      if (out.data.extension == context->dict.all) {
-         strcpy(context->error_msg, "invalid behavior for `all' extension: `enable'");
-         return -1;
-      }
-      out.token = SL_PP_EXTENSION_ENABLE;
-   } else if (behavior == context->dict.warn) {
-      if (out.data.extension == -1) {
-         /* Warning: the extension is not supported. */
-         return 0;
-      }
-      out.token = SL_PP_EXTENSION_WARN;
-   } else if (behavior == context->dict.disable) {
-      if (out.data.extension == -1) {
-         /* Warning: the extension is not supported. */
-         return 0;
-      }
-      out.token = SL_PP_EXTENSION_DISABLE;
-   } else {
-      strcpy(context->error_msg, "unrecognised behavior name");
-      return -1;
-   }
-
-   /* Grab the end of line. */
-   while (first < last && input[first].token == SL_PP_WHITESPACE) {
-      first++;
-   }
-   if (first < last) {
-      strcpy(context->error_msg, "expected end of line after behavior name");
-      return -1;
-   }
-
-   if (sl_pp_process_out(state, &out)) {
-      return -1;
-   }
-
-   return 0;
-}
diff --git a/src/glsl/pp/sl_pp_if.c b/src/glsl/pp/sl_pp_if.c
deleted file mode 100644 (file)
index 6b7a159..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_expression.h"
-#include "sl_pp_macro.h"
-#include "sl_pp_process.h"
-#include "sl_pp_token.h"
-
-
-static int
-_macro_is_defined(struct sl_pp_context *context,
-                  int macro_name)
-{
-   unsigned int i;
-   struct sl_pp_macro *macro;
-
-   for (i = 0; i < context->num_extensions; i++) {
-      if (macro_name == context->extensions[i].name) {
-         return 1;
-      }
-   }
-
-   for (macro = context->macro; macro; macro = macro->next) {
-      if (macro_name == macro->name) {
-         return 1;
-      }
-   }
-
-   return 0;
-}
-
-static int
-_parse_defined(struct sl_pp_context *context,
-               struct sl_pp_token_buffer *buffer,
-               struct sl_pp_process_state *state)
-{
-   struct sl_pp_token_info input;
-   int parens = 0;
-   int defined;
-   struct sl_pp_token_info result;
-
-   if (sl_pp_token_buffer_skip_white(buffer, &input)) {
-      return -1;
-   }
-
-   if (input.token == SL_PP_LPAREN) {
-      if (sl_pp_token_buffer_skip_white(buffer, &input)) {
-         return -1;
-      }
-      parens = 1;
-   }
-
-   if (input.token != SL_PP_IDENTIFIER) {
-      strcpy(context->error_msg, "expected an identifier");
-      return -1;
-   }
-
-   defined = _macro_is_defined(context, input.data.identifier);
-
-   if (parens) {
-      if (sl_pp_token_buffer_skip_white(buffer, &input)) {
-         return -1;
-      }
-      if (input.token != SL_PP_RPAREN) {
-         strcpy(context->error_msg, "expected `)'");
-         return -1;
-      }
-   }
-
-   result.token = SL_PP_UINT;
-   result.data._uint = (defined ? context->dict._1 : context->dict._0);
-
-   if (sl_pp_process_out(state, &result)) {
-      strcpy(context->error_msg, "out of memory");
-      return -1;
-   }
-
-   return 0;
-}
-
-static unsigned int
-_evaluate_if_stack(struct sl_pp_context *context)
-{
-   unsigned int i;
-
-   for (i = context->if_ptr; i < SL_PP_MAX_IF_NESTING; i++) {
-      if (!context->if_stack[i].u.condition) {
-         return 0;
-      }
-   }
-   return 1;
-}
-
-static int
-_parse_if(struct sl_pp_context *context,
-          struct sl_pp_token_buffer *buffer)
-{
-   struct sl_pp_process_state state;
-   int found_end = 0;
-   struct sl_pp_token_info eof;
-   int result;
-
-   if (!context->if_ptr) {
-      strcpy(context->error_msg, "`#if' nesting too deep");
-      return -1;
-   }
-
-   memset(&state, 0, sizeof(state));
-   while (!found_end) {
-      struct sl_pp_token_info input;
-
-      sl_pp_token_buffer_get(buffer, &input);
-      switch (input.token) {
-      case SL_PP_WHITESPACE:
-         break;
-
-      case SL_PP_IDENTIFIER:
-         if (input.data.identifier == context->dict.defined) {
-            if (_parse_defined(context, buffer, &state)) {
-               free(state.out);
-               return -1;
-            }
-         } else {
-            sl_pp_token_buffer_unget(buffer, &input);
-            if (sl_pp_macro_expand(context, buffer, NULL, &state, sl_pp_macro_expand_unknown_to_0)) {
-               free(state.out);
-               return -1;
-            }
-         }
-         break;
-
-      case SL_PP_NEWLINE:
-      case SL_PP_EOF:
-         found_end = 1;
-         break;
-
-      default:
-         if (sl_pp_process_out(&state, &input)) {
-            strcpy(context->error_msg, "out of memory");
-            free(state.out);
-            return -1;
-         }
-      }
-   }
-
-   eof.token = SL_PP_EOF;
-   if (sl_pp_process_out(&state, &eof)) {
-      strcpy(context->error_msg, "out of memory");
-      free(state.out);
-      return -1;
-   }
-
-   if (sl_pp_execute_expression(context, state.out, &result)) {
-      free(state.out);
-      return -1;
-   }
-
-   free(state.out);
-
-   context->if_ptr--;
-   context->if_stack[context->if_ptr].value = 0;
-   context->if_stack[context->if_ptr].u.condition = result ? 1 : 0;
-   context->if_value = _evaluate_if_stack(context);
-
-   return 0;
-}
-
-static int
-_parse_else(struct sl_pp_context *context)
-{
-   union sl_pp_if_state *state = &context->if_stack[context->if_ptr];
-
-   if (context->if_ptr == SL_PP_MAX_IF_NESTING) {
-      strcpy(context->error_msg, "no matching `#if'");
-      return -1;
-   }
-
-   if (state->u.went_thru_else) {
-      strcpy(context->error_msg, "no matching `#if'");
-      return -1;
-   }
-
-   /* Once we had a true condition, the subsequent #elifs should always be false. */
-   state->u.had_true_cond |= state->u.condition;
-
-   /* Update current condition value and mark that we are in the #else block. */
-   state->u.condition = !(state->u.had_true_cond | state->u.condition);
-   state->u.went_thru_else = 1;
-   context->if_value = _evaluate_if_stack(context);
-
-   return 0;
-}
-
-int
-sl_pp_process_if(struct sl_pp_context *context,
-                 struct sl_pp_token_buffer *buffer)
-{
-   return _parse_if(context, buffer);
-}
-
-int
-sl_pp_process_ifdef(struct sl_pp_context *context,
-                    const struct sl_pp_token_info *input,
-                    unsigned int first,
-                    unsigned int last)
-{
-   unsigned int i;
-
-   if (!context->if_ptr) {
-      strcpy(context->error_msg, "`#if' nesting too deep");
-      return -1;
-   }
-
-   for (i = first; i < last; i++) {
-      switch (input[i].token) {
-      case SL_PP_IDENTIFIER:
-         context->if_ptr--;
-         context->if_stack[context->if_ptr].value = 0;
-         context->if_stack[context->if_ptr].u.condition = _macro_is_defined(context, input[i].data.identifier);
-         context->if_value = _evaluate_if_stack(context);
-         return 0;
-
-      case SL_PP_WHITESPACE:
-         break;
-
-      default:
-         strcpy(context->error_msg, "expected an identifier");
-         return -1;
-      }
-   }
-
-   strcpy(context->error_msg, "expected an identifier");
-   return -1;
-}
-
-int
-sl_pp_process_ifndef(struct sl_pp_context *context,
-                     const struct sl_pp_token_info *input,
-                     unsigned int first,
-                     unsigned int last)
-{
-   unsigned int i;
-
-   if (!context->if_ptr) {
-      strcpy(context->error_msg, "`#if' nesting too deep");
-      return -1;
-   }
-
-   for (i = first; i < last; i++) {
-      switch (input[i].token) {
-      case SL_PP_IDENTIFIER:
-         context->if_ptr--;
-         context->if_stack[context->if_ptr].value = 0;
-         context->if_stack[context->if_ptr].u.condition = !_macro_is_defined(context, input[i].data.identifier);
-         context->if_value = _evaluate_if_stack(context);
-         return 0;
-
-      case SL_PP_WHITESPACE:
-         break;
-
-      default:
-         strcpy(context->error_msg, "expected an identifier");
-         return -1;
-      }
-   }
-
-   strcpy(context->error_msg, "expected an identifier");
-   return -1;
-}
-
-int
-sl_pp_process_elif(struct sl_pp_context *context,
-                   struct sl_pp_token_buffer *buffer)
-{
-   if (_parse_else(context)) {
-      return -1;
-   }
-
-   if (context->if_stack[context->if_ptr].u.condition) {
-      context->if_ptr++;
-      if (_parse_if(context, buffer)) {
-         return -1;
-      }
-   }
-
-   /* We are still in the #if block. */
-   context->if_stack[context->if_ptr].u.went_thru_else = 0;
-
-   return 0;
-}
-
-int
-sl_pp_process_else(struct sl_pp_context *context,
-                   const struct sl_pp_token_info *input,
-                   unsigned int first,
-                   unsigned int last)
-{
-   return _parse_else(context);
-}
-
-int
-sl_pp_process_endif(struct sl_pp_context *context,
-                    const struct sl_pp_token_info *input,
-                    unsigned int first,
-                    unsigned int last)
-{
-   if (context->if_ptr == SL_PP_MAX_IF_NESTING) {
-      strcpy(context->error_msg, "no matching `#if'");
-      return -1;
-   }
-
-   context->if_ptr++;
-   context->if_value = _evaluate_if_stack(context);
-
-   return 0;
-}
diff --git a/src/glsl/pp/sl_pp_line.c b/src/glsl/pp/sl_pp_line.c
deleted file mode 100644 (file)
index 51581c7..0000000
+++ /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 TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_macro.h"
-#include "sl_pp_public.h"
-#include "sl_pp_process.h"
-#include "sl_pp_token.h"
-
-
-int
-sl_pp_process_line(struct sl_pp_context *context,
-                   struct sl_pp_token_buffer *buffer,
-                   struct sl_pp_process_state *pstate)
-{
-   struct sl_pp_process_state state;
-   int found_end = 0;
-   int line_number = -1;
-   int file_number = -1;
-   unsigned int line;
-   unsigned int file;
-
-   memset(&state, 0, sizeof(state));
-   while (!found_end) {
-      struct sl_pp_token_info input;
-
-      sl_pp_token_buffer_get(buffer, &input);
-      switch (input.token) {
-      case SL_PP_WHITESPACE:
-         break;
-
-      case SL_PP_IDENTIFIER:
-         sl_pp_token_buffer_unget(buffer, &input);
-         if (sl_pp_macro_expand(context, buffer, NULL, &state, sl_pp_macro_expand_normal)) {
-            free(state.out);
-            return -1;
-         }
-         break;
-
-      case SL_PP_NEWLINE:
-      case SL_PP_EOF:
-         found_end = 1;
-         break;
-
-      default:
-         if (sl_pp_process_out(&state, &input)) {
-            strcpy(context->error_msg, "out of memory");
-            free(state.out);
-            return -1;
-         }
-      }
-   }
-
-   if (state.out_len > 0 && state.out[0].token == SL_PP_UINT) {
-      line_number = state.out[0].data._uint;
-   } else {
-      strcpy(context->error_msg, "expected a number after `#line'");
-      free(state.out);
-      return -1;
-   }
-
-   if (state.out_len > 1) {
-      if (state.out[1].token == SL_PP_UINT) {
-         file_number = state.out[1].data._uint;
-      } else {
-         strcpy(context->error_msg, "expected a number after line number");
-         free(state.out);
-         return -1;
-      }
-
-      if (state.out_len > 2) {
-         strcpy(context->error_msg, "expected an end of line after file number");
-         free(state.out);
-         return -1;
-      }
-   }
-
-   free(state.out);
-
-   line = atoi(sl_pp_context_cstr(context, line_number));
-   if (file_number != -1) {
-      file = atoi(sl_pp_context_cstr(context, file_number));
-   } else {
-      file = context->file;
-   }
-
-   if (context->line != line || context->file != file) {
-      struct sl_pp_token_info ti;
-
-      ti.token = SL_PP_LINE;
-      ti.data.line.lineno = line;
-      ti.data.line.fileno = file;
-      if (sl_pp_process_out(pstate, &ti)) {
-         strcpy(context->error_msg, "out of memory");
-         return -1;
-      }
-
-      context->line = line;
-      context->file = file;
-   }
-
-   return 0;
-}
diff --git a/src/glsl/pp/sl_pp_macro.c b/src/glsl/pp/sl_pp_macro.c
deleted file mode 100644 (file)
index 2cf9ea3..0000000
+++ /dev/null
@@ -1,415 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_public.h"
-#include "sl_pp_macro.h"
-#include "sl_pp_process.h"
-#include "sl_pp_token.h"
-
-
-static void
-_macro_init(struct sl_pp_macro *macro)
-{
-   macro->name = -1;
-   macro->num_args = -1;
-   macro->arg = NULL;
-   macro->body = NULL;
-}
-
-struct sl_pp_macro *
-sl_pp_macro_new(void)
-{
-   struct sl_pp_macro *macro;
-
-   macro = calloc(1, sizeof(struct sl_pp_macro));
-   if (macro) {
-      _macro_init(macro);
-   }
-   return macro;
-}
-
-static void
-_macro_destroy(struct sl_pp_macro *macro)
-{
-   struct sl_pp_macro_formal_arg *arg = macro->arg;
-
-   while (arg) {
-      struct sl_pp_macro_formal_arg *next_arg = arg->next;
-
-      free(arg);
-      arg = next_arg;
-   }
-
-   free(macro->body);
-}
-
-void
-sl_pp_macro_free(struct sl_pp_macro *macro)
-{
-   while (macro) {
-      struct sl_pp_macro *next_macro = macro->next;
-
-      _macro_destroy(macro);
-      free(macro);
-      macro = next_macro;
-   }
-}
-
-void
-sl_pp_macro_reset(struct sl_pp_macro *macro)
-{
-   _macro_destroy(macro);
-   _macro_init(macro);
-}
-
-static int
-_out_number(struct sl_pp_context *context,
-            struct sl_pp_process_state *state,
-            unsigned int number)
-{
-   char buf[32];
-   struct sl_pp_token_info ti;
-
-   sprintf(buf, "%u", number);
-
-   ti.token = SL_PP_UINT;
-   ti.data._uint = sl_pp_context_add_unique_str(context, buf);
-   if (sl_pp_process_out(state, &ti)) {
-      strcpy(context->error_msg, "out of memory");
-      return -1;
-   }
-
-   return 0;
-}
-
-int
-sl_pp_macro_expand(struct sl_pp_context *context,
-                   struct sl_pp_token_buffer *tokens,
-                   struct sl_pp_macro *local,
-                   struct sl_pp_process_state *state,
-                   enum sl_pp_macro_expand_behaviour behaviour)
-{
-   int mute = (behaviour == sl_pp_macro_expand_mute);
-   struct sl_pp_token_info input;
-   int macro_name;
-   struct sl_pp_macro *macro = NULL;
-   struct sl_pp_macro *actual_arg = NULL;
-   unsigned int j;
-
-   if (sl_pp_token_buffer_get(tokens, &input)) {
-      return -1;
-   }
-
-   if (input.token != SL_PP_IDENTIFIER) {
-      strcpy(context->error_msg, "expected an identifier");
-      return -1;
-   }
-
-   macro_name = input.data.identifier;
-
-   /* First look for predefined macros.
-    */
-
-   if (macro_name == context->dict.___LINE__) {
-      if (!mute && _out_number(context, state, context->line)) {
-         return -1;
-      }
-      return 0;
-   }
-   if (macro_name == context->dict.___FILE__) {
-      if (!mute && _out_number(context, state, context->file)) {
-         return -1;
-      }
-      return 0;
-   }
-   if (macro_name == context->dict.___VERSION__) {
-      if (!mute && _out_number(context, state, 110)) {
-         return -1;
-      }
-      return 0;
-   }
-
-   for (j = 0; j < context->num_predefined; j++) {
-      if (macro_name == context->predefined[j].name) {
-         if (!mute) {
-            struct sl_pp_token_info ti;
-
-            ti.token = SL_PP_UINT;
-            ti.data._uint = context->predefined[j].value;
-            if (sl_pp_process_out(state, &ti)) {
-               strcpy(context->error_msg, "out of memory");
-               return -1;
-            }
-         }
-         return 0;
-      }
-   }
-
-   /* Replace extension names with 1.
-    */
-   for (j = 0; j < context->num_extensions; j++) {
-      if (macro_name == context->extensions[j].name) {
-         if (!mute && _out_number(context, state, 1)) {
-            return -1;
-         }
-         return 0;
-      }
-   }
-
-   if (local) {
-      for (macro = local; macro; macro = macro->next) {
-         if (macro->name == macro_name) {
-            break;
-         }
-      }
-   }
-
-   if (!macro) {
-      for (macro = context->macro; macro; macro = macro->next) {
-         if (macro->name == macro_name) {
-            break;
-         }
-      }
-   }
-
-   if (!macro) {
-      if (behaviour == sl_pp_macro_expand_unknown_to_0) {
-         if (_out_number(context, state, 0)) {
-            strcpy(context->error_msg, "out of memory");
-            return -1;
-         }
-      } else if (!mute) {
-         if (sl_pp_process_out(state, &input)) {
-            strcpy(context->error_msg, "out of memory");
-            return -1;
-         }
-      }
-      return 0;
-   }
-
-   if (macro->num_args >= 0) {
-      if (sl_pp_token_buffer_skip_white(tokens, &input)) {
-         return -1;
-      }
-      if (input.token != SL_PP_LPAREN) {
-         strcpy(context->error_msg, "expected `('");
-         return -1;
-      }
-      if (sl_pp_token_buffer_skip_white(tokens, &input)) {
-         return -1;
-      }
-      sl_pp_token_buffer_unget(tokens, &input);
-   }
-
-   if (macro->num_args > 0) {
-      struct sl_pp_macro_formal_arg *formal_arg = macro->arg;
-      struct sl_pp_macro **pmacro = &actual_arg;
-
-      for (j = 0; j < (unsigned int)macro->num_args; j++) {
-         struct sl_pp_process_state arg_state;
-         int done = 0;
-         unsigned int paren_nesting = 0;
-         struct sl_pp_token_info eof;
-
-         memset(&arg_state, 0, sizeof(arg_state));
-
-         while (!done) {
-            if (sl_pp_token_buffer_get(tokens, &input)) {
-               goto fail_arg;
-            }
-            switch (input.token) {
-            case SL_PP_WHITESPACE:
-               break;
-
-            case SL_PP_COMMA:
-               if (!paren_nesting) {
-                  if (j < (unsigned int)macro->num_args - 1) {
-                     done = 1;
-                  } else {
-                     strcpy(context->error_msg, "too many actual macro arguments");
-                     goto fail_arg;
-                  }
-               } else {
-                  if (sl_pp_process_out(&arg_state, &input)) {
-                     strcpy(context->error_msg, "out of memory");
-                     goto fail_arg;
-                  }
-               }
-               break;
-
-            case SL_PP_LPAREN:
-               paren_nesting++;
-               if (sl_pp_process_out(&arg_state, &input)) {
-                  goto oom_arg;
-               }
-               break;
-
-            case SL_PP_RPAREN:
-               if (!paren_nesting) {
-                  if (j == (unsigned int)macro->num_args - 1) {
-                     done = 1;
-                  } else {
-                     strcpy(context->error_msg, "too few actual macro arguments");
-                     goto fail_arg;
-                  }
-               } else {
-                  paren_nesting--;
-                  if (sl_pp_process_out(&arg_state, &input)) {
-                     goto oom_arg;
-                  }
-               }
-               break;
-
-            case SL_PP_IDENTIFIER:
-               sl_pp_token_buffer_unget(tokens, &input);
-               if (sl_pp_macro_expand(context, tokens, local, &arg_state, sl_pp_macro_expand_normal)) {
-                  goto fail_arg;
-               }
-               break;
-
-            case SL_PP_EOF:
-               strcpy(context->error_msg, "too few actual macro arguments");
-               goto fail_arg;
-
-            default:
-               if (sl_pp_process_out(&arg_state, &input)) {
-                  goto oom_arg;
-               }
-            }
-         }
-
-         eof.token = SL_PP_EOF;
-         if (sl_pp_process_out(&arg_state, &eof)) {
-            goto oom_arg;
-         }
-
-         *pmacro = sl_pp_macro_new();
-         if (!*pmacro) {
-            goto oom_arg;
-         }
-
-         (**pmacro).name = formal_arg->name;
-         (**pmacro).body = arg_state.out;
-
-         formal_arg = formal_arg->next;
-         pmacro = &(**pmacro).next;
-
-         continue;
-
-oom_arg:
-         strcpy(context->error_msg, "out of memory");
-fail_arg:
-         free(arg_state.out);
-         goto fail;
-      }
-   }
-
-   /* Right paren for non-empty argument list has already been eaten. */
-   if (macro->num_args == 0) {
-      if (sl_pp_token_buffer_skip_white(tokens, &input)) {
-         goto fail;
-      }
-      if (input.token != SL_PP_RPAREN) {
-         strcpy(context->error_msg, "expected `)'");
-         goto fail;
-      }
-   }
-
-   /* XXX: This is all wrong, we should be ungetting all tokens
-    *      back to the main token buffer.
-    */
-   {
-      struct sl_pp_token_buffer buffer;
-
-      /* Seek to the end.
-       */
-      for (j = 0; macro->body[j].token != SL_PP_EOF; j++) {
-      }
-      j++;
-
-      /* Create a context-less token buffer since we are not going to underrun
-       * its internal buffer.
-       */
-      if (sl_pp_token_buffer_init(&buffer, NULL)) {
-         strcpy(context->error_msg, "out of memory");
-         goto fail;
-      }
-
-      /* Unget the tokens in reverse order so later they will be fetched correctly.
-       */
-      for (; j > 0; j--) {
-         sl_pp_token_buffer_unget(&buffer, &macro->body[j - 1]);
-      }
-
-      /* Expand.
-       */
-      for (;;) {
-         struct sl_pp_token_info input;
-
-         sl_pp_token_buffer_get(&buffer, &input);
-         switch (input.token) {
-         case SL_PP_NEWLINE:
-            if (sl_pp_process_out(state, &input)) {
-               strcpy(context->error_msg, "out of memory");
-               sl_pp_token_buffer_destroy(&buffer);
-               goto fail;
-            }
-            break;
-
-         case SL_PP_IDENTIFIER:
-            sl_pp_token_buffer_unget(&buffer, &input);
-            if (sl_pp_macro_expand(context, &buffer, actual_arg, state, behaviour)) {
-               sl_pp_token_buffer_destroy(&buffer);
-               goto fail;
-            }
-            break;
-
-         case SL_PP_EOF:
-            sl_pp_token_buffer_destroy(&buffer);
-            sl_pp_macro_free(actual_arg);
-            return 0;
-
-         default:
-            if (!mute) {
-               if (sl_pp_process_out(state, &input)) {
-                  strcpy(context->error_msg, "out of memory");
-                  sl_pp_token_buffer_destroy(&buffer);
-                  goto fail;
-               }
-            }
-         }
-      }
-   }
-
-fail:
-   sl_pp_macro_free(actual_arg);
-   return -1;
-}
diff --git a/src/glsl/pp/sl_pp_macro.h b/src/glsl/pp/sl_pp_macro.h
deleted file mode 100644 (file)
index 6e65a0a..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#ifndef SL_PP_MACRO_H
-#define SL_PP_MACRO_H
-
-struct sl_pp_context;
-struct sl_pp_process_state;
-struct sl_pp_token_buffer;
-
-struct sl_pp_macro_formal_arg {
-   int name;
-   struct sl_pp_macro_formal_arg *next;
-};
-
-struct sl_pp_macro {
-   int name;
-   int num_args;                       /* -1 means no args, 0 means `()' */
-   struct sl_pp_macro_formal_arg *arg;
-   struct sl_pp_token_info *body;
-   struct sl_pp_macro *next;
-};
-
-struct sl_pp_macro *
-sl_pp_macro_new(void);
-
-void
-sl_pp_macro_free(struct sl_pp_macro *macro);
-
-void
-sl_pp_macro_reset(struct sl_pp_macro *macro);
-
-enum sl_pp_macro_expand_behaviour {
-   sl_pp_macro_expand_normal,
-   sl_pp_macro_expand_mute,
-   sl_pp_macro_expand_unknown_to_0
-};
-
-int
-sl_pp_macro_expand(struct sl_pp_context *context,
-                   struct sl_pp_token_buffer *tokens,
-                   struct sl_pp_macro *local,
-                   struct sl_pp_process_state *state,
-                   enum sl_pp_macro_expand_behaviour behaviour);
-
-#endif /* SL_PP_MACRO_H */
diff --git a/src/glsl/pp/sl_pp_pragma.c b/src/glsl/pp/sl_pp_pragma.c
deleted file mode 100644 (file)
index 6789704..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_process.h"
-#include "sl_pp_token.h"
-
-
-int
-sl_pp_process_pragma(struct sl_pp_context *context,
-                     const struct sl_pp_token_info *input,
-                     unsigned int first,
-                     unsigned int last,
-                     struct sl_pp_process_state *state)
-{
-   int pragma_name = -1;
-   struct sl_pp_token_info out;
-   int arg_name = -1;
-
-   if (first < last && input[first].token == SL_PP_IDENTIFIER) {
-      pragma_name = input[first].data.identifier;
-      first++;
-   }
-   if (pragma_name == -1) {
-      return 0;
-   }
-
-   if (pragma_name == context->dict.optimize) {
-      out.token = SL_PP_PRAGMA_OPTIMIZE;
-   } else if (pragma_name == context->dict.debug) {
-      out.token = SL_PP_PRAGMA_DEBUG;
-   } else {
-      return 0;
-   }
-
-   while (first < last && input[first].token == SL_PP_WHITESPACE) {
-      first++;
-   }
-
-   if (first < last && input[first].token == SL_PP_LPAREN) {
-      first++;
-   } else {
-      return 0;
-   }
-
-   while (first < last && input[first].token == SL_PP_WHITESPACE) {
-      first++;
-   }
-
-   if (first < last && input[first].token == SL_PP_IDENTIFIER) {
-      arg_name = input[first].data.identifier;
-      first++;
-   }
-   if (arg_name == -1) {
-      return 0;
-   }
-
-   if (arg_name == context->dict.off) {
-      out.data.pragma = 0;
-   } else if (arg_name == context->dict.on) {
-      out.data.pragma = 1;
-   } else {
-      return 0;
-   }
-
-   while (first < last && input[first].token == SL_PP_WHITESPACE) {
-      first++;
-   }
-
-   if (first < last && input[first].token == SL_PP_RPAREN) {
-      first++;
-   } else {
-      return 0;
-   }
-
-   /* Ignore the tokens that follow. */
-
-   if (sl_pp_process_out(state, &out)) {
-      strcpy(context->error_msg, "out of memory");
-      return -1;
-   }
-
-   return 0;
-}
diff --git a/src/glsl/pp/sl_pp_process.c b/src/glsl/pp/sl_pp_process.c
deleted file mode 100644 (file)
index 2f12393..0000000
+++ /dev/null
@@ -1,331 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_context.h"
-#include "sl_pp_macro.h"
-#include "sl_pp_process.h"
-#include "sl_pp_public.h"
-#include "sl_pp_token.h"
-
-
-int
-sl_pp_process_out(struct sl_pp_process_state *state,
-                  const struct sl_pp_token_info *token)
-{
-   if (state->out_len >= state->out_max) {
-      unsigned int new_max = state->out_max;
-
-      if (new_max < 0x100) {
-         new_max = 0x100;
-      } else if (new_max < 0x10000) {
-         new_max *= 2;
-      } else {
-         new_max += 0x10000;
-      }
-
-      state->out = realloc(state->out, new_max * sizeof(struct sl_pp_token_info));
-      if (!state->out) {
-         return -1;
-      }
-      state->out_max = new_max;
-   }
-
-   state->out[state->out_len++] = *token;
-   return 0;
-}
-
-int
-sl_pp_process_get(struct sl_pp_context *context,
-                  struct sl_pp_token_info *output)
-{
-   if (!context->process_state.out) {
-      if (context->line > 1) {
-         struct sl_pp_token_info ti;
-
-         ti.token = SL_PP_LINE;
-         ti.data.line.lineno = context->line - 1;
-         ti.data.line.fileno = context->file;
-         if (sl_pp_process_out(&context->process_state, &ti)) {
-            strcpy(context->error_msg, "out of memory");
-            return -1;
-         }
-
-         ti.token = SL_PP_NEWLINE;
-         if (sl_pp_process_out(&context->process_state, &ti)) {
-            strcpy(context->error_msg, "out of memory");
-            return -1;
-         }
-      }
-   }
-
-   for (;;) {
-      struct sl_pp_token_info input;
-      int found_eof = 0;
-
-      if (context->process_state.out_len) {
-         assert(context->process_state.out);
-         *output = context->process_state.out[0];
-
-         if (context->process_state.out_len > 1) {
-            unsigned int i;
-
-            for (i = 1; i < context->process_state.out_len; i++) {
-               context->process_state.out[i - 1] = context->process_state.out[i];
-            }
-         }
-         context->process_state.out_len--;
-
-         return 0;
-      }
-
-      if (sl_pp_token_buffer_skip_white(&context->tokens, &input)) {
-         return -1;
-      }
-      if (input.token == SL_PP_HASH) {
-         if (sl_pp_token_buffer_skip_white(&context->tokens, &input)) {
-            return -1;
-         }
-         switch (input.token) {
-         case SL_PP_IDENTIFIER:
-            {
-               int name;
-               int found_eol = 0;
-               struct sl_pp_token_info endof;
-               struct sl_pp_token_peek peek;
-               int result = 0;
-
-               /* Directive name. */
-               name = input.data.identifier;
-
-               if (sl_pp_token_buffer_skip_white(&context->tokens, &input)) {
-                  return -1;
-               }
-               sl_pp_token_buffer_unget(&context->tokens, &input);
-
-               if (sl_pp_token_peek_init(&peek, &context->tokens)) {
-                  return -1;
-               }
-
-               while (!found_eol) {
-                  if (sl_pp_token_peek_get(&peek, &input)) {
-                     sl_pp_token_peek_destroy(&peek);
-                     return -1;
-                  }
-                  switch (input.token) {
-                  case SL_PP_NEWLINE:
-                     /* Preserve newline just for the sake of line numbering. */
-                     endof = input;
-                     found_eol = 1;
-                     break;
-
-                  case SL_PP_EOF:
-                     endof = input;
-                     found_eof = 1;
-                     found_eol = 1;
-                     break;
-
-                  default:
-                     break;
-                  }
-               }
-
-               if (name == context->dict._if) {
-                  struct sl_pp_token_buffer buffer;
-
-                  result = sl_pp_token_peek_to_buffer(&peek, &buffer);
-                  if (result == 0) {
-                     result = sl_pp_process_if(context, &buffer);
-                     sl_pp_token_buffer_destroy(&buffer);
-                  }
-               } else if (name == context->dict.ifdef) {
-                  result = sl_pp_process_ifdef(context, peek.tokens, 0, peek.size - 1);
-               } else if (name == context->dict.ifndef) {
-                  result = sl_pp_process_ifndef(context, peek.tokens, 0, peek.size - 1);
-               } else if (name == context->dict.elif) {
-                  struct sl_pp_token_buffer buffer;
-
-                  result = sl_pp_token_peek_to_buffer(&peek, &buffer);
-                  if (result == 0) {
-                     result = sl_pp_process_elif(context, &buffer);
-                     sl_pp_token_buffer_destroy(&buffer);
-                  }
-               } else if (name == context->dict._else) {
-                  result = sl_pp_process_else(context, peek.tokens, 0, peek.size - 1);
-               } else if (name == context->dict.endif) {
-                  result = sl_pp_process_endif(context, peek.tokens, 0, peek.size - 1);
-               } else if (context->if_value) {
-                  if (name == context->dict.define) {
-                     result = sl_pp_process_define(context, peek.tokens, 0, peek.size - 1);
-                  } else if (name == context->dict.error) {
-                     sl_pp_process_error(context, peek.tokens, 0, peek.size - 1);
-                     result = -1;
-                  } else if (name == context->dict.extension) {
-                     result = sl_pp_process_extension(context, peek.tokens, 0, peek.size - 1, &context->process_state);
-                  } else if (name == context->dict.line) {
-                     struct sl_pp_token_buffer buffer;
-
-                     result = sl_pp_token_peek_to_buffer(&peek, &buffer);
-                     if (result == 0) {
-                        result = sl_pp_process_line(context, &buffer, &context->process_state);
-                        sl_pp_token_buffer_destroy(&buffer);
-                     }
-                  } else if (name == context->dict.pragma) {
-                     result = sl_pp_process_pragma(context, peek.tokens, 0, peek.size - 1, &context->process_state);
-                  } else if (name == context->dict.undef) {
-                     result = sl_pp_process_undef(context, peek.tokens, 0, peek.size - 1);
-                  } else {
-                     strcpy(context->error_msg, "unrecognised directive name");
-                     result = -1;
-                  }
-               }
-
-               sl_pp_token_peek_commit(&peek);
-               sl_pp_token_peek_destroy(&peek);
-
-               if (result) {
-                  return result;
-               }
-
-               if (sl_pp_process_out(&context->process_state, &endof)) {
-                  strcpy(context->error_msg, "out of memory");
-                  return -1;
-               }
-               context->line++;
-            }
-            break;
-
-         case SL_PP_NEWLINE:
-            /* Empty directive. */
-            if (sl_pp_process_out(&context->process_state, &input)) {
-               strcpy(context->error_msg, "out of memory");
-               return -1;
-            }
-            context->line++;
-            break;
-
-         case SL_PP_EOF:
-            /* Empty directive. */
-            if (sl_pp_process_out(&context->process_state, &input)) {
-               strcpy(context->error_msg, "out of memory");
-               return -1;
-            }
-            found_eof = 1;
-            break;
-
-         default:
-            strcpy(context->error_msg, "expected a directive name");
-            return -1;
-         }
-      } else {
-         int found_eol = 0;
-
-         sl_pp_token_buffer_unget(&context->tokens, &input);
-
-         while (!found_eol) {
-            if (sl_pp_token_buffer_get(&context->tokens, &input)) {
-               return -1;
-            }
-
-            switch (input.token) {
-            case SL_PP_WHITESPACE:
-               /* Drop whitespace all together at this point. */
-               break;
-
-            case SL_PP_NEWLINE:
-               /* Preserve newline just for the sake of line numbering. */
-               if (sl_pp_process_out(&context->process_state, &input)) {
-                  strcpy(context->error_msg, "out of memory");
-                  return -1;
-               }
-               context->line++;
-               found_eol = 1;
-               break;
-
-            case SL_PP_EOF:
-               if (sl_pp_process_out(&context->process_state, &input)) {
-                  strcpy(context->error_msg, "out of memory");
-                  return -1;
-               }
-               found_eof = 1;
-               found_eol = 1;
-               break;
-
-            case SL_PP_IDENTIFIER:
-               sl_pp_token_buffer_unget(&context->tokens, &input);
-               if (sl_pp_macro_expand(context, &context->tokens, NULL, &context->process_state,
-                                      context->if_value ? sl_pp_macro_expand_normal : sl_pp_macro_expand_mute)) {
-                  return -1;
-               }
-               break;
-
-            default:
-               if (context->if_value) {
-                  if (sl_pp_process_out(&context->process_state, &input)) {
-                     strcpy(context->error_msg, "out of memory");
-                     return -1;
-                  }
-               }
-            }
-         }
-      }
-
-      if (found_eof) {
-         if (context->if_ptr != SL_PP_MAX_IF_NESTING) {
-            strcpy(context->error_msg, "expected `#endif' directive");
-            return -1;
-         }
-      }
-   }
-}
-
-int
-sl_pp_process(struct sl_pp_context *context,
-              struct sl_pp_token_info **output)
-{
-   struct sl_pp_process_state state;
-
-   memset(&state, 0, sizeof(state));
-   for (;;) {
-      struct sl_pp_token_info input;
-
-      if (sl_pp_process_get(context, &input)) {
-         free(state.out);
-         return -1;
-      }
-      if (sl_pp_process_out(&state, &input)) {
-         free(state.out);
-         return -1;
-      }
-      if (input.token == SL_PP_EOF) {
-         *output = state.out;
-         return 0;
-      }
-   }
-}
diff --git a/src/glsl/pp/sl_pp_process.h b/src/glsl/pp/sl_pp_process.h
deleted file mode 100644 (file)
index 04e9be4..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#ifndef SL_PP_PROCESS_H
-#define SL_PP_PROCESS_H
-
-struct sl_pp_context;
-struct sl_pp_token_buffer;
-
-struct sl_pp_process_state {
-   struct sl_pp_token_info *out;
-   unsigned int out_len;
-   unsigned int out_max;
-};
-
-int
-sl_pp_process_define(struct sl_pp_context *context,
-                     const struct sl_pp_token_info *input,
-                     unsigned int first,
-                     unsigned int last);
-
-int
-sl_pp_process_undef(struct sl_pp_context *context,
-                    const struct sl_pp_token_info *input,
-                    unsigned int first,
-                    unsigned int last);
-
-int
-sl_pp_process_if(struct sl_pp_context *context,
-                 struct sl_pp_token_buffer *input);
-
-int
-sl_pp_process_ifdef(struct sl_pp_context *context,
-                    const struct sl_pp_token_info *input,
-                    unsigned int first,
-                    unsigned int last);
-
-int
-sl_pp_process_ifndef(struct sl_pp_context *context,
-                     const struct sl_pp_token_info *input,
-                     unsigned int first,
-                     unsigned int last);
-
-int
-sl_pp_process_elif(struct sl_pp_context *context,
-                   struct sl_pp_token_buffer *buffer);
-
-int
-sl_pp_process_else(struct sl_pp_context *context,
-                   const struct sl_pp_token_info *input,
-                   unsigned int first,
-                   unsigned int last);
-
-int
-sl_pp_process_endif(struct sl_pp_context *context,
-                    const struct sl_pp_token_info *input,
-                    unsigned int first,
-                    unsigned int last);
-
-void
-sl_pp_process_error(struct sl_pp_context *context,
-                    const struct sl_pp_token_info *input,
-                    unsigned int first,
-                    unsigned int last);
-
-int
-sl_pp_process_pragma(struct sl_pp_context *context,
-                     const struct sl_pp_token_info *input,
-                     unsigned int first,
-                     unsigned int last,
-                     struct sl_pp_process_state *state);
-
-int
-sl_pp_process_extension(struct sl_pp_context *context,
-                        const struct sl_pp_token_info *input,
-                        unsigned int first,
-                        unsigned int last,
-                        struct sl_pp_process_state *state);
-
-int
-sl_pp_process_line(struct sl_pp_context *context,
-                   struct sl_pp_token_buffer *buffer,
-                   struct sl_pp_process_state *state);
-
-int
-sl_pp_process_out(struct sl_pp_process_state *state,
-                  const struct sl_pp_token_info *token);
-
-#endif /* SL_PP_PROCESS_H */
diff --git a/src/glsl/pp/sl_pp_public.h b/src/glsl/pp/sl_pp_public.h
deleted file mode 100644 (file)
index 66ced6c..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#ifndef SL_PP_PUBLIC_H
-#define SL_PP_PUBLIC_H
-
-struct sl_pp_context;
-struct sl_pp_purify_options;
-struct sl_pp_token_info;
-
-struct sl_pp_context *
-sl_pp_context_create(const char *input,
-                     const struct sl_pp_purify_options *options);
-
-void
-sl_pp_context_destroy(struct sl_pp_context *context);
-
-const char *
-sl_pp_context_error_message(const struct sl_pp_context *context);
-
-void
-sl_pp_context_error_position(const struct sl_pp_context *context,
-                             unsigned int *file,
-                             unsigned int *line);
-
-int
-sl_pp_context_add_extension(struct sl_pp_context *context,
-                            const char *name);
-
-int
-sl_pp_context_add_predefined(struct sl_pp_context *context,
-                             const char *name,
-                             const char *value);
-
-int
-sl_pp_context_add_unique_str(struct sl_pp_context *context,
-                             const char *str);
-
-const char *
-sl_pp_context_cstr(const struct sl_pp_context *context,
-                   int offset);
-
-int
-sl_pp_version(struct sl_pp_context *context,
-              unsigned int *version);
-
-int
-sl_pp_process_get(struct sl_pp_context *context,
-                  struct sl_pp_token_info *output);
-
-int
-sl_pp_process(struct sl_pp_context *context,
-              struct sl_pp_token_info **output);
-
-#endif /* SL_PP_PUBLIC_H */
diff --git a/src/glsl/pp/sl_pp_purify.c b/src/glsl/pp/sl_pp_purify.c
deleted file mode 100644 (file)
index acc000c..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include "sl_pp_purify.h"
-
-
-/*
- * Preprocessor purifier performs the following tasks.
- * - Convert all variants of newlines into a Unix newline.
- * - Merge continued lines into a single long line.
- * - Remove line comments and replace block comments with whitespace.
- */
-
-
-static unsigned int
-_purify_newline(const char *input,
-                char *out,
-                unsigned int *current_line)
-{
-   if (input[0] == '\n') {
-      *out = '\n';
-      (*current_line)++;
-      if (input[1] == '\r') {
-         /*
-          * The GLSL spec is not explicit about whether this
-          * combination is a valid newline or not.
-          * Let's assume it is acceptable.
-          */
-         return 2;
-      }
-      return 1;
-   }
-   if (input[0] == '\r') {
-      *out = '\n';
-      (*current_line)++;
-      if (input[1] == '\n') {
-         return 2;
-      }
-      return 1;
-   }
-   *out = input[0];
-   return 1;
-}
-
-
-static unsigned int
-_purify_backslash(const char *input,
-                  char *out,
-                  unsigned int *current_line)
-{
-   unsigned int eaten = 0;
-
-   for (;;) {
-      if (input[0] == '\\') {
-         char next;
-         unsigned int next_eaten;
-         unsigned int next_line = *current_line;
-
-         eaten++;
-         input++;
-
-         next_eaten = _purify_newline(input, &next, &next_line);
-         if (next == '\n') {
-            /*
-             * If this is really a line continuation sequence, eat
-             * it and do not exit the loop.
-             */
-            eaten += next_eaten;
-            input += next_eaten;
-            *current_line = next_line;
-         } else {
-            /*
-             * It is an error to put anything between a backslash
-             * and a newline and still expect it to behave like a line
-             * continuation sequence.
-             * Even if it is an innocent whitespace.
-             */
-            *out = '\\';
-            break;
-         }
-      } else {
-         eaten += _purify_newline(input, out, current_line);
-         break;
-      }
-   }
-   return eaten;
-}
-
-
-static void
-_report_error(char *buf,
-              unsigned int cbbuf,
-              const char *msg,
-              ...)
-{
-   va_list args;
-
-   va_start(args, msg);
-   vsnprintf(buf, cbbuf, msg, args);
-   va_end(args);
-}
-
-
-void
-sl_pp_purify_state_init(struct sl_pp_purify_state *state,
-                        const char *input,
-                        const struct sl_pp_purify_options *options)
-{
-   state->options = *options;
-   state->input = input;
-   state->current_line = 1;
-   state->inside_c_comment = 0;
-}
-
-
-static unsigned int
-_purify_comment(struct sl_pp_purify_state *state,
-                char *output,
-                unsigned int *current_line,
-                char *errormsg,
-                unsigned int cberrormsg)
-{
-   for (;;) {
-      unsigned int eaten;
-      char next;
-
-      eaten = _purify_backslash(state->input, &next, current_line);
-      state->input += eaten;
-      while (next == '*') {
-         eaten = _purify_backslash(state->input, &next, current_line);
-         state->input += eaten;
-         if (next == '/') {
-            *output = ' ';
-            state->inside_c_comment = 0;
-            return 1;
-         }
-      }
-      if (next == '\n') {
-         *output = '\n';
-         state->inside_c_comment = 1;
-         return 1;
-      }
-      if (next == '\0') {
-         _report_error(errormsg, cberrormsg, "expected `*/' but end of translation unit found");
-         return 0;
-      }
-   }
-}
-
-
-unsigned int
-sl_pp_purify_getc(struct sl_pp_purify_state *state,
-                  char *output,
-                  unsigned int *current_line,
-                  char *errormsg,
-                  unsigned int cberrormsg)
-{
-   unsigned int eaten;
-
-   if (state->inside_c_comment) {
-      return _purify_comment(state, output, current_line, errormsg, cberrormsg);
-   }
-
-   eaten = _purify_backslash(state->input, output, current_line);
-   state->input += eaten;
-   if (*output == '/') {
-      char next;
-      unsigned int next_line = *current_line;
-
-      eaten = _purify_backslash(state->input, &next, &next_line);
-      if (next == '/') {
-         state->input += eaten;
-         *current_line = next_line;
-
-         /* Replace a line comment with either a newline or nil. */
-         for (;;) {
-            eaten = _purify_backslash(state->input, &next, current_line);
-            state->input += eaten;
-            if (next == '\n' || next == '\0') {
-               *output = next;
-               return eaten;
-            }
-         }
-      } else if (next == '*') {
-         state->input += eaten;
-         *current_line = next_line;
-
-         return _purify_comment(state, output, current_line, errormsg, cberrormsg);
-      }
-   }
-   return eaten;
-}
-
-
-struct out_buf {
-   char *out;
-   unsigned int len;
-   unsigned int capacity;
-   unsigned int current_line;
-   char *errormsg;
-   unsigned int cberrormsg;
-};
-
-
-static int
-_out_buf_putc(struct out_buf *obuf,
-              char c)
-{
-   if (obuf->len >= obuf->capacity) {
-      unsigned int new_max = obuf->capacity;
-
-      if (new_max < 0x100) {
-         new_max = 0x100;
-      } else if (new_max < 0x10000) {
-         new_max *= 2;
-      } else {
-         new_max += 0x10000;
-      }
-
-      obuf->out = realloc(obuf->out, new_max);
-      if (!obuf->out) {
-         _report_error(obuf->errormsg, obuf->cberrormsg, "out of memory");
-         return -1;
-      }
-      obuf->capacity = new_max;
-   }
-
-   obuf->out[obuf->len++] = c;
-
-   return 0;
-}
-
-
-int
-sl_pp_purify(const char *input,
-             const struct sl_pp_purify_options *options,
-             char **output,
-             char *errormsg,
-             unsigned int cberrormsg,
-             unsigned int *errorline)
-{
-   struct out_buf obuf;
-   struct sl_pp_purify_state state;
-
-   obuf.out = NULL;
-   obuf.len = 0;
-   obuf.capacity = 0;
-   obuf.current_line = 1;
-   obuf.errormsg = errormsg;
-   obuf.cberrormsg = cberrormsg;
-
-   sl_pp_purify_state_init(&state, input, options);
-
-   for (;;) {
-      unsigned int eaten;
-      char c;
-
-      eaten = sl_pp_purify_getc(&state, &c, &obuf.current_line, errormsg, cberrormsg);
-      if (!eaten) {
-         *errorline = obuf.current_line;
-         return -1;
-      }
-      if (_out_buf_putc(&obuf, c)) {
-         *errorline = obuf.current_line;
-         return -1;
-      }
-
-      if (c == '\0') {
-         break;
-      }
-   }
-
-   *output = obuf.out;
-   return 0;
-}
diff --git a/src/glsl/pp/sl_pp_purify.h b/src/glsl/pp/sl_pp_purify.h
deleted file mode 100644 (file)
index c0f55cb..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#ifndef SL_PP_PURIFY_H
-#define SL_PP_PURIFY_H
-
-struct sl_pp_purify_options {
-   unsigned int preserve_columns:1;
-   unsigned int tab_width:4;
-};
-
-int
-sl_pp_purify(const char *input,
-             const struct sl_pp_purify_options *options,
-             char **output,
-             char *errormsg,
-             unsigned int cberrormsg,
-             unsigned int *errorline);
-
-struct sl_pp_purify_state {
-   struct sl_pp_purify_options options;
-   const char *input;
-   unsigned int current_line;
-   unsigned int inside_c_comment:1;
-};
-
-void
-sl_pp_purify_state_init(struct sl_pp_purify_state *state,
-                        const char *input,
-                        const struct sl_pp_purify_options *options);
-
-unsigned int
-sl_pp_purify_getc(struct sl_pp_purify_state *state,
-                  char *output,
-                  unsigned int *current_line,
-                  char *errormsg,
-                  unsigned int cberrormsg);
-
-#endif /* SL_PP_PURIFY_H */
diff --git a/src/glsl/pp/sl_pp_token.c b/src/glsl/pp/sl_pp_token.c
deleted file mode 100644 (file)
index a708978..0000000
+++ /dev/null
@@ -1,854 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_public.h"
-#include "sl_pp_context.h"
-#include "sl_pp_token.h"
-
-
-#define PURE_ERROR 256
-
-static int
-_pure_getc(struct sl_pp_context *context)
-{
-   char c;
-
-   if (context->getc_buf_size) {
-      return context->getc_buf[--context->getc_buf_size];
-   }
-
-   if (sl_pp_purify_getc(&context->pure, &c, &context->error_line, context->error_msg, sizeof(context->error_msg)) == 0) {
-      return PURE_ERROR;
-   }
-   return c;
-}
-
-
-static void
-_pure_ungetc(struct sl_pp_context *context,
-             int c)
-{
-   assert(c != PURE_ERROR);
-
-   if (context->getc_buf_size == context->getc_buf_capacity) {
-      context->getc_buf_capacity += 64;
-      context->getc_buf = realloc(context->getc_buf, context->getc_buf_capacity * sizeof(char));
-      assert(context->getc_buf);                            
-   }
-
-   context->getc_buf[context->getc_buf_size++] = (char)c;
-}
-
-
-struct lookahead_state {
-   char buf[256];
-   unsigned int pos;
-   struct sl_pp_context *context;
-};
-
-
-static void
-_lookahead_init(struct lookahead_state *lookahead,
-                struct sl_pp_context *context)
-{
-   lookahead->pos = 0;
-   lookahead->context = context;
-}
-
-
-static unsigned int
-_lookahead_tell(const struct lookahead_state *lookahead)
-{
-   return lookahead->pos;
-}
-
-
-static const void *
-_lookahead_buf(const struct lookahead_state *lookahead)
-{
-   return lookahead->buf;
-}
-
-
-static void
-_lookahead_revert(struct lookahead_state *lookahead,
-                  unsigned int pos)
-{
-   assert(pos <= lookahead->pos);
-
-   while (lookahead->pos > pos) {
-      _pure_ungetc(lookahead->context, lookahead->buf[--lookahead->pos]);
-   }
-}
-
-
-static int
-_lookahead_getc(struct lookahead_state *lookahead)
-{
-   int c;
-
-   assert(lookahead->pos < sizeof(lookahead->buf) / sizeof(lookahead->buf[0]));
-
-   c = _pure_getc(lookahead->context);
-   if (c != PURE_ERROR) {
-      lookahead->buf[lookahead->pos++] = (char)c;
-   }
-   return c;
-}
-
-
-static int
-_is_identifier_char(char c)
-{
-   return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
-}
-
-
-static int
-_tokenise_identifier(struct sl_pp_context *context,
-                     struct sl_pp_token_info *out)
-{
-   int c;
-   char identifier[256];   /* XXX: Remove this artifical limit. */
-   unsigned int i = 0;
-
-   out->token = SL_PP_IDENTIFIER;
-   out->data.identifier = -1;
-
-   c = _pure_getc(context);
-   if (c == PURE_ERROR) {
-      return -1;
-   }
-   identifier[i++] = (char)c;
-   for (;;) {
-      c = _pure_getc(context);
-      if (c == PURE_ERROR) {
-         return -1;
-      }
-
-      if (_is_identifier_char((char)c)) {
-         if (i >= sizeof(identifier) / sizeof(char) - 1) {
-            strcpy(context->error_msg, "out of memory");
-            _pure_ungetc(context, c);
-            while (i) {
-               _pure_ungetc(context, identifier[--i]);
-            }
-            return -1;
-         }
-         identifier[i++] = (char)c;
-      } else {
-         _pure_ungetc(context, c);
-         break;
-      }
-   }
-   identifier[i] = '\0';
-
-   out->data.identifier = sl_pp_context_add_unique_str(context, identifier);
-   if (out->data.identifier == -1) {
-      while (i) {
-         _pure_ungetc(context, identifier[--i]);
-      }
-      return -1;
-   }
-
-   return 0;
-}
-
-
-/*
- * Return the number of consecutive decimal digits in the input stream.
- */
-static unsigned int
-_parse_float_digits(struct lookahead_state *lookahead)
-{
-   unsigned int eaten;
-
-   for (eaten = 0;; eaten++) {
-      unsigned int pos = _lookahead_tell(lookahead);
-      char c = _lookahead_getc(lookahead);
-
-      if (c < '0' || c > '9') {
-         _lookahead_revert(lookahead, pos);
-         break;
-      }
-   }
-   return eaten;
-}
-
-
-/*
- * Try to match one of the following patterns for the fractional part
- * of a floating point number.
- *
- * digits . [digits]
- * . digits
- *
- * Return 0 if the pattern could not be matched, otherwise the number
- * of eaten characters from the input stream.
- */
-static unsigned int
-_parse_float_frac(struct lookahead_state *lookahead)
-{
-   unsigned int pos;
-   int c;
-   unsigned int eaten;
-
-   pos = _lookahead_tell(lookahead);
-   c = _lookahead_getc(lookahead);
-   if (c == '.') {
-      eaten = _parse_float_digits(lookahead);
-      if (eaten) {
-         return eaten + 1;
-      }
-      _lookahead_revert(lookahead, pos);
-      return 0;
-   }
-
-   _lookahead_revert(lookahead, pos);
-   eaten = _parse_float_digits(lookahead);
-   if (eaten) {
-      c = _lookahead_getc(lookahead);
-      if (c == '.') {
-         return eaten + 1 + _parse_float_digits(lookahead);
-      }
-   }
-
-   _lookahead_revert(lookahead, pos);
-   return 0;
-}
-
-
-/*
- * Try to match the following pattern for the exponential part
- * of a floating point number.
- *
- * (e|E) [(+|-)] digits
- *
- * Return 0 if the pattern could not be matched, otherwise the number
- * of eaten characters from the input stream.
- */
-static unsigned int
-_parse_float_exp(struct lookahead_state *lookahead)
-{
-   unsigned int pos, pos2;
-   int c;
-   unsigned int eaten, digits;
-
-   pos = _lookahead_tell(lookahead);
-   c = _lookahead_getc(lookahead);
-   if (c != 'e' && c != 'E') {
-      _lookahead_revert(lookahead, pos);
-      return 0;
-   }
-
-   pos2 = _lookahead_tell(lookahead);
-   c = _lookahead_getc(lookahead);
-   if (c == '-' || c == '+') {
-      eaten = 2;
-   } else {
-      _lookahead_revert(lookahead, pos2);
-      eaten = 1;
-   }
-
-   digits = _parse_float_digits(lookahead);
-   if (!digits) {
-      _lookahead_revert(lookahead, pos);
-      return 0;
-   }
-
-   return eaten + digits;
-}
-
-
-/*
- * Try to match one of the following patterns for a floating point number.
- *
- * fract [exp] [(f|F)]
- * digits exp [(f|F)]
- *
- * Return 0 if the pattern could not be matched, otherwise the number
- * of eaten characters from the input stream.
- */
-static unsigned int
-_parse_float(struct lookahead_state *lookahead)
-{
-   unsigned int eaten;
-
-   eaten = _parse_float_frac(lookahead);
-   if (eaten) {
-      unsigned int pos;
-      int c;
-
-      eaten += _parse_float_exp(lookahead);
-
-      pos = _lookahead_tell(lookahead);
-      c = _lookahead_getc(lookahead);
-      if (c == 'f' || c == 'F') {
-         eaten++;
-      } else {
-         _lookahead_revert(lookahead, pos);
-      }
-
-      return eaten;
-   }
-
-   eaten = _parse_float_digits(lookahead);
-   if (eaten) {
-      unsigned int exponent;
-
-      exponent = _parse_float_exp(lookahead);
-      if (exponent) {
-         unsigned int pos;
-         int c;
-
-         eaten += exponent;
-
-         pos = _lookahead_tell(lookahead);
-         c = _lookahead_getc(lookahead);
-         if (c == 'f' || c == 'F') {
-            eaten++;
-         } else {
-            _lookahead_revert(lookahead, pos);
-         }
-
-         return eaten;
-      }
-   }
-
-   _lookahead_revert(lookahead, 0);
-   return 0;
-}
-
-
-static unsigned int
-_parse_hex(struct lookahead_state *lookahead)
-{
-   int c;
-   unsigned int n;
-
-   c = _lookahead_getc(lookahead);
-   if (c != '0') {
-      _lookahead_revert(lookahead, 0);
-      return 0;
-   }
-
-   c = _lookahead_getc(lookahead);
-   if (c != 'x' && c != 'X') {
-      _lookahead_revert(lookahead, 0);
-      return 0;
-   }
-
-   for (n = 2;;) {
-      unsigned int pos = _lookahead_tell(lookahead);
-
-      c = _lookahead_getc(lookahead);
-      if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
-         n++;
-      } else {
-         _lookahead_revert(lookahead, pos);
-         break;
-      }
-   }
-
-   if (n > 2) {
-      return n;
-   }
-
-   _lookahead_revert(lookahead, 0);
-   return 0;
-}
-
-
-static unsigned int
-_parse_oct(struct lookahead_state *lookahead)
-{
-   int c;
-   unsigned int n;
-
-   c = _lookahead_getc(lookahead);
-   if (c != '0') {
-      _lookahead_revert(lookahead, 0);
-      return 0;
-   }
-
-   for (n = 1;;) {
-      unsigned int pos = _lookahead_tell(lookahead);
-
-      c = _lookahead_getc(lookahead);
-      if ((c >= '0' && c <= '7')) {
-         n++;
-      } else {
-         _lookahead_revert(lookahead, pos);
-         break;
-      }
-   }
-
-   return n;
-}
-
-
-static unsigned int
-_parse_dec(struct lookahead_state *lookahead)
-{
-   unsigned int n = 0;
-
-   for (;;) {
-      unsigned int pos = _lookahead_tell(lookahead);
-      int c = _lookahead_getc(lookahead);
-
-      if ((c >= '0' && c <= '9')) {
-         n++;
-      } else {
-         _lookahead_revert(lookahead, pos);
-         break;
-      }
-   }
-
-   return n;
-}
-
-
-static int
-_tokenise_number(struct sl_pp_context *context,
-                 struct sl_pp_token_info *out)
-{
-   struct lookahead_state lookahead;
-   unsigned int eaten;
-   unsigned int is_float = 0;
-   unsigned int pos;
-   int c;
-   char number[256];   /* XXX: Remove this artifical limit. */
-
-   _lookahead_init(&lookahead, context);
-
-   eaten = _parse_float(&lookahead);
-   if (!eaten) {
-      eaten = _parse_hex(&lookahead);
-      if (!eaten) {
-         eaten = _parse_oct(&lookahead);
-         if (!eaten) {
-            eaten = _parse_dec(&lookahead);
-         }
-      }
-   } else {
-      is_float = 1;
-   }
-
-   if (!eaten) {
-      strcpy(context->error_msg, "expected a number");
-      return -1;
-   }
-
-   pos = _lookahead_tell(&lookahead);
-   c = _lookahead_getc(&lookahead);
-   _lookahead_revert(&lookahead, pos);
-
-   if (_is_identifier_char(c)) {
-      strcpy(context->error_msg, "expected a number");
-      _lookahead_revert(&lookahead, 0);
-      return -1;
-   }
-
-   if (eaten > sizeof(number) - 1) {
-      strcpy(context->error_msg, "out of memory");
-      _lookahead_revert(&lookahead, 0);
-      return -1;
-   }
-
-   assert(_lookahead_tell(&lookahead) == eaten);
-
-   memcpy(number, _lookahead_buf(&lookahead), eaten);
-   number[eaten] = '\0';
-
-   if (is_float) {
-      out->token = SL_PP_FLOAT;
-      out->data._float = sl_pp_context_add_unique_str(context, number);
-      if (out->data._float == -1) {
-         _lookahead_revert(&lookahead, 0);
-         return -1;
-      }
-   } else {
-      out->token = SL_PP_UINT;
-      out->data._uint = sl_pp_context_add_unique_str(context, number);
-      if (out->data._uint == -1) {
-         _lookahead_revert(&lookahead, 0);
-         return -1;
-      }
-   }
-
-   return 0;
-}
-
-
-int
-sl_pp_token_get(struct sl_pp_context *context,
-                struct sl_pp_token_info *out)
-{
-   int c = _pure_getc(context);
-
-   switch (c) {
-   case ' ':
-   case '\t':
-      out->token = SL_PP_WHITESPACE;
-      break;
-
-   case '\n':
-      out->token = SL_PP_NEWLINE;
-      break;
-
-   case '#':
-      out->token = SL_PP_HASH;
-      break;
-
-   case ',':
-      out->token = SL_PP_COMMA;
-      break;
-
-   case ';':
-      out->token = SL_PP_SEMICOLON;
-      break;
-
-   case '{':
-      out->token = SL_PP_LBRACE;
-      break;
-
-   case '}':
-      out->token = SL_PP_RBRACE;
-      break;
-
-   case '(':
-      out->token = SL_PP_LPAREN;
-      break;
-
-   case ')':
-      out->token = SL_PP_RPAREN;
-      break;
-
-   case '[':
-      out->token = SL_PP_LBRACKET;
-      break;
-
-   case ']':
-      out->token = SL_PP_RBRACKET;
-      break;
-
-   case '.':
-      {
-         int c2 = _pure_getc(context);
-
-         if (c2 == PURE_ERROR) {
-            return -1;
-         }
-         if (c2 >= '0' && c2 <= '9') {
-            _pure_ungetc(context, c2);
-            _pure_ungetc(context, c);
-            if (_tokenise_number(context, out)) {
-               return -1;
-            }
-         } else {
-            _pure_ungetc(context, c2);
-            out->token = SL_PP_DOT;
-         }
-      }
-      break;
-
-   case '+':
-      c = _pure_getc(context);
-      if (c == PURE_ERROR) {
-         return -1;
-      }
-      if (c == '+') {
-         out->token = SL_PP_INCREMENT;
-      } else if (c == '=') {
-         out->token = SL_PP_ADDASSIGN;
-      } else {
-         _pure_ungetc(context, c);
-         out->token = SL_PP_PLUS;
-      }
-      break;
-
-   case '-':
-      c = _pure_getc(context);
-      if (c == PURE_ERROR) {
-         return -1;
-      }
-      if (c == '-') {
-         out->token = SL_PP_DECREMENT;
-      } else if (c == '=') {
-         out->token = SL_PP_SUBASSIGN;
-      } else {
-         _pure_ungetc(context, c);
-         out->token = SL_PP_MINUS;
-      }
-      break;
-
-   case '~':
-      out->token = SL_PP_BITNOT;
-      break;
-
-   case '!':
-      c = _pure_getc(context);
-      if (c == PURE_ERROR) {
-         return -1;
-      }
-      if (c == '=') {
-         out->token = SL_PP_NOTEQUAL;
-      } else {
-         _pure_ungetc(context, c);
-         out->token = SL_PP_NOT;
-      }
-      break;
-
-   case '*':
-      c = _pure_getc(context);
-      if (c == PURE_ERROR) {
-         return -1;
-      }
-      if (c == '=') {
-         out->token = SL_PP_MULASSIGN;
-      } else {
-         _pure_ungetc(context, c);
-         out->token = SL_PP_STAR;
-      }
-      break;
-
-   case '/':
-      c = _pure_getc(context);
-      if (c == PURE_ERROR) {
-         return -1;
-      }
-      if (c == '=') {
-         out->token = SL_PP_DIVASSIGN;
-      } else {
-         _pure_ungetc(context, c);
-         out->token = SL_PP_SLASH;
-      }
-      break;
-
-   case '%':
-      c = _pure_getc(context);
-      if (c == PURE_ERROR) {
-         return -1;
-      }
-      if (c == '=') {
-         out->token = SL_PP_MODASSIGN;
-      } else {
-         _pure_ungetc(context, c);
-         out->token = SL_PP_MODULO;
-      }
-      break;
-
-   case '<':
-      c = _pure_getc(context);
-      if (c == PURE_ERROR) {
-         return -1;
-      }
-      if (c == '<') {
-         c = _pure_getc(context);
-         if (c == PURE_ERROR) {
-            return -1;
-         }
-         if (c == '=') {
-            out->token = SL_PP_LSHIFTASSIGN;
-         } else {
-            _pure_ungetc(context, c);
-            out->token = SL_PP_LSHIFT;
-         }
-      } else if (c == '=') {
-         out->token = SL_PP_LESSEQUAL;
-      } else {
-         _pure_ungetc(context, c);
-         out->token = SL_PP_LESS;
-      }
-      break;
-
-   case '>':
-      c = _pure_getc(context);
-      if (c == PURE_ERROR) {
-         return -1;
-      }
-      if (c == '>') {
-         c = _pure_getc(context);
-         if (c == PURE_ERROR) {
-            return -1;
-         }
-         if (c == '=') {
-            out->token = SL_PP_RSHIFTASSIGN;
-         } else {
-            _pure_ungetc(context, c);
-            out->token = SL_PP_RSHIFT;
-         }
-      } else if (c == '=') {
-         out->token = SL_PP_GREATEREQUAL;
-      } else {
-         _pure_ungetc(context, c);
-         out->token = SL_PP_GREATER;
-      }
-      break;
-
-   case '=':
-      c = _pure_getc(context);
-      if (c == PURE_ERROR) {
-         return -1;
-      }
-      if (c == '=') {
-         out->token = SL_PP_EQUAL;
-      } else {
-         _pure_ungetc(context, c);
-         out->token = SL_PP_ASSIGN;
-      }
-      break;
-
-   case '&':
-      c = _pure_getc(context);
-      if (c == PURE_ERROR) {
-         return -1;
-      }
-      if (c == '&') {
-         out->token = SL_PP_AND;
-      } else if (c == '=') {
-         out->token = SL_PP_BITANDASSIGN;
-      } else {
-         _pure_ungetc(context, c);
-         out->token = SL_PP_BITAND;
-      }
-      break;
-
-   case '^':
-      c = _pure_getc(context);
-      if (c == PURE_ERROR) {
-         return -1;
-      }
-      if (c == '^') {
-         out->token = SL_PP_XOR;
-      } else if (c == '=') {
-         out->token = SL_PP_BITXORASSIGN;
-      } else {
-         _pure_ungetc(context, c);
-         out->token = SL_PP_BITXOR;
-      }
-      break;
-
-   case '|':
-      c = _pure_getc(context);
-      if (c == PURE_ERROR) {
-         return -1;
-      }
-      if (c == '|') {
-         out->token = SL_PP_OR;
-      } else if (c == '=') {
-         out->token = SL_PP_BITORASSIGN;
-      } else {
-         _pure_ungetc(context, c);
-         out->token = SL_PP_BITOR;
-      }
-      break;
-
-   case '?':
-      out->token = SL_PP_QUESTION;
-      break;
-
-   case ':':
-      out->token = SL_PP_COLON;
-      break;
-
-   case '\0':
-      out->token = SL_PP_EOF;
-      break;
-
-   case PURE_ERROR:
-      return -1;
-
-   default:
-      if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_') {
-         _pure_ungetc(context, c);
-         if (_tokenise_identifier(context, out)) {
-            return -1;
-         }
-      } else if (c >= '0' && c <= '9') {
-         _pure_ungetc(context, c);
-         if (_tokenise_number(context, out)) {
-            return -1;
-         }
-      } else {
-         out->data.other = c;
-         out->token = SL_PP_OTHER;
-      }
-   }
-
-   return 0;
-}
-
-
-int
-sl_pp_tokenise(struct sl_pp_context *context,
-               struct sl_pp_token_info **output)
-{
-   struct sl_pp_token_info *out = NULL;
-   unsigned int out_len = 0;
-   unsigned int out_max = 0;
-
-   for (;;) {
-      struct sl_pp_token_info info;
-
-      if (sl_pp_token_buffer_get(&context->tokens, &info)) {
-         free(out);
-         return -1;
-      }
-
-      if (out_len >= out_max) {
-         unsigned int new_max = out_max;
-
-         if (new_max < 0x100) {
-            new_max = 0x100;
-         } else if (new_max < 0x10000) {
-            new_max *= 2;
-         } else {
-            new_max += 0x10000;
-         }
-
-         out = realloc(out, new_max * sizeof(struct sl_pp_token_info));
-         if (!out) {
-            strcpy(context->error_msg, "out of memory");
-            return -1;
-         }
-         out_max = new_max;
-      }
-
-      out[out_len++] = info;
-
-      if (info.token == SL_PP_EOF) {
-         break;
-      }
-   }
-
-   *output = out;
-   return 0;
-}
diff --git a/src/glsl/pp/sl_pp_token.h b/src/glsl/pp/sl_pp_token.h
deleted file mode 100644 (file)
index a12b193..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#ifndef SL_PP_TOKEN_H
-#define SL_PP_TOKEN_H
-
-
-struct sl_pp_context;
-
-enum sl_pp_token {
-   SL_PP_WHITESPACE,
-   SL_PP_NEWLINE,
-   SL_PP_HASH,             /* #   */
-
-   SL_PP_COMMA,            /* ,   */
-   SL_PP_SEMICOLON,        /* ;   */
-   SL_PP_LBRACE,           /* {   */
-   SL_PP_RBRACE,           /* }   */
-   SL_PP_LPAREN,           /* (   */
-   SL_PP_RPAREN,           /* )   */
-   SL_PP_LBRACKET,         /* [   */
-   SL_PP_RBRACKET,         /* ]   */
-   SL_PP_DOT,              /* .   */
-   SL_PP_INCREMENT,        /* ++  */
-   SL_PP_ADDASSIGN,        /* +=  */
-   SL_PP_PLUS,             /* +   */
-   SL_PP_DECREMENT,        /* --  */
-   SL_PP_SUBASSIGN,        /* -=  */
-   SL_PP_MINUS,            /* -   */
-   SL_PP_BITNOT,           /* ~   */
-   SL_PP_NOTEQUAL,         /* !=  */
-   SL_PP_NOT,              /* !   */
-   SL_PP_MULASSIGN,        /* *=  */
-   SL_PP_STAR,             /* *   */
-   SL_PP_DIVASSIGN,        /* /=  */
-   SL_PP_SLASH,            /* /   */
-   SL_PP_MODASSIGN,        /* %=  */
-   SL_PP_MODULO,           /* %   */
-   SL_PP_LSHIFTASSIGN,     /* <<= */
-   SL_PP_LSHIFT,           /* <<  */
-   SL_PP_LESSEQUAL,        /* <=  */
-   SL_PP_LESS,             /* <   */
-   SL_PP_RSHIFTASSIGN,     /* >>= */
-   SL_PP_RSHIFT,           /* >>  */
-   SL_PP_GREATEREQUAL,     /* >=  */
-   SL_PP_GREATER,          /* >   */
-   SL_PP_EQUAL,            /* ==  */
-   SL_PP_ASSIGN,           /* =   */
-   SL_PP_AND,              /* &&  */
-   SL_PP_BITANDASSIGN,     /* &=  */
-   SL_PP_BITAND,           /* &   */
-   SL_PP_XOR,              /* ^^  */
-   SL_PP_BITXORASSIGN,     /* ^=  */
-   SL_PP_BITXOR,           /* ^   */
-   SL_PP_OR,               /* ||  */
-   SL_PP_BITORASSIGN,      /* |=  */
-   SL_PP_BITOR,            /* |   */
-   SL_PP_QUESTION,         /* ?   */
-   SL_PP_COLON,            /* :   */
-
-   SL_PP_IDENTIFIER,
-
-   SL_PP_UINT,
-   SL_PP_FLOAT,
-
-   SL_PP_OTHER,
-
-   SL_PP_PRAGMA_OPTIMIZE,
-   SL_PP_PRAGMA_DEBUG,
-
-   SL_PP_EXTENSION_REQUIRE,
-   SL_PP_EXTENSION_ENABLE,
-   SL_PP_EXTENSION_WARN,
-   SL_PP_EXTENSION_DISABLE,
-
-   SL_PP_LINE,
-
-   SL_PP_EOF
-};
-
-union sl_pp_token_data {
-   int identifier;
-   int _uint;
-   int _float;
-   char other;
-   int pragma;
-   int extension;
-   struct {
-      unsigned int lineno: 24;
-      unsigned int fileno: 8;
-   } line;
-};
-
-struct sl_pp_token_info {
-   enum sl_pp_token token;
-   union sl_pp_token_data data;
-};
-
-struct sl_pp_purify_options;
-
-int
-sl_pp_token_get(struct sl_pp_context *context,
-                struct sl_pp_token_info *out);
-
-int
-sl_pp_tokenise(struct sl_pp_context *context,
-               struct sl_pp_token_info **output);
-
-#endif /* SL_PP_TOKEN_H */
diff --git a/src/glsl/pp/sl_pp_token_util.c b/src/glsl/pp/sl_pp_token_util.c
deleted file mode 100644 (file)
index 43be496..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <assert.h>
-#include <stdlib.h>
-#include "sl_pp_token_util.h"
-#include "sl_pp_token.h"
-
-
-int
-sl_pp_token_buffer_init(struct sl_pp_token_buffer *buffer,
-                        struct sl_pp_context *context)
-{
-   buffer->context = context;
-   buffer->size = 0;
-   buffer->capacity = 64;
-   buffer->tokens = malloc(buffer->capacity * sizeof(struct sl_pp_token_info));
-   if (!buffer->tokens) {
-      return -1;
-   }
-   return 0;
-}
-
-void
-sl_pp_token_buffer_destroy(struct sl_pp_token_buffer *buffer)
-{
-   free(buffer->tokens);
-}
-
-int
-sl_pp_token_buffer_get(struct sl_pp_token_buffer *buffer,
-                       struct sl_pp_token_info *out)
-{
-   /* Pop from stack first if not empty. */
-   if (buffer->size) {
-      *out = buffer->tokens[--buffer->size];
-      return 0;
-   }
-
-   assert(buffer->context);
-   return sl_pp_token_get(buffer->context, out);
-}
-
-void
-sl_pp_token_buffer_unget(struct sl_pp_token_buffer *buffer,
-                         const struct sl_pp_token_info *in)
-{
-   /* Resize if needed. */
-   if (buffer->size == buffer->capacity) {
-      buffer->capacity += 64;
-      buffer->tokens = realloc(buffer->tokens,
-                               buffer->capacity * sizeof(struct sl_pp_token_info));
-      assert(buffer->tokens);
-   }
-
-   /* Push token on stack. */
-   buffer->tokens[buffer->size++] = *in;
-}
-
-int
-sl_pp_token_buffer_skip_white(struct sl_pp_token_buffer *buffer,
-                              struct sl_pp_token_info *out)
-{
-   if (sl_pp_token_buffer_get(buffer, out)) {
-      return -1;
-   }
-
-   while (out->token == SL_PP_WHITESPACE) {
-      if (sl_pp_token_buffer_get(buffer, out)) {
-         return -1;
-      }
-   }
-
-   return 0;
-}
-
-
-
-int
-sl_pp_token_peek_init(struct sl_pp_token_peek *peek,
-                      struct sl_pp_token_buffer *buffer)
-{
-   peek->buffer = buffer;
-   peek->size = 0;
-   peek->capacity = 64;
-   peek->tokens = malloc(peek->capacity * sizeof(struct sl_pp_token_info));
-   if (!peek->tokens) {
-      return -1;
-   }
-   return 0;
-}
-
-void
-sl_pp_token_peek_destroy(struct sl_pp_token_peek *peek)
-{
-   /* Abort. */
-   while (peek->size) {
-      sl_pp_token_buffer_unget(peek->buffer, &peek->tokens[--peek->size]);
-   }
-   free(peek->tokens);
-}
-
-int
-sl_pp_token_peek_get(struct sl_pp_token_peek *peek,
-                     struct sl_pp_token_info *out)
-{
-   /* Get token from buffer. */
-   if (sl_pp_token_buffer_get(peek->buffer, out)) {
-      return -1;
-   }
-
-   /* Save it. */
-   if (peek->size == peek->capacity) {
-      peek->capacity += 64;
-      peek->tokens = realloc(peek->tokens,
-                             peek->capacity * sizeof(struct sl_pp_token_info));
-      assert(peek->tokens);
-   }
-   peek->tokens[peek->size++] = *out;
-   return 0;
-}
-
-void
-sl_pp_token_peek_commit(struct sl_pp_token_peek *peek)
-{
-   peek->size = 0;
-}
-
-int
-sl_pp_token_peek_to_buffer(const struct sl_pp_token_peek *peek,
-                           struct sl_pp_token_buffer *buffer)
-{
-   unsigned int i;
-
-   if (sl_pp_token_buffer_init(buffer, NULL)) {
-      return -1;
-   }
-   for (i = peek->size; i > 0; i--) {
-      sl_pp_token_buffer_unget(buffer, &peek->tokens[i - 1]);
-   }
-   return 0;
-}
-
-int
-sl_pp_token_peek_skip_white(struct sl_pp_token_peek *peek,
-                            struct sl_pp_token_info *out)
-{
-   if (sl_pp_token_peek_get(peek, out)) {
-      return -1;
-   }
-
-   while (out->token == SL_PP_WHITESPACE) {
-      if (sl_pp_token_peek_get(peek, out)) {
-         return -1;
-      }
-   }
-
-   return 0;
-}
diff --git a/src/glsl/pp/sl_pp_token_util.h b/src/glsl/pp/sl_pp_token_util.h
deleted file mode 100644 (file)
index 35d7210..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#ifndef SL_PP_TOKEN_UTIL_H
-#define SL_PP_TOKEN_UTIL_H
-
-struct sl_pp_context;
-
-/*
- * A token buffer allows one to get and unget a token
- * from a preprocessor context.
- */
-struct sl_pp_token_buffer {
-   struct sl_pp_context *context;
-   unsigned int size;
-   unsigned int capacity;
-   struct sl_pp_token_info *tokens;
-};
-
-int
-sl_pp_token_buffer_init(struct sl_pp_token_buffer *buffer,
-                        struct sl_pp_context *context);
-
-void
-sl_pp_token_buffer_destroy(struct sl_pp_token_buffer *buffer);
-
-int
-sl_pp_token_buffer_get(struct sl_pp_token_buffer *buffer,
-                       struct sl_pp_token_info *out);
-
-void
-sl_pp_token_buffer_unget(struct sl_pp_token_buffer *buffer,
-                         const struct sl_pp_token_info *in);
-
-int
-sl_pp_token_buffer_skip_white(struct sl_pp_token_buffer *buffer,
-                              struct sl_pp_token_info *out);
-
-
-/*
- * A token peek allows one to get a number of tokens from a buffer
- * and then either commit the operation or abort it,
- * effectively ungetting the peeked tokens.
- */
-struct sl_pp_token_peek {
-   struct sl_pp_token_buffer *buffer;
-   unsigned int size;
-   unsigned int capacity;
-   struct sl_pp_token_info *tokens;
-};
-
-int
-sl_pp_token_peek_init(struct sl_pp_token_peek *peek,
-                      struct sl_pp_token_buffer *buffer);
-
-void
-sl_pp_token_peek_destroy(struct sl_pp_token_peek *peek);
-
-int
-sl_pp_token_peek_get(struct sl_pp_token_peek *peek,
-                     struct sl_pp_token_info *out);
-
-void
-sl_pp_token_peek_commit(struct sl_pp_token_peek *peek);
-
-int
-sl_pp_token_peek_to_buffer(const struct sl_pp_token_peek *peek,
-                           struct sl_pp_token_buffer *buffer);
-
-int
-sl_pp_token_peek_skip_white(struct sl_pp_token_peek *peek,
-                            struct sl_pp_token_info *out);
-
-#endif /* SL_PP_TOKEN_UTIL_H */
diff --git a/src/glsl/pp/sl_pp_version.c b/src/glsl/pp/sl_pp_version.c
deleted file mode 100644 (file)
index 6735c05..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "sl_pp_public.h"
-#include "sl_pp_context.h"
-#include "sl_pp_token.h"
-
-
-int
-sl_pp_version(struct sl_pp_context *context,
-              unsigned int *version)
-{
-   struct sl_pp_token_peek peek;
-   unsigned int line = context->line;
-
-   /* Default values if `#version' is not present. */
-   *version = 110;
-
-   if (sl_pp_token_peek_init(&peek, &context->tokens)) {
-      return -1;
-   }
-
-   /* There can be multiple `#version' directives present.
-    * Accept the value of the last one.
-    */
-   for (;;) {
-      struct sl_pp_token_info input;
-      int found_hash = 0;
-      int found_version = 0;
-      int found_number = 0;
-      int found_end = 0;
-
-      /* Skip whitespace and newlines and seek for hash. */
-      while (!found_hash) {
-         if (sl_pp_token_peek_get(&peek, &input)) {
-            sl_pp_token_peek_destroy(&peek);
-            return -1;
-         }
-
-         switch (input.token) {
-         case SL_PP_NEWLINE:
-            line++;
-            break;
-
-         case SL_PP_WHITESPACE:
-            break;
-
-         case SL_PP_HASH:
-            found_hash = 1;
-            break;
-
-         default:
-            sl_pp_token_peek_destroy(&peek);
-            return 0;
-         }
-      }
-
-      /* Skip whitespace and seek for `version'. */
-      while (!found_version) {
-         if (sl_pp_token_peek_get(&peek, &input)) {
-            sl_pp_token_peek_destroy(&peek);
-            return -1;
-         }
-
-         switch (input.token) {
-         case SL_PP_WHITESPACE:
-            break;
-
-         case SL_PP_IDENTIFIER:
-            if (input.data.identifier != context->dict.version) {
-               sl_pp_token_peek_destroy(&peek);
-               return 0;
-            }
-            found_version = 1;
-            break;
-
-         default:
-            sl_pp_token_peek_destroy(&peek);
-            return 0;
-         }
-      }
-
-      sl_pp_token_peek_commit(&peek);
-
-      /* Skip whitespace and seek for version number. */
-      while (!found_number) {
-         if (sl_pp_token_buffer_get(&context->tokens, &input)) {
-            sl_pp_token_peek_destroy(&peek);
-            return -1;
-         }
-
-         switch (input.token) {
-         case SL_PP_WHITESPACE:
-            break;
-
-         case SL_PP_UINT:
-            *version = atoi(sl_pp_context_cstr(context, input.data._uint));
-            found_number = 1;
-            break;
-
-         default:
-            strcpy(context->error_msg, "expected version number after `#version'");
-            sl_pp_token_peek_destroy(&peek);
-            return -1;
-         }
-      }
-
-      /* Skip whitespace and seek for either newline or eof. */
-      while (!found_end) {
-         if (sl_pp_token_buffer_get(&context->tokens, &input)) {
-            sl_pp_token_peek_destroy(&peek);
-            return -1;
-         }
-
-         switch (input.token) {
-         case SL_PP_WHITESPACE:
-            break;
-
-         case SL_PP_NEWLINE:
-            line++;
-            /* pass thru */
-         case SL_PP_EOF:
-            context->line = line;
-            found_end = 1;
-            break;
-
-         default:
-            strcpy(context->error_msg, "expected end of line after version number");
-            sl_pp_token_peek_destroy(&peek);
-            return -1;
-         }
-      }
-   }
-
-   /* Should not get here. */
-}
diff --git a/src/glsl/program.h b/src/glsl/program.h
new file mode 100644 (file)
index 0000000..893169b
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "main/core.h"
+
+extern void
+link_shaders(GLcontext *ctx, struct gl_shader_program *prog);
diff --git a/src/glsl/s_expression.cpp b/src/glsl/s_expression.cpp
new file mode 100644 (file)
index 0000000..4458c48
--- /dev/null
@@ -0,0 +1,140 @@
+/* -*- c++ -*- */
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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 <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <assert.h>
+#include "s_expression.h"
+
+s_symbol::s_symbol(const char *tmp, size_t n)
+{
+   this->str = talloc_strndup (this, tmp, n);
+   assert(this->str != NULL);
+}
+
+s_list::s_list()
+{
+}
+
+unsigned
+s_list::length() const
+{
+   unsigned i = 0;
+   foreach_iter(exec_list_iterator, it, this->subexpressions) {
+      i++;
+   }
+   return i;
+}
+
+static s_expression *
+read_atom(void *ctx, const char *& src)
+{
+   s_expression *expr = NULL;
+
+   // Skip leading spaces.
+   src += strspn(src, " \v\t\r\n");
+
+   size_t n = strcspn(src, "( \v\t\r\n)");
+   if (n == 0)
+      return NULL; // no atom
+
+   // Check if the atom is a number.
+   char *float_end = NULL;
+   double f = strtod(src, &float_end);
+   if (float_end != src) {
+      char *int_end = NULL;
+      int i = strtol(src, &int_end, 10);
+      // If strtod matched more characters, it must have a decimal part
+      if (float_end > int_end)
+        expr = new(ctx) s_float(f);
+      else
+        expr = new(ctx) s_int(i);
+   } else {
+      // Not a number; return a symbol.
+      expr = new(ctx) s_symbol(src, n);
+   }
+
+   src += n;
+
+   return expr;
+}
+
+s_expression *
+s_expression::read_expression(void *ctx, const char *&src)
+{
+   assert(src != NULL);
+
+   s_expression *atom = read_atom(ctx, src);
+   if (atom != NULL)
+      return atom;
+
+   // Skip leading spaces.
+   src += strspn(src, " \v\t\r\n");
+   if (src[0] == '(') {
+      ++src;
+
+      s_list *list = new(ctx) s_list;
+      s_expression *expr;
+
+      while ((expr = read_expression(ctx, src)) != NULL) {
+        list->subexpressions.push_tail(expr);
+      }
+      src += strspn(src, " \v\t\r\n");
+      if (src[0] != ')') {
+        printf("Unclosed expression (check your parenthesis).\n");
+        return NULL;
+      }
+      ++src;
+      return list;
+   }
+   return NULL;
+}
+
+void s_int::print()
+{
+   printf("%d", this->val);
+}
+
+void s_float::print()
+{
+   printf("%f", this->val);
+}
+
+void s_symbol::print()
+{
+   printf("%s", this->str);
+}
+
+void s_list::print()
+{
+   printf("(");
+   foreach_iter(exec_list_iterator, it, this->subexpressions) {
+      s_expression *expr = (s_expression*) it.get();
+      expr->print();
+      printf(" ");
+   }
+   printf(")");
+}
+
diff --git a/src/glsl/s_expression.h b/src/glsl/s_expression.h
new file mode 100644 (file)
index 0000000..aa22475
--- /dev/null
@@ -0,0 +1,142 @@
+/* -*- c++ -*- */
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+#pragma once
+#ifndef S_EXPRESSION_H
+#define S_EXPRESSION_H
+
+#include "list.h"
+
+#define SX_AS_(t,x) ((x) && ((s_expression*) x)->is_##t()) ? ((s_##t*) (x)) \
+                                                           : NULL
+#define SX_AS_LIST(x)   SX_AS_(list, x)
+#define SX_AS_SYMBOL(x) SX_AS_(symbol, x)
+#define SX_AS_NUMBER(x) SX_AS_(number, x)
+#define SX_AS_INT(x)    SX_AS_(int, x)
+
+/* For our purposes, S-Expressions are:
+ * - <int>
+ * - <float>
+ * - symbol
+ * - (expr1 expr2 ... exprN)     where exprN is an S-Expression
+ *
+ * Unlike LISP/Scheme, we do not support (foo . bar) pairs.
+ */
+class s_expression : public exec_node
+{
+public:
+   /**
+    * Read an S-Expression from the given string.
+    * Advances the supplied pointer to just after the expression read.
+    *
+    * Any allocation will be performed with 'ctx' as the talloc owner.
+    */
+   static s_expression *read_expression(void *ctx, const char *&src);
+
+   /**
+    * Print out an S-Expression.  Useful for debugging.
+    */
+   virtual void print() = 0;
+
+   virtual bool is_list()   const { return false; }
+   virtual bool is_symbol() const { return false; }
+   virtual bool is_number() const { return false; }
+   virtual bool is_int()    const { return false; }
+
+protected:
+   s_expression() { }
+};
+
+/* Atoms */
+
+class s_number : public s_expression
+{
+public:
+   bool is_number() const { return true; }
+
+   virtual float fvalue() = 0;
+
+protected:
+   s_number() { }
+};
+
+class s_int : public s_number
+{
+public:
+   s_int(int x) : val(x) { }
+
+   bool is_int() const { return true; }
+
+   float fvalue() { return float(this->val); }
+   int value() { return this->val; }
+
+   void print();
+
+private:
+   int val;
+};
+
+class s_float : public s_number
+{
+public:
+   s_float(float x) : val(x) { }
+
+   float fvalue() { return this->val; }
+
+   void print();
+
+private:
+   float val;
+};
+
+class s_symbol : public s_expression
+{
+public:
+   s_symbol(const char *, size_t);
+
+   bool is_symbol() const { return true; }
+
+   const char *value() { return this->str; }
+
+   void print();
+
+private:
+   char *str;
+};
+
+/* Lists of expressions: (expr1 ... exprN) */
+class s_list : public s_expression
+{
+public:
+   s_list();
+
+   virtual bool is_list() const { return true; }
+   unsigned length() const;
+
+   void print();
+
+   exec_list subexpressions;
+};
+
+#endif /* S_EXPRESSION_H */
diff --git a/src/glsl/tests/array-01.glsl b/src/glsl/tests/array-01.glsl
new file mode 100644 (file)
index 0000000..d14135f
--- /dev/null
@@ -0,0 +1,3 @@
+#version 120
+/* FAIL - array size type must be int */
+uniform vec4 [3.2] a;
diff --git a/src/glsl/tests/array-02.glsl b/src/glsl/tests/array-02.glsl
new file mode 100644 (file)
index 0000000..d743617
--- /dev/null
@@ -0,0 +1,3 @@
+#version 120
+/* FAIL - array size type must be scalar */
+uniform vec4 [ivec4(3)] a;
diff --git a/src/glsl/tests/array-03.glsl b/src/glsl/tests/array-03.glsl
new file mode 100644 (file)
index 0000000..0026913
--- /dev/null
@@ -0,0 +1,3 @@
+#version 120
+/* PASS */
+uniform vec4 [3] a;
diff --git a/src/glsl/tests/array-04.glsl b/src/glsl/tests/array-04.glsl
new file mode 100644 (file)
index 0000000..70f434d
--- /dev/null
@@ -0,0 +1,2 @@
+/* FAIL - array size type must be int */
+uniform vec4 a[3.2];
diff --git a/src/glsl/tests/array-05.glsl b/src/glsl/tests/array-05.glsl
new file mode 100644 (file)
index 0000000..1687040
--- /dev/null
@@ -0,0 +1,2 @@
+/* FAIL - array size type must be scalar */
+uniform vec4 a[ivec4(3)];
diff --git a/src/glsl/tests/array-06.glsl b/src/glsl/tests/array-06.glsl
new file mode 100644 (file)
index 0000000..46b4379
--- /dev/null
@@ -0,0 +1,2 @@
+/* PASS */
+uniform vec4 a[3];
diff --git a/src/glsl/tests/array-07.glsl b/src/glsl/tests/array-07.glsl
new file mode 100644 (file)
index 0000000..161ffbf
--- /dev/null
@@ -0,0 +1,2 @@
+/* FAIL - array size must be > 0 */
+uniform vec4 a[0];
diff --git a/src/glsl/tests/array-08.glsl b/src/glsl/tests/array-08.glsl
new file mode 100644 (file)
index 0000000..4bf0c6b
--- /dev/null
@@ -0,0 +1,2 @@
+/* FAIL - array size must be > 0 */
+uniform vec4 a[-1];
diff --git a/src/glsl/tests/array-09.glsl b/src/glsl/tests/array-09.glsl
new file mode 100644 (file)
index 0000000..cad6d0e
--- /dev/null
@@ -0,0 +1,9 @@
+#version 120
+/* PASS */
+
+void main()
+{
+  vec4 a[2] = vec4 [2] (vec4(1.0), vec4(2.0));
+
+  gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/array-10.glsl b/src/glsl/tests/array-10.glsl
new file mode 100644 (file)
index 0000000..019aa21
--- /dev/null
@@ -0,0 +1,11 @@
+/* FAIL - array constructors forbidden in GLSL 1.10
+ *
+ * This can also generate an error because the 'vec4[]' style syntax is
+ * illegal in GLSL 1.10.
+ */
+void main()
+{
+  vec4 a[2] = vec4 [2] (vec4(1.0), vec4(2.0));
+
+  gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/array-11.glsl b/src/glsl/tests/array-11.glsl
new file mode 100644 (file)
index 0000000..51d94e9
--- /dev/null
@@ -0,0 +1,9 @@
+#version 120
+/* PASS */
+
+void main()
+{
+  vec4 a[] = vec4 [] (vec4(1.0), vec4(2.0));
+
+  gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/array-12.glsl b/src/glsl/tests/array-12.glsl
new file mode 100644 (file)
index 0000000..7fc9579
--- /dev/null
@@ -0,0 +1,11 @@
+#version 120
+/* FAIL - array must have an implicit or explicit size */
+
+void main()
+{
+  vec4 a[];
+
+  a = vec4 [2] (vec4(1.0), vec4(2.0));
+
+  gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/array-13.glsl b/src/glsl/tests/array-13.glsl
new file mode 100644 (file)
index 0000000..cc7e29a
--- /dev/null
@@ -0,0 +1,11 @@
+#version 120
+/* PASS */
+
+void main()
+{
+  vec4 a[2];
+
+  a = vec4 [] (vec4(1.0), vec4(2.0));
+
+  gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/attribute-01.glsl b/src/glsl/tests/attribute-01.glsl
new file mode 100644 (file)
index 0000000..18e9e44
--- /dev/null
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type int */
+attribute int i;
+
+void main()
+{
+  gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-02.glsl b/src/glsl/tests/attribute-02.glsl
new file mode 100644 (file)
index 0000000..6b6df74
--- /dev/null
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type ivec2 */
+attribute ivec2 i;
+
+void main()
+{
+  gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-03.glsl b/src/glsl/tests/attribute-03.glsl
new file mode 100644 (file)
index 0000000..870de9e
--- /dev/null
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type ivec3 */
+attribute ivec3 i;
+
+void main()
+{
+  gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-04.glsl b/src/glsl/tests/attribute-04.glsl
new file mode 100644 (file)
index 0000000..14af2fc
--- /dev/null
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type ivec4 */
+attribute ivec4 i;
+
+void main()
+{
+  gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-05.glsl b/src/glsl/tests/attribute-05.glsl
new file mode 100644 (file)
index 0000000..18822c7
--- /dev/null
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type bool */
+attribute bool i;
+
+void main()
+{
+  gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-06.glsl b/src/glsl/tests/attribute-06.glsl
new file mode 100644 (file)
index 0000000..f18027b
--- /dev/null
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type bvec2 */
+attribute bvec2 i;
+
+void main()
+{
+  gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-07.glsl b/src/glsl/tests/attribute-07.glsl
new file mode 100644 (file)
index 0000000..0af13ba
--- /dev/null
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type bvec3 */
+attribute bvec3 i;
+
+void main()
+{
+  gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-08.glsl b/src/glsl/tests/attribute-08.glsl
new file mode 100644 (file)
index 0000000..b069c04
--- /dev/null
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have type bvec4 */
+attribute bvec4 i;
+
+void main()
+{
+  gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-09.glsl b/src/glsl/tests/attribute-09.glsl
new file mode 100644 (file)
index 0000000..6a60724
--- /dev/null
@@ -0,0 +1,7 @@
+/* FAIL - attribute cannot have array type in GLSL 1.10 */
+attribute vec4 i[10];
+
+void main()
+{
+  gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-10.glsl b/src/glsl/tests/attribute-10.glsl
new file mode 100644 (file)
index 0000000..6f5ef63
--- /dev/null
@@ -0,0 +1,8 @@
+#version 120
+/* FAIL - attribute cannot have array type in GLSL 1.20 */
+attribute vec4 i[10];
+
+void main()
+{
+  gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/attribute-11.glsl b/src/glsl/tests/attribute-11.glsl
new file mode 100644 (file)
index 0000000..47cb5a0
--- /dev/null
@@ -0,0 +1,8 @@
+#version 130
+/* FAIL - attribute cannot have array type in GLSL 1.30 */
+attribute vec4 i[10];
+
+void main()
+{
+  gl_Position = vec4(1.0);
+}
diff --git a/src/glsl/tests/condition-01.glsl b/src/glsl/tests/condition-01.glsl
new file mode 100644 (file)
index 0000000..d89c313
--- /dev/null
@@ -0,0 +1,8 @@
+/* FAIL - :? condition is not bool scalar */
+
+uniform bvec4 a;
+
+void main()
+{
+  gl_Position = (a) ? vec4(1.0, 0.0, 0.0, 1.0) : vec4(0.0, 1.0, 0.0, 1.0);
+}
diff --git a/src/glsl/tests/condition-02.glsl b/src/glsl/tests/condition-02.glsl
new file mode 100644 (file)
index 0000000..cbd0e18
--- /dev/null
@@ -0,0 +1,8 @@
+/* FAIL - :? condition is not bool scalar */
+
+uniform float a;
+
+void main()
+{
+  gl_Position = (a) ? vec4(1.0, 0.0, 0.0, 1.0) : vec4(0.0, 1.0, 0.0, 1.0);
+}
diff --git a/src/glsl/tests/condition-03.glsl b/src/glsl/tests/condition-03.glsl
new file mode 100644 (file)
index 0000000..9af5d7a
--- /dev/null
@@ -0,0 +1,8 @@
+/* PASS */
+
+uniform bool a;
+
+void main()
+{
+  gl_Position = (a) ? vec4(1.0, 0.0, 0.0, 1.0) : vec4(0.0, 1.0, 0.0, 1.0);
+}
diff --git a/src/glsl/tests/condition-04.glsl b/src/glsl/tests/condition-04.glsl
new file mode 100644 (file)
index 0000000..f440b7e
--- /dev/null
@@ -0,0 +1,8 @@
+/* FAIL - type of second two operands must match */
+
+uniform bool a;
+
+void main()
+{
+  gl_Position = (a) ? vec4(1.0, 0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
+}
diff --git a/src/glsl/tests/condition-05.glsl b/src/glsl/tests/condition-05.glsl
new file mode 100644 (file)
index 0000000..3dff18f
--- /dev/null
@@ -0,0 +1,13 @@
+#version 120
+/* PASS */
+
+uniform bool a;
+uniform int b;
+
+void main()
+{
+  float x;
+
+  x = (a) ? 2.0 : b;
+  gl_Position = vec4(x);
+}
diff --git a/src/glsl/tests/constructor-01.glsl b/src/glsl/tests/constructor-01.glsl
new file mode 100644 (file)
index 0000000..fdfaf89
--- /dev/null
@@ -0,0 +1,6 @@
+/* PASS */
+
+void main()
+{
+  gl_Position = vec4(1.0, 1.0, 1.0, 0.0);;
+}
diff --git a/src/glsl/tests/constructor-02.glsl b/src/glsl/tests/constructor-02.glsl
new file mode 100644 (file)
index 0000000..47acbe9
--- /dev/null
@@ -0,0 +1,7 @@
+/* FAIL - cannot construct samplers */
+void main()
+{
+  int i;
+
+  i = sampler2D(0);
+}
diff --git a/src/glsl/tests/constructor-03.glsl b/src/glsl/tests/constructor-03.glsl
new file mode 100644 (file)
index 0000000..07ec225
--- /dev/null
@@ -0,0 +1,12 @@
+/* FAIL - cannot construct a matrix from a matrix in GLSL 1.10 */
+
+uniform mat2 a;
+
+void main()
+{
+  mat2 b;
+
+  b = mat2(a);
+
+  gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/constructor-04.glsl b/src/glsl/tests/constructor-04.glsl
new file mode 100644 (file)
index 0000000..19d5e01
--- /dev/null
@@ -0,0 +1,14 @@
+#version 120
+/* FAIL - matrix must be only parameter to matrix constructor */
+
+uniform mat2 a;
+uniform float x;
+
+void main()
+{
+  mat2 b;
+
+  b = mat2(a, x);
+
+  gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/constructor-05.glsl b/src/glsl/tests/constructor-05.glsl
new file mode 100644 (file)
index 0000000..9c74f75
--- /dev/null
@@ -0,0 +1,13 @@
+/* FAIL - too few components supplied to constructor */
+
+uniform vec2 a;
+uniform float x;
+
+void main()
+{
+  mat2 b;
+
+  b = mat2(a, x);
+
+  gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/constructor-06.glsl b/src/glsl/tests/constructor-06.glsl
new file mode 100644 (file)
index 0000000..d77a5f9
--- /dev/null
@@ -0,0 +1,13 @@
+#version 120
+/* PASS */
+
+uniform mat2 a;
+
+void main()
+{
+  mat2 b;
+
+  b = mat2(a);
+
+  gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/constructor-07.glsl b/src/glsl/tests/constructor-07.glsl
new file mode 100644 (file)
index 0000000..9232250
--- /dev/null
@@ -0,0 +1,13 @@
+/* PASS */
+
+uniform ivec2 a;
+uniform ivec2 b;
+
+void main()
+{
+  mat2 c;
+
+  c = mat2(a, b);
+
+  gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/constructor-08.glsl b/src/glsl/tests/constructor-08.glsl
new file mode 100644 (file)
index 0000000..27153f0
--- /dev/null
@@ -0,0 +1,13 @@
+/* PASS */
+
+uniform float a;
+uniform float b;
+
+void main()
+{
+  ivec2 c;
+
+  c = ivec2(a, b);
+
+  gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/constructor-09.glsl b/src/glsl/tests/constructor-09.glsl
new file mode 100644 (file)
index 0000000..1985699
--- /dev/null
@@ -0,0 +1,26 @@
+/* PASS */
+
+uniform int a;
+uniform float b;
+uniform bool c;
+
+void main()
+{
+  float x;
+  int y;
+  bool z;
+
+  x = float(a);
+  x = float(b);
+  x = float(c);
+
+  y = int(a);
+  y = int(b);
+  y = int(c);
+
+  z = bool(a);
+  z = bool(b);
+  z = bool(c);
+
+  gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/function-01.glsl b/src/glsl/tests/function-01.glsl
new file mode 100644 (file)
index 0000000..0eaa239
--- /dev/null
@@ -0,0 +1,16 @@
+/* FAIL - no function named 'foo' exists */
+
+vec4 bar(float x, float y, float z, float w)
+{
+  vec4 v;
+  v.x = x;
+  v.y = y;
+  v.z = z;
+  v.w = w;
+  return v;
+}
+
+void main()
+{
+  gl_Position = foo(1.0, 1.0, 1.0, 0.0);
+}
diff --git a/src/glsl/tests/function-02.glsl b/src/glsl/tests/function-02.glsl
new file mode 100644 (file)
index 0000000..941fcc1
--- /dev/null
@@ -0,0 +1,16 @@
+/* FAIL - no version of 'foo' matches the call to 'foo' */
+
+vec4 foo(float x, float y, float z, float w)
+{
+  vec4 v;
+  v.x = x;
+  v.y = y;
+  v.z = z;
+  v.w = w;
+  return v;
+}
+
+void main()
+{
+  gl_Position = foo(1.0, 1.0, 1.0);
+}
diff --git a/src/glsl/tests/function-03.glsl b/src/glsl/tests/function-03.glsl
new file mode 100644 (file)
index 0000000..b0da42f
--- /dev/null
@@ -0,0 +1,16 @@
+/* PASS */
+
+vec4 foo(in float x, in float y, float z, float w)
+{
+  vec4 v;
+  v.x = x;
+  v.y = y;
+  v.z = z;
+  v.w = w;
+  return v;
+}
+
+void main()
+{
+  gl_Position = foo(1.0, 1.0, 1.0, 0.0);
+}
diff --git a/src/glsl/tests/function-04.glsl b/src/glsl/tests/function-04.glsl
new file mode 100644 (file)
index 0000000..dfc0d2b
--- /dev/null
@@ -0,0 +1,15 @@
+/* FAIL - type mismatch in assignment */
+
+vec3 foo(float x, float y, float z)
+{
+  vec3 v;
+  v.x = x;
+  v.y = y;
+  v.z = z;
+  return v;
+}
+
+void main()
+{
+  gl_Position = foo(1.0, 1.0, 1.0);
+}
diff --git a/src/glsl/tests/function-05.glsl b/src/glsl/tests/function-05.glsl
new file mode 100644 (file)
index 0000000..43365bf
--- /dev/null
@@ -0,0 +1,26 @@
+/* PASS */
+
+vec4 foo(in float x, in float y, float z, float w)
+{
+  vec4 v;
+  v.x = x;
+  v.y = y;
+  v.z = z;
+  v.w = w;
+  return v;
+}
+
+vec4 foo(in float x)
+{
+   vec4 v;
+   v.x = x;
+   v.y = x;
+   v.z = x;
+   v.w = x;
+}
+
+void main()
+{
+  gl_Position = foo(1.0, 1.0, 1.0, 0.0);
+  gl_Position = foo(2.0);
+}
diff --git a/src/glsl/tests/if-01.glsl b/src/glsl/tests/if-01.glsl
new file mode 100644 (file)
index 0000000..ca9abd5
--- /dev/null
@@ -0,0 +1,11 @@
+/* FAIL - if-statement condition is not bool scalar */
+
+uniform bvec4 a;
+
+void main()
+{
+  if (a)
+    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
+  else
+    gl_Position = vec4(0.0, 1.0, 0.0, 1.0);
+}
diff --git a/src/glsl/tests/if-02.glsl b/src/glsl/tests/if-02.glsl
new file mode 100644 (file)
index 0000000..7adccea
--- /dev/null
@@ -0,0 +1,11 @@
+/* FAIL - if-statement condition is not bool scalar */
+
+uniform float a;
+
+void main()
+{
+  if (a)
+    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
+  else
+    gl_Position = vec4(0.0, 1.0, 0.0, 1.0);
+}
diff --git a/src/glsl/tests/if-03.glsl b/src/glsl/tests/if-03.glsl
new file mode 100644 (file)
index 0000000..179618c
--- /dev/null
@@ -0,0 +1,11 @@
+/* PASS */
+
+uniform bool a;
+
+void main()
+{
+  if (a)
+    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
+  else
+    gl_Position = vec4(0.0, 1.0, 0.0, 1.0);
+}
diff --git a/src/glsl/tests/if-04.glsl b/src/glsl/tests/if-04.glsl
new file mode 100644 (file)
index 0000000..7b711fb
--- /dev/null
@@ -0,0 +1,11 @@
+/* PASS */
+
+uniform bvec4 a;
+
+void main()
+{
+  if (a.x)
+    gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
+  else
+    gl_Position = vec4(0.0, 1.0, 0.0, 1.0);
+}
diff --git a/src/glsl/tests/matrix-01.glsl b/src/glsl/tests/matrix-01.glsl
new file mode 100644 (file)
index 0000000..f46416c
--- /dev/null
@@ -0,0 +1,6 @@
+/* FAIL - non-square matrices are not available in GLSL 1.10 */
+
+void main()
+{
+    mat2x3 m;
+}
diff --git a/src/glsl/tests/matrix-02.glsl b/src/glsl/tests/matrix-02.glsl
new file mode 100644 (file)
index 0000000..0630722
--- /dev/null
@@ -0,0 +1,6 @@
+/* FAIL - non-square matrices are not available in GLSL 1.10 */
+
+void main()
+{
+    mat2x4 m;
+}
diff --git a/src/glsl/tests/matrix-03.glsl b/src/glsl/tests/matrix-03.glsl
new file mode 100644 (file)
index 0000000..925dc80
--- /dev/null
@@ -0,0 +1,6 @@
+/* FAIL - non-square matrices are not available in GLSL 1.10 */
+
+void main()
+{
+    mat3x2 m;
+}
diff --git a/src/glsl/tests/matrix-04.glsl b/src/glsl/tests/matrix-04.glsl
new file mode 100644 (file)
index 0000000..5275619
--- /dev/null
@@ -0,0 +1,6 @@
+/* FAIL - non-square matrices are not available in GLSL 1.10 */
+
+void main()
+{
+    mat3x4 m;
+}
diff --git a/src/glsl/tests/matrix-05.glsl b/src/glsl/tests/matrix-05.glsl
new file mode 100644 (file)
index 0000000..74e1fd2
--- /dev/null
@@ -0,0 +1,6 @@
+/* FAIL - non-square matrices are not available in GLSL 1.10 */
+
+void main()
+{
+    mat4x2 m;
+}
diff --git a/src/glsl/tests/matrix-06.glsl b/src/glsl/tests/matrix-06.glsl
new file mode 100644 (file)
index 0000000..0a512b8
--- /dev/null
@@ -0,0 +1,6 @@
+/* FAIL - non-square matrices are not available in GLSL 1.10 */
+
+void main()
+{
+    mat4x3 m;
+}
diff --git a/src/glsl/tests/matrix-07.glsl b/src/glsl/tests/matrix-07.glsl
new file mode 100644 (file)
index 0000000..0b59aa6
--- /dev/null
@@ -0,0 +1,27 @@
+/* PASS */
+
+uniform mat2 a;
+uniform mat2 b;
+uniform mat2 c;
+uniform mat2 d;
+uniform mat3 e;
+uniform mat3 f;
+uniform mat3 g;
+uniform mat3 h;
+uniform mat4 i;
+uniform mat4 j;
+uniform mat4 k;
+uniform mat4 l;
+
+void main()
+{
+    mat2 x;
+    mat3 y;
+    mat4 z;
+
+    x = a * b + c / d;
+    y = e * f + g / h;
+    z = i * j + k / l;
+
+    gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/matrix-08.glsl b/src/glsl/tests/matrix-08.glsl
new file mode 100644 (file)
index 0000000..38138d2
--- /dev/null
@@ -0,0 +1,19 @@
+#version 120
+/* PASS */
+
+uniform mat2x3 a;
+uniform mat3x2 b;
+uniform mat3x3 c;
+uniform mat3x3 d;
+
+void main()
+{
+    mat3x3 x;
+
+    /* Multiplying a 2 column, 3 row matrix with a 3 column, 2 row matrix
+     * results in a 3 column, 3 row matrix.
+     */
+    x = (a * b) + c / d;
+
+    gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/matrix-09.glsl b/src/glsl/tests/matrix-09.glsl
new file mode 100644 (file)
index 0000000..18afbca
--- /dev/null
@@ -0,0 +1,11 @@
+/* FAIL - matrix-to-matrix constructors are not available in GLSL 1.10 */
+
+uniform mat3 a;
+
+void main()
+{
+    mat2 m;
+
+    m = mat2(a);
+    gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/matrix-10.glsl b/src/glsl/tests/matrix-10.glsl
new file mode 100644 (file)
index 0000000..20b5518
--- /dev/null
@@ -0,0 +1,12 @@
+#version 120
+/* PASS */
+
+uniform mat3 a;
+
+void main()
+{
+    mat2 m;
+
+    m = mat2(a);
+    gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/parameters-01.glsl b/src/glsl/tests/parameters-01.glsl
new file mode 100644 (file)
index 0000000..b485106
--- /dev/null
@@ -0,0 +1,11 @@
+/* FAIL: redefinition of a() */
+
+void a()
+{
+       ;       
+}
+
+void a()
+{
+       ;       
+}
diff --git a/src/glsl/tests/parameters-02.glsl b/src/glsl/tests/parameters-02.glsl
new file mode 100644 (file)
index 0000000..7ff5f59
--- /dev/null
@@ -0,0 +1,11 @@
+/* PASS */
+
+void a()
+{
+       ;       
+}
+
+void a(float x)
+{
+       ;       
+}
diff --git a/src/glsl/tests/parameters-03.glsl b/src/glsl/tests/parameters-03.glsl
new file mode 100644 (file)
index 0000000..7ec30f8
--- /dev/null
@@ -0,0 +1,9 @@
+/* FAIL - x is redeclared in the function body at the same scope as the
+ *        parameter
+ */
+void a(float x, float y)
+{
+       float x;
+
+       x = y;
+}
diff --git a/src/glsl/tests/qualifier-01.glsl b/src/glsl/tests/qualifier-01.glsl
new file mode 100644 (file)
index 0000000..54ec357
--- /dev/null
@@ -0,0 +1,3 @@
+#version 130
+/* FAIL - inout only allowed in parameter list */
+inout vec4 foo;
diff --git a/src/glsl/tests/qualifier-02.glsl b/src/glsl/tests/qualifier-02.glsl
new file mode 100644 (file)
index 0000000..b635d52
--- /dev/null
@@ -0,0 +1,2 @@
+/* FAIL - in only allowed in parameter list in GLSL 1.10 */
+in foo;
diff --git a/src/glsl/tests/qualifier-03.glsl b/src/glsl/tests/qualifier-03.glsl
new file mode 100644 (file)
index 0000000..7e44803
--- /dev/null
@@ -0,0 +1,2 @@
+/* FAIL - out only allowed in parameter list in GLSL 1.10 */
+out vec4 foo;
diff --git a/src/glsl/tests/qualifier-04.glsl b/src/glsl/tests/qualifier-04.glsl
new file mode 100644 (file)
index 0000000..d03cafc
--- /dev/null
@@ -0,0 +1,3 @@
+#version 130
+/* PASS */
+in vec4 foo;
diff --git a/src/glsl/tests/qualifier-05.glsl b/src/glsl/tests/qualifier-05.glsl
new file mode 100644 (file)
index 0000000..15281f3
--- /dev/null
@@ -0,0 +1,3 @@
+#version 130
+/* PASS */
+out vec4 foo;
diff --git a/src/glsl/tests/qualifier-06.glsl b/src/glsl/tests/qualifier-06.glsl
new file mode 100644 (file)
index 0000000..1907a08
--- /dev/null
@@ -0,0 +1,7 @@
+/* FAIL - in only allowed in parameter list in GLSL 1.10 */
+void main()
+{
+  in vec4 foo;
+
+  gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/qualifier-07.glsl b/src/glsl/tests/qualifier-07.glsl
new file mode 100644 (file)
index 0000000..12568a5
--- /dev/null
@@ -0,0 +1,7 @@
+/* FAIL - out only allowed in parameter list in GLSL 1.10 */
+void main()
+{
+  out vec4 foo;
+
+  gl_Position = gl_Vertex;
+}
diff --git a/src/glsl/tests/swiz-01.glsl b/src/glsl/tests/swiz-01.glsl
new file mode 100644 (file)
index 0000000..3268fa1
--- /dev/null
@@ -0,0 +1,11 @@
+/* PASS */
+#version 120
+
+void main()
+{
+       float a;
+       vec4 b;
+
+       b.x = 6.0;
+       a = b.x;
+}
diff --git a/src/glsl/tests/swiz-02.glsl b/src/glsl/tests/swiz-02.glsl
new file mode 100644 (file)
index 0000000..e3f043c
--- /dev/null
@@ -0,0 +1,11 @@
+/* FAIL: assignment of a vec2 to a float */
+#version 120
+
+void main()
+{
+       float a;
+       vec4 b;
+
+       b.x = 6.0;
+       a = b.xy;
+}
diff --git a/src/glsl/tests/void-01.glsl b/src/glsl/tests/void-01.glsl
new file mode 100644 (file)
index 0000000..5719edc
--- /dev/null
@@ -0,0 +1,2 @@
+/* FAIL - cannot declare a variable as having type `void' */
+void foo;
index 842aefc93c7f43bf4984d2ab22f55ca09d54d18f..213819e75107ba6c41bed1f141ebfff2ee29084a 100644 (file)
@@ -44,7 +44,7 @@ unsigned int __glutDisplayMode =
   GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH;
 char *__glutDisplayString = NULL;
 int __glutConnectionFD;
-XSizeHints __glutSizeHints = {0};
+XSizeHints __glutSizeHints;
 int __glutInitWidth = 300, __glutInitHeight = 300;
 int __glutInitX = -1, __glutInitY = -1;
 GLboolean __glutForceDirect = GL_FALSE,
index 9a22d0c547ac269f4483b46d8ce5b20f3c59267f..ba5708ffed589d20349bf82a6b563e9dfdc4feb8 100644 (file)
@@ -71,8 +71,9 @@ default: depend $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME)
 
 # Make libGL
 $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME): $(OBJECTS) $(GLAPI_LIB) Makefile
-       $(MKLIB) -o $(GL_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
-               -major 1 -minor 2 $(MKLIB_OPTIONS) \
+       $(MKLIB) -o $(GL_LIB) -linker '$(CXX)' -ldflags '$(LDFLAGS)' \
+               -major 1 -minor 2 \
+               -cplusplus $(MKLIB_OPTIONS) \
                -install $(TOP)/$(LIB_DIR) -id $(INSTALL_LIB_DIR)/lib$(GL_LIB).1.dylib \
                $(GL_LIB_DEPS) $(OBJECTS) $(GLAPI_LIB)
 
index 0ca0ff92a6c497152e882f6f999c1ef6ed2b8dd4..bd41c9e667ac8dabdb7587f650d1ddc6b6c493e4 100644 (file)
@@ -895,13 +895,13 @@ static int NoOp(void)
  * Create and initialize a new GL dispatch table.  The table is initialized
  * with GLX indirect rendering protocol functions.
  */
-__GLapi * __glXNewIndirectAPI( void )
+struct _glapi_table * __glXNewIndirectAPI( void )
 {
-    __GLapi *glAPI;
+    struct _glapi_table *glAPI;
     GLuint entries;
 
     entries = _glapi_get_dispatch_table_size();
-    glAPI = (__GLapi *) Xmalloc(entries * sizeof(void *));
+    glAPI = (struct _glapi_table *) Xmalloc(entries * sizeof(void *));
 
     /* first, set all entries to point to no-op functions */
     {
index a74884d595ae57a35744d9359041819092f0e0df..a0bb0781063bc7ac02756ac7a5640169091e44c8 100644 (file)
 #ifndef _GLAPI_H
 #define _GLAPI_H
 
-#ifndef MAPI_GLAPI_CURRENT
-#define MAPI_GLAPI_CURRENT
+
+/* opengl.dll does not export _glapi_* */
+#if defined(_WIN32)
+#define _GLAPI_NO_EXPORTS
 #endif
 
+#ifdef _GLAPI_NO_EXPORTS
+#  define _GLAPI_EXPORT
+#else /* _GLAPI_NO_EXPORTS */
+#  ifdef _WIN32
+#    ifdef _GLAPI_DLL_EXPORTS
+#      define _GLAPI_EXPORT __declspec(dllexport)
+#    else
+#      define _GLAPI_EXPORT __declspec(dllimport)
+#    endif
+#  elif defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
+#    define _GLAPI_EXPORT __attribute__((visibility("default")))
+#  else
+#    define _GLAPI_EXPORT
+#  endif
+#endif /* _GLAPI_NO_EXPORTS */
+
+
+/* Is this needed?  It is incomplete anyway. */
 #ifdef USE_MGL_NAMESPACE
 #define _glapi_set_dispatch _mglapi_set_dispatch
 #define _glapi_get_dispatch _mglapi_get_dispatch
 #define _glapi_Context _mglapi_Context
 #endif
 
-#include "mapi/u_current.h"
 #include "glapi/glthread.h"
 
 typedef void (*_glapi_proc)(void);
+struct _glapi_table;
+
+
+#if defined (GLX_USE_TLS)
+
+_GLAPI_EXPORT extern __thread struct _glapi_table * _glapi_tls_Dispatch
+    __attribute__((tls_model("initial-exec")));
+
+_GLAPI_EXPORT extern __thread void * _glapi_tls_Context
+    __attribute__((tls_model("initial-exec")));
+
+_GLAPI_EXPORT extern const struct _glapi_table *_glapi_Dispatch;
+_GLAPI_EXPORT extern const void *_glapi_Context;
+
+# define GET_DISPATCH() _glapi_tls_Dispatch
+# define GET_CURRENT_CONTEXT(C)  GLcontext *C = (GLcontext *) _glapi_tls_Context
+
+#else
+
+_GLAPI_EXPORT extern struct _glapi_table *_glapi_Dispatch;
+_GLAPI_EXPORT extern void *_glapi_Context;
+
+# ifdef THREADS
+
+#  define GET_DISPATCH() \
+     (likely(_glapi_Dispatch) ? _glapi_Dispatch : _glapi_get_dispatch())
+
+#  define GET_CURRENT_CONTEXT(C)  GLcontext *C = (GLcontext *) \
+     (likely(_glapi_Context) ? _glapi_Context : _glapi_get_context())
+
+# else
+
+#  define GET_DISPATCH() _glapi_Dispatch
+#  define GET_CURRENT_CONTEXT(C)  GLcontext *C = (GLcontext *) _glapi_Context
+
+# endif
+
+#endif /* defined (GLX_USE_TLS) */
+
+
+void
+_glapi_destroy_multithread(void);
+
 
-#define GET_DISPATCH() ((struct _glapi_table *) u_current_get())
-#define GET_CURRENT_CONTEXT(C) GLcontext *C = (GLcontext *) u_current_get_user()
+_GLAPI_EXPORT void
+_glapi_check_multithread(void);
 
-PUBLIC unsigned int
+
+_GLAPI_EXPORT void
+_glapi_set_context(void *context);
+
+
+_GLAPI_EXPORT void *
+_glapi_get_context(void);
+
+
+_GLAPI_EXPORT void
+_glapi_set_dispatch(struct _glapi_table *dispatch);
+
+
+_GLAPI_EXPORT struct _glapi_table *
+_glapi_get_dispatch(void);
+
+
+_GLAPI_EXPORT unsigned int
 _glapi_get_dispatch_table_size(void);
 
 
-PUBLIC int
+_GLAPI_EXPORT int
 _glapi_add_dispatch( const char * const * function_names,
                     const char * parameter_signature );
 
-PUBLIC int
+_GLAPI_EXPORT int
 _glapi_get_proc_offset(const char *funcName);
 
 
-PUBLIC _glapi_proc
+_GLAPI_EXPORT _glapi_proc
 _glapi_get_proc_address(const char *funcName);
 
 
-PUBLIC const char *
+_GLAPI_EXPORT const char *
 _glapi_get_proc_name(unsigned int offset);
 
 
-#endif
+_GLAPI_EXPORT unsigned long
+_glthread_GetID(void);
+
+
+/*
+ * These stubs are kept so that the old DRI drivers still load.
+ */
+_GLAPI_EXPORT void
+_glapi_noop_enable_warnings(unsigned char enable);
+
+
+_GLAPI_EXPORT void
+_glapi_set_warning_func(_glapi_proc func);
+
+
+#endif /* _GLAPI_H */
index ae59140ad3ab6197e1228649201cefbbd3980cd6..7421a36d35a560c4b672f87b2af9536ffee31104 100644 (file)
  * \author Brian Paul <brian@precisioninsight.com>
  */
 
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#include "glapi/mesa.h"
-#else
-#include "main/glheader.h"
-#include "main/compiler.h"
-#endif
-
-#include "glapi/glapi.h"
+#include "glapi/glapi_priv.h"
 #include "glapi/glapitable.h"
 #include "glapi/glapidispatch.h"
-#include "glapi/glthread.h"
 
 
 #if !(defined(USE_X86_ASM) || defined(USE_X86_64_ASM) || defined(USE_SPARC_ASM))
index 82c68c27c8bb141642a4c617c9cb102a671619a6..993ccb94c2430205b48098e4f30576a549e607b3 100644 (file)
  */
 
 
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#include "glapi/mesa.h"
-#else
-#include "main/glheader.h"
-#include "main/compiler.h"
-#endif
-
-#include "glapi/glapi.h"
 #include "glapi/glapi_priv.h"
 #include "mapi/u_execmem.h"
 
index 3c134f929d6350973b672d4b3131b284dbcdbe67..dc4905b64e03a60223ef293babbc5804c5712803 100644 (file)
  */
 
 
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#include "glapi/mesa.h"
-#else
-#include "main/glheader.h"
-#include "main/compiler.h"
-#endif
-
-#include "glapi/glapi.h"
 #include "glapi/glapi_priv.h"
 #include "glapi/glapitable.h"
 #include "glapi/glapioffsets.h"
index 9709551ee78bfeefebe089c4fe55898765c409cc..9b092971506f59bb12df7a3d941877ab0b710e42 100644 (file)
 
 
 
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#include "glapi/mesa.h"
-#else
-#include "main/compiler.h"
-#include "main/glheader.h"
-#endif
-
-#include "glapi/glapi.h"
-
-
-/*
- * These stubs are kept so that the old DRI drivers still load.
- */
-PUBLIC void
-_glapi_noop_enable_warnings(GLboolean enable);
+#include "glapi/glapi_priv.h"
 
-PUBLIC void
-_glapi_set_warning_func(_glapi_proc func);
 
 void
-_glapi_noop_enable_warnings(GLboolean enable)
+_glapi_noop_enable_warnings(unsigned char enable)
 {
 }
 
index 1c2a7042113814feff207be80214fd63b72065db..89f81c723e91cdba703c792503790eca8bfb4d97 100644 (file)
 #ifndef _GLAPI_PRIV_H
 #define _GLAPI_PRIV_H
 
-#include "glthread.h"
-#include "glapi.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#include "glapi/mesa.h"
+#else /* HAVE_DIX_CONFIG_H */
+#define GL_GLEXT_PROTOTYPES
+#include "GL/gl.h"
+#include "GL/glext.h"
+
+#ifndef GL_FIXED
+typedef int GLfixed;
+typedef int GLclampx;
+#endif
+
+#ifndef GL_OES_EGL_image
+typedef void *GLeglImageOES;
+#endif
+
+#endif /* HAVE_DIX_CONFIG_H */
 
+#include "glapi/glapi.h"
 
 
 /* getproc */
index 9dbc0e9a56f2f4fcfcfbd56fb01ff814fa3e1750..00915380f97b8c2d5ae6a4f221f8e7d2f8603bc0 100644 (file)
@@ -1,4 +1,4 @@
-#include "glthread.h"
+#include "glapi/glapi.h"
 
 unsigned long
 _glthread_GetID(void)
index 54292706acfc4a7e79a1741e3659abae06996967..fc4ece7c3384e57fc8ac2bda13d3e3c54b77cd52 100644 (file)
@@ -17,7 +17,4 @@
 typedef struct u_tsd _glthread_TSD;
 typedef u_mutex _glthread_Mutex;
 
-PUBLIC unsigned long
-_glthread_GetID(void);
-
-#endif /* THREADS_H */
+#endif /* GLTHREAD_H */
index d4c9907b895f43911be8c2625c22dc02c5e2a815..0f6e8125e8480003088fdfeffea9df3938597f4b 100644 (file)
@@ -33,7 +33,7 @@
 __asm__(".text");
 
 __asm__("x86_64_current_tls:\n\t"
-       "movq _glapi_tls_Dispatch@GOTTPOFF(%rip), %rax\n\t"
+       "movq u_current_table_tls@GOTTPOFF(%rip), %rax\n\t"
        "ret");
 
 #define STUB_ASM_ENTRY(func)                             \
@@ -43,7 +43,7 @@ __asm__("x86_64_current_tls:\n\t"
    func ":"
 
 #define STUB_ASM_CODE(slot)                              \
-   "movq _glapi_tls_Dispatch@GOTTPOFF(%rip), %rax\n\t"   \
+   "movq u_current_table_tls@GOTTPOFF(%rip), %rax\n\t"   \
    "movq %fs:(%rax), %r11\n\t"                           \
    "jmp *(8 * " slot ")(%r11)"
 
index de0498181de96d29a28caf7df8eee440a168b6ab..ff2b9575f6736270f0d5b8e3a2d52325dc495023 100644 (file)
@@ -37,7 +37,7 @@ __asm__("x86_current_tls:\n\t"
         "1:\n\t"
         "popl %eax\n\t"
        "addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %eax\n\t"
-       "movl _glapi_tls_Dispatch@GOTNTPOFF(%eax), %eax\n\t"
+       "movl u_current_table_tls@GOTNTPOFF(%eax), %eax\n\t"
        "ret");
 
 #ifndef GLX_X86_READONLY_TEXT
index d31e0676f078a1849aaff208250165170bee49ed..fbf4ec54971fc56a21d4fa501c780ab9f5920136 100644 (file)
@@ -41,12 +41,12 @@ __asm__(".text");
    func ":"
 
 #define STUB_ASM_CODE(slot)         \
-   "movl _glapi_Dispatch, %eax\n\t" \
+   "movl u_current_table, %eax\n\t" \
    "testl %eax, %eax\n\t"           \
    "je 1f\n\t"                      \
    "jmp *(4 * " slot ")(%eax)\n"    \
    "1:\n\t"                         \
-   "call _glapi_get_dispatch\n\t"   \
+   "call u_current_get_internal\n\t"\
    "jmp *(4 * " slot ")(%eax)"
 
 #define MAPI_TMP_STUB_ASM_GCC
index 8832b3dfb6e82a6c91691cab334bcfea50007144..c7e43e22e9fae803f26b2d67fc63454b16935e51 100644 (file)
 
 #include "u_compiler.h"
 
+#ifdef _WIN32
+#ifdef MAPI_DLL_EXPORTS
+#define MAPI_EXPORT __declspec(dllexport)
+#else
+#define MAPI_EXPORT __declspec(dllimport)
+#endif
+#else /* _WIN32 */
+#define MAPI_EXPORT PUBLIC
+#endif
+
 typedef void (*mapi_proc)(void);
 
 struct mapi_table;
 
-PUBLIC void
+MAPI_EXPORT void
 mapi_init(const char *spec);
 
-PUBLIC mapi_proc
+MAPI_EXPORT mapi_proc
 mapi_get_proc_address(const char *name);
 
-PUBLIC struct mapi_table *
+MAPI_EXPORT struct mapi_table *
 mapi_table_create(void);
 
-PUBLIC void
+MAPI_EXPORT void
 mapi_table_destroy(struct mapi_table *tbl);
 
-PUBLIC void
+MAPI_EXPORT void
 mapi_table_fill(struct mapi_table *tbl, const mapi_proc *procs);
 
-PUBLIC void
+MAPI_EXPORT void
 mapi_table_make_current(const struct mapi_table *tbl);
 
 #endif /* _MAPI_H_ */
index 91547c48301efa4a1cad62c847cfc631d1978bc2..ed9ccfe229958760546818c4f8c8c63bbc911784 100644 (file)
@@ -99,25 +99,25 @@ extern void (*__glapi_noop_table[])(void);
 /*@{*/
 #if defined(GLX_USE_TLS)
 
-__thread struct _glapi_table *_glapi_tls_Dispatch
+__thread struct mapi_table *u_current_table_tls
     __attribute__((tls_model("initial-exec")))
-    = (struct _glapi_table *) table_noop_array;
+    = (struct mapi_table *) table_noop_array;
 
-__thread void * _glapi_tls_Context
+__thread void *u_current_user_tls
     __attribute__((tls_model("initial-exec")));
 
-const struct _glapi_table *_glapi_Dispatch;
-const void *_glapi_Context;
+const struct mapi_table *u_current_table;
+const void *u_current_user;
 
 #else
 
-struct _glapi_table *_glapi_Dispatch =
-   (struct _glapi_table *) table_noop_array;
-void *_glapi_Context;
+struct mapi_table *u_current_table =
+   (struct mapi_table *) table_noop_array;
+void *u_current_user;
 
 #ifdef THREADS
-struct u_tsd _gl_DispatchTSD;
-static struct u_tsd ContextTSD;
+struct u_tsd u_current_table_tsd;
+static struct u_tsd u_current_user_tsd;
 static int ThreadSafe;
 #endif /* THREADS */
 
@@ -126,11 +126,11 @@ static int ThreadSafe;
 
 
 void
-_glapi_destroy_multithread(void)
+u_current_destroy(void)
 {
 #if defined(THREADS) && defined(WIN32_THREADS)
-   u_tsd_destroy(&_gl_DispatchTSD);
-   u_tsd_destroy(&ContextTSD);
+   u_tsd_destroy(&u_current_table_tsd);
+   u_tsd_destroy(&u_current_user_tsd);
 #endif
 }
 
@@ -138,10 +138,10 @@ _glapi_destroy_multithread(void)
 #if defined(THREADS) && !defined(GLX_USE_TLS)
 
 static void
-_glapi_init_multithread(void)
+u_current_init_tsd(void)
 {
-   u_tsd_init(&_gl_DispatchTSD);
-   u_tsd_init(&ContextTSD);
+   u_tsd_init(&u_current_table_tsd);
+   u_tsd_init(&u_current_user_tsd);
 }
 
 /**
@@ -162,7 +162,7 @@ u_mutex_declare_static(ThreadCheckMutex);
  * in order to test if multiple threads are being used.
  */
 void
-_glapi_check_multithread(void)
+u_current_init(void)
 {
    static unsigned long knownID;
    static int firstCall = 1;
@@ -172,15 +172,15 @@ _glapi_check_multithread(void)
 
    CHECK_MULTITHREAD_LOCK();
    if (firstCall) {
-      _glapi_init_multithread();
+      u_current_init_tsd();
 
       knownID = u_thread_self();
       firstCall = 0;
    }
    else if (knownID != u_thread_self()) {
       ThreadSafe = 1;
-      _glapi_set_dispatch(NULL);
-      _glapi_set_context(NULL);
+      u_current_set_internal(NULL);
+      u_current_set_user_internal(NULL);
    }
    CHECK_MULTITHREAD_UNLOCK();
 }
@@ -188,7 +188,7 @@ _glapi_check_multithread(void)
 #else
 
 void
-_glapi_check_multithread(void)
+u_current_init(void)
 {
 }
 
@@ -202,15 +202,17 @@ _glapi_check_multithread(void)
  * void from the real context pointer type.
  */
 void
-_glapi_set_context(void *context)
+u_current_set_user_internal(void *ptr)
 {
+   u_current_init();
+
 #if defined(GLX_USE_TLS)
-   _glapi_tls_Context = context;
+   u_current_user_tls = ptr;
 #elif defined(THREADS)
-   u_tsd_set(&ContextTSD, context);
-   _glapi_Context = (ThreadSafe) ? NULL : context;
+   u_tsd_set(&u_current_user_tsd, ptr);
+   u_current_user = (ThreadSafe) ? NULL : ptr;
 #else
-   _glapi_Context = context;
+   u_current_user = ptr;
 #endif
 }
 
@@ -220,16 +222,16 @@ _glapi_set_context(void *context)
  * void to the real context pointer type.
  */
 void *
-_glapi_get_context(void)
+u_current_get_user_internal(void)
 {
 #if defined(GLX_USE_TLS)
-   return _glapi_tls_Context;
+   return u_current_user_tls;
 #elif defined(THREADS)
    return (ThreadSafe)
-      ? u_tsd_get(&ContextTSD)
-      : _glapi_Context;
+      ? u_tsd_get(&u_current_user_tsd)
+      : u_current_user;
 #else
-   return _glapi_Context;
+   return u_current_user;
 #endif
 }
 
@@ -239,36 +241,37 @@ _glapi_get_context(void)
  * table (__glapi_noop_table).
  */
 void
-_glapi_set_dispatch(struct _glapi_table *dispatch)
+u_current_set_internal(struct mapi_table *tbl)
 {
+   u_current_init();
+
    stub_init_once();
 
-   if (!dispatch)
-      dispatch = (struct _glapi_table *) table_noop_array;
+   if (!tbl)
+      tbl = (struct mapi_table *) table_noop_array;
 
 #if defined(GLX_USE_TLS)
-   _glapi_tls_Dispatch = dispatch;
+   u_current_table_tls = tbl;
 #elif defined(THREADS)
-   u_tsd_set(&_gl_DispatchTSD, (void *) dispatch);
-   _glapi_Dispatch = (ThreadSafe) ? NULL : dispatch;
+   u_tsd_set(&u_current_table_tsd, (void *) tbl);
+   u_current_table = (ThreadSafe) ? NULL : tbl;
 #else
-   _glapi_Dispatch = dispatch;
+   u_current_table = tbl;
 #endif
 }
 
 /**
  * Return pointer to current dispatch table for calling thread.
  */
-struct _glapi_table *
-_glapi_get_dispatch(void)
+struct mapi_table *
+u_current_get_internal(void)
 {
 #if defined(GLX_USE_TLS)
-   return _glapi_tls_Dispatch;
+   return u_current_table_tls;
 #elif defined(THREADS)
-   return (ThreadSafe)
-      ? (struct _glapi_table *) u_tsd_get(&_gl_DispatchTSD)
-      : _glapi_Dispatch;
+   return (struct mapi_table *) ((ThreadSafe) ?
+         u_tsd_get(&u_current_table_tsd) : (void *) u_current_table);
 #else
-   return _glapi_Dispatch;
+   return u_current_table;
 #endif
 }
index a6256f5b51296e916cc771a3ec33f07262cd5a8a..62e54c6c93d54b0355f0fe5c65e8692bc7a0cd2a 100644 (file)
 #ifndef _U_CURRENT_H_
 #define _U_CURRENT_H_
 
-#include "u_compiler.h"
-
 #ifdef MAPI_GLAPI_CURRENT
-#define GLAPI_EXPORT PUBLIC
-#else
-#define GLAPI_EXPORT
-#endif
 
-/*
- * Unlike other utility functions, we need to keep the old names (_glapi_*) for
- * ABI compatibility.  The desired functions are wrappers to the old ones.
- */
+#include "glapi/glapi.h"
+
+/* ugly renames to match glapi.h */
+#define mapi_table _glapi_table
+
+#define u_current_table_tls _glapi_tls_Dispatch
+#define u_current_user_tls _glapi_tls_Context
+#define u_current_table _glapi_Dispatch
+#define u_current_user _glapi_Context
+
+#define u_current_destroy _glapi_destroy_multithread
+#define u_current_init _glapi_check_multithread
+#define u_current_set_internal _glapi_set_dispatch
+#define u_current_get_internal _glapi_get_dispatch
+#define u_current_set_user_internal _glapi_set_context
+#define u_current_get_user_internal _glapi_get_context
+
+#define u_current_table_tsd _gl_DispatchTSD
+
+#else /* MAPI_GLAPI_CURRENT */
+
+#include "u_compiler.h"
 
-struct _glapi_table;
+struct mapi_table;
 
 #ifdef GLX_USE_TLS
 
-GLAPI_EXPORT extern __thread struct _glapi_table *_glapi_tls_Dispatch
+extern __thread struct mapi_table *u_current_table_tls
     __attribute__((tls_model("initial-exec")));
 
-GLAPI_EXPORT extern __thread void *_glapi_tls_Context
+extern __thread void *u_current_user_tls
     __attribute__((tls_model("initial-exec")));
 
-GLAPI_EXPORT extern const struct _glapi_table *_glapi_Dispatch;
-GLAPI_EXPORT extern const void *_glapi_Context;
+extern const struct mapi_table *u_current_table;
+extern const void *u_current_user;
 
 #else /* GLX_USE_TLS */
 
-GLAPI_EXPORT extern struct _glapi_table *_glapi_Dispatch;
-GLAPI_EXPORT extern void *_glapi_Context;
+extern struct mapi_table *u_current_table;
+extern void *u_current_user;
 
 #endif /* GLX_USE_TLS */
 
-GLAPI_EXPORT void
-_glapi_check_multithread(void);
-
-GLAPI_EXPORT void
-_glapi_set_context(void *context);
+void
+u_current_init(void);
 
-GLAPI_EXPORT void *
-_glapi_get_context(void);
+void
+u_current_destroy(void);
 
-GLAPI_EXPORT void
-_glapi_set_dispatch(struct _glapi_table *dispatch);
+void
+u_current_set_internal(struct mapi_table *tbl);
 
-GLAPI_EXPORT struct _glapi_table *
-_glapi_get_dispatch(void);
+struct mapi_table *
+u_current_get_internal(void);
 
 void
-_glapi_destroy_multithread(void);
-
+u_current_set_user_internal(void *ptr);
 
-struct mapi_table;
+void *
+u_current_get_user_internal(void);
 
 static INLINE void
 u_current_set(const struct mapi_table *tbl)
 {
-   _glapi_check_multithread();
-   _glapi_set_dispatch((struct _glapi_table *) tbl);
+   u_current_set_internal((struct mapi_table *) tbl);
 }
 
 static INLINE const struct mapi_table *
 u_current_get(void)
 {
 #ifdef GLX_USE_TLS
-   return (const struct mapi_table *) _glapi_tls_Dispatch;
+   return (const struct mapi_table *) u_current_table_tls;
 #else
-   return (const struct mapi_table *) (likely(_glapi_Dispatch) ?
-      _glapi_Dispatch : _glapi_get_dispatch());
+   return (likely(u_current_table) ?
+         (const struct mapi_table *) u_current_table : u_current_get_internal());
 #endif
 }
 
 static INLINE void
 u_current_set_user(void *ptr)
 {
-   _glapi_check_multithread();
-   _glapi_set_context(ptr);
+   u_current_set_internal(ptr);
 }
 
 static INLINE void *
 u_current_get_user(void)
 {
 #ifdef GLX_USE_TLS
-   return _glapi_tls_Context;
+   return u_current_user_tls;
 #else
-   return likely(_glapi_Context) ? _glapi_Context : _glapi_get_context();
+   return likely(u_current_user) ? u_current_user : u_current_get_user_internal();
 #endif
 }
 
-#endif /* GLX_USE_TLS */
+#endif /* MAPI_GLAPI_CURRENT */
+
+#endif /* _U_CURRENT_H_ */
index bf51264ab949e2ab5fa1c5070e5758de4187558a..20d7f2744d09c3605fe0895dc179d411b76ec104 100644 (file)
@@ -18,6 +18,7 @@ if env['platform'] != 'winddk':
 
        env.Append(CPPDEFINES = [
                'MAPI_ABI_HEADER=\\"vgapi/vgapi_tmp.h\\"',
+               'MAPI_DLL_EXPORTS',
                'KHRONOS_DLL_EXPORTS',
        ])
 
index 7073c92240b3c55d8efb1c2a7645b9fb72a24f7d..ef31fd24f08854c0a4d4ad1e1e8101b6ce698302 100644 (file)
@@ -42,35 +42,53 @@ MESA_GALLIUM_OBJECTS := $(addprefix $(MESA_OBJ_DIR)/, $(MESA_GALLIUM_OBJECTS))
 MESA_INCLUDES := $(INCLUDE_DIRS)
 ES1_INCLUDES := -I$(TOP)/src/mapi/es1api $(INCLUDE_DIRS)
 ES2_INCLUDES := -I$(TOP)/src/mapi/es2api $(INCLUDE_DIRS)
-
+MESA_INCLUDES := -I$(TOP)/src/glsl $(MESA_INCLUDES)
+ES1_INCLUDES := -I$(TOP)/src/glsl $(ES1_INCLUDES)
+ES2_INCLUDES := -I$(TOP)/src/glsl $(ES2_INCLUDES)
+# For symbol_table.h in glsl compiler headers.
+MESA_INCLUDES := -I$(TOP)/src/mesa/shader $(MESA_INCLUDES)
 
 define mesa-cc-c
        @mkdir -p $(dir $@)
        $(CC) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_INCLUDES) $(CFLAGS)
 endef
 
+define mesa-cxx-c
+       @mkdir -p $(dir $@)
+       $(CXX) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_INCLUDES) $(CXXFLAGS)
+endef
+
 $(MESA_OBJ_DIR)/%.o: %.c
        $(call mesa-cc-c,MESA)
 
+$(MESA_OBJ_DIR)/%.o: %.cpp
+       $(call mesa-cxx-c,MESA)
+
 $(MESA_OBJ_DIR)/%.o: %.S
        $(call mesa-cc-c,MESA)
 
 $(ES1_OBJ_DIR)/%.o: %.c
        $(call mesa-cc-c,ES1)
 
+$(ES1_OBJ_DIR)/%.o: %.cpp
+       $(call mesa-cxx-c,ES1)
+
 $(ES1_OBJ_DIR)/%.o: %.S
        $(call mesa-cc-c,ES1)
 
 $(ES2_OBJ_DIR)/%.o: %.c
        $(call mesa-cc-c,ES2)
 
+$(ES2_OBJ_DIR)/%.o: %.cpp
+       $(call mesa-cxx-c,ES2)
+
 $(ES2_OBJ_DIR)/%.o: %.S
        $(call mesa-cc-c,ES2)
 
 
 # Default: build dependencies, then asm_subdirs, GLSL built-in lib,
 # then convenience libs (.a) and finally the device drivers:
-default: $(DEPENDS) asm_subdirs glsl_builtin \
+default: $(DEPENDS) asm_subdirs \
        $(MESA_LIBS) $(ES1_LIBS) $(ES2_LIBS) driver_subdirs
 
 main/api_exec_es1.c: main/APIspec.xml main/es_generator.py main/APIspecutil.py main/APIspec.py
@@ -120,12 +138,6 @@ asm_subdirs:
        fi
 
 
-######################################################################
-# GLSL built-in library
-glsl_builtin:
-       (cd slang/library && $(MAKE)) || exit 1 ;
-
-
 ######################################################################
 # Dependency generation
 
@@ -241,7 +253,6 @@ clean: clean-es1 clean-es2
        -rm -f depend depend.bak libmesa.a libmesagallium.a
        -rm -f drivers/*/*.o
        -rm -f *.pc
-       -rm -f slang/library/*_gc.h
        -@cd drivers/dri && $(MAKE) clean
        -@cd drivers/x11 && $(MAKE) clean
        -@cd drivers/osmesa && $(MAKE) clean
index d31b957234b21c8a16f7fc41aed108a041c3ea58..28598f4a17c331f6c92b9ea6233fbecaca74fe48 100644 (file)
@@ -10,6 +10,7 @@ if env['platform'] != 'winddk':
        
        env.Append(CPPPATH = [
                '#/src/mapi',
+               '#/src/glsl',
                '#/src/mesa',
        ])
        
@@ -19,6 +20,7 @@ if env['platform'] != 'winddk':
                        'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers 
                        'WIN32_THREADS', # use Win32 thread API
                ])       
+        env.Prepend(CPPPATH = ['#src/talloc'])
 
        #
        # Source files
@@ -51,6 +53,7 @@ if env['platform'] != 'winddk':
                'main/dlist.c',
                'main/dlopen.c',
                'main/drawpix.c',
+               'main/drawtex.c',
                'main/enable.c',
                'main/enums.c',
                'main/eval.c',
@@ -104,6 +107,7 @@ if env['platform'] != 'winddk':
                'main/texgetimage.c',
                'main/teximage.c',
                'main/texobj.c',
+               'main/texpal.c',
                'main/texparam.c',
                'main/texrender.c',
                'main/texstate.c',
@@ -174,6 +178,7 @@ if env['platform'] != 'winddk':
                'state_tracker/st_cb_condrender.c',
                'state_tracker/st_cb_flush.c',
                'state_tracker/st_cb_drawpixels.c',
+               'state_tracker/st_cb_drawtex.c',
                'state_tracker/st_cb_eglimage.c',
                'state_tracker/st_cb_fbo.c',
                'state_tracker/st_cb_feedback.c',
@@ -201,6 +206,7 @@ if env['platform'] != 'winddk':
        program_sources = [
                'program/arbprogparse.c',
                'program/hash_table.c',
+        'program/ir_to_mesa.cpp',
                'program/lex.yy.c',
                'program/nvfragparse.c',
                'program/nvvertparse.c',
@@ -221,36 +227,13 @@ if env['platform'] != 'winddk':
                'program/symbol_table.c',
        ]
        
-       slang_sources = [
-               'slang/slang_builtin.c',
-               'slang/slang_codegen.c',
-               'slang/slang_compile.c',
-               'slang/slang_compile_function.c',
-               'slang/slang_compile_operation.c',
-               'slang/slang_compile_struct.c',
-               'slang/slang_compile_variable.c',
-               'slang/slang_emit.c',
-               'slang/slang_ir.c',
-               'slang/slang_label.c',
-               'slang/slang_link.c',
-               'slang/slang_log.c',
-               'slang/slang_mem.c',
-               'slang/slang_print.c',
-               'slang/slang_simplify.c',
-               'slang/slang_storage.c',
-               'slang/slang_typeinfo.c',
-               'slang/slang_vartable.c',
-               'slang/slang_utility.c',
-       ]
-       
        mesa_sources = (
                main_sources +
                math_sources +
                program_sources +
                vbo_sources +
                vf_sources +
-               statetracker_sources +
-               slang_sources
+               statetracker_sources
        )
 
        #
@@ -328,8 +311,6 @@ if env['platform'] != 'winddk':
                # build dir) to the include path  
                env.Append(CPPPATH = [matypes[0].dir])
 
-       SConscript('slang/library/SConscript')
-
        #
        # Libraries
        # 
index 8cb25439e4843ba15c36c1bf605bc10255163c9e..a00018cafa751b0e33ab752985432a21b31a35e1 100644 (file)
@@ -17,6 +17,7 @@ COMMON_SOURCES = $(COMMON_GALLIUM_SOURCES) \
 INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES)
 
 OBJECTS = $(C_SOURCES:.c=.o) \
+         $(CXX_SOURCES:.cpp=.o) \
          $(ASM_SOURCES:.S=.o) 
 
 
@@ -33,12 +34,16 @@ SHARED_INCLUDES = \
        $(LIBDRM_CFLAGS)
 
 CFLAGS += $(API_DEFINES)
+CXXFLAGS += $(API_DEFINES)
 
 ##### RULES #####
 
 .c.o:
        $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
 
+.cpp.o:
+       $(CC) -c $(INCLUDES) $(CXXFLAGS) $(DRIVER_DEFINES) $< -o $@
+
 .S.o:
        $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
 
@@ -54,9 +59,9 @@ lib: symlinks subdirs depend
 
 $(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) Makefile \
                $(TOP)/src/mesa/drivers/dri/Makefile.template $(TOP)/src/mesa/drivers/dri/common/dri_test.o
-       $(MKLIB) -o $@.tmp -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \
+       $(MKLIB) -o $@.tmp -noprefix -linker '$(CXX)' -ldflags '$(LDFLAGS)' \
                $(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) $(DRI_LIB_DEPS)
-       $(CC) $(CFLAGS) -o $@.test $(TOP)/src/mesa/drivers/dri/common/dri_test.o $@.tmp $(DRI_LIB_DEPS)
+       $(CXX) $(CFLAGS) -o $@.test $(TOP)/src/mesa/drivers/dri/common/dri_test.o $@.tmp $(DRI_LIB_DEPS)
        @rm -f $@.test
        mv -f $@.tmp $@
 
index dce84ef0deb37e2c6f48f795542f0cece88fa1f0..a581c6663f2f1d43e41fa4ed0107dd6e9483bc99 100644 (file)
@@ -32,6 +32,7 @@
 #include "drm_sarea.h"
 #include "utils.h"
 #include "xmlpool.h"
+#include "../glsl/glsl_parser_extras.h"
 
 PUBLIC const char __dri2ConfigOptions[] =
    DRI_CONF_BEGIN
@@ -707,6 +708,8 @@ static void driDestroyScreen(__DRIscreen *psp)
         * stream open to the X-server anymore.
         */
 
+       _mesa_destroy_shader_compiler();
+
        if (psp->DriverAPI.DestroyScreen)
            (*psp->DriverAPI.DestroyScreen)(psp);
 
@@ -714,6 +717,9 @@ static void driDestroyScreen(__DRIscreen *psp)
           (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
           (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
           (void)drmCloseOnce(psp->fd);
+       } else {
+          driDestroyOptionCache(&psp->optionCache);
+          driDestroyOptionInfo(&psp->optionInfo);
        }
 
        free(psp);
@@ -839,7 +845,6 @@ dri2CreateNewScreen(int scrn, int fd,
     static const __DRIextension *emptyExtensionList[] = { NULL };
     __DRIscreen *psp;
     drmVersionPtr version;
-    driOptionCache options;
 
     if (driDriverAPI.InitScreen2 == NULL)
         return NULL;
@@ -873,8 +878,10 @@ dri2CreateNewScreen(int scrn, int fd,
 
     psp->DriverAPI = driDriverAPI;
 
-    driParseOptionInfo(&options, __dri2ConfigOptions, __dri2NConfigOptions);
-    driParseConfigFiles(&psp->optionCache, &options, psp->myNum, "dri2");
+    driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions,
+                      __dri2NConfigOptions);
+    driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum,
+                       "dri2");
 
     return psp;
 }
index bc647ff8130f6f74d39034715f682c0c7eb9240d..5096d22cad386045d03b7b3ee908981d46875a7e 100644 (file)
@@ -513,7 +513,11 @@ struct __DRIscreenRec {
      * 
      * This pointer is never touched by the DRI layer.
      */
+#ifdef __cplusplus
+    void *priv;
+#else
     void *private;
+#endif
 
     /* Extensions provided by the loader. */
     const __DRIgetDrawableInfoExtension *getDrawableInfo;
@@ -532,6 +536,7 @@ struct __DRIscreenRec {
     /* The lock actually in use, old sarea or DRI2 */
     drmLock *lock;
 
+    driOptionCache optionInfo;
     driOptionCache optionCache;
    unsigned int api_mask;
 };
index d52ea9812f7f835436bfc71e887ac75232b3a190..8ddce6d82a58990cf89d5c88b379e71684385e76 100644 (file)
@@ -27,7 +27,6 @@
 
 #include "i830_context.h"
 #include "main/imports.h"
-#include "texmem.h"
 #include "tnl/tnl.h"
 #include "tnl/t_vertex.h"
 #include "tnl/t_context.h"
index b3fe1c05d669c4dad0a6a0705a375733b6daeb6f..d8715cf026d3ebe5c49a20920c15e6953b887d5b 100644 (file)
@@ -174,6 +174,8 @@ i915CreateContext(int api,
 
    ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
 
+   ctx->Shader.EmitNoIfs = GL_TRUE;
+
    ctx->Const.MaxDrawBuffers = 1;
 
    _tnl_init_vertices(ctx, ctx->Const.MaxArrayLockSize + 12,
index f1505dc5e73a532d66086cdb26ac5c1cfdbeddc9..4a2e6209d075cbd496deb5a68a15a02a03e3c7d7 100644 (file)
@@ -143,6 +143,20 @@ src_vector(struct i915_fragment_program *p,
       }
       break;
 
+   case PROGRAM_OUTPUT:
+      switch (source->Index) {
+      case FRAG_RESULT_COLOR:
+        src = UREG(REG_TYPE_OC, 0);
+        break;
+      case FRAG_RESULT_DEPTH:
+        src = UREG(REG_TYPE_OD, 0);
+        break;
+      default:
+        i915_program_error(p, "Bad source->Index: %d", source->Index);
+        return 0;
+      }
+      break;
+
       /* Various paramters and env values.  All emitted to
        * hardware as program constants.
        */
@@ -472,6 +486,18 @@ upload_program(struct i915_fragment_program *p)
                         swizzle(tmp, X, X, X, X));
          break;
 
+      case OPCODE_DP2:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+         src1 = src_vector(p, &inst->SrcReg[1], program);
+        i915_emit_arith(p,
+                        A0_DP3,
+                         get_result_vector(p, inst),
+                         get_result_flags(inst), 0,
+                        swizzle(src0, X, Y, ZERO, ZERO),
+                        swizzle(src1, X, Y, ZERO, ZERO),
+                        0);
+         break;
+
       case OPCODE_DP3:
          EMIT_2ARG_ARITH(A0_DP3);
          break;
@@ -957,6 +983,41 @@ upload_program(struct i915_fragment_program *p)
                         0);
          break;
 
+      case OPCODE_SSG:
+        dst = get_result_vector(p, inst);
+        flags = get_result_flags(inst);
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+        tmp = i915_get_utemp(p);
+
+        /* tmp = (src < 0.0) */
+        i915_emit_arith(p,
+                        A0_SLT,
+                        tmp,
+                        flags, 0,
+                        src0,
+                        swizzle(src0, ZERO, ZERO, ZERO, ZERO),
+                        0);
+
+        /* dst = (0.0 < src) */
+        i915_emit_arith(p,
+                        A0_SLT,
+                        dst,
+                        flags, 0,
+                        swizzle(src0, ZERO, ZERO, ZERO, ZERO),
+                        src0,
+                        0);
+
+        /* dst = (src > 0.0) - (src < 0.0) */
+        i915_emit_arith(p,
+                        A0_ADD,
+                        dst,
+                        flags, 0,
+                        dst,
+                        negate(tmp, 1, 1, 1, 1),
+                        0);
+
+         break;
+
       case OPCODE_SUB:
          src0 = src_vector(p, &inst->SrcReg[0], program);
          src1 = src_vector(p, &inst->SrcReg[1], program);
index e381a5c714b31eb6d1b59185b3b5f1290929b442..bea48e13138131be54b1573524a4b5f03a67242e 100644 (file)
@@ -104,6 +104,11 @@ C_SOURCES = \
        $(COMMON_SOURCES) \
        $(DRIVER_SOURCES)
 
+CXX_SOURCES = \
+       brw_fs.cpp \
+       brw_fs_channel_expressions.cpp \
+       brw_fs_vector_splitting.cpp
+
 ASM_SOURCES = 
 
 DRIVER_DEFINES = -I../intel
index 6d064b822e51dba97e315ab0b3cb36ff164e7322..d2b20165f9d49aae9dcb7e8ef74c8a976746c731 100644 (file)
@@ -144,7 +144,8 @@ GLboolean brwCreateContext( int api,
       brw->CMD_VF_STATISTICS = CMD_VF_STATISTICS_GM45;
       brw->CMD_PIPELINE_SELECT = CMD_PIPELINE_SELECT_GM45;
       brw->has_surface_tile_offset = GL_TRUE;
-      brw->has_compr4 = GL_TRUE;
+      if (intel->gen < 6)
+         brw->has_compr4 = GL_TRUE;
       brw->has_aa_line_parameters = GL_TRUE;
       brw->has_pln = GL_TRUE;
   } else {
@@ -153,7 +154,11 @@ GLboolean brwCreateContext( int api,
    }
 
    /* WM maximum threads is number of EUs times number of threads per EU. */
-   if (intel->gen == 5) {
+   if (intel->gen >= 6) {
+      brw->urb.size = 1024;
+      brw->vs_max_threads = 60;
+      brw->wm_max_threads = 80;
+   } else if (intel->gen == 5) {
       brw->urb.size = 1024;
       brw->vs_max_threads = 72;
       brw->wm_max_threads = 12 * 6;
index cc4e6638e8ba39cd13537d9a390e9766271b0229..703a7de78d1e23738c7e0dfd2f7def688f719272 100644 (file)
@@ -179,6 +179,16 @@ struct brw_fragment_program {
    GLbitfield tex_units_used;
 };
 
+struct brw_shader {
+   struct gl_shader base;
+
+   /** Shader IR transformed for native compile, at link time. */
+   struct exec_list *ir;
+};
+
+struct brw_shader_program {
+   struct gl_shader_program base;
+};
 
 /* Data about a particular attempt to compile a program.  Note that
  * there can be many of these, each in a different GL state
@@ -654,7 +664,13 @@ struct brw_context
 
       drm_intel_bo *prog_bo;
       drm_intel_bo *state_bo;
-      drm_intel_bo *const_bo;
+      drm_intel_bo *const_bo; /* pull constant buffer. */
+      /**
+       *  This is the push constant BO on gen6.
+       *
+       * Pre-gen6, push constants live in the CURBE.
+       */
+      drm_intel_bo *push_const_bo;
    } wm;
 
 
@@ -686,7 +702,13 @@ struct brw_context
 
 #define BRW_PACKCOLOR8888(r,g,b,a)  ((r<<24) | (g<<16) | (b<<8) | a)
 
-
+struct brw_instruction_info {
+    char    *name;
+    int            nsrc;
+    int            ndst;
+    GLboolean is_arith;
+};
+extern const struct brw_instruction_info brw_opcodes[128];
 
 /*======================================================================
  * brw_vtbl.c
index f7a68cead7c731029458b67be03fbd8658aa9f88..6b8e9e05d08bf41aec4d8759c2fdcf7e46c99df4 100644 (file)
 #define BRW_SAMPLER_MESSAGE_SAMPLE_BIAS_GEN5       1
 #define BRW_SAMPLER_MESSAGE_SAMPLE_LOD_GEN5        2
 #define BRW_SAMPLER_MESSAGE_SAMPLE_COMPARE_GEN5    3
+#define BRW_SAMPLER_MESSAGE_SAMPLE_DERIVS_GEN5     4
+#define BRW_SAMPLER_MESSAGE_SAMPLE_BIAS_COMPARE_GEN5 5
+#define BRW_SAMPLER_MESSAGE_SAMPLE_LOD_COMPARE_GEN5 6
 
 /* for GEN5 only */
 #define BRW_SAMPLER_SIMD_MODE_SIMD4X2                   0
index d23071453619b6de13e3f2444d24e8d282eda859..f74a236834be38efb9adc61564779ba8b0bfcf8e 100644 (file)
@@ -159,6 +159,11 @@ char *saturate[2] = {
     [1] = ".sat"
 };
 
+char *accwr[2] = {
+    [0] = "",
+    [1] = "AccWrEnable"
+};
+
 char *exec_size[8] = {
     [0] = "1",
     [1] = "2",
@@ -206,6 +211,7 @@ char *compr_ctrl[4] = {
     [0] = "",
     [1] = "sechalf",
     [2] = "compr",
+    [3] = "compr4",
 };
 
 char *dep_ctrl[4] = {
@@ -235,6 +241,16 @@ char *reg_encoding[8] = {
     [7] = "F"
 };
 
+int reg_type_size[8] = {
+    [0] = 4,
+    [1] = 4,
+    [2] = 2,
+    [3] = 2,
+    [4] = 1,
+    [5] = 1,
+    [7] = 4
+};
+
 char *imm_encoding[8] = {
     [0] = "UD",
     [1] = "D",
@@ -423,6 +439,11 @@ static int print_opcode (FILE *file, int id)
 static int reg (FILE *file, GLuint _reg_file, GLuint _reg_nr)
 {
     int        err = 0;
+
+    /* Clear the Compr4 instruction compression bit. */
+    if (_reg_file == BRW_MESSAGE_REGISTER_FILE)
+       _reg_nr &= ~(1 << 7);
+
     if (_reg_file == BRW_ARCHITECTURE_REGISTER_FILE) {
        switch (_reg_nr & 0xf0) {
        case BRW_ARF_NULL:
@@ -476,7 +497,8 @@ static int dest (FILE *file, struct brw_instruction *inst)
            if (err == -1)
                return 0;
            if (inst->bits1.da1.dest_subreg_nr)
-               format (file, ".%d", inst->bits1.da1.dest_subreg_nr);
+               format (file, ".%d", inst->bits1.da1.dest_subreg_nr /
+                                    reg_type_size[inst->bits1.da1.dest_reg_type]);
            format (file, "<%d>", inst->bits1.da1.dest_horiz_stride);
            err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.da1.dest_reg_type, NULL);
        }
@@ -484,7 +506,8 @@ static int dest (FILE *file, struct brw_instruction *inst)
        {
            string (file, "g[a0");
            if (inst->bits1.ia1.dest_subreg_nr)
-               format (file, ".%d", inst->bits1.ia1.dest_subreg_nr);
+               format (file, ".%d", inst->bits1.ia1.dest_subreg_nr /
+                                       reg_type_size[inst->bits1.ia1.dest_reg_type]);
            if (inst->bits1.ia1.dest_indirect_offset)
                format (file, " %d", inst->bits1.ia1.dest_indirect_offset);
            string (file, "]");
@@ -500,7 +523,8 @@ static int dest (FILE *file, struct brw_instruction *inst)
            if (err == -1)
                return 0;
            if (inst->bits1.da16.dest_subreg_nr)
-               format (file, ".%d", inst->bits1.da16.dest_subreg_nr);
+               format (file, ".%d", inst->bits1.da16.dest_subreg_nr /
+                                    reg_type_size[inst->bits1.da16.dest_reg_type]);
            string (file, "<1>");
            err |= control (file, "writemask", writemask, inst->bits1.da16.dest_writemask, NULL);
            err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.da16.dest_reg_type, NULL);
@@ -541,7 +565,7 @@ static int src_da1 (FILE *file, GLuint type, GLuint _reg_file,
     if (err == -1)
        return 0;
     if (sub_reg_num)
-       format (file, ".%d", sub_reg_num);
+       format (file, ".%d", sub_reg_num / reg_type_size[type]); /* use formal style like spec */
     src_align1_region (file, _vert_stride, _width, _horiz_stride);
     err |= control (file, "src reg encoding", reg_encoding, type, NULL);
     return err;
@@ -595,11 +619,12 @@ static int src_da16 (FILE *file,
     if (err == -1)
        return 0;
     if (_subreg_nr)
-       format (file, ".%d", _subreg_nr);
+       /* bit4 for subreg number byte addressing. Make this same meaning as
+          in da1 case, so output looks consistent. */
+       format (file, ".%d", 16 / reg_type_size[_reg_type]);
     string (file, "<");
     err |= control (file, "vert stride", vert_stride, _vert_stride, NULL);
     string (file, ",4,1>");
-    err |= control (file, "src da16 reg type", reg_encoding, _reg_type, NULL);
     /*
      * Three kinds of swizzle display:
      *  identity - nothing printed
@@ -863,12 +888,25 @@ int brw_disasm (FILE *file, struct brw_instruction *inst, int gen)
                            inst->bits3.math.precision, &space);
            break;
        case BRW_MESSAGE_TARGET_SAMPLER:
-           format (file, " (%d, %d, ",
-                   inst->bits3.sampler.binding_table_index,
-                   inst->bits3.sampler.sampler);
-           err |= control (file, "sampler target format", sampler_target_format,
-                           inst->bits3.sampler.return_format, NULL);
-           string (file, ")");
+           if (gen >= 5) {
+               format (file, " (%d, %d, %d, %d)",
+                       inst->bits3.sampler_gen5.binding_table_index,
+                       inst->bits3.sampler_gen5.sampler,
+                       inst->bits3.sampler_gen5.msg_type,
+                       inst->bits3.sampler_gen5.simd_mode);
+           } else if (0 /* FINISHME: is_g4x */) {
+               format (file, " (%d, %d)",
+                       inst->bits3.sampler_g4x.binding_table_index,
+                       inst->bits3.sampler_g4x.sampler);
+           } else {
+               format (file, " (%d, %d, ",
+                       inst->bits3.sampler.binding_table_index,
+                       inst->bits3.sampler.sampler);
+               err |= control (file, "sampler target format",
+                               sampler_target_format,
+                               inst->bits3.sampler.return_format, NULL);
+               string (file, ")");
+           }
            break;
        case BRW_MESSAGE_TARGET_DATAPORT_READ:
            if (gen >= 6) {
@@ -929,6 +967,11 @@ int brw_disasm (FILE *file, struct brw_instruction *inst, int gen)
                            inst->bits3.urb.used, &space);
            err |= control (file, "urb complete", urb_complete,
                            inst->bits3.urb.complete, &space);
+           if (gen >= 5) {
+               format (file, " mlen %d, rlen %d\n",
+                       inst->bits3.urb_gen5.msg_length,
+                       inst->bits3.urb_gen5.response_length);
+           }
            break;
        case BRW_MESSAGE_TARGET_THREAD_SPAWNER:
            break;
@@ -957,8 +1000,19 @@ int brw_disasm (FILE *file, struct brw_instruction *inst, int gen)
        err |= control(file, "access mode", access_mode, inst->header.access_mode, &space);
        err |= control (file, "mask control", mask_ctrl, inst->header.mask_control, &space);
        err |= control (file, "dependency control", dep_ctrl, inst->header.dependency_control, &space);
-       err |= control (file, "compression control", compr_ctrl, inst->header.compression_control, &space);
+
+       if (inst->header.compression_control == BRW_COMPRESSION_COMPRESSED &&
+           opcode[inst->header.opcode].ndst > 0 &&
+           inst->bits1.da1.dest_reg_file == BRW_MESSAGE_REGISTER_FILE &&
+           inst->bits1.da1.dest_reg_nr & (1 << 7)) {
+          format (file, " compr4");
+       } else {
+          err |= control (file, "compression control", compr_ctrl,
+                          inst->header.compression_control, &space);
+       }
        err |= control (file, "thread control", thread_ctrl, inst->header.thread_control, &space);
+       if (gen >= 6)
+           err |= control (file, "acc write control", accwr, inst->header.acc_wr_control, &space);
        if (inst->header.opcode == BRW_OPCODE_SEND)
            err |= control (file, "end of thread", end_of_thread,
                            inst->bits3.generic.end_of_thread, &space);
index f07aab86e9048120f92aa156a78c345a98579c96..249e874ab1a7476be5064789fc46a7a1dbd5a294 100644 (file)
@@ -476,7 +476,7 @@ static void brw_emit_vertices(struct brw_context *brw)
    if (brw->vb.nr_enabled == 0) {
       BEGIN_BATCH(3);
       OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | 1);
-      if (IS_GEN6(intel->intelScreen->deviceID)) {
+      if (intel->gen >= 6) {
         OUT_BATCH((0 << GEN6_VE0_INDEX_SHIFT) |
                   GEN6_VE0_VALID |
                   (BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_VE0_FORMAT_SHIFT) |
@@ -553,7 +553,7 @@ static void brw_emit_vertices(struct brw_context *brw)
         break;
       }
 
-      if (IS_GEN6(intel->intelScreen->deviceID)) {
+      if (intel->gen >= 6) {
         OUT_BATCH((i << GEN6_VE0_INDEX_SHIFT) |
                   GEN6_VE0_VALID |
                   (format << BRW_VE0_FORMAT_SHIFT) |
index 4e7c1226ad4dd8b26b1c1a572f85b14bfe01dd36..2ff39e8e64a4eec3290bf48acda433ec4425f795 100644 (file)
@@ -85,6 +85,12 @@ void brw_set_saturate( struct brw_compile *p, GLuint value )
    p->current->header.saturate = value;
 }
 
+void brw_set_acc_write_control(struct brw_compile *p, GLuint value)
+{
+   if (p->brw->intel.gen >= 6)
+      p->current->header.acc_wr_control = value;
+}
+
 void brw_push_insn_state( struct brw_compile *p )
 {
    assert(p->current != &p->stack[BRW_EU_MAX_INSN_STACK-1]);
index ffdddd0a38875fb00fb9db2b2817ad8491380777..c63db164609c7ce9a90ecca331366a4da0965cdd 100644 (file)
@@ -633,6 +633,8 @@ static INLINE struct brw_reg brw_swizzle( struct brw_reg reg,
                                            GLuint z,
                                            GLuint w)
 {
+   assert(reg.file != BRW_IMMEDIATE_VALUE);
+
    reg.dw1.bits.swizzle = BRW_SWIZZLE4(BRW_GET_SWZ(reg.dw1.bits.swizzle, x),
                                       BRW_GET_SWZ(reg.dw1.bits.swizzle, y),
                                       BRW_GET_SWZ(reg.dw1.bits.swizzle, z),
@@ -650,6 +652,7 @@ static INLINE struct brw_reg brw_swizzle1( struct brw_reg reg,
 static INLINE struct brw_reg brw_writemask( struct brw_reg reg,
                                              GLuint mask )
 {
+   assert(reg.file != BRW_IMMEDIATE_VALUE);
    reg.dw1.bits.writemask &= mask;
    return reg;
 }
@@ -657,6 +660,7 @@ static INLINE struct brw_reg brw_writemask( struct brw_reg reg,
 static INLINE struct brw_reg brw_set_writemask( struct brw_reg reg,
                                                  GLuint mask )
 {
+   assert(reg.file != BRW_IMMEDIATE_VALUE);
    reg.dw1.bits.writemask = mask;
    return reg;
 }
@@ -766,6 +770,7 @@ void brw_set_compression_control( struct brw_compile *p, GLboolean control );
 void brw_set_predicate_control_flag_value( struct brw_compile *p, GLuint value );
 void brw_set_predicate_control( struct brw_compile *p, GLuint pc );
 void brw_set_conditionalmod( struct brw_compile *p, GLuint conditional );
+void brw_set_acc_write_control(struct brw_compile *p, GLuint value);
 
 void brw_init_compile( struct brw_context *, struct brw_compile *p );
 const GLuint *brw_get_program( struct brw_compile *p, GLuint *sz );
@@ -840,6 +845,7 @@ void brw_ff_sync(struct brw_compile *p,
                   GLboolean eot);
 
 void brw_fb_WRITE(struct brw_compile *p,
+                 int dispatch_width,
                   struct brw_reg dest,
                   GLuint msg_reg_nr,
                   struct brw_reg src0,
@@ -925,8 +931,8 @@ struct brw_instruction *brw_DO(struct brw_compile *p,
 struct brw_instruction *brw_WHILE(struct brw_compile *p, 
               struct brw_instruction *patch_insn);
 
-struct brw_instruction *brw_BREAK(struct brw_compile *p);
-struct brw_instruction *brw_CONT(struct brw_compile *p);
+struct brw_instruction *brw_BREAK(struct brw_compile *p, int pop_count);
+struct brw_instruction *brw_CONT(struct brw_compile *p, int pop_count);
 /* Forward jumps:
  */
 void brw_land_fwd_jump(struct brw_compile *p, 
index 0d5d17f501d45692b5b0672fc267114548dd9bd7..0906150613b3e39f09f28cc69bad66687bf0b4d6 100644 (file)
@@ -75,6 +75,8 @@ static void brw_set_dest( struct brw_instruction *insn,
       else {
         insn->bits1.da16.dest_subreg_nr = dest.subnr / 16;
         insn->bits1.da16.dest_writemask = dest.dw1.bits.writemask;
+        /* even ignored in da16, still need to set as '01' */
+        insn->bits1.da16.dest_horiz_stride = 1;
       }
    }
    else {
@@ -90,6 +92,8 @@ static void brw_set_dest( struct brw_instruction *insn,
       }
       else {
         insn->bits1.ia16.dest_indirect_offset = dest.dw1.bits.indirect_offset;
+        /* even ignored in da16, still need to set as '01' */
+        insn->bits1.ia16.dest_horiz_stride = 1;
       }
    }
 
@@ -368,9 +372,23 @@ static void brw_set_dp_write_message( struct brw_context *brw,
                                      GLuint send_commit_msg)
 {
    struct intel_context *intel = &brw->intel;
-   brw_set_src1(insn, brw_imm_d(0));
+   brw_set_src1(insn, brw_imm_ud(0));
 
-   if (intel->gen == 5) {
+   if (intel->gen >= 6) {
+       insn->bits3.dp_render_cache.binding_table_index = binding_table_index;
+       insn->bits3.dp_render_cache.msg_control = msg_control;
+       insn->bits3.dp_render_cache.pixel_scoreboard_clear = pixel_scoreboard_clear;
+       insn->bits3.dp_render_cache.msg_type = msg_type;
+       insn->bits3.dp_render_cache.send_commit_msg = send_commit_msg;
+       insn->bits3.dp_render_cache.header_present = 0; /* XXX */
+       insn->bits3.dp_render_cache.response_length = response_length;
+       insn->bits3.dp_render_cache.msg_length = msg_length;
+       insn->bits3.dp_render_cache.end_of_thread = end_of_thread;
+       insn->header.destreg__conditionalmod = BRW_MESSAGE_TARGET_DATAPORT_WRITE;
+       /* XXX really need below? */
+       insn->bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_DATAPORT_WRITE;
+       insn->bits2.send_gen5.end_of_thread = end_of_thread;
+   } else if (intel->gen == 5) {
        insn->bits3.dp_write_gen5.binding_table_index = binding_table_index;
        insn->bits3.dp_write_gen5.msg_control = msg_control;
        insn->bits3.dp_write_gen5.pixel_scoreboard_clear = pixel_scoreboard_clear;
@@ -759,7 +777,7 @@ void brw_ENDIF(struct brw_compile *p,
    }
 }
 
-struct brw_instruction *brw_BREAK(struct brw_compile *p)
+struct brw_instruction *brw_BREAK(struct brw_compile *p, int pop_count)
 {
    struct brw_instruction *insn;
    insn = next_insn(p, BRW_OPCODE_BREAK);
@@ -770,10 +788,11 @@ struct brw_instruction *brw_BREAK(struct brw_compile *p)
    insn->header.execution_size = BRW_EXECUTE_8;
    /* insn->header.mask_control = BRW_MASK_DISABLE; */
    insn->bits3.if_else.pad0 = 0;
+   insn->bits3.if_else.pop_count = pop_count;
    return insn;
 }
 
-struct brw_instruction *brw_CONT(struct brw_compile *p)
+struct brw_instruction *brw_CONT(struct brw_compile *p, int pop_count)
 {
    struct brw_instruction *insn;
    insn = next_insn(p, BRW_OPCODE_CONTINUE);
@@ -784,6 +803,7 @@ struct brw_instruction *brw_CONT(struct brw_compile *p)
    insn->header.execution_size = BRW_EXECUTE_8;
    /* insn->header.mask_control = BRW_MASK_DISABLE; */
    insn->bits3.if_else.pad0 = 0;
+   insn->bits3.if_else.pop_count = pop_count;
    return insn;
 }
 
@@ -1332,6 +1352,7 @@ void brw_dp_READ_4_vs_relative(struct brw_compile *p,
 
 
 void brw_fb_WRITE(struct brw_compile *p,
+                 int dispatch_width,
                   struct brw_reg dest,
                   GLuint msg_reg_nr,
                   struct brw_reg src0,
@@ -1340,22 +1361,40 @@ void brw_fb_WRITE(struct brw_compile *p,
                   GLuint response_length,
                   GLboolean eot)
 {
-   struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
-   
+   struct intel_context *intel = &p->brw->intel;
+   struct brw_instruction *insn;
+   GLuint msg_control, msg_type;
+
+   insn = next_insn(p, BRW_OPCODE_SEND);
    insn->header.predicate_control = 0; /* XXX */
-   insn->header.compression_control = BRW_COMPRESSION_NONE; 
-   insn->header.destreg__conditionalmod = msg_reg_nr;
-  
+   insn->header.compression_control = BRW_COMPRESSION_NONE;
+
+   if (intel->gen >= 6) {
+       /* headerless version, just submit color payload */
+       src0 = brw_message_reg(msg_reg_nr);
+
+       msg_type = BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE_GEN6;
+   } else {
+      insn->header.destreg__conditionalmod = msg_reg_nr;
+
+      msg_type = BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE;
+   }
+
+   if (dispatch_width == 16)
+      msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE;
+   else
+      msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01;
+
    brw_set_dest(insn, dest);
    brw_set_src0(insn, src0);
    brw_set_dp_write_message(p->brw,
                            insn,
                            binding_table_index,
-                           BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE, /* msg_control */
-                           BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE, /* msg_type */
+                           msg_control,
+                           msg_type,
                            msg_length,
                            1,  /* pixel scoreboard */
-                           response_length, 
+                           response_length,
                            eot,
                            0 /* send_commit_msg */);
 }
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
new file mode 100644 (file)
index 0000000..34c5d52
--- /dev/null
@@ -0,0 +1,1924 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+extern "C" {
+
+#include <sys/types.h>
+
+#include "main/macros.h"
+#include "main/shaderobj.h"
+#include "program/prog_parameter.h"
+#include "program/prog_print.h"
+#include "program/prog_optimize.h"
+#include "program/hash_table.h"
+#include "brw_context.h"
+#include "brw_eu.h"
+#include "brw_wm.h"
+#include "talloc.h"
+}
+#include "../glsl/glsl_types.h"
+#include "../glsl/ir_optimization.h"
+#include "../glsl/ir_print_visitor.h"
+
+enum register_file {
+   ARF = BRW_ARCHITECTURE_REGISTER_FILE,
+   GRF = BRW_GENERAL_REGISTER_FILE,
+   MRF = BRW_MESSAGE_REGISTER_FILE,
+   IMM = BRW_IMMEDIATE_VALUE,
+   FIXED_HW_REG, /* a struct brw_reg */
+   UNIFORM, /* prog_data->params[hw_reg] */
+   BAD_FILE
+};
+
+enum fs_opcodes {
+   FS_OPCODE_FB_WRITE = 256,
+   FS_OPCODE_RCP,
+   FS_OPCODE_RSQ,
+   FS_OPCODE_SQRT,
+   FS_OPCODE_EXP2,
+   FS_OPCODE_LOG2,
+   FS_OPCODE_POW,
+   FS_OPCODE_SIN,
+   FS_OPCODE_COS,
+   FS_OPCODE_DDX,
+   FS_OPCODE_DDY,
+   FS_OPCODE_LINTERP,
+   FS_OPCODE_TEX,
+   FS_OPCODE_TXB,
+   FS_OPCODE_TXL,
+   FS_OPCODE_DISCARD,
+};
+
+static int using_new_fs = -1;
+
+struct gl_shader *
+brw_new_shader(GLcontext *ctx, GLuint name, GLuint type)
+{
+   struct brw_shader *shader;
+
+   shader = talloc_zero(NULL, struct brw_shader);
+   if (shader) {
+      shader->base.Type = type;
+      shader->base.Name = name;
+      _mesa_init_shader(ctx, &shader->base);
+   }
+
+   return &shader->base;
+}
+
+struct gl_shader_program *
+brw_new_shader_program(GLcontext *ctx, GLuint name)
+{
+   struct brw_shader_program *prog;
+   prog = talloc_zero(NULL, struct brw_shader_program);
+   if (prog) {
+      prog->base.Name = name;
+      _mesa_init_shader_program(ctx, &prog->base);
+   }
+   return &prog->base;
+}
+
+GLboolean
+brw_compile_shader(GLcontext *ctx, struct gl_shader *shader)
+{
+   if (!_mesa_ir_compile_shader(ctx, shader))
+      return GL_FALSE;
+
+   return GL_TRUE;
+}
+
+GLboolean
+brw_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
+{
+   if (using_new_fs == -1)
+      using_new_fs = getenv("INTEL_NEW_FS") != NULL;
+
+   for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+      struct brw_shader *shader = (struct brw_shader *)prog->_LinkedShaders[i];
+
+      if (using_new_fs && shader->base.Type == GL_FRAGMENT_SHADER) {
+        void *mem_ctx = talloc_new(NULL);
+        bool progress;
+
+        if (shader->ir)
+           talloc_free(shader->ir);
+        shader->ir = new(shader) exec_list;
+        clone_ir_list(mem_ctx, shader->ir, shader->base.ir);
+
+        do_mat_op_to_vec(shader->ir);
+        do_mod_to_fract(shader->ir);
+        do_div_to_mul_rcp(shader->ir);
+        do_sub_to_add_neg(shader->ir);
+        do_explog_to_explog2(shader->ir);
+
+        brw_do_channel_expressions(shader->ir);
+        brw_do_vector_splitting(shader->ir);
+
+        do {
+           progress = false;
+
+           progress = do_common_optimization(shader->ir, true) || progress;
+        } while (progress);
+
+        validate_ir_tree(shader->ir);
+
+        reparent_ir(shader->ir, shader->ir);
+        talloc_free(mem_ctx);
+      }
+   }
+
+   if (!_mesa_ir_link_shader(ctx, prog))
+      return GL_FALSE;
+
+   return GL_TRUE;
+}
+
+static int
+type_size(const struct glsl_type *type)
+{
+   unsigned int size, i;
+
+   switch (type->base_type) {
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_FLOAT:
+   case GLSL_TYPE_BOOL:
+      return type->components();
+   case GLSL_TYPE_ARRAY:
+      /* FINISHME: uniform/varying arrays. */
+      return type_size(type->fields.array) * type->length;
+   case GLSL_TYPE_STRUCT:
+      size = 0;
+      for (i = 0; i < type->length; i++) {
+        size += type_size(type->fields.structure[i].type);
+      }
+      return size;
+   case GLSL_TYPE_SAMPLER:
+      /* Samplers take up no register space, since they're baked in at
+       * link time.
+       */
+      return 0;
+   default:
+      assert(!"not reached");
+      return 0;
+   }
+}
+
+class fs_reg {
+public:
+   /* Callers of this talloc-based new need not call delete. It's
+    * easier to just talloc_free 'ctx' (or any of its ancestors). */
+   static void* operator new(size_t size, void *ctx)
+   {
+      void *node;
+
+      node = talloc_size(ctx, size);
+      assert(node != NULL);
+
+      return node;
+   }
+
+   /** Generic unset register constructor. */
+   fs_reg()
+   {
+      this->file = BAD_FILE;
+      this->reg = 0;
+      this->reg_offset = 0;
+      this->hw_reg = -1;
+      this->negate = 0;
+      this->abs = 0;
+   }
+
+   /** Immediate value constructor. */
+   fs_reg(float f)
+   {
+      this->file = IMM;
+      this->reg = 0;
+      this->hw_reg = 0;
+      this->type = BRW_REGISTER_TYPE_F;
+      this->imm.f = f;
+      this->negate = 0;
+      this->abs = 0;
+   }
+
+   /** Immediate value constructor. */
+   fs_reg(int32_t i)
+   {
+      this->file = IMM;
+      this->reg = 0;
+      this->hw_reg = 0;
+      this->type = BRW_REGISTER_TYPE_D;
+      this->imm.i = i;
+      this->negate = 0;
+      this->abs = 0;
+   }
+
+   /** Immediate value constructor. */
+   fs_reg(uint32_t u)
+   {
+      this->file = IMM;
+      this->reg = 0;
+      this->hw_reg = 0;
+      this->type = BRW_REGISTER_TYPE_UD;
+      this->imm.u = u;
+      this->negate = 0;
+      this->abs = 0;
+   }
+
+   /** Fixed brw_reg Immediate value constructor. */
+   fs_reg(struct brw_reg fixed_hw_reg)
+   {
+      this->file = FIXED_HW_REG;
+      this->fixed_hw_reg = fixed_hw_reg;
+      this->reg = 0;
+      this->hw_reg = 0;
+      this->type = fixed_hw_reg.type;
+      this->negate = 0;
+      this->abs = 0;
+   }
+
+   fs_reg(enum register_file file, int hw_reg);
+   fs_reg(class fs_visitor *v, const struct glsl_type *type);
+
+   /** Register file: ARF, GRF, MRF, IMM. */
+   enum register_file file;
+   /** Abstract register number.  0 = fixed hw reg */
+   int reg;
+   /** Offset within the abstract register. */
+   int reg_offset;
+   /** HW register number.  Generally unset until register allocation. */
+   int hw_reg;
+   /** Register type.  BRW_REGISTER_TYPE_* */
+   int type;
+   bool negate;
+   bool abs;
+   struct brw_reg fixed_hw_reg;
+
+   /** Value for file == BRW_IMMMEDIATE_FILE */
+   union {
+      int32_t i;
+      uint32_t u;
+      float f;
+   } imm;
+};
+
+static const fs_reg reg_undef;
+static const fs_reg reg_null(ARF, BRW_ARF_NULL);
+
+class fs_inst : public exec_node {
+public:
+   /* Callers of this talloc-based new need not call delete. It's
+    * easier to just talloc_free 'ctx' (or any of its ancestors). */
+   static void* operator new(size_t size, void *ctx)
+   {
+      void *node;
+
+      node = talloc_zero_size(ctx, size);
+      assert(node != NULL);
+
+      return node;
+   }
+
+   void init()
+   {
+      this->opcode = BRW_OPCODE_NOP;
+      this->saturate = false;
+      this->conditional_mod = BRW_CONDITIONAL_NONE;
+      this->predicated = false;
+      this->sampler = 0;
+      this->shadow_compare = false;
+   }
+
+   fs_inst()
+   {
+      init();
+   }
+
+   fs_inst(int opcode)
+   {
+      init();
+      this->opcode = opcode;
+   }
+
+   fs_inst(int opcode, fs_reg dst, fs_reg src0)
+   {
+      init();
+      this->opcode = opcode;
+      this->dst = dst;
+      this->src[0] = src0;
+   }
+
+   fs_inst(int opcode, fs_reg dst, fs_reg src0, fs_reg src1)
+   {
+      init();
+      this->opcode = opcode;
+      this->dst = dst;
+      this->src[0] = src0;
+      this->src[1] = src1;
+   }
+
+   fs_inst(int opcode, fs_reg dst, fs_reg src0, fs_reg src1, fs_reg src2)
+   {
+      init();
+      this->opcode = opcode;
+      this->dst = dst;
+      this->src[0] = src0;
+      this->src[1] = src1;
+      this->src[2] = src2;
+   }
+
+   int opcode; /* BRW_OPCODE_* or FS_OPCODE_* */
+   fs_reg dst;
+   fs_reg src[3];
+   bool saturate;
+   bool predicated;
+   int conditional_mod; /**< BRW_CONDITIONAL_* */
+
+   int mlen; /** SEND message length */
+   int sampler;
+   bool shadow_compare;
+
+   /** @{
+    * Annotation for the generated IR.  One of the two can be set.
+    */
+   ir_instruction *ir;
+   const char *annotation;
+   /** @} */
+};
+
+class fs_visitor : public ir_visitor
+{
+public:
+
+   fs_visitor(struct brw_wm_compile *c, struct brw_shader *shader)
+   {
+      this->c = c;
+      this->p = &c->func;
+      this->brw = p->brw;
+      this->intel = &brw->intel;
+      this->ctx = &intel->ctx;
+      this->mem_ctx = talloc_new(NULL);
+      this->shader = shader;
+      this->fail = false;
+      this->next_abstract_grf = 1;
+      this->variable_ht = hash_table_ctor(0,
+                                         hash_table_pointer_hash,
+                                         hash_table_pointer_compare);
+
+      this->frag_color = NULL;
+      this->frag_data = NULL;
+      this->frag_depth = NULL;
+      this->first_non_payload_grf = 0;
+
+      this->current_annotation = NULL;
+      this->annotation_string = NULL;
+      this->annotation_ir = NULL;
+   }
+   ~fs_visitor()
+   {
+      talloc_free(this->mem_ctx);
+      hash_table_dtor(this->variable_ht);
+   }
+
+   fs_reg *variable_storage(ir_variable *var);
+
+   void visit(ir_variable *ir);
+   void visit(ir_assignment *ir);
+   void visit(ir_dereference_variable *ir);
+   void visit(ir_dereference_record *ir);
+   void visit(ir_dereference_array *ir);
+   void visit(ir_expression *ir);
+   void visit(ir_texture *ir);
+   void visit(ir_if *ir);
+   void visit(ir_constant *ir);
+   void visit(ir_swizzle *ir);
+   void visit(ir_return *ir);
+   void visit(ir_loop *ir);
+   void visit(ir_loop_jump *ir);
+   void visit(ir_discard *ir);
+   void visit(ir_call *ir);
+   void visit(ir_function *ir);
+   void visit(ir_function_signature *ir);
+
+   fs_inst *emit(fs_inst inst);
+   void assign_curb_setup();
+   void assign_urb_setup();
+   void assign_regs();
+   void generate_code();
+   void generate_fb_write(fs_inst *inst);
+   void generate_linterp(fs_inst *inst, struct brw_reg dst,
+                        struct brw_reg *src);
+   void generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src);
+   void generate_math(fs_inst *inst, struct brw_reg dst, struct brw_reg *src);
+   void generate_discard(fs_inst *inst);
+
+   void emit_dummy_fs();
+   void emit_interpolation();
+   void emit_pinterp(int location);
+   void emit_fb_writes();
+
+   struct brw_reg interp_reg(int location, int channel);
+
+   struct brw_context *brw;
+   struct intel_context *intel;
+   GLcontext *ctx;
+   struct brw_wm_compile *c;
+   struct brw_compile *p;
+   struct brw_shader *shader;
+   void *mem_ctx;
+   exec_list instructions;
+   int next_abstract_grf;
+   struct hash_table *variable_ht;
+   ir_variable *frag_color, *frag_data, *frag_depth;
+   int first_non_payload_grf;
+
+   /** @{ debug annotation info */
+   const char *current_annotation;
+   ir_instruction *base_ir;
+   const char **annotation_string;
+   ir_instruction **annotation_ir;
+   /** @} */
+
+   bool fail;
+
+   /* Result of last visit() method. */
+   fs_reg result;
+
+   fs_reg pixel_x;
+   fs_reg pixel_y;
+   fs_reg pixel_w;
+   fs_reg delta_x;
+   fs_reg delta_y;
+   fs_reg interp_attrs[64];
+
+   int grf_used;
+
+};
+
+/** Fixed HW reg constructor. */
+fs_reg::fs_reg(enum register_file file, int hw_reg)
+{
+   this->file = file;
+   this->reg = 0;
+   this->reg_offset = 0;
+   this->hw_reg = hw_reg;
+   this->type = BRW_REGISTER_TYPE_F;
+   this->negate = 0;
+   this->abs = 0;
+}
+
+/** Automatic reg constructor. */
+fs_reg::fs_reg(class fs_visitor *v, const struct glsl_type *type)
+{
+   this->file = GRF;
+   this->reg = v->next_abstract_grf;
+   this->reg_offset = 0;
+   v->next_abstract_grf += type_size(type);
+   this->hw_reg = -1;
+   this->negate = 0;
+   this->abs = 0;
+
+   switch (type->base_type) {
+   case GLSL_TYPE_FLOAT:
+      this->type = BRW_REGISTER_TYPE_F;
+      break;
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_BOOL:
+      this->type = BRW_REGISTER_TYPE_D;
+      break;
+   case GLSL_TYPE_UINT:
+      this->type = BRW_REGISTER_TYPE_UD;
+      break;
+   default:
+      assert(!"not reached");
+      this->type =  BRW_REGISTER_TYPE_F;
+      break;
+   }
+}
+
+fs_reg *
+fs_visitor::variable_storage(ir_variable *var)
+{
+   return (fs_reg *)hash_table_find(this->variable_ht, var);
+}
+
+void
+fs_visitor::visit(ir_variable *ir)
+{
+   fs_reg *reg = NULL;
+
+   if (strcmp(ir->name, "gl_FragColor") == 0) {
+      this->frag_color = ir;
+   } else if (strcmp(ir->name, "gl_FragData") == 0) {
+      this->frag_data = ir;
+   } else if (strcmp(ir->name, "gl_FragDepth") == 0) {
+      this->frag_depth = ir;
+      assert(!"FINISHME: this hangs currently.");
+   }
+
+   if (ir->mode == ir_var_in) {
+      reg = &this->interp_attrs[ir->location];
+   }
+
+   if (ir->mode == ir_var_uniform) {
+      const float *vec_values;
+      int param_index = c->prog_data.nr_params;
+
+      /* FINISHME: This is wildly incomplete. */
+      assert(ir->type->is_scalar() || ir->type->is_vector() ||
+            ir->type->is_sampler());
+
+      const struct gl_program *fp = &this->brw->fragment_program->Base;
+      /* Our support for uniforms is piggy-backed on the struct
+       * gl_fragment_program, because that's where the values actually
+       * get stored, rather than in some global gl_shader_program uniform
+       * store.
+       */
+      vec_values = fp->Parameters->ParameterValues[ir->location];
+      for (unsigned int i = 0; i < ir->type->vector_elements; i++) {
+        c->prog_data.param[c->prog_data.nr_params++] = &vec_values[i];
+      }
+
+      reg = new(this->mem_ctx) fs_reg(UNIFORM, param_index);
+   }
+
+   if (!reg)
+      reg = new(this->mem_ctx) fs_reg(this, ir->type);
+
+   hash_table_insert(this->variable_ht, reg, ir);
+}
+
+void
+fs_visitor::visit(ir_dereference_variable *ir)
+{
+   fs_reg *reg = variable_storage(ir->var);
+   this->result = *reg;
+}
+
+void
+fs_visitor::visit(ir_dereference_record *ir)
+{
+   assert(!"FINISHME");
+}
+
+void
+fs_visitor::visit(ir_dereference_array *ir)
+{
+   ir_constant *index;
+   int element_size;
+
+   ir->array->accept(this);
+   index = ir->array_index->as_constant();
+
+   if (ir->type->is_matrix()) {
+      element_size = ir->type->vector_elements;
+   } else {
+      element_size = type_size(ir->type);
+   }
+
+   if (index) {
+      assert(this->result.file == UNIFORM ||
+            (this->result.file == GRF &&
+             this->result.reg != 0));
+      this->result.reg_offset += index->value.i[0] * element_size;
+   } else {
+      assert(!"FINISHME: non-constant matrix column");
+   }
+}
+
+void
+fs_visitor::visit(ir_expression *ir)
+{
+   unsigned int operand;
+   fs_reg op[2], temp;
+   fs_reg result;
+   fs_inst *inst;
+
+   for (operand = 0; operand < ir->get_num_operands(); operand++) {
+      ir->operands[operand]->accept(this);
+      if (this->result.file == BAD_FILE) {
+        ir_print_visitor v;
+        printf("Failed to get tree for expression operand:\n");
+        ir->operands[operand]->accept(&v);
+        this->fail = true;
+      }
+      op[operand] = this->result;
+
+      /* Matrix expression operands should have been broken down to vector
+       * operations already.
+       */
+      assert(!ir->operands[operand]->type->is_matrix());
+      /* And then those vector operands should have been broken down to scalar.
+       */
+      assert(!ir->operands[operand]->type->is_vector());
+   }
+
+   /* Storage for our result.  If our result goes into an assignment, it will
+    * just get copy-propagated out, so no worries.
+    */
+   this->result = fs_reg(this, ir->type);
+
+   switch (ir->operation) {
+   case ir_unop_logic_not:
+      emit(fs_inst(BRW_OPCODE_ADD, this->result, op[0], fs_reg(-1)));
+      break;
+   case ir_unop_neg:
+      op[0].negate = ~op[0].negate;
+      this->result = op[0];
+      break;
+   case ir_unop_abs:
+      op[0].abs = true;
+      this->result = op[0];
+      break;
+   case ir_unop_sign:
+      temp = fs_reg(this, ir->type);
+
+      emit(fs_inst(BRW_OPCODE_MOV, this->result, fs_reg(0.0f)));
+
+      inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null, op[0], fs_reg(0.0f)));
+      inst->conditional_mod = BRW_CONDITIONAL_G;
+      inst = emit(fs_inst(BRW_OPCODE_MOV, this->result, fs_reg(1.0f)));
+      inst->predicated = true;
+
+      inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null, op[0], fs_reg(0.0f)));
+      inst->conditional_mod = BRW_CONDITIONAL_L;
+      inst = emit(fs_inst(BRW_OPCODE_MOV, this->result, fs_reg(-1.0f)));
+      inst->predicated = true;
+
+      break;
+   case ir_unop_rcp:
+      emit(fs_inst(FS_OPCODE_RCP, this->result, op[0]));
+      break;
+
+   case ir_unop_exp2:
+      emit(fs_inst(FS_OPCODE_EXP2, this->result, op[0]));
+      break;
+   case ir_unop_log2:
+      emit(fs_inst(FS_OPCODE_LOG2, this->result, op[0]));
+      break;
+   case ir_unop_exp:
+   case ir_unop_log:
+      assert(!"not reached: should be handled by ir_explog_to_explog2");
+      break;
+   case ir_unop_sin:
+      emit(fs_inst(FS_OPCODE_SIN, this->result, op[0]));
+      break;
+   case ir_unop_cos:
+      emit(fs_inst(FS_OPCODE_COS, this->result, op[0]));
+      break;
+
+   case ir_unop_dFdx:
+      emit(fs_inst(FS_OPCODE_DDX, this->result, op[0]));
+      break;
+   case ir_unop_dFdy:
+      emit(fs_inst(FS_OPCODE_DDY, this->result, op[0]));
+      break;
+
+   case ir_binop_add:
+      emit(fs_inst(BRW_OPCODE_ADD, this->result, op[0], op[1]));
+      break;
+   case ir_binop_sub:
+      assert(!"not reached: should be handled by ir_sub_to_add_neg");
+      break;
+
+   case ir_binop_mul:
+      emit(fs_inst(BRW_OPCODE_MUL, this->result, op[0], op[1]));
+      break;
+   case ir_binop_div:
+      assert(!"not reached: should be handled by ir_div_to_mul_rcp");
+      break;
+   case ir_binop_mod:
+      assert(!"ir_binop_mod should have been converted to b * fract(a/b)");
+      break;
+
+   case ir_binop_less:
+      inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], op[1]));
+      inst->conditional_mod = BRW_CONDITIONAL_L;
+      emit(fs_inst(BRW_OPCODE_AND, this->result, this->result, fs_reg(0x1)));
+      break;
+   case ir_binop_greater:
+      inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], op[1]));
+      inst->conditional_mod = BRW_CONDITIONAL_G;
+      emit(fs_inst(BRW_OPCODE_AND, this->result, this->result, fs_reg(0x1)));
+      break;
+   case ir_binop_lequal:
+      inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], op[1]));
+      inst->conditional_mod = BRW_CONDITIONAL_LE;
+      emit(fs_inst(BRW_OPCODE_AND, this->result, this->result, fs_reg(0x1)));
+      break;
+   case ir_binop_gequal:
+      inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], op[1]));
+      inst->conditional_mod = BRW_CONDITIONAL_GE;
+      emit(fs_inst(BRW_OPCODE_AND, this->result, this->result, fs_reg(0x1)));
+      break;
+   case ir_binop_equal:
+      inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], op[1]));
+      inst->conditional_mod = BRW_CONDITIONAL_Z;
+      emit(fs_inst(BRW_OPCODE_AND, this->result, this->result, fs_reg(0x1)));
+      break;
+   case ir_binop_nequal:
+      inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], op[1]));
+      inst->conditional_mod = BRW_CONDITIONAL_NZ;
+      emit(fs_inst(BRW_OPCODE_AND, this->result, this->result, fs_reg(0x1)));
+      break;
+
+   case ir_binop_logic_xor:
+      emit(fs_inst(BRW_OPCODE_XOR, this->result, op[0], op[1]));
+      break;
+
+   case ir_binop_logic_or:
+      emit(fs_inst(BRW_OPCODE_OR, this->result, op[0], op[1]));
+      break;
+
+   case ir_binop_logic_and:
+      emit(fs_inst(BRW_OPCODE_AND, this->result, op[0], op[1]));
+      break;
+
+   case ir_binop_dot:
+   case ir_binop_cross:
+   case ir_unop_any:
+      assert(!"not reached: should be handled by brw_channel_expressions");
+      break;
+
+   case ir_unop_sqrt:
+      emit(fs_inst(FS_OPCODE_SQRT, this->result, op[0]));
+      break;
+
+   case ir_unop_rsq:
+      emit(fs_inst(FS_OPCODE_RSQ, this->result, op[0]));
+      break;
+
+   case ir_unop_i2f:
+   case ir_unop_b2f:
+   case ir_unop_b2i:
+      emit(fs_inst(BRW_OPCODE_MOV, this->result, op[0]));
+      break;
+   case ir_unop_f2i:
+      emit(fs_inst(BRW_OPCODE_RNDZ, this->result, op[0]));
+      break;
+   case ir_unop_f2b:
+   case ir_unop_i2b:
+      inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], fs_reg(0.0f)));
+      inst->conditional_mod = BRW_CONDITIONAL_NZ;
+
+   case ir_unop_trunc:
+      emit(fs_inst(BRW_OPCODE_RNDD, this->result, op[0]));
+      break;
+   case ir_unop_ceil:
+      op[0].negate = ~op[0].negate;
+      inst = emit(fs_inst(BRW_OPCODE_RNDD, this->result, op[0]));
+      this->result.negate = true;
+      break;
+   case ir_unop_floor:
+      inst = emit(fs_inst(BRW_OPCODE_RNDD, this->result, op[0]));
+      break;
+   case ir_unop_fract:
+      inst = emit(fs_inst(BRW_OPCODE_FRC, this->result, op[0]));
+      break;
+
+   case ir_binop_min:
+      inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], op[1]));
+      inst->conditional_mod = BRW_CONDITIONAL_L;
+
+      inst = emit(fs_inst(BRW_OPCODE_SEL, this->result, op[0], op[1]));
+      inst->predicated = true;
+      break;
+   case ir_binop_max:
+      inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], op[1]));
+      inst->conditional_mod = BRW_CONDITIONAL_G;
+
+      inst = emit(fs_inst(BRW_OPCODE_SEL, this->result, op[0], op[1]));
+      inst->predicated = true;
+      break;
+
+   case ir_binop_pow:
+      inst = emit(fs_inst(FS_OPCODE_POW, this->result, op[0], op[1]));
+      break;
+
+   case ir_unop_bit_not:
+   case ir_unop_u2f:
+   case ir_binop_lshift:
+   case ir_binop_rshift:
+   case ir_binop_bit_and:
+   case ir_binop_bit_xor:
+   case ir_binop_bit_or:
+      assert(!"GLSL 1.30 features unsupported");
+      break;
+   }
+}
+
+void
+fs_visitor::visit(ir_assignment *ir)
+{
+   struct fs_reg l, r;
+   int i;
+   int write_mask;
+   fs_inst *inst;
+
+   /* FINISHME: arrays on the lhs */
+   ir->lhs->accept(this);
+   l = this->result;
+
+   ir->rhs->accept(this);
+   r = this->result;
+
+   /* FINISHME: This should really set to the correct maximal writemask for each
+    * FINISHME: component written (in the loops below).  This case can only
+    * FINISHME: occur for matrices, arrays, and structures.
+    */
+   if (ir->write_mask == 0) {
+      assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector());
+      write_mask = WRITEMASK_XYZW;
+   } else {
+      assert(ir->lhs->type->is_vector() || ir->lhs->type->is_scalar());
+      write_mask = ir->write_mask;
+   }
+
+   assert(l.file != BAD_FILE);
+   assert(r.file != BAD_FILE);
+
+   if (ir->condition) {
+      /* Get the condition bool into the predicate. */
+      ir->condition->accept(this);
+      inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, fs_reg(0)));
+      inst->conditional_mod = BRW_CONDITIONAL_NZ;
+   }
+
+   for (i = 0; i < type_size(ir->lhs->type); i++) {
+      if (i >= 4 || (write_mask & (1 << i))) {
+        inst = emit(fs_inst(BRW_OPCODE_MOV, l, r));
+        if (ir->condition)
+           inst->predicated = true;
+      }
+      l.reg_offset++;
+      r.reg_offset++;
+   }
+}
+
+void
+fs_visitor::visit(ir_texture *ir)
+{
+   int base_mrf = 2;
+   fs_inst *inst = NULL;
+   unsigned int mlen = 0;
+
+   ir->coordinate->accept(this);
+   fs_reg coordinate = this->result;
+
+   if (ir->projector) {
+      fs_reg inv_proj = fs_reg(this, glsl_type::float_type);
+
+      ir->projector->accept(this);
+      emit(fs_inst(FS_OPCODE_RCP, inv_proj, this->result));
+
+      fs_reg proj_coordinate = fs_reg(this, ir->coordinate->type);
+      for (unsigned int i = 0; i < ir->coordinate->type->vector_elements; i++) {
+        emit(fs_inst(BRW_OPCODE_MUL, proj_coordinate, coordinate, inv_proj));
+        coordinate.reg_offset++;
+        proj_coordinate.reg_offset++;
+      }
+      proj_coordinate.reg_offset = 0;
+
+      coordinate = proj_coordinate;
+   }
+
+   for (mlen = 0; mlen < ir->coordinate->type->vector_elements; mlen++) {
+      emit(fs_inst(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), coordinate));
+      coordinate.reg_offset++;
+   }
+
+   /* Pre-Ironlake, the 8-wide sampler always took u,v,r. */
+   if (intel->gen < 5)
+      mlen = 3;
+
+   if (ir->shadow_comparitor) {
+      /* For shadow comparisons, we have to supply u,v,r. */
+      mlen = 3;
+
+      ir->shadow_comparitor->accept(this);
+      emit(fs_inst(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), this->result));
+      mlen++;
+   }
+
+   /* Do we ever want to handle writemasking on texture samples?  Is it
+    * performance relevant?
+    */
+   fs_reg dst = fs_reg(this, glsl_type::vec4_type);
+
+   switch (ir->op) {
+   case ir_tex:
+      inst = emit(fs_inst(FS_OPCODE_TEX, dst, fs_reg(MRF, base_mrf)));
+      break;
+   case ir_txb:
+      ir->lod_info.bias->accept(this);
+      emit(fs_inst(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), this->result));
+      mlen++;
+
+      inst = emit(fs_inst(FS_OPCODE_TXB, dst, fs_reg(MRF, base_mrf)));
+      break;
+   case ir_txl:
+      ir->lod_info.lod->accept(this);
+      emit(fs_inst(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), this->result));
+      mlen++;
+
+      inst = emit(fs_inst(FS_OPCODE_TXL, dst, fs_reg(MRF, base_mrf)));
+      break;
+   case ir_txd:
+   case ir_txf:
+      assert(!"GLSL 1.30 features unsupported");
+      break;
+   }
+
+   this->result = dst;
+
+   if (ir->shadow_comparitor)
+      inst->shadow_compare = true;
+   inst->mlen = mlen;
+}
+
+void
+fs_visitor::visit(ir_swizzle *ir)
+{
+   ir->val->accept(this);
+   fs_reg val = this->result;
+
+   fs_reg result = fs_reg(this, ir->type);
+   this->result = result;
+
+   for (unsigned int i = 0; i < ir->type->vector_elements; i++) {
+      fs_reg channel = val;
+      int swiz = 0;
+
+      switch (i) {
+      case 0:
+        swiz = ir->mask.x;
+        break;
+      case 1:
+        swiz = ir->mask.y;
+        break;
+      case 2:
+        swiz = ir->mask.z;
+        break;
+      case 3:
+        swiz = ir->mask.w;
+        break;
+      }
+
+      channel.reg_offset += swiz;
+      emit(fs_inst(BRW_OPCODE_MOV, result, channel));
+      result.reg_offset++;
+   }
+}
+
+void
+fs_visitor::visit(ir_discard *ir)
+{
+   assert(ir->condition == NULL); /* FINISHME */
+
+   emit(fs_inst(FS_OPCODE_DISCARD));
+}
+
+void
+fs_visitor::visit(ir_constant *ir)
+{
+   fs_reg reg(this, ir->type);
+   this->result = reg;
+
+   for (unsigned int i = 0; i < ir->type->vector_elements; i++) {
+      switch (ir->type->base_type) {
+      case GLSL_TYPE_FLOAT:
+        emit(fs_inst(BRW_OPCODE_MOV, reg, fs_reg(ir->value.f[i])));
+        break;
+      case GLSL_TYPE_UINT:
+        emit(fs_inst(BRW_OPCODE_MOV, reg, fs_reg(ir->value.u[i])));
+        break;
+      case GLSL_TYPE_INT:
+        emit(fs_inst(BRW_OPCODE_MOV, reg, fs_reg(ir->value.i[i])));
+        break;
+      case GLSL_TYPE_BOOL:
+        emit(fs_inst(BRW_OPCODE_MOV, reg, fs_reg((int)ir->value.b[i])));
+        break;
+      default:
+        assert(!"Non-float/uint/int/bool constant");
+      }
+      reg.reg_offset++;
+   }
+}
+
+void
+fs_visitor::visit(ir_if *ir)
+{
+   fs_inst *inst;
+
+   /* Don't point the annotation at the if statement, because then it plus
+    * the then and else blocks get printed.
+    */
+   this->base_ir = ir->condition;
+
+   /* Generate the condition into the condition code. */
+   ir->condition->accept(this);
+   inst = emit(fs_inst(BRW_OPCODE_MOV, fs_reg(brw_null_reg()), this->result));
+   inst->conditional_mod = BRW_CONDITIONAL_NZ;
+
+   inst = emit(fs_inst(BRW_OPCODE_IF));
+   inst->predicated = true;
+
+   foreach_iter(exec_list_iterator, iter, ir->then_instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      this->base_ir = ir;
+
+      ir->accept(this);
+   }
+
+   if (!ir->else_instructions.is_empty()) {
+      emit(fs_inst(BRW_OPCODE_ELSE));
+
+      foreach_iter(exec_list_iterator, iter, ir->else_instructions) {
+        ir_instruction *ir = (ir_instruction *)iter.get();
+        this->base_ir = ir;
+
+        ir->accept(this);
+      }
+   }
+
+   emit(fs_inst(BRW_OPCODE_ENDIF));
+}
+
+void
+fs_visitor::visit(ir_loop *ir)
+{
+   assert(!ir->from);
+   assert(!ir->to);
+   assert(!ir->increment);
+   assert(!ir->counter);
+
+   emit(fs_inst(BRW_OPCODE_DO));
+
+   /* Start a safety counter.  If the user messed up their loop
+    * counting, we don't want to hang the GPU.
+    */
+   fs_reg max_iter = fs_reg(this, glsl_type::int_type);
+   emit(fs_inst(BRW_OPCODE_MOV, max_iter, fs_reg(10000)));
+
+   foreach_iter(exec_list_iterator, iter, ir->body_instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      fs_inst *inst;
+
+      this->base_ir = ir;
+      ir->accept(this);
+
+      /* Check the maximum loop iters counter. */
+      inst = emit(fs_inst(BRW_OPCODE_ADD, max_iter, max_iter, fs_reg(-1)));
+      inst->conditional_mod = BRW_CONDITIONAL_Z;
+
+      inst = emit(fs_inst(BRW_OPCODE_BREAK));
+      inst->predicated = true;
+   }
+
+   emit(fs_inst(BRW_OPCODE_WHILE));
+}
+
+void
+fs_visitor::visit(ir_loop_jump *ir)
+{
+   switch (ir->mode) {
+   case ir_loop_jump::jump_break:
+      emit(fs_inst(BRW_OPCODE_BREAK));
+      break;
+   case ir_loop_jump::jump_continue:
+      emit(fs_inst(BRW_OPCODE_CONTINUE));
+      break;
+   }
+}
+
+void
+fs_visitor::visit(ir_call *ir)
+{
+   assert(!"FINISHME");
+}
+
+void
+fs_visitor::visit(ir_return *ir)
+{
+   assert(!"FINISHME");
+}
+
+void
+fs_visitor::visit(ir_function *ir)
+{
+   /* Ignore function bodies other than main() -- we shouldn't see calls to
+    * them since they should all be inlined before we get to ir_to_mesa.
+    */
+   if (strcmp(ir->name, "main") == 0) {
+      const ir_function_signature *sig;
+      exec_list empty;
+
+      sig = ir->matching_signature(&empty);
+
+      assert(sig);
+
+      foreach_iter(exec_list_iterator, iter, sig->body) {
+        ir_instruction *ir = (ir_instruction *)iter.get();
+        this->base_ir = ir;
+
+        ir->accept(this);
+      }
+   }
+}
+
+void
+fs_visitor::visit(ir_function_signature *ir)
+{
+   assert(!"not reached");
+   (void)ir;
+}
+
+fs_inst *
+fs_visitor::emit(fs_inst inst)
+{
+   fs_inst *list_inst = new(mem_ctx) fs_inst;
+   *list_inst = inst;
+
+   list_inst->annotation = this->current_annotation;
+   list_inst->ir = this->base_ir;
+
+   this->instructions.push_tail(list_inst);
+
+   return list_inst;
+}
+
+/** Emits a dummy fragment shader consisting of magenta for bringup purposes. */
+void
+fs_visitor::emit_dummy_fs()
+{
+   /* Everyone's favorite color. */
+   emit(fs_inst(BRW_OPCODE_MOV,
+               fs_reg(MRF, 2),
+               fs_reg(1.0f)));
+   emit(fs_inst(BRW_OPCODE_MOV,
+               fs_reg(MRF, 3),
+               fs_reg(0.0f)));
+   emit(fs_inst(BRW_OPCODE_MOV,
+               fs_reg(MRF, 4),
+               fs_reg(1.0f)));
+   emit(fs_inst(BRW_OPCODE_MOV,
+               fs_reg(MRF, 5),
+               fs_reg(0.0f)));
+
+   fs_inst *write;
+   write = emit(fs_inst(FS_OPCODE_FB_WRITE,
+                       fs_reg(0),
+                       fs_reg(0)));
+}
+
+/* The register location here is relative to the start of the URB
+ * data.  It will get adjusted to be a real location before
+ * generate_code() time.
+ */
+struct brw_reg
+fs_visitor::interp_reg(int location, int channel)
+{
+   int regnr = location * 2 + channel / 2;
+   int stride = (channel & 1) * 4;
+
+   return brw_vec1_grf(regnr, stride);
+}
+
+/** Emits the interpolation for the varying inputs. */
+void
+fs_visitor::emit_interpolation()
+{
+   struct brw_reg g1_uw = retype(brw_vec1_grf(1, 0), BRW_REGISTER_TYPE_UW);
+   /* For now, the source regs for the setup URB data will be unset,
+    * since we don't know until codegen how many push constants we'll
+    * use, and therefore what the setup URB offset is.
+    */
+   fs_reg src_reg = reg_undef;
+
+   this->current_annotation = "compute pixel centers";
+   this->pixel_x = fs_reg(this, glsl_type::uint_type);
+   this->pixel_y = fs_reg(this, glsl_type::uint_type);
+   emit(fs_inst(BRW_OPCODE_ADD,
+               this->pixel_x,
+               fs_reg(stride(suboffset(g1_uw, 4), 2, 4, 0)),
+               fs_reg(brw_imm_v(0x10101010))));
+   emit(fs_inst(BRW_OPCODE_ADD,
+               this->pixel_y,
+               fs_reg(stride(suboffset(g1_uw, 5), 2, 4, 0)),
+               fs_reg(brw_imm_v(0x11001100))));
+
+   this->current_annotation = "compute pixel deltas from v0";
+   this->delta_x = fs_reg(this, glsl_type::float_type);
+   this->delta_y = fs_reg(this, glsl_type::float_type);
+   emit(fs_inst(BRW_OPCODE_ADD,
+               this->delta_x,
+               this->pixel_x,
+               fs_reg(negate(brw_vec1_grf(1, 0)))));
+   emit(fs_inst(BRW_OPCODE_ADD,
+               this->delta_y,
+               this->pixel_y,
+               fs_reg(brw_vec1_grf(1, 1))));
+
+   this->current_annotation = "compute pos.w and 1/pos.w";
+   /* Compute wpos.  Unlike many other varying inputs, we usually need it
+    * to produce 1/w, and the varying variable wouldn't show up.
+    */
+   fs_reg wpos = fs_reg(this, glsl_type::vec4_type);
+   this->interp_attrs[FRAG_ATTRIB_WPOS] = wpos;
+   emit(fs_inst(BRW_OPCODE_MOV, wpos, this->pixel_x)); /* FINISHME: ARB_fcc */
+   wpos.reg_offset++;
+   emit(fs_inst(BRW_OPCODE_MOV, wpos, this->pixel_y)); /* FINISHME: ARB_fcc */
+   wpos.reg_offset++;
+   emit(fs_inst(FS_OPCODE_LINTERP, wpos, this->delta_x, this->delta_y,
+               interp_reg(FRAG_ATTRIB_WPOS, 2)));
+   wpos.reg_offset++;
+   emit(fs_inst(FS_OPCODE_LINTERP, wpos, this->delta_x, this->delta_y,
+               interp_reg(FRAG_ATTRIB_WPOS, 3)));
+   /* Compute the pixel W value from wpos.w. */
+   this->pixel_w = fs_reg(this, glsl_type::float_type);
+   emit(fs_inst(FS_OPCODE_RCP, this->pixel_w, wpos));
+
+   /* FINISHME: gl_FrontFacing */
+
+   foreach_iter(exec_list_iterator, iter, *this->shader->ir) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      ir_variable *var = ir->as_variable();
+
+      if (!var)
+        continue;
+
+      if (var->mode != ir_var_in)
+        continue;
+
+      /* If it's already set up (WPOS), skip. */
+      if (var->location == 0)
+        continue;
+
+      this->current_annotation = talloc_asprintf(this->mem_ctx,
+                                                "interpolate %s "
+                                                "(FRAG_ATTRIB[%d])",
+                                                var->name,
+                                                var->location);
+      emit_pinterp(var->location);
+   }
+   this->current_annotation = NULL;
+}
+
+void
+fs_visitor::emit_pinterp(int location)
+{
+   fs_reg interp_attr = fs_reg(this, glsl_type::vec4_type);
+   this->interp_attrs[location] = interp_attr;
+
+   for (unsigned int i = 0; i < 4; i++) {
+      struct brw_reg interp = interp_reg(location, i);
+      emit(fs_inst(FS_OPCODE_LINTERP,
+                  interp_attr,
+                  this->delta_x,
+                  this->delta_y,
+                  fs_reg(interp)));
+      interp_attr.reg_offset++;
+   }
+   interp_attr.reg_offset -= 4;
+
+   for (unsigned int i = 0; i < 4; i++) {
+      emit(fs_inst(BRW_OPCODE_MUL,
+                  interp_attr,
+                  interp_attr,
+                  this->pixel_w));
+      interp_attr.reg_offset++;
+   }
+}
+
+void
+fs_visitor::emit_fb_writes()
+{
+   this->current_annotation = "FB write";
+
+   assert(this->frag_color || !"FINISHME: MRT");
+   fs_reg color = *(variable_storage(this->frag_color));
+
+   for (int i = 0; i < 4; i++) {
+      emit(fs_inst(BRW_OPCODE_MOV,
+                  fs_reg(MRF, 2 + i),
+                  color));
+      color.reg_offset++;
+   }
+
+   emit(fs_inst(FS_OPCODE_FB_WRITE,
+               fs_reg(0),
+               fs_reg(0)));
+
+   this->current_annotation = NULL;
+}
+
+void
+fs_visitor::generate_fb_write(fs_inst *inst)
+{
+   GLboolean eot = 1; /* FINISHME: MRT */
+   /* FINISHME: AADS */
+
+   /* Header is 2 regs, g0 and g1 are the contents. g0 will be implied
+    * move, here's g1.
+    */
+   brw_push_insn_state(p);
+   brw_set_mask_control(p, BRW_MASK_DISABLE);
+   brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+   brw_MOV(p,
+          brw_message_reg(1),
+          brw_vec8_grf(1, 0));
+   brw_pop_insn_state(p);
+
+   int nr = 2 + 4;
+
+   brw_fb_WRITE(p,
+               8, /* dispatch_width */
+               retype(vec8(brw_null_reg()), BRW_REGISTER_TYPE_UW),
+               0, /* base MRF */
+               retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW),
+               0, /* FINISHME: MRT target */
+               nr,
+               0,
+               eot);
+}
+
+void
+fs_visitor::generate_linterp(fs_inst *inst,
+                            struct brw_reg dst, struct brw_reg *src)
+{
+   struct brw_reg delta_x = src[0];
+   struct brw_reg delta_y = src[1];
+   struct brw_reg interp = src[2];
+
+   if (brw->has_pln &&
+       delta_y.nr == delta_x.nr + 1 &&
+       (intel->gen >= 6 || (delta_x.nr & 1) == 0)) {
+      brw_PLN(p, dst, interp, delta_x);
+   } else {
+      brw_LINE(p, brw_null_reg(), interp, delta_x);
+      brw_MAC(p, dst, suboffset(interp, 1), delta_y);
+   }
+}
+
+void
+fs_visitor::generate_math(fs_inst *inst,
+                         struct brw_reg dst, struct brw_reg *src)
+{
+   int op;
+
+   switch (inst->opcode) {
+   case FS_OPCODE_RCP:
+      op = BRW_MATH_FUNCTION_INV;
+      break;
+   case FS_OPCODE_RSQ:
+      op = BRW_MATH_FUNCTION_RSQ;
+      break;
+   case FS_OPCODE_SQRT:
+      op = BRW_MATH_FUNCTION_SQRT;
+      break;
+   case FS_OPCODE_EXP2:
+      op = BRW_MATH_FUNCTION_EXP;
+      break;
+   case FS_OPCODE_LOG2:
+      op = BRW_MATH_FUNCTION_LOG;
+      break;
+   case FS_OPCODE_POW:
+      op = BRW_MATH_FUNCTION_POW;
+      break;
+   case FS_OPCODE_SIN:
+      op = BRW_MATH_FUNCTION_SIN;
+      break;
+   case FS_OPCODE_COS:
+      op = BRW_MATH_FUNCTION_COS;
+      break;
+   default:
+      assert(!"not reached: unknown math function");
+      op = 0;
+      break;
+   }
+
+   if (inst->opcode == FS_OPCODE_POW) {
+      brw_MOV(p, brw_message_reg(3), src[1]);
+   }
+
+   brw_math(p, dst,
+           op,
+           inst->saturate ? BRW_MATH_SATURATE_SATURATE :
+           BRW_MATH_SATURATE_NONE,
+           2, src[0],
+           BRW_MATH_DATA_VECTOR,
+           BRW_MATH_PRECISION_FULL);
+}
+
+void
+fs_visitor::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src)
+{
+   int msg_type = -1;
+   int rlen = 4;
+
+   if (intel->gen == 5) {
+      switch (inst->opcode) {
+      case FS_OPCODE_TEX:
+        if (inst->shadow_compare) {
+           msg_type = BRW_SAMPLER_MESSAGE_SAMPLE_COMPARE_GEN5;
+        } else {
+           msg_type = BRW_SAMPLER_MESSAGE_SAMPLE_GEN5;
+        }
+        break;
+      case FS_OPCODE_TXB:
+        if (inst->shadow_compare) {
+           msg_type = BRW_SAMPLER_MESSAGE_SAMPLE_BIAS_COMPARE_GEN5;
+        } else {
+           msg_type = BRW_SAMPLER_MESSAGE_SAMPLE_BIAS_GEN5;
+        }
+        break;
+      }
+   } else {
+      switch (inst->opcode) {
+      case FS_OPCODE_TEX:
+        /* Note that G45 and older determines shadow compare and dispatch width
+         * from message length for most messages.
+         */
+        if (inst->shadow_compare) {
+           msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE;
+        } else {
+           msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE;
+        }
+      case FS_OPCODE_TXB:
+        if (inst->shadow_compare) {
+           assert(!"FINISHME: shadow compare with bias.");
+           msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS;
+        } else {
+           msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS;
+           rlen = 8;
+        }
+        break;
+      }
+   }
+   assert(msg_type != -1);
+
+   /* g0 header. */
+   src.nr--;
+
+   brw_SAMPLE(p,
+             retype(dst, BRW_REGISTER_TYPE_UW),
+             src.nr,
+             retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW),
+              SURF_INDEX_TEXTURE(inst->sampler),
+             inst->sampler,
+             WRITEMASK_XYZW,
+             msg_type,
+             rlen,
+             inst->mlen + 1,
+             0,
+             1,
+             BRW_SAMPLER_SIMD_MODE_SIMD8);
+}
+
+void
+fs_visitor::generate_discard(fs_inst *inst)
+{
+   struct brw_reg g0 = retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW);
+   brw_push_insn_state(p);
+   brw_set_mask_control(p, BRW_MASK_DISABLE);
+   brw_NOT(p, c->emit_mask_reg, brw_mask_reg(1)); /* IMASK */
+   brw_AND(p, g0, c->emit_mask_reg, g0);
+   brw_pop_insn_state(p);
+}
+
+static void
+trivial_assign_reg(int header_size, fs_reg *reg)
+{
+   if (reg->file == GRF && reg->reg != 0) {
+      reg->hw_reg = header_size + reg->reg - 1 + reg->reg_offset;
+      reg->reg = 0;
+   }
+}
+
+void
+fs_visitor::assign_curb_setup()
+{
+   c->prog_data.first_curbe_grf = c->key.nr_payload_regs;
+   c->prog_data.curb_read_length = ALIGN(c->prog_data.nr_params, 8) / 8;
+
+   /* Map the offsets in the UNIFORM file to fixed HW regs. */
+   foreach_iter(exec_list_iterator, iter, this->instructions) {
+      fs_inst *inst = (fs_inst *)iter.get();
+
+      for (unsigned int i = 0; i < 3; i++) {
+        if (inst->src[i].file == UNIFORM) {
+           int constant_nr = inst->src[i].hw_reg + inst->src[i].reg_offset;
+           struct brw_reg brw_reg = brw_vec1_grf(c->prog_data.first_curbe_grf +
+                                                 constant_nr / 8,
+                                                 constant_nr % 8);
+
+           inst->src[i].file = FIXED_HW_REG;
+           inst->src[i].fixed_hw_reg = brw_reg;
+        }
+      }
+   }
+}
+
+void
+fs_visitor::assign_urb_setup()
+{
+   int urb_start = c->prog_data.first_curbe_grf + c->prog_data.curb_read_length;
+   int interp_reg_nr[FRAG_ATTRIB_MAX];
+
+   c->prog_data.urb_read_length = 0;
+
+   /* Figure out where each of the incoming setup attributes lands. */
+   for (unsigned int i = 0; i < FRAG_ATTRIB_MAX; i++) {
+      interp_reg_nr[i] = -1;
+
+      if (i != FRAG_ATTRIB_WPOS &&
+         !(brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(i)))
+        continue;
+
+      /* Each attribute is 4 setup channels, each of which is half a reg. */
+      interp_reg_nr[i] = urb_start + c->prog_data.urb_read_length;
+      c->prog_data.urb_read_length += 2;
+   }
+
+   /* Map the register numbers for FS_OPCODE_LINTERP so that it uses
+    * the correct setup input.
+    */
+   foreach_iter(exec_list_iterator, iter, this->instructions) {
+      fs_inst *inst = (fs_inst *)iter.get();
+
+      if (inst->opcode != FS_OPCODE_LINTERP)
+        continue;
+
+      assert(inst->src[2].file == FIXED_HW_REG);
+
+      int location = inst->src[2].fixed_hw_reg.nr / 2;
+      assert(interp_reg_nr[location] != -1);
+      inst->src[2].fixed_hw_reg.nr = (interp_reg_nr[location] +
+                                     (inst->src[2].fixed_hw_reg.nr & 1));
+   }
+
+   this->first_non_payload_grf = urb_start + c->prog_data.urb_read_length;
+}
+
+void
+fs_visitor::assign_regs()
+{
+   int header_size = this->first_non_payload_grf;
+   int last_grf = 0;
+
+   /* FINISHME: trivial assignment of register numbers */
+   foreach_iter(exec_list_iterator, iter, this->instructions) {
+      fs_inst *inst = (fs_inst *)iter.get();
+
+      trivial_assign_reg(header_size, &inst->dst);
+      trivial_assign_reg(header_size, &inst->src[0]);
+      trivial_assign_reg(header_size, &inst->src[1]);
+
+      last_grf = MAX2(last_grf, inst->dst.hw_reg);
+      last_grf = MAX2(last_grf, inst->src[0].hw_reg);
+      last_grf = MAX2(last_grf, inst->src[1].hw_reg);
+   }
+
+   this->grf_used = last_grf + 1;
+}
+
+static struct brw_reg brw_reg_from_fs_reg(fs_reg *reg)
+{
+   struct brw_reg brw_reg;
+
+   switch (reg->file) {
+   case GRF:
+   case ARF:
+   case MRF:
+      brw_reg = brw_vec8_reg(reg->file,
+                           reg->hw_reg, 0);
+      brw_reg = retype(brw_reg, reg->type);
+      break;
+   case IMM:
+      switch (reg->type) {
+      case BRW_REGISTER_TYPE_F:
+        brw_reg = brw_imm_f(reg->imm.f);
+        break;
+      case BRW_REGISTER_TYPE_D:
+        brw_reg = brw_imm_d(reg->imm.i);
+        break;
+      case BRW_REGISTER_TYPE_UD:
+        brw_reg = brw_imm_ud(reg->imm.u);
+        break;
+      default:
+        assert(!"not reached");
+        break;
+      }
+      break;
+   case FIXED_HW_REG:
+      brw_reg = reg->fixed_hw_reg;
+      break;
+   case BAD_FILE:
+      /* Probably unused. */
+      brw_reg = brw_null_reg();
+      break;
+   case UNIFORM:
+      assert(!"not reached");
+      brw_reg = brw_null_reg();
+      break;
+   }
+   if (reg->abs)
+      brw_reg = brw_abs(brw_reg);
+   if (reg->negate)
+      brw_reg = negate(brw_reg);
+
+   return brw_reg;
+}
+
+void
+fs_visitor::generate_code()
+{
+   unsigned int annotation_len = 0;
+   int last_native_inst = 0;
+   struct brw_instruction *if_stack[16], *loop_stack[16];
+   int if_stack_depth = 0, loop_stack_depth = 0;
+   int if_depth_in_loop[16];
+
+   if_depth_in_loop[loop_stack_depth] = 0;
+
+   memset(&if_stack, 0, sizeof(if_stack));
+   foreach_iter(exec_list_iterator, iter, this->instructions) {
+      fs_inst *inst = (fs_inst *)iter.get();
+      struct brw_reg src[3], dst;
+
+      for (unsigned int i = 0; i < 3; i++) {
+        src[i] = brw_reg_from_fs_reg(&inst->src[i]);
+      }
+      dst = brw_reg_from_fs_reg(&inst->dst);
+
+      brw_set_conditionalmod(p, inst->conditional_mod);
+      brw_set_predicate_control(p, inst->predicated);
+
+      switch (inst->opcode) {
+      case BRW_OPCODE_MOV:
+        brw_MOV(p, dst, src[0]);
+        break;
+      case BRW_OPCODE_ADD:
+        brw_ADD(p, dst, src[0], src[1]);
+        break;
+      case BRW_OPCODE_MUL:
+        brw_MUL(p, dst, src[0], src[1]);
+        break;
+
+      case BRW_OPCODE_FRC:
+        brw_FRC(p, dst, src[0]);
+        break;
+      case BRW_OPCODE_RNDD:
+        brw_RNDD(p, dst, src[0]);
+        break;
+      case BRW_OPCODE_RNDZ:
+        brw_RNDZ(p, dst, src[0]);
+        break;
+
+      case BRW_OPCODE_AND:
+        brw_AND(p, dst, src[0], src[1]);
+        break;
+      case BRW_OPCODE_OR:
+        brw_OR(p, dst, src[0], src[1]);
+        break;
+      case BRW_OPCODE_XOR:
+        brw_XOR(p, dst, src[0], src[1]);
+        break;
+
+      case BRW_OPCODE_CMP:
+        brw_CMP(p, dst, inst->conditional_mod, src[0], src[1]);
+        break;
+      case BRW_OPCODE_SEL:
+        brw_SEL(p, dst, src[0], src[1]);
+        break;
+
+      case BRW_OPCODE_IF:
+        assert(if_stack_depth < 16);
+        if_stack[if_stack_depth] = brw_IF(p, BRW_EXECUTE_8);
+        if_stack_depth++;
+        break;
+      case BRW_OPCODE_ELSE:
+        if_stack[if_stack_depth - 1] =
+           brw_ELSE(p, if_stack[if_stack_depth - 1]);
+        break;
+      case BRW_OPCODE_ENDIF:
+        if_stack_depth--;
+        brw_ENDIF(p , if_stack[if_stack_depth]);
+        break;
+
+      case BRW_OPCODE_DO:
+        loop_stack[loop_stack_depth++] = brw_DO(p, BRW_EXECUTE_8);
+        if_depth_in_loop[loop_stack_depth] = 0;
+        break;
+
+      case BRW_OPCODE_BREAK:
+        brw_BREAK(p, if_depth_in_loop[loop_stack_depth]);
+        brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+        break;
+      case BRW_OPCODE_CONTINUE:
+        brw_CONT(p, if_depth_in_loop[loop_stack_depth]);
+        brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+        break;
+
+      case BRW_OPCODE_WHILE: {
+        struct brw_instruction *inst0, *inst1;
+        GLuint br = 1;
+
+        if (intel->gen == 5)
+           br = 2;
+
+        assert(loop_stack_depth > 0);
+        loop_stack_depth--;
+        inst0 = inst1 = brw_WHILE(p, loop_stack[loop_stack_depth]);
+        /* patch all the BREAK/CONT instructions from last BGNLOOP */
+        while (inst0 > loop_stack[loop_stack_depth]) {
+           inst0--;
+           if (inst0->header.opcode == BRW_OPCODE_BREAK &&
+               inst0->bits3.if_else.jump_count == 0) {
+              inst0->bits3.if_else.jump_count = br * (inst1 - inst0 + 1);
+           }
+           else if (inst0->header.opcode == BRW_OPCODE_CONTINUE &&
+                    inst0->bits3.if_else.jump_count == 0) {
+              inst0->bits3.if_else.jump_count = br * (inst1 - inst0);
+           }
+        }
+      }
+        break;
+
+      case FS_OPCODE_RCP:
+      case FS_OPCODE_RSQ:
+      case FS_OPCODE_SQRT:
+      case FS_OPCODE_EXP2:
+      case FS_OPCODE_LOG2:
+      case FS_OPCODE_POW:
+      case FS_OPCODE_SIN:
+      case FS_OPCODE_COS:
+        generate_math(inst, dst, src);
+        break;
+      case FS_OPCODE_LINTERP:
+        generate_linterp(inst, dst, src);
+        break;
+      case FS_OPCODE_TEX:
+      case FS_OPCODE_TXB:
+      case FS_OPCODE_TXL:
+        generate_tex(inst, dst, src[0]);
+        break;
+      case FS_OPCODE_DISCARD:
+        generate_discard(inst);
+        break;
+      case FS_OPCODE_FB_WRITE:
+        generate_fb_write(inst);
+        break;
+      default:
+        if (inst->opcode < (int)ARRAY_SIZE(brw_opcodes)) {
+           _mesa_problem(ctx, "Unsupported opcode `%s' in FS",
+                         brw_opcodes[inst->opcode].name);
+        } else {
+           _mesa_problem(ctx, "Unsupported opcode %d in FS", inst->opcode);
+        }
+        this->fail = true;
+      }
+
+      if (annotation_len < p->nr_insn) {
+        annotation_len *= 2;
+        if (annotation_len < 16)
+           annotation_len = 16;
+
+        this->annotation_string = talloc_realloc(this->mem_ctx,
+                                                 annotation_string,
+                                                 const char *,
+                                                 annotation_len);
+        this->annotation_ir = talloc_realloc(this->mem_ctx,
+                                             annotation_ir,
+                                             ir_instruction *,
+                                             annotation_len);
+      }
+
+      for (unsigned int i = last_native_inst; i < p->nr_insn; i++) {
+        this->annotation_string[i] = inst->annotation;
+        this->annotation_ir[i] = inst->ir;
+      }
+      last_native_inst = p->nr_insn;
+   }
+}
+
+GLboolean
+brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c)
+{
+   struct brw_compile *p = &c->func;
+   struct intel_context *intel = &brw->intel;
+   GLcontext *ctx = &intel->ctx;
+   struct brw_shader *shader = NULL;
+   struct gl_shader_program *prog = ctx->Shader.CurrentProgram;
+
+   if (!prog)
+      return GL_FALSE;
+
+   if (!using_new_fs)
+      return GL_FALSE;
+
+   for (unsigned int i = 0; i < prog->_NumLinkedShaders; i++) {
+      if (prog->_LinkedShaders[i]->Type == GL_FRAGMENT_SHADER) {
+        shader = (struct brw_shader *)prog->_LinkedShaders[i];
+        break;
+      }
+   }
+   if (!shader)
+      return GL_FALSE;
+
+   /* We always use 8-wide mode, at least for now.  For one, flow
+    * control only works in 8-wide.  Also, when we're fragment shader
+    * bound, we're almost always under register pressure as well, so
+    * 8-wide would save us from the performance cliff of spilling
+    * regs.
+    */
+   c->dispatch_width = 8;
+
+   if (INTEL_DEBUG & DEBUG_WM) {
+      printf("GLSL IR for native fragment shader %d:\n", prog->Name);
+      _mesa_print_ir(shader->ir, NULL);
+      printf("\n");
+   }
+
+   /* Now the main event: Visit the shader IR and generate our FS IR for it.
+    */
+   fs_visitor v(c, shader);
+
+   if (0) {
+      v.emit_dummy_fs();
+   } else {
+      v.emit_interpolation();
+
+      /* Generate FS IR for main().  (the visitor only descends into
+       * functions called "main").
+       */
+      foreach_iter(exec_list_iterator, iter, *shader->ir) {
+        ir_instruction *ir = (ir_instruction *)iter.get();
+        v.base_ir = ir;
+        ir->accept(&v);
+      }
+
+      if (v.fail)
+        return GL_FALSE;
+
+      v.emit_fb_writes();
+      v.assign_curb_setup();
+      v.assign_urb_setup();
+      v.assign_regs();
+   }
+
+   v.generate_code();
+
+   if (INTEL_DEBUG & DEBUG_WM) {
+      const char *last_annotation_string = NULL;
+      ir_instruction *last_annotation_ir = NULL;
+
+      printf("Native code for fragment shader %d:\n", prog->Name);
+      for (unsigned int i = 0; i < p->nr_insn; i++) {
+        if (last_annotation_ir != v.annotation_ir[i]) {
+           last_annotation_ir = v.annotation_ir[i];
+           if (last_annotation_ir) {
+              printf("   ");
+              last_annotation_ir->print();
+              printf("\n");
+           }
+        }
+        if (last_annotation_string != v.annotation_string[i]) {
+           last_annotation_string = v.annotation_string[i];
+           if (last_annotation_string)
+              printf("   %s\n", last_annotation_string);
+        }
+        brw_disasm(stdout, &p->store[i], intel->gen);
+      }
+      printf("\n");
+   }
+
+   c->prog_data.total_grf = v.grf_used;
+   c->prog_data.total_scratch = 0;
+
+   return GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp
new file mode 100644 (file)
index 0000000..d8d58a9
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file brw_wm_channel_expressions.cpp
+ *
+ * Breaks vector operations down into operations on each component.
+ *
+ * The 965 fragment shader receives 8 or 16 pixels at a time, so each
+ * channel of a vector is laid out as 1 or 2 8-float registers.  Each
+ * ALU operation operates on one of those channel registers.  As a
+ * result, there is no value to the 965 fragment shader in tracking
+ * "vector" expressions in the sense of GLSL fragment shaders, when
+ * doing a channel at a time may help in constant folding, algebraic
+ * simplification, and reducing the liveness of channel registers.
+ *
+ * The exception to the desire to break everything down to floats is
+ * texturing.  The texture sampler returns a writemasked masked
+ * 4/8-register sequence containing the texture values.  We don't want
+ * to dispatch to the sampler separately for each channel we need, so
+ * we do retain the vector types in that case.
+ */
+
+extern "C" {
+#include "main/core.h"
+#include "brw_wm.h"
+}
+#include "../glsl/ir.h"
+#include "../glsl/ir_expression_flattening.h"
+#include "../glsl/glsl_types.h"
+
+class ir_channel_expressions_visitor : public ir_hierarchical_visitor {
+public:
+   ir_channel_expressions_visitor()
+   {
+      this->progress = false;
+      this->mem_ctx = NULL;
+   }
+
+   ir_visitor_status visit_leave(ir_assignment *);
+
+   ir_rvalue *get_element(ir_variable *var, unsigned int element);
+   void assign(ir_assignment *ir, int elem, ir_rvalue *val);
+
+   bool progress;
+   void *mem_ctx;
+};
+
+static bool
+channel_expressions_predicate(ir_instruction *ir)
+{
+   ir_expression *expr = ir->as_expression();
+   unsigned int i;
+
+   if (!expr)
+      return false;
+
+   for (i = 0; i < expr->get_num_operands(); i++) {
+      if (expr->operands[i]->type->is_vector())
+        return true;
+   }
+
+   return false;
+}
+
+extern "C" {
+GLboolean
+brw_do_channel_expressions(exec_list *instructions)
+{
+   ir_channel_expressions_visitor v;
+
+   /* Pull out any matrix expression to a separate assignment to a
+    * temp.  This will make our handling of the breakdown to
+    * operations on the matrix's vector components much easier.
+    */
+   do_expression_flattening(instructions, channel_expressions_predicate);
+
+   visit_list_elements(&v, instructions);
+
+   return v.progress;
+}
+}
+
+ir_rvalue *
+ir_channel_expressions_visitor::get_element(ir_variable *var, unsigned int elem)
+{
+   ir_dereference *deref;
+
+   if (var->type->is_scalar())
+      return new(mem_ctx) ir_dereference_variable(var);
+
+   assert(elem < var->type->components());
+   deref = new(mem_ctx) ir_dereference_variable(var);
+   return new(mem_ctx) ir_swizzle(deref, elem, 0, 0, 0, 1);
+}
+
+void
+ir_channel_expressions_visitor::assign(ir_assignment *ir, int elem, ir_rvalue *val)
+{
+   ir_dereference *lhs = ir->lhs->clone(mem_ctx, NULL);
+   ir_assignment *assign;
+   ir_swizzle *val_swiz;
+
+   /* This assign-of-expression should have been generated by the
+    * expression flattening visitor (since we never short circit to
+    * not flatten, even for plain assignments of variables), so the
+    * writemask is always full.
+    */
+   assert(ir->write_mask == (1 << ir->lhs->type->components()) - 1);
+
+   /* Smear the float across all the channels for the masked write. */
+   val_swiz = new(mem_ctx) ir_swizzle(val, 0, 0, 0, 0,
+                                     ir->lhs->type->components());
+   assign = new(mem_ctx) ir_assignment(lhs, val_swiz, NULL, (1 << elem));
+   ir->insert_before(assign);
+}
+
+ir_visitor_status
+ir_channel_expressions_visitor::visit_leave(ir_assignment *ir)
+{
+   ir_expression *expr = ir->rhs->as_expression();
+   bool found_vector = false;
+   unsigned int i, vector_elements = 1;
+   ir_variable *op_var[2];
+
+   if (!expr)
+      return visit_continue;
+
+   if (!this->mem_ctx)
+      this->mem_ctx = talloc_parent(ir);
+
+   for (i = 0; i < expr->get_num_operands(); i++) {
+      if (expr->operands[i]->type->is_vector()) {
+        found_vector = true;
+        vector_elements = expr->operands[i]->type->vector_elements;
+        break;
+      }
+   }
+   if (!found_vector)
+      return visit_continue;
+
+   /* Store the expression operands in temps so we can use them
+    * multiple times.
+    */
+   for (i = 0; i < expr->get_num_operands(); i++) {
+      ir_assignment *assign;
+      ir_dereference *deref;
+
+      assert(!expr->operands[i]->type->is_matrix());
+
+      op_var[i] = new(mem_ctx) ir_variable(expr->operands[i]->type,
+                                          "channel_expressions",
+                                          ir_var_temporary);
+      ir->insert_before(op_var[i]);
+
+      deref = new(mem_ctx) ir_dereference_variable(op_var[i]);
+      assign = new(mem_ctx) ir_assignment(deref,
+                                         expr->operands[i],
+                                         NULL);
+      ir->insert_before(assign);
+   }
+
+   const glsl_type *element_type = glsl_type::get_instance(ir->lhs->type->base_type,
+                                                          1, 1);
+
+   /* OK, time to break down this vector operation. */
+   switch (expr->operation) {
+   case ir_unop_bit_not:
+   case ir_unop_logic_not:
+   case ir_unop_neg:
+   case ir_unop_abs:
+   case ir_unop_sign:
+   case ir_unop_rcp:
+   case ir_unop_rsq:
+   case ir_unop_sqrt:
+   case ir_unop_exp:
+   case ir_unop_log:
+   case ir_unop_exp2:
+   case ir_unop_log2:
+   case ir_unop_f2i:
+   case ir_unop_i2f:
+   case ir_unop_f2b:
+   case ir_unop_b2f:
+   case ir_unop_i2b:
+   case ir_unop_b2i:
+   case ir_unop_u2f:
+   case ir_unop_trunc:
+   case ir_unop_ceil:
+   case ir_unop_floor:
+   case ir_unop_fract:
+   case ir_unop_sin:
+   case ir_unop_cos:
+   case ir_unop_dFdx:
+   case ir_unop_dFdy:
+      for (i = 0; i < vector_elements; i++) {
+        ir_rvalue *op0 = get_element(op_var[0], i);
+
+        assign(ir, i, new(mem_ctx) ir_expression(expr->operation,
+                                                 element_type,
+                                                 op0,
+                                                 NULL));
+      }
+      break;
+
+   case ir_binop_add:
+   case ir_binop_sub:
+   case ir_binop_mul:
+   case ir_binop_div:
+   case ir_binop_mod:
+   case ir_binop_min:
+   case ir_binop_max:
+   case ir_binop_pow:
+   case ir_binop_lshift:
+   case ir_binop_rshift:
+   case ir_binop_bit_and:
+   case ir_binop_bit_xor:
+   case ir_binop_bit_or:
+      for (i = 0; i < vector_elements; i++) {
+        ir_rvalue *op0 = get_element(op_var[0], i);
+        ir_rvalue *op1 = get_element(op_var[1], i);
+
+        assign(ir, i, new(mem_ctx) ir_expression(expr->operation,
+                                                 element_type,
+                                                 op0,
+                                                 op1));
+      }
+      break;
+
+   case ir_unop_any: {
+      ir_expression *temp;
+      temp = new(mem_ctx) ir_expression(ir_binop_logic_or,
+                                       element_type,
+                                       get_element(op_var[0], 0),
+                                       get_element(op_var[0], 1));
+
+      for (i = 2; i < vector_elements; i++) {
+        temp = new(mem_ctx) ir_expression(ir_binop_logic_or,
+                                          element_type,
+                                          get_element(op_var[0], i),
+                                          temp);
+      }
+      assign(ir, 0, temp);
+      break;
+   }
+
+   case ir_binop_dot: {
+      ir_expression *last = NULL;
+      for (i = 0; i < vector_elements; i++) {
+        ir_rvalue *op0 = get_element(op_var[0], i);
+        ir_rvalue *op1 = get_element(op_var[1], i);
+        ir_expression *temp;
+
+        temp = new(mem_ctx) ir_expression(ir_binop_mul,
+                                          element_type,
+                                          op0,
+                                          op1);
+        if (last) {
+           last = new(mem_ctx) ir_expression(ir_binop_add,
+                                             element_type,
+                                             temp,
+                                             last);
+        } else {
+           last = temp;
+        }
+      }
+      assign(ir, 0, last);
+      break;
+   }
+
+   case ir_binop_cross: {
+      for (i = 0; i < vector_elements; i++) {
+        int swiz0 = (i + 1) % 3;
+        int swiz1 = (i + 2) % 3;
+        ir_expression *temp1, *temp2;
+
+        temp1 = new(mem_ctx) ir_expression(ir_binop_mul,
+                                           element_type,
+                                           get_element(op_var[0], swiz0),
+                                           get_element(op_var[1], swiz1));
+
+        temp2 = new(mem_ctx) ir_expression(ir_binop_mul,
+                                           element_type,
+                                           get_element(op_var[1], swiz0),
+                                           get_element(op_var[0], swiz1));
+
+        temp2 = new(mem_ctx) ir_expression(ir_unop_neg,
+                                           element_type,
+                                           temp2,
+                                           NULL);
+
+        assign(ir, i, new(mem_ctx) ir_expression(ir_binop_add,
+                                                 element_type,
+                                                 temp1, temp2));
+      }
+      break;
+   }
+
+   case ir_binop_less:
+   case ir_binop_greater:
+   case ir_binop_lequal:
+   case ir_binop_gequal:
+   case ir_binop_logic_and:
+   case ir_binop_logic_xor:
+   case ir_binop_logic_or:
+      ir->print();
+      printf("\n");
+      assert(!"not reached: expression operates on scalars only");
+      break;
+   case ir_binop_equal:
+   case ir_binop_nequal: {
+      ir_expression *last = NULL;
+      for (i = 0; i < vector_elements; i++) {
+        ir_rvalue *op0 = get_element(op_var[0], i);
+        ir_rvalue *op1 = get_element(op_var[1], i);
+        ir_expression *temp;
+        ir_expression_operation join;
+
+        if (expr->operation == ir_binop_equal)
+           join = ir_binop_logic_and;
+        else
+           join = ir_binop_logic_or;
+
+        temp = new(mem_ctx) ir_expression(expr->operation,
+                                          element_type,
+                                          op0,
+                                          op1);
+        if (last) {
+           last = new(mem_ctx) ir_expression(join,
+                                             element_type,
+                                             temp,
+                                             last);
+        } else {
+           last = temp;
+        }
+      }
+      assign(ir, 0, last);
+      break;
+   }
+   }
+
+   ir->remove();
+   this->progress = true;
+
+   return visit_continue;
+}
diff --git a/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp b/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp
new file mode 100644 (file)
index 0000000..00d5c20
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file brw_wm_vector_splitting.cpp
+ *
+ * If a vector is only ever referenced by its components, then
+ * split those components out to individual variables so they can be
+ * handled normally by other optimization passes.
+ *
+ * This skips vectors in uniforms and varyings, which need to be
+ * accessible as vectors for their access by the GL.  Also, vector
+ * results of non-variable-derefs in assignments aren't handled
+ * because to do so we would have to store the vector result to a
+ * temporary in order to unload each channel, and to do so would just
+ * loop us back to where we started.  For the 965, this is exactly the
+ * behavior we want for the results of texture lookups, but probably not for
+ */
+
+extern "C" {
+#include "main/core.h"
+#include "intel_context.h"
+}
+#include "../glsl/ir.h"
+#include "../glsl/ir_visitor.h"
+#include "../glsl/ir_print_visitor.h"
+#include "../glsl/ir_rvalue_visitor.h"
+#include "../glsl/glsl_types.h"
+
+static bool debug = false;
+
+class variable_entry : public exec_node
+{
+public:
+   variable_entry(ir_variable *var)
+   {
+      this->var = var;
+      this->whole_vector_access = 0;
+      this->declaration = false;
+      this->mem_ctx = NULL;
+   }
+
+   ir_variable *var; /* The key: the variable's pointer. */
+
+   /** Number of times the variable is referenced, including assignments. */
+   unsigned whole_vector_access;
+
+   bool declaration; /* If the variable had a decl in the instruction stream */
+
+   ir_variable *components[4];
+
+   /** talloc_parent(this->var) -- the shader's talloc context. */
+   void *mem_ctx;
+};
+
+class ir_vector_reference_visitor : public ir_hierarchical_visitor {
+public:
+   ir_vector_reference_visitor(void)
+   {
+      this->mem_ctx = talloc_new(NULL);
+      this->variable_list.make_empty();
+   }
+
+   ~ir_vector_reference_visitor(void)
+   {
+      talloc_free(mem_ctx);
+   }
+
+   virtual ir_visitor_status visit(ir_variable *);
+   virtual ir_visitor_status visit(ir_dereference_variable *);
+   virtual ir_visitor_status visit_enter(ir_swizzle *);
+   virtual ir_visitor_status visit_enter(ir_assignment *);
+   virtual ir_visitor_status visit_enter(ir_function_signature *);
+
+   variable_entry *get_variable_entry(ir_variable *var);
+
+   /* List of variable_entry */
+   exec_list variable_list;
+
+   void *mem_ctx;
+};
+
+variable_entry *
+ir_vector_reference_visitor::get_variable_entry(ir_variable *var)
+{
+   assert(var);
+
+   if (!var->type->is_vector())
+      return NULL;
+
+   switch (var->mode) {
+   case ir_var_uniform:
+   case ir_var_in:
+   case ir_var_out:
+   case ir_var_inout:
+      /* Can't split varyings or uniforms.  Function in/outs won't get split
+       * either, so don't care about the ambiguity.
+       */
+      return NULL;
+   case ir_var_auto:
+   case ir_var_temporary:
+      break;
+   }
+
+   foreach_iter(exec_list_iterator, iter, this->variable_list) {
+      variable_entry *entry = (variable_entry *)iter.get();
+      if (entry->var == var)
+        return entry;
+   }
+
+   variable_entry *entry = new(mem_ctx) variable_entry(var);
+   this->variable_list.push_tail(entry);
+   return entry;
+}
+
+
+ir_visitor_status
+ir_vector_reference_visitor::visit(ir_variable *ir)
+{
+   variable_entry *entry = this->get_variable_entry(ir);
+
+   if (entry)
+      entry->declaration = true;
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_vector_reference_visitor::visit(ir_dereference_variable *ir)
+{
+   ir_variable *const var = ir->var;
+   variable_entry *entry = this->get_variable_entry(var);
+
+   if (entry)
+      entry->whole_vector_access++;
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_vector_reference_visitor::visit_enter(ir_swizzle *ir)
+{
+   /* Don't descend into a vector ir_dereference_variable below. */
+   if (ir->val->as_dereference_variable() && ir->type->is_scalar())
+      return visit_continue_with_parent;
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_vector_reference_visitor::visit_enter(ir_assignment *ir)
+{
+   if (ir->lhs->as_dereference_variable() &&
+       ir->rhs->as_dereference_variable() &&
+       !ir->condition) {
+      /* We'll split copies of a vector to copies of channels, so don't
+       * descend to the ir_dereference_variables.
+       */
+      return visit_continue_with_parent;
+   }
+   if (ir->lhs->as_dereference_variable() &&
+       is_power_of_two(ir->write_mask) &&
+       !ir->condition) {
+      /* If we're writing just a channel, then channel-splitting the LHS is OK.
+       */
+      ir->rhs->accept(this);
+      return visit_continue_with_parent;
+   }
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_vector_reference_visitor::visit_enter(ir_function_signature *ir)
+{
+   /* We don't want to descend into the function parameters and
+    * split them, so just accept the body here.
+    */
+   visit_list_elements(this, &ir->body);
+   return visit_continue_with_parent;
+}
+
+class ir_vector_splitting_visitor : public ir_rvalue_visitor {
+public:
+   ir_vector_splitting_visitor(exec_list *vars)
+   {
+      this->variable_list = vars;
+   }
+
+   virtual ir_visitor_status visit_leave(ir_assignment *);
+
+   void handle_rvalue(ir_rvalue **rvalue);
+   struct variable_entry *get_splitting_entry(ir_variable *var);
+
+   exec_list *variable_list;
+   void *mem_ctx;
+};
+
+struct variable_entry *
+ir_vector_splitting_visitor::get_splitting_entry(ir_variable *var)
+{
+   assert(var);
+
+   if (!var->type->is_vector())
+      return NULL;
+
+   foreach_iter(exec_list_iterator, iter, *this->variable_list) {
+      variable_entry *entry = (variable_entry *)iter.get();
+      if (entry->var == var) {
+        return entry;
+      }
+   }
+
+   return NULL;
+}
+
+void
+ir_vector_splitting_visitor::handle_rvalue(ir_rvalue **rvalue)
+{
+   if (!*rvalue)
+      return;
+
+   ir_swizzle *swiz = (*rvalue)->as_swizzle();
+   if (!swiz || !swiz->type->is_scalar())
+      return;
+
+   ir_dereference_variable *deref_var = swiz->val->as_dereference_variable();
+   if (!deref_var)
+      return;
+
+   variable_entry *entry = get_splitting_entry(deref_var->var);
+   if (!entry)
+      return;
+
+   ir_variable *var = entry->components[swiz->mask.x];
+   *rvalue = new(entry->mem_ctx) ir_dereference_variable(var);
+}
+
+ir_visitor_status
+ir_vector_splitting_visitor::visit_leave(ir_assignment *ir)
+{
+   ir_dereference_variable *lhs_deref = ir->lhs->as_dereference_variable();
+   ir_dereference_variable *rhs_deref = ir->rhs->as_dereference_variable();
+   variable_entry *lhs = lhs_deref ? get_splitting_entry(lhs_deref->var) : NULL;
+   variable_entry *rhs = rhs_deref ? get_splitting_entry(rhs_deref->var) : NULL;
+
+   if (lhs_deref && rhs_deref && (lhs || rhs) && !ir->condition) {
+      /* Straight assignment of vector variables. */
+      for (unsigned int i = 0; i < ir->rhs->type->vector_elements; i++) {
+        ir_dereference *new_lhs;
+        ir_rvalue *new_rhs;
+        void *mem_ctx = lhs ? lhs->mem_ctx : rhs->mem_ctx;
+        unsigned int writemask;
+
+        if (lhs) {
+           new_lhs = new(mem_ctx) ir_dereference_variable(lhs->components[i]);
+           writemask = (ir->write_mask >> i) & 1;
+        } else {
+           new_lhs = ir->lhs->clone(mem_ctx, NULL);
+           writemask = ir->write_mask & (1 << i);
+        }
+
+        if (rhs) {
+           new_rhs = new(mem_ctx) ir_dereference_variable(rhs->components[i]);
+           /* If we're writing into a writemask, smear it out to that channel. */
+           if (!lhs)
+              new_rhs = new(mem_ctx) ir_swizzle(new_rhs, i, i, i, i, i + 1);
+        } else {
+           new_rhs = new(mem_ctx) ir_swizzle(ir->rhs->clone(mem_ctx, NULL),
+                                             i, i, i, i, 1);
+        }
+
+        ir->insert_before(new(mem_ctx) ir_assignment(new_lhs,
+                                                     new_rhs,
+                                                     NULL, writemask));
+      }
+      ir->remove();
+   } else if (lhs) {
+      int elem = -1;
+
+      switch (ir->write_mask) {
+      case (1 << 0):
+        elem = 0;
+        break;
+      case (1 << 1):
+        elem = 1;
+        break;
+      case (1 << 2):
+        elem = 2;
+        break;
+      case (1 << 3):
+        elem = 3;
+        break;
+      default:
+        ir->print();
+        assert(!"not reached: non-channelwise dereference of LHS.");
+      }
+
+      ir->lhs = new(mem_ctx) ir_dereference_variable(lhs->components[elem]);
+      ir->write_mask = (1 << 0);
+
+      handle_rvalue(&ir->rhs);
+      ir->rhs = new(mem_ctx) ir_swizzle(ir->rhs,
+                                       elem, elem, elem, elem, 1);
+   } else {
+      handle_rvalue(&ir->rhs);
+   }
+
+   handle_rvalue(&ir->condition);
+
+   return visit_continue;
+}
+
+extern "C" {
+bool
+brw_do_vector_splitting(exec_list *instructions)
+{
+   ir_vector_reference_visitor refs;
+
+   visit_list_elements(&refs, instructions);
+
+   /* Trim out variables we can't split. */
+   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
+      variable_entry *entry = (variable_entry *)iter.get();
+
+      if (debug) {
+        printf("vector %s@%p: decl %d, whole_access %d\n",
+               entry->var->name, (void *) entry->var, entry->declaration,
+               entry->whole_vector_access);
+      }
+
+      if (!entry->declaration || entry->whole_vector_access) {
+        entry->remove();
+      }
+   }
+
+   if (refs.variable_list.is_empty())
+      return false;
+
+   void *mem_ctx = talloc_new(NULL);
+
+   /* Replace the decls of the vectors to be split with their split
+    * components.
+    */
+   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
+      variable_entry *entry = (variable_entry *)iter.get();
+      const struct glsl_type *type;
+      type = glsl_type::get_instance(entry->var->type->base_type, 1, 1);
+
+      entry->mem_ctx = talloc_parent(entry->var);
+
+      for (unsigned int i = 0; i < entry->var->type->vector_elements; i++) {
+        const char *name = talloc_asprintf(mem_ctx, "%s_%c",
+                                           entry->var->name,
+                                           "xyzw"[i]);
+
+        entry->components[i] = new(entry->mem_ctx) ir_variable(type, name,
+                                                               ir_var_temporary);
+        entry->var->insert_before(entry->components[i]);
+      }
+
+      entry->var->remove();
+   }
+
+   ir_vector_splitting_visitor split(&refs.variable_list);
+   visit_list_elements(&split, instructions);
+
+   talloc_free(mem_ctx);
+
+   return true;
+}
+}
index 572175f463e16fdf8408027570f13c86135828c1..6eeaba777207d35fd4d96e28ba9537c1eca1ae2c 100644 (file)
@@ -281,7 +281,7 @@ static void emit_depthbuffer(struct brw_context *brw)
       }
 
       assert(region->tiling != I915_TILING_X);
-      if (IS_GEN6(intel->intelScreen->deviceID))
+      if (intel->gen >= 6)
         assert(region->tiling != I915_TILING_NONE);
 
       BEGIN_BATCH(len);
@@ -295,7 +295,7 @@ static void emit_depthbuffer(struct brw_context *brw)
                I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
                0);
       OUT_BATCH((BRW_SURFACE_MIPMAPLAYOUT_BELOW << 1) |
-               ((region->pitch - 1) << 6) |
+               ((region->width - 1) << 6) |
                ((region->height - 1) << 19));
       OUT_BATCH(0);
 
index 8aa6fb6cc6fb2534e2a3a97966829c22691cd696..cbed2bd5cb168effaa621d884b65825d3bbcf006 100644 (file)
 #include "brw_defines.h"
 #include "brw_eu.h"
 
-static const struct {
-    char    *name;
-    int            nsrc;
-    int            ndst;
-    GLboolean is_arith;
-} inst_opcode[128] = {
+const struct brw_instruction_info brw_opcodes[128] = {
     [BRW_OPCODE_MOV] = { .name = "mov", .nsrc = 1, .ndst = 1, .is_arith = 1 },
     [BRW_OPCODE_FRC] = { .name = "frc", .nsrc = 1, .ndst = 1, .is_arith = 1 },
     [BRW_OPCODE_RNDU] = { .name = "rndu", .nsrc = 1, .ndst = 1, .is_arith = 1 },
@@ -94,7 +89,7 @@ static const struct {
 static INLINE
 GLboolean brw_is_arithmetic_inst(const struct brw_instruction *inst)
 {
-   return inst_opcode[inst->header.opcode].is_arith;
+   return brw_opcodes[inst->header.opcode].is_arith;
 }
 
 static const GLuint inst_stride[7] = {
@@ -122,7 +117,7 @@ brw_is_grf_written(const struct brw_instruction *inst,
                    int reg_index, int size,
                    int gen)
 {
-   if (inst_opcode[inst->header.opcode].ndst == 0)
+   if (brw_opcodes[inst->header.opcode].ndst == 0)
       return GL_FALSE;
 
    if (inst->bits1.da1.dest_address_mode != BRW_ADDRESS_DIRECT)
@@ -161,20 +156,19 @@ brw_is_grf_written(const struct brw_instruction *inst,
    return left < right;
 }
 
-/* Specific path for message register since we need to handle the compr4 case */
-static INLINE GLboolean
-brw_is_mrf_written(const struct brw_instruction *inst, int reg_index, int size)
+static GLboolean
+brw_is_mrf_written_alu(const struct brw_instruction *inst,
+                      int reg_index, int size)
 {
-   if (inst_opcode[inst->header.opcode].ndst == 0)
+   if (brw_opcodes[inst->header.opcode].ndst == 0)
       return GL_FALSE;
 
-   if (inst->bits1.da1.dest_address_mode != BRW_ADDRESS_DIRECT)
-      if (inst->bits1.ia1.dest_reg_file == BRW_MESSAGE_REGISTER_FILE)
-         return GL_TRUE;
-
    if (inst->bits1.da1.dest_reg_file != BRW_MESSAGE_REGISTER_FILE)
       return GL_FALSE;
 
+   if (inst->bits1.da1.dest_address_mode != BRW_ADDRESS_DIRECT)
+      return GL_TRUE;
+
    const int reg_start = reg_index * REG_SIZE;
    const int reg_end = reg_start + size;
 
@@ -188,8 +182,6 @@ brw_is_mrf_written(const struct brw_instruction *inst, int reg_index, int size)
    if (is_compr4 && inst->header.execution_size != BRW_EXECUTE_16)
       return GL_TRUE;
 
-   GLboolean is_written = GL_FALSE;
-
    /* Here we write mrf_{i} and mrf_{i+4}. So we read two times 8 elements */
    if (is_compr4) {
       const int length = 8 * type_size * inst->bits1.da1.dest_horiz_stride;
@@ -210,7 +202,8 @@ brw_is_mrf_written(const struct brw_instruction *inst, int reg_index, int size)
       const int left1 = MAX2(write_start1, reg_start);
       const int right1 = MIN2(write_end1, reg_end);
 
-      is_written = left0 < right0 || left1 < right1;
+      if (left0 < right0 || left1 < right1)
+        return GL_TRUE;
    }
    else {
       int length;
@@ -223,25 +216,41 @@ brw_is_mrf_written(const struct brw_instruction *inst, int reg_index, int size)
                             + inst->bits1.da1.dest_subreg_nr;
       const int write_end = write_start + length;
       const int left = MAX2(write_start, reg_start);
-      const int right = MIN2(write_end, reg_end);;
+      const int right = MIN2(write_end, reg_end);
 
-      is_written = left < right;
+      if (left < right)
+        return GL_TRUE;
    }
 
-   /* SEND may perform an implicit mov to a mrf register */
-   if (is_written == GL_FALSE &&
-       inst->header.opcode == BRW_OPCODE_SEND &&
-       inst->bits1.da1.src0_reg_file != 0) {
+   return GL_FALSE;
+}
 
-      const int mrf_start = inst->header.destreg__conditionalmod;
-      const int write_start = mrf_start * REG_SIZE;
-      const int write_end = write_start + REG_SIZE;
-      const int left = MAX2(write_start, reg_start);
-      const int right = MIN2(write_end, reg_end);;
-      is_written = left < right;
-   }
+/* SEND may perform an implicit mov to a mrf register */
+static GLboolean brw_is_mrf_written_send(const struct brw_instruction *inst,
+                                        int reg_index, int size)
+{
+
+   const int reg_start = reg_index * REG_SIZE;
+   const int reg_end = reg_start + size;
+   const int mrf_start = inst->header.destreg__conditionalmod;
+   const int write_start = mrf_start * REG_SIZE;
+   const int write_end = write_start + REG_SIZE;
+   const int left = MAX2(write_start, reg_start);
+   const int right = MIN2(write_end, reg_end);
+
+   if (inst->header.opcode != BRW_OPCODE_SEND ||
+       inst->bits1.da1.src0_reg_file == 0)
+      return GL_FALSE;
 
-   return is_written;
+   return left < right;
+}
+
+/* Specific path for message register since we need to handle the compr4 case */
+static INLINE GLboolean
+brw_is_mrf_written(const struct brw_instruction *inst, int reg_index, int size)
+{
+   return (brw_is_mrf_written_alu(inst, reg_index, size) ||
+          brw_is_mrf_written_send(inst, reg_index, size));
 }
 
 static INLINE GLboolean
@@ -284,7 +293,7 @@ static INLINE GLboolean
 brw_is_grf_read(const struct brw_instruction *inst, int reg_index, int size)
 {
    int i, j;
-   if (inst_opcode[inst->header.opcode].nsrc == 0)
+   if (brw_opcodes[inst->header.opcode].nsrc == 0)
       return GL_FALSE;
 
    /* Look at first source. We must take into account register regions to
@@ -292,7 +301,7 @@ brw_is_grf_read(const struct brw_instruction *inst, int reg_index, int size)
     * since we do not take into account the fact that some complete registers
     * may be skipped
     */
-   if (inst_opcode[inst->header.opcode].nsrc >= 1) {
+   if (brw_opcodes[inst->header.opcode].nsrc >= 1) {
 
       if (inst->bits2.da1.src0_address_mode != BRW_ADDRESS_DIRECT)
          if (inst->bits1.ia1.src0_reg_file == BRW_GENERAL_REGISTER_FILE)
@@ -327,7 +336,7 @@ brw_is_grf_read(const struct brw_instruction *inst, int reg_index, int size)
    }
 
    /* Second src register */
-   if (inst_opcode[inst->header.opcode].nsrc >= 2) {
+   if (brw_opcodes[inst->header.opcode].nsrc >= 2) {
 
       if (inst->bits3.da1.src1_address_mode != BRW_ADDRESS_DIRECT)
          if (inst->bits1.ia1.src1_reg_file == BRW_GENERAL_REGISTER_FILE)
index 4b08d2599bc0b1c49546856366f437a6dc80cb15..bc152204a42f5a5a31759ff24998eeea9de9afff 100644 (file)
@@ -36,6 +36,7 @@
 #include "program/program.h"
 #include "program/programopt.h"
 #include "tnl/tnl.h"
+#include "talloc.h"
 
 #include "brw_context.h"
 #include "brw_wm.h"
@@ -114,10 +115,7 @@ shader_error(GLcontext *ctx, struct gl_program *prog, const char *msg)
    shader = _mesa_lookup_shader_program(ctx, prog->Id);
 
    if (shader) {
-      if (shader->InfoLog) {
-        free(shader->InfoLog);
-      }
-      shader->InfoLog = _mesa_strdup(msg);
+      shader->InfoLog = talloc_strdup_append(shader->InfoLog, msg);
       shader->LinkStatus = GL_FALSE;
    }
 }
@@ -170,6 +168,9 @@ static GLboolean brwProgramStringNotify( GLcontext *ctx,
     * See piglit glsl-{vs,fs}-functions-[23] tests.
     */
    for (i = 0; i < prog->NumInstructions; i++) {
+      struct prog_instruction *inst = prog->Instructions + i;
+      int r;
+
       if (prog->Instructions[i].Opcode == OPCODE_CAL) {
         shader_error(ctx, prog,
                      "i965 driver doesn't yet support uninlined function "
@@ -177,16 +178,28 @@ static GLboolean brwProgramStringNotify( GLcontext *ctx,
                      "the end of the function to work around it.\n");
         return GL_FALSE;
       }
-      if (prog->Instructions[i].DstReg.RelAddr &&
-         prog->Instructions[i].DstReg.File == PROGRAM_INPUT) {
+
+      if (prog->Instructions[i].Opcode == OPCODE_RET) {
         shader_error(ctx, prog,
-                     "Variable indexing of shader inputs unsupported\n");
+                     "i965 driver doesn't yet support \"return\" "
+                     "from main().\n");
         return GL_FALSE;
       }
-      if (prog->Instructions[i].DstReg.RelAddr &&
+
+      for (r = 0; r < _mesa_num_inst_src_regs(inst->Opcode); r++) {
+        if (prog->Instructions[i].SrcReg[r].RelAddr &&
+            prog->Instructions[i].SrcReg[r].File == PROGRAM_INPUT) {
+           shader_error(ctx, prog,
+                        "Variable indexing of shader inputs unsupported\n");
+           return GL_FALSE;
+        }
+      }
+
+      if (target == GL_FRAGMENT_PROGRAM_ARB &&
+         prog->Instructions[i].DstReg.RelAddr &&
          prog->Instructions[i].DstReg.File == PROGRAM_OUTPUT) {
         shader_error(ctx, prog,
-                     "Variable indexing of shader outputs unsupported\n");
+                     "Variable indexing of FS outputs unsupported\n");
         return GL_FALSE;
       }
       if (target == GL_FRAGMENT_PROGRAM_ARB) {
@@ -218,5 +231,10 @@ void brwInitFragProgFuncs( struct dd_function_table *functions )
    functions->DeleteProgram = brwDeleteProgram;
    functions->IsProgramNative = brwIsProgramNative;
    functions->ProgramStringNotify = brwProgramStringNotify;
+
+   functions->NewShader = brw_new_shader;
+   functions->NewShaderProgram = brw_new_shader_program;
+   functions->CompileShader = brw_compile_shader;
+   functions->LinkShader = brw_link_shader;
 }
 
index af08446f2d8fdaf20c8928fc1dfd7673eaf3a727..c5d296b1295111cec9611e7ff2e0c463bb0781e4 100644 (file)
@@ -107,6 +107,7 @@ extern const struct brw_tracked_state gen6_sf_vp;
 extern const struct brw_tracked_state gen6_urb;
 extern const struct brw_tracked_state gen6_viewport_state;
 extern const struct brw_tracked_state gen6_vs_state;
+extern const struct brw_tracked_state gen6_wm_constants;
 extern const struct brw_tracked_state gen6_wm_state;
 
 /***********************************************************************
index f92a19c2aa0f7c28905d562d6661244ceb794a4f..a0c130557e3c4bb58b7bfd19d63e0f6719fe3cc3 100644 (file)
@@ -35,7 +35,6 @@
 #include "brw_state.h"
 #include "intel_batchbuffer.h"
 #include "intel_buffers.h"
-#include "intel_chipset.h"
 
 /* This is used to initialize brw->state.atoms[].  We could use this
  * list directly except for a single atom, brw_constant_buffer, which
@@ -129,7 +128,7 @@ const struct brw_tracked_state *gen6_atoms[] =
    &gen6_cc_state_pointers,
 
    &brw_vs_constants, /* Before vs_surfaces and constant_buffer */
-   &brw_wm_constants, /* Before wm_surfaces and constant_buffer */
+   &gen6_wm_constants, /* Before wm_surfaces and constant_buffer */
 
    &brw_vs_surfaces,           /* must do before unit */
    &brw_wm_constant_surface,   /* must do before wm surfaces/bind bo */
@@ -351,7 +350,7 @@ void brw_validate_state( struct brw_context *brw )
 
    brw_add_validated_bo(brw, intel->batch->buf);
 
-   if (IS_GEN6(intel->intelScreen->deviceID)) {
+   if (intel->gen >= 6) {
       atoms = gen6_atoms;
       num_atoms = ARRAY_SIZE(gen6_atoms);
    } else {
@@ -425,7 +424,7 @@ void brw_upload_state(struct brw_context *brw)
    const struct brw_tracked_state **atoms;
    int num_atoms;
 
-   if (IS_GEN6(intel->intelScreen->deviceID)) {
+   if (intel->gen >= 6) {
       atoms = gen6_atoms;
       num_atoms = ARRAY_SIZE(gen6_atoms);
    } else {
index 2fde42a70607750c2b1302d6e7dfcf70088482df..2a118e01c5386e8869d98836166d2b2c171dc271 100644 (file)
@@ -750,7 +750,7 @@ struct gen6_depth_stencil_state
    } ds1;
 
    struct {
-      GLuint pad0:25;
+      GLuint pad0:26;
       GLuint depth_write_enable:1;
       GLuint depth_test_func:3;
       GLuint pad1:1;
@@ -1305,13 +1305,14 @@ struct brw_instruction
       GLuint access_mode:1;
       GLuint mask_control:1;
       GLuint dependency_control:2;
-      GLuint compression_control:2;
+      GLuint compression_control:2; /* gen6: quater control */
       GLuint thread_control:2;
       GLuint predicate_control:4;
       GLuint predicate_inverse:1;
       GLuint execution_size:3;
       GLuint destreg__conditionalmod:4; /* destreg - send, conditionalmod - others */
-      GLuint pad0:2;
+      GLuint acc_wr_control:1;
+      GLuint cmpt_control:1;
       GLuint debug_control:1;
       GLuint saturate:1;
    } header;
@@ -1359,7 +1360,7 @@ struct brw_instruction
         GLuint dest_writemask:4;
         GLuint dest_subreg_nr:1;
         GLuint dest_reg_nr:8;
-        GLuint pad1:2;
+        GLuint dest_horiz_stride:2;
         GLuint dest_address_mode:1;
       } da16;
 
@@ -1373,7 +1374,7 @@ struct brw_instruction
         GLuint dest_writemask:4;
         GLint dest_indirect_offset:6;
         GLuint dest_subreg_nr:3;
-        GLuint pad1:2;
+        GLuint dest_horiz_stride:2;
         GLuint dest_address_mode:1;
       } ia16;
    } bits1;
index 9a832af9a9702d739ab729c43d0f428fc118e032..9f90e1e5e5c818182ec326d15737a4972f642f01 100644 (file)
@@ -75,10 +75,10 @@ static void do_vs_prog( struct brw_context *brw,
         c.prog_data.outputs_written |= BITFIELD64_BIT(VERT_RESULT_TEX0 + i);
    }
 
-   if (0)
-      _mesa_print_program(&c.vp->program.Base);
-
-
+   if (0) {
+      _mesa_fprint_program_opt(stdout, &c.vp->program.Base, PROG_PRINT_DEBUG,
+                              GL_TRUE);
+   }
 
    /* Emit GEN4 code.
     */
index b6b558e9a69b68027c2b0b728199cf0d99a494a4..1d88c6b5a461d516b69a31f7efda621045448d37 100644 (file)
@@ -47,6 +47,7 @@ brw_vs_arg_can_be_immediate(enum prog_opcode opcode, int arg)
       [OPCODE_MOV] = 1,
       [OPCODE_ADD] = 2,
       [OPCODE_CMP] = 3,
+      [OPCODE_DP2] = 2,
       [OPCODE_DP3] = 2,
       [OPCODE_DP4] = 2,
       [OPCODE_DPH] = 2,
@@ -97,6 +98,39 @@ static void release_tmps( struct brw_vs_compile *c )
    c->last_tmp = c->first_tmp;
 }
 
+static int
+get_first_reladdr_output(struct gl_vertex_program *vp)
+{
+   int i;
+   int first_reladdr_output = VERT_RESULT_MAX;
+
+   for (i = 0; i < vp->Base.NumInstructions; i++) {
+      struct prog_instruction *inst = vp->Base.Instructions + i;
+
+      if (inst->DstReg.File == PROGRAM_OUTPUT &&
+         inst->DstReg.RelAddr &&
+         inst->DstReg.Index < first_reladdr_output)
+        first_reladdr_output = inst->DstReg.Index;
+   }
+
+   return first_reladdr_output;
+}
+
+/* Clears the record of which vp_const_buffer elements have been
+ * loaded into our constant buffer registers, for the starts of new
+ * blocks after control flow.
+ */
+static void
+clear_current_const(struct brw_vs_compile *c)
+{
+   unsigned int i;
+
+   if (c->vp->use_const_buffer) {
+      for (i = 0; i < 3; i++) {
+         c->current_const[i].index = -1;
+      }
+   }
+}
 
 /**
  * Preallocate GRF register before code emit.
@@ -108,6 +142,7 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c )
    struct intel_context *intel = &c->func.brw->intel;
    GLuint i, reg = 0, mrf;
    int attributes_in_vue;
+   int first_reladdr_output;
 
    /* Determine whether to use a real constant buffer or use a block
     * of GRF registers for constants.  The later is faster but only
@@ -225,6 +260,7 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c )
    else
       mrf = 4;
 
+   first_reladdr_output = get_first_reladdr_output(&c->vp->program);
    for (i = 0; i < VERT_RESULT_MAX; i++) {
       if (c->prog_data.outputs_written & BITFIELD64_BIT(i)) {
         c->nr_outputs++;
@@ -253,15 +289,16 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c )
             * For attributes beyond the compute-to-MRF, we compute to
             * GRFs and they will be written in the second URB_WRITE.
             */
-            if (mrf < 15) {
+            if (first_reladdr_output > i && mrf < 15) {
                c->regs[PROGRAM_OUTPUT][i] = brw_message_reg(mrf);
                mrf++;
             }
             else {
-               if (!c->first_overflow_output)
+               if (mrf >= 15 && !c->first_overflow_output)
                   c->first_overflow_output = i;
                c->regs[PROGRAM_OUTPUT][i] = brw_vec8_grf(reg, 0);
                reg++;
+              mrf++;
             }
         }
       }
@@ -292,10 +329,10 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c )
 
    if (c->vp->use_const_buffer) {
       for (i = 0; i < 3; i++) {
-         c->current_const[i].index = -1;
          c->current_const[i].reg = brw_vec8_grf(reg, 0);
          reg++;
       }
+      clear_current_const(c);
    }
 
    for (i = 0; i < 128; i++) {
@@ -502,6 +539,23 @@ static void emit_cmp( struct brw_compile *p,
    brw_set_predicate_control(p, BRW_PREDICATE_NONE);
 }
 
+static void emit_sign(struct brw_vs_compile *c,
+                     struct brw_reg dst,
+                     struct brw_reg arg0)
+{
+   struct brw_compile *p = &c->func;
+
+   brw_MOV(p, dst, brw_imm_f(0));
+
+   brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, arg0, brw_imm_f(0));
+   brw_MOV(p, dst, brw_imm_f(-1.0));
+   brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+   brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_G, arg0, brw_imm_f(0));
+   brw_MOV(p, dst, brw_imm_f(1.0));
+   brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+}
+
 static void emit_max( struct brw_compile *p, 
                      struct brw_reg dst,
                      struct brw_reg arg0,
@@ -1010,13 +1064,11 @@ move_to_reladdr_dst(struct brw_vs_compile *c,
    int reg_size = 32;
    struct brw_reg addr_reg = c->regs[PROGRAM_ADDRESS][0];
    struct brw_reg vp_address = retype(vec1(addr_reg), BRW_REGISTER_TYPE_D);
-   struct brw_reg temp_base = c->regs[inst->DstReg.File][0];
-   GLuint byte_offset = temp_base.nr * 32 + temp_base.subnr;
+   struct brw_reg base = c->regs[inst->DstReg.File][inst->DstReg.Index];
+   GLuint byte_offset = base.nr * 32 + base.subnr;
    struct brw_reg indirect = brw_vec4_indirect(0,0);
    struct brw_reg acc = retype(vec1(get_tmp(c)), BRW_REGISTER_TYPE_UW);
 
-   byte_offset += inst->DstReg.Index * reg_size;
-
    brw_push_insn_state(p);
    brw_set_access_mode(p, BRW_ALIGN_1);
 
@@ -1162,10 +1214,12 @@ static struct brw_reg get_arg( struct brw_vs_compile *c,
 
    /* Convert 3-bit swizzle to 2-bit.  
     */
-   reg.dw1.bits.swizzle = BRW_SWIZZLE4(GET_SWZ(src->Swizzle, 0),
-                                      GET_SWZ(src->Swizzle, 1),
-                                      GET_SWZ(src->Swizzle, 2),
-                                      GET_SWZ(src->Swizzle, 3));
+   if (reg.file != BRW_IMMEDIATE_VALUE) {
+      reg.dw1.bits.swizzle = BRW_SWIZZLE4(GET_SWZ(src->Swizzle, 0),
+                                         GET_SWZ(src->Swizzle, 1),
+                                         GET_SWZ(src->Swizzle, 2),
+                                         GET_SWZ(src->Swizzle, 3));
+   }
 
    /* Note this is ok for non-swizzle instructions: 
     */
@@ -1211,6 +1265,7 @@ static struct brw_reg get_dst( struct brw_vs_compile *c,
       reg = brw_null_reg();
    }
 
+   assert(reg.type != BRW_IMMEDIATE_VALUE);
    reg.dw1.bits.writemask = dst.WriteMask;
 
    return reg;
@@ -1299,6 +1354,7 @@ static void emit_vertex_write( struct brw_vs_compile *c)
    struct brw_reg ndc;
    int eot;
    GLuint len_vertex_header = 2;
+   int next_mrf, i;
 
    if (c->key.copy_edgeflag) {
       brw_MOV(p, 
@@ -1376,6 +1432,7 @@ static void emit_vertex_write( struct brw_vs_compile *c)
     * of zeros followed by two sets of NDC coordinates:
     */
    brw_set_access_mode(p, BRW_ALIGN_1);
+   brw_set_acc_write_control(p, 0);
 
    /* The VUE layout is documented in Volume 2a. */
    if (intel->gen >= 6) {
@@ -1416,6 +1473,23 @@ static void emit_vertex_write( struct brw_vs_compile *c)
       len_vertex_header = 2;
    }
 
+   /* Move variable-addressed, non-overflow outputs to their MRFs. */
+   next_mrf = 2 + len_vertex_header;
+   for (i = 0; i < VERT_RESULT_MAX; i++) {
+      if (c->first_overflow_output > 0 && i >= c->first_overflow_output)
+        break;
+      if (!(c->prog_data.outputs_written & BITFIELD64_BIT(i)))
+        continue;
+
+      if (i >= VERT_RESULT_TEX0 &&
+         c->regs[PROGRAM_OUTPUT][i].file == BRW_GENERAL_REGISTER_FILE) {
+        brw_MOV(p, brw_message_reg(next_mrf), c->regs[PROGRAM_OUTPUT][i]);
+        next_mrf++;
+      } else if (c->regs[PROGRAM_OUTPUT][i].file == BRW_MESSAGE_REGISTER_FILE) {
+        next_mrf = c->regs[PROGRAM_OUTPUT][i].nr + 1;
+      }
+   }
+
    eot = (c->first_overflow_output == 0);
 
    brw_urb_WRITE(p, 
@@ -1541,18 +1615,23 @@ void brw_vs_emit(struct brw_vs_compile *c )
    const GLuint nr_insns = c->vp->program.Base.NumInstructions;
    GLuint insn, if_depth = 0, loop_depth = 0;
    struct brw_instruction *if_inst[MAX_IF_DEPTH], *loop_inst[MAX_LOOP_DEPTH] = { 0 };
+   int if_depth_in_loop[MAX_LOOP_DEPTH];
    const struct brw_indirect stack_index = brw_indirect(0, 0);   
    GLuint index;
    GLuint file;
 
    if (INTEL_DEBUG & DEBUG_VS) {
       printf("vs-mesa:\n");
-      _mesa_print_program(&c->vp->program.Base); 
+      _mesa_fprint_program_opt(stdout, &c->vp->program.Base, PROG_PRINT_DEBUG,
+                              GL_TRUE);
       printf("\n");
    }
 
    brw_set_compression_control(p, BRW_COMPRESSION_NONE);
    brw_set_access_mode(p, BRW_ALIGN_16);
+   if_depth_in_loop[loop_depth] = 0;
+
+   brw_set_acc_write_control(p, 1);
 
    for (insn = 0; insn < nr_insns; insn++) {
        GLuint i;
@@ -1591,7 +1670,7 @@ void brw_vs_emit(struct brw_vs_compile *c )
       const struct prog_instruction *inst = &c->vp->program.Base.Instructions[insn];
       struct brw_reg args[3], dst;
       GLuint i;
-      
+
 #if 0
       printf("%d: ", insn);
       _mesa_print_instruction(inst);
@@ -1636,6 +1715,9 @@ void brw_vs_emit(struct brw_vs_compile *c )
       case OPCODE_COS:
         emit_math1(c, BRW_MATH_FUNCTION_COS, dst, args[0], BRW_MATH_PRECISION_FULL);
         break;
+      case OPCODE_DP2:
+        brw_DP2(p, dst, args[0], args[1]);
+        break;
       case OPCODE_DP3:
         brw_DP3(p, dst, args[0], args[1]);
         break;
@@ -1732,6 +1814,9 @@ void brw_vs_emit(struct brw_vs_compile *c )
       case OPCODE_SLE:
          unalias2(c, dst, args[0], args[1], emit_sle);
          break;
+      case OPCODE_SSG:
+         unalias1(c, dst, args[0], emit_sign);
+         break;
       case OPCODE_SUB:
         brw_ADD(p, dst, args[0], negate(args[1]));
         break;
@@ -1753,31 +1838,38 @@ void brw_vs_emit(struct brw_vs_compile *c )
         if_inst[if_depth] = brw_IF(p, BRW_EXECUTE_8);
         /* Note that brw_IF smashes the predicate_control field. */
         if_inst[if_depth]->header.predicate_control = get_predicate(inst);
+        if_depth_in_loop[loop_depth]++;
         if_depth++;
         break;
       case OPCODE_ELSE:
+        clear_current_const(c);
         assert(if_depth > 0);
         if_inst[if_depth-1] = brw_ELSE(p, if_inst[if_depth-1]);
         break;
       case OPCODE_ENDIF:
+        clear_current_const(c);
          assert(if_depth > 0);
         brw_ENDIF(p, if_inst[--if_depth]);
+        if_depth_in_loop[loop_depth]--;
         break;                 
       case OPCODE_BGNLOOP:
+        clear_current_const(c);
          loop_inst[loop_depth++] = brw_DO(p, BRW_EXECUTE_8);
+        if_depth_in_loop[loop_depth] = 0;
          break;
       case OPCODE_BRK:
         brw_set_predicate_control(p, get_predicate(inst));
-         brw_BREAK(p);
+        brw_BREAK(p, if_depth_in_loop[loop_depth]);
         brw_set_predicate_control(p, BRW_PREDICATE_NONE);
          break;
       case OPCODE_CONT:
         brw_set_predicate_control(p, get_predicate(inst));
-         brw_CONT(p);
+        brw_CONT(p, if_depth_in_loop[loop_depth]);
          brw_set_predicate_control(p, BRW_PREDICATE_NONE);
          break;
       case OPCODE_ENDLOOP: 
          {
+           clear_current_const(c);
             struct brw_instruction *inst0, *inst1;
            GLuint br = 1;
 
@@ -1793,12 +1885,10 @@ void brw_vs_emit(struct brw_vs_compile *c )
                if (inst0->header.opcode == BRW_OPCODE_BREAK &&
                   inst0->bits3.if_else.jump_count == 0) {
                   inst0->bits3.if_else.jump_count = br * (inst1 - inst0 + 1);
-                  inst0->bits3.if_else.pop_count = 0;
                }
                else if (inst0->header.opcode == BRW_OPCODE_CONTINUE &&
                        inst0->bits3.if_else.jump_count == 0) {
                   inst0->bits3.if_else.jump_count = br * (inst1 - inst0);
-                  inst0->bits3.if_else.pop_count = 0;
                }
             }
          }
@@ -1883,11 +1973,9 @@ void brw_vs_emit(struct brw_vs_compile *c )
          }
       }
 
-      if (inst->DstReg.RelAddr && inst->DstReg.File == PROGRAM_TEMPORARY) {
-        /* We don't do RelAddr of PROGRAM_OUTPUT yet, because of the
-         * compute-to-mrf and the fact that we are allocating
-         * registers for only the used PROGRAM_OUTPUTs.
-         */
+      if (inst->DstReg.RelAddr) {
+        assert(inst->DstReg.File == PROGRAM_TEMPORARY||
+               inst->DstReg.File == PROGRAM_OUTPUT);
         move_to_reladdr_dst(c, inst, dst);
       }
 
@@ -1903,7 +1991,7 @@ void brw_vs_emit(struct brw_vs_compile *c )
 
       printf("vs-native:\n");
       for (i = 0; i < p->nr_insn; i++)
-        brw_disasm(stderr, &p->store[i], intel->gen);
+        brw_disasm(stdout, &p->store[i], intel->gen);
       printf("\n");
    }
 }
index 14227a51332f1988370e8461f1168b1af6689cc9..8f1601d10f1bf18ba3d019a250273802f9efa6f0 100644 (file)
@@ -101,6 +101,7 @@ static void brw_destroy_context( struct intel_context *intel )
    dri_bo_release(&brw->wm.prog_bo);
    dri_bo_release(&brw->wm.state_bo);
    dri_bo_release(&brw->wm.const_bo);
+   dri_bo_release(&brw->wm.push_const_bo);
    dri_bo_release(&brw->cc.prog_bo);
    dri_bo_release(&brw->cc.state_bo);
    dri_bo_release(&brw->cc.vp_bo);
index e182fc32029ccc2ce0b9f4f9cd2caed09882b0a5..d70be7bda28557b4d5f5541c33dcd67a5aac8287 100644 (file)
@@ -32,7 +32,7 @@
 #include "brw_context.h"
 #include "brw_wm.h"
 #include "brw_state.h"
-
+#include "main/formats.h"
 
 /** Return number of src args for given instruction */
 GLuint brw_wm_nr_args( GLuint opcode )
@@ -68,6 +68,7 @@ GLuint brw_wm_is_scalar_result( GLuint opcode )
    case OPCODE_RCP:
    case OPCODE_RSQ:
    case OPCODE_SIN:
+   case OPCODE_DP2:
    case OPCODE_DP3:
    case OPCODE_DP4:
    case OPCODE_DPH:
@@ -177,17 +178,19 @@ static void do_wm_prog( struct brw_context *brw,
    /* temporary sanity check assertion */
    ASSERT(fp->isGLSL == brw_wm_is_glsl(&c->fp->program));
 
-   /*
-    * Shader which use GLSL features such as flow control are handled
-    * differently from "simple" shaders.
-    */
-   if (fp->isGLSL) {
-      c->dispatch_width = 8;
-      brw_wm_glsl_emit(brw, c);
-   }
-   else {
-      c->dispatch_width = 16;
-      brw_wm_non_glsl_emit(brw, c);
+   if (!brw_wm_fs_emit(brw, c)) {
+      /*
+       * Shader which use GLSL features such as flow control are handled
+       * differently from "simple" shaders.
+       */
+      if (fp->isGLSL) {
+        c->dispatch_width = 8;
+        brw_wm_glsl_emit(brw, c);
+      }
+      else {
+        c->dispatch_width = 16;
+        brw_wm_non_glsl_emit(brw, c);
+      }
    }
 
    if (INTEL_DEBUG & DEBUG_WM)
index f40977fab8d523901982310e65426747b3a3f7fb..2639d4f26b392e93a69f75988fa89f2293a4dbfa 100644 (file)
@@ -61,7 +61,7 @@ struct brw_wm_prog_key {
    GLuint source_depth_reg:3;
    GLuint aa_dest_stencil_reg:3;
    GLuint dest_depth_reg:3;
-   GLuint nr_depth_regs:3;
+   GLuint nr_payload_regs:4;
    GLuint computes_depth:1;    /* could be derived from program string */
    GLuint source_depth_to_render_target:1;
    GLuint flat_shade:1;
@@ -306,6 +306,7 @@ void brw_wm_lookup_iz( GLuint line_aa,
 
 GLboolean brw_wm_is_glsl(const struct gl_fragment_program *fp);
 void brw_wm_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c);
+GLboolean brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c);
 
 /* brw_wm_emit.c */
 void emit_alu1(struct brw_compile *p,
@@ -343,6 +344,11 @@ void emit_delta_xy(struct brw_compile *p,
                   const struct brw_reg *dst,
                   GLuint mask,
                   const struct brw_reg *arg0);
+void emit_dp2(struct brw_compile *p,
+             const struct brw_reg *dst,
+             GLuint mask,
+             const struct brw_reg *arg0,
+             const struct brw_reg *arg1);
 void emit_dp3(struct brw_compile *p,
              const struct brw_reg *dst,
              GLuint mask,
@@ -425,6 +431,10 @@ void emit_sop(struct brw_compile *p,
              GLuint cond,
              const struct brw_reg *arg0,
              const struct brw_reg *arg1);
+void emit_sign(struct brw_compile *p,
+              const struct brw_reg *dst,
+              GLuint mask,
+              const struct brw_reg *arg0);
 void emit_tex(struct brw_wm_compile *c,
              struct brw_reg *dst,
              GLuint dst_flags,
@@ -450,4 +460,13 @@ void emit_xpd(struct brw_compile *p,
              const struct brw_reg *arg0,
              const struct brw_reg *arg1);
 
+GLboolean brw_compile_shader(GLcontext *ctx,
+                            struct gl_shader *shader);
+GLboolean brw_link_shader(GLcontext *ctx, struct gl_shader_program *prog);
+struct gl_shader *brw_new_shader(GLcontext *ctx, GLuint name, GLuint type);
+struct gl_shader_program *brw_new_shader_program(GLcontext *ctx, GLuint name);
+
+GLboolean brw_do_channel_expressions(struct exec_list *instructions);
+GLboolean brw_do_vector_splitting(struct exec_list *instructions);
+
 #endif
index a78cc8b54e5316dc6d51867dac714e77d8ef159f..6a91251a80ec7219cd8bfe7f1131b499fecb4b33 100644 (file)
@@ -44,16 +44,16 @@ void brw_wm_print_value( struct brw_wm_compile *c,
       printf("undef");
    else if( value - c->vreg >= 0 &&
            value - c->vreg < BRW_WM_MAX_VREG)
-      printf("r%d", value - c->vreg);
+      printf("r%ld", (long) (value - c->vreg));
    else if (value - c->creg >= 0 &&
            value - c->creg < BRW_WM_MAX_PARAM)
-      printf("c%d", value - c->creg);
+      printf("c%ld", (long) (value - c->creg));
    else if (value - c->payload.input_interp >= 0 &&
            value - c->payload.input_interp < FRAG_ATTRIB_MAX)
-      printf("i%d", value - c->payload.input_interp);
+      printf("i%ld", (long) (value - c->payload.input_interp));
    else if (value - c->payload.depth >= 0 &&
            value - c->payload.depth < FRAG_ATTRIB_MAX)
-      printf("d%d", value - c->payload.depth);
+      printf("d%ld", (long) (value - c->payload.depth));
    else 
       printf("?");
 }
index d9fa2e63354bb7f47813c8fb5acf07b8205d93af..f3ad01b3fec3b06b08f798b44c12c62835fdef6d 100644 (file)
@@ -668,6 +668,28 @@ void emit_cmp(struct brw_compile *p,
    }
 }
 
+void emit_sign(struct brw_compile *p,
+              const struct brw_reg *dst,
+              GLuint mask,
+              const struct brw_reg *arg0)
+{
+   GLuint i;
+
+   for (i = 0; i < 4; i++) {
+      if (mask & (1<<i)) {
+        brw_MOV(p, dst[i], brw_imm_f(0.0));
+
+        brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, arg0[i], brw_imm_f(0));
+        brw_MOV(p, dst[i], brw_imm_f(-1.0));
+        brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+        brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_G, arg0[i], brw_imm_f(0));
+        brw_MOV(p, dst[i], brw_imm_f(1.0));
+        brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+      }
+   }
+}
+
 void emit_max(struct brw_compile *p,
              const struct brw_reg *dst,
              GLuint mask,
@@ -709,6 +731,27 @@ void emit_min(struct brw_compile *p,
 }
 
 
+void emit_dp2(struct brw_compile *p,
+             const struct brw_reg *dst,
+             GLuint mask,
+             const struct brw_reg *arg0,
+             const struct brw_reg *arg1)
+{
+   int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
+
+   if (!(mask & WRITEMASK_XYZW))
+      return; /* Do not emit dead code */
+
+   assert(is_power_of_two(mask & WRITEMASK_XYZW));
+
+   brw_MUL(p, brw_null_reg(), arg0[0], arg1[0]);
+
+   brw_set_saturate(p, (mask & SATURATE) ? 1 : 0);
+   brw_MAC(p, dst[dst_chan], arg0[1], arg1[1]);
+   brw_set_saturate(p, 0);
+}
+
+
 void emit_dp3(struct brw_compile *p,
              const struct brw_reg *dst,
              GLuint mask,
@@ -809,21 +852,28 @@ void emit_math1(struct brw_wm_compile *c,
                const struct brw_reg *arg0)
 {
    struct brw_compile *p = &c->func;
+   struct intel_context *intel = &p->brw->intel;
    int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
    GLuint saturate = ((mask & SATURATE) ?
                      BRW_MATH_SATURATE_SATURATE :
                      BRW_MATH_SATURATE_NONE);
+   struct brw_reg src;
+
+   if (intel->gen >= 6 && arg0[0].hstride == BRW_HORIZONTAL_STRIDE_0) {
+      /* Gen6 math requires that source and dst horizontal stride be 1.
+       *
+       */
+      src = *dst;
+      brw_MOV(p, src, arg0[0]);
+   } else {
+      src = arg0[0];
+   }
 
    if (!(mask & WRITEMASK_XYZW))
       return; /* Do not emit dead code */
 
    assert(is_power_of_two(mask & WRITEMASK_XYZW));
 
-   /* If compressed, this will write message reg 2,3 from arg0.x's 16
-    * channels.
-    */
-   brw_MOV(p, brw_message_reg(2), arg0[0]);
-
    /* Send two messages to perform all 16 operations:
     */
    brw_push_insn_state(p);
@@ -833,7 +883,7 @@ void emit_math1(struct brw_wm_compile *c,
            function,
            saturate,
            2,
-           brw_null_reg(),
+           src,
            BRW_MATH_DATA_VECTOR,
            BRW_MATH_PRECISION_FULL);
 
@@ -844,7 +894,7 @@ void emit_math1(struct brw_wm_compile *c,
               function,
               saturate,
               3,
-              brw_null_reg(),
+              sechalf(src),
               BRW_MATH_DATA_VECTOR,
               BRW_MATH_PRECISION_FULL);
    }
@@ -872,13 +922,6 @@ void emit_math2(struct brw_wm_compile *c,
 
    brw_push_insn_state(p);
 
-   brw_set_compression_control(p, BRW_COMPRESSION_NONE);
-   brw_MOV(p, brw_message_reg(2), arg0[0]);
-   if (c->dispatch_width == 16) {
-      brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF);
-      brw_MOV(p, brw_message_reg(4), sechalf(arg0[0]));
-   }
-
    brw_set_compression_control(p, BRW_COMPRESSION_NONE);
    brw_MOV(p, brw_message_reg(3), arg1[0]);
    if (c->dispatch_width == 16) {
@@ -892,7 +935,7 @@ void emit_math2(struct brw_wm_compile *c,
            function,
            saturate,
            2,
-           brw_null_reg(),
+           arg0[0],
            BRW_MATH_DATA_VECTOR,
            BRW_MATH_PRECISION_FULL);
 
@@ -905,7 +948,7 @@ void emit_math2(struct brw_wm_compile *c,
               function,
               saturate,
               4,
-              brw_null_reg(),
+              sechalf(arg0[0]),
               BRW_MATH_DATA_VECTOR,
               BRW_MATH_PRECISION_FULL);
    }
@@ -1199,6 +1242,7 @@ static void fire_fb_write( struct brw_wm_compile *c,
                           GLuint eot )
 {
    struct brw_compile *p = &c->func;
+   struct intel_context *intel = &p->brw->intel;
    struct brw_reg dst;
 
    if (c->dispatch_width == 16)
@@ -1209,6 +1253,7 @@ static void fire_fb_write( struct brw_wm_compile *c,
    /* Pass through control information:
     */
 /*  mov (8) m1.0<1>:ud   r1.0<8;8,1>:ud   { Align1 NoMask } */
+   if (intel->gen < 6) /* gen6, use headerless for fb write */
    {
       brw_push_insn_state(p);
       brw_set_mask_control(p, BRW_MASK_DISABLE); /* ? */
@@ -1222,6 +1267,7 @@ static void fire_fb_write( struct brw_wm_compile *c,
    /* Send framebuffer write message: */
 /*  send (16) null.0<1>:uw m0               r0.0<8;8,1>:uw   0x85a04000:ud    { Align1 EOT } */
    brw_fb_WRITE(p,
+               c->dispatch_width,
                dst,
                base_reg,
                retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW),
@@ -1263,8 +1309,10 @@ void emit_fb_write(struct brw_wm_compile *c,
 {
    struct brw_compile *p = &c->func;
    struct brw_context *brw = p->brw;
+   struct intel_context *intel = &brw->intel;
    GLuint nr = 2;
    GLuint channel;
+   int base_reg; /* For gen6 fb write with no header, starting from color payload directly!. */
 
    /* Reserve a space for AA - may not be needed:
     */
@@ -1276,9 +1324,40 @@ void emit_fb_write(struct brw_wm_compile *c,
     */
    brw_push_insn_state(p);
 
+   if (intel->gen >= 6)
+       base_reg = nr;
+   else
+       base_reg = 0;
+
    for (channel = 0; channel < 4; channel++) {
-      if (c->dispatch_width == 16 && brw->has_compr4) {
-        /* By setting the high bit of the MRF register number, we indicate
+      if (intel->gen >= 6) {
+        /* gen6 SIMD16 single source DP write looks like:
+         * m + 0: r0
+         * m + 1: r1
+         * m + 2: g0
+         * m + 3: g1
+         * m + 4: b0
+         * m + 5: b1
+         * m + 6: a0
+         * m + 7: a1
+         */
+        if (c->dispatch_width == 16) {
+           brw_MOV(p, brw_message_reg(nr + channel * 2), arg0[channel]);
+        } else {
+           brw_MOV(p, brw_message_reg(nr + channel), arg0[channel]);
+        }
+      } else if (c->dispatch_width == 16 && brw->has_compr4) {
+        /* pre-gen6 SIMD16 single source DP write looks like:
+         * m + 0: r0
+         * m + 1: g0
+         * m + 2: b0
+         * m + 3: a0
+         * m + 4: r1
+         * m + 5: g1
+         * m + 6: b1
+         * m + 7: a1
+         *
+         * By setting the high bit of the MRF register number, we indicate
          * that we want COMPR4 mode - instead of doing the usual destination
          * + 1 for the second half we get destination + 4.
          */
@@ -1303,7 +1382,11 @@ void emit_fb_write(struct brw_wm_compile *c,
    }
    /* skip over the regs populated above:
     */
-   nr += 8;
+   if (c->dispatch_width == 16)
+      nr += 8;
+   else
+      nr += 4;
+
    brw_pop_insn_state(p);
 
    if (c->key.source_depth_to_render_target)
@@ -1336,11 +1419,16 @@ void emit_fb_write(struct brw_wm_compile *c,
       nr += 2;
    }
 
+   if (intel->gen >= 6) {
+      /* Subtract off the message header, since we send headerless. */
+      nr -= 2;
+   }
+
    if (!c->key.runtime_check_aads_emit) {
       if (c->key.aa_dest_stencil_reg)
         emit_aa(c, arg1, 2);
 
-      fire_fb_write(c, 0, nr, target, eot);
+      fire_fb_write(c, base_reg, nr, target, eot);
    }
    else {
       struct brw_reg v1_null_ud = vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD));
@@ -1562,6 +1650,10 @@ void brw_wm_emit( struct brw_wm_compile *c )
         emit_ddxy(p, dst, dst_flags, GL_FALSE, args[0]);
         break;
 
+      case OPCODE_DP2:
+        emit_dp2(p, dst, dst_flags, args[0], args[1]);
+        break;
+
       case OPCODE_DP3:
         emit_dp3(p, dst, dst_flags, args[0], args[1]);
         break;
@@ -1673,6 +1765,10 @@ void brw_wm_emit( struct brw_wm_compile *c )
         emit_sne(p, dst, dst_flags, args[0], args[1]);
        break;
 
+      case OPCODE_SSG:
+        emit_sign(p, dst, dst_flags, args[0]);
+        break;
+
       case OPCODE_LIT:
         emit_lit(c, dst, dst_flags, args[0]);
         break;
@@ -1724,7 +1820,7 @@ void brw_wm_emit( struct brw_wm_compile *c )
 
      printf("wm-native:\n");
      for (i = 0; i < p->nr_insn; i++)
-        brw_disasm(stderr, &p->store[i], p->brw->intel.gen);
+        brw_disasm(stdout, &p->store[i], p->brw->intel.gen);
       printf("\n");
    }
 }
index 0bef874b88752f847e64dccc200de6b87529c9ef..3870bf10fcb75fca0abc7247da92645effcf0c1a 100644 (file)
@@ -88,6 +88,7 @@ static struct prog_src_register src_reg(GLuint file, GLuint idx)
    reg.RelAddr = 0;
    reg.Negate = NEGATE_NONE;
    reg.Abs = 0;
+   reg.HasIndex2 = 0;
    return reg;
 }
 
@@ -1036,13 +1037,12 @@ static void print_insns( const struct prog_instruction *insn,
    for (i = 0; i < nr; i++, insn++) {
       printf("%3d: ", i);
       if (insn->Opcode < MAX_OPCODE)
-        _mesa_print_instruction(insn);
+        _mesa_fprint_instruction_opt(stdout, insn, 0, PROG_PRINT_DEBUG, NULL);
       else if (insn->Opcode < MAX_WM_OPCODE) {
         GLuint idx = insn->Opcode - MAX_OPCODE;
 
-        _mesa_print_alu_instruction(insn,
-                                    wm_opcode_strings[idx],
-                                    3);
+        _mesa_fprint_alu_instruction(stdout, insn, wm_opcode_strings[idx],
+                                     3, PROG_PRINT_DEBUG, NULL);
       }
       else 
         printf("965 Opcode %d\n", insn->Opcode);
@@ -1061,7 +1061,8 @@ void brw_wm_pass_fp( struct brw_wm_compile *c )
 
    if (INTEL_DEBUG & DEBUG_WM) {
       printf("pre-fp:\n");
-      _mesa_print_program(&fp->program.Base); 
+      _mesa_fprint_program_opt(stdout, &fp->program.Base, PROG_PRINT_DEBUG,
+                              GL_TRUE);
       printf("\n");
    }
 
index 575f89b17faf666d722e765516f36a007bfcf2a4..c1083c594224ce43450cd12945650ec794c454a4 100644 (file)
@@ -303,13 +303,13 @@ static void prealloc_reg(struct brw_wm_compile *c)
     c->first_free_grf = 0;
 
     for (i = 0; i < 4; i++) {
-        if (i < c->key.nr_depth_regs) 
+       if (i < (c->key.nr_payload_regs + 1) / 2)
             reg = brw_vec8_grf(i * 2, 0);
         else
             reg = brw_vec8_grf(0, 0);
        set_reg(c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, i, reg);
     }
-    reg_index += 2 * c->key.nr_depth_regs;
+    reg_index += c->key.nr_payload_regs;
 
     /* constants */
     {
@@ -380,7 +380,7 @@ static void prealloc_reg(struct brw_wm_compile *c)
        }
     }
 
-    c->prog_data.first_curbe_grf = c->key.nr_depth_regs * 2;
+    c->prog_data.first_curbe_grf = c->key.nr_payload_regs;
     c->prog_data.urb_read_length = urb_read_length;
     c->prog_data.curb_read_length = c->nr_creg;
     c->emit_mask_reg = brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, reg_index, 0);
@@ -1803,12 +1803,15 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
 #define MAX_IF_DEPTH 32
 #define MAX_LOOP_DEPTH 32
     struct brw_instruction *if_inst[MAX_IF_DEPTH], *loop_inst[MAX_LOOP_DEPTH];
+    int if_depth_in_loop[MAX_LOOP_DEPTH];
     GLuint i, if_depth = 0, loop_depth = 0;
     struct brw_compile *p = &c->func;
     struct brw_indirect stack_index = brw_indirect(0, 0);
 
     c->out_of_regs = GL_FALSE;
 
+    if_depth_in_loop[loop_depth] = 0;
+
     prealloc_reg(c);
     brw_set_compression_control(p, BRW_COMPRESSION_NONE);
     brw_MOV(p, get_addr_reg(stack_index), brw_address(c->stack));
@@ -1903,6 +1906,9 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
            case OPCODE_SWZ:
                emit_alu1(p, brw_MOV, dst, dst_flags, args[0]);
                break;
+           case OPCODE_DP2:
+               emit_dp2(p, dst, dst_flags, args[0], args[1]);
+               break;
            case OPCODE_DP3:
                emit_dp3(p, dst, dst_flags, args[0], args[1]);
                break;
@@ -1971,6 +1977,9 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
                emit_sop(p, dst, dst_flags,
                         BRW_CONDITIONAL_NEQ, args[0], args[1]);
                break;
+           case OPCODE_SSG:
+               emit_sign(p, dst, dst_flags, args[0]);
+               break;
            case OPCODE_MUL:
                emit_alu2(p, brw_MUL, dst, dst_flags, args[0], args[1]);
                break;
@@ -2014,6 +2023,7 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
            case OPCODE_IF:
                assert(if_depth < MAX_IF_DEPTH);
                if_inst[if_depth++] = brw_IF(p, BRW_EXECUTE_8);
+               if_depth_in_loop[loop_depth]++;
                break;
            case OPCODE_ELSE:
                assert(if_depth > 0);
@@ -2022,6 +2032,7 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
            case OPCODE_ENDIF:
                assert(if_depth > 0);
                brw_ENDIF(p, if_inst[--if_depth]);
+               if_depth_in_loop[loop_depth]--;
                break;
            case OPCODE_BGNSUB:
                brw_save_label(p, inst->Comment, p->nr_insn);
@@ -2056,13 +2067,14 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
            case OPCODE_BGNLOOP:
                 /* XXX may need to invalidate the current_constant regs */
                loop_inst[loop_depth++] = brw_DO(p, BRW_EXECUTE_8);
+               if_depth_in_loop[loop_depth] = 0;
                break;
            case OPCODE_BRK:
-               brw_BREAK(p);
+               brw_BREAK(p, if_depth_in_loop[loop_depth]);
                brw_set_predicate_control(p, BRW_PREDICATE_NONE);
                break;
            case OPCODE_CONT:
-               brw_CONT(p);
+               brw_CONT(p, if_depth_in_loop[loop_depth]);
                brw_set_predicate_control(p, BRW_PREDICATE_NONE);
                break;
            case OPCODE_ENDLOOP: 
@@ -2082,12 +2094,10 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
                      if (inst0->header.opcode == BRW_OPCODE_BREAK &&
                         inst0->bits3.if_else.jump_count == 0) {
                        inst0->bits3.if_else.jump_count = br * (inst1 - inst0 + 1);
-                       inst0->bits3.if_else.pop_count = 0;
                      }
                      else if (inst0->header.opcode == BRW_OPCODE_CONTINUE &&
                              inst0->bits3.if_else.jump_count == 0) {
                         inst0->bits3.if_else.jump_count = br * (inst1 - inst0);
-                        inst0->bits3.if_else.pop_count = 0;
                      }
                   }
                }
@@ -2111,7 +2121,7 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
     if (INTEL_DEBUG & DEBUG_WM) {
       printf("wm-native:\n");
       for (i = 0; i < p->nr_insn; i++)
-        brw_disasm(stderr, &p->store[i], intel->gen);
+        brw_disasm(stdout, &p->store[i], intel->gen);
       printf("\n");
     }
 }
index 5e399ac62a8c88a33007b63f1cdccf4557123e32..8505ef19510535eab0d56f25ea08ae1a75d25300 100644 (file)
@@ -152,6 +152,6 @@ void brw_wm_lookup_iz( GLuint line_aa,
       reg+=2;
    }
 
-   key->nr_depth_regs = (reg+1)/2;
+   key->nr_payload_regs = reg;
 }
 
index 05de85a957e1dc79cde45247324f8848ade08453..8fc960b44567ac393c072912ba0cfd7b0626524e 100644 (file)
@@ -379,7 +379,7 @@ static void pass0_init_payload( struct brw_wm_compile *c )
    GLuint i;
 
    for (i = 0; i < 4; i++) {
-      GLuint j = i >= c->key.nr_depth_regs ? 0 : i;
+      GLuint j = i >= (c->key.nr_payload_regs + 1) / 2 ? 0 : i;
       pass0_set_fpreg_value( c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, i, 
                             &c->payload.depth[j] );
    }
index b44939402920083e2df8984e95268d7ea9100ccf..962515a99e905590d5a9b613882826a1fea12111 100644 (file)
@@ -158,6 +158,7 @@ void brw_wm_pass1( struct brw_wm_compile *c )
       case OPCODE_FLR:
       case OPCODE_FRC:
       case OPCODE_MOV:
+      case OPCODE_SSG:
       case OPCODE_SWZ:
       case OPCODE_TRUNC:
         read0 = writemask;
@@ -254,6 +255,11 @@ void brw_wm_pass1( struct brw_wm_compile *c )
         read2 = WRITEMASK_W; /* pixel w */
         break;
 
+      case OPCODE_DP2:
+        read0 = WRITEMASK_XY;
+        read1 = WRITEMASK_XY;
+        break;
+
       case OPCODE_DP3: 
         read0 = WRITEMASK_XYZ;
         read1 = WRITEMASK_XYZ;
index 31303febf09142ba621cddbbeda2285158b41606..54acb3038b5c7458e1f1b32246230a65e3e816b3 100644 (file)
@@ -76,7 +76,7 @@ static void init_registers( struct brw_wm_compile *c )
    for (j = 0; j < c->grf_limit; j++) 
       c->pass2_grf[j].nextuse = BRW_WM_MAX_INSN;
 
-   for (j = 0; j < c->key.nr_depth_regs; j++) 
+   for (j = 0; j < (c->key.nr_payload_regs + 1) / 2; j++)
       prealloc_reg(c, &c->payload.depth[j], i++);
 
    for (j = 0; j < c->nr_creg; j++) 
@@ -101,7 +101,7 @@ static void init_registers( struct brw_wm_compile *c )
 
    assert(nr_interp_regs >= 1);
 
-   c->prog_data.first_curbe_grf = c->key.nr_depth_regs * 2;
+   c->prog_data.first_curbe_grf = ALIGN(c->key.nr_payload_regs, 2);
    c->prog_data.urb_read_length = nr_interp_regs * 2;
    c->prog_data.curb_read_length = c->nr_creg * 2;
 
index c1cf4db1caeba957d7a1f010861d60a0c727f376..6699d0a73e6501bb3a688c4fdb7a2dfb0ac21a85 100644 (file)
@@ -104,8 +104,22 @@ wm_unit_populate_key(struct brw_context *brw, struct brw_wm_unit_key *key)
    key->uses_kill = fp->UsesKill || ctx->Color.AlphaEnabled;
    key->is_glsl = bfp->isGLSL;
 
-   /* temporary sanity check assertion */
-   ASSERT(bfp->isGLSL == brw_wm_is_glsl(fp));
+   /* If using the fragment shader backend, the program is always
+    * 8-wide.
+    */
+   if (ctx->Shader.CurrentProgram) {
+      int i;
+
+      for (i = 0; i < ctx->Shader.CurrentProgram->_NumLinkedShaders; i++) {
+        struct brw_shader *shader =
+           (struct brw_shader *)ctx->Shader.CurrentProgram->_LinkedShaders[i];;
+
+        if (shader->base.Type == GL_FRAGMENT_SHADER &&
+            shader->ir != NULL) {
+           key->is_glsl = GL_TRUE;
+        }
+      }
+   }
 
    /* _NEW_DEPTH */
    key->stats_wm = intel->stats_wm;
index f7acad6912950aa9099db4899fd05e08db335f9a..26f1070a16407f778c46da5f56c14a28db4eee79 100644 (file)
@@ -267,9 +267,9 @@ static void upload_cc_state_pointers(struct brw_context *brw)
 
    BEGIN_BATCH(4);
    OUT_BATCH(CMD_3D_CC_STATE_POINTERS << 16 | (4 - 2));
-   OUT_RELOC(brw->cc.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1);
    OUT_RELOC(brw->cc.blend_state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1);
    OUT_RELOC(brw->cc.depth_stencil_state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1);
+   OUT_RELOC(brw->cc.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1);
    ADVANCE_BATCH();
 
    intel_batchbuffer_emit_mi_flush(intel->batch);
index 863c85449d9adc04061ef17fbb64ee01316f0e21..2cd640de17526e15b2652fc8ab41c9037416e9bc 100644 (file)
 #include "program/prog_statevars.h"
 #include "intel_batchbuffer.h"
 
+static void
+prepare_wm_constants(struct brw_context *brw)
+{
+   struct intel_context *intel = &brw->intel;
+   GLcontext *ctx = &intel->ctx;
+   const struct brw_fragment_program *fp =
+      brw_fragment_program_const(brw->fragment_program);
+
+   drm_intel_bo_unreference(brw->wm.push_const_bo);
+   brw->wm.push_const_bo = NULL;
+
+   /* Updates the ParamaterValues[i] pointers for all parameters of the
+    * basic type of PROGRAM_STATE_VAR.
+    */
+   /* XXX: Should this happen somewhere before to get our state flag set? */
+   _mesa_load_state_parameters(ctx, fp->program.Base.Parameters);
+
+   if (brw->wm.prog_data->nr_params != 0) {
+      float *constants;
+      unsigned int i;
+
+      brw->wm.push_const_bo = drm_intel_bo_alloc(intel->bufmgr,
+                                                "WM constant_bo",
+                                                brw->wm.prog_data->nr_params *
+                                                sizeof(float),
+                                                4096);
+      drm_intel_gem_bo_map_gtt(brw->wm.push_const_bo);
+      constants = brw->wm.push_const_bo->virtual;
+      for (i = 0; i < brw->wm.prog_data->nr_params; i++) {
+        constants[i] = *brw->wm.prog_data->param[i];
+      }
+      drm_intel_gem_bo_unmap_gtt(brw->wm.push_const_bo);
+   }
+}
+
+const struct brw_tracked_state gen6_wm_constants = {
+   .dirty = {
+      .mesa  = _NEW_PROGRAM_CONSTANTS,
+      .brw   = 0,
+      .cache = 0,
+   },
+   .prepare = prepare_wm_constants,
+};
+
 static void
 upload_wm_state(struct brw_context *brw)
 {
@@ -40,12 +84,9 @@ upload_wm_state(struct brw_context *brw)
    GLcontext *ctx = &intel->ctx;
    const struct brw_fragment_program *fp =
       brw_fragment_program_const(brw->fragment_program);
-   unsigned int nr_params = fp->program.Base.Parameters->NumParameters;
-   drm_intel_bo *constant_bo;
-   int i;
    uint32_t dw2, dw4, dw5, dw6;
 
-   if (fp->use_const_buffer || nr_params == 0) {
+   if (fp->use_const_buffer || brw->wm.prog_data->nr_params == 0) {
       /* Disable the push constant buffers. */
       BEGIN_BATCH(5);
       OUT_BATCH(CMD_3D_CONSTANT_PS_STATE << 16 | (5 - 2));
@@ -55,35 +96,17 @@ upload_wm_state(struct brw_context *brw)
       OUT_BATCH(0);
       ADVANCE_BATCH();
    } else {
-      /* Updates the ParamaterValues[i] pointers for all parameters of the
-       * basic type of PROGRAM_STATE_VAR.
-       */
-      _mesa_load_state_parameters(ctx, fp->program.Base.Parameters);
-
-      constant_bo = drm_intel_bo_alloc(intel->bufmgr, "WM constant_bo",
-                                      nr_params * 4 * sizeof(float),
-                                      4096);
-      drm_intel_gem_bo_map_gtt(constant_bo);
-      for (i = 0; i < nr_params; i++) {
-        memcpy((char *)constant_bo->virtual + i * 4 * sizeof(float),
-               fp->program.Base.Parameters->ParameterValues[i],
-               4 * sizeof(float));
-      }
-      drm_intel_gem_bo_unmap_gtt(constant_bo);
-
       BEGIN_BATCH(5);
       OUT_BATCH(CMD_3D_CONSTANT_PS_STATE << 16 |
                GEN6_CONSTANT_BUFFER_0_ENABLE |
                (5 - 2));
-      OUT_RELOC(constant_bo,
+      OUT_RELOC(brw->wm.push_const_bo,
                I915_GEM_DOMAIN_RENDER, 0, /* XXX: bad domain */
-               ALIGN(nr_params, 2) / 2 - 1);
+               ALIGN(brw->wm.prog_data->nr_params, 8) / 8 - 1);
       OUT_BATCH(0);
       OUT_BATCH(0);
       OUT_BATCH(0);
       ADVANCE_BATCH();
-
-      drm_intel_bo_unreference(constant_bo);
    }
 
    intel_batchbuffer_emit_mi_flush(intel->batch);
index 8ab41f8d279086672bec19f423ebb7dadce9c0e4..117d4daf3babb23147763eaf412a6ba2f7f93bfc 100644 (file)
@@ -202,6 +202,9 @@ intel_bufferobj_subdata(GLcontext * ctx,
    struct intel_context *intel = intel_context(ctx);
    struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
 
+   if (size == 0)
+      return;
+
    assert(intel_obj);
 
    if (intel_obj->region)
@@ -426,6 +429,9 @@ intel_bufferobj_flush_mapped_range(GLcontext *ctx, GLenum target,
    if (intel_obj->range_map_buffer == NULL)
       return;
 
+   if (length == 0)
+      return;
+
    temp_bo = drm_intel_bo_alloc(intel->bufmgr, "range map flush", length, 64);
 
    drm_intel_bo_subdata(temp_bo, 0, length, intel_obj->range_map_buffer);
index 72a74322ee553b03ae92dcf320cfcefc2489f476..b5f180bbc883ff3138dc06c7629a85d3e3403066 100644 (file)
@@ -73,6 +73,7 @@
 
 #define PCI_CHIP_SANDYBRIDGE           0x0102
 #define PCI_CHIP_SANDYBRIDGE_M         0x0106
+#define PCI_CHIP_SANDYBRIDGE_M_D0      0x0126
 
 #define IS_MOBILE(devid)       (devid == PCI_CHIP_I855_GM || \
                                 devid == PCI_CHIP_I915_GM || \
 #define IS_IRONLAKE(devid)     IS_GEN5(devid)
 
 #define IS_GEN6(devid)         (devid == PCI_CHIP_SANDYBRIDGE || \
-                                devid == PCI_CHIP_SANDYBRIDGE_M)
+                                devid == PCI_CHIP_SANDYBRIDGE_M || \
+                                devid == PCI_CHIP_SANDYBRIDGE_M_D0)
 
 #define IS_965(devid)          (IS_GEN4(devid) || \
                                 IS_G4X(devid) || \
index e19f44035fdd5f21b465eefa955554d38a5e6e69..a9ba93d24bb93eee0972a2ac59345d8ed7554ab1 100644 (file)
@@ -377,7 +377,8 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
          intel_region_reference(&region, depth_region);
        }
        else
-          region = intel_region_alloc_for_handle(intel, buffers[i].cpp,
+          region = intel_region_alloc_for_handle(intel->intelScreen,
+                                                buffers[i].cpp,
                                                 drawable->w,
                                                 drawable->h,
                                                 buffers[i].pitch / buffers[i].cpp,
@@ -720,6 +721,8 @@ intelInitContext(struct intel_context *intel,
    ctx->Const.MaxPointSizeAA = 3.0;
    ctx->Const.PointSizeGranularity = 1.0;
 
+   ctx->Const.MaxSamples = 1.0;
+
    /* reinitialize the context point state.
     * It depend on constants in __GLcontextRec::Const
     */
index c7ac2de01e6bb7c8ad5c39ce60b78bad8264819d..28d53284fdf438d45d1eac2aafc7ca3774bb7c2d 100644 (file)
 
 #include "main/mtypes.h"
 #include "main/mm.h"
-#include "texmem.h"
 #include "dri_metaops.h"
+
+#ifdef __cplusplus
+extern "C" {
+       /* Evil hack for using libdrm in a c++ compiler. */
+       #define virtual virt
+#endif
+
 #include "drm.h"
 #include "intel_bufmgr.h"
 
 #include "intel_screen.h"
 #include "intel_tex_obj.h"
 #include "i915_drm.h"
+
+#ifdef __cplusplus
+       #undef virtual
+}
+#endif
+
 #include "tnl/t_vertex.h"
 
 #define TAG(x) intel##x
index edba1fc2f2b53304a1a1ce2bf3140b18fee26afb..bf22a423fcb98166286bcbb6fde4f6d6ffb6f939 100644 (file)
@@ -50,8 +50,9 @@
 #define need_GL_EXT_cull_vertex
 #define need_GL_EXT_draw_buffers2
 #define need_GL_EXT_fog_coord
-#define need_GL_EXT_framebuffer_object
 #define need_GL_EXT_framebuffer_blit
+#define need_GL_EXT_framebuffer_multisample
+#define need_GL_EXT_framebuffer_object
 #define need_GL_EXT_gpu_program_parameters
 #define need_GL_EXT_point_parameters
 #define need_GL_EXT_provoking_vertex
@@ -111,6 +112,7 @@ static const struct dri_extension card_extensions[] = {
    { "GL_EXT_cull_vertex",                GL_EXT_cull_vertex_functions },
    { "GL_EXT_framebuffer_blit",         GL_EXT_framebuffer_blit_functions },
    { "GL_EXT_framebuffer_object",       GL_EXT_framebuffer_object_functions },
+   { "GL_EXT_framebuffer_multisample",    GL_EXT_framebuffer_multisample_functions },
    { "GL_EXT_fog_coord",                  GL_EXT_fog_coord_functions },
    { "GL_EXT_gpu_program_parameters",     GL_EXT_gpu_program_parameters_functions },
    { "GL_EXT_packed_depth_stencil",       NULL },
index 4a83886fc16206f899b02cee30ff97aa189d8b4a..2693b5fa72e5ec9eb1cbe406dcd4761b7497c492 100644 (file)
@@ -137,27 +137,21 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
       rb->Format = MESA_FORMAT_A8;
       rb->DataType = GL_UNSIGNED_BYTE;
       break;
+   case GL_DEPTH_COMPONENT16:
+      rb->Format = MESA_FORMAT_Z16;
+      rb->DataType = GL_UNSIGNED_SHORT;
+      break;
    case GL_STENCIL_INDEX:
    case GL_STENCIL_INDEX1_EXT:
    case GL_STENCIL_INDEX4_EXT:
    case GL_STENCIL_INDEX8_EXT:
    case GL_STENCIL_INDEX16_EXT:
-      /* alloc a depth+stencil buffer */
-      rb->Format = MESA_FORMAT_S8_Z24;
-      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
-      break;
-   case GL_DEPTH_COMPONENT16:
-      rb->Format = MESA_FORMAT_Z16;
-      rb->DataType = GL_UNSIGNED_SHORT;
-      break;
    case GL_DEPTH_COMPONENT:
    case GL_DEPTH_COMPONENT24:
    case GL_DEPTH_COMPONENT32:
-      rb->Format = MESA_FORMAT_S8_Z24;
-      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
-      break;
    case GL_DEPTH_STENCIL_EXT:
    case GL_DEPTH24_STENCIL8_EXT:
+      /* alloc a depth+stencil buffer */
       rb->Format = MESA_FORMAT_S8_Z24;
       rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
       break;
@@ -182,7 +176,7 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
    /* alloc hardware renderbuffer */
    DBG("Allocating %d x %d Intel RBO\n", width, height);
 
-   irb->region = intel_region_alloc(intel, I915_TILING_NONE, cpp,
+   irb->region = intel_region_alloc(intel->intelScreen, I915_TILING_NONE, cpp,
                                    width, height, GL_TRUE);
    if (!irb->region)
       return GL_FALSE;       /* out of memory? */
index 39ac0205fa1e2b71cdaa333d6734721b0853f80c..d316d34d6900e2e2994309d9e943defbe83f2dad 100644 (file)
@@ -30,6 +30,7 @@
 #include "intel_regions.h"
 #include "intel_tex_layout.h"
 #include "main/enums.h"
+#include "main/formats.h"
 
 #define FILE_DEBUG_FLAG DEBUG_MIPTREE
 
@@ -136,7 +137,7 @@ intel_miptree_create(struct intel_context *intel,
       return NULL;
    }
 
-   mt->region = intel_region_alloc(intel,
+   mt->region = intel_region_alloc(intel->intelScreen,
                                   tiling,
                                   mt->cpp,
                                   mt->total_width,
index 680d18ba2999eac1f6c5c379a36091f6838f1b3a..e87e29462c38934794bad322af12160ceb4b5d60 100644 (file)
@@ -142,10 +142,10 @@ intel_region_unmap(struct intel_context *intel, struct intel_region *region)
 }
 
 static struct intel_region *
-intel_region_alloc_internal(struct intel_context *intel,
+intel_region_alloc_internal(struct intel_screen *screen,
                            GLuint cpp,
                            GLuint width, GLuint height, GLuint pitch,
-                           drm_intel_bo *buffer)
+                           uint32_t tiling, drm_intel_bo *buffer)
 {
    struct intel_region *region;
 
@@ -164,44 +164,52 @@ intel_region_alloc_internal(struct intel_context *intel,
    region->pitch = pitch;
    region->refcount = 1;
    region->buffer = buffer;
-
-   /* Default to no tiling */
-   region->tiling = I915_TILING_NONE;
+   region->tiling = tiling;
+   region->screen = screen;
 
    _DBG("%s <-- %p\n", __FUNCTION__, region);
    return region;
 }
 
 struct intel_region *
-intel_region_alloc(struct intel_context *intel,
+intel_region_alloc(struct intel_screen *screen,
                   uint32_t tiling,
                    GLuint cpp, GLuint width, GLuint height,
                   GLboolean expect_accelerated_upload)
 {
    drm_intel_bo *buffer;
-   struct intel_region *region;
    unsigned long flags = 0;
    unsigned long aligned_pitch;
 
    if (expect_accelerated_upload)
       flags |= BO_ALLOC_FOR_RENDER;
 
-   buffer = drm_intel_bo_alloc_tiled(intel->bufmgr, "region",
+   buffer = drm_intel_bo_alloc_tiled(screen->bufmgr, "region",
                                     width, height, cpp,
                                     &tiling, &aligned_pitch, flags);
 
-   region = intel_region_alloc_internal(intel, cpp, width, height,
-                                       aligned_pitch / cpp, buffer);
-   if (region == NULL)
-      return region;
+   return intel_region_alloc_internal(screen, cpp, width, height,
+                                     aligned_pitch / cpp, tiling, buffer);
+}
 
-   region->tiling = tiling;
+GLboolean
+intel_region_flink(struct intel_region *region, uint32_t *name)
+{
+   if (region->name == 0) {
+      if (drm_intel_bo_flink(region->buffer, &region->name))
+        return GL_FALSE;
+      
+      _mesa_HashInsert(region->screen->named_regions,
+                      region->name, region);
+   }
 
-   return region;
+   *name = region->name;
+
+   return GL_TRUE;
 }
 
 struct intel_region *
-intel_region_alloc_for_handle(struct intel_context *intel,
+intel_region_alloc_for_handle(struct intel_screen *screen,
                              GLuint cpp,
                              GLuint width, GLuint height, GLuint pitch,
                              GLuint handle, const char *name)
@@ -209,9 +217,9 @@ intel_region_alloc_for_handle(struct intel_context *intel,
    struct intel_region *region, *dummy;
    drm_intel_bo *buffer;
    int ret;
-   uint32_t bit_6_swizzle;
+   uint32_t bit_6_swizzle, tiling;
 
-   region = _mesa_HashLookup(intel->intelScreen->named_regions, handle);
+   region = _mesa_HashLookup(screen->named_regions, handle);
    if (region != NULL) {
       dummy = NULL;
       if (region->width != width || region->height != height ||
@@ -225,25 +233,26 @@ intel_region_alloc_for_handle(struct intel_context *intel,
       return dummy;
    }
 
-   buffer = intel_bo_gem_create_from_name(intel->bufmgr, name, handle);
-
-   region = intel_region_alloc_internal(intel, cpp,
-                                       width, height, pitch, buffer);
-   if (region == NULL)
-      return region;
-
-   ret = drm_intel_bo_get_tiling(region->buffer, &region->tiling,
-                                &bit_6_swizzle);
+   buffer = intel_bo_gem_create_from_name(screen->bufmgr, name, handle);
+   if (buffer == NULL)
+      return NULL;
+   ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle);
    if (ret != 0) {
       fprintf(stderr, "Couldn't get tiling of buffer %d (%s): %s\n",
              handle, name, strerror(-ret));
-      intel_region_release(&region);
+      drm_intel_bo_unreference(buffer);
+      return NULL;
+   }
+
+   region = intel_region_alloc_internal(screen, cpp,
+                                       width, height, pitch, tiling, buffer);
+   if (region == NULL) {
+      drm_intel_bo_unreference(buffer);
       return NULL;
    }
 
    region->name = handle;
-   region->screen = intel->intelScreen;
-   _mesa_HashInsert(intel->intelScreen->named_regions, handle, region);
+   _mesa_HashInsert(screen->named_regions, handle, region);
 
    return region;
 }
index 6bbed32f2a29ac553ac02bf7a404c908abcaa22c..8464a5e937d205fdf6c077e0cadfee4e90bd9d68 100644 (file)
@@ -76,18 +76,21 @@ struct intel_region
 /* Allocate a refcounted region.  Pointers to regions should only be
  * copied by calling intel_reference_region().
  */
-struct intel_region *intel_region_alloc(struct intel_context *intel,
+struct intel_region *intel_region_alloc(struct intel_screen *screen,
                                         uint32_t tiling,
                                        GLuint cpp, GLuint width,
                                         GLuint height,
                                        GLboolean expect_accelerated_upload);
 
 struct intel_region *
-intel_region_alloc_for_handle(struct intel_context *intel,
+intel_region_alloc_for_handle(struct intel_screen *screen,
                              GLuint cpp,
                              GLuint width, GLuint height, GLuint pitch,
                              unsigned int handle, const char *name);
 
+GLboolean
+intel_region_flink(struct intel_region *region, uint32_t *name);
+
 void intel_region_reference(struct intel_region **dst,
                             struct intel_region *src);
 
index 15a465c6402ae9b4bdb47a565251d554fd55e1fb..0a542a7303d71fcf988b877cdbba4cf8bfbdc17a 100644 (file)
@@ -70,7 +70,7 @@ PUBLIC const char __driConfigOptions[] =
         DRI_CONF_DESC(en, "Enable early Z in classic mode (unstable, 945-only).")
       DRI_CONF_OPT_END
 
-      DRI_CONF_OPT_BEGIN(fragment_shader, bool, false)
+      DRI_CONF_OPT_BEGIN(fragment_shader, bool, true)
         DRI_CONF_DESC(en, "Enable limited ARB_fragment_shader support on 915/945.")
       DRI_CONF_OPT_END
 
@@ -159,7 +159,8 @@ intel_create_image_from_name(__DRIcontext *context,
     image->data = loaderPrivate;
     cpp = _mesa_get_format_bytes(image->format);
 
-    image->region = intel_region_alloc_for_handle(intel, cpp, width, height,
+    image->region = intel_region_alloc_for_handle(intel->intelScreen,
+                                                 cpp, width, height,
                                                  pitch, name, "image");
     if (image->region == NULL) {
        FREE(image);
@@ -206,11 +207,79 @@ intel_destroy_image(__DRIimage *image)
     FREE(image);
 }
 
+static __DRIimage *
+intel_create_image(__DRIscreen *screen,
+                  int width, int height, int format,
+                  unsigned int use,
+                  void *loaderPrivate)
+{
+   __DRIimage *image;
+   struct intel_screen *intelScreen = screen->private;
+   int cpp;
+
+   image = CALLOC(sizeof *image);
+   if (image == NULL)
+      return NULL;
+
+   switch (format) {
+   case __DRI_IMAGE_FORMAT_RGB565:
+      image->format = MESA_FORMAT_RGB565;
+      image->internal_format = GL_RGB;
+      image->data_type = GL_UNSIGNED_BYTE;
+      break;
+   case __DRI_IMAGE_FORMAT_XRGB8888:
+      image->format = MESA_FORMAT_XRGB8888;
+      image->internal_format = GL_RGB;
+      image->data_type = GL_UNSIGNED_BYTE;
+      break;
+   case __DRI_IMAGE_FORMAT_ARGB8888:
+      image->format = MESA_FORMAT_ARGB8888;
+      image->internal_format = GL_RGBA;
+      image->data_type = GL_UNSIGNED_BYTE;
+      break;
+   default:
+      free(image);
+      return NULL;
+   }
+
+   image->data = loaderPrivate;
+   cpp = _mesa_get_format_bytes(image->format);
+
+   image->region =
+      intel_region_alloc(intelScreen, I915_TILING_NONE,
+                        cpp, width, height, GL_TRUE);
+   if (image->region == NULL) {
+      FREE(image);
+      return NULL;
+   }
+   
+   return image;
+}
+
+static GLboolean
+intel_query_image(__DRIimage *image, int attrib, int *value)
+{
+   switch (attrib) {
+   case __DRI_IMAGE_ATTRIB_STRIDE:
+      *value = image->region->pitch * image->region->cpp;
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_HANDLE:
+      *value = image->region->buffer->handle;
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_NAME:
+      return intel_region_flink(image->region, (uint32_t *) value);
+   default:
+      return GL_FALSE;
+   }
+}
+
 static struct __DRIimageExtensionRec intelImageExtension = {
     { __DRI_IMAGE, __DRI_IMAGE_VERSION },
     intel_create_image_from_name,
     intel_create_image_from_renderbuffer,
     intel_destroy_image,
+    intel_create_image,
+    intel_query_image
 };
 
 static const __DRIextension *intelScreenExtensions[] = {
index 4bb012dc65e023f744f11b67809c078bba96e5f8..cd77dd5b8e47e5e85ec20f47ea188e01b1af8fdd 100644 (file)
@@ -31,8 +31,6 @@
 #include "main/mtypes.h"
 #include "main/formats.h"
 #include "intel_context.h"
-#include "texmem.h"
-
 
 void intelInitTextureFuncs(struct dd_function_table *functions);
 
index 4ec864c181c23165b10d44da033d278e6362218c..6452fe218e570d64d806a4b699a121d533eb3e40 100644 (file)
@@ -138,5 +138,7 @@ nouveau_driver_functions_init(struct dd_function_table *functions)
        functions->DrawPixels = _mesa_meta_DrawPixels;
        functions->CopyPixels = _mesa_meta_CopyPixels;
        functions->Bitmap = _mesa_meta_Bitmap;
+#if FEATURE_EXT_framebuffer_blit
        functions->BlitFramebuffer = _mesa_meta_BlitFramebuffer;
+#endif
 }
index bd1273beea709805225688220d57af4ae0192255..32d8f2d0f9bbcca1ad0c8e6e981c343b47c0c244 100644 (file)
@@ -262,10 +262,12 @@ nouveau_finish_render_texture(GLcontext *ctx,
 void
 nouveau_fbo_functions_init(struct dd_function_table *functions)
 {
+#if FEATURE_EXT_framebuffer_object
        functions->NewFramebuffer = nouveau_framebuffer_new;
        functions->NewRenderbuffer = nouveau_renderbuffer_new;
        functions->BindFramebuffer = nouveau_bind_framebuffer;
        functions->FramebufferRenderbuffer = nouveau_framebuffer_renderbuffer;
        functions->RenderTexture = nouveau_render_texture;
        functions->FinishRenderTexture = nouveau_finish_render_texture;
+#endif
 }
index 3167d49bcae7a5acc5e4e4c12e0df717478e5b03..d0eb170784502525832651847a52abeb588793a1 100644 (file)
@@ -23,6 +23,7 @@ C_SOURCES = \
                radeon_dataflow_deadcode.c \
                radeon_dataflow_swizzles.c \
                radeon_optimize.c \
+               radeon_remove_constants.c \
                radeon_rename_regs.c \
                r3xx_fragprog.c \
                r300_fragprog.c \
index c6f47a6f8a4940e8d8245114fa83d1e2aacc0fd1..847857b1425b675bbfe2b71cd347c48d7641a1ea 100755 (executable)
@@ -22,6 +22,7 @@ r300compiler = env.ConvenienceLibrary(
         'radeon_pair_schedule.c',
         'radeon_pair_regalloc.c',
         'radeon_optimize.c',
+        'radeon_remove_constants.c',
         'radeon_rename_regs.c',
         'radeon_emulate_branches.c',
         'radeon_emulate_loops.c',
index d2fa816894ce109e157eb9d33bc571995bfc09c5..8613ec51091f3314d017e20a272239108f8759ee 100644 (file)
@@ -30,6 +30,7 @@
 #include "radeon_program_alu.h"
 #include "radeon_program_tex.h"
 #include "radeon_rename_regs.h"
+#include "radeon_remove_constants.h"
 #include "r300_fragprog.h"
 #include "r300_fragprog_swizzle.h"
 #include "r500_fragprog.h"
@@ -180,6 +181,13 @@ void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c)
 
        debug_program_log(c, "after dataflow passes");
 
+       if (c->Base.remove_unused_constants) {
+               rc_remove_unused_constants(&c->Base,
+                                          &c->code->constants_remap_table);
+
+               debug_program_log(c, "after constants cleanup");
+       }
+
        if(!c->Base.is_r500) {
                /* This pass makes it easier for the scheduler to group TEX
                 * instructions and reduces the chances of creating too
@@ -224,4 +232,14 @@ void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c)
                        r300FragmentProgramDump(c->code);
                }
        }
+
+       /* Check the number of constants. */
+       if (!c->Base.Error) {
+               unsigned max = c->Base.is_r500 ? R500_PFS_NUM_CONST_REGS : R300_PFS_NUM_CONST_REGS;
+
+               if (c->Base.Program.Constants.Count > max) {
+                       rc_error(&c->Base, "Too many constants. Max: %i, Got: %i\n",
+                                max, c->Base.Program.Constants.Count);
+               }
+       }
 }
index 666c9c2a7a9439f9bb39a84900848c9588a03fb6..b05b3aabf308918c5880d897b31f7ef98e27fc49 100644 (file)
@@ -31,6 +31,7 @@
 #include "radeon_swizzle.h"
 #include "radeon_emulate_branches.h"
 #include "radeon_emulate_loops.h"
+#include "radeon_remove_constants.h"
 
 struct loop {
        int BgnLoop;
@@ -465,7 +466,7 @@ static void translate_vertex_program(struct r300_vertex_program_compiler * compi
 {
        struct rc_instruction *rci;
 
-       struct loop * loops;
+       struct loop * loops = NULL;
        int current_loop_depth = 0;
        int loops_reserved = 0;
 
@@ -484,6 +485,21 @@ static void translate_vertex_program(struct r300_vertex_program_compiler * compi
                if (!valid_dst(compiler->code, &vpi->DstReg))
                        continue;
 
+               if (rc_get_opcode_info(vpi->Opcode)->HasDstReg) {
+                       /* Relative addressing of destination operands is not supported yet. */
+                       if (vpi->DstReg.RelAddr) {
+                               rc_error(&compiler->Base, "Vertex program does not support relative "
+                                        "addressing of destination operands (yet).\n");
+                               return;
+                       }
+
+                       /* Neither is Saturate. */
+                       if (vpi->SaturateMode != RC_SATURATE_NONE) {
+                               rc_error(&compiler->Base, "Vertex program does not support the Saturate "
+                                        "modifier (yet).\n");
+                       }
+               }
+
                if (compiler->code->length >= R500_VS_MAX_ALU_DWORDS ||
                    (compiler->code->length >= R300_VS_MAX_ALU_DWORDS && !compiler->Base.is_r500)) {
                        rc_error(&compiler->Base, "Vertex program has too many instructions\n");
@@ -543,10 +559,16 @@ static void translate_vertex_program(struct r300_vertex_program_compiler * compi
                }
                case RC_OPCODE_ENDLOOP:
                {
-                       struct loop * l = &loops[current_loop_depth - 1];
-                       unsigned int act_addr = l->BgnLoop - 1;
-                       unsigned int last_addr = (compiler->code->length / 4) - 1;
-                       unsigned int ret_addr = l->BgnLoop;
+                       struct loop * l;
+                       unsigned int act_addr;
+                       unsigned int last_addr;
+                       unsigned int ret_addr;
+
+                       assert(loops);
+                       l = &loops[current_loop_depth - 1];
+                       act_addr = l->BgnLoop - 1;
+                       last_addr = (compiler->code->length / 4) - 1;
+                       ret_addr = l->BgnLoop;
 
                        if (loops_reserved >= R300_VS_MAX_FC_OPS) {
                                rc_error(&compiler->Base,
@@ -624,10 +646,9 @@ static void allocate_temporary_registers(struct r300_vertex_program_compiler * c
        struct temporary_allocation * ta;
        unsigned int i, j;
 
-       compiler->code->num_temporaries = 0;
        memset(hwtemps, 0, sizeof(hwtemps));
 
-       /* Pass 1: Count original temporaries and allocate structures */
+       /* Pass 1: Count original temporaries. */
        for(inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) {
                const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
 
@@ -645,12 +666,30 @@ static void allocate_temporary_registers(struct r300_vertex_program_compiler * c
                        }
                }
        }
+       compiler->code->num_temporaries = num_orig_temps;
+
+       /* Pass 2: If there is relative addressing of temporaries, we cannot change register indices. Give up. */
+       for (inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) {
+               const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->U.I.Opcode);
+
+               if (opcode->HasDstReg)
+                       if (inst->U.I.DstReg.RelAddr)
+                               return;
 
+               for (i = 0; i < opcode->NumSrcRegs; ++i) {
+                       if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY &&
+                           inst->U.I.SrcReg[i].RelAddr) {
+                               return;
+                       }
+               }
+       }
+
+       compiler->code->num_temporaries = 0;
        ta = (struct temporary_allocation*)memory_pool_malloc(&compiler->Base.Pool,
                        sizeof(struct temporary_allocation) * num_orig_temps);
        memset(ta, 0, sizeof(struct temporary_allocation) * num_orig_temps);
 
-       /* Pass 2: Determine original temporary lifetimes */
+       /* Pass 3: Determine original temporary lifetimes */
        for(inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) {
                const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
                /* Instructions inside of loops need to use the ENDLOOP
@@ -685,7 +724,7 @@ static void allocate_temporary_registers(struct r300_vertex_program_compiler * c
                }
        }
 
-       /* Pass 3: Register allocation */
+       /* Pass 4: Register allocation */
        for(inst = compiler->Base.Program.Instructions.Next; inst != &compiler->Base.Program.Instructions; inst = inst->Next) {
                const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
 
@@ -853,6 +892,76 @@ static int swizzle_is_native(rc_opcode opcode, struct rc_src_register reg)
        return 1;
 }
 
+static void transform_negative_addressing(struct r300_vertex_program_compiler *c,
+                                         struct rc_instruction *arl,
+                                         struct rc_instruction *end,
+                                         int min_offset)
+{
+       struct rc_instruction *inst, *add;
+       unsigned const_swizzle;
+
+       /* Transform ARL */
+       add = rc_insert_new_instruction(&c->Base, arl->Prev);
+       add->U.I.Opcode = RC_OPCODE_ADD;
+       add->U.I.DstReg.File = RC_FILE_TEMPORARY;
+       add->U.I.DstReg.Index = rc_find_free_temporary(&c->Base);
+       add->U.I.DstReg.WriteMask = RC_MASK_X;
+       add->U.I.SrcReg[0] = arl->U.I.SrcReg[0];
+       add->U.I.SrcReg[1].File = RC_FILE_CONSTANT;
+       add->U.I.SrcReg[1].Index = rc_constants_add_immediate_scalar(&c->Base.Program.Constants,
+                                                                    min_offset, &const_swizzle);
+       add->U.I.SrcReg[1].Swizzle = const_swizzle;
+
+       arl->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
+       arl->U.I.SrcReg[0].Index = add->U.I.DstReg.Index;
+       arl->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XXXX;
+
+       /* Rewrite offsets up to and excluding inst. */
+       for (inst = arl->Next; inst != end; inst = inst->Next) {
+               const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
+
+               for (unsigned i = 0; i < opcode->NumSrcRegs; i++)
+                       if (inst->U.I.SrcReg[i].RelAddr)
+                               inst->U.I.SrcReg[i].Index -= min_offset;
+       }
+}
+
+static void rc_emulate_negative_addressing(struct r300_vertex_program_compiler *c)
+{
+       struct rc_instruction *inst, *lastARL = NULL;
+       int min_offset = 0;
+
+       for (inst = c->Base.Program.Instructions.Next; inst != &c->Base.Program.Instructions; inst = inst->Next) {
+               const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
+
+               if (inst->U.I.Opcode == RC_OPCODE_ARL) {
+                       if (lastARL != NULL && min_offset < 0)
+                               transform_negative_addressing(c, lastARL, inst, min_offset);
+
+                       lastARL = inst;
+                       min_offset = 0;
+                       continue;
+               }
+
+               for (unsigned i = 0; i < opcode->NumSrcRegs; i++) {
+                       if (inst->U.I.SrcReg[i].RelAddr &&
+                           inst->U.I.SrcReg[i].Index < 0) {
+                               /* ARL must precede any indirect addressing. */
+                               if (lastARL == NULL) {
+                                       rc_error(&c->Base, "Vertex shader: Found relative addressing without ARL.");
+                                       return;
+                               }
+
+                               if (inst->U.I.SrcReg[i].Index < min_offset)
+                                       min_offset = inst->U.I.SrcReg[i].Index;
+                       }
+               }
+       }
+
+       if (lastARL != NULL && min_offset < 0)
+               transform_negative_addressing(c, lastARL, inst, min_offset);
+}
+
 static void debug_program_log(struct r300_vertex_program_compiler* c, const char * where)
 {
        if (c->Base.Debug) {
@@ -868,44 +977,56 @@ static struct rc_swizzle_caps r300_vertprog_swizzle_caps = {
 };
 
 
-void r3xx_compile_vertex_program(struct r300_vertex_program_compiler* compiler)
+void r3xx_compile_vertex_program(struct r300_vertex_program_compiler *c)
 {
        struct emulate_loop_state loop_state;
 
-       compiler->Base.SwizzleCaps = &r300_vertprog_swizzle_caps;
+       c->Base.SwizzleCaps = &r300_vertprog_swizzle_caps;
 
-       addArtificialOutputs(compiler);
+       addArtificialOutputs(c);
 
-       debug_program_log(compiler, "before compilation");
+       debug_program_log(c, "before compilation");
 
-       if (compiler->Base.is_r500)
-               rc_transform_loops(&compiler->Base, &loop_state, R500_VS_MAX_ALU);
+       if (c->Base.is_r500)
+               rc_transform_loops(&c->Base, &loop_state, R500_VS_MAX_ALU);
        else
-               rc_transform_loops(&compiler->Base, &loop_state, R300_VS_MAX_ALU);
+               rc_transform_loops(&c->Base, &loop_state, R300_VS_MAX_ALU);
+       if (c->Base.Error)
+               return;
 
-       debug_program_log(compiler, "after emulate loops");
+       debug_program_log(c, "after emulate loops");
 
-       if (!compiler->Base.is_r500) {
-               rc_emulate_branches(&compiler->Base);
-               debug_program_log(compiler, "after emulate branches");
+       if (!c->Base.is_r500) {
+               rc_emulate_branches(&c->Base);
+               if (c->Base.Error)
+                       return;
+               debug_program_log(c, "after emulate branches");
        }
 
-       if (compiler->Base.is_r500) {
+       rc_emulate_negative_addressing(c);
+
+       debug_program_log(c, "after negative addressing emulation");
+
+       if (c->Base.is_r500) {
                struct radeon_program_transformation transformations[] = {
                        { &r300_transform_vertex_alu, 0 },
                        { &r300_transform_trig_scale_vertex, 0 }
                };
-               radeonLocalTransform(&compiler->Base, 2, transformations);
+               radeonLocalTransform(&c->Base, 2, transformations);
+               if (c->Base.Error)
+                       return;
 
-               debug_program_log(compiler, "after native rewrite");
+               debug_program_log(c, "after native rewrite");
        } else {
                struct radeon_program_transformation transformations[] = {
                        { &r300_transform_vertex_alu, 0 },
                        { &radeonTransformTrigSimple, 0 }
                };
-               radeonLocalTransform(&compiler->Base, 2, transformations);
+               radeonLocalTransform(&c->Base, 2, transformations);
+               if (c->Base.Error)
+                       return;
 
-               debug_program_log(compiler, "after native rewrite");
+               debug_program_log(c, "after native rewrite");
 
                /* Note: This pass has to be done seperately from ALU rewrite,
                 * because it needs to check every instruction.
@@ -913,9 +1034,11 @@ void r3xx_compile_vertex_program(struct r300_vertex_program_compiler* compiler)
                struct radeon_program_transformation transformations2[] = {
                        { &transform_nonnative_modifiers, 0 },
                };
-               radeonLocalTransform(&compiler->Base, 1, transformations2);
+               radeonLocalTransform(&c->Base, 1, transformations2);
+               if (c->Base.Error)
+                       return;
 
-               debug_program_log(compiler, "after emulate modifiers");
+               debug_program_log(c, "after emulate modifiers");
        }
 
        {
@@ -926,30 +1049,58 @@ void r3xx_compile_vertex_program(struct r300_vertex_program_compiler* compiler)
                struct radeon_program_transformation transformations[] = {
                        { &transform_source_conflicts, 0 },
                };
-               radeonLocalTransform(&compiler->Base, 1, transformations);
+               radeonLocalTransform(&c->Base, 1, transformations);
+               if (c->Base.Error)
+                       return;
        }
 
-       debug_program_log(compiler, "after source conflict resolve");
+       debug_program_log(c, "after source conflict resolve");
 
-       rc_dataflow_deadcode(&compiler->Base, &dataflow_outputs_mark_used, compiler);
+       rc_dataflow_deadcode(&c->Base, &dataflow_outputs_mark_used, c);
+       if (c->Base.Error)
+               return;
 
-       debug_program_log(compiler, "after deadcode");
+       debug_program_log(c, "after deadcode");
 
-       rc_dataflow_swizzles(&compiler->Base);
+       rc_dataflow_swizzles(&c->Base);
+       if (c->Base.Error)
+               return;
 
-       allocate_temporary_registers(compiler);
+       debug_program_log(c, "after dataflow");
 
-       debug_program_log(compiler, "after dataflow");
+       allocate_temporary_registers(c);
+       if (c->Base.Error)
+               return;
 
-       translate_vertex_program(compiler);
+       debug_program_log(c, "after register allocation");
 
-       rc_constants_copy(&compiler->code->constants, &compiler->Base.Program.Constants);
+       if (c->Base.remove_unused_constants) {
+               rc_remove_unused_constants(&c->Base,
+                                          &c->code->constants_remap_table);
+               if (c->Base.Error)
+                       return;
 
-       compiler->code->InputsRead = compiler->Base.Program.InputsRead;
-       compiler->code->OutputsWritten = compiler->Base.Program.OutputsWritten;
+               debug_program_log(c, "after constants cleanup");
+       }
 
-       if (compiler->Base.Debug) {
+       translate_vertex_program(c);
+       if (c->Base.Error)
+               return;
+
+       rc_constants_copy(&c->code->constants, &c->Base.Program.Constants);
+
+       c->code->InputsRead = c->Base.Program.InputsRead;
+       c->code->OutputsWritten = c->Base.Program.OutputsWritten;
+
+       if (c->Base.Debug) {
                fprintf(stderr, "Final vertex program code:\n");
-               r300_vertex_program_dump(compiler);
+               r300_vertex_program_dump(c);
+       }
+
+       /* Check the number of constants. */
+       if (!c->Base.Error &&
+           c->Base.Program.Constants.Count > 256) {
+               rc_error(&c->Base, "Too many constants. Max: 256, Got: %i\n",
+                        c->Base.Program.Constants.Count);
        }
 }
index 896246d203535b8584e36f819b6517661cbade57..f76676fae8e505c9e1e51ef09e548725180fbba2 100644 (file)
@@ -235,6 +235,7 @@ struct rX00_fragment_program_code {
        unsigned writes_depth:1;
 
        struct rc_constant_list constants;
+       unsigned *constants_remap_table;
 };
 
 
@@ -266,6 +267,7 @@ struct r300_vertex_program_code {
        int outputs[VSF_MAX_OUTPUTS];
 
        struct rc_constant_list constants;
+       unsigned *constants_remap_table;
 
        uint32_t InputsRead;
        uint32_t OutputsWritten;
index 7c42eb3ae5783e88e9a608e6b9649b46183c7aad..5155b912e174c92d5dd17b089bdc80d12c14faa0 100644 (file)
@@ -39,9 +39,12 @@ struct radeon_compiler {
        char * ErrorMsg;
 
        /* Hardware specification. */
-       unsigned is_r500;
+       unsigned is_r500:1;
        unsigned max_temp_regs;
 
+       /* Whether to remove unused constants and empty holes in constant space. */
+       unsigned remove_unused_constants:1;
+
        /**
         * Variables used internally, not be touched by callers
         * of the compiler
index faf531b412e29d9abd61fbe16f3f3ea36b1aeb9f..acdb371de936192570610f9cbe9260fdc548a63c 100644 (file)
@@ -157,8 +157,12 @@ static void update_instruction(struct deadcode_state * s, struct rc_instruction
                unsigned char * pused = get_used_ptr(s, inst->U.I.DstReg.File, inst->U.I.DstReg.Index);
                if (pused) {
                        usedmask = *pused & inst->U.I.DstReg.WriteMask;
-                       *pused &= ~usedmask;
+                       if (!inst->U.I.DstReg.RelAddr)
+                               *pused &= ~usedmask;
                }
+
+               if (inst->U.I.DstReg.RelAddr)
+                       mark_used(s, RC_FILE_ADDRESS, 0, RC_MASK_X);
        }
 
        insts->WriteMask |= usedmask;
@@ -213,6 +217,7 @@ void rc_dataflow_deadcode(struct radeon_compiler * c, rc_dataflow_mark_outputs_f
 {
        struct deadcode_state s;
        unsigned int nr_instructions;
+       unsigned has_temp_reladdr_src = 0;
 
        memset(&s, 0, sizeof(s));
        s.C = c;
@@ -300,6 +305,30 @@ void rc_dataflow_deadcode(struct radeon_compiler * c, rc_dataflow_mark_outputs_f
                                        rc_error(c, "%s: Unhandled control flow instruction %s\n", __FUNCTION__, opcode->Name);
                                }
                        }
+
+                       if (!has_temp_reladdr_src) {
+                               for (unsigned i = 0; i < opcode->NumSrcRegs; i++) {
+                                       if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY &&
+                                           inst->U.I.SrcReg[i].RelAddr) {
+                                               /* If there is a register read from a temporary file with relative addressing,
+                                                * mark all preceding written registers as used. */
+                                               for (struct rc_instruction *ptr = inst->Prev;
+                                                    ptr != &c->Program.Instructions;
+                                                    ptr = ptr->Prev) {
+                                                       if (opcode->HasDstReg &&
+                                                           ptr->U.I.DstReg.File == RC_FILE_TEMPORARY &&
+                                                           ptr->U.I.DstReg.WriteMask) {
+                                                               mark_used(&s,
+                                                                         ptr->U.I.DstReg.File,
+                                                                         ptr->U.I.DstReg.Index,
+                                                                         ptr->U.I.DstReg.WriteMask);
+                                                       }
+                                               }
+
+                                               has_temp_reladdr_src = 1;
+                                       }
+                               }
+                       }
                }
 
                update_instruction(&s, inst);
index 2ea830be7f9b701930432e119645e1e497b60a22..da495a3afaa7d9eb0b666456646e8454f562be9e 100644 (file)
@@ -94,6 +94,12 @@ struct rc_opcode_info rc_opcodes[MAX_RC_OPCODE] = {
                .HasDstReg = 1,
                .IsComponentwise = 1
        },
+       {
+               .Opcode = RC_OPCODE_DP2,
+               .Name = "DP2",
+               .NumSrcRegs = 2,
+               .HasDstReg = 1
+       },
        {
                .Opcode = RC_OPCODE_DP3,
                .Name = "DP3",
@@ -294,6 +300,13 @@ struct rc_opcode_info rc_opcodes[MAX_RC_OPCODE] = {
                .HasDstReg = 1,
                .IsComponentwise = 1
        },
+       {
+               .Opcode = RC_OPCODE_SSG,
+               .Name = "SSG",
+               .NumSrcRegs = 1,
+               .HasDstReg = 1,
+               .IsComponentwise = 1
+       },
        {
                .Opcode = RC_OPCODE_SUB,
                .Name = "SUB",
@@ -435,6 +448,10 @@ void rc_compute_sources_for_writemask(
                case RC_OPCODE_ARL:
                        srcmasks[0] |= RC_MASK_X;
                        break;
+               case RC_OPCODE_DP2:
+                       srcmasks[0] |= RC_MASK_XY;
+                       srcmasks[1] |= RC_MASK_XY;
+                       break;
                case RC_OPCODE_DP3:
                        srcmasks[0] |= RC_MASK_XYZ;
                        srcmasks[1] |= RC_MASK_XYZ;
index 6e18d6eb3f14cc4423acb4e57f302c5fa6fa2f4f..d3f639c87012fc0d8268e52c484879db5c5798a5 100644 (file)
@@ -64,6 +64,9 @@ typedef enum {
         * dst.c = d src0.c / dy */
        RC_OPCODE_DDY,
 
+       /** scalar instruction: dst = src0.x*src1.x + src0.y*src1.y */
+       RC_OPCODE_DP2,
+
        /** scalar instruction: dst = src0.x*src1.x + src0.y*src1.y + src0.z*src1.z */
        RC_OPCODE_DP3,
 
@@ -154,6 +157,9 @@ typedef enum {
        /** vec4 instruction: dst.c = (src0.c != src1.c) ? 1.0 : 0.0 */
        RC_OPCODE_SNE,
 
+       /** vec4 instruction: dst.c = (src0.c < 0 ?) -1 : ((src0.c > 0) : 1 : 0) */
+       RC_OPCODE_SSG,
+
        /** vec4 instruction: dst.c = src0.c - src1.c */
        RC_OPCODE_SUB,
 
index 407a0a55ee27155b4855a575f8f3d3bc3b44fcc8..8327e9aced693c7b12e488bf10bd29a950c65815 100644 (file)
@@ -230,6 +230,34 @@ static void set_pair_instruction(struct r300_fragment_program_compiler *c,
 }
 
 
+static void check_opcode_support(struct r300_fragment_program_compiler *c,
+                                struct rc_sub_instruction *inst)
+{
+       const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Opcode);
+
+       if (opcode->HasDstReg) {
+               if (inst->DstReg.RelAddr) {
+                       rc_error(&c->Base, "Fragment program does not support relative addressing "
+                                "of destination operands.\n");
+                       return;
+               }
+
+               if (inst->SaturateMode == RC_SATURATE_MINUS_PLUS_ONE) {
+                       rc_error(&c->Base, "Fragment program does not support signed Saturate.\n");
+                       return;
+               }
+       }
+
+       for (unsigned i = 0; i < opcode->NumSrcRegs; i++) {
+               if (inst->SrcReg[i].RelAddr) {
+                       rc_error(&c->Base, "Fragment program does not support relative addressing "
+                                " of source operands.\n");
+                       return;
+               }
+       }
+}
+
+
 /**
  * Translate all ALU instructions into corresponding pair instructions,
  * performing no other changes.
@@ -249,6 +277,8 @@ void rc_pair_translate(struct r300_fragment_program_compiler *c)
 
                struct rc_sub_instruction copy = inst->U.I;
 
+               check_opcode_support(c, &copy);
+
                final_rewrite(&copy);
                inst->Type = RC_INSTRUCTION_PAIR;
                set_pair_instruction(c, &inst->U.P, &copy);
index 857aae55145434f479cd8792794460077055f1e9..704a7bb2d231eb7881166aa58bdb69cd2380ea51 100644 (file)
@@ -216,18 +216,18 @@ static void transform_CEIL(struct radeon_compiler* c,
        rc_remove_instruction(inst);
 }
 
-static void transform_DP3(struct radeon_compiler* c,
+static void transform_DP2(struct radeon_compiler* c,
        struct rc_instruction* inst)
 {
        struct rc_src_register src0 = inst->U.I.SrcReg[0];
        struct rc_src_register src1 = inst->U.I.SrcReg[1];
-       src0.Negate &= ~RC_MASK_W;
-       src0.Swizzle &= ~(7 << (3 * 3));
-       src0.Swizzle |= RC_SWIZZLE_ZERO << (3 * 3);
-       src1.Negate &= ~RC_MASK_W;
-       src1.Swizzle &= ~(7 << (3 * 3));
-       src1.Swizzle |= RC_SWIZZLE_ZERO << (3 * 3);
-       emit2(c, inst->Prev, RC_OPCODE_DP4, inst->U.I.SaturateMode, inst->U.I.DstReg, src0, src1);
+       src0.Negate &= ~(RC_MASK_Z | RC_MASK_W);
+       src0.Swizzle &= ~(63 << (3 * 2));
+       src0.Swizzle |= (RC_SWIZZLE_ZERO << (3 * 2)) | (RC_SWIZZLE_ZERO << (3 * 3));
+       src1.Negate &= ~(RC_MASK_Z | RC_MASK_W);
+       src1.Swizzle &= ~(63 << (3 * 2));
+       src1.Swizzle |= (RC_SWIZZLE_ZERO << (3 * 2)) | (RC_SWIZZLE_ZERO << (3 * 3));
+       emit2(c, inst->Prev, RC_OPCODE_DP3, inst->U.I.SaturateMode, inst->U.I.DstReg, src0, src1);
        rc_remove_instruction(inst);
 }
 
@@ -464,6 +464,43 @@ static void transform_SNE(struct radeon_compiler* c,
        rc_remove_instruction(inst);
 }
 
+static void transform_SSG(struct radeon_compiler* c,
+       struct rc_instruction* inst)
+{
+       /* result = sign(x)
+        *
+        *   CMP tmp0, -x, 1, 0
+        *   CMP tmp1, x, 1, 0
+        *   ADD result, tmp0, -tmp1;
+        */
+       unsigned tmp0, tmp1;
+
+       /* 0 < x */
+       tmp0 = rc_find_free_temporary(c);
+       emit3(c, inst->Prev, RC_OPCODE_CMP, 0,
+             dstregtmpmask(tmp0, inst->U.I.DstReg.WriteMask),
+             negate(inst->U.I.SrcReg[0]),
+             builtin_one,
+             builtin_zero);
+
+       /* x < 0 */
+       tmp1 = rc_find_free_temporary(c);
+       emit3(c, inst->Prev, RC_OPCODE_CMP, 0,
+             dstregtmpmask(tmp1, inst->U.I.DstReg.WriteMask),
+             inst->U.I.SrcReg[0],
+             builtin_one,
+             builtin_zero);
+
+       /* Either both are zero, or one of them is one and the other is zero. */
+       /* result = tmp0 - tmp1 */
+       emit2(c, inst->Prev, RC_OPCODE_ADD, 0,
+             inst->U.I.DstReg,
+             srcreg(RC_FILE_TEMPORARY, tmp0),
+             negate(srcreg(RC_FILE_TEMPORARY, tmp1)));
+
+       rc_remove_instruction(inst);
+}
+
 static void transform_SUB(struct radeon_compiler* c,
        struct rc_instruction* inst)
 {
@@ -516,6 +553,7 @@ int radeonTransformALU(
        switch(inst->U.I.Opcode) {
        case RC_OPCODE_ABS: transform_ABS(c, inst); return 1;
        case RC_OPCODE_CEIL: transform_CEIL(c, inst); return 1;
+       case RC_OPCODE_DP2: transform_DP2(c, inst); return 1;
        case RC_OPCODE_DPH: transform_DPH(c, inst); return 1;
        case RC_OPCODE_DST: transform_DST(c, inst); return 1;
        case RC_OPCODE_FLR: transform_FLR(c, inst); return 1;
@@ -530,6 +568,7 @@ int radeonTransformALU(
        case RC_OPCODE_SLE: transform_SLE(c, inst); return 1;
        case RC_OPCODE_SLT: transform_SLT(c, inst); return 1;
        case RC_OPCODE_SNE: transform_SNE(c, inst); return 1;
+       case RC_OPCODE_SSG: transform_SSG(c, inst); return 1;
        case RC_OPCODE_SUB: transform_SUB(c, inst); return 1;
        case RC_OPCODE_SWZ: transform_SWZ(c, inst); return 1;
        case RC_OPCODE_XPD: transform_XPD(c, inst); return 1;
@@ -577,6 +616,29 @@ static void transform_r300_vertex_CMP(struct radeon_compiler* c,
        rc_remove_instruction(inst);
 }
 
+static void transform_r300_vertex_DP2(struct radeon_compiler* c,
+       struct rc_instruction* inst)
+{
+       struct rc_instruction *next_inst = inst->Next;
+       transform_DP2(c, inst);
+       next_inst->Prev->U.I.Opcode = RC_OPCODE_DP4;
+}
+
+static void transform_r300_vertex_DP3(struct radeon_compiler* c,
+       struct rc_instruction* inst)
+{
+       struct rc_src_register src0 = inst->U.I.SrcReg[0];
+       struct rc_src_register src1 = inst->U.I.SrcReg[1];
+       src0.Negate &= ~RC_MASK_W;
+       src0.Swizzle &= ~(7 << (3 * 3));
+       src0.Swizzle |= RC_SWIZZLE_ZERO << (3 * 3);
+       src1.Negate &= ~RC_MASK_W;
+       src1.Swizzle &= ~(7 << (3 * 3));
+       src1.Swizzle |= RC_SWIZZLE_ZERO << (3 * 3);
+       emit2(c, inst->Prev, RC_OPCODE_DP4, inst->U.I.SaturateMode, inst->U.I.DstReg, src0, src1);
+       rc_remove_instruction(inst);
+}
+
 static void transform_r300_vertex_fix_LIT(struct radeon_compiler* c,
        struct rc_instruction* inst)
 {
@@ -672,6 +734,41 @@ static void transform_r300_vertex_SLE(struct radeon_compiler* c,
        inst->U.I.SrcReg[1].Negate ^= RC_MASK_XYZW;
 }
 
+static void transform_r300_vertex_SSG(struct radeon_compiler* c,
+       struct rc_instruction* inst)
+{
+       /* result = sign(x)
+        *
+        *   SLT tmp0, 0, x;
+        *   SLT tmp1, x, 0;
+        *   ADD result, tmp0, -tmp1;
+        */
+       unsigned tmp0, tmp1;
+
+       /* 0 < x */
+       tmp0 = rc_find_free_temporary(c);
+       emit2(c, inst->Prev, RC_OPCODE_SLT, 0,
+             dstregtmpmask(tmp0, inst->U.I.DstReg.WriteMask),
+             builtin_zero,
+             inst->U.I.SrcReg[0]);
+
+       /* x < 0 */
+       tmp1 = rc_find_free_temporary(c);
+       emit2(c, inst->Prev, RC_OPCODE_SLT, 0,
+             dstregtmpmask(tmp1, inst->U.I.DstReg.WriteMask),
+             inst->U.I.SrcReg[0],
+             builtin_zero);
+
+       /* Either both are zero, or one of them is one and the other is zero. */
+       /* result = tmp0 - tmp1 */
+       emit2(c, inst->Prev, RC_OPCODE_ADD, 0,
+             inst->U.I.DstReg,
+             srcreg(RC_FILE_TEMPORARY, tmp0),
+             negate(srcreg(RC_FILE_TEMPORARY, tmp1)));
+
+       rc_remove_instruction(inst);
+}
+
 /**
  * For use with radeonLocalTransform, this transforms non-native ALU
  * instructions of the r300 up to r500 vertex engine.
@@ -685,7 +782,8 @@ int r300_transform_vertex_alu(
        case RC_OPCODE_ABS: transform_r300_vertex_ABS(c, inst); return 1;
        case RC_OPCODE_CEIL: transform_CEIL(c, inst); return 1;
        case RC_OPCODE_CMP: transform_r300_vertex_CMP(c, inst); return 1;
-       case RC_OPCODE_DP3: transform_DP3(c, inst); return 1;
+       case RC_OPCODE_DP2: transform_r300_vertex_DP2(c, inst); return 1;
+       case RC_OPCODE_DP3: transform_r300_vertex_DP3(c, inst); return 1;
        case RC_OPCODE_DPH: transform_DPH(c, inst); return 1;
        case RC_OPCODE_FLR: transform_FLR(c, inst); return 1;
        case RC_OPCODE_LIT: transform_r300_vertex_fix_LIT(c, inst); return 1;
@@ -705,6 +803,7 @@ int r300_transform_vertex_alu(
                        return 1;
                }
                return 0;
+       case RC_OPCODE_SSG: transform_r300_vertex_SSG(c, inst); return 1;
        case RC_OPCODE_SUB: transform_SUB(c, inst); return 1;
        case RC_OPCODE_SWZ: transform_SWZ(c, inst); return 1;
        case RC_OPCODE_XPD: transform_XPD(c, inst); return 1;
index 9c4b65f4c00c12ce0f91b801371f43f4427e3c79..ddce590ee66e2fcac67c604bf5ef86a3bfeb2d19 100644 (file)
@@ -117,8 +117,8 @@ int radeonTransformTEX(
                        struct rc_instruction * inst_rcp = NULL;
                        struct rc_instruction * inst_mad;
                        struct rc_instruction * inst_cmp;
-                       unsigned tmp_texsample = rc_find_free_temporary(c);
-                       unsigned tmp_sum = rc_find_free_temporary(c);
+                       unsigned tmp_texsample;
+                       unsigned tmp_sum;
                        unsigned tmp_recip_w = 0;
                        int pass, fail, tex;
 
@@ -126,6 +126,7 @@ int radeonTransformTEX(
                        struct rc_dst_register output_reg = inst->U.I.DstReg;
 
                        /* Redirect TEX to a new temp. */
+                       tmp_texsample = rc_find_free_temporary(c);
                        inst->U.I.DstReg.File = RC_FILE_TEMPORARY;
                        inst->U.I.DstReg.Index = tmp_texsample;
                        inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
@@ -144,6 +145,7 @@ int radeonTransformTEX(
                        }
 
                        /* Perspective-divide r by W (if it's TXP) and add the texture sample (see below). */
+                       tmp_sum = rc_find_free_temporary(c);
                        inst_mad = rc_insert_new_instruction(c, inst_rcp ? inst_rcp : inst);
                        inst_mad->U.I.DstReg.File = RC_FILE_TEMPORARY;
                        inst_mad->U.I.DstReg.Index = tmp_sum;
@@ -199,6 +201,8 @@ int radeonTransformTEX(
                        inst_cmp->U.I.SrcReg[pass].File = RC_FILE_NONE;
                        inst_cmp->U.I.SrcReg[pass].Swizzle = RC_SWIZZLE_1111;
                        inst_cmp->U.I.SrcReg[fail] = shadow_ambient(compiler, inst->U.I.TexSrcUnit);
+
+                       assert(tmp_texsample != tmp_sum && tmp_sum != tmp_recip_w);
                }
        }
 
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.c b/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.c
new file mode 100644 (file)
index 0000000..be89e9f
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2010 Marek Olšák <maraeo@gmail.com>
+ *
+ * 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, 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 COPYRIGHT OWNER(S) 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 "radeon_remove_constants.h"
+
+void rc_remove_unused_constants(struct radeon_compiler *c,
+                                unsigned **out_remap_table)
+{
+        unsigned char *const_used;
+        unsigned *remap_table;
+        unsigned *inv_remap_table;
+        unsigned has_rel_addr = 0;
+        unsigned is_identity = 1;
+       unsigned are_externals_remapped = 0;
+        struct rc_constant *constants = c->Program.Constants.Constants;
+
+        if (!c->Program.Constants.Count) {
+                *out_remap_table = NULL;
+                return;
+        }
+
+        const_used = malloc(c->Program.Constants.Count);
+        memset(const_used, 0, c->Program.Constants.Count);
+
+       /* Pass 1: Mark used constants. */
+        for (struct rc_instruction *inst = c->Program.Instructions.Next;
+             inst != &c->Program.Instructions; inst = inst->Next) {
+                const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->U.I.Opcode);
+
+                for (unsigned i = 0; i < opcode->NumSrcRegs; i++) {
+                        if (inst->U.I.SrcReg[i].File == RC_FILE_CONSTANT) {
+                                if (inst->U.I.SrcReg[i].RelAddr) {
+                                        has_rel_addr = 1;
+                                } else {
+                                        const_used[inst->U.I.SrcReg[i].Index] = 1;
+                                }
+                        }
+                }
+        }
+
+        /* Pass 2: If there is relative addressing, mark all externals as used. */
+        if (has_rel_addr) {
+                for (unsigned i = 0; i < c->Program.Constants.Count; i++)
+                        if (constants[i].Type == RC_CONSTANT_EXTERNAL)
+                                const_used[i] = 1;
+        }
+
+        /* Pass 3: Make the remapping table and remap constants.
+        * This pass removes unused constants simply by overwriting them by other constants. */
+        remap_table = malloc(c->Program.Constants.Count * sizeof(unsigned));
+        inv_remap_table = malloc(c->Program.Constants.Count * sizeof(unsigned));
+        unsigned new_count = 0;
+
+        for (unsigned i = 0; i < c->Program.Constants.Count; i++) {
+                if (const_used[i]) {
+                        remap_table[new_count] = i;
+                        inv_remap_table[i] = new_count;
+
+                        if (i != new_count) {
+                               if (constants[i].Type == RC_CONSTANT_EXTERNAL)
+                                       are_externals_remapped = 1;
+
+                               constants[new_count] = constants[i];
+                                is_identity = 0;
+                        }
+                        new_count++;
+                }
+        }
+
+       /*  is_identity ==> new_count == old_count
+        * !is_identity ==> new_count <  old_count */
+       assert( is_identity || new_count <  c->Program.Constants.Count);
+       assert(!(has_rel_addr && are_externals_remapped));
+
+        /* Pass 4: Redirect reads of all constants to their new locations. */
+        if (!is_identity) {
+                for (struct rc_instruction *inst = c->Program.Instructions.Next;
+                     inst != &c->Program.Instructions; inst = inst->Next) {
+                        const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->U.I.Opcode);
+
+                        for (unsigned i = 0; i < opcode->NumSrcRegs; i++) {
+                                if (inst->U.I.SrcReg[i].File == RC_FILE_CONSTANT) {
+                                        inst->U.I.SrcReg[i].Index = inv_remap_table[inst->U.I.SrcReg[i].Index];
+                                }
+                        }
+                }
+
+       }
+
+       /* Set the new constant count. Note that new_count may be less than
+        * Count even though the remapping function is identity. In that case,
+        * the constants have been removed at the end of the array. */
+       c->Program.Constants.Count = new_count;
+
+       if (are_externals_remapped) {
+                *out_remap_table = remap_table;
+        } else {
+                *out_remap_table = NULL;
+                free(remap_table);
+        }
+
+        free(const_used);
+        free(inv_remap_table);
+}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.h b/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.h
new file mode 100644 (file)
index 0000000..0d3a26c
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 Marek Olšák <maraeo@gmail.com>
+ *
+ * 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, 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 COPYRIGHT OWNER(S) 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 RADEON_REMOVE_CONSTANTS_H
+#define RADEON_REMOVE_CONSTANTS_H
+
+#include "radeon_compiler.h"
+
+void rc_remove_unused_constants(struct radeon_compiler *c,
+                                unsigned **out_remap_table);
+
+#endif
index 95f4306f604fcf3be422df6544252bac9f0e6ee1..7b6521c7480372ec04fbe327c787c927e11c6cdf 100644 (file)
@@ -38,7 +38,6 @@
 
 #include "r300_fragprog_common.h"
 
-#include "program/prog_parameter.h"
 #include "program/prog_print.h"
 
 #include "compiler/radeon_compiler.h"
index 17915621ee4d1bc6907c77686b1db64f49c10108..03c17540e02e6a94b344009b7e04446f4c5688f7 100644 (file)
@@ -59,6 +59,15 @@ DRIVER_SOURCES = \
                 r600_texstate.c      \
                 r600_blit.c     \
                 r700_debug.c    \
+         evergreen_context.c    \
+         evergreen_state.c      \
+         evergreen_tex.c        \
+         evergreen_ioctl.c      \
+         evergreen_render.c     \
+         evergreen_chip.c       \
+         evergreen_vertprog.c   \
+         evergreen_fragprog.c   \
+         evergreen_oglprog.c    \
                 $(RADEON_COMMON_SOURCES) \
                 $(EGL_SOURCES) \
                 $(CS_SOURCES)
diff --git a/src/mesa/drivers/dri/r600/evergreen_chip.c b/src/mesa/drivers/dri/r600/evergreen_chip.c
new file mode 100644 (file)
index 0000000..f925f21
--- /dev/null
@@ -0,0 +1,1289 @@
+/*
+ * Copyright (C) 2008-2010  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com> 
+ */
+
+#include "main/imports.h"
+#include "main/glheader.h"
+#include "main/simple_list.h"
+
+#include "r600_context.h"
+#include "r600_cmdbuf.h"
+
+#include "evergreen_chip.h"
+#include "evergreen_off.h"
+#include "evergreen_diff.h"
+#include "evergreen_fragprog.h"
+#include "evergreen_vertprog.h"
+
+#include "radeon_mipmap_tree.h"
+
+void evergreenCreateChip(context_t *context)
+{
+    EVERGREEN_CHIP_CONTEXT * evergreen = 
+           (EVERGREEN_CHIP_CONTEXT*) CALLOC(sizeof(EVERGREEN_CHIP_CONTEXT));
+
+    context->pChip = (void*)evergreen;
+}
+
+#define EVERGREEN_ALLOC_STATE( ATOM, CHK, SZ, EMIT )                           \
+do {                                                                   \
+       context->evergreen_atoms.ATOM.cmd_size = (SZ);                          \
+       context->evergreen_atoms.ATOM.cmd = NULL;                                       \
+       context->evergreen_atoms.ATOM.name = #ATOM;                             \
+       context->evergreen_atoms.ATOM.idx = 0;                                  \
+       context->evergreen_atoms.ATOM.check = check_##CHK;                      \
+       context->evergreen_atoms.ATOM.dirty = GL_FALSE;                         \
+       context->evergreen_atoms.ATOM.emit = (EMIT);                            \
+       context->radeon.hw.max_state_size += (SZ);                      \
+       insert_at_tail(&context->radeon.hw.atomlist, &context->evergreen_atoms.ATOM); \
+} while (0)
+
+/*
+static void evergreen_init_query_stateobj(radeonContextPtr radeon, int SZ)
+{
+       radeon->query.queryobj.cmd_size = (SZ);
+       radeon->query.queryobj.cmd = NULL;
+       radeon->query.queryobj.name = "queryobj";
+       radeon->query.queryobj.idx = 0;
+       radeon->query.queryobj.check = check_queryobj;
+       radeon->query.queryobj.dirty = GL_FALSE;
+       radeon->query.queryobj.emit = r700SendQueryBegin;
+       radeon->hw.max_state_size += (SZ);
+       insert_at_tail(&radeon->hw.atomlist, &radeon->query.queryobj);
+}
+*/
+
+static int check_always(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+       return atom->cmd_size;
+}
+
+static void evergreenSendTexState(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+
+    struct evergreen_vertex_program *vp = context->selected_vp;
+
+       struct radeon_bo *bo = NULL;
+       unsigned int i;
+    unsigned int nBorderSet = 0;
+       BATCH_LOCALS(&context->radeon);
+
+    radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+    for (i = 0; i < R700_TEXTURE_NUMBERUNITS; i++) {
+               if (ctx->Texture.Unit[i]._ReallyEnabled) {            
+                       radeonTexObj *t = evergreen->textures[i];
+
+                       if (t) {
+                /* Tex resource */
+                               if (!t->image_override) {
+                                       bo = t->mt->bo;
+                               } else {
+                                       bo = t->bo;
+                               }
+                               if (bo) 
+                {                    
+                    radeon_bo_unmap(bo);                    
+
+                                       r700SyncSurf(context, bo,
+                                                    RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM,
+                                                    0, TC_ACTION_ENA_bit);                    
+
+                                       BEGIN_BATCH_NO_AUTOSTATE(10 + 4);
+                                       R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_RESOURCE, 8));
+
+                    if( (1<<i) & vp->r700AsmCode.unVetTexBits )                    
+                    {   /* vs texture */                                     
+                        R600_OUT_BATCH((i + VERT_ATTRIB_MAX + EG_SQ_FETCH_RESOURCE_VS_OFFSET) * FETCH_RESOURCE_STRIDE);
+                    }
+                    else
+                    {
+                                           R600_OUT_BATCH(i * EG_FETCH_RESOURCE_STRIDE);
+                    }
+
+                                       R600_OUT_BATCH(evergreen->textures[i]->SQ_TEX_RESOURCE0);
+                                       R600_OUT_BATCH(evergreen->textures[i]->SQ_TEX_RESOURCE1);
+                                       R600_OUT_BATCH(evergreen->textures[i]->SQ_TEX_RESOURCE2);
+                                       R600_OUT_BATCH(evergreen->textures[i]->SQ_TEX_RESOURCE3);
+                                       R600_OUT_BATCH(evergreen->textures[i]->SQ_TEX_RESOURCE4);
+                                       R600_OUT_BATCH(evergreen->textures[i]->SQ_TEX_RESOURCE5);
+                                       R600_OUT_BATCH(evergreen->textures[i]->SQ_TEX_RESOURCE6);
+                    R600_OUT_BATCH(evergreen->textures[i]->SQ_TEX_RESOURCE7);
+
+                                       R600_OUT_BATCH_RELOC(evergreen->textures[i]->SQ_TEX_RESOURCE2,
+                                                            bo,
+                                                            evergreen->textures[i]->SQ_TEX_RESOURCE2,
+                                                            RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+                                       R600_OUT_BATCH_RELOC(evergreen->textures[i]->SQ_TEX_RESOURCE3,
+                                                            bo,
+                                                            evergreen->textures[i]->SQ_TEX_RESOURCE3,
+                                                            RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+                                       END_BATCH();
+                                       COMMIT_BATCH();
+                               }
+                /* Tex sampler */
+                BEGIN_BATCH_NO_AUTOSTATE(5);
+                               R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_SAMPLER, 3));
+             
+                if( (1<<i) & vp->r700AsmCode.unVetTexBits )                    
+                {   /* vs texture */
+                    R600_OUT_BATCH((i+SQ_TEX_SAMPLER_VS_OFFSET) * 3); 
+                }
+                else
+                {
+                                   R600_OUT_BATCH(i * 3);
+                }
+                               R600_OUT_BATCH(evergreen->textures[i]->SQ_TEX_SAMPLER0);
+                               R600_OUT_BATCH(evergreen->textures[i]->SQ_TEX_SAMPLER1);
+                               R600_OUT_BATCH(evergreen->textures[i]->SQ_TEX_SAMPLER2);
+
+                               END_BATCH();
+                               COMMIT_BATCH();
+
+                /* Tex border color */
+                if(0 == nBorderSet)
+                {
+                    BEGIN_BATCH_NO_AUTOSTATE(2 + 4);
+                                   R600_OUT_BATCH_REGSEQ(EG_TD_PS_BORDER_COLOR_RED, 4);
+                                   R600_OUT_BATCH(evergreen->textures[i]->TD_PS_SAMPLER0_BORDER_RED);
+                                   R600_OUT_BATCH(evergreen->textures[i]->TD_PS_SAMPLER0_BORDER_GREEN);
+                                   R600_OUT_BATCH(evergreen->textures[i]->TD_PS_SAMPLER0_BORDER_BLUE);
+                                   R600_OUT_BATCH(evergreen->textures[i]->TD_PS_SAMPLER0_BORDER_ALPHA);
+                                   END_BATCH();
+                                   COMMIT_BATCH();
+
+                    nBorderSet = 1;
+                }
+                       }
+               }
+       }
+}
+
+static int check_evergreen_tx(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       unsigned int i, count = 0;
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+
+       for (i = 0; i < R700_TEXTURE_NUMBERUNITS; i++) {
+               if (ctx->Texture.Unit[i]._ReallyEnabled) {
+                       radeonTexObj *t = evergreen->textures[i];
+                       if (t)
+                               count++;
+               }
+       }
+       radeon_print(RADEON_STATE, RADEON_TRACE, "%s %d\n", __func__, count);
+       return count * 37 + 6;
+}
+
+static void evergreenSendSQConfig(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       BATCH_LOCALS(&context->radeon);
+       radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);    
+
+    BEGIN_BATCH_NO_AUTOSTATE(19);
+    //6
+    EVERGREEN_OUT_BATCH_REGVAL(EG_SPI_CONFIG_CNTL,   evergreen->evergreen_config.SPI_CONFIG_CNTL.u32All);
+       EVERGREEN_OUT_BATCH_REGVAL(EG_SPI_CONFIG_CNTL_1, evergreen->evergreen_config.SPI_CONFIG_CNTL_1.u32All);
+    //6
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_CONFIG, 4);
+    R600_OUT_BATCH(evergreen->evergreen_config.SQ_CONFIG.u32All);
+       R600_OUT_BATCH(evergreen->evergreen_config.SQ_GPR_RESOURCE_MGMT_1.u32All);
+       R600_OUT_BATCH(evergreen->evergreen_config.SQ_GPR_RESOURCE_MGMT_2.u32All);
+       R600_OUT_BATCH(evergreen->evergreen_config.SQ_GPR_RESOURCE_MGMT_3.u32All);
+    //7
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_THREAD_RESOURCE_MGMT, 5);
+    R600_OUT_BATCH(evergreen->evergreen_config.SQ_THREAD_RESOURCE_MGMT.u32All);
+       R600_OUT_BATCH(evergreen->evergreen_config.SQ_THREAD_RESOURCE_MGMT_2.u32All);
+       R600_OUT_BATCH(evergreen->evergreen_config.SQ_STACK_RESOURCE_MGMT_1.u32All);
+       R600_OUT_BATCH(evergreen->evergreen_config.SQ_STACK_RESOURCE_MGMT_2.u32All);
+    R600_OUT_BATCH(evergreen->evergreen_config.SQ_STACK_RESOURCE_MGMT_3.u32All);
+
+    END_BATCH();
+
+    COMMIT_BATCH();
+}
+
+extern int evergreen_getTypeSize(GLenum type);
+static void evergreenSetupVTXConstants(GLcontext  * ctx,
+                                 void *       pAos,
+                                 StreamDesc * pStreamDesc)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    struct radeon_aos * paos = (struct radeon_aos *)pAos;
+    unsigned int nVBsize;
+    BATCH_LOCALS(&context->radeon);
+
+    unsigned int uSQ_VTX_CONSTANT_WORD0_0;
+    unsigned int uSQ_VTX_CONSTANT_WORD1_0;
+    unsigned int uSQ_VTX_CONSTANT_WORD2_0 = 0;
+    unsigned int uSQ_VTX_CONSTANT_WORD3_0 = 0;
+    unsigned int uSQ_VTX_CONSTANT_WORD7_0 = 0;
+
+    if (!paos->bo)
+           return;
+
+       r700SyncSurf(context, paos->bo, RADEON_GEM_DOMAIN_GTT, 0, VC_ACTION_ENA_bit);
+
+    if(0 == pStreamDesc->stride)
+    {
+        nVBsize = paos->count * pStreamDesc->size * getTypeSize(pStreamDesc->type);
+    }
+    else
+    {
+        nVBsize = (paos->count - 1) * pStreamDesc->stride
+                  + pStreamDesc->size * getTypeSize(pStreamDesc->type);
+    }
+
+    //uSQ_VTX_CONSTANT_WORD0_0
+    uSQ_VTX_CONSTANT_WORD0_0 = paos->offset;
+
+    //uSQ_VTX_CONSTANT_WORD1_0
+    uSQ_VTX_CONSTANT_WORD1_0 = nVBsize;
+        
+    //uSQ_VTX_CONSTANT_WORD2_0
+    SETfield(uSQ_VTX_CONSTANT_WORD2_0, 
+             pStreamDesc->stride, 
+             SQ_VTX_CONSTANT_WORD2_0__STRIDE_shift, 
+                SQ_VTX_CONSTANT_WORD2_0__STRIDE_mask);
+    SETfield(uSQ_VTX_CONSTANT_WORD2_0, GetSurfaceFormat(pStreamDesc->type, pStreamDesc->size, NULL),
+            SQ_VTX_CONSTANT_WORD2_0__DATA_FORMAT_shift,
+            SQ_VTX_CONSTANT_WORD2_0__DATA_FORMAT_mask); // TODO : trace back api for initial data type, not only GL_FLOAT     
+    SETfield(uSQ_VTX_CONSTANT_WORD2_0, 0, BASE_ADDRESS_HI_shift, BASE_ADDRESS_HI_mask); // TODO    
+    if(GL_TRUE == pStreamDesc->normalize)
+    {
+        SETfield(uSQ_VTX_CONSTANT_WORD2_0, SQ_NUM_FORMAT_NORM,
+                    SQ_VTX_CONSTANT_WORD2_0__NUM_FORMAT_ALL_shift, SQ_VTX_CONSTANT_WORD2_0__NUM_FORMAT_ALL_mask);
+    }
+    else
+    {
+        SETfield(uSQ_VTX_CONSTANT_WORD2_0, SQ_NUM_FORMAT_SCALED,
+                    SQ_VTX_CONSTANT_WORD2_0__NUM_FORMAT_ALL_shift, SQ_VTX_CONSTANT_WORD2_0__NUM_FORMAT_ALL_mask);
+    }
+    if(1 == pStreamDesc->_signed)
+    {
+        SETbit(uSQ_VTX_CONSTANT_WORD2_0, SQ_VTX_CONSTANT_WORD2_0__FORMAT_COMP_ALL_bit);
+    }
+
+    //uSQ_VTX_CONSTANT_WORD3_0
+    SETfield(uSQ_VTX_CONSTANT_WORD3_0, SQ_SEL_X, 
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_X_shift, 
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_X_mask);
+    SETfield(uSQ_VTX_CONSTANT_WORD3_0, SQ_SEL_Y, 
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_Y_shift, 
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_Y_mask);
+    SETfield(uSQ_VTX_CONSTANT_WORD3_0, SQ_SEL_Z, 
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_Z_shift, 
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_Z_mask);
+    SETfield(uSQ_VTX_CONSTANT_WORD3_0, SQ_SEL_W, 
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_W_shift, 
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_W_mask);
+
+    //uSQ_VTX_CONSTANT_WORD7_0
+    SETfield(uSQ_VTX_CONSTANT_WORD7_0, SQ_TEX_VTX_VALID_BUFFER,
+            SQ_TEX_RESOURCE_WORD6_0__TYPE_shift, SQ_TEX_RESOURCE_WORD6_0__TYPE_mask);
+
+    BEGIN_BATCH_NO_AUTOSTATE(10 + 2);
+
+    R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_RESOURCE, 8));
+    R600_OUT_BATCH((pStreamDesc->element + EG_SQ_FETCH_RESOURCE_VS_OFFSET) * EG_FETCH_RESOURCE_STRIDE);
+    R600_OUT_BATCH(uSQ_VTX_CONSTANT_WORD0_0);
+    R600_OUT_BATCH(uSQ_VTX_CONSTANT_WORD1_0);
+    R600_OUT_BATCH(uSQ_VTX_CONSTANT_WORD2_0);
+    R600_OUT_BATCH(uSQ_VTX_CONSTANT_WORD3_0);
+    R600_OUT_BATCH(0);
+    R600_OUT_BATCH(0);
+    R600_OUT_BATCH(0);
+    R600_OUT_BATCH(uSQ_VTX_CONSTANT_WORD7_0);
+    R600_OUT_BATCH_RELOC(uSQ_VTX_CONSTANT_WORD0_0,
+                         paos->bo,
+                         uSQ_VTX_CONSTANT_WORD0_0,
+                         RADEON_GEM_DOMAIN_GTT, 0, 0);
+    END_BATCH();
+    
+    COMMIT_BATCH();
+}
+
+static int check_evergreen_vtx(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       int count = context->radeon.tcl.aos_count * 12;
+
+       if (count)
+               count += 6;
+
+       radeon_print(RADEON_STATE, RADEON_TRACE, "%s %d\n", __func__, count);
+       return count;
+}
+
+static void evergreenSendVTX(GLcontext *ctx, struct radeon_state_atom *atom)
+{    
+    context_t         *context = EVERGREEN_CONTEXT(ctx);
+    struct evergreen_vertex_program *vp = (struct evergreen_vertex_program *)(context->selected_vp);
+    unsigned int i, j = 0;
+    BATCH_LOCALS(&context->radeon);
+       radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+    if (context->radeon.tcl.aos_count == 0)
+           return;
+
+    BEGIN_BATCH_NO_AUTOSTATE(6);
+    R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CTL_CONST, 1));
+    R600_OUT_BATCH(mmSQ_VTX_BASE_VTX_LOC - ASIC_CTL_CONST_BASE_INDEX);
+    R600_OUT_BATCH(0);
+
+    R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CTL_CONST, 1));
+    R600_OUT_BATCH(mmSQ_VTX_START_INST_LOC - ASIC_CTL_CONST_BASE_INDEX);
+    R600_OUT_BATCH(0);
+    END_BATCH();
+    COMMIT_BATCH();
+    
+    for(i=0; i<VERT_ATTRIB_MAX; i++) {
+           if(vp->mesa_program->Base.InputsRead & (1 << i))
+           {
+            evergreenSetupVTXConstants(ctx,
+                                     (void*)(&context->radeon.tcl.aos[j]),
+                                     &(context->stream_desc[j]));
+                   j++;
+           }
+    } 
+}
+static void evergreenSendPA(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       BATCH_LOCALS(&context->radeon);
+       radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+    int id = 0;
+
+    BEGIN_BATCH_NO_AUTOSTATE(3);
+    EVERGREEN_OUT_BATCH_REGVAL(EG_PA_SU_HARDWARE_SCREEN_OFFSET, 0);
+    END_BATCH();
+
+    BEGIN_BATCH_NO_AUTOSTATE(22);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_PA_SC_SCREEN_SCISSOR_TL, 2);
+    R600_OUT_BATCH(evergreen->PA_SC_SCREEN_SCISSOR_TL.u32All);  
+    R600_OUT_BATCH(evergreen->PA_SC_SCREEN_SCISSOR_BR.u32All);  
+
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_PA_SC_WINDOW_OFFSET, 12);
+    R600_OUT_BATCH(evergreen->PA_SC_WINDOW_OFFSET.u32All);       
+    R600_OUT_BATCH(evergreen->PA_SC_WINDOW_SCISSOR_TL.u32All);   
+    R600_OUT_BATCH(evergreen->PA_SC_WINDOW_SCISSOR_BR.u32All);   
+    R600_OUT_BATCH(evergreen->PA_SC_CLIPRECT_RULE.u32All);       
+    R600_OUT_BATCH(evergreen->PA_SC_CLIPRECT_0_TL.u32All);       
+    R600_OUT_BATCH(evergreen->PA_SC_CLIPRECT_0_BR.u32All);       
+    R600_OUT_BATCH(evergreen->PA_SC_CLIPRECT_1_TL.u32All);  
+    R600_OUT_BATCH(evergreen->PA_SC_CLIPRECT_1_BR.u32All);  
+    R600_OUT_BATCH(evergreen->PA_SC_CLIPRECT_2_TL.u32All);  
+    R600_OUT_BATCH(evergreen->PA_SC_CLIPRECT_2_BR.u32All);  
+    R600_OUT_BATCH(evergreen->PA_SC_CLIPRECT_3_TL.u32All);  
+    R600_OUT_BATCH(evergreen->PA_SC_CLIPRECT_3_BR.u32All);  
+    
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_PA_SC_GENERIC_SCISSOR_TL, 2);
+    R600_OUT_BATCH(evergreen->PA_SC_GENERIC_SCISSOR_TL.u32All);  
+    R600_OUT_BATCH(evergreen->PA_SC_GENERIC_SCISSOR_BR.u32All); 
+    END_BATCH();
+
+    BEGIN_BATCH_NO_AUTOSTATE(3);
+    EVERGREEN_OUT_BATCH_REGVAL(EG_PA_SC_EDGERULE, evergreen->PA_SC_EDGERULE.u32All);
+    END_BATCH();
+        
+
+    BEGIN_BATCH_NO_AUTOSTATE(18);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_PA_SC_VPORT_SCISSOR_0_TL, 4);
+    R600_OUT_BATCH(evergreen->viewport[id].PA_SC_VPORT_SCISSOR_0_TL.u32All);    
+    R600_OUT_BATCH(evergreen->viewport[id].PA_SC_VPORT_SCISSOR_0_BR.u32All);    
+    R600_OUT_BATCH(evergreen->viewport[id].PA_SC_VPORT_SCISSOR_0_TL.u32All);    
+    R600_OUT_BATCH(evergreen->viewport[id].PA_SC_VPORT_SCISSOR_0_BR.u32All);        
+
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_PA_SC_VPORT_ZMIN_0, 2);
+       R600_OUT_BATCH(evergreen->viewport[id].PA_SC_VPORT_ZMIN_0.u32All);  
+    R600_OUT_BATCH(evergreen->viewport[id].PA_SC_VPORT_ZMAX_0.u32All);  
+
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_PA_CL_VPORT_XSCALE, 6);
+       R600_OUT_BATCH(evergreen->viewport[id].PA_CL_VPORT_XSCALE.u32All);     
+    R600_OUT_BATCH(evergreen->viewport[id].PA_CL_VPORT_XOFFSET.u32All);    
+    R600_OUT_BATCH(evergreen->viewport[id].PA_CL_VPORT_YSCALE.u32All);     
+    R600_OUT_BATCH(evergreen->viewport[id].PA_CL_VPORT_YOFFSET.u32All);    
+    R600_OUT_BATCH(evergreen->viewport[id].PA_CL_VPORT_ZSCALE.u32All);     
+    R600_OUT_BATCH(evergreen->viewport[id].PA_CL_VPORT_ZOFFSET.u32All);    
+    END_BATCH();
+
+    
+    for (id = 0; id < EVERGREEN_MAX_UCP; id++) {
+               if (evergreen->ucp[id].enabled) {
+                       BEGIN_BATCH_NO_AUTOSTATE(6);
+                       EVERGREEN_OUT_BATCH_REGSEQ(EG_PA_CL_UCP_0_X + (4 * id), 4);
+                       R600_OUT_BATCH(evergreen->ucp[id].PA_CL_UCP_0_X.u32All);
+                       R600_OUT_BATCH(evergreen->ucp[id].PA_CL_UCP_0_Y.u32All);
+                       R600_OUT_BATCH(evergreen->ucp[id].PA_CL_UCP_0_Z.u32All);
+                       R600_OUT_BATCH(evergreen->ucp[id].PA_CL_UCP_0_W.u32All);
+                       END_BATCH();                    
+               }
+       }
+
+    BEGIN_BATCH_NO_AUTOSTATE(42);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_PA_CL_CLIP_CNTL, 5);
+    R600_OUT_BATCH(evergreen->PA_CL_CLIP_CNTL.u32All);                           
+    R600_OUT_BATCH(evergreen->PA_SU_SC_MODE_CNTL.u32All);                       
+    R600_OUT_BATCH(evergreen->PA_CL_VTE_CNTL.u32All);                          
+    R600_OUT_BATCH(evergreen->PA_CL_VS_OUT_CNTL.u32All);                       
+    R600_OUT_BATCH(evergreen->PA_CL_NANINF_CNTL.u32All);                     
+     
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_PA_SU_POINT_SIZE, 3);
+    R600_OUT_BATCH(evergreen->PA_SU_POINT_SIZE.u32All);                        
+    R600_OUT_BATCH(evergreen->PA_SU_POINT_MINMAX.u32All);                        
+    R600_OUT_BATCH(evergreen->PA_SU_LINE_CNTL.u32All);                           
+    
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_PA_SC_MODE_CNTL_0, 2);
+    R600_OUT_BATCH(evergreen->PA_SC_MODE_CNTL_0.u32All);                         
+    R600_OUT_BATCH(evergreen->PA_SC_MODE_CNTL_1.u32All);                       
+
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_PA_SU_POLY_OFFSET_DB_FMT_CNTL, 6);
+    R600_OUT_BATCH(evergreen->PA_SU_POLY_OFFSET_DB_FMT_CNTL.u32All);            
+    R600_OUT_BATCH(evergreen->PA_SU_POLY_OFFSET_CLAMP.u32All);                  
+    R600_OUT_BATCH(evergreen->PA_SU_POLY_OFFSET_FRONT_SCALE.u32All);          
+    R600_OUT_BATCH(evergreen->PA_SU_POLY_OFFSET_FRONT_OFFSET.u32All);        
+    R600_OUT_BATCH(evergreen->PA_SU_POLY_OFFSET_BACK_SCALE.u32All);            
+    R600_OUT_BATCH(evergreen->PA_SU_POLY_OFFSET_BACK_OFFSET.u32All);            
+
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_PA_SC_LINE_CNTL, 16);
+    R600_OUT_BATCH(evergreen->PA_SC_LINE_CNTL.u32All);                           
+    R600_OUT_BATCH(evergreen->PA_SC_AA_CONFIG.u32All);                            
+    R600_OUT_BATCH(evergreen->PA_SU_VTX_CNTL.u32All);                           
+    R600_OUT_BATCH(evergreen->PA_CL_GB_VERT_CLIP_ADJ.u32All);                    
+    R600_OUT_BATCH(evergreen->PA_CL_GB_VERT_DISC_ADJ.u32All);                    
+    R600_OUT_BATCH(evergreen->PA_CL_GB_HORZ_CLIP_ADJ.u32All);                    
+    R600_OUT_BATCH(evergreen->PA_CL_GB_HORZ_DISC_ADJ.u32All);                    
+    R600_OUT_BATCH(evergreen->PA_SC_AA_SAMPLE_LOCS_0.u32All);                    
+    R600_OUT_BATCH(evergreen->PA_SC_AA_SAMPLE_LOCS_1.u32All);                    
+    R600_OUT_BATCH(evergreen->PA_SC_AA_SAMPLE_LOCS_2.u32All);                    
+    R600_OUT_BATCH(evergreen->PA_SC_AA_SAMPLE_LOCS_3.u32All);                    
+    R600_OUT_BATCH(evergreen->PA_SC_AA_SAMPLE_LOCS_4.u32All);                    
+    R600_OUT_BATCH(evergreen->PA_SC_AA_SAMPLE_LOCS_5.u32All);                    
+    R600_OUT_BATCH(evergreen->PA_SC_AA_SAMPLE_LOCS_6.u32All);                    
+    R600_OUT_BATCH(evergreen->PA_SC_AA_SAMPLE_LOCS_7.u32All);                    
+    R600_OUT_BATCH(evergreen->PA_SC_AA_MASK.u32All);    
+    
+    END_BATCH();
+
+    COMMIT_BATCH();
+}
+static void evergreenSendTP(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+    /*
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       BATCH_LOCALS(&context->radeon);
+       radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+    COMMIT_BATCH();
+    */
+}
+
+static void evergreenSendPSresource(GLcontext *ctx)
+{    
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+    struct radeon_bo * pbo;
+       
+       struct radeon_bo * pbo_const;
+
+    BATCH_LOCALS(&context->radeon);
+    radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+    pbo = (struct radeon_bo *)evergreenGetActiveFpShaderBo(GL_CONTEXT(context));
+
+    if (!pbo)
+           return;
+
+    r700SyncSurf(context, pbo, RADEON_GEM_DOMAIN_GTT, 0, SH_ACTION_ENA_bit);
+
+    BEGIN_BATCH_NO_AUTOSTATE(3 + 2);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_PGM_START_PS, 1);
+    R600_OUT_BATCH(evergreen->ps.SQ_PGM_START_PS.u32All);
+    R600_OUT_BATCH_RELOC(evergreen->ps.SQ_PGM_START_PS.u32All,
+                                pbo,
+                                evergreen->ps.SQ_PGM_START_PS.u32All,
+                                RADEON_GEM_DOMAIN_GTT, 0, 0);
+    END_BATCH();
+   
+    BEGIN_BATCH_NO_AUTOSTATE(3);
+    EVERGREEN_OUT_BATCH_REGVAL(EG_SQ_LOOP_CONST_0, 0x01000FFF);
+    END_BATCH();
+
+       pbo_const = (struct radeon_bo *)(context->fp_Constbo);
+        
+    if(NULL != pbo_const)
+    {                  
+        r700SyncSurf(context, pbo_const, RADEON_GEM_DOMAIN_GTT, 0, SH_ACTION_ENA_bit); 
+
+           BEGIN_BATCH_NO_AUTOSTATE(3);  
+        
+        if(evergreen->ps.num_consts < 4)
+        {
+            EVERGREEN_OUT_BATCH_REGVAL(EG_SQ_ALU_CONST_BUFFER_SIZE_PS_0, 1);
+        }
+        else
+        {
+            EVERGREEN_OUT_BATCH_REGVAL(EG_SQ_ALU_CONST_BUFFER_SIZE_PS_0, (evergreen->ps.num_consts * 4)/16 );
+        }
+        
+        END_BATCH();
+
+        BEGIN_BATCH_NO_AUTOSTATE(3 + 2);            
+        EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_ALU_CONST_CACHE_PS_0, 1);
+        R600_OUT_BATCH(context->fp_bo_offset >> 8);
+        R600_OUT_BATCH_RELOC(0,
+                                pbo_const,
+                                0,
+                                RADEON_GEM_DOMAIN_GTT, 0, 0);
+        END_BATCH();            
+    }        
+
+    COMMIT_BATCH();    
+}
+
+static void evergreenSendVSresource(GLcontext *ctx, struct radeon_state_atom *atom)
+{    
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+    struct radeon_bo * pbo;
+       
+       struct radeon_bo * pbo_const;
+
+    BATCH_LOCALS(&context->radeon);
+    radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+    pbo = (struct radeon_bo *)evergreenGetActiveVpShaderBo(GL_CONTEXT(context));
+
+    if (!pbo)
+           return;     
+
+    r700SyncSurf(context, pbo, RADEON_GEM_DOMAIN_GTT, 0, SH_ACTION_ENA_bit);
+
+    BEGIN_BATCH_NO_AUTOSTATE(3 + 2);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_PGM_START_VS, 1);
+    R600_OUT_BATCH(evergreen->vs.SQ_PGM_START_VS.u32All);
+    R600_OUT_BATCH_RELOC(evergreen->vs.SQ_PGM_START_VS.u32All,
+                                pbo,
+                                evergreen->vs.SQ_PGM_START_VS.u32All,
+                                RADEON_GEM_DOMAIN_GTT, 0, 0);
+    END_BATCH();
+
+    BEGIN_BATCH_NO_AUTOSTATE(3);
+    EVERGREEN_OUT_BATCH_REGVAL((EG_SQ_LOOP_CONST_0 + 32*1), 0x0100000F); //consts == 1
+    //EVERGREEN_OUT_BATCH_REGVAL((EG_SQ_LOOP_CONST_0 + (SQ_LOOP_CONST_vs<2)), 0x0100000F);
+    END_BATCH();
+            
+       pbo_const = (struct radeon_bo *)(context->vp_Constbo);    
+
+    if(NULL != pbo_const)
+    {                  
+        r700SyncSurf(context, pbo_const, RADEON_GEM_DOMAIN_GTT, 0, SH_ACTION_ENA_bit);
+
+           BEGIN_BATCH_NO_AUTOSTATE(3);   
+        
+        if(evergreen->vs.num_consts < 4)
+        {
+            EVERGREEN_OUT_BATCH_REGVAL(EG_SQ_ALU_CONST_BUFFER_SIZE_VS_0, 1);
+        }
+        else
+        {
+            EVERGREEN_OUT_BATCH_REGVAL(EG_SQ_ALU_CONST_BUFFER_SIZE_VS_0, (evergreen->vs.num_consts * 4)/16 );
+        }
+       
+        END_BATCH();
+
+        BEGIN_BATCH_NO_AUTOSTATE(3 + 2);            
+        EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_ALU_CONST_CACHE_VS_0, 1);
+        R600_OUT_BATCH(context->vp_bo_offset >> 8);
+        R600_OUT_BATCH_RELOC(0,
+                                pbo_const,
+                                0,
+                                RADEON_GEM_DOMAIN_GTT, 0, 0);
+        END_BATCH();            
+    }        
+
+    COMMIT_BATCH();    
+}
+
+static void evergreenSendSQ(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       BATCH_LOCALS(&context->radeon);
+       radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+    evergreenSendPSresource(ctx); //16 entries now
+
+    BEGIN_BATCH_NO_AUTOSTATE(77);
+
+    //34
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_VTX_SEMANTIC_0, 32);
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_0.u32All);    ////                      // = 0x28380, // SAME
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_1.u32All);    ////                      // = 0x28384, // SAME
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_2.u32All);    ////                      // = 0x28388, // SAME
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_3.u32All);    ////                      // = 0x2838C, // SAME
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_4.u32All);    ////                      // = 0x28390, // SAME
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_5.u32All);    ////                      // = 0x28394, // SAME
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_6.u32All);    ////                      // = 0x28398, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_7.u32All);    ////                      // = 0x2839C, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_8.u32All);    ////                      // = 0x283A0, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_9.u32All);    ////                      // = 0x283A4, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_10.u32All);   ////                      // = 0x283A8, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_11.u32All);   ////                      // = 0x283AC, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_12.u32All);   ////                      // = 0x283B0, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_13.u32All);   ////                      // = 0x283B4, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_14.u32All);   ////                      // = 0x283B8, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_15.u32All);   ////                      // = 0x283BC, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_16.u32All);   ////                      // = 0x283C0, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_17.u32All);   ////                      // = 0x283C4, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_18.u32All);   ////                      // = 0x283C8, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_19.u32All);   ////                      // = 0x283CC, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_20.u32All);   ////                      // = 0x283D0, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_21.u32All);   ////                      // = 0x283D4, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_22.u32All);   ////                      // = 0x283D8, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_23.u32All);   ////                      // = 0x283DC, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_24.u32All);   ////                      // = 0x283E0, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_25.u32All);   ////                      // = 0x283E4, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_26.u32All);   ////                      // = 0x283E8, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_27.u32All);   ////                      // = 0x283EC, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_28.u32All);   ////                      // = 0x283F0, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_29.u32All);   ////                      // = 0x283F4, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_30.u32All);   ////                      // = 0x283F8, // SAME 
+    R600_OUT_BATCH(evergreen->SQ_VTX_SEMANTIC_31.u32All);   ////                      // = 0x283FC, // SAME 
+    
+
+    //3
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_DYN_GPR_RESOURCE_LIMIT_1, 1);
+    R600_OUT_BATCH(evergreen->SQ_DYN_GPR_RESOURCE_LIMIT_1.u32All);////                // = 0x28838, // 
+    
+    //5
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_PGM_RESOURCES_PS, 3);
+    R600_OUT_BATCH(evergreen->SQ_PGM_RESOURCES_PS.u32All);  ////                      // = 0x28844, // DIFF 0x28850 
+    R600_OUT_BATCH(evergreen->SQ_PGM_RESOURCES_2_PS.u32All); ////                     // = 0x28848, // 
+    R600_OUT_BATCH(evergreen->SQ_PGM_EXPORTS_PS.u32All); ////                         // = 0x2884C, // SAME 0x28854 
+    
+    //4
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_PGM_RESOURCES_VS, 2);
+    R600_OUT_BATCH(evergreen->SQ_PGM_RESOURCES_VS.u32All);////                        // = 0x28860, // DIFF 0x28868 
+    R600_OUT_BATCH(evergreen->SQ_PGM_RESOURCES_2_VS.u32All);  ////                    // = 0x28864, // 
+
+    //5
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_PGM_RESOURCES_GS, 2);
+    /*
+    R600_OUT_BATCH(evergreen->SQ_PGM_START_GS.u32All); ////                           // = 0x28874, // SAME 0x2886C 
+    */
+    R600_OUT_BATCH(evergreen->SQ_PGM_RESOURCES_GS.u32All); ////                       // = 0x28878, // DIFF 0x2887C 
+    R600_OUT_BATCH(evergreen->SQ_PGM_RESOURCES_2_GS.u32All); ////                     // = 0x2887C, // 
+
+    //5
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_PGM_RESOURCES_ES, 2);
+    /*
+    R600_OUT_BATCH(evergreen->SQ_PGM_START_ES.u32All);  ////                          // = 0x2888C, // SAME 0x28880 
+    */
+    R600_OUT_BATCH(evergreen->SQ_PGM_RESOURCES_ES.u32All); ////                       // = 0x28890, // DIFF 
+    R600_OUT_BATCH(evergreen->SQ_PGM_RESOURCES_2_ES.u32All); ////                     // = 0x28894, // 
+
+    //4
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_PGM_RESOURCES_FS, 1);
+    /*
+    R600_OUT_BATCH(evergreen->SQ_PGM_START_FS.u32All); ////                           // = 0x288A4, // SAME 0x28894 
+    */
+    R600_OUT_BATCH(evergreen->SQ_PGM_RESOURCES_FS.u32All);  ////                      // = 0x288A8, // DIFF 0x288A4 
+    
+    //3
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_PGM_RESOURCES_2_HS, 1);
+    R600_OUT_BATCH(evergreen->SQ_PGM_RESOURCES_2_HS.u32All);////                      // = 0x288C0, // 
+    
+    //3
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_PGM_RESOURCES_2_LS, 1);
+    R600_OUT_BATCH(evergreen->SQ_PGM_RESOURCES_2_LS.u32All);  ////                    // = 0x288D8, // 
+    
+    //3
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_LDS_ALLOC_PS, 1);
+    R600_OUT_BATCH(evergreen->SQ_LDS_ALLOC_PS.u32All); ////                           // = 0x288EC, // 
+    
+    //8
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_ESGS_RING_ITEMSIZE, 6);
+    R600_OUT_BATCH(evergreen->SQ_ESGS_RING_ITEMSIZE.u32All); ////                     // = 0x28900, // SAME 0x288A8 
+    R600_OUT_BATCH(evergreen->SQ_GSVS_RING_ITEMSIZE.u32All); ////                     // = 0x28904, // SAME 0x288AC 
+    R600_OUT_BATCH(evergreen->SQ_ESTMP_RING_ITEMSIZE.u32All);  ////                   // = 0x28908, // SAME 0x288B0 
+    R600_OUT_BATCH(evergreen->SQ_GSTMP_RING_ITEMSIZE.u32All);  ////                   // = 0x2890C, // SAME 0x288B4 
+    R600_OUT_BATCH(evergreen->SQ_VSTMP_RING_ITEMSIZE.u32All);  ////                   // = 0x28910, // SAME 0x288B8 
+    R600_OUT_BATCH(evergreen->SQ_PSTMP_RING_ITEMSIZE.u32All);  ////                   // = 0x28914, // SAME 0x288BC 
+
+    //3
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SQ_GS_VERT_ITEMSIZE, 1);
+    R600_OUT_BATCH(evergreen->SQ_GS_VERT_ITEMSIZE.u32All);     ////                   // = 0x2891C, // SAME 0x288C8    
+    
+    END_BATCH();
+
+    COMMIT_BATCH();
+
+}
+static void evergreenSendSPI(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       BATCH_LOCALS(&context->radeon);
+       radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+    BEGIN_BATCH_NO_AUTOSTATE(59);
+
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SPI_VS_OUT_ID_0, 10);
+    R600_OUT_BATCH(evergreen->SPI_VS_OUT_ID_0.u32All);                        
+    R600_OUT_BATCH(evergreen->SPI_VS_OUT_ID_1.u32All);                        
+    R600_OUT_BATCH(evergreen->SPI_VS_OUT_ID_2.u32All);                        
+    R600_OUT_BATCH(evergreen->SPI_VS_OUT_ID_3.u32All);                        
+    R600_OUT_BATCH(evergreen->SPI_VS_OUT_ID_4.u32All);                        
+    R600_OUT_BATCH(evergreen->SPI_VS_OUT_ID_5.u32All);                        
+    R600_OUT_BATCH(evergreen->SPI_VS_OUT_ID_6.u32All);                        
+    R600_OUT_BATCH(evergreen->SPI_VS_OUT_ID_7.u32All);                        
+    R600_OUT_BATCH(evergreen->SPI_VS_OUT_ID_8.u32All);                        
+    R600_OUT_BATCH(evergreen->SPI_VS_OUT_ID_9.u32All);                        
+
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_SPI_PS_INPUT_CNTL_0, 45);
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[0].u32All);
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[1].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[2].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[3].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[4].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[5].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[6].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[7].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[8].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[9].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[10].u32All);
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[11].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[12].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[13].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[14].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[15].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[16].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[17].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[18].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[19].u32All);
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[20].u32All);
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[21].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[22].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[23].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[24].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[25].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[26].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[27].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[28].u32All); 
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[29].u32All);
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[30].u32All);
+    R600_OUT_BATCH(evergreen->SPI_PS_INPUT_CNTL[31].u32All);
+    R600_OUT_BATCH(evergreen->SPI_VS_OUT_CONFIG.u32All);                  
+    R600_OUT_BATCH(evergreen->SPI_THREAD_GROUPING.u32All);                 
+    R600_OUT_BATCH(evergreen->SPI_PS_IN_CONTROL_0.u32All);                 
+    R600_OUT_BATCH(evergreen->SPI_PS_IN_CONTROL_1.u32All);                 
+    R600_OUT_BATCH(evergreen->SPI_INTERP_CONTROL_0.u32All);                
+    R600_OUT_BATCH(evergreen->SPI_INPUT_Z.u32All);                         
+    R600_OUT_BATCH(evergreen->SPI_FOG_CNTL.u32All);                        
+    R600_OUT_BATCH(evergreen->SPI_BARYC_CNTL.u32All);  
+    R600_OUT_BATCH(evergreen->SPI_PS_IN_CONTROL_2.u32All); 
+    R600_OUT_BATCH(evergreen->SPI_COMPUTE_INPUT_CNTL.u32All);                     
+    R600_OUT_BATCH(evergreen->SPI_COMPUTE_NUM_THREAD_X.u32All);                   
+    R600_OUT_BATCH(evergreen->SPI_COMPUTE_NUM_THREAD_Y.u32All);                   
+    R600_OUT_BATCH(evergreen->SPI_COMPUTE_NUM_THREAD_Z.u32All);                   
+
+    END_BATCH();
+
+    COMMIT_BATCH();
+}
+static void evergreenSendSX(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       BATCH_LOCALS(&context->radeon);
+       radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+    BEGIN_BATCH_NO_AUTOSTATE(9);
+    
+    EVERGREEN_OUT_BATCH_REGVAL(EG_SX_MISC,               evergreen->SX_MISC.u32All); 
+    EVERGREEN_OUT_BATCH_REGVAL(EG_SX_ALPHA_TEST_CONTROL, evergreen->SX_ALPHA_TEST_CONTROL.u32All);
+    EVERGREEN_OUT_BATCH_REGVAL(EG_SX_ALPHA_REF,          evergreen->SX_ALPHA_REF.u32All);
+
+    END_BATCH();
+
+    COMMIT_BATCH();
+}
+
+static void evergreenSetDepthTarget(context_t *context)
+{
+    EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+    struct radeon_renderbuffer *rrb;
+    unsigned int nPitchInPixel;
+
+    rrb = radeon_get_depthbuffer(&context->radeon);
+    if (!rrb)
+    {
+        return;
+    }
+
+    EVERGREEN_STATECHANGE(context, db);
+
+    evergreen->DB_DEPTH_SIZE.u32All  = 0;        
+    
+    SETfield(evergreen->DB_DEPTH_SIZE.u32All, (nPitchInPixel/8)-1,
+             EG_DB_DEPTH_SIZE__PITCH_TILE_MAX_shift, 
+             EG_DB_DEPTH_SIZE__PITCH_TILE_MAX_mask);
+    SETfield(evergreen->DB_DEPTH_SIZE.u32All, (context->radeon.radeonScreen->driScreen->fbHeight/8)-1,
+             EG_DB_DEPTH_SIZE__HEIGHT_TILE_MAX_shift, 
+             EG_DB_DEPTH_SIZE__HEIGHT_TILE_MAX_mask);
+    evergreen->DB_DEPTH_SLICE.u32All = ( (nPitchInPixel * context->radeon.radeonScreen->driScreen->fbHeight)/64 )-1;
+
+    if(4 == rrb->cpp)
+    {
+        SETfield(evergreen->DB_Z_INFO.u32All, DEPTH_8_24,
+                 EG_DB_Z_INFO__FORMAT_shift, 
+                 EG_DB_Z_INFO__FORMAT_mask);
+    }
+    else
+    {
+        SETfield(evergreen->DB_Z_INFO.u32All, DEPTH_16,
+                 EG_DB_Z_INFO__FORMAT_shift, 
+                 EG_DB_Z_INFO__FORMAT_mask);
+    }
+    SETfield(evergreen->DB_Z_INFO.u32All, ARRAY_1D_TILED_THIN1,
+             EG_DB_Z_INFO__ARRAY_MODE_shift, 
+             EG_DB_Z_INFO__ARRAY_MODE_mask);        
+}
+
+static void evergreenSendDB(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+    struct radeon_renderbuffer *rrb;
+       BATCH_LOCALS(&context->radeon);
+       radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);  
+    
+    evergreenSetDepthTarget(context);
+
+    //8
+    BEGIN_BATCH_NO_AUTOSTATE(7); 
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_DB_RENDER_CONTROL, 5);
+    R600_OUT_BATCH(evergreen->DB_RENDER_CONTROL.u32All);                        
+    R600_OUT_BATCH(evergreen->DB_COUNT_CONTROL.u32All);                          
+    R600_OUT_BATCH(evergreen->DB_DEPTH_VIEW.u32All);                             
+    R600_OUT_BATCH(evergreen->DB_RENDER_OVERRIDE.u32All);                        
+    R600_OUT_BATCH(evergreen->DB_RENDER_OVERRIDE2.u32All);  
+    /*
+    R600_OUT_BATCH(evergreen->DB_HTILE_DATA_BASE.u32All); 
+    */
+    END_BATCH();
+
+    //4
+    BEGIN_BATCH_NO_AUTOSTATE(4); 
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_DB_STENCIL_CLEAR, 2);
+    R600_OUT_BATCH(evergreen->DB_STENCIL_CLEAR.u32All);                          
+    R600_OUT_BATCH(evergreen->DB_DEPTH_CLEAR.u32All);  
+    END_BATCH();
+
+    //4    
+    BEGIN_BATCH_NO_AUTOSTATE(4);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_DB_DEPTH_SIZE, 2);
+    R600_OUT_BATCH(evergreen->DB_DEPTH_SIZE.u32All);                              
+    R600_OUT_BATCH(evergreen->DB_DEPTH_SLICE.u32All);
+    END_BATCH();    
+    
+    //3
+    BEGIN_BATCH_NO_AUTOSTATE(3);
+    EVERGREEN_OUT_BATCH_REGVAL(EG_DB_DEPTH_CONTROL, evergreen->DB_DEPTH_CONTROL.u32All);
+    END_BATCH();
+
+    //3
+    BEGIN_BATCH_NO_AUTOSTATE(3);
+    EVERGREEN_OUT_BATCH_REGVAL(EG_DB_SHADER_CONTROL, evergreen->DB_SHADER_CONTROL.u32All);  
+    END_BATCH();
+
+    //5
+    BEGIN_BATCH_NO_AUTOSTATE(5);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_DB_SRESULTS_COMPARE_STATE0, 3);                        
+    R600_OUT_BATCH(evergreen->DB_SRESULTS_COMPARE_STATE0.u32All);               
+    R600_OUT_BATCH(evergreen->DB_SRESULTS_COMPARE_STATE1.u32All);               
+    R600_OUT_BATCH(evergreen->DB_PRELOAD_CONTROL.u32All); 
+    END_BATCH();
+
+    //3
+    BEGIN_BATCH_NO_AUTOSTATE(3);
+    EVERGREEN_OUT_BATCH_REGVAL(EG_DB_ALPHA_TO_MASK, evergreen->DB_ALPHA_TO_MASK.u32All);    
+    END_BATCH();
+    
+    rrb = radeon_get_depthbuffer(&context->radeon);
+       if( (rrb != NULL) && (rrb->bo != NULL) )
+    {
+        //5
+        BEGIN_BATCH_NO_AUTOSTATE(3 + 2);
+        EVERGREEN_OUT_BATCH_REGVAL(EG_DB_Z_INFO, evergreen->DB_Z_INFO.u32All);
+        R600_OUT_BATCH_RELOC(evergreen->DB_Z_INFO.u32All,
+                            rrb->bo,
+                            evergreen->DB_Z_INFO.u32All,
+                            0, RADEON_GEM_DOMAIN_VRAM, 0);
+        END_BATCH();
+
+        //5
+        if((evergreen->DB_DEPTH_CONTROL.u32All & Z_ENABLE_bit) > 0)
+        {
+            BEGIN_BATCH_NO_AUTOSTATE(3 + 2);
+            EVERGREEN_OUT_BATCH_REGVAL(EG_DB_Z_READ_BASE, evergreen->DB_Z_READ_BASE.u32All);           
+               R600_OUT_BATCH_RELOC(evergreen->DB_Z_READ_BASE.u32All,
+                                            rrb->bo,
+                                            evergreen->DB_Z_READ_BASE.u32All,
+                                            0, RADEON_GEM_DOMAIN_VRAM, 0);
+            END_BATCH();
+        }
+        //5
+        if((evergreen->DB_DEPTH_CONTROL.u32All & Z_WRITE_ENABLE_bit) > 0)
+        {
+            BEGIN_BATCH_NO_AUTOSTATE(3 + 2);
+            EVERGREEN_OUT_BATCH_REGVAL(EG_DB_Z_WRITE_BASE, evergreen->DB_Z_READ_BASE.u32All);  
+               R600_OUT_BATCH_RELOC(evergreen->DB_Z_WRITE_BASE.u32All,
+                                            rrb->bo,
+                                            evergreen->DB_Z_WRITE_BASE.u32All,
+                                            0, RADEON_GEM_DOMAIN_VRAM, 0);
+            END_BATCH();        
+        }
+       }    
+/*
+    if (ctx->DrawBuffer) 
+    {
+               rrb     = radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
+               
+        if((rrb != NULL) && (rrb->bo != NULL))
+        {
+            //5
+            BEGIN_BATCH_NO_AUTOSTATE(3 + 2);
+            EVERGREEN_OUT_BATCH_REGVAL(EG_DB_STENCIL_INFO, evergreen->DB_Z_INFO.u32All);
+            R600_OUT_BATCH_RELOC(evergreen->DB_STENCIL_INFO.u32All,
+                            rrb->bo,
+                            evergreen->DB_STENCIL_INFO.u32All,
+                            0, RADEON_GEM_DOMAIN_VRAM, 0);
+            END_BATCH();
+
+            //10
+            if((evergreen->DB_DEPTH_CONTROL.u32All & STENCIL_ENABLE_bit) > 0)
+            {
+                BEGIN_BATCH_NO_AUTOSTATE(3 + 2);
+                EVERGREEN_OUT_BATCH_REGVAL(EG_DB_STENCIL_READ_BASE, evergreen->DB_STENCIL_READ_BASE.u32All);   
+                   R600_OUT_BATCH_RELOC(evergreen->DB_STENCIL_READ_BASE.u32All,
+                                                rrb->bo,
+                                                evergreen->DB_STENCIL_READ_BASE.u32All,
+                                                0, RADEON_GEM_DOMAIN_VRAM, 0);
+                END_BATCH();
+
+                BEGIN_BATCH_NO_AUTOSTATE(3 + 2);
+                EVERGREEN_OUT_BATCH_REGVAL(EG_DB_STENCIL_WRITE_BASE, evergreen->DB_STENCIL_WRITE_BASE.u32All); 
+                   R600_OUT_BATCH_RELOC(evergreen->DB_STENCIL_WRITE_BASE.u32All,
+                                                rrb->bo,
+                                                evergreen->DB_STENCIL_WRITE_BASE.u32All,
+                                                0, RADEON_GEM_DOMAIN_VRAM, 0);
+                END_BATCH();                   
+            }     
+        }
+       }   
+*/    
+    COMMIT_BATCH();
+}
+
+static void evergreenSetRenderTarget(context_t *context, int id)
+{
+    EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+
+    struct radeon_renderbuffer *rrb;
+    unsigned int nPitchInPixel;
+
+    rrb = radeon_get_colorbuffer(&context->radeon);
+    if (!rrb || !rrb->bo) {
+           return;
+    }
+
+    EVERGREEN_STATECHANGE(context, cb);
+
+    /* addr */
+    evergreen->render_target[id].CB_COLOR0_BASE.u32All = context->radeon.state.color.draw_offset / 256;
+
+    /* pitch */
+    nPitchInPixel = rrb->pitch/rrb->cpp;    
+
+    SETfield(evergreen->render_target[id].CB_COLOR0_PITCH.u32All, (nPitchInPixel/8)-1,
+             EG_CB_COLOR0_PITCH__TILE_MAX_shift, 
+             EG_CB_COLOR0_PITCH__TILE_MAX_mask);
+
+    /* skice */
+    SETfield(evergreen->render_target[id].CB_COLOR0_SLICE.u32All, 
+             //( (nPitchInPixel * context->radeon.radeonScreen->driScreen->fbHeight)/64 )-1,
+             ( (nPitchInPixel * 240)/64 )-1,
+             EG_CB_COLOR0_SLICE__TILE_MAX_shift, 
+             EG_CB_COLOR0_SLICE__TILE_MAX_mask);
+
+    /* CB_COLOR0_ATTRIB */ /* TODO : for z clear, this should be set to 0 */
+    SETbit(evergreen->render_target[id].CB_COLOR0_ATTRIB.u32All, 
+           EG_CB_COLOR0_ATTRIB__NON_DISP_TILING_ORDER_bit);
+
+    /* CB_COLOR0_INFO */
+    SETfield(evergreen->render_target[id].CB_COLOR0_INFO.u32All, 
+             ENDIAN_NONE, 
+             EG_CB_COLOR0_INFO__ENDIAN_shift, 
+             EG_CB_COLOR0_INFO__ENDIAN_mask);
+    SETfield(evergreen->render_target[id].CB_COLOR0_INFO.u32All, 
+             ARRAY_LINEAR_GENERAL, 
+             EG_CB_COLOR0_INFO__ARRAY_MODE_shift, 
+             EG_CB_COLOR0_INFO__ARRAY_MODE_mask);   
+    if(4 == rrb->cpp)
+    {
+        SETfield(evergreen->render_target[id].CB_COLOR0_INFO.u32All, 
+                 COLOR_8_8_8_8,
+                 EG_CB_COLOR0_INFO__FORMAT_shift, 
+                 EG_CB_COLOR0_INFO__FORMAT_mask);
+        SETfield(evergreen->render_target[id].CB_COLOR0_INFO.u32All, 
+                 SWAP_ALT, //SWAP_STD
+                 EG_CB_COLOR0_INFO__COMP_SWAP_shift, 
+                 EG_CB_COLOR0_INFO__COMP_SWAP_mask);
+    }
+    else
+    {
+        SETfield(evergreen->render_target[id].CB_COLOR0_INFO.u32All, 
+                 COLOR_5_6_5,
+                 EG_CB_COLOR0_INFO__FORMAT_shift, 
+                 EG_CB_COLOR0_INFO__FORMAT_mask);
+        SETfield(evergreen->render_target[id].CB_COLOR0_INFO.u32All, 
+                 SWAP_ALT_REV,
+                 EG_CB_COLOR0_INFO__COMP_SWAP_shift, 
+                 EG_CB_COLOR0_INFO__COMP_SWAP_mask);
+    }
+    SETfield(evergreen->render_target[id].CB_COLOR0_INFO.u32All, 
+             1,
+             EG_CB_COLOR0_INFO__SOURCE_FORMAT_shift, 
+             EG_CB_COLOR0_INFO__SOURCE_FORMAT_mask);
+    SETbit(evergreen->render_target[id].CB_COLOR0_INFO.u32All, 
+           EG_CB_COLOR0_INFO__BLEND_CLAMP_bit);
+    SETfield(evergreen->render_target[id].CB_COLOR0_INFO.u32All, 
+             NUMBER_UNORM,
+             EG_CB_COLOR0_INFO__NUMBER_TYPE_shift, 
+             EG_CB_COLOR0_INFO__NUMBER_TYPE_mask);
+
+    evergreen->render_target[id].CB_COLOR0_VIEW.u32All        = 0;
+    evergreen->render_target[id].CB_COLOR0_CMASK.u32All       = 0;
+    evergreen->render_target[id].CB_COLOR0_FMASK.u32All       = 0;
+    evergreen->render_target[id].CB_COLOR0_FMASK_SLICE.u32All = 0; 
+
+    evergreen->render_target[id].enabled = GL_TRUE;
+}
+
+static void evergreenSendCB(GLcontext *ctx, struct radeon_state_atom *atom)
+{    
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       struct radeon_renderbuffer *rrb;
+       BATCH_LOCALS(&context->radeon);
+       int id = 0;
+       radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+       rrb = radeon_get_colorbuffer(&context->radeon);
+       if (!rrb || !rrb->bo) {
+               return;
+       }
+
+       evergreenSetRenderTarget(context, 0);
+
+       if (!evergreen->render_target[id].enabled)
+               return;
+
+    BEGIN_BATCH_NO_AUTOSTATE(3 + 2);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_CB_COLOR0_BASE + (4 * id), 1);
+       R600_OUT_BATCH(evergreen->render_target[id].CB_COLOR0_BASE.u32All);
+       R600_OUT_BATCH_RELOC(evergreen->render_target[id].CB_COLOR0_BASE.u32All,
+                                    rrb->bo,
+                                    evergreen->render_target[id].CB_COLOR0_BASE.u32All,
+                                    0, RADEON_GEM_DOMAIN_VRAM, 0);
+    END_BATCH();
+
+    BEGIN_BATCH_NO_AUTOSTATE(3 + 2);
+    EVERGREEN_OUT_BATCH_REGVAL(EG_CB_COLOR0_INFO, evergreen->render_target[id].CB_COLOR0_INFO.u32All);
+    R600_OUT_BATCH_RELOC(evergreen->render_target[id].CB_COLOR0_INFO.u32All,
+                                rrb->bo,
+                                evergreen->render_target[id].CB_COLOR0_INFO.u32All,
+                                0, RADEON_GEM_DOMAIN_VRAM, 0);
+    END_BATCH();
+
+    BEGIN_BATCH_NO_AUTOSTATE(5);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_CB_COLOR0_PITCH, 3);
+    R600_OUT_BATCH(evergreen->render_target[id].CB_COLOR0_PITCH.u32All); 
+    R600_OUT_BATCH(evergreen->render_target[id].CB_COLOR0_SLICE.u32All); 
+    R600_OUT_BATCH(evergreen->render_target[id].CB_COLOR0_VIEW.u32All);  
+    END_BATCH();
+
+    BEGIN_BATCH_NO_AUTOSTATE(4);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_CB_COLOR0_ATTRIB, 2);
+    R600_OUT_BATCH(evergreen->render_target[id].CB_COLOR0_ATTRIB.u32All); 
+    R600_OUT_BATCH(evergreen->render_target[id].CB_COLOR0_DIM.u32All); 
+    /*
+    R600_OUT_BATCH(evergreen->render_target[id].CB_COLOR0_CMASK.u32All);  
+    R600_OUT_BATCH(evergreen->render_target[id].CB_COLOR0_CMASK_SLICE.u32All);    
+    R600_OUT_BATCH(evergreen->render_target[id].CB_COLOR0_FMASK.u32All); 
+    R600_OUT_BATCH(evergreen->render_target[id].CB_COLOR0_FMASK_SLICE.u32All); 
+    */
+    END_BATCH();
+
+    BEGIN_BATCH_NO_AUTOSTATE(4);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_CB_TARGET_MASK, 2);
+    R600_OUT_BATCH(evergreen->CB_TARGET_MASK.u32All);   
+    R600_OUT_BATCH(evergreen->CB_SHADER_MASK.u32All);   
+    END_BATCH();
+
+    BEGIN_BATCH_NO_AUTOSTATE(5);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_CB_BLEND_RED, 3);
+    R600_OUT_BATCH(evergreen->CB_BLEND_RED.u32All);    
+    R600_OUT_BATCH(evergreen->CB_BLEND_GREEN.u32All);  
+    R600_OUT_BATCH(evergreen->CB_BLEND_BLUE.u32All);   
+    END_BATCH();
+
+    BEGIN_BATCH_NO_AUTOSTATE(9);
+    EVERGREEN_OUT_BATCH_REGVAL(EG_CB_BLEND_ALPHA, evergreen->CB_BLEND_ALPHA.u32All);  
+    EVERGREEN_OUT_BATCH_REGVAL(EG_CB_BLEND0_CONTROL, evergreen->CB_BLEND0_CONTROL.u32All);  
+    EVERGREEN_OUT_BATCH_REGVAL(EG_CB_COLOR_CONTROL, evergreen->CB_COLOR_CONTROL.u32All);  
+    END_BATCH();
+    
+    COMMIT_BATCH();
+}
+static void evergreenSendCP(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);       
+       BATCH_LOCALS(&context->radeon);
+       radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+    //first to send
+    //r700Start3D
+    BEGIN_BATCH_NO_AUTOSTATE(3);
+    R600_OUT_BATCH(CP_PACKET3(R600_IT_CONTEXT_CONTROL, 1)); //IT_CONTEXT_CONTROL 0x28
+    R600_OUT_BATCH(0x80000000);
+    R600_OUT_BATCH(0x80000000);
+    END_BATCH();
+
+    COMMIT_BATCH();
+}
+static void evergreenSendVGT(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       BATCH_LOCALS(&context->radeon);
+       radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+
+/* moved to draw:
+    VGT_DRAW_INITIATOR             
+    VGT_INDEX_TYPE                 
+    VGT_PRIMITIVE_TYPE             
+*/
+    BEGIN_BATCH_NO_AUTOSTATE(5);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_VGT_MAX_VTX_INDX, 3);
+    R600_OUT_BATCH(evergreen->VGT_MAX_VTX_INDX.u32All);    
+    R600_OUT_BATCH(evergreen->VGT_MIN_VTX_INDX.u32All);    
+    R600_OUT_BATCH(evergreen->VGT_INDX_OFFSET.u32All);     
+    END_BATCH();
+    
+    BEGIN_BATCH_NO_AUTOSTATE(6);
+    EVERGREEN_OUT_BATCH_REGVAL(EG_VGT_OUTPUT_PATH_CNTL, evergreen->VGT_OUTPUT_PATH_CNTL.u32All); 
+    
+    EVERGREEN_OUT_BATCH_REGVAL(EG_VGT_GS_MODE, evergreen->VGT_GS_MODE.u32All); 
+    END_BATCH();
+    
+    BEGIN_BATCH_NO_AUTOSTATE(3);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_VGT_PRIMITIVEID_EN, 1);
+    R600_OUT_BATCH(evergreen->VGT_PRIMITIVEID_EN.u32All);   
+    END_BATCH();
+    
+    BEGIN_BATCH_NO_AUTOSTATE(4);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_VGT_INSTANCE_STEP_RATE_0, 2);
+    R600_OUT_BATCH(evergreen->VGT_INSTANCE_STEP_RATE_0.u32All); 
+    R600_OUT_BATCH(evergreen->VGT_INSTANCE_STEP_RATE_1.u32All); 
+    END_BATCH();
+
+    BEGIN_BATCH_NO_AUTOSTATE(4);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_VGT_REUSE_OFF, 2);
+    R600_OUT_BATCH(evergreen->VGT_REUSE_OFF.u32All);      
+    R600_OUT_BATCH(evergreen->VGT_VTX_CNT_EN.u32All);     
+    END_BATCH();
+    
+    BEGIN_BATCH_NO_AUTOSTATE(3);
+    EVERGREEN_OUT_BATCH_REGVAL(EG_VGT_SHADER_STAGES_EN, evergreen->VGT_SHADER_STAGES_EN.u32All);  
+    END_BATCH();
+    
+    BEGIN_BATCH_NO_AUTOSTATE(4);
+    EVERGREEN_OUT_BATCH_REGSEQ(EG_VGT_STRMOUT_CONFIG, 2);
+    R600_OUT_BATCH(evergreen->VGT_STRMOUT_CONFIG.u32All); 
+    R600_OUT_BATCH(evergreen->VGT_STRMOUT_BUFFER_CONFIG.u32All);  
+    END_BATCH();
+
+    COMMIT_BATCH();
+}
+
+static void evergreenSendTIMESTAMP(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);       
+       BATCH_LOCALS(&context->radeon);
+       radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
+}
+
+void evergreenInitAtoms(context_t *context)
+{        
+    radeon_print(RADEON_STATE, RADEON_NORMAL, "%s %p\n", __func__, context);
+    context->radeon.hw.max_state_size = 10 + 5 + 14 + 3; /* start 3d, idle, cb/db flush, 3 for time stamp */
+
+    /* Setup the atom linked list */
+    make_empty_list(&context->radeon.hw.atomlist);
+    context->radeon.hw.atomlist.name = "atom-list";
+
+    EVERGREEN_ALLOC_STATE(init, always, 19, evergreenSendSQConfig);
+
+    //make sure send first
+    EVERGREEN_ALLOC_STATE(cp, always, 3,    evergreenSendCP);
+
+    EVERGREEN_ALLOC_STATE(vtx,       evergreen_vtx, (6 + (VERT_ATTRIB_MAX * 12)), evergreenSendVTX);
+    EVERGREEN_ALLOC_STATE(pa,        always,        124, evergreenSendPA);
+    EVERGREEN_ALLOC_STATE(tp,        always,        0,   evergreenSendTP);
+    EVERGREEN_ALLOC_STATE(sq,        always,        86,  evergreenSendSQ); /* 85 */
+    EVERGREEN_ALLOC_STATE(vs,        always,        16,  evergreenSendVSresource);
+    EVERGREEN_ALLOC_STATE(spi,       always,        59,  evergreenSendSPI);
+    EVERGREEN_ALLOC_STATE(sx,        always,        9,   evergreenSendSX);
+    EVERGREEN_ALLOC_STATE(tx,        evergreen_tx,  (R700_TEXTURE_NUMBERUNITS * (21+5) + 6), evergreenSendTexState); /* 21 for resource, 5 for sampler */
+    EVERGREEN_ALLOC_STATE(db,        always,        60,  evergreenSendDB); 
+    EVERGREEN_ALLOC_STATE(cb,        always,        35,  evergreenSendCB);     
+    EVERGREEN_ALLOC_STATE(vgt,       always,        29,  evergreenSendVGT);
+    EVERGREEN_ALLOC_STATE(timestamp, always,        3,   evergreenSendTIMESTAMP);
+
+    //evergreen_init_query_stateobj(&context->radeon, 6 * 2);
+
+    context->radeon.hw.is_dirty = GL_TRUE;
+    context->radeon.hw.all_dirty = GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/r600/evergreen_chip.h b/src/mesa/drivers/dri/r600/evergreen_chip.h
new file mode 100644 (file)
index 0000000..2ea5cd2
--- /dev/null
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2008-2010  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com> 
+ */
+
+#ifndef _EVERGREEN_CHIP_H_
+#define _EVERGREEN_CHIP_H_
+
+#include "r700_chip.h"
+
+#define EVERGREEN_MAX_DX9_CONSTS      256
+#define EVERGREEN_MAX_SHADER_EXPORTS  32
+#define EVERGREEN_MAX_VIEWPORTS       16
+
+typedef struct _EVERGREEN_VIEWPORT_STATE
+{
+       union UINT_FLOAT PA_SC_VPORT_SCISSOR_0_TL;   ////0,1         // = 0x28250, // DIFF 
+    union UINT_FLOAT PA_SC_VPORT_SCISSOR_0_BR;   ////0,1         // = 0x28254, // DIFF 
+       union UINT_FLOAT PA_SC_VPORT_ZMIN_0; ////0                        // = 0x282D0, // SAME 
+    union UINT_FLOAT PA_SC_VPORT_ZMAX_0; ////0                        // = 0x282D4, // SAME 
+       union UINT_FLOAT PA_CL_VPORT_XSCALE;    ////                 // = 0x2843C, // SAME 
+    union UINT_FLOAT PA_CL_VPORT_XOFFSET;   ////                 // = 0x28440, // SAME 
+    union UINT_FLOAT PA_CL_VPORT_YSCALE;    ////                 // = 0x28444, // SAME 
+    union UINT_FLOAT PA_CL_VPORT_YOFFSET;   ////                 // = 0x28448, // SAME 
+    union UINT_FLOAT PA_CL_VPORT_ZSCALE;    ////                 // = 0x2844C, // SAME 
+    union UINT_FLOAT PA_CL_VPORT_ZOFFSET;   ////                 // = 0x28450, // SAME 
+       GLboolean                         enabled;
+       GLboolean                         dirty;
+} EVERGREEN_VIEWPORT_STATE;
+
+#define EVERGREEN_MAX_UCP             6
+
+typedef struct _EVERGREEN_UCP_STATE
+{
+       union UINT_FLOAT PA_CL_UCP_0_X;                              // = 0x285BC, // SAME 0x28E20 
+    union UINT_FLOAT PA_CL_UCP_0_Y;                              // = 0x285C0, // SAME 0x28E24 
+    union UINT_FLOAT PA_CL_UCP_0_Z;                              // = 0x285C4, // SAME 0x28E28 
+    union UINT_FLOAT PA_CL_UCP_0_W;                              // = 0x285C8, // SAME 0x28E2C 
+       GLboolean                         enabled;
+       GLboolean                         dirty;
+} EVERGREEN_UCP_STATE;
+
+#define EVERGREEN_MAX_RENDER_TARGETS  12
+
+typedef struct _EVERGREEN_RENDER_TARGET_STATE
+{
+       union UINT_FLOAT CB_COLOR0_BASE;   ////0                          // = 0x28C60, // SAME 0x28040 
+    union UINT_FLOAT CB_COLOR0_PITCH;  ////0                          // = 0x28C64, // 
+    union UINT_FLOAT CB_COLOR0_SLICE;  ////0                          // = 0x28C68, // 
+    union UINT_FLOAT CB_COLOR0_VIEW;   ////0                          // = 0x28C6C, // SAME 0x28080 
+    union UINT_FLOAT CB_COLOR0_INFO;   ////0,1,2,3,4,5,6,78,9,10,11                          // = 0x28C70, // DIFF 0x280A0 
+    union UINT_FLOAT CB_COLOR0_ATTRIB; ////0                          // = 0x28C74, // 
+    union UINT_FLOAT CB_COLOR0_DIM;                              // = 0x28C78, // 
+    union UINT_FLOAT CB_COLOR0_CMASK;  ////0                          // = 0x28C7C, // 
+    union UINT_FLOAT CB_COLOR0_CMASK_SLICE; ////0                     // = 0x28C80, // 
+    union UINT_FLOAT CB_COLOR0_FMASK; ////0                           // = 0x28C84, // 
+    union UINT_FLOAT CB_COLOR0_FMASK_SLICE;  ////0                    // = 0x28C88, // 
+    union UINT_FLOAT CB_COLOR0_CLEAR_WORD0;                      // = 0x28C8C, // 
+    union UINT_FLOAT CB_COLOR0_CLEAR_WORD1;                      // = 0x28C90, // 
+    union UINT_FLOAT CB_COLOR0_CLEAR_WORD2;                      // = 0x28C94, // 
+    union UINT_FLOAT CB_COLOR0_CLEAR_WORD3;                      // = 0x28C98, //
+       GLboolean                         enabled;
+       GLboolean                         dirty;
+} EVERGREEN_RENDER_TARGET_STATE;
+
+typedef struct _EVERGREEN_CONFIG
+{
+    union UINT_FLOAT                SPI_CONFIG_CNTL;              // = 0x9100,  // DIFF
+    union UINT_FLOAT                SPI_CONFIG_CNTL_1;            // = 0x913C,  // DIFF
+    union UINT_FLOAT                CP_PERFMON_CNTL;              // = 0x87FC,  // SAME
+    union UINT_FLOAT                SQ_MS_FIFO_SIZES;             // = 0x8CF0,  // SAME
+
+       union UINT_FLOAT                SQ_CONFIG;                    // = 0x8C00,  // DIFF 
+       union UINT_FLOAT                SQ_GPR_RESOURCE_MGMT_1;       // = 0x8C04,  // SAME 
+       union UINT_FLOAT                SQ_GPR_RESOURCE_MGMT_2;       // = 0x8C08,  // SAME 
+    union UINT_FLOAT                   SQ_GPR_RESOURCE_MGMT_3;       // = 0x8C0C,  //
+
+       union UINT_FLOAT                SQ_THREAD_RESOURCE_MGMT;      // = 0x8C18,  // SAME 0x8C0C 
+    union UINT_FLOAT                   SQ_THREAD_RESOURCE_MGMT_2;    // = 0x8C1C,  //
+       union UINT_FLOAT                SQ_STACK_RESOURCE_MGMT_1;     // = 0x8C20,  // SAME 0x8C10 
+       union UINT_FLOAT                SQ_STACK_RESOURCE_MGMT_2;     // = 0x8C24,  // SAME 0x8C14 
+    union UINT_FLOAT                   SQ_STACK_RESOURCE_MGMT_3;     // = 0x8C28,  //
+
+    union UINT_FLOAT                   SQ_DYN_GPR_CNTL_PS_FLUSH_REQ; // = 0x8D8C,  // DIFF
+    union UINT_FLOAT                   SQ_LDS_RESOURCE_MGMT;         // = 0x8E2C,  //            
+    union UINT_FLOAT                   VGT_CACHE_INVALIDATION;       // = 0x88C4,  // DIFF
+    union UINT_FLOAT                   VGT_GS_VERTEX_REUSE;          // = 0x88D4,  // SAME
+    union UINT_FLOAT                   PA_SC_FORCE_EOV_MAX_CNTS;     // = 0x8B24,  // SAME
+    union UINT_FLOAT                   PA_SC_LINE_STIPPLE_STATE;     // = 0x8B10,  // SAME
+    union UINT_FLOAT                   PA_CL_ENHANCE;                // = 0x8A14,  // SAME
+} EVERGREEN_CONFIG;
+
+typedef struct _EVERGREEN_PS_RES
+{
+       union            UINT_FLOAT SQ_PGM_START_PS; ////                           // = 0x28840, // SAME       
+       GLboolean        dirty;
+
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_0;                    // = 0x28940, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_1;                    // = 0x28944, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_2;                    // = 0x28948, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_3;                    // = 0x2894C, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_4;                    // = 0x28950, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_5;                    // = 0x28954, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_6;                    // = 0x28958, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_7;                    // = 0x2895C, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_8;                    // = 0x28960, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_9;                    // = 0x28964, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_10;                   // = 0x28968, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_11;                   // = 0x2896C, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_12;                   // = 0x28970, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_13;                   // = 0x28974, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_14;                   // = 0x28978, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_PS_15;                   // = 0x2897C, // SAME 
+
+       int              num_consts;
+       union UINT_FLOAT consts[EVERGREEN_MAX_DX9_CONSTS][4];
+} EVERGREEN_PS_RES;
+
+typedef struct _EVERGREEN_VS_RES
+{
+       union UINT_FLOAT SQ_PGM_START_VS;               ////             // = 0x2885C, // SAME 0x28858  
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_VS_0; ////             // = 0x28180, //?
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_0;       ////             // = 0x28980, // SAME 
+
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_1;                    // = 0x28984, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_2;                    // = 0x28988, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_3;                    // = 0x2898C, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_4;                    // = 0x28990, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_5;                    // = 0x28994, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_6;                    // = 0x28998, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_7;                    // = 0x2899C, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_8;                    // = 0x289A0, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_9;                    // = 0x289A4, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_10;                   // = 0x289A8, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_11;                   // = 0x289AC, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_12;                   // = 0x289B0, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_13;                   // = 0x289B4, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_14;                   // = 0x289B8, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_VS_15;                   // = 0x289BC, // SAME
+
+       GLboolean        dirty;
+       int              num_consts;
+       union UINT_FLOAT consts[EVERGREEN_MAX_DX9_CONSTS][4];
+} EVERGREEN_VS_RES;
+
+typedef struct _EVERGREEN_CHIP_CONTEXT 
+{
+/* Registers from PA block: */
+    union UINT_FLOAT PA_SC_SCREEN_SCISSOR_TL;  ////                  // = 0x28030, // DIFF 
+    union UINT_FLOAT PA_SC_SCREEN_SCISSOR_BR;  ////                  // = 0x28034, // DIFF 
+    union UINT_FLOAT PA_SC_WINDOW_OFFSET;      ////                  // = 0x28200, // DIFF 
+    union UINT_FLOAT PA_SC_WINDOW_SCISSOR_TL;  ////                  // = 0x28204, // DIFF 
+    union UINT_FLOAT PA_SC_WINDOW_SCISSOR_BR;  ////                  // = 0x28208, // DIFF 
+    union UINT_FLOAT PA_SC_CLIPRECT_RULE;      ////                  // = 0x2820C, // SAME 
+    union UINT_FLOAT PA_SC_CLIPRECT_0_TL;      ////                  // = 0x28210, // DIFF 
+    union UINT_FLOAT PA_SC_CLIPRECT_0_BR;      ////                  // = 0x28214, // DIFF 
+    union UINT_FLOAT PA_SC_CLIPRECT_1_TL; ////                   // = 0x28218, // DIFF 
+    union UINT_FLOAT PA_SC_CLIPRECT_1_BR; ////                   // = 0x2821C, // DIFF 
+    union UINT_FLOAT PA_SC_CLIPRECT_2_TL; ////                   // = 0x28220, // DIFF 
+    union UINT_FLOAT PA_SC_CLIPRECT_2_BR; ////                   // = 0x28224, // DIFF 
+    union UINT_FLOAT PA_SC_CLIPRECT_3_TL; ////                   // = 0x28228, // DIFF 
+    union UINT_FLOAT PA_SC_CLIPRECT_3_BR; ////                   // = 0x2822C, // DIFF 
+    union UINT_FLOAT PA_SC_EDGERULE;                             // = 0x28230, // SAME 
+    union UINT_FLOAT PA_SU_HARDWARE_SCREEN_OFFSET;               // = 0x28234, // 
+    union UINT_FLOAT PA_SC_GENERIC_SCISSOR_TL; ////              // = 0x28240, // DIFF 
+    union UINT_FLOAT PA_SC_GENERIC_SCISSOR_BR; ////              // = 0x28244, // DIFF
+    
+    EVERGREEN_VIEWPORT_STATE viewport[EVERGREEN_MAX_VIEWPORTS];    
+    EVERGREEN_UCP_STATE      ucp[EVERGREEN_MAX_UCP];
+
+    union UINT_FLOAT PA_CL_POINT_X_RAD;                          // = 0x287D4, // SAME 0x28E10 
+    union UINT_FLOAT PA_CL_POINT_Y_RAD;                          // = 0x287D8, // SAME 0x28E14 
+    union UINT_FLOAT PA_CL_POINT_SIZE;                           // = 0x287DC, // SAME 0x28E18 
+    union UINT_FLOAT PA_CL_POINT_CULL_RAD;                       // = 0x287E0, // SAME 0x28E1C 
+    union UINT_FLOAT PA_CL_CLIP_CNTL;   ////                         // = 0x28810, // SAME 
+    union UINT_FLOAT PA_SU_SC_MODE_CNTL; ////                        // = 0x28814, // SAME 
+    union UINT_FLOAT PA_CL_VTE_CNTL;   ////                          // = 0x28818, // SAME 
+    union UINT_FLOAT PA_CL_VS_OUT_CNTL; ////                         // = 0x2881C, // SAME 
+    union UINT_FLOAT PA_CL_NANINF_CNTL;  ////                        // = 0x28820, // SAME 
+    union UINT_FLOAT PA_SU_LINE_STIPPLE_CNTL;                    // = 0x28824, // 
+    union UINT_FLOAT PA_SU_LINE_STIPPLE_SCALE;                   // = 0x28828, // 
+    union UINT_FLOAT PA_SU_PRIM_FILTER_CNTL;                     // = 0x2882C, // 
+    union UINT_FLOAT PA_SU_POINT_SIZE; ////                          // = 0x28A00, // SAME 
+    union UINT_FLOAT PA_SU_POINT_MINMAX;  ////                       // = 0x28A04, // SAME 
+    union UINT_FLOAT PA_SU_LINE_CNTL;    ////                        // = 0x28A08, // SAME 
+    union UINT_FLOAT PA_SC_LINE_STIPPLE;                         // = 0x28A0C, // SAME 
+    union UINT_FLOAT PA_SC_MODE_CNTL_0; ////                         // = 0x28A48, // 
+    union UINT_FLOAT PA_SC_MODE_CNTL_1; ////                         // = 0x28A4C, // 
+    union UINT_FLOAT PA_SU_POLY_OFFSET_DB_FMT_CNTL; ////             // = 0x28B78, // SAME 0x28DF8 
+    union UINT_FLOAT PA_SU_POLY_OFFSET_CLAMP; ////                   // = 0x28B7C, // SAME 0x28DFC 
+    union UINT_FLOAT PA_SU_POLY_OFFSET_FRONT_SCALE;////              // = 0x28B80, // SAME 0x28E00 
+    union UINT_FLOAT PA_SU_POLY_OFFSET_FRONT_OFFSET; ////            // = 0x28B84, // SAME 0x28E04 
+    union UINT_FLOAT PA_SU_POLY_OFFSET_BACK_SCALE;  ////             // = 0x28B88, // SAME 0x28E08 
+    union UINT_FLOAT PA_SU_POLY_OFFSET_BACK_OFFSET; ////             // = 0x28B8C, // SAME 0x28E0C 
+    union UINT_FLOAT PA_SC_LINE_CNTL; ////                           // = 0x28C00, // DIFF 
+    union UINT_FLOAT PA_SC_AA_CONFIG; ////                           // = 0x28C04, // SAME 
+    union UINT_FLOAT PA_SU_VTX_CNTL;  ////                           // = 0x28C08, // SAME 
+    union UINT_FLOAT PA_CL_GB_VERT_CLIP_ADJ; ////                    // = 0x28C0C, // SAME 
+    union UINT_FLOAT PA_CL_GB_VERT_DISC_ADJ; ////                    // = 0x28C10, // SAME 
+    union UINT_FLOAT PA_CL_GB_HORZ_CLIP_ADJ; ////                    // = 0x28C14, // SAME 
+    union UINT_FLOAT PA_CL_GB_HORZ_DISC_ADJ; ////                    // = 0x28C18, // SAME 
+    union UINT_FLOAT PA_SC_AA_SAMPLE_LOCS_0; ////                    // = 0x28C1C, // 
+    union UINT_FLOAT PA_SC_AA_SAMPLE_LOCS_1; ////                    // = 0x28C20, // 
+    union UINT_FLOAT PA_SC_AA_SAMPLE_LOCS_2; ////                    // = 0x28C24, // 
+    union UINT_FLOAT PA_SC_AA_SAMPLE_LOCS_3; ////                    // = 0x28C28, // 
+    union UINT_FLOAT PA_SC_AA_SAMPLE_LOCS_4; ////                    // = 0x28C2C, // 
+    union UINT_FLOAT PA_SC_AA_SAMPLE_LOCS_5; ////                    // = 0x28C30, // 
+    union UINT_FLOAT PA_SC_AA_SAMPLE_LOCS_6; ////                    // = 0x28C34, // 
+    union UINT_FLOAT PA_SC_AA_SAMPLE_LOCS_7; ////                    // = 0x28C38, // 
+    union UINT_FLOAT PA_SC_AA_MASK;   ////                           // = 0x28C3C, // SAME 0x28C48 
+
+/* Registers from VGT block: */
+    union UINT_FLOAT VGT_INDEX_TYPE;                             // =  0x895C, // SAME
+    union UINT_FLOAT VGT_PRIMITIVE_TYPE;                         // =  0x8958, // SAME
+    union UINT_FLOAT VGT_MAX_VTX_INDX;   ////                    // = 0x28400, // SAME 
+    union UINT_FLOAT VGT_MIN_VTX_INDX;   ////                    // = 0x28404, // SAME 
+    union UINT_FLOAT VGT_INDX_OFFSET;    ////                    // = 0x28408, // SAME 
+    union UINT_FLOAT VGT_MULTI_PRIM_IB_RESET_INDX;               // = 0x2840C, // SAME         
+         
+    union UINT_FLOAT VGT_DRAW_INITIATOR;                         // = 0x287F0, // SAME 
+    union UINT_FLOAT VGT_IMMED_DATA;                             // = 0x287F4, // SAME 
+     
+    union UINT_FLOAT VGT_OUTPUT_PATH_CNTL; ////                      // = 0x28A10, // DIFF 
+    union UINT_FLOAT VGT_HOS_CNTL;                               // = 0x28A14, // SAME 
+    union UINT_FLOAT VGT_HOS_MAX_TESS_LEVEL;                     // = 0x28A18, // SAME 
+    union UINT_FLOAT VGT_HOS_MIN_TESS_LEVEL;                     // = 0x28A1C, // SAME 
+    union UINT_FLOAT VGT_HOS_REUSE_DEPTH;                        // = 0x28A20, // SAME 
+    union UINT_FLOAT VGT_GROUP_PRIM_TYPE;                        // = 0x28A24, // SAME 
+    union UINT_FLOAT VGT_GROUP_FIRST_DECR;                       // = 0x28A28, // SAME 
+    union UINT_FLOAT VGT_GROUP_DECR;                             // = 0x28A2C, // SAME 
+    union UINT_FLOAT VGT_GROUP_VECT_0_CNTL;                      // = 0x28A30, // SAME 
+    union UINT_FLOAT VGT_GROUP_VECT_1_CNTL;                      // = 0x28A34, // SAME 
+    union UINT_FLOAT VGT_GROUP_VECT_0_FMT_CNTL;                  // = 0x28A38, // SAME 
+    union UINT_FLOAT VGT_GROUP_VECT_1_FMT_CNTL;                  // = 0x28A3C, // SAME 
+    union UINT_FLOAT VGT_GS_MODE; ////                               // = 0x28A40, // DIFF 
+       
+    union UINT_FLOAT VGT_PRIMITIVEID_EN;   ////                  // = 0x28A84, // SAME 
+    union UINT_FLOAT VGT_DMA_NUM_INSTANCES;  ////                // = 0x28A88, // SAME 
+    union UINT_FLOAT VGT_EVENT_INITIATOR;                        // = 0x28A90, // SAME 
+    union UINT_FLOAT VGT_MULTI_PRIM_IB_RESET_EN;                 // = 0x28A94, // SAME 
+    union UINT_FLOAT VGT_INSTANCE_STEP_RATE_0; ////                  // = 0x28AA0, // SAME 
+    union UINT_FLOAT VGT_INSTANCE_STEP_RATE_1; ////                  // = 0x28AA4, // SAME 
+    union UINT_FLOAT VGT_REUSE_OFF; ////                             // = 0x28AB4, // SAME 
+    union UINT_FLOAT VGT_VTX_CNT_EN; ////                            // = 0x28AB8, // SAME 
+    
+    union UINT_FLOAT VGT_SHADER_STAGES_EN;  ////                     // = 0x28B54, //
+    union UINT_FLOAT VGT_STRMOUT_CONFIG; ////                        // = 0x28B94, // 
+    union UINT_FLOAT VGT_STRMOUT_BUFFER_CONFIG;  ////                // = 0x28B98, // 
+    union UINT_FLOAT VGT_VERTEX_REUSE_BLOCK_CNTL;////                // = 0x28C58, // SAME 
+    union UINT_FLOAT VGT_OUT_DEALLOC_CNTL;  ////                     // = 0x28C5C, // SAME 
+
+/* Registers from SQ block: */     
+    union UINT_FLOAT SQ_VTX_SEMANTIC_0;    ////                      // = 0x28380, // SAME
+    union UINT_FLOAT SQ_VTX_SEMANTIC_1;    ////                      // = 0x28384, // SAME
+    union UINT_FLOAT SQ_VTX_SEMANTIC_2;    ////                      // = 0x28388, // SAME
+    union UINT_FLOAT SQ_VTX_SEMANTIC_3;    ////                      // = 0x2838C, // SAME
+    union UINT_FLOAT SQ_VTX_SEMANTIC_4;    ////                      // = 0x28390, // SAME
+    union UINT_FLOAT SQ_VTX_SEMANTIC_5;    ////                      // = 0x28394, // SAME
+    union UINT_FLOAT SQ_VTX_SEMANTIC_6;    ////                      // = 0x28398, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_7;    ////                      // = 0x2839C, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_8;    ////                      // = 0x283A0, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_9;    ////                      // = 0x283A4, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_10;   ////                      // = 0x283A8, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_11;   ////                      // = 0x283AC, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_12;   ////                      // = 0x283B0, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_13;   ////                      // = 0x283B4, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_14;   ////                      // = 0x283B8, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_15;   ////                      // = 0x283BC, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_16;   ////                      // = 0x283C0, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_17;   ////                      // = 0x283C4, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_18;   ////                      // = 0x283C8, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_19;   ////                      // = 0x283CC, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_20;   ////                      // = 0x283D0, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_21;   ////                      // = 0x283D4, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_22;   ////                      // = 0x283D8, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_23;   ////                      // = 0x283DC, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_24;   ////                      // = 0x283E0, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_25;   ////                      // = 0x283E4, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_26;   ////                      // = 0x283E8, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_27;   ////                      // = 0x283EC, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_28;   ////                      // = 0x283F0, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_29;   ////                      // = 0x283F4, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_30;   ////                      // = 0x283F8, // SAME 
+    union UINT_FLOAT SQ_VTX_SEMANTIC_31;   ////                      // = 0x283FC, // SAME     
+    union UINT_FLOAT SQ_DYN_GPR_RESOURCE_LIMIT_1;////                // = 0x28838, // 
+    
+    union UINT_FLOAT SQ_PGM_RESOURCES_PS;  ////                      // = 0x28844, // DIFF 0x28850 
+    union UINT_FLOAT SQ_PGM_RESOURCES_2_PS; ////                     // = 0x28848, // 
+    union UINT_FLOAT SQ_PGM_EXPORTS_PS; ////                         // = 0x2884C, // SAME 0x28854 
+    
+    union UINT_FLOAT SQ_PGM_RESOURCES_VS;////                        // = 0x28860, // DIFF 0x28868 
+    union UINT_FLOAT SQ_PGM_RESOURCES_2_VS;  ////                    // = 0x28864, // 
+    union UINT_FLOAT SQ_PGM_START_GS; ////                           // = 0x28874, // SAME 0x2886C 
+    union UINT_FLOAT SQ_PGM_RESOURCES_GS; ////                       // = 0x28878, // DIFF 0x2887C 
+    union UINT_FLOAT SQ_PGM_RESOURCES_2_GS; ////                     // = 0x2887C, // 
+    union UINT_FLOAT SQ_PGM_START_ES;  ////                          // = 0x2888C, // SAME 0x28880 
+    union UINT_FLOAT SQ_PGM_RESOURCES_ES; ////                       // = 0x28890, // DIFF 
+    union UINT_FLOAT SQ_PGM_RESOURCES_2_ES; ////                     // = 0x28894, // 
+    union UINT_FLOAT SQ_PGM_START_FS; ////                           // = 0x288A4, // SAME 0x28894 
+    union UINT_FLOAT SQ_PGM_RESOURCES_FS;  ////                      // = 0x288A8, // DIFF 0x288A4 
+    union UINT_FLOAT SQ_PGM_START_HS;                            // = 0x288B8, // 
+    union UINT_FLOAT SQ_PGM_RESOURCES_HS;                        // = 0x288BC, // 
+    union UINT_FLOAT SQ_PGM_RESOURCES_2_HS;////                      // = 0x288C0, // 
+    union UINT_FLOAT SQ_PGM_START_LS;                            // = 0x288D0, // 
+    union UINT_FLOAT SQ_PGM_RESOURCES_LS;                        // = 0x288D4, // 
+    union UINT_FLOAT SQ_PGM_RESOURCES_2_LS;  ////                    // = 0x288D8, //         
+    union UINT_FLOAT SQ_LDS_ALLOC_PS; ////                           // = 0x288EC, //         
+    union UINT_FLOAT SQ_ESGS_RING_ITEMSIZE; ////                     // = 0x28900, // SAME 0x288A8 
+    union UINT_FLOAT SQ_GSVS_RING_ITEMSIZE; ////                     // = 0x28904, // SAME 0x288AC 
+    union UINT_FLOAT SQ_ESTMP_RING_ITEMSIZE;  ////                   // = 0x28908, // SAME 0x288B0 
+    union UINT_FLOAT SQ_GSTMP_RING_ITEMSIZE;  ////                   // = 0x2890C, // SAME 0x288B4 
+    union UINT_FLOAT SQ_VSTMP_RING_ITEMSIZE;  ////                   // = 0x28910, // SAME 0x288B8 
+    union UINT_FLOAT SQ_PSTMP_RING_ITEMSIZE;  ////                   // = 0x28914, // SAME 0x288BC 
+    union UINT_FLOAT SQ_GS_VERT_ITEMSIZE;     ////                   // = 0x2891C, // SAME 0x288C8 
+    union UINT_FLOAT SQ_GS_VERT_ITEMSIZE_1;                      // = 0x28920, // 
+    union UINT_FLOAT SQ_GS_VERT_ITEMSIZE_2;                      // = 0x28924, // 
+    union UINT_FLOAT SQ_GS_VERT_ITEMSIZE_3;                      // = 0x28928, //             
+     
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_0;                    // = 0x289C0, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_1;                    // = 0x289C4, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_2;                    // = 0x289C8, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_3;                    // = 0x289CC, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_4;                    // = 0x289D0, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_5;                    // = 0x289D4, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_6;                    // = 0x289D8, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_7;                    // = 0x289DC, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_8;                    // = 0x289E0, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_9;                    // = 0x289E4, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_10;                   // = 0x289E8, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_11;                   // = 0x289EC, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_12;                   // = 0x289F0, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_13;                   // = 0x289F4, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_14;                   // = 0x289F8, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_GS_15;                   // = 0x289FC, // SAME 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_0;                    // = 0x28F00, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_1;                    // = 0x28F04, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_2;                    // = 0x28F08, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_3;                    // = 0x28F0C, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_4;                    // = 0x28F10, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_5;                    // = 0x28F14, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_6;                    // = 0x28F18, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_7;                    // = 0x28F1C, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_8;                    // = 0x28F20, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_9;                    // = 0x28F24, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_10;                   // = 0x28F28, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_11;                   // = 0x28F2C, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_12;                   // = 0x28F30, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_13;                   // = 0x28F34, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_14;                   // = 0x28F38, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_HS_15;                   // = 0x28F3C, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_0;                    // = 0x28F40, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_1;                    // = 0x28F44, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_2;                    // = 0x28F48, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_3;                    // = 0x28F4C, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_4;                    // = 0x28F50, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_5;                    // = 0x28F54, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_6;                    // = 0x28F58, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_7;                    // = 0x28F5C, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_8;                    // = 0x28F60, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_9;                    // = 0x28F64, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_10;                   // = 0x28F68, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_11;                   // = 0x28F6C, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_12;                   // = 0x28F70, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_13;                   // = 0x28F74, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_14;                   // = 0x28F78, // 
+    union UINT_FLOAT SQ_ALU_CONST_CACHE_LS_15;                   // = 0x28F7C, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_0;              // = 0x28F80, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_1;              // = 0x28F84, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_2;              // = 0x28F88, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_3;              // = 0x28F8C, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_4;              // = 0x28F90, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_5;              // = 0x28F94, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_6;              // = 0x28F98, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_7;              // = 0x28F9C, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_8;              // = 0x28FA0, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_9;              // = 0x28FA4, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_10;             // = 0x28FA8, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_11;             // = 0x28FAC, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_12;             // = 0x28FB0, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_13;             // = 0x28FB4, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_14;             // = 0x28FB8, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_HS_15;             // = 0x28FBC, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_0;              // = 0x28FC0, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_1;              // = 0x28FC4, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_2;              // = 0x28FC8, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_3;              // = 0x28FCC, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_4;              // = 0x28FD0, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_5;              // = 0x28FD4, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_6;              // = 0x28FD8, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_7;              // = 0x28FDC, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_8;              // = 0x28FE0, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_9;              // = 0x28FE4, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_10;             // = 0x28FE8, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_11;             // = 0x28FEC, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_12;             // = 0x28FF0, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_13;             // = 0x28FF4, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_14;             // = 0x28FF8, // 
+    union UINT_FLOAT SQ_ALU_CONST_BUFFER_SIZE_LS_15;             // = 0x28FFC, // 
+
+    EVERGREEN_PS_RES ps;
+    EVERGREEN_VS_RES vs;
+
+/* Registers from SPI block: */
+    union UINT_FLOAT SPI_VS_OUT_ID_0;     ////                   // = 0x2861C, // SAME 0x28614 
+    union UINT_FLOAT SPI_VS_OUT_ID_1;     ////                   // = 0x28620, // SAME 0x28618 
+    union UINT_FLOAT SPI_VS_OUT_ID_2;     ////                   // = 0x28624, // SAME 0x2861C 
+    union UINT_FLOAT SPI_VS_OUT_ID_3;     ////                   // = 0x28628, // SAME 0x28620 
+    union UINT_FLOAT SPI_VS_OUT_ID_4;     ////                   // = 0x2862C, // SAME 0x28624 
+    union UINT_FLOAT SPI_VS_OUT_ID_5;     ////                   // = 0x28630, // SAME 0x28628 
+    union UINT_FLOAT SPI_VS_OUT_ID_6;     ////                   // = 0x28634, // SAME 0x2862C 
+    union UINT_FLOAT SPI_VS_OUT_ID_7;     ////                   // = 0x28638, // SAME 0x28630 
+    union UINT_FLOAT SPI_VS_OUT_ID_8;     ////                   // = 0x2863C, // SAME 0x28634 
+    union UINT_FLOAT SPI_VS_OUT_ID_9;     ////                   // = 0x28640, // SAME 0x28638 
+    union UINT_FLOAT SPI_PS_INPUT_CNTL[32];     ////                   // = 0x28644, // SAME 
+    
+    union UINT_FLOAT SPI_VS_OUT_CONFIG;  ////                        // = 0x286C4, // SAME 
+    union UINT_FLOAT SPI_THREAD_GROUPING; ////                       // = 0x286C8, // DIFF 
+    union UINT_FLOAT SPI_PS_IN_CONTROL_0; ////                       // = 0x286CC, // SAME 
+    union UINT_FLOAT SPI_PS_IN_CONTROL_1; ////                       // = 0x286D0, // SAME 
+    union UINT_FLOAT SPI_INTERP_CONTROL_0;  ////                     // = 0x286D4, // SAME 
+    union UINT_FLOAT SPI_INPUT_Z;           ////                     // = 0x286D8, // SAME 
+    union UINT_FLOAT SPI_FOG_CNTL;          ////                     // = 0x286DC, // SAME 
+    union UINT_FLOAT SPI_BARYC_CNTL;  ////                           // = 0x286E0, // 
+    union UINT_FLOAT SPI_PS_IN_CONTROL_2; ////                       // = 0x286E4, // 
+    union UINT_FLOAT SPI_COMPUTE_INPUT_CNTL;                     // = 0x286E8, // 
+    union UINT_FLOAT SPI_COMPUTE_NUM_THREAD_X;                   // = 0x286EC, // 
+    union UINT_FLOAT SPI_COMPUTE_NUM_THREAD_Y;                   // = 0x286F0, // 
+    union UINT_FLOAT SPI_COMPUTE_NUM_THREAD_Z;                   // = 0x286F4, // 
+
+/* Registers from SX block: */
+    union UINT_FLOAT SX_MISC;                                    // = 0x28350, // SAME 
+    union UINT_FLOAT SX_SURFACE_SYNC;                            // = 0x28354, // DIFF 
+    union UINT_FLOAT SX_ALPHA_TEST_CONTROL;  ////                // = 0x28410, // SAME 
+    union UINT_FLOAT SX_ALPHA_REF;                               // = 0x28438, // SAME 
+
+/* Registers from DB block: */
+    union UINT_FLOAT DB_RENDER_CONTROL; ////                         // = 0x28000, // DIFF 0x28D0C 
+    union UINT_FLOAT DB_COUNT_CONTROL; ////                          // = 0x28004, // 
+    union UINT_FLOAT DB_DEPTH_VIEW;  ////                            // = 0x28008, // DIFF 0x28004 
+    union UINT_FLOAT DB_RENDER_OVERRIDE;   ////                      // = 0x2800C, // DIFF 0x28D10 
+    union UINT_FLOAT DB_RENDER_OVERRIDE2;  ////                      // = 0x28010, // 
+    union UINT_FLOAT DB_HTILE_DATA_BASE;   ////                      // = 0x28014, // SAME 
+    union UINT_FLOAT DB_STENCIL_CLEAR; ////                          // = 0x28028, // SAME 
+    union UINT_FLOAT DB_DEPTH_CLEAR; ////                            // = 0x2802C, // SAME 
+    union UINT_FLOAT DB_Z_INFO;   ////                               // = 0x28040, // 
+    union UINT_FLOAT DB_STENCIL_INFO;  ////                          // = 0x28044, // 
+    union UINT_FLOAT DB_Z_READ_BASE; ////                            // = 0x28048, // 
+    union UINT_FLOAT DB_STENCIL_READ_BASE;////                       // = 0x2804C, // 
+    union UINT_FLOAT DB_Z_WRITE_BASE;  ////                          // = 0x28050, // 
+    union UINT_FLOAT DB_STENCIL_WRITE_BASE; ////                     // = 0x28054, // 
+    union UINT_FLOAT DB_DEPTH_SIZE;   ////                           // = 0x28058, // DIFF 0x28000 
+    union UINT_FLOAT DB_DEPTH_SLICE; ////                            // = 0x2805C, // 
+    union UINT_FLOAT DB_STENCILREFMASK;                          // = 0x28430, // SAME 
+    union UINT_FLOAT DB_STENCILREFMASK_BF;                       // = 0x28434, // SAME 
+    union UINT_FLOAT DB_DEPTH_CONTROL;      ////                     // = 0x28800, // SAME 
+    union UINT_FLOAT DB_SHADER_CONTROL;////                          // = 0x2880C, // DIFF 
+    union UINT_FLOAT DB_HTILE_SURFACE;  ////                         // = 0x28ABC, // SAME 0x28D24 
+    union UINT_FLOAT DB_SRESULTS_COMPARE_STATE0; ////                // = 0x28AC0, // SAME 0x28D28 
+    union UINT_FLOAT DB_SRESULTS_COMPARE_STATE1; ////                // = 0x28AC4, // SAME 0x28D2C 
+    union UINT_FLOAT DB_PRELOAD_CONTROL; ////                        // = 0x28AC8, // SAME 0x28D30 
+    union UINT_FLOAT DB_ALPHA_TO_MASK; ////                          // = 0x28B70, // SAME 0x28D44 
+
+/* Registers from CB block: */
+    union UINT_FLOAT CB_TARGET_MASK;  ////                       // = 0x28238, // SAME 
+    union UINT_FLOAT CB_SHADER_MASK;  ////                       // = 0x2823C, // SAME 
+    union UINT_FLOAT CB_BLEND_RED;   ////                            // = 0x28414, // SAME 
+    union UINT_FLOAT CB_BLEND_GREEN; ////                            // = 0x28418, // SAME 
+    union UINT_FLOAT CB_BLEND_BLUE;  ////                            // = 0x2841C, // SAME 
+    union UINT_FLOAT CB_BLEND_ALPHA;  ////                           // = 0x28420, // SAME 
+    union UINT_FLOAT CB_BLEND0_CONTROL; ////                         // = 0x28780, // DIFF 
+    union UINT_FLOAT CB_BLEND1_CONTROL;                          // = 0x28784, // DIFF 
+    union UINT_FLOAT CB_BLEND2_CONTROL;                          // = 0x28788, // DIFF 
+    union UINT_FLOAT CB_BLEND3_CONTROL;                          // = 0x2878C, // DIFF 
+    union UINT_FLOAT CB_BLEND4_CONTROL;                          // = 0x28790, // DIFF 
+    union UINT_FLOAT CB_BLEND5_CONTROL;                          // = 0x28794, // DIFF 
+    union UINT_FLOAT CB_BLEND6_CONTROL;                          // = 0x28798, // DIFF 
+    union UINT_FLOAT CB_BLEND7_CONTROL;                          // = 0x2879C, // DIFF 
+    union UINT_FLOAT CB_COLOR_CONTROL; ////                          // = 0x28808, // DIFF      
+    union UINT_FLOAT CB_CLRCMP_CONTROL; ////                         // = 0x28C40, // SAME 0x28C30 
+    union UINT_FLOAT CB_CLRCMP_SRC;  ////                            // = 0x28C44, // SAME 0x28C34 
+    union UINT_FLOAT CB_CLRCMP_DST;  ////                            // = 0x28C48, // SAME 0x28C38 
+    union UINT_FLOAT CB_CLRCMP_MSK;  ////                            // = 0x28C4C, // SAME 0x28C3C 
+    
+    EVERGREEN_RENDER_TARGET_STATE      render_target[EVERGREEN_MAX_RENDER_TARGETS];  
+    
+    radeonTexObj*    textures[R700_TEXTURE_NUMBERUNITS];
+
+    EVERGREEN_CONFIG evergreen_config;
+
+    GLboolean           bEnablePerspective;
+
+} EVERGREEN_CHIP_CONTEXT;
+
+#endif /* _EVERGREEN_CHIP_H_ */
\ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/evergreen_context.c b/src/mesa/drivers/dri/r600/evergreen_context.c
new file mode 100644 (file)
index 0000000..65b5898
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008-2010  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#include "main/glheader.h"
+#include "main/api_arrayelt.h"
+#include "main/context.h"
+#include "main/simple_list.h"
+#include "main/imports.h"
+#include "main/bufferobj.h"
+#include "main/texobj.h"
+
+#include "radeon_common_context.h"
+#include "evergreen_context.h"
+#include "evergreen_state.h"
+#include "r600_blit.h"
+
+static void evergreen_get_lock(radeonContextPtr rmesa)
+{
+       drm_radeon_sarea_t *sarea = rmesa->sarea;
+
+       if (sarea->ctx_owner != rmesa->dri.hwContext) {
+               sarea->ctx_owner = rmesa->dri.hwContext;
+               if (!rmesa->radeonScreen->kernel_mm)
+                       radeon_bo_legacy_texture_age(rmesa->radeonScreen->bom);
+       }
+}
+
+static void evergreen_vtbl_emit_cs_header(struct radeon_cs *cs, radeonContextPtr rmesa)
+{
+    /* please flush pipe do all pending work */
+    /* to be enabled */
+}
+
+static void evergreen_vtbl_pre_emit_atoms(radeonContextPtr radeon)
+{
+    //TODO apr.01
+       //r700Start3D((context_t *)radeon);
+}
+
+static void evergreen_fallback(GLcontext *ctx, GLuint bit, GLboolean mode)
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       if (mode)
+               context->radeon.Fallback |= bit;
+       else
+               context->radeon.Fallback &= ~bit;
+}
+
+static void evergreen_emit_query_finish(radeonContextPtr radeon)
+{
+    //TODO apr.01
+       //context_t *context = (context_t*) radeon;
+       //BATCH_LOCALS(&context->radeon);
+
+       struct radeon_query_object *query = radeon->query.current;
+
+       //BEGIN_BATCH_NO_AUTOSTATE(4 + 2);
+       //R600_OUT_BATCH(CP_PACKET3(R600_IT_EVENT_WRITE, 2));
+       //R600_OUT_BATCH(ZPASS_DONE);
+       //R600_OUT_BATCH(query->curr_offset + 8); /* hw writes qwords */
+       //R600_OUT_BATCH(0x00000000);
+       //R600_OUT_BATCH_RELOC(VGT_EVENT_INITIATOR, query->bo, 0, 0, RADEON_GEM_DOMAIN_GTT, 0);
+       //END_BATCH();
+       //assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
+       query->emitted_begin = GL_FALSE;
+}
+
+void evergreen_init_vtbl(radeonContextPtr radeon)
+{
+       radeon->vtbl.get_lock = evergreen_get_lock;
+       radeon->vtbl.update_viewport_offset = evergreenUpdateViewportOffset;
+       radeon->vtbl.emit_cs_header = evergreen_vtbl_emit_cs_header;
+       radeon->vtbl.swtcl_flush = NULL;
+       radeon->vtbl.pre_emit_atoms = evergreen_vtbl_pre_emit_atoms;
+       radeon->vtbl.fallback = evergreen_fallback;
+       radeon->vtbl.emit_query_finish = evergreen_emit_query_finish;
+       radeon->vtbl.check_blit = r600_check_blit;
+       radeon->vtbl.blit = r600_blit;
+       radeon->vtbl.is_format_renderable = radeonIsFormatRenderable;
+}
+
+
+
diff --git a/src/mesa/drivers/dri/r600/evergreen_context.h b/src/mesa/drivers/dri/r600/evergreen_context.h
new file mode 100644 (file)
index 0000000..4e50999
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008-2010  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#ifndef _EVERGREEN_CONTEXT_H_
+#define _EVERGREEN_CONTEXT_H_
+
+extern void evergreen_init_vtbl(radeonContextPtr radeon);
+
+#endif //_EVERGREEN_CONTEXT_H_
+
+
+
+
+
+
diff --git a/src/mesa/drivers/dri/r600/evergreen_diff.h b/src/mesa/drivers/dri/r600/evergreen_diff.h
new file mode 100644 (file)
index 0000000..c3a5fd0
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2008-2010  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#ifndef _EVERGREEN_DIFF_H_
+#define _EVERGREEN_DIFF_H_
+
+enum {
+    /* CB_BLEND_CONTROL */
+        EG_CB_BLENDX_CONTROL_ENABLE_bit = 1 << 30,
+    /* PA_SC_SCREEN_SCISSOR_TL */
+        EG_PA_SC_SCREEN_SCISSOR_TL__TL_X_mask                = 0xffff << 0,    
+           EG_PA_SC_SCREEN_SCISSOR_TL__TL_Y_mask                = 0xffff << 16,
+    /* PA_SC_SCREEN_SCISSOR_BR */
+           EG_PA_SC_SCREEN_SCISSOR_BR__BR_X_mask                = 0xffff << 0, 
+           EG_PA_SC_SCREEN_SCISSOR_BR__BR_Y_mask                = 0xffff << 16,
+    /* PA_SC_WINDOW_SCISSOR_TL */ 
+           EG_PA_SC_WINDOW_SCISSOR_TL__TL_X_mask                = 0x7fff << 0, 
+           EG_PA_SC_WINDOW_SCISSOR_TL__TL_Y_mask                = 0x7fff << 16,        
+    /* PA_SC_WINDOW_SCISSOR_BR */
+           EG_PA_SC_WINDOW_SCISSOR_BR__BR_X_mask                = 0x7fff << 0, 
+           EG_PA_SC_WINDOW_SCISSOR_BR__BR_Y_mask                = 0x7fff << 16,
+    /* PA_SC_CLIPRECT_0_TL */
+        EG_PA_SC_CLIPRECT_0_TL__TL_X_mask                    = 0x7fff << 0,    
+           EG_PA_SC_CLIPRECT_0_TL__TL_Y_mask                    = 0x7fff << 16,        
+    /* PA_SC_CLIPRECT_0_BR */  
+           EG_PA_SC_CLIPRECT_0_BR__BR_X_mask                    = 0x7fff << 0, 
+           EG_PA_SC_CLIPRECT_0_BR__BR_Y_mask                    = 0x7fff << 16,
+    /* PA_SC_GENERIC_SCISSOR_TL */
+           EG_PA_SC_GENERIC_SCISSOR_TL__TL_X_mask               = 0x7fff << 0, 
+           EG_PA_SC_GENERIC_SCISSOR_TL__TL_Y_mask               = 0x7fff << 16,        
+    /* PA_SC_GENERIC_SCISSOR_BR */
+           EG_PA_SC_GENERIC_SCISSOR_BR__BR_X_mask               = 0x7fff << 0, 
+           EG_PA_SC_GENERIC_SCISSOR_BR__BR_Y_mask               = 0x7fff << 16,
+    /* PA_SC_VPORT_SCISSOR_0_TL */     
+           EG_PA_SC_VPORT_SCISSOR_0_TL__TL_X_mask               = 0x7fff << 0, 
+           EG_PA_SC_VPORT_SCISSOR_0_TL__TL_Y_mask               = 0x7fff << 16,        
+    /* PA_SC_VPORT_SCISSOR_0_BR */             
+           EG_PA_SC_VPORT_SCISSOR_0_BR__BR_X_mask               = 0x7fff << 0, 
+           EG_PA_SC_VPORT_SCISSOR_0_BR__BR_Y_mask               = 0x7fff << 16,
+    /* PA_SC_WINDOW_OFFSET */
+        EG_PA_SC_WINDOW_OFFSET__WINDOW_X_OFFSET_shift        = 0,
+        EG_PA_SC_WINDOW_OFFSET__WINDOW_X_OFFSET_mask         = 0xffff << 0,
+        EG_PA_SC_WINDOW_OFFSET__WINDOW_Y_OFFSET_shift        = 16,
+        EG_PA_SC_WINDOW_OFFSET__WINDOW_Y_OFFSET_mask         = 0xffff << 16,
+    /* SPI_BARYC_CNTL */
+        EG_SPI_BARYC_CNTL__PERSP_CENTROID_ENA_shift          = 4,
+        EG_SPI_BARYC_CNTL__PERSP_CENTROID_ENA_mask           = 0x3    << 4,
+        EG_SPI_BARYC_CNTL__LINEAR_CENTROID_ENA_shift         = 20,
+        EG_SPI_BARYC_CNTL__LINEAR_CENTROID_ENA_mask          = 0x3    << 20,
+    /* DB_SHADER_CONTROL */
+        EG_DB_SHADER_CONTROL__DUAL_EXPORT_ENABLE_bit         = 1 << 9,
+
+    /* DB_Z_INFO */
+        EG_DB_Z_INFO__FORMAT_shift                           = 0,        //2;
+        EG_DB_Z_INFO__FORMAT_mask                            = 0x3,
+                                                                                //2;
+               EG_DB_Z_INFO__ARRAY_MODE_shift                       = 4,        //4;
+        EG_DB_Z_INFO__ARRAY_MODE_mask                        = 0xf << 4,
+               EG_DB_Z_INFO__TILE_SPLIT_shift                       = 8,        //3;
+        EG_DB_Z_INFO__TILE_SPLIT_mask                        = 0x7 << 8,
+                                                                                //1;
+               EG_DB_Z_INFO__NUM_BANKS_shift                        = 12,       //2;
+        EG_DB_Z_INFO__NUM_BANKS_mask                         = 0x3 << 12,
+                                                                                //2;
+               EG_DB_Z_INFO__BANK_WIDTH_shift                       = 16,       //2;
+        EG_DB_Z_INFO__BANK_WIDTH_mask                        = 0x3 << 16,
+                                                                                //2;
+               EG_DB_Z_INFO__BANK_HEIGHT_shift                      = 20,       //2;
+        EG_DB_Z_INFO__BANK_HEIGHT_mask                       = 0x3 << 20,
+        
+        EG_Z_INVALID                                         = 0x00000000,
+        EG_Z_16                                              = 0x00000001,
+        EG_Z_24                                              = 0x00000002,
+        EG_Z_32_FLOAT                                        = 0x00000003,
+        EG_ADDR_SURF_TILE_SPLIT_256B                         = 0x00000002,
+        EG_ADDR_SURF_8_BANK                                  = 0x00000002,
+        EG_ADDR_SURF_BANK_WIDTH_1                            = 0x00000000,
+        EG_ADDR_SURF_BANK_HEIGHT_1                           = 0x00000000,
+    /* DB_STENCIL_INFO */
+        EG_DB_STENCIL_INFO__FORMAT_bit                       = 1,   //1;
+                                                                           //7;
+               EG_DB_STENCIL_INFO__TILE_SPLIT_shift                 = 8,   //3;
+        EG_DB_STENCIL_INFO__TILE_SPLIT_mask                  = 0x7 << 8,
+    
+    /* DB_DEPTH_SIZE */
+        EG_DB_DEPTH_SIZE__PITCH_TILE_MAX_shift               = 0,  // 11;
+        EG_DB_DEPTH_SIZE__PITCH_TILE_MAX_mask                = 0x7ff,
+               EG_DB_DEPTH_SIZE__HEIGHT_TILE_MAX_shift              = 11, // 11;
+        EG_DB_DEPTH_SIZE__HEIGHT_TILE_MAX_mask               = 0x7ff << 11,
+
+    /* DB_COUNT_CONTROL */
+        EG_DB_COUNT_CONTROL__ZPASS_INCREMENT_DISABLE_shift   = 0,  //1
+        EG_DB_COUNT_CONTROL__ZPASS_INCREMENT_DISABLE_bit     = 1,
+        EG_DB_COUNT_CONTROL__PERFECT_ZPASS_COUNTS_shift      = 1,  //1
+        EG_DB_COUNT_CONTROL__PERFECT_ZPASS_COUNTS_bit        = 1 << 1,    
+
+    /* CB_COLOR_CONTROL */
+                                                                      //3;
+               EG_CB_COLOR_CONTROL__DEGAMMA_ENABLE_bit              = 1 << 3,//1;
+               EG_CB_COLOR_CONTROL__MODE_shift                      = 4,     //3;
+        EG_CB_COLOR_CONTROL__MODE_mask                       = 0x7 << 4,
+                                                                             //9;
+               EG_CB_COLOR_CONTROL__ROP3_shift                      = 16,    //8;
+        EG_CB_COLOR_CONTROL__ROP3_mask                       = 0xff << 16,
+        EG_CB_NORMAL                                         = 0x00000001,
+
+    /* CB_COLOR0_INFO */
+        EG_CB_COLOR0_INFO__ENDIAN_shift                      = 0,      //2;
+        EG_CB_COLOR0_INFO__ENDIAN_mask                       = 0x3,
+               EG_CB_COLOR0_INFO__FORMAT_shift                      = 2,      //6;
+        EG_CB_COLOR0_INFO__FORMAT_mask                       = 0x3f << 2,
+               EG_CB_COLOR0_INFO__ARRAY_MODE_shift                  = 8,      //4;
+        EG_CB_COLOR0_INFO__ARRAY_MODE_mask                   = 0xf << 8,
+               EG_CB_COLOR0_INFO__NUMBER_TYPE_shift                 = 12,     //3;
+        EG_CB_COLOR0_INFO__NUMBER_TYPE_mask                  = 0x7 << 12,
+               EG_CB_COLOR0_INFO__COMP_SWAP_shift                   = 15,     //2;
+        EG_CB_COLOR0_INFO__COMP_SWAP_mask                    = 0x3 << 15,
+               EG_CB_COLOR0_INFO__FAST_CLEAR_bit                    = 1 << 17,//1;
+               EG_CB_COLOR0_INFO__COMPRESSION_bit                   = 1 << 18,//1;
+               EG_CB_COLOR0_INFO__BLEND_CLAMP_bit                   = 1 << 19,//1;
+               EG_CB_COLOR0_INFO__BLEND_BYPASS_bit                  = 1 << 20,//1;
+               EG_CB_COLOR0_INFO__SIMPLE_FLOAT_bit                  = 1 << 21,//1;
+               EG_CB_COLOR0_INFO__ROUND_MODE_bit                    = 1 << 22,//1;
+               EG_CB_COLOR0_INFO__TILE_COMPACT_bit                  = 1 << 23,//1;
+               EG_CB_COLOR0_INFO__SOURCE_FORMAT_shift               = 24,     //2;
+        EG_CB_COLOR0_INFO__SOURCE_FORMAT_mask                = 0x3 << 24,
+               EG_CB_COLOR0_INFO__RAT_bit                           = 1 << 26,//1;
+               EG_CB_COLOR0_INFO__RESOURCE_TYPE_shift               = 27,     //3;
+        EG_CB_COLOR0_INFO__RESOURCE_TYPE_mask                = 0x7 << 27,
+
+    /* CB_COLOR0_ATTRIB */
+        EG_CB_COLOR0_ATTRIB__NON_DISP_TILING_ORDER_shift     = 4,
+        EG_CB_COLOR0_ATTRIB__NON_DISP_TILING_ORDER_bit       = 1 << 4,
+
+    /* SPI_CONFIG_CNTL_1 */
+        EG_SPI_CONFIG_CNTL_1__VTX_DONE_DELAY_shift           = 0,
+        EG_SPI_CONFIG_CNTL_1__VTX_DONE_DELAY_mask            = 0xf,
+    /* SQ_MS_FIFO_SIZES */
+        EG_SQ_MS_FIFO_SIZES__CACHE_FIFO_SIZE_shift           = 0,
+        EG_SQ_MS_FIFO_SIZES__CACHE_FIFO_SIZE_mask            = 0xff,
+        EG_SQ_MS_FIFO_SIZES__FETCH_FIFO_HIWATER_shift        = 8,
+        EG_SQ_MS_FIFO_SIZES__FETCH_FIFO_HIWATER_mask         = 0x1f << 8,
+        EG_SQ_MS_FIFO_SIZES__DONE_FIFO_HIWATER_shift         = 16,
+        EG_SQ_MS_FIFO_SIZES__DONE_FIFO_HIWATER_mask          = 0xff << 16,
+        EG_SQ_MS_FIFO_SIZES__ALU_UPDATE_FIFO_HIWATER_shift   = 24,
+        EG_SQ_MS_FIFO_SIZES__ALU_UPDATE_FIFO_HIWATER_mask    = 0x1f << 24,
+    /* SQ_CONFIG */
+        EG_SQ_CONFIG__VC_ENABLE_bit                          = 1,
+        EG_SQ_CONFIG__EXPORT_SRC_C_bit                       = 1 << 1,
+        EG_SQ_CONFIG__PS_PRIO_shift                          = 24,
+        EG_SQ_CONFIG__PS_PRIO_mask                           = 0x3 << 24,
+        EG_SQ_CONFIG__VS_PRIO_shift                          = 26,
+        EG_SQ_CONFIG__VS_PRIO_mask                           = 0x3 << 26,
+        EG_SQ_CONFIG__GS_PRIO_shift                          = 28,
+        EG_SQ_CONFIG__GS_PRIO_mask                           = 0x3 << 28,
+        EG_SQ_CONFIG__ES_PRIO_shift                          = 30,
+        EG_SQ_CONFIG__ES_PRIO_mask                           = 0x3 << 30,
+    /* PA_SC_FORCE_EOV_MAX_CNTS */
+        EG_PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_CLK_CNT_shift = 0,
+        EG_PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_CLK_CNT_mask  = 0x3fff,
+        EG_PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_REZ_CNT_shift = 16,
+        EG_PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_REZ_CNT_mask  = 0x3fff << 16,
+    /* VGT_CACHE_INVALIDATION */
+        EG_VGT_CACHE_INVALIDATION__CACHE_INVALIDATION_shift      = 0,
+        EG_VGT_CACHE_INVALIDATION__CACHE_INVALIDATION_mask       = 0x3, 
+    /* CB_COLOR0_PITCH */
+        EG_CB_COLOR0_PITCH__TILE_MAX_shift                       = 0,
+        EG_CB_COLOR0_PITCH__TILE_MAX_mask                        = 0x7ff,
+    /* CB_COLOR0_SLICE */
+        EG_CB_COLOR0_SLICE__TILE_MAX_shift                       = 0,
+        EG_CB_COLOR0_SLICE__TILE_MAX_mask                        = 0x3fffff,    
+    /* SQ_VTX_CONSTANT_WORD3_0 */
+        EG_SQ_VTX_CONSTANT_WORD3_0__UNCACHED_shift  = 2,
+        EG_SQ_VTX_CONSTANT_WORD3_0__UNCACHED_bit    = 1 << 2,
+
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_X_shift = 3, 
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_X_mask  = 0x7 << 3,
+     
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_Y_shift = 6, 
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_Y_mask  = 0x7 << 6,
+     
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_Z_shift = 9, 
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_Z_mask  = 0x7 << 9,
+     
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_W_shift = 12, 
+        EG_SQ_VTX_CONSTANT_WORD3_0__DST_SEL_W_mask  = 0x7 << 12,
+    /* SQ_VTX_CONSTANT_WORD4_0 */
+        EG_SQ_VTX_CONSTANT_WORD4_0__NUM_ELEMENTS_shift = 0,
+        EG_SQ_VTX_CONSTANT_WORD4_0__NUM_ELEMENTS_mask  = 0xFFFFFFFF,
+    /* SQ_VTX_CONSTANT_WORD7_0 */
+        EG_SQ_VTX_CONSTANT_WORD7_0__TYPE_shift         = 30,
+        EG_SQ_VTX_CONSTANT_WORD7_0__TYPE_mask          = 0x3 << 30,
+    /* SQ_TEX_SAMPLER_WORD0_0 */
+        EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_shift         = 0,  // 3;
+        EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_mask          = 0x7,
+               EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_Y_shift         = 3,  // 3;
+        EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_Y_mask          = 0x7 << 3,
+               EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_Z_shift         = 6,  // 3;
+        EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_Z_mask          = 0x7 << 6,
+               EG_SQ_TEX_SAMPLER_WORD0_0__XY_MAG_FILTER_shift   = 9,  // 2;
+        EG_SQ_TEX_SAMPLER_WORD0_0__XY_MAG_FILTER_mask    = 0x3 << 9,
+               EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_shift   = 11, // 2;
+        EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_mask    = 0x3 << 11,
+               EG_SQ_TEX_SAMPLER_WORD0_0__Z_FILTER_shift        = 13, // 2;
+        EG_SQ_TEX_SAMPLER_WORD0_0__Z_FILTER_mask         = 0x3 << 13,
+               EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_shift      = 15, // 2;
+        EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_mask       = 0x3 << 15,
+               EG_SQ_TEX_SAMPLER_WORD0_0__MAX_ANISO_RATIO_shift = 17, // 3;
+        EG_SQ_TEX_SAMPLER_WORD0_0__MAX_ANISO_RATIO_mask  = 0x7 << 17,
+               EG_SQ_TEX_SAMPLER_WORD0_0__BORDER_COLOR_TYPE_shift = 20,//2;
+        EG_SQ_TEX_SAMPLER_WORD0_0__BORDER_COLOR_TYPE_mask  = 0x3 << 20,
+               EG_SQ_TEX_SAMPLER_WORD0_0__DCF_shift             = 22, // 3;
+        EG_SQ_TEX_SAMPLER_WORD0_0__DCF_mask              = 0x7 << 22,
+               EG_SQ_TEX_SAMPLER_WORD0_0__CHROMA_KEY_shift      = 25, // 2;
+        EG_SQ_TEX_SAMPLER_WORD0_0__CHROMA_KEY_mask       = 0x3 << 25,
+               EG_SQ_TEX_SAMPLER_WORD0_0__ANISO_THRESHOLD_shift = 27, // 3;
+        EG_SQ_TEX_SAMPLER_WORD0_0__ANISO_THRESHOLD_mask  = 0x7 << 27,
+               EG_SQ_TEX_SAMPLER_WORD0_0__Reserved_shift        = 30, // 2         
+        EG_SQ_TEX_SAMPLER_WORD0_0__Reserved_mask         = 0x3 << 30,
+    /* SQ_TEX_SAMPLER_WORD1_0 */
+        EG_SQ_TEX_SAMPLER_WORD1_0__MIN_LOD_shift         = 0, // 12;
+        EG_SQ_TEX_SAMPLER_WORD1_0__MIN_LOD_mask          = 0xfff,
+               EG_SQ_TEX_SAMPLER_WORD1_0__MAX_LOD_shift         = 12,// 12;
+        EG_SQ_TEX_SAMPLER_WORD1_0__MAX_LOD_mask          = 0xfff << 12,
+    /* SQ_TEX_SAMPLER_WORD2_0 */
+        EG_SQ_TEX_SAMPLER_WORD2_0__LOD_BIAS_shift          = 0, //14;
+        EG_SQ_TEX_SAMPLER_WORD2_0__LOD_BIAS_mask           = 0x3fff,
+               EG_SQ_TEX_SAMPLER_WORD2_0__LOD_BIAS_SEC_shift      = 14,//6;
+        EG_SQ_TEX_SAMPLER_WORD2_0__LOD_BIAS_SEC_mask       = 0x3f << 14,
+               EG_SQ_TEX_SAMPLER_WORD2_0__MC_COORD_TRUNCATE_shift = 20,//1;
+        EG_SQ_TEX_SAMPLER_WORD2_0__MC_COORD_TRUNCATE_bit   = 1 << 20,
+               EG_SQ_TEX_SAMPLER_WORD2_0__FORCE_DEGAMMA_shift     = 21,//1;
+        EG_SQ_TEX_SAMPLER_WORD2_0__FORCE_DEGAMMA_bit       = 1 << 21,
+               EG_SQ_TEX_SAMPLER_WORD2_0__ANISO_BIAS_shift        = 22,//6;
+        EG_SQ_TEX_SAMPLER_WORD2_0__ANISO_BIAS_mask         = 0x3f << 22,
+               EG_SQ_TEX_SAMPLER_WORD2_0__TRUNCATE_COORD_shift    = 28,//1;
+        EG_SQ_TEX_SAMPLER_WORD2_0__TRUNCATE_COORD_bit      = 1 << 28,
+               EG_SQ_TEX_SAMPLER_WORD2_0__DISABLE_CUBE_WRAP_shift = 29,//1;
+        EG_SQ_TEX_SAMPLER_WORD2_0__DISABLE_CUBE_WRAP_bit   = 1 << 29,
+               EG_SQ_TEX_SAMPLER_WORD2_0__Reserved_shift          = 30,//1;
+        EG_SQ_TEX_SAMPLER_WORD2_0__Reserved_bit            = 1 << 30,
+               EG_SQ_TEX_SAMPLER_WORD2_0__TYPE_shift              = 31,//1;
+        EG_SQ_TEX_SAMPLER_WORD2_0__TYPE_bit                = 1 << 31,
+    /* SQ_TEX_RESOURCE_WORD0_0 */
+        EG_SQ_TEX_RESOURCE_WORD0_0__DIM_shift              = 0, // 3;
+        EG_SQ_TEX_RESOURCE_WORD0_0__DIM_mask               = 0x7,
+               EG_SQ_TEX_RESOURCE_WORD0_0__ISET_shift             = 3, // 1;
+        EG_SQ_TEX_RESOURCE_WORD0_0__ISET_bit               = 1 << 3,
+               EG_SQ_TEX_RESOURCE_WORD0_0__Reserve_shift          = 4, // 1;
+        EG_SQ_TEX_RESOURCE_WORD0_0__Reserve_bit            = 1 << 4,
+               EG_SQ_TEX_RESOURCE_WORD0_0__NDTO_shift             = 5, // 1;
+        EG_SQ_TEX_RESOURCE_WORD0_0__NDTO_bit               = 1 << 5,
+               EG_SQ_TEX_RESOURCE_WORD0_0__PITCH_shift            = 6, // 12;
+        EG_SQ_TEX_RESOURCE_WORD0_0__PITCH_mask             = 0xfff << 6,
+               EG_SQ_TEX_RESOURCE_WORD0_0__TEX_WIDTH_shift        = 18,// 14;
+        EG_SQ_TEX_RESOURCE_WORD0_0__TEX_WIDTH_mask         = 0x3fff << 18,
+    /* SQ_TEX_RESOURCE_WORD1_0 */
+        EG_SQ_TEX_RESOURCE_WORD1_0__TEX_HEIGHT_shift       = 0, // 14;
+        EG_SQ_TEX_RESOURCE_WORD1_0__TEX_HEIGHT_mask        = 0x3fff,
+               EG_SQ_TEX_RESOURCE_WORD1_0__TEX_DEPTH_shift        = 14,// 13;
+        EG_SQ_TEX_RESOURCE_WORD1_0__TEX_DEPTH_mask         = 0x1fff << 14,
+               EG_SQ_TEX_RESOURCE_WORD1_0__Reserved_shift         = 27,// 1;
+        EG_SQ_TEX_RESOURCE_WORD1_0__Reserved_bit           = 1 << 27,
+               EG_SQ_TEX_RESOURCE_WORD1_0__ARRAY_MODE_shift       = 28,// 4;
+        EG_SQ_TEX_RESOURCE_WORD1_0__ARRAY_MODE_mask        = 0xf << 28,
+    /* SQ_TEX_RESOURCE_WORD6_0 */
+        EG_SQ_TEX_RESOURCE_WORD6_0__MAX_ANISO_RATIO_shift  = 0, //: 3;
+        EG_SQ_TEX_RESOURCE_WORD6_0__MAX_ANISO_RATIO_mask   = 0x7,              
+               EG_SQ_TEX_RESOURCE_WORD6_0__INTERLACED_shift       = 6, //1;
+        EG_SQ_TEX_RESOURCE_WORD6_0__INTERLACED_bit         = 1 << 6,           
+               EG_SQ_TEX_RESOURCE_WORD6_0__MIN_LOD_shift          = 8, //12;
+        EG_SQ_TEX_RESOURCE_WORD6_0__MIN_LOD_mask           = 0xfff << 8,               
+               EG_SQ_TEX_RESOURCE_WORD6_0__TILE_SPLIT_shift       = 29,// 3;
+        EG_SQ_TEX_RESOURCE_WORD6_0__TILE_SPLIT_mask        = 0x7 << 29,
+    /* SQ_TEX_RESOURCE_WORD7_0 */
+        EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift            = 0, // 6;
+        EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask             = 0x3f,
+               EG_SQ_TEX_RESOURCE_WORD7_0__MACRO_TILE_ASPECT_shift      = 6, // 2;
+        EG_SQ_TEX_RESOURCE_WORD7_0__MACRO_TILE_ASPECT_mask       = 0x3 << 6,
+               EG_SQ_TEX_RESOURCE_WORD7_0__BANK_WIDTH_shift             = 8, // 2;
+        EG_SQ_TEX_RESOURCE_WORD7_0__BANK_WIDTH_mask              = 0x3 << 8,
+               EG_SQ_TEX_RESOURCE_WORD7_0__BANK_HEIGHT_shift            = 10,// 2;
+        EG_SQ_TEX_RESOURCE_WORD7_0__BANK_HEIGHT_mask             = 0x3 << 10,          
+               EG_SQ_TEX_RESOURCE_WORD7_0__DEPTH_SAMPLE_ORDER_shift     = 15,// 1;
+        EG_SQ_TEX_RESOURCE_WORD7_0__DEPTH_SAMPLE_ORDER_bit       = 1 << 15,
+               EG_SQ_TEX_RESOURCE_WORD7_0__NUM_BANKS_shift              = 16,// 2;
+        EG_SQ_TEX_RESOURCE_WORD7_0__NUM_BANKS_mask               = 0x3 << 16,          
+               EG_SQ_TEX_RESOURCE_WORD7_0__TYPE_shift                   = 30,// 2;
+        EG_SQ_TEX_RESOURCE_WORD7_0__TYPE_mask                    = 0x3 << 30,
+};
+
+/*  */
+
+#define EG_SQ_FETCH_RESOURCE_COUNT        0x00000400
+#define EG_SQ_TEX_SAMPLER_COUNT           0x0000006c
+#define EG_SQ_LOOP_CONST_COUNT            0x000000c0
+
+#define EG_SET_RESOURCE_OFFSET  0x30000
+#define EG_SET_RESOURCE_END     0x30400 //r600 := offset + 0x4000
+
+#define EG_SET_LOOP_CONST_OFFSET 0x3A200
+#define EG_SET_LOOP_CONST_END    0x3A26C //r600 := offset + 0x180
+
+
+#define EG_SQ_FETCH_RESOURCE_VS_OFFSET 0x000000b0
+#define EG_FETCH_RESOURCE_STRIDE       8
+
+#define EG_SET_BOOL_CONST_OFFSET       0x3A500
+#define EG_SET_BOOL_CONST_END          0x3A506
+
+
+#endif //_EVERGREEN_DIFF_H_
diff --git a/src/mesa/drivers/dri/r600/evergreen_fragprog.c b/src/mesa/drivers/dri/r600/evergreen_fragprog.c
new file mode 100644 (file)
index 0000000..b53ff42
--- /dev/null
@@ -0,0 +1,817 @@
+/*
+ * Copyright (C) 2008-2009  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ *   CooperYuan <cooper.yuan@amd.com>, <cooperyuan@gmail.com>
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "main/imports.h"
+
+#include "program/prog_parameter.h"
+#include "program/prog_statevars.h"
+#include "program/program.h"
+
+#include "r600_context.h"
+#include "r600_cmdbuf.h"
+#include "r600_emit.h"
+
+#include "evergreen_vertprog.h"
+#include "evergreen_fragprog.h"
+
+void evergreen_insert_wpos_code(GLcontext *ctx, struct gl_fragment_program *fprog)
+{
+    static const gl_state_index winstate[STATE_LENGTH]
+         = { STATE_INTERNAL, STATE_FB_SIZE, 0, 0, 0};
+    struct prog_instruction *newInst, *inst;
+    GLint  win_size;  /* state reference */
+    GLuint wpos_temp; /* temp register */
+    int i, j;
+
+    /* PARAM win_size = STATE_FB_SIZE */
+    win_size = _mesa_add_state_reference(fprog->Base.Parameters, winstate);
+
+    wpos_temp = fprog->Base.NumTemporaries++;
+
+    /* scan program where WPOS is used and replace with wpos_temp */
+    inst = fprog->Base.Instructions;
+    for (i = 0; i < fprog->Base.NumInstructions; i++) {
+        for (j=0; j < 3; j++) {
+            if(inst->SrcReg[j].File == PROGRAM_INPUT && 
+               inst->SrcReg[j].Index == FRAG_ATTRIB_WPOS) {
+                inst->SrcReg[j].File = PROGRAM_TEMPORARY;
+                inst->SrcReg[j].Index = wpos_temp;
+            }
+        }
+        inst++;
+    }
+
+    _mesa_insert_instructions(&(fprog->Base), 0, 1);
+
+    newInst = fprog->Base.Instructions;
+    /* invert wpos.y
+     * wpos_temp.xyzw = wpos.x-yzw + winsize.0y00 */
+    newInst[0].Opcode = OPCODE_ADD;
+    newInst[0].DstReg.File = PROGRAM_TEMPORARY;
+    newInst[0].DstReg.Index = wpos_temp;
+    newInst[0].DstReg.WriteMask = WRITEMASK_XYZW;
+
+    newInst[0].SrcReg[0].File = PROGRAM_INPUT;
+    newInst[0].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
+    newInst[0].SrcReg[0].Swizzle = SWIZZLE_XYZW;
+    newInst[0].SrcReg[0].Negate = NEGATE_Y;
+
+    newInst[0].SrcReg[1].File = PROGRAM_STATE_VAR;
+    newInst[0].SrcReg[1].Index = win_size;
+    newInst[0].SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ZERO);
+
+}
+
+//TODO : Validate FP input with VP output.
+void evergreen_Map_Fragment_Program(r700_AssemblerBase         *pAsm,
+                                                 struct gl_fragment_program *mesa_fp,
+                          GLcontext *ctx) 
+{
+       unsigned int unBit;
+    unsigned int i;
+    GLuint       ui;
+
+    /* match fp inputs with vp exports. */
+    struct evergreen_vertex_program_cont *vpc =
+                      (struct evergreen_vertex_program_cont *)ctx->VertexProgram._Current;
+    GLbitfield OutputsWritten = vpc->mesa_program.Base.OutputsWritten;
+    
+       pAsm->number_used_registers = 0;
+
+//Input mapping : mesa_fp->Base.InputsRead set the flag, set in 
+       //The flags parsed in parse_attrib_binding. FRAG_ATTRIB_COLx, FRAG_ATTRIB_TEXx, ...
+       //MUST match order in Map_Vertex_Output
+       unBit = 1 << FRAG_ATTRIB_WPOS;
+       if(mesa_fp->Base.InputsRead & unBit)
+       {
+               pAsm->uiFP_AttributeMap[FRAG_ATTRIB_WPOS] = pAsm->number_used_registers++;
+       }
+
+    unBit = 1 << VERT_RESULT_COL0;
+       if(OutputsWritten & unBit)
+       {
+               pAsm->uiFP_AttributeMap[FRAG_ATTRIB_COL0] = pAsm->number_used_registers++;
+       }
+
+       unBit = 1 << VERT_RESULT_COL1;
+       if(OutputsWritten & unBit)
+       {
+               pAsm->uiFP_AttributeMap[FRAG_ATTRIB_COL1] = pAsm->number_used_registers++;
+       }
+
+    unBit = 1 << VERT_RESULT_FOGC;
+    if(OutputsWritten & unBit)
+    {
+        pAsm->uiFP_AttributeMap[FRAG_ATTRIB_FOGC] = pAsm->number_used_registers++;
+    }
+
+       for(i=0; i<8; i++)
+       {
+               unBit = 1 << (VERT_RESULT_TEX0 + i);
+               if(OutputsWritten & unBit)
+               {
+                       pAsm->uiFP_AttributeMap[FRAG_ATTRIB_TEX0 + i] = pAsm->number_used_registers++;
+               }
+       }
+/* order has been taken care of */ 
+#if 1
+    for(i=VERT_RESULT_VAR0; i<VERT_RESULT_MAX; i++)
+       {
+        unBit = 1 << i;
+        if(OutputsWritten & unBit)
+               {
+            pAsm->uiFP_AttributeMap[i-VERT_RESULT_VAR0+FRAG_ATTRIB_VAR0] = pAsm->number_used_registers++;
+        }
+    }
+#else
+    if( (mesa_fp->Base.InputsRead >> FRAG_ATTRIB_VAR0) > 0 )
+    {
+           struct evergreen_vertex_program_cont *vpc =
+                      (struct evergreen_vertex_program_cont *)ctx->VertexProgram._Current;
+        struct gl_program_parameter_list * VsVarying = vpc->mesa_program.Base.Varying;
+        struct gl_program_parameter_list * PsVarying = mesa_fp->Base.Varying;
+        struct gl_program_parameter      * pVsParam;
+        struct gl_program_parameter      * pPsParam;
+        GLuint j, k;
+        GLuint unMaxVarying = 0;
+
+        for(i=0; i<VsVarying->NumParameters; i++)
+        {
+            pAsm->uiFP_AttributeMap[i + FRAG_ATTRIB_VAR0] = 0;
+        }
+
+        for(i=FRAG_ATTRIB_VAR0; i<FRAG_ATTRIB_MAX; i++)
+           {
+            unBit = 1 << i;
+            if(mesa_fp->Base.InputsRead & unBit)
+                   {
+                j = i - FRAG_ATTRIB_VAR0;
+                pPsParam = PsVarying->Parameters + j;
+
+                for(k=0; k<VsVarying->NumParameters; k++)
+                {                                      
+                    pVsParam = VsVarying->Parameters + k;
+
+                               if( strcmp(pPsParam->Name, pVsParam->Name) == 0)
+                    {
+                        pAsm->uiFP_AttributeMap[i] = pAsm->number_used_registers + k;                  
+                        if(k > unMaxVarying)
+                        {
+                            unMaxVarying = k;
+                        }
+                        break;
+                    }
+                }
+                   }
+        }
+
+        pAsm->number_used_registers += unMaxVarying + 1;
+    }
+#endif
+    unBit = 1 << FRAG_ATTRIB_FACE;
+    if(mesa_fp->Base.InputsRead & unBit)
+    {
+        pAsm->uiFP_AttributeMap[FRAG_ATTRIB_FACE] = pAsm->number_used_registers++;
+    }
+
+    unBit = 1 << FRAG_ATTRIB_PNTC;
+    if(mesa_fp->Base.InputsRead & unBit)
+    {
+        pAsm->uiFP_AttributeMap[FRAG_ATTRIB_PNTC] = pAsm->number_used_registers++;
+    }
+
+    pAsm->uIIns = pAsm->number_used_registers;
+
+/* Map temporary registers (GPRs) */
+    pAsm->starting_temp_register_number = pAsm->number_used_registers;
+
+    if(mesa_fp->Base.NumNativeTemporaries >= mesa_fp->Base.NumTemporaries)
+    {
+           pAsm->number_used_registers += mesa_fp->Base.NumNativeTemporaries;
+    }
+    else
+    {
+        pAsm->number_used_registers += mesa_fp->Base.NumTemporaries;
+    }
+
+/* Output mapping */
+       pAsm->number_of_exports = 0;
+       pAsm->number_of_colorandz_exports = 0; /* don't include stencil and mask out. */
+       pAsm->starting_export_register_number = pAsm->number_used_registers;
+       unBit = 1 << FRAG_RESULT_COLOR;
+       if(mesa_fp->Base.OutputsWritten & unBit)
+       {
+               pAsm->uiFP_OutputMap[FRAG_RESULT_COLOR] = pAsm->number_used_registers++;
+               pAsm->number_of_exports++;
+               pAsm->number_of_colorandz_exports++;
+       }
+       unBit = 1 << FRAG_RESULT_DEPTH;
+       if(mesa_fp->Base.OutputsWritten & unBit)
+       {
+        pAsm->depth_export_register_number = pAsm->number_used_registers;
+               pAsm->uiFP_OutputMap[FRAG_RESULT_DEPTH] = pAsm->number_used_registers++;
+               pAsm->number_of_exports++;
+               pAsm->number_of_colorandz_exports++;
+               pAsm->pR700Shader->depthIsExported = 1;
+       }
+
+    pAsm->pucOutMask = (unsigned char*) MALLOC(pAsm->number_of_exports);
+    for(ui=0; ui<pAsm->number_of_exports; ui++)
+    {
+        pAsm->pucOutMask[ui] = 0x0;
+    }
+
+    pAsm->flag_reg_index = pAsm->number_used_registers++;
+
+    pAsm->uFirstHelpReg = pAsm->number_used_registers;
+}
+
+GLboolean evergreen_Find_Instruction_Dependencies_fp(struct evergreen_fragment_program *fp,
+                                                               struct gl_fragment_program   *mesa_fp)
+{
+    GLuint i, j;
+    GLint * puiTEMPwrites;
+    GLint * puiTEMPreads;
+    struct prog_instruction * pILInst;
+    InstDeps         *pInstDeps;
+    struct prog_instruction * texcoord_DepInst;
+    GLint              nDepInstID;
+
+    puiTEMPwrites = (GLint*) MALLOC(sizeof(GLuint)*mesa_fp->Base.NumTemporaries);
+    puiTEMPreads = (GLint*) MALLOC(sizeof(GLuint)*mesa_fp->Base.NumTemporaries);
+
+    for(i=0; i<mesa_fp->Base.NumTemporaries; i++)
+    {
+        puiTEMPwrites[i] = -1;
+        puiTEMPreads[i] = -1;
+    }
+
+    pInstDeps = (InstDeps*)MALLOC(sizeof(InstDeps)*mesa_fp->Base.NumInstructions);
+
+    for(i=0; i<mesa_fp->Base.NumInstructions; i++)
+    {
+        pInstDeps[i].nDstDep = -1;
+        pILInst = &(mesa_fp->Base.Instructions[i]);
+
+        //Dst
+        if(pILInst->DstReg.File == PROGRAM_TEMPORARY)
+        {
+            //Set lastwrite for the temp
+            puiTEMPwrites[pILInst->DstReg.Index] = i;
+        }
+
+        //Src
+        for(j=0; j<3; j++)
+        {
+            if(pILInst->SrcReg[j].File == PROGRAM_TEMPORARY)
+            {
+                //Set dep.
+                pInstDeps[i].nSrcDeps[j] = puiTEMPwrites[pILInst->SrcReg[j].Index];
+                //Set first read
+                if(puiTEMPreads[pILInst->SrcReg[j].Index] < 0 )
+                {
+                    puiTEMPreads[pILInst->SrcReg[j].Index] = i;
+                }
+            }
+            else
+            {
+                pInstDeps[i].nSrcDeps[j] = -1;
+            }
+        }
+    }
+
+    fp->r700AsmCode.pInstDeps = pInstDeps;
+
+    //Find dep for tex inst    
+    for(i=0; i<mesa_fp->Base.NumInstructions; i++)
+    {
+        pILInst = &(mesa_fp->Base.Instructions[i]);
+
+        if(GL_TRUE == IsTex(pILInst->Opcode))
+        {   //src0 is the tex coord register, src1 is texunit, src2 is textype
+            nDepInstID = pInstDeps[i].nSrcDeps[0];
+            if(nDepInstID >= 0)
+            {
+                texcoord_DepInst = &(mesa_fp->Base.Instructions[nDepInstID]);
+                if(GL_TRUE == IsAlu(texcoord_DepInst->Opcode) )
+                {
+                    pInstDeps[nDepInstID].nDstDep = i;
+                    pInstDeps[i].nDstDep = i;
+                }
+                else if(GL_TRUE == IsTex(texcoord_DepInst->Opcode) )
+                {
+                    pInstDeps[i].nDstDep = i;
+                }
+                else
+                {   //... other deps?
+                }
+            }
+            // make sure that we dont overwrite src used earlier
+            nDepInstID = puiTEMPreads[pILInst->DstReg.Index];
+            if(nDepInstID < i)
+            {
+                pInstDeps[i].nDstDep = puiTEMPreads[pILInst->DstReg.Index];
+                texcoord_DepInst = &(mesa_fp->Base.Instructions[nDepInstID]);
+                if(GL_TRUE == IsAlu(texcoord_DepInst->Opcode) )
+                {
+                    pInstDeps[nDepInstID].nDstDep = i;
+                }
+            }
+
+        }
+       }
+
+    FREE(puiTEMPwrites);
+    FREE(puiTEMPreads);
+
+    return GL_TRUE;
+}
+
+GLboolean evergreenTranslateFragmentShader(struct evergreen_fragment_program *fp,
+                                                            struct gl_fragment_program   *mesa_fp,
+                                 GLcontext *ctx) 
+{
+       GLuint    number_of_colors_exported;
+       GLboolean z_enabled = GL_FALSE;
+       GLuint    unBit, shadow_unit;
+       int i;
+       struct prog_instruction *inst;
+       gl_state_index shadow_ambient[STATE_LENGTH]
+           = { STATE_INTERNAL, STATE_SHADOW_AMBIENT, 0, 0, 0};
+
+    //Init_Program
+       Init_r700_AssemblerBase( SPT_FP, &(fp->r700AsmCode), &(fp->r700Shader) );
+        
+    fp->constbo0 = NULL;
+    fp->r700AsmCode.bUseMemConstant = GL_TRUE;  
+    fp->r700AsmCode.unAsic = 8;
+
+    if(mesa_fp->Base.InputsRead & FRAG_BIT_WPOS)
+    {
+        evergreen_insert_wpos_code(ctx, mesa_fp);
+    }
+
+    /* add/map  consts for ARB_shadow_ambient */
+    if(mesa_fp->Base.ShadowSamplers)
+    {
+        inst = mesa_fp->Base.Instructions;
+        for (i = 0; i < mesa_fp->Base.NumInstructions; i++)
+        {
+            if(inst->TexShadow == 1)
+            {
+                shadow_unit = inst->TexSrcUnit;
+                shadow_ambient[2] = shadow_unit;
+                fp->r700AsmCode.shadow_regs[shadow_unit] = 
+                    _mesa_add_state_reference(mesa_fp->Base.Parameters, shadow_ambient);
+            }
+            inst++;
+        }
+    }
+
+    evergreen_Map_Fragment_Program(&(fp->r700AsmCode), mesa_fp, ctx); 
+
+    if( GL_FALSE == evergreen_Find_Instruction_Dependencies_fp(fp, mesa_fp) )
+       {
+               return GL_FALSE;
+    }
+
+    InitShaderProgram(&(fp->r700AsmCode));
+       
+    for(i=0; i < MAX_SAMPLERS; i++)
+    {
+         fp->r700AsmCode.SamplerUnits[i] = fp->mesa_program.Base.SamplerUnits[i];
+    }
+
+    fp->r700AsmCode.unCurNumILInsts = mesa_fp->Base.NumInstructions;
+
+       if( GL_FALSE == AssembleInstr(0,
+                                  0,
+                                  mesa_fp->Base.NumInstructions,
+                                  &(mesa_fp->Base.Instructions[0]), 
+                                  &(fp->r700AsmCode)) )
+       {
+               return GL_FALSE;
+       }
+
+    if(GL_FALSE == Process_Fragment_Exports(&(fp->r700AsmCode), mesa_fp->Base.OutputsWritten) )
+    {
+        return GL_FALSE;
+    }
+
+    if( GL_FALSE == RelocProgram(&(fp->r700AsmCode), &(mesa_fp->Base)) )
+    {
+        return GL_FALSE;
+    }
+
+    fp->r700Shader.nRegs = (fp->r700AsmCode.number_used_registers == 0) ? 0 
+                         : (fp->r700AsmCode.number_used_registers - 1);
+
+       fp->r700Shader.nParamExports = fp->r700AsmCode.number_of_exports;
+
+       number_of_colors_exported = fp->r700AsmCode.number_of_colorandz_exports;
+
+       unBit = 1 << FRAG_RESULT_DEPTH;
+       if(mesa_fp->Base.OutputsWritten & unBit)
+       {
+               z_enabled = GL_TRUE;
+               number_of_colors_exported--;
+       }
+
+       /* illegal to set this to 0 */
+       if(number_of_colors_exported || z_enabled)
+       {
+           fp->r700Shader.exportMode = number_of_colors_exported << 1 | z_enabled;
+       }
+       else
+       {
+           fp->r700Shader.exportMode = (1 << 1);
+       }
+
+    fp->translated = GL_TRUE;
+
+       return GL_TRUE;
+}
+
+void evergreenSelectFragmentShader(GLcontext *ctx)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    struct evergreen_fragment_program *fp = (struct evergreen_fragment_program *)
+           (ctx->FragmentProgram._Current);
+    if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770)
+    {
+           fp->r700AsmCode.bR6xx = 1;
+    }
+
+    if (GL_FALSE == fp->translated)
+           evergreenTranslateFragmentShader(fp, &(fp->mesa_program), ctx); 
+}
+
+void * evergreenGetActiveFpShaderBo(GLcontext * ctx)
+{
+    struct evergreen_fragment_program *fp = (struct evergreen_fragment_program *)
+                                          (ctx->FragmentProgram._Current);
+
+    return fp->shaderbo;
+}
+
+void * evergreenGetActiveFpShaderConstBo(GLcontext * ctx)
+{
+    struct evergreen_fragment_program *fp = (struct evergreen_fragment_program *)
+                                          (ctx->FragmentProgram._Current);
+
+    return fp->constbo0;
+}
+
+GLboolean evergreenSetupFragmentProgram(GLcontext * ctx)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+    struct evergreen_fragment_program *fp = (struct evergreen_fragment_program *)
+                                          (ctx->FragmentProgram._Current);
+    r700_AssemblerBase         *pAsm = &(fp->r700AsmCode);
+    struct gl_fragment_program *mesa_fp = &(fp->mesa_program);    
+    unsigned int ui, i;
+    unsigned int unNumOfReg;
+    unsigned int unBit;
+    GLuint exportCount;
+    GLboolean point_sprite = GL_FALSE;
+
+    if(GL_FALSE == fp->loaded)
+    {
+           if(fp->r700Shader.bNeedsAssembly == GL_TRUE)
+           {
+                   Assemble( &(fp->r700Shader) );
+           }
+
+        r600EmitShader(ctx,
+                       &(fp->shaderbo),
+                       (GLvoid *)(fp->r700Shader.pProgram),
+                       fp->r700Shader.uShaderBinaryDWORDSize,
+                       "FS");
+        
+        fp->loaded = GL_TRUE;
+    }
+
+    /* TODO : enable this after MemUse fixed *=
+    (context->chipobj.MemUse)(context, fp->shadercode.buf->id);
+    */
+
+    EVERGREEN_STATECHANGE(context, sq);
+
+    evergreen->SQ_PGM_RESOURCES_PS.u32All = 0;
+    SETbit(evergreen->SQ_PGM_RESOURCES_PS.u32All, PGM_RESOURCES__PRIME_CACHE_ON_DRAW_bit);
+
+    evergreen->ps.SQ_ALU_CONST_CACHE_PS_0.u32All = 0; 
+    evergreen->ps.SQ_PGM_START_PS.u32All = 0;         
+
+    EVERGREEN_STATECHANGE(context, spi);
+
+    unNumOfReg = fp->r700Shader.nRegs + 1;
+
+    ui = (evergreen->SPI_PS_IN_CONTROL_0.u32All & NUM_INTERP_mask) / (1 << NUM_INTERP_shift);
+
+    /* PS uses fragment.position */
+    if (mesa_fp->Base.InputsRead & (1 << FRAG_ATTRIB_WPOS))
+    {
+        ui += 1;
+        SETfield(evergreen->SPI_PS_IN_CONTROL_0.u32All, ui, NUM_INTERP_shift, NUM_INTERP_mask);
+        SETfield(evergreen->SPI_PS_IN_CONTROL_0.u32All, CENTERS_ONLY, BARYC_SAMPLE_CNTL_shift, BARYC_SAMPLE_CNTL_mask);
+        SETbit(evergreen->SPI_PS_IN_CONTROL_0.u32All, POSITION_ENA_bit);
+        SETbit(evergreen->SPI_INPUT_Z.u32All, PROVIDE_Z_TO_SPI_bit);
+    }
+    else
+    {
+        CLEARbit(evergreen->SPI_PS_IN_CONTROL_0.u32All, POSITION_ENA_bit);
+        CLEARbit(evergreen->SPI_INPUT_Z.u32All, PROVIDE_Z_TO_SPI_bit);
+    }
+
+    if (mesa_fp->Base.InputsRead & (1 << FRAG_ATTRIB_FACE))
+    {
+        ui += 1;
+        SETfield(evergreen->SPI_PS_IN_CONTROL_0.u32All, ui, NUM_INTERP_shift, NUM_INTERP_mask);
+        SETbit(evergreen->SPI_PS_IN_CONTROL_1.u32All, FRONT_FACE_ENA_bit);
+        SETbit(evergreen->SPI_PS_IN_CONTROL_1.u32All, FRONT_FACE_ALL_BITS_bit);
+        SETfield(evergreen->SPI_PS_IN_CONTROL_1.u32All, pAsm->uiFP_AttributeMap[FRAG_ATTRIB_FACE], FRONT_FACE_ADDR_shift, FRONT_FACE_ADDR_mask);
+    }
+    else
+    {
+        CLEARbit(evergreen->SPI_PS_IN_CONTROL_1.u32All, FRONT_FACE_ENA_bit);
+    }
+
+    /* see if we need any point_sprite replacements */
+    for (i = VERT_RESULT_TEX0; i<= VERT_RESULT_TEX7; i++)
+    {
+        if(ctx->Point.CoordReplace[i - VERT_RESULT_TEX0] == GL_TRUE)
+            point_sprite = GL_TRUE;
+    }
+
+    if ((mesa_fp->Base.InputsRead & (1 << FRAG_ATTRIB_PNTC)) || point_sprite)
+    {
+        /* for FRAG_ATTRIB_PNTC we need to increase num_interp */
+        if(mesa_fp->Base.InputsRead & (1 << FRAG_ATTRIB_PNTC))
+        {
+            ui++;
+            SETfield(evergreen->SPI_PS_IN_CONTROL_0.u32All, ui, NUM_INTERP_shift, NUM_INTERP_mask);
+        }
+        SETbit(evergreen->SPI_INTERP_CONTROL_0.u32All, PNT_SPRITE_ENA_bit);
+        SETfield(evergreen->SPI_INTERP_CONTROL_0.u32All, SPI_PNT_SPRITE_SEL_S, PNT_SPRITE_OVRD_X_shift, PNT_SPRITE_OVRD_X_mask);
+        SETfield(evergreen->SPI_INTERP_CONTROL_0.u32All, SPI_PNT_SPRITE_SEL_T, PNT_SPRITE_OVRD_Y_shift, PNT_SPRITE_OVRD_Y_mask);
+        SETfield(evergreen->SPI_INTERP_CONTROL_0.u32All, SPI_PNT_SPRITE_SEL_0, PNT_SPRITE_OVRD_Z_shift, PNT_SPRITE_OVRD_Z_mask);
+        SETfield(evergreen->SPI_INTERP_CONTROL_0.u32All, SPI_PNT_SPRITE_SEL_1, PNT_SPRITE_OVRD_W_shift, PNT_SPRITE_OVRD_W_mask);
+        if(ctx->Point.SpriteOrigin == GL_LOWER_LEFT)
+            SETbit(evergreen->SPI_INTERP_CONTROL_0.u32All, PNT_SPRITE_TOP_1_bit);
+        else
+            CLEARbit(evergreen->SPI_INTERP_CONTROL_0.u32All, PNT_SPRITE_TOP_1_bit);
+    }
+    else
+    {
+        CLEARbit(evergreen->SPI_INTERP_CONTROL_0.u32All, PNT_SPRITE_ENA_bit);
+    }
+
+
+    ui = (unNumOfReg < ui) ? ui : unNumOfReg;
+
+    SETfield(evergreen->SQ_PGM_RESOURCES_PS.u32All, ui, NUM_GPRS_shift, NUM_GPRS_mask);
+
+    CLEARbit(evergreen->SQ_PGM_RESOURCES_PS.u32All, UNCACHED_FIRST_INST_bit);
+
+    if(fp->r700Shader.uStackSize) /* we don't use branch for now, it should be zero. */
+       {
+        SETfield(evergreen->SQ_PGM_RESOURCES_PS.u32All, fp->r700Shader.uStackSize,
+                 STACK_SIZE_shift, STACK_SIZE_mask);
+    }
+
+    SETfield(evergreen->SQ_PGM_EXPORTS_PS.u32All, fp->r700Shader.exportMode,
+             EXPORT_MODE_shift, EXPORT_MODE_mask);
+
+    // emit ps input map
+    struct evergreen_vertex_program_cont *vpc =
+                      (struct evergreen_vertex_program_cont *)ctx->VertexProgram._Current;
+    GLbitfield OutputsWritten = vpc->mesa_program.Base.OutputsWritten;
+    
+    for(ui = 0; ui < EVERGREEN_MAX_SHADER_EXPORTS; ui++)
+        evergreen->SPI_PS_INPUT_CNTL[ui].u32All = 0;
+
+    unBit = 1 << FRAG_ATTRIB_WPOS;
+    if(mesa_fp->Base.InputsRead & unBit)
+    {
+            ui = pAsm->uiFP_AttributeMap[FRAG_ATTRIB_WPOS];
+            SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit);
+            SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui,
+                     SEMANTIC_shift, SEMANTIC_mask);
+            if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit)
+                    SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+            else
+                    CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+    }
+
+    unBit = 1 << VERT_RESULT_COL0;
+    if(OutputsWritten & unBit)
+    {
+           ui = pAsm->uiFP_AttributeMap[FRAG_ATTRIB_COL0];
+           SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit);
+           SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui,
+                    SEMANTIC_shift, SEMANTIC_mask);
+           if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit)
+                   SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+           else
+                   CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+    }
+
+    unBit = 1 << VERT_RESULT_COL1;
+    if(OutputsWritten & unBit)
+    {
+           ui = pAsm->uiFP_AttributeMap[FRAG_ATTRIB_COL1];
+           SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit);
+           SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui,
+                    SEMANTIC_shift, SEMANTIC_mask);
+           if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit)
+                   SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+           else
+                   CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+    }
+
+    unBit = 1 << VERT_RESULT_FOGC;
+    if(OutputsWritten & unBit)
+    {
+            ui = pAsm->uiFP_AttributeMap[FRAG_ATTRIB_FOGC];
+            SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit);
+            SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui,
+                     SEMANTIC_shift, SEMANTIC_mask);
+            if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit)
+                    SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+            else
+                    CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+    }
+
+    for(i=0; i<8; i++)
+    {
+           unBit = 1 << (VERT_RESULT_TEX0 + i);
+           if(OutputsWritten & unBit)
+           {
+                   ui = pAsm->uiFP_AttributeMap[FRAG_ATTRIB_TEX0 + i];
+                   SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit);
+                   SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui,
+                            SEMANTIC_shift, SEMANTIC_mask);
+                   CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+                   /* ARB_point_sprite */
+                   if(ctx->Point.CoordReplace[i] == GL_TRUE)
+                   {
+                            SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, PT_SPRITE_TEX_bit);
+                   }
+           }
+    }
+
+    unBit = 1 << FRAG_ATTRIB_FACE;
+    if(mesa_fp->Base.InputsRead & unBit)
+    {
+            ui = pAsm->uiFP_AttributeMap[FRAG_ATTRIB_FACE];
+            SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit);
+            SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui,
+                     SEMANTIC_shift, SEMANTIC_mask);
+            if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit)
+                    SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+            else
+                    CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+    }
+    unBit = 1 << FRAG_ATTRIB_PNTC;
+    if(mesa_fp->Base.InputsRead & unBit)
+    {
+            ui = pAsm->uiFP_AttributeMap[FRAG_ATTRIB_PNTC];
+            SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit);
+            SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui,
+                     SEMANTIC_shift, SEMANTIC_mask);
+            if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit)
+                    SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+            else
+                    CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+            SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, PT_SPRITE_TEX_bit);
+    }
+
+
+
+
+    for(i=VERT_RESULT_VAR0; i<VERT_RESULT_MAX; i++)
+       {
+        unBit = 1 << i;
+        if(OutputsWritten & unBit)
+               {
+            ui = pAsm->uiFP_AttributeMap[i-VERT_RESULT_VAR0+FRAG_ATTRIB_VAR0];
+            SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit);
+            SETfield(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, ui,
+                            SEMANTIC_shift, SEMANTIC_mask);
+            if (evergreen->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit)
+                       SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+            else
+                       CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+        }
+    }
+
+    exportCount = (evergreen->SQ_PGM_EXPORTS_PS.u32All & EXPORT_MODE_mask) / (1 << EXPORT_MODE_shift);
+
+    return GL_TRUE;
+}
+
+GLboolean evergreenSetupFPconstants(GLcontext * ctx)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+    struct evergreen_fragment_program *fp = (struct evergreen_fragment_program *)
+                                          (ctx->FragmentProgram._Current);
+    r700_AssemblerBase *pAsm = &(fp->r700AsmCode);
+
+    struct gl_program_parameter_list *paramList;
+    unsigned int unNumParamData;
+    unsigned int ui;
+
+    /* sent out shader constants. */
+    paramList = fp->mesa_program.Base.Parameters;
+
+    if(NULL != paramList) 
+    {
+           _mesa_load_state_parameters(ctx, paramList);
+
+           if (paramList->NumParameters > EVERGREEN_MAX_DX9_CONSTS)
+                   return GL_FALSE;
+
+           EVERGREEN_STATECHANGE(context, sq);
+
+           evergreen->ps.num_consts = paramList->NumParameters;
+
+           unNumParamData = paramList->NumParameters;
+
+           for(ui=0; ui<unNumParamData; ui++) {
+                       evergreen->ps.consts[ui][0].f32All = paramList->ParameterValues[ui][0];
+                       evergreen->ps.consts[ui][1].f32All = paramList->ParameterValues[ui][1];
+                       evergreen->ps.consts[ui][2].f32All = paramList->ParameterValues[ui][2];
+                       evergreen->ps.consts[ui][3].f32All = paramList->ParameterValues[ui][3];
+           }
+        
+        /* Load fp constants to gpu */
+        if(unNumParamData > 0) 
+        {            
+            radeonAllocDmaRegion(&context->radeon, 
+                                &context->fp_Constbo, 
+                                &context->fp_bo_offset, 
+                                256, 
+                                256);            
+            r600EmitShaderConsts(ctx,
+                                 context->fp_Constbo,
+                                 context->fp_bo_offset,         
+                                 (GLvoid *)&(evergreen->ps.consts[0][0]),
+                                 unNumParamData * 4 * 4);
+        }
+    } else
+           evergreen->ps.num_consts = 0;
+
+    COMPILED_SUB * pCompiledSub;
+    GLuint uj;
+    GLuint unConstOffset = evergreen->ps.num_consts;
+    for(ui=0; ui<pAsm->unNumPresub; ui++)
+    {
+        pCompiledSub = pAsm->presubs[ui].pCompiledSub;
+
+        evergreen->ps.num_consts += pCompiledSub->NumParameters;
+
+        for(uj=0; uj<pCompiledSub->NumParameters; uj++)
+        {
+            evergreen->ps.consts[uj + unConstOffset][0].f32All = pCompiledSub->ParameterValues[uj][0];
+                   evergreen->ps.consts[uj + unConstOffset][1].f32All = pCompiledSub->ParameterValues[uj][1];
+                   evergreen->ps.consts[uj + unConstOffset][2].f32All = pCompiledSub->ParameterValues[uj][2];
+                   evergreen->ps.consts[uj + unConstOffset][3].f32All = pCompiledSub->ParameterValues[uj][3];
+        }
+        unConstOffset += pCompiledSub->NumParameters;
+    }
+}
\ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/evergreen_fragprog.h b/src/mesa/drivers/dri/r600/evergreen_fragprog.h
new file mode 100644 (file)
index 0000000..0e200bf
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2008-2009  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#ifndef _EVERGREEN_FRAGPROG_H_
+#define _EVERGREEN_FRAGPROG_H_
+
+#include "r600_context.h"
+#include "r700_assembler.h"
+
+struct evergreen_fragment_program
+{
+       struct gl_fragment_program mesa_program;
+
+    r700_AssemblerBase r700AsmCode;
+       R700_Shader        r700Shader;
+
+       GLboolean translated;
+    GLboolean loaded;
+       GLboolean error;
+
+    void * shaderbo;
+
+       GLuint k0used;
+    void * constbo0;
+
+       GLboolean WritesDepth;
+       GLuint optimization;
+};
+
+/* Internal */
+void evergreen_insert_wpos_code(GLcontext *ctx, struct gl_fragment_program *fprog);
+
+void evergreen_Map_Fragment_Program(r700_AssemblerBase         *pAsm,
+                         struct gl_fragment_program *mesa_fp,
+                          GLcontext *ctx); 
+GLboolean evergreen_Find_Instruction_Dependencies_fp(struct evergreen_fragment_program *fp,
+                                          struct gl_fragment_program   *mesa_fp);
+
+GLboolean evergreenTranslateFragmentShader(struct evergreen_fragment_program *fp,
+                                     struct gl_fragment_program   *mesa_vp,
+                                      GLcontext *ctx); 
+
+/* Interface */
+extern void evergreenSelectFragmentShader(GLcontext *ctx);
+
+extern GLboolean evergreenSetupFragmentProgram(GLcontext * ctx);
+
+extern GLboolean evergreenSetupFPconstants(GLcontext * ctx);
+
+extern void *    evergreenGetActiveFpShaderBo(GLcontext * ctx);
+
+extern void *    evergreenGetActiveFpShaderConstBo(GLcontext * ctx);
+
+#endif /*_EVERGREEN_FRAGPROG_H_*/
diff --git a/src/mesa/drivers/dri/r600/evergreen_ioctl.c b/src/mesa/drivers/dri/r600/evergreen_ioctl.c
new file mode 100644 (file)
index 0000000..5c12707
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008-2009  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#include <sched.h>
+#include <errno.h>
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/context.h"
+#include "main/simple_list.h"
+
+#include "radeon_common.h"
+#include "r600_context.h"
+
+#include "evergreen_ioctl.h"
+
+#include "r700_clear.h"
+
+void evergreenClear(GLcontext * ctx, GLbitfield mask)
+{    
+    r700Clear(ctx, mask);
+}
+
+void evergreenInitIoctlFuncs(struct dd_function_table *functions)
+{
+       functions->Clear = evergreenClear;
+       functions->Finish = radeonFinish;
+       functions->Flush = radeonFlush;
+}
diff --git a/src/mesa/drivers/dri/r600/evergreen_ioctl.h b/src/mesa/drivers/dri/r600/evergreen_ioctl.h
new file mode 100644 (file)
index 0000000..3c663a7
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2010  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#ifndef _EVERGREEN_IOCTL_H_
+#define _EVERGREEN_IOCTL_H_
+
+#include "r600_context.h"
+#include "radeon_drm.h"
+
+extern void evergreenClear(GLcontext * ctx, GLbitfield mask);
+extern void evergreenInitIoctlFuncs(struct dd_function_table *functions);
+
+#endif    /* _EVERGREEN_IOCTL_H_ */
diff --git a/src/mesa/drivers/dri/r600/evergreen_off.h b/src/mesa/drivers/dri/r600/evergreen_off.h
new file mode 100644 (file)
index 0000000..8c25069
--- /dev/null
@@ -0,0 +1,881 @@
+/*
+ * Copyright (C) 2008-2010  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com> 
+ */
+
+#ifndef _EVERGREEN_OFF_H_
+#define _EVERGREEN_OFF_H_
+
+enum 
+{
+/* Registers from PA block: */         
+  EG_PA_SC_SCREEN_SCISSOR_TL                    = 0x28030, // DIFF 
+  EG_PA_SC_SCREEN_SCISSOR_BR                    = 0x28034, // DIFF 
+  EG_PA_SC_WINDOW_OFFSET                        = 0x28200, // DIFF 
+  EG_PA_SC_WINDOW_SCISSOR_TL                    = 0x28204, // DIFF 
+  EG_PA_SC_WINDOW_SCISSOR_BR                    = 0x28208, // DIFF 
+  EG_PA_SC_CLIPRECT_RULE                        = 0x2820C, // SAME 
+  EG_PA_SC_CLIPRECT_0_TL                        = 0x28210, // DIFF 
+  EG_PA_SC_CLIPRECT_0_BR                        = 0x28214, // DIFF 
+  EG_PA_SC_CLIPRECT_1_TL                        = 0x28218, // DIFF 
+  EG_PA_SC_CLIPRECT_1_BR                        = 0x2821C, // DIFF 
+  EG_PA_SC_CLIPRECT_2_TL                        = 0x28220, // DIFF 
+  EG_PA_SC_CLIPRECT_2_BR                        = 0x28224, // DIFF 
+  EG_PA_SC_CLIPRECT_3_TL                        = 0x28228, // DIFF 
+  EG_PA_SC_CLIPRECT_3_BR                        = 0x2822C, // DIFF 
+  EG_PA_SC_EDGERULE                             = 0x28230, // SAME 
+  EG_PA_SU_HARDWARE_SCREEN_OFFSET               = 0x28234, // 
+  EG_PA_SC_GENERIC_SCISSOR_TL                   = 0x28240, // DIFF 
+  EG_PA_SC_GENERIC_SCISSOR_BR                   = 0x28244, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_0_TL                   = 0x28250, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_0_BR                   = 0x28254, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_1_TL                   = 0x28258, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_1_BR                   = 0x2825C, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_2_TL                   = 0x28260, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_2_BR                   = 0x28264, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_3_TL                   = 0x28268, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_3_BR                   = 0x2826C, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_4_TL                   = 0x28270, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_4_BR                   = 0x28274, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_5_TL                   = 0x28278, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_5_BR                   = 0x2827C, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_6_TL                   = 0x28280, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_6_BR                   = 0x28284, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_7_TL                   = 0x28288, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_7_BR                   = 0x2828C, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_8_TL                   = 0x28290, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_8_BR                   = 0x28294, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_9_TL                   = 0x28298, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_9_BR                   = 0x2829C, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_10_TL                  = 0x282A0, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_10_BR                  = 0x282A4, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_11_TL                  = 0x282A8, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_11_BR                  = 0x282AC, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_12_TL                  = 0x282B0, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_12_BR                  = 0x282B4, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_13_TL                  = 0x282B8, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_13_BR                  = 0x282BC, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_14_TL                  = 0x282C0, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_14_BR                  = 0x282C4, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_15_TL                  = 0x282C8, // DIFF 
+  EG_PA_SC_VPORT_SCISSOR_15_BR                  = 0x282CC, // DIFF 
+  EG_PA_SC_VPORT_ZMIN_0                         = 0x282D0, // SAME 
+  EG_PA_SC_VPORT_ZMAX_0                         = 0x282D4, // SAME 
+  EG_PA_SC_VPORT_ZMIN_1                         = 0x282D8, // SAME 
+  EG_PA_SC_VPORT_ZMAX_1                         = 0x282DC, // SAME 
+  EG_PA_SC_VPORT_ZMIN_2                         = 0x282E0, // SAME 
+  EG_PA_SC_VPORT_ZMAX_2                         = 0x282E4, // SAME 
+  EG_PA_SC_VPORT_ZMIN_3                         = 0x282E8, // SAME 
+  EG_PA_SC_VPORT_ZMAX_3                         = 0x282EC, // SAME 
+  EG_PA_SC_VPORT_ZMIN_4                         = 0x282F0, // SAME 
+  EG_PA_SC_VPORT_ZMAX_4                         = 0x282F4, // SAME 
+  EG_PA_SC_VPORT_ZMIN_5                         = 0x282F8, // SAME 
+  EG_PA_SC_VPORT_ZMAX_5                         = 0x282FC, // SAME 
+  EG_PA_SC_VPORT_ZMIN_6                         = 0x28300, // SAME 
+  EG_PA_SC_VPORT_ZMAX_6                         = 0x28304, // SAME 
+  EG_PA_SC_VPORT_ZMIN_7                         = 0x28308, // SAME 
+  EG_PA_SC_VPORT_ZMAX_7                         = 0x2830C, // SAME 
+  EG_PA_SC_VPORT_ZMIN_8                         = 0x28310, // SAME 
+  EG_PA_SC_VPORT_ZMAX_8                         = 0x28314, // SAME 
+  EG_PA_SC_VPORT_ZMIN_9                         = 0x28318, // SAME 
+  EG_PA_SC_VPORT_ZMAX_9                         = 0x2831C, // SAME 
+  EG_PA_SC_VPORT_ZMIN_10                        = 0x28320, // SAME 
+  EG_PA_SC_VPORT_ZMAX_10                        = 0x28324, // SAME 
+  EG_PA_SC_VPORT_ZMIN_11                        = 0x28328, // SAME 
+  EG_PA_SC_VPORT_ZMAX_11                        = 0x2832C, // SAME 
+  EG_PA_SC_VPORT_ZMIN_12                        = 0x28330, // SAME 
+  EG_PA_SC_VPORT_ZMAX_12                        = 0x28334, // SAME 
+  EG_PA_SC_VPORT_ZMIN_13                        = 0x28338, // SAME 
+  EG_PA_SC_VPORT_ZMAX_13                        = 0x2833C, // SAME 
+  EG_PA_SC_VPORT_ZMIN_14                        = 0x28340, // SAME 
+  EG_PA_SC_VPORT_ZMAX_14                        = 0x28344, // SAME 
+  EG_PA_SC_VPORT_ZMIN_15                        = 0x28348, // SAME 
+  EG_PA_SC_VPORT_ZMAX_15                        = 0x2834C, // SAME 
+  EG_PA_CL_VPORT_XSCALE                         = 0x2843C, // SAME 
+  EG_PA_CL_VPORT_XOFFSET                        = 0x28440, // SAME 
+  EG_PA_CL_VPORT_YSCALE                         = 0x28444, // SAME 
+  EG_PA_CL_VPORT_YOFFSET                        = 0x28448, // SAME 
+  EG_PA_CL_VPORT_ZSCALE                         = 0x2844C, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET                        = 0x28450, // SAME 
+  EG_PA_CL_VPORT_XSCALE_1                       = 0x28454, // SAME 
+  EG_PA_CL_VPORT_XOFFSET_1                      = 0x28458, // SAME 
+  EG_PA_CL_VPORT_YSCALE_1                       = 0x2845C, // SAME 
+  EG_PA_CL_VPORT_YOFFSET_1                      = 0x28460, // SAME 
+  EG_PA_CL_VPORT_ZSCALE_1                       = 0x28464, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET_1                      = 0x28468, // SAME 
+  EG_PA_CL_VPORT_XSCALE_2                       = 0x2846C, // SAME 
+  EG_PA_CL_VPORT_XOFFSET_2                      = 0x28470, // SAME 
+  EG_PA_CL_VPORT_YSCALE_2                       = 0x28474, // SAME 
+  EG_PA_CL_VPORT_YOFFSET_2                      = 0x28478, // SAME 
+  EG_PA_CL_VPORT_ZSCALE_2                       = 0x2847C, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET_2                      = 0x28480, // SAME 
+  EG_PA_CL_VPORT_XSCALE_3                       = 0x28484, // SAME 
+  EG_PA_CL_VPORT_XOFFSET_3                      = 0x28488, // SAME 
+  EG_PA_CL_VPORT_YSCALE_3                       = 0x2848C, // SAME 
+  EG_PA_CL_VPORT_YOFFSET_3                      = 0x28490, // SAME 
+  EG_PA_CL_VPORT_ZSCALE_3                       = 0x28494, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET_3                      = 0x28498, // SAME 
+  EG_PA_CL_VPORT_XSCALE_4                       = 0x2849C, // SAME 
+  EG_PA_CL_VPORT_XOFFSET_4                      = 0x284A0, // SAME 
+  EG_PA_CL_VPORT_YSCALE_4                       = 0x284A4, // SAME 
+  EG_PA_CL_VPORT_YOFFSET_4                      = 0x284A8, // SAME 
+  EG_PA_CL_VPORT_ZSCALE_4                       = 0x284AC, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET_4                      = 0x284B0, // SAME 
+  EG_PA_CL_VPORT_XSCALE_5                       = 0x284B4, // SAME 
+  EG_PA_CL_VPORT_XOFFSET_5                      = 0x284B8, // SAME 
+  EG_PA_CL_VPORT_YSCALE_5                       = 0x284BC, // SAME 
+  EG_PA_CL_VPORT_YOFFSET_5                      = 0x284C0, // SAME 
+  EG_PA_CL_VPORT_ZSCALE_5                       = 0x284C4, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET_5                      = 0x284C8, // SAME 
+  EG_PA_CL_VPORT_XSCALE_6                       = 0x284CC, // SAME 
+  EG_PA_CL_VPORT_XOFFSET_6                      = 0x284D0, // SAME 
+  EG_PA_CL_VPORT_YSCALE_6                       = 0x284D4, // SAME 
+  EG_PA_CL_VPORT_YOFFSET_6                      = 0x284D8, // SAME 
+  EG_PA_CL_VPORT_ZSCALE_6                       = 0x284DC, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET_6                      = 0x284E0, // SAME 
+  EG_PA_CL_VPORT_XSCALE_7                       = 0x284E4, // SAME 
+  EG_PA_CL_VPORT_XOFFSET_7                      = 0x284E8, // SAME 
+  EG_PA_CL_VPORT_YSCALE_7                       = 0x284EC, // SAME 
+  EG_PA_CL_VPORT_YOFFSET_7                      = 0x284F0, // SAME 
+  EG_PA_CL_VPORT_ZSCALE_7                       = 0x284F4, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET_7                      = 0x284F8, // SAME 
+  EG_PA_CL_VPORT_XSCALE_8                       = 0x284FC, // SAME 
+  EG_PA_CL_VPORT_XOFFSET_8                      = 0x28500, // SAME 
+  EG_PA_CL_VPORT_YSCALE_8                       = 0x28504, // SAME 
+  EG_PA_CL_VPORT_YOFFSET_8                      = 0x28508, // SAME 
+  EG_PA_CL_VPORT_ZSCALE_8                       = 0x2850C, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET_8                      = 0x28510, // SAME 
+  EG_PA_CL_VPORT_XSCALE_9                       = 0x28514, // SAME 
+  EG_PA_CL_VPORT_XOFFSET_9                      = 0x28518, // SAME 
+  EG_PA_CL_VPORT_YSCALE_9                       = 0x2851C, // SAME 
+  EG_PA_CL_VPORT_YOFFSET_9                      = 0x28520, // SAME 
+  EG_PA_CL_VPORT_ZSCALE_9                       = 0x28524, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET_9                      = 0x28528, // SAME 
+  EG_PA_CL_VPORT_XSCALE_10                      = 0x2852C, // SAME 
+  EG_PA_CL_VPORT_XOFFSET_10                     = 0x28530, // SAME 
+  EG_PA_CL_VPORT_YSCALE_10                      = 0x28534, // SAME 
+  EG_PA_CL_VPORT_YOFFSET_10                     = 0x28538, // SAME 
+  EG_PA_CL_VPORT_ZSCALE_10                      = 0x2853C, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET_10                     = 0x28540, // SAME 
+  EG_PA_CL_VPORT_XSCALE_11                      = 0x28544, // SAME 
+  EG_PA_CL_VPORT_XOFFSET_11                     = 0x28548, // SAME 
+  EG_PA_CL_VPORT_YSCALE_11                      = 0x2854C, // SAME 
+  EG_PA_CL_VPORT_YOFFSET_11                     = 0x28550, // SAME 
+  EG_PA_CL_VPORT_ZSCALE_11                      = 0x28554, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET_11                     = 0x28558, // SAME 
+  EG_PA_CL_VPORT_XSCALE_12                      = 0x2855C, // SAME 
+  EG_PA_CL_VPORT_XOFFSET_12                     = 0x28560, // SAME 
+  EG_PA_CL_VPORT_YSCALE_12                      = 0x28564, // SAME 
+  EG_PA_CL_VPORT_YOFFSET_12                     = 0x28568, // SAME 
+  EG_PA_CL_VPORT_ZSCALE_12                      = 0x2856C, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET_12                     = 0x28570, // SAME 
+  EG_PA_CL_VPORT_XSCALE_13                      = 0x28574, // SAME 
+  EG_PA_CL_VPORT_XOFFSET_13                     = 0x28578, // SAME 
+  EG_PA_CL_VPORT_YSCALE_13                      = 0x2857C, // SAME 
+  EG_PA_CL_VPORT_YOFFSET_13                     = 0x28580, // SAME 
+  EG_PA_CL_VPORT_ZSCALE_13                      = 0x28584, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET_13                     = 0x28588, // SAME 
+  EG_PA_CL_VPORT_XSCALE_14                      = 0x2858C, // SAME 
+  EG_PA_CL_VPORT_XOFFSET_14                     = 0x28590, // SAME 
+  EG_PA_CL_VPORT_YSCALE_14                      = 0x28594, // SAME 
+  EG_PA_CL_VPORT_YOFFSET_14                     = 0x28598, // SAME 
+  EG_PA_CL_VPORT_ZSCALE_14                      = 0x2859C, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET_14                     = 0x285A0, // SAME 
+  EG_PA_CL_VPORT_XSCALE_15                      = 0x285A4, // SAME 
+  EG_PA_CL_VPORT_XOFFSET_15                     = 0x285A8, // SAME 
+  EG_PA_CL_VPORT_YSCALE_15                      = 0x285AC, // SAME 
+  EG_PA_CL_VPORT_YOFFSET_15                     = 0x285B0, // SAME 
+  EG_PA_CL_VPORT_ZSCALE_15                      = 0x285B4, // SAME 
+  EG_PA_CL_VPORT_ZOFFSET_15                     = 0x285B8, // SAME 
+  EG_PA_CL_UCP_0_X                              = 0x285BC, // SAME 0x28E20 
+  EG_PA_CL_UCP_0_Y                              = 0x285C0, // SAME 0x28E24 
+  EG_PA_CL_UCP_0_Z                              = 0x285C4, // SAME 0x28E28 
+  EG_PA_CL_UCP_0_W                              = 0x285C8, // SAME 0x28E2C 
+  EG_PA_CL_UCP_1_X                              = 0x285CC, // SAME 0x28E30 
+  EG_PA_CL_UCP_1_Y                              = 0x285D0, // SAME 0x28E34 
+  EG_PA_CL_UCP_1_Z                              = 0x285D4, // SAME 0x28E38 
+  EG_PA_CL_UCP_1_W                              = 0x285D8, // SAME 0x28E3C 
+  EG_PA_CL_UCP_2_X                              = 0x285DC, // SAME 0x28E40 
+  EG_PA_CL_UCP_2_Y                              = 0x285E0, // SAME 0x28E44 
+  EG_PA_CL_UCP_2_Z                              = 0x285E4, // SAME 0x28E48 
+  EG_PA_CL_UCP_2_W                              = 0x285E8, // SAME 0x28E4C 
+  EG_PA_CL_UCP_3_X                              = 0x285EC, // SAME 0x28E50 
+  EG_PA_CL_UCP_3_Y                              = 0x285F0, // SAME 0x28E54 
+  EG_PA_CL_UCP_3_Z                              = 0x285F4, // SAME 0x28E58 
+  EG_PA_CL_UCP_3_W                              = 0x285F8, // SAME 0x28E5C 
+  EG_PA_CL_UCP_4_X                              = 0x285FC, // SAME 0x28E60 
+  EG_PA_CL_UCP_4_Y                              = 0x28600, // SAME 0x28E64 
+  EG_PA_CL_UCP_4_Z                              = 0x28604, // SAME 0x28E68 
+  EG_PA_CL_UCP_4_W                              = 0x28608, // SAME 0x28E6C 
+  EG_PA_CL_UCP_5_X                              = 0x2860C, // SAME 0x28E70 
+  EG_PA_CL_UCP_5_Y                              = 0x28610, // SAME 0x28E74 
+  EG_PA_CL_UCP_5_Z                              = 0x28614, // SAME 0x28E78 
+  EG_PA_CL_UCP_5_W                              = 0x28618, // SAME 0x28E7C 
+  EG_PA_CL_POINT_X_RAD                          = 0x287D4, // SAME 0x28E10 
+  EG_PA_CL_POINT_Y_RAD                          = 0x287D8, // SAME 0x28E14 
+  EG_PA_CL_POINT_SIZE                           = 0x287DC, // SAME 0x28E18 
+  EG_PA_CL_POINT_CULL_RAD                       = 0x287E0, // SAME 0x28E1C 
+  EG_PA_CL_CLIP_CNTL                            = 0x28810, // SAME 
+  EG_PA_SU_SC_MODE_CNTL                         = 0x28814, // SAME 
+  EG_PA_CL_VTE_CNTL                             = 0x28818, // SAME 
+  EG_PA_CL_VS_OUT_CNTL                          = 0x2881C, // SAME 
+  EG_PA_CL_NANINF_CNTL                          = 0x28820, // SAME 
+  EG_PA_SU_LINE_STIPPLE_CNTL                    = 0x28824, // 
+  EG_PA_SU_LINE_STIPPLE_SCALE                   = 0x28828, // 
+  EG_PA_SU_PRIM_FILTER_CNTL                     = 0x2882C, // 
+  EG_PA_SU_POINT_SIZE                           = 0x28A00, // SAME 
+  EG_PA_SU_POINT_MINMAX                         = 0x28A04, // SAME 
+  EG_PA_SU_LINE_CNTL                            = 0x28A08, // SAME 
+  EG_PA_SC_LINE_STIPPLE                         = 0x28A0C, // SAME 
+  EG_PA_SC_MODE_CNTL_0                          = 0x28A48, // 
+  EG_PA_SC_MODE_CNTL_1                          = 0x28A4C, // 
+  EG_PA_SU_POLY_OFFSET_DB_FMT_CNTL              = 0x28B78, // SAME 0x28DF8 
+  EG_PA_SU_POLY_OFFSET_CLAMP                    = 0x28B7C, // SAME 0x28DFC 
+  EG_PA_SU_POLY_OFFSET_FRONT_SCALE              = 0x28B80, // SAME 0x28E00 
+  EG_PA_SU_POLY_OFFSET_FRONT_OFFSET             = 0x28B84, // SAME 0x28E04 
+  EG_PA_SU_POLY_OFFSET_BACK_SCALE               = 0x28B88, // SAME 0x28E08 
+  EG_PA_SU_POLY_OFFSET_BACK_OFFSET              = 0x28B8C, // SAME 0x28E0C 
+  EG_PA_SC_LINE_CNTL                            = 0x28C00, // DIFF 
+  EG_PA_SC_AA_CONFIG                            = 0x28C04, // SAME 
+  EG_PA_SU_VTX_CNTL                             = 0x28C08, // SAME 
+  EG_PA_CL_GB_VERT_CLIP_ADJ                     = 0x28C0C, // SAME 
+  EG_PA_CL_GB_VERT_DISC_ADJ                     = 0x28C10, // SAME 
+  EG_PA_CL_GB_HORZ_CLIP_ADJ                     = 0x28C14, // SAME 
+  EG_PA_CL_GB_HORZ_DISC_ADJ                     = 0x28C18, // SAME 
+  EG_PA_SC_AA_SAMPLE_LOCS_0                     = 0x28C1C, // 
+  EG_PA_SC_AA_SAMPLE_LOCS_1                     = 0x28C20, // 
+  EG_PA_SC_AA_SAMPLE_LOCS_2                     = 0x28C24, // 
+  EG_PA_SC_AA_SAMPLE_LOCS_3                     = 0x28C28, // 
+  EG_PA_SC_AA_SAMPLE_LOCS_4                     = 0x28C2C, // 
+  EG_PA_SC_AA_SAMPLE_LOCS_5                     = 0x28C30, // 
+  EG_PA_SC_AA_SAMPLE_LOCS_6                     = 0x28C34, // 
+  EG_PA_SC_AA_SAMPLE_LOCS_7                     = 0x28C38, // 
+  EG_PA_SC_AA_MASK                              = 0x28C3C, // SAME 0x28C48 
+
+/* Registers from VGT block: */ 
+  EG_VGT_INDEX_TYPE                             = 0x895C,  //? config space
+  EG_VGT_PRIMITIVE_TYPE                         = 0x8958,  //? config space
+    
+  EG_VGT_MAX_VTX_INDX                           = 0x28400, // SAME 
+  EG_VGT_MIN_VTX_INDX                           = 0x28404, // SAME 
+  EG_VGT_INDX_OFFSET                            = 0x28408, // SAME 
+  EG_VGT_MULTI_PRIM_IB_RESET_INDX               = 0x2840C, // SAME 
+  EG_CS_COPY_STATE                              = 0x287CC, // 
+  EG_GFX_COPY_STATE                             = 0x287D0, // SAME 
+  EG_VGT_DMA_BASE_HI                            = 0x287E4, // SAME 
+  EG_VGT_DMA_BASE                               = 0x287E8, // SAME 
+  EG_VGT_DRAW_INITIATOR                         = 0x287F0, // SAME 
+  EG_VGT_IMMED_DATA                             = 0x287F4, // SAME 
+  EG_VGT_EVENT_ADDRESS_REG                      = 0x287F8, // SAME 
+  EG_VGT_OUTPUT_PATH_CNTL                       = 0x28A10, // DIFF 
+  EG_VGT_HOS_CNTL                               = 0x28A14, // SAME 
+  EG_VGT_HOS_MAX_TESS_LEVEL                     = 0x28A18, // SAME 
+  EG_VGT_HOS_MIN_TESS_LEVEL                     = 0x28A1C, // SAME 
+  EG_VGT_HOS_REUSE_DEPTH                        = 0x28A20, // SAME 
+  EG_VGT_GROUP_PRIM_TYPE                        = 0x28A24, // SAME 
+  EG_VGT_GROUP_FIRST_DECR                       = 0x28A28, // SAME 
+  EG_VGT_GROUP_DECR                             = 0x28A2C, // SAME 
+  EG_VGT_GROUP_VECT_0_CNTL                      = 0x28A30, // SAME 
+  EG_VGT_GROUP_VECT_1_CNTL                      = 0x28A34, // SAME 
+  EG_VGT_GROUP_VECT_0_FMT_CNTL                  = 0x28A38, // SAME 
+  EG_VGT_GROUP_VECT_1_FMT_CNTL                  = 0x28A3C, // SAME 
+  EG_VGT_GS_MODE                                = 0x28A40, // DIFF 
+  EG_VGT_ENHANCE                                = 0x28A50, // DIFF 
+  EG_VGT_GS_PER_ES                              = 0x28A54, // DIFF 0x88C8 
+  EG_VGT_ES_PER_GS                              = 0x28A58, // DIFF 0x88CC 
+  EG_VGT_GS_PER_VS                              = 0x28A5C, // SAME 0x88E8 
+  EG_VGT_GS_OUT_PRIM_TYPE                       = 0x28A6C, // SAME 
+  EG_VGT_DMA_SIZE                               = 0x28A74, // SAME 
+  EG_VGT_DMA_MAX_SIZE                           = 0x28A78, // SAME 
+  EG_VGT_DMA_INDEX_TYPE                         = 0x28A7C, // SAME 
+  EG_VGT_PRIMITIVEID_EN                         = 0x28A84, // SAME 
+  EG_VGT_DMA_NUM_INSTANCES                      = 0x28A88, // SAME 
+  EG_VGT_EVENT_INITIATOR                        = 0x28A90, // SAME 
+  EG_VGT_MULTI_PRIM_IB_RESET_EN                 = 0x28A94, // SAME 
+  EG_VGT_INSTANCE_STEP_RATE_0                   = 0x28AA0, // SAME 
+  EG_VGT_INSTANCE_STEP_RATE_1                   = 0x28AA4, // SAME 
+  EG_VGT_REUSE_OFF                              = 0x28AB4, // SAME 
+  EG_VGT_VTX_CNT_EN                             = 0x28AB8, // SAME 
+  EG_VGT_STRMOUT_BUFFER_SIZE_0                  = 0x28AD0, // SAME 
+  EG_VGT_STRMOUT_VTX_STRIDE_0                   = 0x28AD4, // SAME 
+  EG_VGT_STRMOUT_BUFFER_BASE_0                  = 0x28AD8, // SAME 
+  EG_VGT_STRMOUT_BUFFER_OFFSET_0                = 0x28ADC, // SAME 
+  EG_VGT_STRMOUT_BUFFER_SIZE_1                  = 0x28AE0, // SAME 
+  EG_VGT_STRMOUT_VTX_STRIDE_1                   = 0x28AE4, // SAME 
+  EG_VGT_STRMOUT_BUFFER_BASE_1                  = 0x28AE8, // SAME 
+  EG_VGT_STRMOUT_BUFFER_OFFSET_1                = 0x28AEC, // SAME 
+  EG_VGT_STRMOUT_BUFFER_SIZE_2                  = 0x28AF0, // SAME 
+  EG_VGT_STRMOUT_VTX_STRIDE_2                   = 0x28AF4, // SAME 
+  EG_VGT_STRMOUT_BUFFER_BASE_2                  = 0x28AF8, // SAME 
+  EG_VGT_STRMOUT_BUFFER_OFFSET_2                = 0x28AFC, // SAME 
+  EG_VGT_STRMOUT_BUFFER_SIZE_3                  = 0x28B00, // SAME 
+  EG_VGT_STRMOUT_VTX_STRIDE_3                   = 0x28B04, // SAME 
+  EG_VGT_STRMOUT_BUFFER_BASE_3                  = 0x28B08, // SAME 
+  EG_VGT_STRMOUT_BUFFER_OFFSET_3                = 0x28B0C, // SAME 
+  EG_VGT_STRMOUT_BASE_OFFSET_0                  = 0x28B10, // SAME 
+  EG_VGT_STRMOUT_BASE_OFFSET_1                  = 0x28B14, // SAME 
+  EG_VGT_STRMOUT_BASE_OFFSET_2                  = 0x28B18, // SAME 
+  EG_VGT_STRMOUT_BASE_OFFSET_3                  = 0x28B1C, // SAME 
+  EG_VGT_STRMOUT_DRAW_OPAQUE_OFFSET             = 0x28B28, // SAME 
+  EG_VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE = 0x28B2C, // SAME 
+  EG_VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE      = 0x28B30, // DIFF 
+  EG_VGT_GS_MAX_VERT_OUT                        = 0x28B38, // SAME 
+  EG_VGT_STRMOUT_BASE_OFFSET_HI_0               = 0x28B44, // SAME 
+  EG_VGT_STRMOUT_BASE_OFFSET_HI_1               = 0x28B48, // SAME 
+  EG_VGT_STRMOUT_BASE_OFFSET_HI_2               = 0x28B4C, // SAME 
+  EG_VGT_STRMOUT_BASE_OFFSET_HI_3               = 0x28B50, // SAME 
+  EG_VGT_SHADER_STAGES_EN                       = 0x28B54, // 
+  EG_VGT_LS_HS_CONFIG                           = 0x28B58, // 
+  EG_VGT_LS_SIZE                                = 0x28B5C, // 
+  EG_VGT_HS_SIZE                                = 0x28B60, // 
+  EG_VGT_LS_HS_ALLOC                            = 0x28B64, // 
+  EG_VGT_HS_PATCH_CONST                         = 0x28B68, // 
+  EG_VGT_TF_PARAM                               = 0x28B6C, // 
+  EG_VGT_DISPATCH_INITIATOR                     = 0x28B74, // 
+  EG_VGT_GS_INSTANCE_CNT                        = 0x28B90, // 
+  EG_VGT_STRMOUT_CONFIG                         = 0x28B94, // 
+  EG_VGT_STRMOUT_BUFFER_CONFIG                  = 0x28B98, // 
+  EG_VGT_VERTEX_REUSE_BLOCK_CNTL                = 0x28C58, // SAME 
+  EG_VGT_OUT_DEALLOC_CNTL                       = 0x28C5C, // SAME 
+
+/* Registers from TP block: */         
+  EG_GDS_ADDR_BASE                              = 0x28720, // 
+  EG_GDS_ADDR_SIZE                              = 0x28724, // 
+  EG_GDS_ORDERED_WAVE_PER_SE                    = 0x28728, // 
+  EG_GDS_APPEND_CONSUME_UAV0                    = 0x2872C, // 
+  EG_GDS_APPEND_CONSUME_UAV1                    = 0x28730, // 
+  EG_GDS_APPEND_CONSUME_UAV2                    = 0x28734, // 
+  EG_GDS_APPEND_CONSUME_UAV3                    = 0x28738, // 
+  EG_GDS_APPEND_CONSUME_UAV4                    = 0x2873C, // 
+  EG_GDS_APPEND_CONSUME_UAV5                    = 0x28740, // 
+  EG_GDS_APPEND_CONSUME_UAV6                    = 0x28744, // 
+  EG_GDS_APPEND_CONSUME_UAV7                    = 0x28748, // 
+  EG_GDS_APPEND_CONSUME_UAV8                    = 0x2874C, // 
+  EG_GDS_APPEND_CONSUME_UAV9                    = 0x28750, // 
+  EG_GDS_APPEND_CONSUME_UAV10                   = 0x28754, // 
+  EG_GDS_APPEND_CONSUME_UAV11                   = 0x28758, // 
+
+/* Registers from SQ block: */         
+  EG_SQ_LOOP_CONST_0                            = 0x3A200, //      0x3E200
+  EG_SQ_ALU_CONST_BUFFER_SIZE_VS_0              = 0x28180, // ?
+  EG_SQ_VTX_SEMANTIC_0                          = 0x28380, // SAME
+  EG_SQ_VTX_SEMANTIC_1                          = 0x28384, // SAME
+  EG_SQ_VTX_SEMANTIC_2                          = 0x28388, // SAME
+  EG_SQ_VTX_SEMANTIC_3                          = 0x2838C, // SAME
+  EG_SQ_VTX_SEMANTIC_4                          = 0x28390, // SAME
+  EG_SQ_VTX_SEMANTIC_5                          = 0x28394, // SAME
+  EG_SQ_VTX_SEMANTIC_6                          = 0x28398, // SAME 
+  EG_SQ_VTX_SEMANTIC_7                          = 0x2839C, // SAME 
+  EG_SQ_VTX_SEMANTIC_8                          = 0x283A0, // SAME 
+  EG_SQ_VTX_SEMANTIC_9                          = 0x283A4, // SAME 
+  EG_SQ_VTX_SEMANTIC_10                         = 0x283A8, // SAME 
+  EG_SQ_VTX_SEMANTIC_11                         = 0x283AC, // SAME 
+  EG_SQ_VTX_SEMANTIC_12                         = 0x283B0, // SAME 
+  EG_SQ_VTX_SEMANTIC_13                         = 0x283B4, // SAME 
+  EG_SQ_VTX_SEMANTIC_14                         = 0x283B8, // SAME 
+  EG_SQ_VTX_SEMANTIC_15                         = 0x283BC, // SAME 
+  EG_SQ_VTX_SEMANTIC_16                         = 0x283C0, // SAME 
+  EG_SQ_VTX_SEMANTIC_17                         = 0x283C4, // SAME 
+  EG_SQ_VTX_SEMANTIC_18                         = 0x283C8, // SAME 
+  EG_SQ_VTX_SEMANTIC_19                         = 0x283CC, // SAME 
+  EG_SQ_VTX_SEMANTIC_20                         = 0x283D0, // SAME 
+  EG_SQ_VTX_SEMANTIC_21                         = 0x283D4, // SAME 
+  EG_SQ_VTX_SEMANTIC_22                         = 0x283D8, // SAME 
+  EG_SQ_VTX_SEMANTIC_23                         = 0x283DC, // SAME 
+  EG_SQ_VTX_SEMANTIC_24                         = 0x283E0, // SAME 
+  EG_SQ_VTX_SEMANTIC_25                         = 0x283E4, // SAME 
+  EG_SQ_VTX_SEMANTIC_26                         = 0x283E8, // SAME 
+  EG_SQ_VTX_SEMANTIC_27                         = 0x283EC, // SAME 
+  EG_SQ_VTX_SEMANTIC_28                         = 0x283F0, // SAME 
+  EG_SQ_VTX_SEMANTIC_29                         = 0x283F4, // SAME 
+  EG_SQ_VTX_SEMANTIC_30                         = 0x283F8, // SAME 
+  EG_SQ_VTX_SEMANTIC_31                         = 0x283FC, // SAME 
+  EG_SQ_LSTMP_RING_ITEMSIZE                     = 0x28830, // 
+  EG_SQ_HSTMP_RING_ITEMSIZE                     = 0x28834, // 
+  EG_SQ_DYN_GPR_RESOURCE_LIMIT_1                = 0x28838, // 
+  EG_SQ_PGM_START_PS                            = 0x28840, // SAME 
+  EG_SQ_PGM_RESOURCES_PS                        = 0x28844, // DIFF 0x28850 
+  EG_SQ_PGM_RESOURCES_2_PS                      = 0x28848, // 
+  EG_SQ_PGM_EXPORTS_PS                          = 0x2884C, // SAME 0x28854 
+  EG_SQ_PGM_START_VS                            = 0x2885C, // SAME 0x28858 
+  EG_SQ_PGM_RESOURCES_VS                        = 0x28860, // DIFF 0x28868 
+  EG_SQ_PGM_RESOURCES_2_VS                      = 0x28864, // 
+  EG_SQ_PGM_START_GS                            = 0x28874, // SAME 0x2886C 
+  EG_SQ_PGM_RESOURCES_GS                        = 0x28878, // DIFF 0x2887C 
+  EG_SQ_PGM_RESOURCES_2_GS                      = 0x2887C, // 
+  EG_SQ_PGM_START_ES                            = 0x2888C, // SAME 0x28880 
+  EG_SQ_PGM_RESOURCES_ES                        = 0x28890, // DIFF 
+  EG_SQ_PGM_RESOURCES_2_ES                      = 0x28894, // 
+  EG_SQ_PGM_START_FS                            = 0x288A4, // SAME 0x28894 
+  EG_SQ_PGM_RESOURCES_FS                        = 0x288A8, // DIFF 0x288A4 
+  EG_SQ_PGM_START_HS                            = 0x288B8, // 
+  EG_SQ_PGM_RESOURCES_HS                        = 0x288BC, // 
+  EG_SQ_PGM_RESOURCES_2_HS                      = 0x288C0, // 
+  EG_SQ_PGM_START_LS                            = 0x288D0, // 
+  EG_SQ_PGM_RESOURCES_LS                        = 0x288D4, // 
+  EG_SQ_PGM_RESOURCES_2_LS                      = 0x288D8, // 
+  EG_SQ_THREAD_TRACE_USERDATA                   = 0x288DC, // 
+  EG_SQ_LDS_ALLOC                               = 0x288E8, // 
+  EG_SQ_LDS_ALLOC_PS                            = 0x288EC, // 
+  EG_SQ_VTX_SEMANTIC_CLEAR                      = 0x288F0, // SAME 0x288E0 
+  EG_SQ_THREAD_TRACE_CTRL                       = 0x288F8, // 
+  EG_SQ_ESGS_RING_ITEMSIZE                      = 0x28900, // SAME 0x288A8 
+  EG_SQ_GSVS_RING_ITEMSIZE                      = 0x28904, // SAME 0x288AC 
+  EG_SQ_ESTMP_RING_ITEMSIZE                     = 0x28908, // SAME 0x288B0 
+  EG_SQ_GSTMP_RING_ITEMSIZE                     = 0x2890C, // SAME 0x288B4 
+  EG_SQ_VSTMP_RING_ITEMSIZE                     = 0x28910, // SAME 0x288B8 
+  EG_SQ_PSTMP_RING_ITEMSIZE                     = 0x28914, // SAME 0x288BC 
+  EG_SQ_GS_VERT_ITEMSIZE                        = 0x2891C, // SAME 0x288C8 
+  EG_SQ_GS_VERT_ITEMSIZE_1                      = 0x28920, // 
+  EG_SQ_GS_VERT_ITEMSIZE_2                      = 0x28924, // 
+  EG_SQ_GS_VERT_ITEMSIZE_3                      = 0x28928, // 
+  EG_SQ_GSVS_RING_OFFSET_1                      = 0x2892C, // 
+  EG_SQ_GSVS_RING_OFFSET_2                      = 0x28930, // 
+  EG_SQ_GSVS_RING_OFFSET_3                      = 0x28934, // 
+  EG_SQ_ALU_CONST_CACHE_PS_0                    = 0x28940, // SAME 
+  EG_SQ_ALU_CONST_CACHE_PS_1                    = 0x28944, // SAME 
+  EG_SQ_ALU_CONST_CACHE_PS_2                    = 0x28948, // SAME 
+  EG_SQ_ALU_CONST_CACHE_PS_3                    = 0x2894C, // SAME 
+  EG_SQ_ALU_CONST_CACHE_PS_4                    = 0x28950, // SAME 
+  EG_SQ_ALU_CONST_CACHE_PS_5                    = 0x28954, // SAME 
+  EG_SQ_ALU_CONST_CACHE_PS_6                    = 0x28958, // SAME 
+  EG_SQ_ALU_CONST_CACHE_PS_7                    = 0x2895C, // SAME 
+  EG_SQ_ALU_CONST_CACHE_PS_8                    = 0x28960, // SAME 
+  EG_SQ_ALU_CONST_CACHE_PS_9                    = 0x28964, // SAME 
+  EG_SQ_ALU_CONST_CACHE_PS_10                   = 0x28968, // SAME 
+  EG_SQ_ALU_CONST_CACHE_PS_11                   = 0x2896C, // SAME 
+  EG_SQ_ALU_CONST_CACHE_PS_12                   = 0x28970, // SAME 
+  EG_SQ_ALU_CONST_CACHE_PS_13                   = 0x28974, // SAME 
+  EG_SQ_ALU_CONST_CACHE_PS_14                   = 0x28978, // SAME 
+  EG_SQ_ALU_CONST_CACHE_PS_15                   = 0x2897C, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_0                    = 0x28980, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_1                    = 0x28984, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_2                    = 0x28988, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_3                    = 0x2898C, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_4                    = 0x28990, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_5                    = 0x28994, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_6                    = 0x28998, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_7                    = 0x2899C, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_8                    = 0x289A0, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_9                    = 0x289A4, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_10                   = 0x289A8, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_11                   = 0x289AC, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_12                   = 0x289B0, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_13                   = 0x289B4, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_14                   = 0x289B8, // SAME 
+  EG_SQ_ALU_CONST_CACHE_VS_15                   = 0x289BC, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_0                    = 0x289C0, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_1                    = 0x289C4, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_2                    = 0x289C8, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_3                    = 0x289CC, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_4                    = 0x289D0, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_5                    = 0x289D4, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_6                    = 0x289D8, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_7                    = 0x289DC, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_8                    = 0x289E0, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_9                    = 0x289E4, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_10                   = 0x289E8, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_11                   = 0x289EC, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_12                   = 0x289F0, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_13                   = 0x289F4, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_14                   = 0x289F8, // SAME 
+  EG_SQ_ALU_CONST_CACHE_GS_15                   = 0x289FC, // SAME 
+  EG_SQ_ALU_CONST_CACHE_HS_0                    = 0x28F00, // 
+  EG_SQ_ALU_CONST_CACHE_HS_1                    = 0x28F04, // 
+  EG_SQ_ALU_CONST_CACHE_HS_2                    = 0x28F08, // 
+  EG_SQ_ALU_CONST_CACHE_HS_3                    = 0x28F0C, // 
+  EG_SQ_ALU_CONST_CACHE_HS_4                    = 0x28F10, // 
+  EG_SQ_ALU_CONST_CACHE_HS_5                    = 0x28F14, // 
+  EG_SQ_ALU_CONST_CACHE_HS_6                    = 0x28F18, // 
+  EG_SQ_ALU_CONST_CACHE_HS_7                    = 0x28F1C, // 
+  EG_SQ_ALU_CONST_CACHE_HS_8                    = 0x28F20, // 
+  EG_SQ_ALU_CONST_CACHE_HS_9                    = 0x28F24, // 
+  EG_SQ_ALU_CONST_CACHE_HS_10                   = 0x28F28, // 
+  EG_SQ_ALU_CONST_CACHE_HS_11                   = 0x28F2C, // 
+  EG_SQ_ALU_CONST_CACHE_HS_12                   = 0x28F30, // 
+  EG_SQ_ALU_CONST_CACHE_HS_13                   = 0x28F34, // 
+  EG_SQ_ALU_CONST_CACHE_HS_14                   = 0x28F38, // 
+  EG_SQ_ALU_CONST_CACHE_HS_15                   = 0x28F3C, // 
+  EG_SQ_ALU_CONST_CACHE_LS_0                    = 0x28F40, // 
+  EG_SQ_ALU_CONST_CACHE_LS_1                    = 0x28F44, // 
+  EG_SQ_ALU_CONST_CACHE_LS_2                    = 0x28F48, // 
+  EG_SQ_ALU_CONST_CACHE_LS_3                    = 0x28F4C, // 
+  EG_SQ_ALU_CONST_CACHE_LS_4                    = 0x28F50, // 
+  EG_SQ_ALU_CONST_CACHE_LS_5                    = 0x28F54, // 
+  EG_SQ_ALU_CONST_CACHE_LS_6                    = 0x28F58, // 
+  EG_SQ_ALU_CONST_CACHE_LS_7                    = 0x28F5C, // 
+  EG_SQ_ALU_CONST_CACHE_LS_8                    = 0x28F60, // 
+  EG_SQ_ALU_CONST_CACHE_LS_9                    = 0x28F64, // 
+  EG_SQ_ALU_CONST_CACHE_LS_10                   = 0x28F68, // 
+  EG_SQ_ALU_CONST_CACHE_LS_11                   = 0x28F6C, // 
+  EG_SQ_ALU_CONST_CACHE_LS_12                   = 0x28F70, // 
+  EG_SQ_ALU_CONST_CACHE_LS_13                   = 0x28F74, // 
+  EG_SQ_ALU_CONST_CACHE_LS_14                   = 0x28F78, // 
+  EG_SQ_ALU_CONST_CACHE_LS_15                   = 0x28F7C, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_PS_0              = 0x28140,
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_0              = 0x28F80, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_1              = 0x28F84, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_2              = 0x28F88, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_3              = 0x28F8C, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_4              = 0x28F90, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_5              = 0x28F94, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_6              = 0x28F98, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_7              = 0x28F9C, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_8              = 0x28FA0, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_9              = 0x28FA4, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_10             = 0x28FA8, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_11             = 0x28FAC, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_12             = 0x28FB0, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_13             = 0x28FB4, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_14             = 0x28FB8, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_HS_15             = 0x28FBC, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_0              = 0x28FC0, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_1              = 0x28FC4, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_2              = 0x28FC8, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_3              = 0x28FCC, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_4              = 0x28FD0, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_5              = 0x28FD4, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_6              = 0x28FD8, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_7              = 0x28FDC, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_8              = 0x28FE0, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_9              = 0x28FE4, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_10             = 0x28FE8, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_11             = 0x28FEC, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_12             = 0x28FF0, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_13             = 0x28FF4, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_14             = 0x28FF8, // 
+  EG_SQ_ALU_CONST_BUFFER_SIZE_LS_15             = 0x28FFC, // 
+
+/* Registers from SPI block: */        
+  EG_SPI_VS_OUT_ID_0                            = 0x2861C, // SAME 0x28614 
+  EG_SPI_VS_OUT_ID_1                            = 0x28620, // SAME 0x28618 
+  EG_SPI_VS_OUT_ID_2                            = 0x28624, // SAME 0x2861C 
+  EG_SPI_VS_OUT_ID_3                            = 0x28628, // SAME 0x28620 
+  EG_SPI_VS_OUT_ID_4                            = 0x2862C, // SAME 0x28624 
+  EG_SPI_VS_OUT_ID_5                            = 0x28630, // SAME 0x28628 
+  EG_SPI_VS_OUT_ID_6                            = 0x28634, // SAME 0x2862C 
+  EG_SPI_VS_OUT_ID_7                            = 0x28638, // SAME 0x28630 
+  EG_SPI_VS_OUT_ID_8                            = 0x2863C, // SAME 0x28634 
+  EG_SPI_VS_OUT_ID_9                            = 0x28640, // SAME 0x28638 
+  EG_SPI_PS_INPUT_CNTL_0                        = 0x28644, // SAME 
+  EG_SPI_PS_INPUT_CNTL_1                        = 0x28648, // SAME 
+  EG_SPI_PS_INPUT_CNTL_2                        = 0x2864C, // SAME 
+  EG_SPI_PS_INPUT_CNTL_3                        = 0x28650, // SAME 
+  EG_SPI_PS_INPUT_CNTL_4                        = 0x28654, // SAME 
+  EG_SPI_PS_INPUT_CNTL_5                        = 0x28658, // SAME 
+  EG_SPI_PS_INPUT_CNTL_6                        = 0x2865C, // SAME 
+  EG_SPI_PS_INPUT_CNTL_7                        = 0x28660, // SAME 
+  EG_SPI_PS_INPUT_CNTL_8                        = 0x28664, // SAME 
+  EG_SPI_PS_INPUT_CNTL_9                        = 0x28668, // SAME 
+  EG_SPI_PS_INPUT_CNTL_10                       = 0x2866C, // SAME 
+  EG_SPI_PS_INPUT_CNTL_11                       = 0x28670, // SAME 
+  EG_SPI_PS_INPUT_CNTL_12                       = 0x28674, // SAME 
+  EG_SPI_PS_INPUT_CNTL_13                       = 0x28678, // SAME 
+  EG_SPI_PS_INPUT_CNTL_14                       = 0x2867C, // SAME 
+  EG_SPI_PS_INPUT_CNTL_15                       = 0x28680, // SAME 
+  EG_SPI_PS_INPUT_CNTL_16                       = 0x28684, // SAME 
+  EG_SPI_PS_INPUT_CNTL_17                       = 0x28688, // SAME 
+  EG_SPI_PS_INPUT_CNTL_18                       = 0x2868C, // SAME 
+  EG_SPI_PS_INPUT_CNTL_19                       = 0x28690, // SAME 
+  EG_SPI_PS_INPUT_CNTL_20                       = 0x28694, // SAME 
+  EG_SPI_PS_INPUT_CNTL_21                       = 0x28698, // SAME 
+  EG_SPI_PS_INPUT_CNTL_22                       = 0x2869C, // SAME 
+  EG_SPI_PS_INPUT_CNTL_23                       = 0x286A0, // SAME 
+  EG_SPI_PS_INPUT_CNTL_24                       = 0x286A4, // SAME 
+  EG_SPI_PS_INPUT_CNTL_25                       = 0x286A8, // SAME 
+  EG_SPI_PS_INPUT_CNTL_26                       = 0x286AC, // SAME 
+  EG_SPI_PS_INPUT_CNTL_27                       = 0x286B0, // SAME 
+  EG_SPI_PS_INPUT_CNTL_28                       = 0x286B4, // SAME 
+  EG_SPI_PS_INPUT_CNTL_29                       = 0x286B8, // SAME 
+  EG_SPI_PS_INPUT_CNTL_30                       = 0x286BC, // SAME 
+  EG_SPI_PS_INPUT_CNTL_31                       = 0x286C0, // SAME 
+  EG_SPI_VS_OUT_CONFIG                          = 0x286C4, // SAME 
+  EG_SPI_THREAD_GROUPING                        = 0x286C8, // DIFF 
+  EG_SPI_PS_IN_CONTROL_0                        = 0x286CC, // SAME 
+  EG_SPI_PS_IN_CONTROL_1                        = 0x286D0, // SAME 
+  EG_SPI_INTERP_CONTROL_0                       = 0x286D4, // SAME 
+  EG_SPI_INPUT_Z                                = 0x286D8, // SAME 
+  EG_SPI_FOG_CNTL                               = 0x286DC, // SAME 
+  EG_SPI_BARYC_CNTL                             = 0x286E0, // 
+  EG_SPI_PS_IN_CONTROL_2                        = 0x286E4, // 
+  EG_SPI_COMPUTE_INPUT_CNTL                     = 0x286E8, // 
+  EG_SPI_COMPUTE_NUM_THREAD_X                   = 0x286EC, // 
+  EG_SPI_COMPUTE_NUM_THREAD_Y                   = 0x286F0, // 
+  EG_SPI_COMPUTE_NUM_THREAD_Z                   = 0x286F4, // 
+
+/* Registers from SX block: */ 
+  EG_SX_MISC                                    = 0x28350, // SAME 
+  EG_SX_SURFACE_SYNC                            = 0x28354, // DIFF 
+  EG_SX_ALPHA_TEST_CONTROL                      = 0x28410, // SAME 
+  EG_SX_ALPHA_REF                               = 0x28438, // SAME 
+
+/* Registers from DB block: */         
+  EG_DB_RENDER_CONTROL                          = 0x28000, // DIFF 0x28D0C 
+  EG_DB_COUNT_CONTROL                           = 0x28004, // 
+  EG_DB_DEPTH_VIEW                              = 0x28008, // DIFF 0x28004 
+  EG_DB_RENDER_OVERRIDE                         = 0x2800C, // DIFF 0x28D10 
+  EG_DB_RENDER_OVERRIDE2                        = 0x28010, // 
+  EG_DB_HTILE_DATA_BASE                         = 0x28014, // SAME 
+
+  EG_DB_STENCIL_CLEAR                           = 0x28028, // SAME 
+  EG_DB_DEPTH_CLEAR                             = 0x2802C, // SAME 
+
+  EG_DB_Z_INFO                                  = 0x28040, // 
+  EG_DB_STENCIL_INFO                            = 0x28044, // 
+  EG_DB_Z_READ_BASE                             = 0x28048, // 
+  EG_DB_STENCIL_READ_BASE                       = 0x2804C, // 
+  EG_DB_Z_WRITE_BASE                            = 0x28050, // 
+  EG_DB_STENCIL_WRITE_BASE                      = 0x28054, // 
+  EG_DB_DEPTH_SIZE                              = 0x28058, // DIFF 0x28000 
+  EG_DB_DEPTH_SLICE                             = 0x2805C, // 
+
+  EG_DB_STENCILREFMASK                          = 0x28430, // SAME 
+  EG_DB_STENCILREFMASK_BF                       = 0x28434, // SAME 
+  EG_DB_DEPTH_CONTROL                           = 0x28800, // SAME 
+  EG_DB_SHADER_CONTROL                          = 0x2880C, // DIFF 
+  EG_DB_HTILE_SURFACE                           = 0x28ABC, // SAME 0x28D24 
+  EG_DB_SRESULTS_COMPARE_STATE0                 = 0x28AC0, // SAME 0x28D28 
+  EG_DB_SRESULTS_COMPARE_STATE1                 = 0x28AC4, // SAME 0x28D2C 
+  EG_DB_PRELOAD_CONTROL                         = 0x28AC8, // SAME 0x28D30 
+  EG_DB_ALPHA_TO_MASK                           = 0x28B70, // SAME 0x28D44 
+
+/* Registers from CB block: */         
+  EG_CB_TARGET_MASK                             = 0x28238, // SAME 
+  EG_CB_SHADER_MASK                             = 0x2823C, // SAME 
+  EG_CB_BLEND_RED                               = 0x28414, // SAME 
+  EG_CB_BLEND_GREEN                             = 0x28418, // SAME 
+  EG_CB_BLEND_BLUE                              = 0x2841C, // SAME 
+  EG_CB_BLEND_ALPHA                             = 0x28420, // SAME 
+  EG_CB_BLEND0_CONTROL                          = 0x28780, // DIFF 
+  EG_CB_BLEND1_CONTROL                          = 0x28784, // DIFF 
+  EG_CB_BLEND2_CONTROL                          = 0x28788, // DIFF 
+  EG_CB_BLEND3_CONTROL                          = 0x2878C, // DIFF 
+  EG_CB_BLEND4_CONTROL                          = 0x28790, // DIFF 
+  EG_CB_BLEND5_CONTROL                          = 0x28794, // DIFF 
+  EG_CB_BLEND6_CONTROL                          = 0x28798, // DIFF 
+  EG_CB_BLEND7_CONTROL                          = 0x2879C, // DIFF 
+  EG_CB_COLOR_CONTROL                           = 0x28808, // DIFF 
+  EG_CB_IMMED0_BASE                             = 0x28B9C, // 
+  EG_CB_IMMED1_BASE                             = 0x28BA0, // 
+  EG_CB_IMMED2_BASE                             = 0x28BA4, // 
+  EG_CB_IMMED3_BASE                             = 0x28BA8, // 
+  EG_CB_IMMED4_BASE                             = 0x28BAC, // 
+  EG_CB_IMMED5_BASE                             = 0x28BB0, // 
+  EG_CB_IMMED6_BASE                             = 0x28BB4, // 
+  EG_CB_IMMED7_BASE                             = 0x28BB8, // 
+  EG_CB_IMMED8_BASE                             = 0x28BBC, // 
+  EG_CB_IMMED9_BASE                             = 0x28BC0, // 
+  EG_CB_IMMED10_BASE                            = 0x28BC4, // 
+  EG_CB_IMMED11_BASE                            = 0x28BC8, // 
+  EG_CB_CLRCMP_CONTROL                          = 0x28C40, // SAME 0x28C30 
+  EG_CB_CLRCMP_SRC                              = 0x28C44, // SAME 0x28C34 
+  EG_CB_CLRCMP_DST                              = 0x28C48, // SAME 0x28C38 
+  EG_CB_CLRCMP_MSK                              = 0x28C4C, // SAME 0x28C3C 
+  EG_CB_COLOR0_BASE                             = 0x28C60, // SAME 0x28040 
+  EG_CB_COLOR0_PITCH                            = 0x28C64, // 
+  EG_CB_COLOR0_SLICE                            = 0x28C68, // 
+  EG_CB_COLOR0_VIEW                             = 0x28C6C, // SAME 0x28080 
+  EG_CB_COLOR0_INFO                             = 0x28C70, // DIFF 0x280A0 
+  EG_CB_COLOR0_ATTRIB                           = 0x28C74, // 
+  EG_CB_COLOR0_DIM                              = 0x28C78, // 
+  EG_CB_COLOR0_CMASK                            = 0x28C7C, // 
+  EG_CB_COLOR0_CMASK_SLICE                      = 0x28C80, // 
+  EG_CB_COLOR0_FMASK                            = 0x28C84, // 
+  EG_CB_COLOR0_FMASK_SLICE                      = 0x28C88, // 
+  EG_CB_COLOR0_CLEAR_WORD0                      = 0x28C8C, // 
+  EG_CB_COLOR0_CLEAR_WORD1                      = 0x28C90, // 
+  EG_CB_COLOR0_CLEAR_WORD2                      = 0x28C94, // 
+  EG_CB_COLOR0_CLEAR_WORD3                      = 0x28C98, // 
+  EG_CB_COLOR1_BASE                             = 0x28C9C, // SAME 0x28044 
+  EG_CB_COLOR1_PITCH                            = 0x28CA0, // 
+  EG_CB_COLOR1_SLICE                            = 0x28CA4, // 
+  EG_CB_COLOR1_VIEW                             = 0x28CA8, // SAME 0x28084 
+  EG_CB_COLOR1_INFO                             = 0x28CAC, // DIFF 0x280A4 
+  EG_CB_COLOR1_ATTRIB                           = 0x28CB0, // 
+  EG_CB_COLOR1_DIM                              = 0x28CB4, // 
+  EG_CB_COLOR1_CMASK                            = 0x28CB8, // 
+  EG_CB_COLOR1_CMASK_SLICE                      = 0x28CBC, // 
+  EG_CB_COLOR1_FMASK                            = 0x28CC0, // 
+  EG_CB_COLOR1_FMASK_SLICE                      = 0x28CC4, // 
+  EG_CB_COLOR1_CLEAR_WORD0                      = 0x28CC8, // 
+  EG_CB_COLOR1_CLEAR_WORD1                      = 0x28CCC, // 
+  EG_CB_COLOR1_CLEAR_WORD2                      = 0x28CD0, // 
+  EG_CB_COLOR1_CLEAR_WORD3                      = 0x28CD4, // 
+  EG_CB_COLOR2_BASE                             = 0x28CD8, // SAME 0x28048 
+  EG_CB_COLOR2_PITCH                            = 0x28CDC, // 
+  EG_CB_COLOR2_SLICE                            = 0x28CE0, // 
+  EG_CB_COLOR2_VIEW                             = 0x28CE4, // SAME 0x28088 
+  EG_CB_COLOR2_INFO                             = 0x28CE8, // DIFF 0x280A8 
+  EG_CB_COLOR2_ATTRIB                           = 0x28CEC, // 
+  EG_CB_COLOR2_DIM                              = 0x28CF0, // 
+  EG_CB_COLOR2_CMASK                            = 0x28CF4, // 
+  EG_CB_COLOR2_CMASK_SLICE                      = 0x28CF8, // 
+  EG_CB_COLOR2_FMASK                            = 0x28CFC, // 
+  EG_CB_COLOR2_FMASK_SLICE                      = 0x28D00, // 
+  EG_CB_COLOR2_CLEAR_WORD0                      = 0x28D04, // 
+  EG_CB_COLOR2_CLEAR_WORD1                      = 0x28D08, // 
+  EG_CB_COLOR2_CLEAR_WORD2                      = 0x28D0C, // 
+  EG_CB_COLOR2_CLEAR_WORD3                      = 0x28D10, // 
+  EG_CB_COLOR3_BASE                             = 0x28D14, // SAME 0x2804C 
+  EG_CB_COLOR3_PITCH                            = 0x28D18, // 
+  EG_CB_COLOR3_SLICE                            = 0x28D1C, // 
+  EG_CB_COLOR3_VIEW                             = 0x28D20, // SAME 0x2808C 
+  EG_CB_COLOR3_INFO                             = 0x28D24, // DIFF 0x280AC 
+  EG_CB_COLOR3_ATTRIB                           = 0x28D28, // 
+  EG_CB_COLOR3_DIM                              = 0x28D2C, // 
+  EG_CB_COLOR3_CMASK                            = 0x28D30, // 
+  EG_CB_COLOR3_CMASK_SLICE                      = 0x28D34, // 
+  EG_CB_COLOR3_FMASK                            = 0x28D38, // 
+  EG_CB_COLOR3_FMASK_SLICE                      = 0x28D3C, // 
+  EG_CB_COLOR3_CLEAR_WORD0                      = 0x28D40, // 
+  EG_CB_COLOR3_CLEAR_WORD1                      = 0x28D44, // 
+  EG_CB_COLOR3_CLEAR_WORD2                      = 0x28D48, // 
+  EG_CB_COLOR3_CLEAR_WORD3                      = 0x28D4C, // 
+  EG_CB_COLOR4_BASE                             = 0x28D50, // SAME 0x28050 
+  EG_CB_COLOR4_PITCH                            = 0x28D54, // 
+  EG_CB_COLOR4_SLICE                            = 0x28D58, // 
+  EG_CB_COLOR4_VIEW                             = 0x28D5C, // SAME 0x28090 
+  EG_CB_COLOR4_INFO                             = 0x28D60, // DIFF 0x280B0 
+  EG_CB_COLOR4_ATTRIB                           = 0x28D64, // 
+  EG_CB_COLOR4_DIM                              = 0x28D68, // 
+  EG_CB_COLOR4_CMASK                            = 0x28D6C, // 
+  EG_CB_COLOR4_CMASK_SLICE                      = 0x28D70, // 
+  EG_CB_COLOR4_FMASK                            = 0x28D74, // 
+  EG_CB_COLOR4_FMASK_SLICE                      = 0x28D78, // 
+  EG_CB_COLOR4_CLEAR_WORD0                      = 0x28D7C, // 
+  EG_CB_COLOR4_CLEAR_WORD1                      = 0x28D80, // 
+  EG_CB_COLOR4_CLEAR_WORD2                      = 0x28D84, // 
+  EG_CB_COLOR4_CLEAR_WORD3                      = 0x28D88, // 
+  EG_CB_COLOR5_BASE                             = 0x28D8C, // SAME 0x28054 
+  EG_CB_COLOR5_PITCH                            = 0x28D90, // 
+  EG_CB_COLOR5_SLICE                            = 0x28D94, // 
+  EG_CB_COLOR5_VIEW                             = 0x28D98, // SAME 0x28094 
+  EG_CB_COLOR5_INFO                             = 0x28D9C, // DIFF 0x280B4 
+  EG_CB_COLOR5_ATTRIB                           = 0x28DA0, // 
+  EG_CB_COLOR5_DIM                              = 0x28DA4, // 
+  EG_CB_COLOR5_CMASK                            = 0x28DA8, // 
+  EG_CB_COLOR5_CMASK_SLICE                      = 0x28DAC, // 
+  EG_CB_COLOR5_FMASK                            = 0x28DB0, // 
+  EG_CB_COLOR5_FMASK_SLICE                      = 0x28DB4, // 
+  EG_CB_COLOR5_CLEAR_WORD0                      = 0x28DB8, // 
+  EG_CB_COLOR5_CLEAR_WORD1                      = 0x28DBC, // 
+  EG_CB_COLOR5_CLEAR_WORD2                      = 0x28DC0, // 
+  EG_CB_COLOR5_CLEAR_WORD3                      = 0x28DC4, // 
+  EG_CB_COLOR6_BASE                             = 0x28DC8, // SAME 0x28058 
+  EG_CB_COLOR6_PITCH                            = 0x28DCC, // 
+  EG_CB_COLOR6_SLICE                            = 0x28DD0, // 
+  EG_CB_COLOR6_VIEW                             = 0x28DD4, // SAME 0x28098 
+  EG_CB_COLOR6_INFO                             = 0x28DD8, // DIFF 0x280B8 
+  EG_CB_COLOR6_ATTRIB                           = 0x28DDC, //
+  EG_CB_COLOR6_DIM                              = 0x28DE0, //
+  EG_CB_COLOR6_CMASK                            = 0x28DE4, //
+  EG_CB_COLOR6_CMASK_SLICE                      = 0x28DE8, //
+  EG_CB_COLOR6_FMASK                            = 0x28DEC, //
+  EG_CB_COLOR6_FMASK_SLICE                      = 0x28DF0, //
+  EG_CB_COLOR6_CLEAR_WORD0                      = 0x28DF4, //
+  EG_CB_COLOR6_CLEAR_WORD1                      = 0x28DF8, //
+  EG_CB_COLOR6_CLEAR_WORD2                      = 0x28DFC, //
+  EG_CB_COLOR6_CLEAR_WORD3                      = 0x28E00, //
+  EG_CB_COLOR7_BASE                             = 0x28E04, // SAME 0x2805C 
+  EG_CB_COLOR7_PITCH                            = 0x28E08, // 
+  EG_CB_COLOR7_SLICE                            = 0x28E0C, // 
+  EG_CB_COLOR7_VIEW                             = 0x28E10, // SAME 0x2809C 
+  EG_CB_COLOR7_INFO                             = 0x28E14, // DIFF 0x280BC 
+  EG_CB_COLOR7_ATTRIB                           = 0x28E18, // 
+  EG_CB_COLOR7_DIM                              = 0x28E1C, // 
+  EG_CB_COLOR7_CMASK                            = 0x28E20, // 
+  EG_CB_COLOR7_CMASK_SLICE                      = 0x28E24, // 
+  EG_CB_COLOR7_FMASK                            = 0x28E28, // 
+  EG_CB_COLOR7_FMASK_SLICE                      = 0x28E2C, // 
+  EG_CB_COLOR7_CLEAR_WORD0                      = 0x28E30, // 
+  EG_CB_COLOR7_CLEAR_WORD1                      = 0x28E34, // 
+  EG_CB_COLOR7_CLEAR_WORD2                      = 0x28E38, // 
+  EG_CB_COLOR7_CLEAR_WORD3                      = 0x28E3C, // 
+  EG_CB_COLOR8_BASE                             = 0x28E40, // 
+  EG_CB_COLOR8_PITCH                            = 0x28E44, // 
+  EG_CB_COLOR8_SLICE                            = 0x28E48, // 
+  EG_CB_COLOR8_VIEW                             = 0x28E4C, // 
+  EG_CB_COLOR8_INFO                             = 0x28E50, // 
+  EG_CB_COLOR8_ATTRIB                           = 0x28E54, // 
+  EG_CB_COLOR8_DIM                              = 0x28E58, // 
+  EG_CB_COLOR9_BASE                             = 0x28E5C, // 
+  EG_CB_COLOR9_PITCH                            = 0x28E60, // 
+  EG_CB_COLOR9_SLICE                            = 0x28E64, // 
+  EG_CB_COLOR9_VIEW                             = 0x28E68, // 
+  EG_CB_COLOR9_INFO                             = 0x28E6C, // 
+  EG_CB_COLOR9_ATTRIB                           = 0x28E70, // 
+  EG_CB_COLOR9_DIM                              = 0x28E74, // 
+  EG_CB_COLOR10_BASE                            = 0x28E78, // 
+  EG_CB_COLOR10_PITCH                           = 0x28E7C, // 
+  EG_CB_COLOR10_SLICE                           = 0x28E80, // 
+  EG_CB_COLOR10_VIEW                            = 0x28E84, // 
+  EG_CB_COLOR10_INFO                            = 0x28E88, // 
+  EG_CB_COLOR10_ATTRIB                          = 0x28E8C, // 
+  EG_CB_COLOR10_DIM                             = 0x28E90, // 
+  EG_CB_COLOR11_BASE                            = 0x28E94, // 
+  EG_CB_COLOR11_PITCH                           = 0x28E98, // 
+  EG_CB_COLOR11_SLICE                           = 0x28E9C, // 
+  EG_CB_COLOR11_VIEW                            = 0x28EA0, // 
+  EG_CB_COLOR11_INFO                            = 0x28EA4, // 
+  EG_CB_COLOR11_ATTRIB                          = 0x28EA8, // 
+  EG_CB_COLOR11_DIM                             = 0x28EAC, // 
+
+/* Registers from CP block: */         
+  EG_COHER_DEST_BASE_0                          = 0x28248, // SAME 
+  EG_COHER_DEST_BASE_1                          = 0x2824C, // SAME 
+  EG_CP_PERFMON_CNTX_CNTL                       = 0x28358, // 
+
+/* Config: */
+  EG_SPI_CONFIG_CNTL                            = 0x9100,  // DIFF
+  EG_SPI_CONFIG_CNTL_1                          = 0x913C,  // DIFF
+  EG_CP_PERFMON_CNTL                            = 0x87FC,  // SAME
+  EG_SQ_MS_FIFO_SIZES                           = 0x8CF0,  // SAME
+  EG_SQ_CONFIG                                  = 0x8C00,  // DIFF
+  EG_SQ_GPR_RESOURCE_MGMT_1                     = 0x8C04,  // SAME
+  EG_SQ_GPR_RESOURCE_MGMT_2                     = 0x8C08,  // SAME
+  EG_SQ_THREAD_RESOURCE_MGMT                    = 0x8C18,  // SAME 0x8C0C,
+  EG_SQ_STACK_RESOURCE_MGMT_1                   = 0x8C20,  // SAME 0x8C10,
+  EG_SQ_STACK_RESOURCE_MGMT_2                   = 0x8C24,  // SAME 0x8C14,
+  EG_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ               = 0x8D8C,  // DIFF
+  EG_SQ_LDS_RESOURCE_MGMT                       = 0x8E2C,  //
+  EG_SQ_GPR_RESOURCE_MGMT_3                     = 0x8C0C,  //
+  EG_SQ_STACK_RESOURCE_MGMT_3                   = 0x8C28,  //
+  EG_SQ_THREAD_RESOURCE_MGMT_2                  = 0x8C1C,  //
+  EG_VGT_CACHE_INVALIDATION                     = 0x88C4,  // DIFF
+  EG_VGT_GS_VERTEX_REUSE                        = 0x88D4,  // SAME
+  EG_PA_SC_FORCE_EOV_MAX_CNTS                   = 0x8B24,  // SAME   
+  EG_PA_SC_LINE_STIPPLE_STATE                   = 0x8B10,  // SAME
+  EG_PA_CL_ENHANCE                              = 0x8A14,  // SAME
+
+/* Tex border color */
+  EG_TD_PS_BORDER_COLOR_RED                     = 0xA404,
+  EG_TD_PS_BORDER_COLOR_GREEN                   = 0xA408,
+  EG_TD_PS_BORDER_COLOR_BLUE                    = 0xA40C,
+  EG_TD_PS_BORDER_COLOR_ALPHA                   = 0xA410,
+
+/* const */
+  EG_SQ_VTX_CONSTANT_WORD0_0                    = 0x30000, //      0x38000   
+};
+
+#endif /* _EVERGREEN_OFF_H_ */
\ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/evergreen_oglprog.c b/src/mesa/drivers/dri/r600/evergreen_oglprog.c
new file mode 100644 (file)
index 0000000..9fe5232
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2008-2009  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#include <string.h>
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "program/program.h"
+
+#include "tnl/tnl.h"
+
+#include "r600_context.h"
+#include "r600_emit.h"
+
+#include "evergreen_oglprog.h"
+#include "evergreen_fragprog.h"
+#include "evergreen_vertprog.h"
+
+
+static void evergreen_freeVertProgCache(GLcontext *ctx, struct r700_vertex_program_cont *cache)
+{
+       struct evergreen_vertex_program *tmp, *vp = cache->progs;
+
+       while (vp) {
+               tmp = vp->next;
+               /* Release DMA region */
+               r600DeleteShader(ctx, vp->shaderbo);
+
+        if(NULL != vp->constbo0)
+        {
+                   r600DeleteShader(ctx, vp->constbo0);
+        }
+
+               /* Clean up */
+               Clean_Up_Assembler(&(vp->r700AsmCode));
+               Clean_Up_Shader(&(vp->r700Shader));
+               
+               _mesa_reference_vertprog(ctx, &vp->mesa_program, NULL);
+               free(vp);
+               vp = tmp;
+       }
+}
+
+static struct gl_program *evergreenNewProgram(GLcontext * ctx, 
+                                         GLenum target,
+                                                            GLuint id)
+{
+       struct gl_program *pProgram = NULL;
+
+    struct evergreen_vertex_program_cont *vpc;
+       struct evergreen_fragment_program *fp;
+
+       radeon_print(RADEON_SHADER, RADEON_VERBOSE,
+                       "%s %u, %u\n", __func__, target, id);
+
+    switch (target) 
+    {
+    case GL_VERTEX_STATE_PROGRAM_NV:
+    case GL_VERTEX_PROGRAM_ARB:            
+        vpc       = CALLOC_STRUCT(evergreen_vertex_program_cont);
+           pProgram = _mesa_init_vertex_program(ctx, 
+                                             &vpc->mesa_program,
+                                                                target, 
+                                             id);
+        
+           break;
+    case GL_FRAGMENT_PROGRAM_NV:
+    case GL_FRAGMENT_PROGRAM_ARB:
+               fp       = CALLOC_STRUCT(evergreen_fragment_program);
+               pProgram = _mesa_init_fragment_program(ctx, 
+                                               &fp->mesa_program,
+                                                                      target, 
+                                               id);
+        fp->translated = GL_FALSE;
+        fp->loaded     = GL_FALSE;
+
+        fp->shaderbo   = NULL;
+
+               fp->constbo0   = NULL;
+
+           break;
+    default:
+           _mesa_problem(ctx, "Bad target in evergreenNewProgram");
+    }
+
+       return pProgram;
+}
+
+static void evergreenDeleteProgram(GLcontext * ctx, struct gl_program *prog)
+{
+    struct evergreen_vertex_program_cont *vpc = (struct evergreen_vertex_program_cont *)prog;
+    struct evergreen_fragment_program * fp;
+
+       radeon_print(RADEON_SHADER, RADEON_VERBOSE,
+                       "%s %p\n", __func__, prog);
+
+    switch (prog->Target) 
+    {
+    case GL_VERTEX_STATE_PROGRAM_NV:
+    case GL_VERTEX_PROGRAM_ARB:            
+           evergreen_freeVertProgCache(ctx, vpc);
+           break;
+    case GL_FRAGMENT_PROGRAM_NV:
+    case GL_FRAGMENT_PROGRAM_ARB:
+               fp = (struct evergreen_fragment_program*)prog;
+        /* Release DMA region */
+
+        r600DeleteShader(ctx, fp->shaderbo);
+
+        if(NULL != fp->constbo0)
+        {
+                   r600DeleteShader(ctx, fp->constbo0);
+        }
+
+        /* Clean up */
+        Clean_Up_Assembler(&(fp->r700AsmCode));
+        Clean_Up_Shader(&(fp->r700Shader));
+           break;
+    default:
+           _mesa_problem(ctx, "Bad target in evergreenNewProgram");
+    }
+
+       _mesa_delete_program(ctx, prog);
+}
+
+static GLboolean
+evergreenProgramStringNotify(GLcontext * ctx, GLenum target, struct gl_program *prog)
+{
+       struct evergreen_vertex_program_cont *vpc = (struct evergreen_vertex_program_cont *)prog;
+       struct evergreen_fragment_program * fp = (struct evergreen_fragment_program*)prog;
+
+       switch (target) {
+       case GL_VERTEX_PROGRAM_ARB:
+               evergreen_freeVertProgCache(ctx, vpc);
+               vpc->progs = NULL;
+               break;
+       case GL_FRAGMENT_PROGRAM_ARB:
+               r600DeleteShader(ctx, fp->shaderbo);
+               
+        if(NULL != fp->constbo0)
+        {
+                   r600DeleteShader(ctx, fp->constbo0);
+                   fp->constbo0   = NULL;
+        }
+
+               Clean_Up_Assembler(&(fp->r700AsmCode));
+               Clean_Up_Shader(&(fp->r700Shader));
+               fp->translated = GL_FALSE;
+               fp->loaded     = GL_FALSE;
+               fp->shaderbo   = NULL;
+               break;
+       }
+               
+       /* XXX check if program is legal, within limits */
+       return GL_TRUE;
+}
+
+static GLboolean evergreenIsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog)
+{
+
+       return GL_TRUE;
+}
+
+void evergreenInitShaderFuncs(struct dd_function_table *functions)
+{
+       functions->NewProgram = evergreenNewProgram;
+       functions->DeleteProgram = evergreenDeleteProgram;
+       functions->ProgramStringNotify = evergreenProgramStringNotify;
+       functions->IsProgramNative = evergreenIsProgramNative;
+}
diff --git a/src/mesa/drivers/dri/r600/evergreen_oglprog.h b/src/mesa/drivers/dri/r600/evergreen_oglprog.h
new file mode 100644 (file)
index 0000000..1cf3e79
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008-2009  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com> 
+ */
+
+#ifndef _EVERGREEN_OGLPROG_H_
+#define _EVERGREEN_OGLPROG_H_
+#include "r600_context.h"
+
+extern void evergreenInitShaderFuncs(struct dd_function_table *functions);
+
+#endif /*_EVERGREEN_OGLPROG_H_*/
diff --git a/src/mesa/drivers/dri/r600/evergreen_render.c b/src/mesa/drivers/dri/r600/evergreen_render.c
new file mode 100644 (file)
index 0000000..85b2f9d
--- /dev/null
@@ -0,0 +1,937 @@
+/*
+ * Copyright (C) 2008-2010  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com> 
+ */
+
+#include "main/glheader.h"
+#include "main/state.h"
+#include "main/imports.h"
+#include "main/enums.h"
+#include "main/macros.h"
+#include "main/context.h"
+#include "main/dd.h"
+#include "main/simple_list.h"
+#include "main/api_arrayelt.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "vbo/vbo.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_vp_build.h"
+#include "tnl/t_context.h"
+#include "tnl/t_vertex.h"
+#include "vbo/vbo_context.h"
+
+#include "r600_context.h"
+#include "r600_cmdbuf.h"
+
+#include "evergreen_fragprog.h"
+#include "evergreen_vertprog.h"
+
+#include "evergreen_state.h"
+#include "evergreen_tex.h"
+
+#include "radeon_buffer_objects.h"
+#include "radeon_common_context.h"
+
+static unsigned int evergreenPrimitiveType(int prim) //same
+{
+    switch (prim & PRIM_MODE_MASK)
+    {
+    case GL_POINTS:
+        return DI_PT_POINTLIST;
+        break;
+    case GL_LINES:
+        return DI_PT_LINELIST;
+        break;
+    case GL_LINE_STRIP:
+        return DI_PT_LINESTRIP;
+        break;
+    case GL_LINE_LOOP:
+        return DI_PT_LINELOOP;
+        break;
+    case GL_TRIANGLES:
+        return DI_PT_TRILIST;
+        break;
+    case GL_TRIANGLE_STRIP:
+        return DI_PT_TRISTRIP;
+        break;
+    case GL_TRIANGLE_FAN:
+        return DI_PT_TRIFAN;
+        break;
+    case GL_QUADS:
+        return DI_PT_QUADLIST;
+        break;
+    case GL_QUAD_STRIP:
+        return DI_PT_QUADSTRIP;
+        break;
+    case GL_POLYGON:
+        return DI_PT_POLYGON;
+        break;
+    default:
+        assert(0);
+        return -1;
+        break;
+    }
+}
+
+static int evergreenNumVerts(int num_verts, int prim) //same
+{
+       int verts_off = 0;
+
+       switch (prim & PRIM_MODE_MASK) {
+       case GL_POINTS:
+               verts_off = 0;
+               break;
+       case GL_LINES:
+               verts_off = num_verts % 2;
+               break;
+       case GL_LINE_STRIP:
+               if (num_verts < 2)
+                       verts_off = num_verts;
+               break;
+       case GL_LINE_LOOP:
+               if (num_verts < 2)
+                       verts_off = num_verts;
+               break;
+       case GL_TRIANGLES:
+               verts_off = num_verts % 3;
+               break;
+       case GL_TRIANGLE_STRIP:
+               if (num_verts < 3)
+                       verts_off = num_verts;
+               break;
+       case GL_TRIANGLE_FAN:
+               if (num_verts < 3)
+                       verts_off = num_verts;
+               break;
+       case GL_QUADS:
+               verts_off = num_verts % 4;
+               break;
+       case GL_QUAD_STRIP:
+               if (num_verts < 4)
+                       verts_off = num_verts;
+               else
+                       verts_off = num_verts % 2;
+               break;
+       case GL_POLYGON:
+               if (num_verts < 3)
+                       verts_off = num_verts;
+               break;
+       default:
+               assert(0);
+               return -1;
+               break;
+       }
+
+       return num_verts - verts_off;
+}
+
+static void evergreenRunRenderPrimitive(GLcontext * ctx, int start, int end, int prim) //same
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    BATCH_LOCALS(&context->radeon);
+    int type, total_emit;
+    int num_indices;
+    uint32_t vgt_draw_initiator = 0;
+    uint32_t vgt_index_type     = 0;
+    uint32_t vgt_primitive_type = 0;
+    uint32_t vgt_num_indices    = 0;
+
+    type = evergreenPrimitiveType(prim);
+    num_indices = evergreenNumVerts(end - start, prim);
+
+    radeon_print(RADEON_RENDER, RADEON_TRACE,
+                "%s type %x num_indices %d\n",
+                __func__, type, num_indices);
+
+    if (type < 0 || num_indices <= 0)
+           return;
+
+    SETfield(vgt_primitive_type, type,
+            VGT_PRIMITIVE_TYPE__PRIM_TYPE_shift, VGT_PRIMITIVE_TYPE__PRIM_TYPE_mask);
+
+    SETfield(vgt_index_type, DI_INDEX_SIZE_32_BIT, INDEX_TYPE_shift, INDEX_TYPE_mask);
+
+    if(GL_TRUE != context->ind_buf.is_32bit)
+    {
+            SETfield(vgt_index_type, DI_INDEX_SIZE_16_BIT, INDEX_TYPE_shift, INDEX_TYPE_mask);
+    }
+
+    vgt_num_indices = num_indices;
+    SETfield(vgt_draw_initiator, DI_SRC_SEL_DMA, SOURCE_SELECT_shift, SOURCE_SELECT_mask);
+    SETfield(vgt_draw_initiator, DI_MAJOR_MODE_0, MAJOR_MODE_shift, MAJOR_MODE_mask);
+
+    total_emit =   3  /* VGT_PRIMITIVE_TYPE */
+                + 2  /* VGT_INDEX_TYPE */
+                + 2  /* NUM_INSTANCES */
+                + 5 + 2; /* DRAW_INDEX */
+
+    BEGIN_BATCH_NO_AUTOSTATE(total_emit);
+    // prim
+    R600_OUT_BATCH_REGSEQ(VGT_PRIMITIVE_TYPE, 1);
+    R600_OUT_BATCH(vgt_primitive_type);
+    // index type
+    R600_OUT_BATCH(CP_PACKET3(R600_IT_INDEX_TYPE, 0));
+    R600_OUT_BATCH(vgt_index_type);
+    // num instances
+    R600_OUT_BATCH(CP_PACKET3(R600_IT_NUM_INSTANCES, 0));
+    R600_OUT_BATCH(1);
+    // draw packet
+    R600_OUT_BATCH(CP_PACKET3(R600_IT_DRAW_INDEX, 3));
+    R600_OUT_BATCH(context->ind_buf.bo_offset);
+    R600_OUT_BATCH(0);
+    R600_OUT_BATCH(vgt_num_indices);
+    R600_OUT_BATCH(vgt_draw_initiator);
+    R600_OUT_BATCH_RELOC(context->ind_buf.bo_offset,
+                        context->ind_buf.bo,
+                        context->ind_buf.bo_offset,
+                        RADEON_GEM_DOMAIN_GTT, 0, 0);
+    END_BATCH();
+    COMMIT_BATCH();
+}
+
+static void evergreenRunRenderPrimitiveImmediate(GLcontext * ctx, int start, int end, int prim) //same
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    BATCH_LOCALS(&context->radeon);
+    int type, i;
+    uint32_t num_indices, total_emit = 0;
+    uint32_t vgt_draw_initiator = 0;
+    uint32_t vgt_index_type     = 0;
+    uint32_t vgt_primitive_type = 0;
+    uint32_t vgt_num_indices    = 0;
+
+    type = evergreenPrimitiveType(prim);
+    num_indices = evergreenNumVerts(end - start, prim);
+
+    radeon_print(RADEON_RENDER, RADEON_TRACE,
+                "%s type %x num_indices %d\n",
+                __func__, type, num_indices);
+
+    if (type < 0 || num_indices <= 0)
+           return;
+
+    SETfield(vgt_primitive_type, type,
+            VGT_PRIMITIVE_TYPE__PRIM_TYPE_shift, VGT_PRIMITIVE_TYPE__PRIM_TYPE_mask);
+
+    if (num_indices > 0xffff)
+    {
+           SETfield(vgt_index_type, DI_INDEX_SIZE_32_BIT, INDEX_TYPE_shift, INDEX_TYPE_mask);
+    }
+    else
+    {
+            SETfield(vgt_index_type, DI_INDEX_SIZE_16_BIT, INDEX_TYPE_shift, INDEX_TYPE_mask);
+    }
+
+    vgt_num_indices = num_indices;
+    SETfield(vgt_draw_initiator, DI_MAJOR_MODE_0, MAJOR_MODE_shift, MAJOR_MODE_mask);
+
+    if (start == 0)
+    {
+       SETfield(vgt_draw_initiator, DI_SRC_SEL_AUTO_INDEX, SOURCE_SELECT_shift, SOURCE_SELECT_mask);
+    }
+    else
+    {
+       if (num_indices > 0xffff)
+       {
+               total_emit += num_indices;
+       }
+       else
+       {
+               total_emit += (num_indices + 1) / 2;
+       }
+       SETfield(vgt_draw_initiator, DI_SRC_SEL_IMMEDIATE, SOURCE_SELECT_shift, SOURCE_SELECT_mask);
+    }
+
+    total_emit +=   3 /* VGT_PRIMITIVE_TYPE */
+                 + 2 /* VGT_INDEX_TYPE */
+                 + 2 /* NUM_INSTANCES */
+                 + 3; /* DRAW */              
+
+    BEGIN_BATCH_NO_AUTOSTATE(total_emit);
+    // prim
+    R600_OUT_BATCH_REGSEQ(VGT_PRIMITIVE_TYPE, 1);
+    R600_OUT_BATCH(vgt_primitive_type);
+    // index type
+    R600_OUT_BATCH(CP_PACKET3(R600_IT_INDEX_TYPE, 0));
+    R600_OUT_BATCH(vgt_index_type);
+    // num instances
+    R600_OUT_BATCH(CP_PACKET3(R600_IT_NUM_INSTANCES, 0));
+    R600_OUT_BATCH(1);
+    // draw packet
+    if(start == 0)
+    {
+        R600_OUT_BATCH(CP_PACKET3(R600_IT_DRAW_INDEX_AUTO, 1));
+        R600_OUT_BATCH(vgt_num_indices);
+        R600_OUT_BATCH(vgt_draw_initiator);
+    }
+    else
+    {
+       if (num_indices > 0xffff)
+        {
+           R600_OUT_BATCH(CP_PACKET3(R600_IT_DRAW_INDEX_IMMD, (num_indices + 1)));
+           R600_OUT_BATCH(vgt_num_indices);
+           R600_OUT_BATCH(vgt_draw_initiator);
+           for (i = start; i < (start + num_indices); i++)
+           {
+               R600_OUT_BATCH(i);
+           }
+       }
+       else
+        {
+           R600_OUT_BATCH(CP_PACKET3(R600_IT_DRAW_INDEX_IMMD, (((num_indices + 1) / 2) + 1)));
+           R600_OUT_BATCH(vgt_num_indices);
+           R600_OUT_BATCH(vgt_draw_initiator);
+           for (i = start; i < (start + num_indices); i += 2)
+           {
+               if ((i + 1) == (start + num_indices))
+               {
+                   R600_OUT_BATCH(i);
+               }
+               else
+               {
+                   R600_OUT_BATCH(((i + 1) << 16) | (i));
+               }
+           }
+       }
+    }
+
+    END_BATCH();
+    COMMIT_BATCH();
+}
+
+#define CONVERT( TYPE, MACRO ) do {            \
+       GLuint i, j, sz;                                \
+       sz = input->Size;                               \
+       if (input->Normalized) {                        \
+               for (i = 0; i < count; i++) {           \
+                       const TYPE *in = (TYPE *)src_ptr;               \
+                       for (j = 0; j < sz; j++) {              \
+                               *dst_ptr++ = MACRO(*in);                \
+                               in++;                           \
+                       }                                       \
+                       src_ptr += stride;                      \
+               }                                               \
+       } else {                                        \
+               for (i = 0; i < count; i++) {           \
+                       const TYPE *in = (TYPE *)src_ptr;               \
+                       for (j = 0; j < sz; j++) {              \
+                               *dst_ptr++ = (GLfloat)(*in);            \
+                               in++;                           \
+                       }                                       \
+                       src_ptr += stride;                      \
+               }                                               \
+       }                                               \
+} while (0)
+
+/**
+ * Convert attribute data type to float
+ * If the attribute uses named buffer object replace the bo with newly allocated bo
+ */
+static void evergreenConvertAttrib(GLcontext *ctx, int count, 
+                              const struct gl_client_array *input, 
+                              struct StreamDesc *attr)
+{
+    context_t *context = R700_CONTEXT(ctx);
+    const GLvoid *src_ptr;
+    GLboolean mapped_named_bo = GL_FALSE;
+    GLfloat *dst_ptr;
+    GLuint stride;
+
+    stride = (input->StrideB == 0) ? evergreen_getTypeSize(input->Type) * input->Size : input->StrideB;
+
+    /* Convert value for first element only */
+    if (input->StrideB == 0)
+    {
+        count = 1;
+    }
+
+    if (input->BufferObj->Name) 
+    {
+        if (!input->BufferObj->Pointer) 
+        {
+            ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY_ARB, input->BufferObj);
+            mapped_named_bo = GL_TRUE;
+        }
+
+        src_ptr = ADD_POINTERS(input->BufferObj->Pointer, input->Ptr);
+    } 
+    else 
+    {
+        src_ptr = input->Ptr;
+    }
+
+    radeonAllocDmaRegion(&context->radeon, &attr->bo, &attr->bo_offset, 
+                         sizeof(GLfloat) * input->Size * count, 32);
+
+    radeon_bo_map(attr->bo, 1);
+
+    dst_ptr = (GLfloat *)ADD_POINTERS(attr->bo->ptr, attr->bo_offset);
+
+    assert(src_ptr != NULL);
+
+    switch (input->Type) 
+    {
+        case GL_DOUBLE:
+            CONVERT(GLdouble, (GLfloat));
+            break;
+        case GL_UNSIGNED_INT:
+            CONVERT(GLuint, UINT_TO_FLOAT);
+            break;
+        case GL_INT:
+            CONVERT(GLint, INT_TO_FLOAT);
+            break;
+        case GL_UNSIGNED_SHORT:
+            CONVERT(GLushort, USHORT_TO_FLOAT);
+            break;
+        case GL_SHORT:
+            CONVERT(GLshort, SHORT_TO_FLOAT);
+            break;
+        case GL_UNSIGNED_BYTE:
+            assert(input->Format != GL_BGRA);
+            CONVERT(GLubyte, UBYTE_TO_FLOAT);
+            break;
+        case GL_BYTE:
+            CONVERT(GLbyte, BYTE_TO_FLOAT);
+            break;
+        default:
+            assert(0);
+            break;
+    }
+
+    radeon_bo_unmap(attr->bo);
+
+    if (mapped_named_bo) 
+    {
+        ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, input->BufferObj);
+    }
+}
+
+static void evergreenFixupIndexBuffer(GLcontext *ctx, const struct _mesa_index_buffer *mesa_ind_buf)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    GLvoid *src_ptr;
+    GLuint *out;
+    int i;
+    GLboolean mapped_named_bo = GL_FALSE;
+
+    if (mesa_ind_buf->obj->Name && !mesa_ind_buf->obj->Pointer)
+    {
+        ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY_ARB, mesa_ind_buf->obj);
+        mapped_named_bo = GL_TRUE;
+        assert(mesa_ind_buf->obj->Pointer != NULL);
+    }
+    src_ptr = ADD_POINTERS(mesa_ind_buf->obj->Pointer, mesa_ind_buf->ptr);
+
+    if (mesa_ind_buf->type == GL_UNSIGNED_BYTE)
+    {
+        GLuint size = sizeof(GLushort) * ((mesa_ind_buf->count + 1) & ~1);
+        GLubyte *in = (GLubyte *)src_ptr;
+
+       radeonAllocDmaRegion(&context->radeon, &context->ind_buf.bo,
+                            &context->ind_buf.bo_offset, size, 4);
+
+       radeon_bo_map(context->ind_buf.bo, 1);
+       assert(context->ind_buf.bo->ptr != NULL);
+       out = (GLuint *)ADD_POINTERS(context->ind_buf.bo->ptr, context->ind_buf.bo_offset);
+
+        for (i = 0; i + 1 < mesa_ind_buf->count; i += 2)
+        {
+            *out++ = in[i] | in[i + 1] << 16;
+        }
+
+        if (i < mesa_ind_buf->count)
+        {
+            *out++ = in[i];
+        }
+
+       radeon_bo_unmap(context->ind_buf.bo);
+#if MESA_BIG_ENDIAN
+    }
+    else
+    { /* if (mesa_ind_buf->type == GL_UNSIGNED_SHORT) */
+        GLushort *in = (GLushort *)src_ptr;
+        GLuint size = sizeof(GLushort) * ((mesa_ind_buf->count + 1) & ~1);
+
+       radeonAllocDmaRegion(&context->radeon, &context->ind_buf.bo,
+                            &context->ind_buf.bo_offset, size, 4);
+
+       radeon_bo_map(context->ind_buf.bo, 1);
+       assert(context->ind_buf.bo->ptr != NULL);
+       out = (GLuint *)ADD_POINTERS(context->ind_buf.bo->ptr, context->ind_buf.bo_offset);
+
+        for (i = 0; i + 1 < mesa_ind_buf->count; i += 2)
+        {
+            *out++ = in[i] | in[i + 1] << 16;
+        }
+
+        if (i < mesa_ind_buf->count)
+        {
+            *out++ = in[i];
+        }
+       radeon_bo_unmap(context->ind_buf.bo);
+#endif
+    }
+
+    context->ind_buf.is_32bit = GL_FALSE;
+    context->ind_buf.count = mesa_ind_buf->count;
+
+    if (mapped_named_bo)
+    {
+        ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, mesa_ind_buf->obj);
+    }
+}
+
+static GLboolean evergreen_check_fallbacks(GLcontext *ctx) //same
+{
+       if (ctx->RenderMode != GL_RENDER)
+               return GL_TRUE;
+
+       return GL_FALSE;
+}
+
+/* start 3d, idle, cb/db flush */
+#define PRE_EMIT_STATE_BUFSZ 5 + 5 + 14
+
+static GLuint evergreenPredictRenderSize(GLcontext* ctx,
+                                   const struct _mesa_prim *prim,
+                                   const struct _mesa_index_buffer *ib,
+                                   GLuint nr_prims)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    GLboolean flushed;
+    GLuint dwords, i;
+    GLuint state_size;
+
+    dwords = PRE_EMIT_STATE_BUFSZ;
+    if (ib)
+           dwords += nr_prims * 14;
+    else {
+           for (i = 0; i < nr_prims; ++i)
+           {
+                   if (prim[i].start == 0)
+                           dwords += 10;
+                   else if (prim[i].count > 0xffff)
+                           dwords += prim[i].count + 10;
+                   else
+                           dwords += ((prim[i].count + 1) / 2) + 10;
+           }
+    }
+
+    state_size = radeonCountStateEmitSize(&context->radeon);
+    flushed = rcommonEnsureCmdBufSpace(&context->radeon,
+                                      dwords + state_size,
+                                      __FUNCTION__);
+    if (flushed)
+           dwords += radeonCountStateEmitSize(&context->radeon);
+    else
+           dwords += state_size;
+
+    radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s: total prediction size is %d.\n", __FUNCTION__, dwords);
+    return dwords;
+
+}
+
+static void evergreenSetupIndexBuffer(GLcontext *ctx, const struct _mesa_index_buffer *mesa_ind_buf)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+
+    if (!mesa_ind_buf) {
+        context->ind_buf.bo = NULL;
+        return;
+    }
+
+#if MESA_BIG_ENDIAN
+    if (mesa_ind_buf->type == GL_UNSIGNED_INT)
+#else
+    if (mesa_ind_buf->type != GL_UNSIGNED_BYTE)
+#endif
+    {
+        const GLvoid *src_ptr;
+        GLvoid *dst_ptr;
+        GLboolean mapped_named_bo = GL_FALSE;
+
+        if (mesa_ind_buf->obj->Name && !mesa_ind_buf->obj->Pointer)
+        {
+               ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY_ARB, mesa_ind_buf->obj);
+               assert(mesa_ind_buf->obj->Pointer != NULL);
+               mapped_named_bo = GL_TRUE;
+        }
+
+        src_ptr = ADD_POINTERS(mesa_ind_buf->obj->Pointer, mesa_ind_buf->ptr);
+
+        const GLuint size = mesa_ind_buf->count * getTypeSize(mesa_ind_buf->type);
+
+       radeonAllocDmaRegion(&context->radeon, &context->ind_buf.bo,
+                            &context->ind_buf.bo_offset, size, 4);
+       radeon_bo_map(context->ind_buf.bo, 1);
+       assert(context->ind_buf.bo->ptr != NULL);
+       dst_ptr = ADD_POINTERS(context->ind_buf.bo->ptr, context->ind_buf.bo_offset);
+
+        memcpy(dst_ptr, src_ptr, size);
+
+       radeon_bo_unmap(context->ind_buf.bo);
+        context->ind_buf.is_32bit = (mesa_ind_buf->type == GL_UNSIGNED_INT);
+        context->ind_buf.count = mesa_ind_buf->count;
+
+        if (mapped_named_bo)
+        {
+               ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, mesa_ind_buf->obj);
+        }
+    }
+    else
+    {
+           evergreenFixupIndexBuffer(ctx, mesa_ind_buf);
+    }
+}
+
+static void evergreenAlignDataToDword(GLcontext *ctx, 
+                                 const struct gl_client_array *input, 
+                                 int count, 
+                                 struct StreamDesc *attr)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    const int dst_stride = (input->StrideB + 3) & ~3;
+    const int size = getTypeSize(input->Type) * input->Size * count;
+    GLboolean mapped_named_bo = GL_FALSE;
+
+    radeonAllocDmaRegion(&context->radeon, &attr->bo, &attr->bo_offset, size, 32);
+
+    radeon_bo_map(attr->bo, 1);
+
+    if (!input->BufferObj->Pointer) 
+    {
+        ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY_ARB, input->BufferObj);
+        mapped_named_bo = GL_TRUE;
+    }
+
+    {
+        GLvoid *src_ptr = ADD_POINTERS(input->BufferObj->Pointer, input->Ptr);
+        GLvoid *dst_ptr = ADD_POINTERS(attr->bo->ptr, attr->bo_offset);
+        int i;
+
+        for (i = 0; i < count; ++i) 
+        {
+            memcpy(dst_ptr, src_ptr, input->StrideB);
+            src_ptr += input->StrideB;
+            dst_ptr += dst_stride;
+        }
+    }
+
+    radeon_bo_unmap(attr->bo);
+    if (mapped_named_bo) 
+    {
+        ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, input->BufferObj);
+    }
+
+    attr->stride = dst_stride;
+}
+
+static void evergreenSetupStreams(GLcontext *ctx, const struct gl_client_array *input[], int count)
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+    GLuint stride;
+    int ret;
+    int i, index;
+
+    EVERGREEN_STATECHANGE(context, vtx);
+
+    for(index = 0; index < context->nNumActiveAos; index++) 
+    {
+        struct radeon_aos *aos = &context->radeon.tcl.aos[index];
+        i = context->stream_desc[index].element;
+
+        stride = (input[i]->StrideB == 0) ? getTypeSize(input[i]->Type) * input[i]->Size : input[i]->StrideB;
+
+        if (input[i]->Type == GL_DOUBLE || input[i]->Type == GL_UNSIGNED_INT || input[i]->Type == GL_INT ||
+#if MESA_BIG_ENDIAN
+            getTypeSize(input[i]->Type) != 4 || 
+#endif
+            stride < 4) 
+        {
+            evergreenConvertAttrib(ctx, count, input[i], &context->stream_desc[index]);
+        } 
+        else 
+        {
+            if (input[i]->BufferObj->Name) 
+            {
+                if (stride % 4 != 0) 
+                {
+                    assert(((intptr_t) input[i]->Ptr) % input[i]->StrideB == 0);
+                    evergreenAlignDataToDword(ctx, input[i], count, &context->stream_desc[index]);
+                    context->stream_desc[index].is_named_bo = GL_FALSE;
+                } 
+                else 
+                {
+                    context->stream_desc[index].stride = input[i]->StrideB;
+                    context->stream_desc[index].bo_offset = (intptr_t) input[i]->Ptr;
+                    context->stream_desc[index].bo = get_radeon_buffer_object(input[i]->BufferObj)->bo;
+                    context->stream_desc[index].is_named_bo = GL_TRUE;
+                }
+            } 
+            else 
+            {
+                int size;
+                int local_count = count;
+                uint32_t *dst;
+
+                if (input[i]->StrideB == 0) 
+                {
+                    size = getTypeSize(input[i]->Type) * input[i]->Size;
+                    local_count = 1;
+                } 
+                else 
+                {
+                    size = getTypeSize(input[i]->Type) * input[i]->Size * local_count;
+                }
+
+                radeonAllocDmaRegion(&context->radeon, &context->stream_desc[index].bo, 
+                                     &context->stream_desc[index].bo_offset, size, 32);
+
+                radeon_bo_map(context->stream_desc[index].bo, 1);
+                assert(context->stream_desc[index].bo->ptr != NULL);
+
+
+                dst = (uint32_t *)ADD_POINTERS(context->stream_desc[index].bo->ptr, 
+                                               context->stream_desc[index].bo_offset);
+
+                switch (context->stream_desc[index].dwords) 
+                {
+                case 1:                       
+                    radeonEmitVec4(dst, input[i]->Ptr, input[i]->StrideB, local_count);
+                    break;
+                case 2:                     
+                    radeonEmitVec8(dst, input[i]->Ptr, input[i]->StrideB, local_count); 
+                    break;
+                case 3:                     
+                    radeonEmitVec12(dst, input[i]->Ptr, input[i]->StrideB, local_count); 
+                    break;
+                case 4:                     
+                    radeonEmitVec16(dst, input[i]->Ptr, input[i]->StrideB, local_count); 
+                    break;
+                default: 
+                    assert(0); 
+                    break;
+                }
+
+                radeon_bo_unmap(context->stream_desc[index].bo);
+            }
+        }
+
+        aos->count = context->stream_desc[index].stride == 0 ? 1 : count;
+        aos->stride = context->stream_desc[index].stride / sizeof(float);
+        aos->components = context->stream_desc[index].dwords;
+        aos->bo = context->stream_desc[index].bo;
+        aos->offset = context->stream_desc[index].bo_offset;
+
+        if(context->stream_desc[index].is_named_bo) 
+        {
+            radeon_cs_space_add_persistent_bo(context->radeon.cmdbuf.cs, 
+                                              context->stream_desc[index].bo, 
+                                              RADEON_GEM_DOMAIN_GTT, 0);
+        }
+    }
+
+    ret = radeon_cs_space_check_with_bo(context->radeon.cmdbuf.cs, 
+                                        first_elem(&context->radeon.dma.reserved)->bo, 
+                                        RADEON_GEM_DOMAIN_GTT, 0);    
+}
+
+static void evergreenFreeData(GLcontext *ctx)
+{
+    /* Need to zero tcl.aos[n].bo and tcl.elt_dma_bo
+     * to prevent double unref in radeonReleaseArrays
+     * called during context destroy
+     */
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+
+    int i;
+
+    for (i = 0; i < context->nNumActiveAos; i++)
+    {
+        if (!context->stream_desc[i].is_named_bo)
+        {
+               radeon_bo_unref(context->stream_desc[i].bo);
+        }
+        context->radeon.tcl.aos[i].bo = NULL;
+    }
+
+    if(context->vp_Constbo != NULL)
+    {
+        radeon_bo_unref(context->vp_Constbo);
+        context->vp_Constbo = NULL;
+    }
+    if(context->fp_Constbo != NULL)
+    {
+        radeon_bo_unref(context->fp_Constbo);
+        context->fp_Constbo = NULL;
+    }
+
+    if (context->ind_buf.bo != NULL)
+    {
+            radeon_bo_unref(context->ind_buf.bo);
+    }
+}
+
+static GLboolean evergreenTryDrawPrims(GLcontext *ctx,
+                                 const struct gl_client_array *arrays[],
+                                 const struct _mesa_prim *prim,
+                                 GLuint nr_prims,
+                                 const struct _mesa_index_buffer *ib,
+                                 GLuint min_index,
+                                 GLuint max_index )
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    radeonContextPtr radeon = &context->radeon;
+    GLuint i, id = 0;
+    struct radeon_renderbuffer *rrb;
+
+    if (ctx->NewState)
+        _mesa_update_state( ctx );
+
+    if (evergreen_check_fallbacks(ctx))
+           return GL_FALSE;
+
+    _tnl_UpdateFixedFunctionProgram(ctx);
+    evergreenSetVertexFormat(ctx, arrays, max_index + 1);
+
+
+    /* shaders need to be updated before buffers are validated */
+    evergreenUpdateShaders(ctx);
+    if (!evergreenValidateBuffers(ctx))
+           return GL_FALSE;
+
+    /* always emit CB base to prevent
+     * lock ups on some chips.
+     */
+    EVERGREEN_STATECHANGE(context, cb);
+    /* mark vtx as dirty since it changes per-draw */
+    EVERGREEN_STATECHANGE(context, vtx);
+
+    evergreenSetScissor(context);
+
+    evergreenSetupVertexProgram(ctx);
+    evergreenSetupFragmentProgram(ctx);
+    evergreenUpdateShaderStates(ctx);
+
+    GLuint emit_end = evergreenPredictRenderSize(ctx, prim, ib, nr_prims)
+                    + context->radeon.cmdbuf.cs->cdw;
+
+    /* evergreenPredictRenderSize will call radeonReleaseDmaRegions, so update VP/FP const buf after it. */
+    evergreenSetupVPconstants(ctx);
+    evergreenSetupFPconstants(ctx);
+
+    evergreenSetupIndexBuffer(ctx, ib);
+
+    evergreenSetupStreams(ctx, arrays, max_index + 1);
+
+    radeonEmitState(radeon);
+
+    radeon_debug_add_indent();
+
+    for (i = 0; i < nr_prims; ++i)
+    {
+           if (context->ind_buf.bo)
+                   evergreenRunRenderPrimitive(ctx,
+                                          prim[i].start,
+                                          prim[i].start + prim[i].count,
+                                          prim[i].mode);
+           else
+                   evergreenRunRenderPrimitiveImmediate(ctx,
+                                                   prim[i].start,
+                                                   prim[i].start + prim[i].count,
+                                                   prim[i].mode);
+    }
+
+    radeon_debug_remove_indent();
+
+    /* Flush render op cached for last several quads. */
+    /* XXX drm should handle this in fence submit */
+
+    //evergreeWaitForIdleClean(context);
+
+    rrb = radeon_get_colorbuffer(&context->radeon);
+    if (rrb && rrb->bo)
+           r700SyncSurf(context, rrb->bo, 0, RADEON_GEM_DOMAIN_VRAM,
+                        CB_ACTION_ENA_bit | (1 << (id + 6)));
+
+    rrb = radeon_get_depthbuffer(&context->radeon);
+    if (rrb && rrb->bo)
+           r700SyncSurf(context, rrb->bo, 0, RADEON_GEM_DOMAIN_VRAM,
+                        DB_ACTION_ENA_bit | DB_DEST_BASE_ENA_bit);
+
+    evergreenFreeData(ctx);
+
+    if (emit_end < context->radeon.cmdbuf.cs->cdw)
+    {
+        WARN_ONCE("Rendering was %d commands larger than predicted size."
+            " We might overflow  command buffer.\n", context->radeon.cmdbuf.cs->cdw - emit_end);
+    }
+
+    return GL_TRUE;
+}
+
+static void evergreenDrawPrims(GLcontext *ctx,
+                         const struct gl_client_array *arrays[],
+                         const struct _mesa_prim *prim,
+                         GLuint nr_prims,
+                         const struct _mesa_index_buffer *ib,
+                         GLboolean index_bounds_valid,
+                         GLuint min_index,
+                         GLuint max_index)
+{
+       GLboolean retval = GL_FALSE;
+
+       /* This check should get folded into just the places that
+        * min/max index are really needed.
+        */
+       if (!index_bounds_valid) {
+               vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
+       }
+
+       if (min_index) {
+               vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, min_index, max_index, evergreenDrawPrims );
+               return;
+       }
+
+       /* Make an attempt at drawing */
+       retval = evergreenTryDrawPrims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
+
+       /* If failed run tnl pipeline - it should take care of fallbacks */
+       if (!retval) {
+               _swsetup_Wakeup(ctx);
+               _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
+       }
+}
+
+void evergreenInitDraw(GLcontext *ctx)
+{
+       struct vbo_context *vbo = vbo_context(ctx);
+
+       /* to be enabled */
+       vbo->draw_prims = evergreenDrawPrims;
+}
+
+
diff --git a/src/mesa/drivers/dri/r600/evergreen_sq.h b/src/mesa/drivers/dri/r600/evergreen_sq.h
new file mode 100644 (file)
index 0000000..b1a536e
--- /dev/null
@@ -0,0 +1,735 @@
+/*
+ * Copyright (C) 2008-2010  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com> 
+ */
+
+#ifndef _EVERGREEN_SQ_H_
+#define _EVERGREEN_SQ_H_
+
+enum{
+//CF
+    EG_CF_WORD0__ADDR_shift          = 0,
+    EG_CF_WORD0__ADDR_mask           = 0xFFFFFF,
+    EG_CF_WORD0__JUMPTABLE_SEL_shift = 24,
+    EG_CF_WORD0__JUMPTABLE_SEL_mask  = 0x7 << 24,
+
+    EG_CF_WORD1__POP_COUNT_shift     = 0, //3 bits
+    EG_CF_WORD1__POP_COUNT_mask      = 0x7,
+    EG_CF_WORD1__CF_CONST_shift      = 3, //5 bits
+    EG_CF_WORD1__CF_CONST_mask       = 0x1F << 3,
+    EG_CF_WORD1__COND_shift          = 8, //2 bits
+    EG_CF_WORD1__COND_mask           = 0x3 << 8,
+    EG_CF_WORD1__COUNT_shift         = 10,//6 bits
+    EG_CF_WORD1__COUNT_mask          = 0x3F << 10,
+    EG_CF_WORD1__reserved_shift      = 16,//4 bits
+    EG_CF_WORD1__VPM_shift           = 20,//1 bit
+    EG_CF_WORD1__VPM_bit             = 1 << 20,
+    EG_CF_WORD1__EOP_shift           = 21,//1 bit
+    EG_CF_WORD1__EOP_bit             = 1 << 21,
+    EG_CF_WORD1__CF_INST_shift       = 22,//8 bits
+    EG_CF_WORD1__CF_INST_mask        = 0xFF << 22,
+    EG_CF_WORD1__WQM_shift           = 30,//1 bit
+    EG_CF_WORD1__WQM_bit             = 1 << 30,
+    EG_CF_WORD1__BARRIER_shift       = 31,//1 bit
+    EG_CF_WORD1__BARRIER_bit         = 1 << 31,
+
+    EG_CF_INST_NOP                   = 0,
+    EG_CF_INST_TC                    = 1,
+    EG_CF_INST_VC                    = 2,
+    EG_CF_INST_GDS                   = 3,
+    EG_CF_INST_LOOP_START            = 4,
+    EG_CF_INST_LOOP_END              = 5,
+    EG_CF_INST_LOOP_START_DX10       = 6,
+    EG_CF_INST_LOOP_START_NO_AL      = 7,
+    EG_CF_INST_LOOP_CONTINUE         = 8,
+    EG_CF_INST_LOOP_BREAK            = 9,
+    EG_CF_INST_JUMP                  = 10,
+    EG_CF_INST_PUSH                  = 11,
+    EG_CF_INST_Reserved_12           = 12,
+    EG_CF_INST_ELSE                  = 13,
+    EG_CF_INST_POP                   = 14, 
+    EG_CF_INST_Reserved_15           = 15,
+    EG_CF_INST_Reserved_16           = 16,
+    EG_CF_INST_Reserved_17           = 17,
+    EG_CF_INST_CALL                  = 18,
+    EG_CF_INST_CALL_FS               = 19,
+    EG_CF_INST_RETURN                = 20,
+    EG_CF_INST_EMIT_VERTEX           = 21,
+    EG_CF_INST_EMIT_CUT_VERTEX       = 22,
+    EG_CF_INST_CUT_VERTEX            = 23,
+    EG_CF_INST_KILL                  = 24,
+    EG_CF_INST_Reserved_25           = 25,
+    EG_CF_INST_WAIT_ACK              = 26,
+    EG_CF_INST_TC_ACK                = 27,
+    EG_CF_INST_VC_ACK                = 28,
+    EG_CF_INST_JUMPTABLE             = 29,
+    EG_CF_INST_GLOBAL_WAVE_SYNC      = 30,
+    EG_CF_INST_HALT                  = 31,
+
+//TEX
+    EG_TEX_WORD0__TEX_INST_shift     = 0, //5 bits
+    EG_TEX_WORD0__TEX_INST_mask      = 0x1F,
+    EG_TEX_WORD0__INST_MOD_shift     = 5, //2 bits
+    EG_TEX_WORD0__INST_MOD_mask      = 0x3 << 5,
+    EG_TEX_WORD0__FWQ_shift          = 7, //1 bit
+    EG_TEX_WORD0__FWQ_bit            = 1 << 7,
+    EG_TEX_WORD0__RESOURCE_ID_shift  = 8, //8 bits
+    EG_TEX_WORD0__RESOURCE_ID_mask   = 0xFF << 8,
+    EG_TEX_WORD0__SRC_GPR_shift      = 16,//7 bits
+    EG_TEX_WORD0__SRC_GPR_mask       = 0x7F << 16,
+    EG_TEX_WORD0__SRC_REL_shift      = 23,//1 bit
+    EG_TEX_WORD0__SRC_REL_bit        = 1 << 23,
+    EG_TEX_WORD0__ALT_CONST_shift    = 24,//1 bit
+    EG_TEX_WORD0__ALT_CONST_bit      = 1 << 24,
+    EG_TEX_WORD0__RIM_shift          = 25,//2 bits
+    EG_TEX_WORD0__RIM_mask           = 0x3 << 25,
+    EG_TEX_WORD0__SIM_shift          = 27,//2 bits
+    EG_TEX_WORD0__SIM_mask           = 0x3 << 27,
+    EG_TEX_WORD0__Reserved_shift     = 29,//3 bits
+    EG_TEX_WORD0__Reserved_mask      = 0x7 << 29,
+
+    EG_TEX_INST_Reserved_0           = 0,
+    EG_TEX_INST_Reserved_1           = 1,
+    EG_TEX_INST_Reserved_2           = 2,
+    EG_TEX_INST_LD                   = 3,
+    EG_TEX_INST_GET_TEXTURE_RESINFO  = 4,
+    EG_TEX_INST_GET_NUMBER_OF_SAMPLES= 5,
+    EG_TEX_INST_GET_COMP_TEX_LOD     = 6,
+    EG_TEX_INST_GET_GRADIENTS_H      = 7,
+    EG_TEX_INST_GET_GRADIENTS_V      = 8,
+    EG_TEX_INST_SET_TEXTURE_OFFSETS  = 9,
+    EG_TEX_INST_KEEP_GRADIENTS       = 10,
+    EG_TEX_INST_SET_GRADIENTS_H      = 11,
+    EG_TEX_INST_SET_GRADIENTS_V      = 12,
+    EG_TEX_INST_Reserved_13          = 13,
+    EG_TEX_INST_Reserved_14          = 14,
+    EG_TEX_INST_Reserved_15          = 15,
+    EG_TEX_INST_SAMPLE               = 16,
+    EG_TEX_INST_SAMPLE_L             = 17,
+    EG_TEX_INST_SAMPLE_LB            = 18,
+    EG_TEX_INST_SAMPLE_LZ            = 19,
+    EG_TEX_INST_SAMPLE_G             = 20,
+    EG_TEX_INST_GATHER4              = 21,
+    EG_TEX_INST_SAMPLE_G_LB          = 22,
+    EG_TEX_INST_GATHER4_O            = 23,
+    EG_TEX_INST_SAMPLE_C             = 24,
+    EG_TEX_INST_SAMPLE_C_L           = 25,
+    EG_TEX_INST_SAMPLE_C_LB          = 26,
+    EG_TEX_INST_SAMPLE_C_LZ          = 27,
+    EG_TEX_INST_SAMPLE_C_G           = 28,
+    EG_TEX_INST_GATHER4_C            = 29,
+    EG_TEX_INST_SAMPLE_C_G_LB        = 30,
+    EG_TEX_INST_GATHER4_C_O          = 31,
+
+    EG_TEX_WORD1__DST_GPR_shift      = 0, //7 bits
+    EG_TEX_WORD1__DST_GPR_mask       = 0x7F,
+    EG_TEX_WORD1__DST_REL_shift      = 7, //1 bit
+    EG_TEX_WORD1__DST_REL_bit        = 1 << 7,
+    EG_TEX_WORD1__Reserved_shift     = 8, //1 bit
+    EG_TEX_WORD1__Reserved_bit       = 1 << 8,
+    EG_TEX_WORD1__DST_SEL_X_shift    = 9, //3 bits
+    EG_TEX_WORD1__DST_SEL_X_mask     = 0x7 << 9,
+    EG_TEX_WORD1__DST_SEL_Y_shift    = 12,//3 bits
+    EG_TEX_WORD1__DST_SEL_Y_mask     = 0x7 << 12,
+    EG_TEX_WORD1__DST_SEL_Z_shift    = 15,//3 bits
+    EG_TEX_WORD1__DST_SEL_Z_mask     = 0x7 << 15,
+    EG_TEX_WORD1__DST_SEL_W_shift    = 18,//3 bits
+    EG_TEX_WORD1__DST_SEL_W_mask     = 0x7 << 18,
+    EG_TEX_WORD1__LOD_BIAS_shift     = 21,//7 bits
+    EG_TEX_WORD1__LOD_BIAS_mask      = 0x7F << 21,
+    EG_TEX_WORD1__COORD_TYPE_X_shift = 28,//1 bit
+    EG_TEX_WORD1__COORD_TYPE_X_bit   = 1 << 28,
+    EG_TEX_WORD1__COORD_TYPE_Y_shift = 29,//1 bit
+    EG_TEX_WORD1__COORD_TYPE_Y_bit   = 1 << 29,
+    EG_TEX_WORD1__COORD_TYPE_Z_shift = 30,//1 bit
+    EG_TEX_WORD1__COORD_TYPE_Z_bit   = 1 << 30,
+    EG_TEX_WORD1__COORD_TYPE_W_shift = 31,//1 bit
+    EG_TEX_WORD1__COORD_TYPE_W_bit   = 1 << 31,
+
+    EG_TEX_WORD2__OFFSET_X_shift     = 0, //5 bits
+    EG_TEX_WORD2__OFFSET_X_mask      = 0x1F,
+    EG_TEX_WORD2__OFFSET_Y_shift     = 5, //5 bits
+    EG_TEX_WORD2__OFFSET_Y_mask      = 0x1F << 5,
+    EG_TEX_WORD2__OFFSET_Z_shift     = 10,//5 bits
+    EG_TEX_WORD2__OFFSET_Z_mask      = 0x1F << 10,
+    EG_TEX_WORD2__SAMPLER_ID_shift   = 15,//5 bits
+    EG_TEX_WORD2__SAMPLER_ID_mask    = 0x1F << 15,
+    EG_TEX_WORD2__SRC_SEL_X_shift    = 20,//3 bits
+    EG_TEX_WORD2__SRC_SEL_X_mask     = 0x7 << 20,
+    EG_TEX_WORD2__SRC_SEL_Y_shift    = 23,//3 bits
+    EG_TEX_WORD2__SRC_SEL_Y_mask     = 0x7 << 23,
+    EG_TEX_WORD2__SRC_SEL_Z_shift    = 26,//3 bits
+    EG_TEX_WORD2__SRC_SEL_Z_mask     = 0x7 << 26,
+    EG_TEX_WORD2__SRC_SEL_W_shift    = 29,//3 bits
+    EG_TEX_WORD2__SRC_SEL_W_mask     = 0x7 << 29,
+
+//VTX
+    EG_VTX_WORD0__VC_INST_shift      = 0, //5 bits
+    EG_VTX_WORD0__VC_INST_mask       = 0x1F,
+    EG_VTX_WORD0__FETCH_TYPE_shift   = 5, //2 bits
+    EG_VTX_WORD0__FETCH_TYPE_mask    = 0x3 << 5,
+    EG_VTX_WORD0__FWQ_shift          = 7, //1 bit
+    EG_VTX_WORD0__FWQ_bit            = 1 << 7,
+    EG_VTX_WORD0__BUFFER_ID_shift    = 8, //8 bits
+    EG_VTX_WORD0__BUFFER_ID_mask     = 0xFF << 8,
+    EG_VTX_WORD0__SRC_GPR_shift      = 16,//7 bits
+    EG_VTX_WORD0__SRC_GPR_mask       = 0x7F << 16,
+    EG_VTX_WORD0__SRC_REL_shift      = 23,//1 bit
+    EG_VTX_WORD0__SRC_REL_bit        = 1 << 23,
+    EG_VTX_WORD0__SRC_SEL_X_shift    = 24,//2 bits
+    EG_VTX_WORD0__SRC_SEL_X_mask     = 0x3 << 24,
+    EG_VTX_WORD0__MFC_shift          = 26,//6 bits
+    EG_VTX_WORD0__MFC_mask           = 0x3F << 26,
+
+    EG_VC_INST_FETCH                 = 0,
+    EG_VC_INST_SEMANTIC              = 1,
+    EG_VC_INST_Reserved_2            = 2,
+    EG_VC_INST_Reserved_3            = 3,
+    EG_VC_INST_Reserved_4            = 4,
+    EG_VC_INST_Reserved_5            = 5,
+    EG_VC_INST_Reserved_6            = 6,
+    EG_VC_INST_Reserved_7            = 7,
+    EG_VC_INST_Reserved_8            = 8,
+    EG_VC_INST_Reserved_9            = 9,
+    EG_VC_INST_Reserved_10           = 10,
+    EG_VC_INST_Reserved_11           = 11,
+    EG_VC_INST_Reserved_12           = 12,
+    EG_VC_INST_Reserved_13           = 13,
+    EG_VC_INST_GET_BUFFER_RESINFO    = 14,
+
+    EG_VTX_FETCH_VERTEX_DATA         = 0,
+    EG_VTX_FETCH_INSTANCE_DATA       = 1,
+    EG_VTX_FETCH_NO_INDEX_OFFSET     = 2,
+
+    EG_VTX_WORD1_SEM__SEMANTIC_ID_shift = 0, //8 bits
+    EG_VTX_WORD1_SEM__SEMANTIC_ID_mask  = 0xFF,
+    EG_VTX_WORD1_GPR__DST_GPR_shift  = 0, //7 bits
+    EG_VTX_WORD1_GPR__DST_GPR_mask   = 0x7F,
+    EG_VTX_WORD1_GPR__DST_REL_shift  = 7, //1 bit
+    EG_VTX_WORD1_GPR__DST_REL_bit    = 1 << 7,
+    EG_VTX_WORD1__Reserved_shift     = 8, //1 bit
+    EG_VTX_WORD1__Reserved_bit       = 1 << 8,
+    EG_VTX_WORD1__DST_SEL_X_shift    = 9, //3 bits
+    EG_VTX_WORD1__DST_SEL_X_mask     = 0x7 << 9,
+    EG_VTX_WORD1__DST_SEL_Y_shift    = 12,//3 bits
+    EG_VTX_WORD1__DST_SEL_Y_mask     = 0x7 << 12,
+    EG_VTX_WORD1__DST_SEL_Z_shift    = 15,//3 bits
+    EG_VTX_WORD1__DST_SEL_Z_mask     = 0x7 << 15,
+    EG_VTX_WORD1__DST_SEL_W_shift    = 18,//3 bits
+    EG_VTX_WORD1__DST_SEL_W_mask     = 0x7 << 18,
+    EG_VTX_WORD1__UCF_shift          = 21,//1 bit
+    EG_VTX_WORD1__UCF_bit            = 1 << 21,
+    EG_VTX_WORD1__DATA_FORMAT_shift  = 22,//6 bits
+    EG_VTX_WORD1__DATA_FORMAT_mask   = 0x3F << 22,
+    EG_VTX_WORD1__NFA_shift          = 28,//2 bits
+    EG_VTX_WORD1__NFA_mask           = 0x3 << 28,
+    EG_VTX_WORD1__FCA_shift          = 30,//1 bit
+    EG_VTX_WORD1__FCA_bit            = 1 << 30,
+    EG_VTX_WORD1__SMA_shift          = 31,//1 bit
+    EG_VTX_WORD1__SMA_bit            = 1 << 31,
+
+    EG_VTX_WORD2__OFFSET_shift       = 0, //16 bits
+    EG_VTX_WORD2__OFFSET_mask        = 0xFFFF,
+    EG_VTX_WORD2__ENDIAN_SWAP_shift  = 16,//2 bits
+    EG_VTX_WORD2__ENDIAN_SWAP_mask   = 0x3 << 16,
+    EG_VTX_WORD2__CBNS_shift         = 18,//1 bit
+    EG_VTX_WORD2__CBNS_bit           = 1 << 18,
+    EG_VTX_WORD2__MEGA_FETCH_shift   = 19,//1 bit
+    EG_VTX_WORD2__MEGA_FETCH_mask    = 1 << 19,
+    EG_VTX_WORD2__ALT_CONST_shift    = 20,//1 bit
+    EG_VTX_WORD2__ALT_CONST_mask     = 1 << 20,
+    EG_VTX_WORD2__BIM_shift          = 21,//2 bits
+    EG_VTX_WORD2__BIM_mask           = 0x3 << 21,
+    EG_VTX_WORD2__Reserved_shift     = 23,//9 bits
+    EG_VTX_WORD2__Reserved_mask      = 0x1FF << 23,
+
+//CF_ALU
+    EG_CF_ALU_WORD0__ADDR_shift         = 0, //22 bits
+    EG_CF_ALU_WORD0__ADDR_mask          = 0x3FFFFF,
+    EG_CF_ALU_WORD0__KCACHE_BANK0_shift = 22,//4 bits
+    EG_CF_ALU_WORD0__KCACHE_BANK0_mask  = 0xF << 22,
+    EG_CF_ALU_WORD0__KCACHE_BANK1_shift = 26,//4 bits
+    EG_CF_ALU_WORD0__KCACHE_BANK1_mask  = 0xF << 26,
+    EG_CF_ALU_WORD0__KCACHE_MODE0_shift = 30,//2 bits
+    EG_CF_ALU_WORD0__KCACHE_MODE0_mask  = 0x3 << 30,
+
+    EG_CF_ALU_WORD1__KCACHE_MODE1_shift = 0,  //2 bits
+    EG_CF_ALU_WORD1__KCACHE_MODE1_mask  = 0x3,
+    EG_CF_ALU_WORD1__KCACHE_ADDR0_shift = 2,  //8 bits
+    EG_CF_ALU_WORD1__KCACHE_ADDR0_mask  = 0xFF << 2,
+    EG_CF_ALU_WORD1__KCACHE_ADDR1_shift = 10, //8 bits
+    EG_CF_ALU_WORD1__KCACHE_ADDR1_mask  = 0xFF << 10,
+    EG_CF_ALU_WORD1__COUNT_shift        = 18, //7 bits
+    EG_CF_ALU_WORD1__COUNT_mask         = 0x7F << 18,
+    EG_CF_ALU_WORD1__ALT_CONST_shift    = 25, //1 bit
+    EG_CF_ALU_WORD1__ALT_CONST_bit      = 1 << 25,
+    EG_CF_ALU_WORD1__CF_INST_shift      = 26, //4 bits
+    EG_CF_ALU_WORD1__CF_INST_mask       = 0xF << 26,
+    EG_CF_ALU_WORD1__WQM_shift          = 30, //1 bit
+    EG_CF_ALU_WORD1__WQM_bit            = 1 << 30,
+    EG_CF_ALU_WORD1__BARRIER_shift      = 31, //1 bit
+    EG_CF_ALU_WORD1__BARRIER_bit        = 1 << 31,
+
+    EG_CF_INST_ALU                      = 8,
+    EG_CF_INST_ALU_PUSH_BEFORE          = 9,
+    EG_CF_INST_ALU_POP_AFTER            = 10,
+    EG_CF_INST_ALU_POP2_AFTER           = 11,
+    EG_CF_INST_ALU_EXTENDED             = 12,
+    EG_CF_INST_ALU_CONTINUE             = 13,
+    EG_CF_INST_ALU_BREAK                = 14,
+    EG_CF_INST_ALU_ELSE_AFTER           = 15,
+
+    EG_CF_ALU_WORD0_EXT__Reserved0_shift    = 0, //4 bits
+    EG_CF_ALU_WORD0_EXT__Reserved0_mask     = 0xF,
+    EG_CF_ALU_WORD0_EXT__KBIM0_shift        = 4, //2 bits
+    EG_CF_ALU_WORD0_EXT__KBIM0_mask         = 0x3 << 4,
+    EG_CF_ALU_WORD0_EXT__KBIM1_shift        = 6, //2 bits
+    EG_CF_ALU_WORD0_EXT__KBIM1_mask         = 0x3 << 6,
+    EG_CF_ALU_WORD0_EXT__KBIM2_shift        = 8, //2 bits
+    EG_CF_ALU_WORD0_EXT__KBIM2_mask         = 0x3 << 8,
+    EG_CF_ALU_WORD0_EXT__KBIM3_shift        = 10,//2 bits
+    EG_CF_ALU_WORD0_EXT__KBIM3_mask         = 0x3 << 10,
+    EG_CF_ALU_WORD0_EXT__Reserved12_shift   = 12,//10 bits
+    EG_CF_ALU_WORD0_EXT__Reserved12_mask    = 0x3FF << 12,
+    EG_CF_ALU_WORD0_EXT__KCACHE_BANK2_shift = 22,//4 bits
+    EG_CF_ALU_WORD0_EXT__KCACHE_BANK2_mask  = 0xF << 22,
+    EG_CF_ALU_WORD0_EXT__KCACHE_BANK3_shift = 26,//4 bits
+    EG_CF_ALU_WORD0_EXT__KCACHE_BANK3_mask  = 0xF << 26,
+    EG_CF_ALU_WORD0_EXT__KCACHE_MODE2_shift = 30,//2 btis
+    EG_CF_ALU_WORD0_EXT__KCACHE_MODE2_mask  = 0x3 << 30,
+
+    EG_CF_ALU_WORD1_EXT__KCACHE_MODE3_shift = 0,  //2 bits
+    EG_CF_ALU_WORD1_EXT__KCACHE_MODE3_mask  = 0x3,
+    EG_CF_ALU_WORD1_EXT__KCACHE_ADDR2_shift = 2,  //8 bits
+    EG_CF_ALU_WORD1_EXT__KCACHE_ADDR2_mask  = 0xFF << 2,
+    EG_CF_ALU_WORD1_EXT__KCACHE_ADDR3_shift = 10, //8 bits
+    EG_CF_ALU_WORD1_EXT__KCACHE_ADDR3_mask  = 0xFF << 10,
+    EG_CF_ALU_WORD1_EXT__Reserved18_shift   = 18, //8 bits
+    EG_CF_ALU_WORD1_EXT__Reserved18_mask    = 0xFF << 18,
+    EG_CF_ALU_WORD1_EXT__CF_INST_shift      = 26, //4 bits
+    EG_CF_ALU_WORD1_EXT__CF_INST_mask       = 0xF << 26,
+    EG_CF_ALU_WORD1_EXT__Reserved30_shift   = 30, //1 bit
+    EG_CF_ALU_WORD1_EXT__Reserved30_bit     = 1 << 30,
+    EG_CF_ALU_WORD1_EXT__BARRIER_shift      = 31, //1 bit
+    EG_CF_ALU_WORD1_EXT__BARRIER_bit        = 1 << 31,
+
+//ALU
+    EG_ALU_WORD0__SRC0_SEL_shift            = 0, //9 bits
+    EG_ALU_WORD0__SRC0_SEL_mask             = 0x1FF,
+    EG_ALU_WORD0__SRC1_SEL_shift            = 13,//9 bits
+    EG_ALU_WORD0__SRC1_SEL_mask             = 0x1FF << 13,
+    EG_ALU_WORD0__SRC0_REL_shift            = 9, //1 bit
+    EG_ALU_WORD0__SRC0_REL_bit              = 1 << 9,
+    EG_ALU_WORD0__SRC1_REL_shift            = 22,//1 bit
+    EG_ALU_WORD0__SRC1_REL_bit              = 1 << 22,
+    EG_ALU_WORD0__SRC0_CHAN_shift           = 10,//2 bits
+    EG_ALU_WORD0__SRC0_CHAN_mask            = 0x3 << 10,
+    EG_ALU_WORD0__SRC1_CHAN_shift           = 23,//2 bits
+    EG_ALU_WORD0__SRC1_CHAN_mask            = 0x3 << 23,
+    EG_ALU_WORD0__SRC0_NEG_shift            = 12,//1 bit
+    EG_ALU_WORD0__SRC0_NEG_bit              = 1 << 12,
+    EG_ALU_WORD0__SRC1_NEG_shift            = 25,//1 bit
+    EG_ALU_WORD0__SRC1_NEG_bit              = 1 << 25,
+    EG_ALU_WORD0__INDEX_MODE_shift          = 26,//3 bits
+    EG_ALU_WORD0__INDEX_MODE_mask           = 0x7 << 26,
+    EG_ALU_WORD0__PRED_SEL_shift            = 29,//2 bits
+    EG_ALU_WORD0__PRED_SEL_mask             = 0x3 << 29,
+    EG_ALU_WORD0__LAST_shift                = 31,//1 bit
+    EG_ALU_WORD0__LAST_bit                  = 1 << 31,
+
+    EG_ALU_WORD1_OP2__SRC0_ABS_shift        = 0, //1 bit 
+    EG_ALU_WORD1_OP2__SRC0_ABS_bit          = 1,
+    EG_ALU_WORD1_OP2__SRC1_ABS_shift        = 1, //1 bit 
+    EG_ALU_WORD1_OP2__SRC1_ABS_bit          = 1 << 1,
+    EG_ALU_WORD1_OP2__UEM_shift             = 2, //1 bit 
+    EG_ALU_WORD1_OP2__UEM_bit               = 1 << 2,
+    EG_ALU_WORD1_OP2__UPDATE_PRED_shift     = 3, //1 bit 
+    EG_ALU_WORD1_OP2__UPDATE_PRED_bit       = 1 << 3,
+    EG_ALU_WORD1_OP2__WRITE_MASK_shift      = 4, //1 bit 
+    EG_ALU_WORD1_OP2__WRITE_MASK_bit        = 1 << 4,
+    EG_ALU_WORD1_OP2__OMOD_shift            = 5, //2 bits 
+    EG_ALU_WORD1_OP2__OMOD_mask             = 0x3 << 5,
+    EG_ALU_WORD1_OP2__ALU_INST_shift        = 7, //11 bits
+    EG_ALU_WORD1_OP2__ALU_INST_mask         = 0x7FF << 7,
+
+    EG_ALU_WORD1__BANK_SWIZZLE_shift    = 18,//3 bits
+    EG_ALU_WORD1__BANK_SWIZZLE_mask     = 0x7 << 18,
+    EG_ALU_WORD1__DST_GPR_shift         = 21,//7 bits
+    EG_ALU_WORD1__DST_GPR_mask          = 0x7F << 21,
+    EG_ALU_WORD1__DST_REL_shift         = 28,//1 bit
+    EG_ALU_WORD1__DST_REL_mask          = 1 << 28,
+    EG_ALU_WORD1__DST_CHAN_shift        = 29,//2 bits
+    EG_ALU_WORD1__DST_CHAN_mask         = 0x3 << 29,
+    EG_ALU_WORD1__CLAMP_shift           = 31,//1 bits
+    EG_ALU_WORD1__CLAMP_mask            = 1 << 31,
+
+    EG_ALU_WORD1_OP3__SRC2_SEL_shift        = 0, //9 bits
+    EG_ALU_WORD1_OP3__SRC2_SEL_mask         = 0x1FF,
+    EG_ALU_WORD1_OP3__SRC2_REL_shift        = 9, //1 bit
+    EG_ALU_WORD1_OP3__SRC2_REL_bit          = 1 << 9,
+    EG_ALU_WORD1_OP3__SRC2_CHAN_shift       = 10,//2 bits
+    EG_ALU_WORD1_OP3__SRC2_CHAN_mask        = 0x3 << 10,
+    EG_ALU_WORD1_OP3__SRC2_NEG_shift        = 12,//1 bit
+    EG_ALU_WORD1_OP3__SRC2_NEG_bit          = 1 << 12,
+    EG_ALU_WORD1_OP3__ALU_INST_shift        = 13,//5 bits
+    EG_ALU_WORD1_OP3__ALU_INST_mask         = 0x1F << 13,
+
+    EG_OP3_INST_BFE_UINT                    = 4,
+    EG_OP3_INST_BFE_INT                     = 5,
+    EG_OP3_INST_BFI_INT                     = 6,
+    EG_OP3_INST_FMA                         = 7,
+    EG_OP3_INST_CNDNE_64                    = 9,
+    EG_OP3_INST_FMA_64                      = 10,
+    EG_OP3_INST_LERP_UINT                   = 11,
+    EG_OP3_INST_BIT_ALIGN_INT               = 12,
+    EG_OP3_INST_BYTE_ALIGN_INT              = 13,
+    EG_OP3_INST_SAD_ACCUM_UINT              = 14,
+    EG_OP3_INST_SAD_ACCUM_HI_UINT           = 15,
+    EG_OP3_INST_MULADD_UINT24               = 16,
+    EG_OP3_INST_LDS_IDX_OP                  = 17,
+    EG_OP3_INST_MULADD                      = 20,
+    EG_OP3_INST_MULADD_M2                   = 21,
+    EG_OP3_INST_MULADD_M4                   = 22,
+    EG_OP3_INST_MULADD_D2                   = 23,
+    EG_OP3_INST_MULADD_IEEE                 = 24,
+    EG_OP3_INST_CNDE                        = 25,
+    EG_OP3_INST_CNDGT                       = 26,
+    EG_OP3_INST_CNDGE                       = 27,
+    EG_OP3_INST_CNDE_INT                    = 28,
+    EG_OP3_INST_CMNDGT_INT                  = 29,
+    EG_OP3_INST_CMNDGE_INT                  = 30,
+    EG_OP3_INST_MUL_LIT                     = 31,
+
+    EG_OP2_INST_ADD                       = 0,
+    EG_OP2_INST_MUL                       = 1,
+    EG_OP2_INST_MUL_IEEE                  = 2,
+    EG_OP2_INST_MAX                       = 3,
+    EG_OP2_INST_MIN                       = 4,
+    EG_OP2_INST_MAX_DX10                  = 5,
+    EG_OP2_INST_MIN_DX10                  = 6,
+    EG_OP2_INST_SETE                      = 8,
+    EG_OP2_INST_SETGT                     = 9,
+    EG_OP2_INST_SETGE                     = 10,
+    EG_OP2_INST_SETNE                     = 11,
+    EG_OP2_INST_SETE_DX10                 = 12,
+    EG_OP2_INST_SETGT_DX10                = 13,
+    EG_OP2_INST_SETGE_DX10                = 14,
+    EG_OP2_INST_SETNE_DX10                = 15,
+    EG_OP2_INST_FRACT                     = 16,
+    EG_OP2_INST_TRUNC                     = 17,
+    EG_OP2_INST_CEIL                      = 18,
+    EG_OP2_INST_RNDNE                     = 19,
+    EG_OP2_INST_FLOOR                     = 20,
+    EG_OP2_INST_ASHR_INT                  = 21,
+    EG_OP2_INST_LSHR_INT                  = 22,
+    EG_OP2_INST_LSHL_INT                  = 23,
+    EG_OP2_INST_MOV                       = 25,
+    EG_OP2_INST_NOP                       = 26,
+    EG_OP2_INST_MUL_64                    = 27,
+    EG_OP2_INST_FLT64_TO_FLT32            = 28,
+    EG_OP2_INST_FLT32_TO_FLT64            = 29,
+    EG_OP2_INST_PRED_SETGT_UINT           = 30,
+    EG_OP2_INST_PRED_SETGE_UINT           = 31,
+    EG_OP2_INST_PRED_SETE                 = 32,
+    EG_OP2_INST_PRED_SETGT                = 33,
+    EG_OP2_INST_PRED_SETGE                = 34,
+    EG_OP2_INST_PRED_SETNE                = 35,
+    EG_OP2_INST_PRED_SET_INV              = 36,
+    EG_OP2_INST_PRED_SET_POP              = 37,
+    EG_OP2_INST_PRED_SET_CLR              = 38,
+    EG_OP2_INST_PRED_SET_RESTORE          = 39,
+    EG_OP2_INST_PRED_SETE_PUSH            = 40,
+    EG_OP2_INST_PRED_SETGT_PUSH           = 41,
+    EG_OP2_INST_PRED_SETGE_PUSH           = 42,
+    EG_OP2_INST_PRED_SETNE_PUSH           = 43,
+    EG_OP2_INST_KILLE                     = 44,
+    EG_OP2_INST_KILLGT                    = 45,
+    EG_OP2_INST_KILLGE                    = 46,
+    EG_OP2_INST_KILLNE                    = 47,
+    EG_OP2_INST_AND_INT                   = 48,
+    EG_OP2_INST_OR_INT                    = 49,
+    EG_OP2_INST_XOR_INT                   = 50,
+    EG_OP2_INST_NOT_INT                   = 51,
+    EG_OP2_INST_ADD_INT                   = 52,
+    EG_OP2_INST_SUB_INT                   = 53,
+    EG_OP2_INST_MAX_INT                   = 54,
+    EG_OP2_INST_MIN_INT                   = 55,
+    EG_OP2_INST_MAX_UINT                  = 56,
+    EG_OP2_INST_MIN_UINT                  = 57,
+    EG_OP2_INST_SETE_INT                  = 58,
+    EG_OP2_INST_SETGT_INT                 = 59,
+    EG_OP2_INST_SETGE_INT                 = 60,
+    EG_OP2_INST_SETNE_INT                 = 61,
+    EG_OP2_INST_SETGT_UINT                = 62,
+    EG_OP2_INST_SETGE_UINT                = 63,
+    EG_OP2_INST_KILLGT_UINT               = 64,
+    EG_OP2_INST_KILLGE_UINT               = 65,
+    EG_OP2_INST_PREDE_INT                 = 66,
+    EG_OP2_INST_PRED_SETGT_INT            = 67,
+    EG_OP2_INST_PRED_SETGE_INT            = 68,
+    EG_OP2_INST_PRED_SETNE_INT            = 69,
+    EG_OP2_INST_KILLE_INT                 = 70,
+    EG_OP2_INST_KILLGT_INT                = 71,
+    EG_OP2_INST_KILLGE_INT                = 72,
+    EG_OP2_INST_KILLNE_INT                = 73,
+    EG_OP2_INST_PRED_SETE_PUSH_INT        = 74,
+    EG_OP2_INST_PRED_SETGT_PUSH_INT       = 75,
+    EG_OP2_INST_PRED_SETGE_PUSH_INT       = 76,
+    EG_OP2_INST_PRED_SETNE_PUSH_INT       = 77,
+    EG_OP2_INST_PRED_SETLT_PUSH_INT       = 78,
+    EG_OP2_INST_PRED_SETLE_PUSH_INT       = 79,
+    EG_OP2_INST_FLT_TO_INT                = 80,
+    EG_OP2_INST_BFREV_INT                 = 81,
+    EG_OP2_INST_ADDC_UINT                 = 82,
+    EG_OP2_INST_SUBB_UINT                 = 83,
+    EG_OP2_INST_GROUP_BARRIER             = 84,
+    EG_OP2_INST_GROUP_SEQ_BEGIN           = 85,
+    EG_OP2_INST_GROUP_SEQ_END             = 86,
+    EG_OP2_INST_SET_MODE                  = 87,
+    EG_OP2_INST_SET_CF_IDX0               = 88,
+    EG_OP2_INST_SET_CF_IDX1               = 89,
+    EG_OP2_INST_SET_LDS_SIZE              = 90,
+    EG_OP2_INST_EXP_IEEE                  = 129,
+    EG_OP2_INST_LOG_CLAMPED               = 130,
+    EG_OP2_INST_LOG_IEEE                  = 131,
+    EG_OP2_INST_RECIP_CLAMPED             = 132,
+    EG_OP2_INST_RECIP_FF                  = 133,
+    EG_OP2_INST_RECIP_IEEE                = 134,
+    EG_OP2_INST_RECIPSQRT_CLAMPED         = 135,
+    EG_OP2_INST_RECIPSQRT_FF              = 136,
+    EG_OP2_INST_RECIPSQRT_IEEE            = 137,
+    EG_OP2_INST_SQRT_IEEE                 = 138,
+    EG_OP2_INST_SIN                       = 141,
+    EG_OP2_INST_COS                       = 142,
+    EG_OP2_INST_MULLO_INT                 = 143,
+    EG_OP2_INST_MULHI_INT                 = 144,
+    EG_OP2_INST_MULLO_UINT                = 145,
+    EG_OP2_INST_MULHI_UINT                = 146,
+    EG_OP2_INST_RECIP_INT                 = 147,
+    EG_OP2_INST_RECIP_UINT                = 148,
+    EG_OP2_INST_RECIP_64                  = 149,
+    EG_OP2_INST_RECIP_CLAMPED_64          = 150,
+    EG_OP2_INST_RECIPSQRT_64              = 151,
+    EG_OP2_INST_RECIPSQRT_CLAMPED_64      = 152,
+    EG_OP2_INST_SQRT_64                   = 153,
+    EG_OP2_INST_FLT_TO_UINT               = 154,
+    EG_OP2_INST_INT_TO_FLT                = 155,
+    EG_OP2_INST_UINT_TO_FLT               = 156,
+    EG_OP2_INST_BFM_INT                   = 160,
+    EG_OP2_INST_FLT32_TO_FLT16            = 162,
+    EG_OP2_INST_FLT16_TO_FLT32            = 163,
+    EG_OP2_INST_UBYTE0_FLT                = 164,
+    EG_OP2_INST_UBYTE1_FLT                = 165,
+    EG_OP2_INST_UBYTE2_FLT                = 166,
+    EG_OP2_INST_UBYTE3_FLT                = 167,
+    EG_OP2_INST_BCNT_INT                  = 170,
+    EG_OP2_INST_FFBH_UINT                 = 171,
+    EG_OP2_INST_FFBL_INT                  = 172,
+    EG_OP2_INST_FFBH_INT                  = 173,
+    EG_OP2_INST_FLT_TO_UINT4              = 174,
+    EG_OP2_INST_DOT_IEEE                  = 175,
+    EG_OP2_INST_FLT_TO_INT_RPI            = 176,
+    EG_OP2_INST_FLT_TO_INT_FLOOR          = 177,
+    EG_OP2_INST_MULHI_UINT24              = 178,
+    EG_OP2_INST_MBCNT_32HI_INT            = 179,
+    EG_OP2_INST_OFFSET_TO_FLT             = 180,
+    EG_OP2_INST_MUL_UINT24                = 181,
+    EG_OP2_INST_BCNT_ACCUM_PREV_INT       = 182,
+    EG_OP2_INST_MBCNT_32LO_ACCUM_PREV_INT = 183,
+    EG_OP2_INST_SETE_64                   = 184,
+    EG_OP2_INST_SETNE_64                  = 185,
+    EG_OP2_INST_SETGT_64                  = 186,
+    EG_OP2_INST_SETGE_64                  = 187,
+    EG_OP2_INST_MIN_64                    = 188,
+    EG_OP2_INST_MAX_64                    = 189,
+    EG_OP2_INST_DOT4                      = 190,
+    EG_OP2_INST_DOT4_IEEE                 = 191,
+    EG_OP2_INST_CUBE                      = 192,
+    EG_OP2_INST_MAX4                      = 193,
+    EG_OP2_INST_FREXP_64                  = 196,
+    EG_OP2_INST_LDEXP_64                  = 197,
+    EG_OP2_INST_FRACT_64                  = 198,
+    EG_OP2_INST_PRED_SETGT_64             = 199,
+    EG_OP2_INST_PRED_SETE_64              = 200,
+    EG_OP2_INST_PRED_SETGE_64             = 201,
+    EG_OP2_INST_MUL_64_2                  = 202, //same as prev?
+    EG_OP2_INST_ADD_64                    = 203,
+    EG_OP2_INST_MOVA_INT                  = 204,
+    EG_OP2_INST_FLT64_TO_FLT32_2          = 205, //same as prev?
+    EG_OP2_INST_FLT32_TO_FLT64_2          = 206, //same as prev?
+    EG_OP2_INST_SAD_ACCUM_PREV_UINT       = 207,
+    EG_OP2_INST_DOT                       = 208,
+    EG_OP2_INST_MUL_PREV                  = 209,
+    EG_OP2_INST_MUL_IEEE_PREV             = 210,
+    EG_OP2_INST_ADD_PREV                  = 211,
+    EG_OP2_INST_MULADD_PREV               = 212,
+    EG_OP2_INST_MULADD_IEEE_PREV          = 213,
+    EG_OP2_INST_INTERP_XY                 = 214,
+    EG_OP2_INST_INTERP_ZW                 = 215,
+    EG_OP2_INST_INTERP_X                  = 216,
+    EG_OP2_INST_INTERP_Z                  = 217,
+    EG_OP2_INST_STORE_FLAGS               = 218,
+    EG_OP2_INST_LOAD_STORE_FLAGS          = 219,
+    EG_OP2_INST_LDS_1A                    = 220,
+    EG_OP2_INST_LDS_1A1D                  = 221,
+    EG_OP2_INST_LDS_2A                    = 223,
+    EG_OP2_INST_INTERP_LOAD_P0            = 224,
+    EG_OP2_INST_INTERP_LOAD_P10           = 225,
+    EG_OP2_INST_INTERP_LOAD_P20           = 226,
+
+    EG_SRC_SEL__GPR_start                 = 0,
+    EG_SRC_SEL__GPR_end                   = 127,
+    EG_SRC_SEL__KCONST_BANK0_start        = 128,
+    EG_SRC_SEL__KCONST_BANK0_end          = 159,
+    EG_SRC_SEL__KCONST_BANK1_start        = 160,
+    EG_SRC_SEL__KCONST_BANK1_end          = 191,
+    EG_SRC_SEL__INLINE_satrt              = 192,
+    EG_SRC_SEL__INLINE_end                = 255,
+    EG_SRC_SEL__KCONST_BANK2_start        = 256,
+    EG_SRC_SEL__KCONST_BANK2_end          = 287,
+    EG_SRC_SEL__KCONST_BANK3_start        = 288,
+    EG_SRC_SEL__KCONST_BANK3_end          = 319,
+    EG_SRC_SEL__ALU_SRC_LDS_OQ_A             = 219,
+    EG_SRC_SEL__ALU_SRC_LDS_OQ_B             = 220,
+    EG_SRC_SEL__ALU_SRC_LDS_OQ_A_POP         = 221,
+    EG_SRC_SEL__ALU_SRC_LDS_OQ_B_POP         = 222,
+    EG_SRC_SEL__ALU_SRC_LDS_DIRECT_A         = 223,
+    EG_SRC_SEL__ALU_SRC_LDS_DIRECT_B         = 224,
+    EG_SRC_SEL__ALU_SRC_TIME_HI              = 227,
+    EG_SRC_SEL__ALU_SRC_TIME_LO              = 228,
+    EG_SRC_SEL__ALU_SRC_MASK_HI              = 229,
+    EG_SRC_SEL__ALU_SRC_MASK_LO              = 230,
+    EG_SRC_SEL__ALU_SRC_HW_WAVE_ID           = 231,
+    EG_SRC_SEL__ALU_SRC_SIMD_ID              = 232,
+    EG_SRC_SEL__ALU_SRC_SE_ID                = 233,
+    EG_SRC_SEL__ALU_SRC_HW_THREADGRP_ID      = 234,
+    EG_SRC_SEL__ALU_SRC_WAVE_ID_IN_GRP       = 235,
+    EG_SRC_SEL__ALU_SRC_NUM_THREADGRP_WAVES  = 236,
+    EG_SRC_SEL__ALU_SRC_HW_ALU_ODD           = 237,
+    EG_SRC_SEL__ALU_SRC_LOOP_IDX             = 238,
+    EG_SRC_SEL__ALU_SRC_PARAM_BASE_ADDR      = 240,
+    EG_SRC_SEL__ALU_SRC_NEW_PRIM_MASK        = 241,
+    EG_SRC_SEL__ALU_SRC_PRIM_MASK_HI         = 242,
+    EG_SRC_SEL__ALU_SRC_PRIM_MASK_LO         = 243,
+    EG_SRC_SEL__ALU_SRC_1_DBL_L              = 244,
+    EG_SRC_SEL__ALU_SRC_1_DBL_M              = 245,
+    EG_SRC_SEL__ALU_SRC_0_5_DBL_L            = 246,
+    EG_SRC_SEL__ALU_SRC_0_5_DBL_M            = 247,
+    EG_SRC_SEL__ALU_SRC_0                    = 248,
+    EG_SRC_SEL__ALU_SRC_1                    = 249,
+    EG_SRC_SEL__ALU_SRC_1_INT                = 250,
+    EG_SRC_SEL__ALU_SRC_M_1_INT              = 251,
+    EG_SRC_SEL__ALU_SRC_0_5                  = 252,
+    EG_SRC_SEL__ALU_SRC_LITERAL              = 253,
+    EG_SRC_SEL__ALU_SRC_PV                   = 254,
+    EG_SRC_SEL__ALU_SRC_PS                   = 255,
+
+//ALLOC_EXPORT
+    EG_CF_ALLOC_EXPORT_WORD0__ARRAY_BASE_shift = 0, //13 bits 
+    EG_CF_ALLOC_EXPORT_WORD0__ARRAY_BASE_mask  = 0x1FFF,
+    EG_CF_ALLOC_EXPORT_WORD0__TYPE_shift       = 13,//2 bits
+    EG_CF_ALLOC_EXPORT_WORD0__TYPE_mask        = 0x3 << 13,
+    EG_CF_ALLOC_EXPORT_WORD0__RW_GPR_shift     = 15,//7 bits
+    EG_CF_ALLOC_EXPORT_WORD0__RW_GPR_mask      = 0x7F << 15,
+    EG_CF_ALLOC_EXPORT_WORD0__RW_REL_shift     = 22,//1 bit
+    EG_CF_ALLOC_EXPORT_WORD0__RW_REL_bit       = 1 << 22,
+    EG_CF_ALLOC_EXPORT_WORD0__INDEX_GPR_shift  = 23,//7 bits
+    EG_CF_ALLOC_EXPORT_WORD0__INDEX_GPR_mask   = 0x7F << 23,
+    EG_CF_ALLOC_EXPORT_WORD0__ELEM_SIZE_shift  = 30,//2 bits
+    EG_CF_ALLOC_EXPORT_WORD0__ELEM_SIZE_mask   = 0x3 << 30,
+
+    EG_CF_ALLOC_EXPORT_WORD1_BUF__ARRAY_SIZE_shift  = 0, //12 bits
+    EG_CF_ALLOC_EXPORT_WORD1_BUF__ARRAY_SIZE_mask   = 0xFFF,
+    EG_CF_ALLOC_EXPORT_WORD1_BUF__COMP_MASK_shift   = 12, //4 bits
+    EG_CF_ALLOC_EXPORT_WORD1_BUF__COMP_MASK_mask    = 0xF << 12,
+
+    EG_CF_ALLOC_EXPORT_WORD1_SWIZ__SEL_X_shift      = 0, //3 bits
+    EG_CF_ALLOC_EXPORT_WORD1_SWIZ__SEL_X_mask       = 0x7,
+    EG_CF_ALLOC_EXPORT_WORD1_SWIZ__SEL_Y_shift      = 3, //3 bits
+    EG_CF_ALLOC_EXPORT_WORD1_SWIZ__SEL_Y_mask       = 0x7 << 3,
+    EG_CF_ALLOC_EXPORT_WORD1_SWIZ__SEL_Z_shift      = 6, //3 bits
+    EG_CF_ALLOC_EXPORT_WORD1_SWIZ__SEL_Z_mask       = 0x7 << 6,
+    EG_CF_ALLOC_EXPORT_WORD1_SWIZ__SEL_W_shift      = 9, //3 bits
+    EG_CF_ALLOC_EXPORT_WORD1_SWIZ__SEL_W_mask       = 0x7 << 9,
+    EG_CF_ALLOC_EXPORT_WORD1_SWIZ__Resreve_shift    = 12,//4 bits
+    EG_CF_ALLOC_EXPORT_WORD1_SWIZ__Resreve_mask     = 0xF << 12,
+
+    EG_CF_ALLOC_EXPORT_WORD1__BURST_COUNT_shift = 16, //4 bits
+    EG_CF_ALLOC_EXPORT_WORD1__BURST_COUNT_mask  = 0xF << 16, 
+    EG_CF_ALLOC_EXPORT_WORD1__VPM_shift         = 20, //1 bit
+    EG_CF_ALLOC_EXPORT_WORD1__VPM_bit           = 1 << 20,
+    EG_CF_ALLOC_EXPORT_WORD1__EOP_shift         = 21, //1 bit
+    EG_CF_ALLOC_EXPORT_WORD1__EOP_bit           = 1 << 21,
+    EG_CF_ALLOC_EXPORT_WORD1__CF_INST_shift     = 22, //8 bits
+    EG_CF_ALLOC_EXPORT_WORD1__CF_INST_mask      = 0xFF << 22,
+    EG_CF_ALLOC_EXPORT_WORD1__MARK_shift        = 30, //1 bit
+    EG_CF_ALLOC_EXPORT_WORD1__MARK_bit          = 1 << 30,
+    EG_CF_ALLOC_EXPORT_WORD1__BARRIER_shift     = 31, //1 bit
+    EG_CF_ALLOC_EXPORT_WORD1__BARRIER_bit       = 1 << 31,
+
+    EG_CF_INST_MEM_STREAM0_BUF0              = 64 ,
+    EG_CF_INST_MEM_STREAM0_BUF1              = 65,
+    EG_CF_INST_MEM_STREAM0_BUF2              = 66,
+    EG_CF_INST_MEM_STREAM0_BUF3              = 67,
+    EG_CF_INST_MEM_STREAM1_BUF0              = 68,
+    EG_CF_INST_MEM_STREAM1_BUF1              = 69,
+    EG_CF_INST_MEM_STREAM1_BUF2              = 70,
+    EG_CF_INST_MEM_STREAM1_BUF3              = 71,
+    EG_CF_INST_MEM_STREAM2_BUF0              = 72,
+    EG_CF_INST_MEM_STREAM2_BUF1              = 73,
+    EG_CF_INST_MEM_STREAM2_BUF2              = 74,
+    EG_CF_INST_MEM_STREAM2_BUF3              = 75,
+    EG_CF_INST_MEM_STREAM3_BUF0              = 76,
+    EG_CF_INST_MEM_STREAM3_BUF1              = 77,
+    EG_CF_INST_MEM_STREAM3_BUF2              = 78,
+    EG_CF_INST_MEM_STREAM3_BUF3              = 79,
+    EG_CF_INST_MEM_WR_SCRATCH                = 80,
+    EG_CF_INST_MEM_RING                      = 82,
+    EG_CF_INST_EXPORT                        = 83,
+    EG_CF_INST_EXPORT_DONE                   = 84,
+    EG_CF_INST_MEM_EXPORT                    = 85,
+    EG_CF_INST_MEM_RAT                       = 86,
+    EG_CF_INST_MEM_RAT_CACHELESS             = 87,
+    EG_CF_INST_MEM_RING1                     = 88,
+    EG_CF_INST_MEM_RING2                     = 89,
+    EG_CF_INST_MEM_RING3                     = 90,
+    EG_CF_INST_MEM_EXPORT_COMBINED           = 91,
+    EG_CF_INST_MEM_RAT_COMBINED_CACHELESS    = 92,
+
+    EG_EXPORT_PIXEL         = 0,
+    EG_EXPORT_WRITE         = 0,
+    EG_EXPORT_POS           = 1,
+    EG_EXPORT_WRITE_IND     = 1,
+    EG_EXPORT_PARAM         = 2,
+    EG_EXPORT_WRITE_ACK     = 2,
+    EG_EXPORT_WRITE_IND_ACK = 3,
+
+    /* PS interp param source */
+    EG_ALU_SRC_PARAM_BASE                    = 0x000001c0,
+    EG_ALU_SRC_PARAM_SIZE                    = 0x00000021,
+};
+
+#endif //_EVERGREEN_SQ_H_
+
+
diff --git a/src/mesa/drivers/dri/r600/evergreen_state.c b/src/mesa/drivers/dri/r600/evergreen_state.c
new file mode 100644 (file)
index 0000000..931478c
--- /dev/null
@@ -0,0 +1,1878 @@
+/*
+ * Copyright (C) 2008-2009  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "main/imports.h"
+#include "main/enums.h"
+#include "main/macros.h"
+#include "main/context.h"
+#include "main/dd.h"
+#include "main/simple_list.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "main/api_arrayelt.h"
+#include "main/framebuffer.h"
+#include "drivers/common/meta.h"
+#include "program/prog_parameter.h"
+#include "program/prog_statevars.h"
+
+#include "vbo/vbo.h"
+
+#include "r600_context.h"
+
+#include "evergreen_state.h"
+#include "evergreen_diff.h"
+#include "evergreen_vertprog.h"
+#include "evergreen_fragprog.h"
+#include "evergreen_tex.h"
+
+void evergreenUpdateStateParameters(GLcontext * ctx, GLuint new_state); //same
+
+void evergreenUpdateShaders(GLcontext * ctx)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+
+    /* should only happenen once, just after context is created */
+    /* TODO: shouldn't we fallback to sw here? */
+    if (!ctx->FragmentProgram._Current) {
+           fprintf(stderr, "No ctx->FragmentProgram._Current!!\n");
+           return;
+    }
+
+    evergreenSelectFragmentShader(ctx);
+
+    evergreenSelectVertexShader(ctx);
+    evergreenUpdateStateParameters(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+    context->radeon.NewGLState = 0;
+}
+
+void evergreeUpdateShaders(GLcontext * ctx)
+{
+    context_t *context = R700_CONTEXT(ctx);
+
+    /* should only happenen once, just after context is created */
+    /* TODO: shouldn't we fallback to sw here? */
+    if (!ctx->FragmentProgram._Current) {
+           fprintf(stderr, "No ctx->FragmentProgram._Current!!\n");
+           return;
+    }
+
+    evergreenSelectFragmentShader(ctx);
+
+    evergreenSelectVertexShader(ctx);
+    evergreenUpdateStateParameters(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+    context->radeon.NewGLState = 0;
+}
+
+/*
+ * To correctly position primitives:
+ */
+void evergreenUpdateViewportOffset(GLcontext * ctx) //------------------
+{
+       context_t *context = R700_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       __DRIdrawable *dPriv = radeon_get_drawable(&context->radeon);
+       GLfloat xoffset = (GLfloat) dPriv->x;
+       GLfloat yoffset = (GLfloat) dPriv->y + dPriv->h;
+       const GLfloat *v = ctx->Viewport._WindowMap.m;
+       int id = 0;
+
+       GLfloat tx = v[MAT_TX] + xoffset;
+       GLfloat ty = (-v[MAT_TY]) + yoffset;
+
+       if (evergreen->viewport[id].PA_CL_VPORT_XOFFSET.f32All != tx ||
+           evergreen->viewport[id].PA_CL_VPORT_YOFFSET.f32All != ty) {
+               /* Note: this should also modify whatever data the context reset
+                * code uses...
+                */
+               EVERGREEN_STATECHANGE(context, pa);
+               evergreen->viewport[id].PA_CL_VPORT_XOFFSET.f32All = tx;
+               evergreen->viewport[id].PA_CL_VPORT_YOFFSET.f32All = ty;
+       }
+
+       radeonUpdateScissor(ctx);
+}
+
+void evergreenUpdateStateParameters(GLcontext * ctx, GLuint new_state) //same
+{
+       struct evergreen_fragment_program *fp =
+               (struct evergreen_fragment_program *)ctx->FragmentProgram._Current;
+       struct gl_program_parameter_list *paramList;
+
+       if (!(new_state & (_NEW_BUFFERS | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)))
+               return;
+
+       if (!ctx->FragmentProgram._Current || !fp)
+               return;
+
+       paramList = ctx->FragmentProgram._Current->Base.Parameters;
+
+       if (!paramList)
+               return;
+
+       _mesa_load_state_parameters(ctx, paramList);
+
+}
+
+/**
+ * Called by Mesa after an internal state update.
+ */
+static void evergreenInvalidateState(GLcontext * ctx, GLuint new_state) //same
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+
+    EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+
+    _swrast_InvalidateState(ctx, new_state);
+    _swsetup_InvalidateState(ctx, new_state);
+    _vbo_InvalidateState(ctx, new_state);
+    _tnl_InvalidateState(ctx, new_state);
+    _ae_invalidate_state(ctx, new_state);
+
+    if (new_state & _NEW_BUFFERS) {
+           _mesa_update_framebuffer(ctx);
+           /* this updates the DrawBuffer's Width/Height if it's a FBO */
+           _mesa_update_draw_buffer_bounds(ctx);
+
+           EVERGREEN_STATECHANGE(context, cb);
+           EVERGREEN_STATECHANGE(context, db);
+    }
+
+    if (new_state & (_NEW_LIGHT)) {
+           EVERGREEN_STATECHANGE(context, pa);
+           if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION)
+                   SETbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, PROVOKING_VTX_LAST_bit);
+           else
+                   CLEARbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, PROVOKING_VTX_LAST_bit);
+    }
+
+    evergreenUpdateStateParameters(ctx, new_state);
+
+    EVERGREEN_STATECHANGE(context, pa);
+    EVERGREEN_STATECHANGE(context, spi);
+
+    if(GL_TRUE == evergreen->bEnablePerspective)
+    {
+        /* Do scale XY and Z by 1/W0 for perspective correction on pos. For orthogonal case, set both to one. */
+        CLEARbit(evergreen->PA_CL_VTE_CNTL.u32All, VTX_XY_FMT_bit);
+        CLEARbit(evergreen->PA_CL_VTE_CNTL.u32All, VTX_Z_FMT_bit);
+
+        SETbit(evergreen->PA_CL_VTE_CNTL.u32All, VTX_W0_FMT_bit);
+
+        SETbit(evergreen->SPI_PS_IN_CONTROL_0.u32All, PERSP_GRADIENT_ENA_bit);
+        CLEARbit(evergreen->SPI_PS_IN_CONTROL_0.u32All, LINEAR_GRADIENT_ENA_bit);
+
+        SETfield(evergreen->SPI_BARYC_CNTL.u32All, 1,
+                        EG_SPI_BARYC_CNTL__PERSP_CENTROID_ENA_shift, 
+                 EG_SPI_BARYC_CNTL__PERSP_CENTROID_ENA_mask);        
+    }
+    else
+    {
+        /* For orthogonal case. */
+        SETbit(evergreen->PA_CL_VTE_CNTL.u32All, VTX_XY_FMT_bit);
+        SETbit(evergreen->PA_CL_VTE_CNTL.u32All, VTX_Z_FMT_bit);
+
+        SETbit(evergreen->PA_CL_VTE_CNTL.u32All, VTX_W0_FMT_bit);
+       
+        CLEARbit(evergreen->SPI_PS_IN_CONTROL_0.u32All, PERSP_GRADIENT_ENA_bit);
+        SETbit(evergreen->SPI_PS_IN_CONTROL_0.u32All, LINEAR_GRADIENT_ENA_bit);
+        
+        SETfield(evergreen->SPI_BARYC_CNTL.u32All, 1,
+                        EG_SPI_BARYC_CNTL__LINEAR_CENTROID_ENA_shift, 
+                 EG_SPI_BARYC_CNTL__LINEAR_CENTROID_ENA_mask);        
+    }
+
+    context->radeon.NewGLState |= new_state;
+}
+
+static void evergreenSetAlphaState(GLcontext * ctx)  //same
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       uint32_t alpha_func = REF_ALWAYS;
+       GLboolean really_enabled = ctx->Color.AlphaEnabled;
+
+       EVERGREEN_STATECHANGE(context, sx);
+
+       switch (ctx->Color.AlphaFunc) {
+       case GL_NEVER:
+               alpha_func = REF_NEVER;
+               break;
+       case GL_LESS:
+               alpha_func = REF_LESS;
+               break;
+       case GL_EQUAL:
+               alpha_func = REF_EQUAL;
+               break;
+       case GL_LEQUAL:
+               alpha_func = REF_LEQUAL;
+               break;
+       case GL_GREATER:
+               alpha_func = REF_GREATER;
+               break;
+       case GL_NOTEQUAL:
+               alpha_func = REF_NOTEQUAL;
+               break;
+       case GL_GEQUAL:
+               alpha_func = REF_GEQUAL;
+               break;
+       case GL_ALWAYS:
+               /*alpha_func = REF_ALWAYS; */
+               really_enabled = GL_FALSE;
+               break;
+       }
+
+       if (really_enabled) {
+               SETfield(evergreen->SX_ALPHA_TEST_CONTROL.u32All, alpha_func,
+                        ALPHA_FUNC_shift, ALPHA_FUNC_mask);
+               SETbit(evergreen->SX_ALPHA_TEST_CONTROL.u32All, ALPHA_TEST_ENABLE_bit);
+               evergreen->SX_ALPHA_REF.f32All = ctx->Color.AlphaRef;
+       } else {
+               CLEARbit(evergreen->SX_ALPHA_TEST_CONTROL.u32All, ALPHA_TEST_ENABLE_bit);
+       }
+}
+
+static void evergreenAlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref) //same
+{
+       (void)func;
+       (void)ref;
+       evergreenSetAlphaState(ctx);
+}
+
+static void evergreenBlendColor(GLcontext * ctx, const GLfloat cf[4]) //same
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+
+       EVERGREEN_STATECHANGE(context, cb);
+
+       evergreen->CB_BLEND_RED.f32All = cf[0];
+       evergreen->CB_BLEND_GREEN.f32All = cf[1];
+       evergreen->CB_BLEND_BLUE.f32All = cf[2];
+       evergreen->CB_BLEND_ALPHA.f32All = cf[3];
+}
+
+static int evergreenblend_factor(GLenum factor, GLboolean is_src) //same
+{
+       switch (factor) {
+       case GL_ZERO:
+               return BLEND_ZERO;
+               break;
+       case GL_ONE:
+               return BLEND_ONE;
+               break;
+       case GL_DST_COLOR:
+               return BLEND_DST_COLOR;
+               break;
+       case GL_ONE_MINUS_DST_COLOR:
+               return BLEND_ONE_MINUS_DST_COLOR;
+               break;
+       case GL_SRC_COLOR:
+               return BLEND_SRC_COLOR;
+               break;
+       case GL_ONE_MINUS_SRC_COLOR:
+               return BLEND_ONE_MINUS_SRC_COLOR;
+               break;
+       case GL_SRC_ALPHA:
+               return BLEND_SRC_ALPHA;
+               break;
+       case GL_ONE_MINUS_SRC_ALPHA:
+               return BLEND_ONE_MINUS_SRC_ALPHA;
+               break;
+       case GL_DST_ALPHA:
+               return BLEND_DST_ALPHA;
+               break;
+       case GL_ONE_MINUS_DST_ALPHA:
+               return BLEND_ONE_MINUS_DST_ALPHA;
+               break;
+       case GL_SRC_ALPHA_SATURATE:
+               return (is_src) ? BLEND_SRC_ALPHA_SATURATE : BLEND_ZERO;
+               break;
+       case GL_CONSTANT_COLOR:
+               return BLEND_CONSTANT_COLOR;
+               break;
+       case GL_ONE_MINUS_CONSTANT_COLOR:
+               return BLEND_ONE_MINUS_CONSTANT_COLOR;
+               break;
+       case GL_CONSTANT_ALPHA:
+               return BLEND_CONSTANT_ALPHA;
+               break;
+       case GL_ONE_MINUS_CONSTANT_ALPHA:
+               return BLEND_ONE_MINUS_CONSTANT_ALPHA;
+               break;
+       default:
+               fprintf(stderr, "unknown blend factor %x\n", factor);
+               return (is_src) ? BLEND_ONE : BLEND_ZERO;
+               break;
+       }
+}
+
+static void evergreenSetBlendState(GLcontext * ctx) //diff : CB_COLOR_CONTROL, CB_BLEND0_CONTROL bits
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       uint32_t blend_reg = 0, eqn, eqnA;
+
+       EVERGREEN_STATECHANGE(context, cb);
+
+       if (RGBA_LOGICOP_ENABLED(ctx) || !ctx->Color.BlendEnabled) {
+               SETfield(blend_reg,
+                        BLEND_ONE, COLOR_SRCBLEND_shift, COLOR_SRCBLEND_mask);
+               SETfield(blend_reg,
+                        BLEND_ZERO, COLOR_DESTBLEND_shift, COLOR_DESTBLEND_mask);
+               SETfield(blend_reg,
+                        COMB_DST_PLUS_SRC, COLOR_COMB_FCN_shift, COLOR_COMB_FCN_mask);
+               SETfield(blend_reg,
+                        BLEND_ONE, ALPHA_SRCBLEND_shift, ALPHA_SRCBLEND_mask);
+               SETfield(blend_reg,
+                        BLEND_ZERO, ALPHA_DESTBLEND_shift, ALPHA_DESTBLEND_mask);
+               SETfield(blend_reg,
+                        COMB_DST_PLUS_SRC, ALPHA_COMB_FCN_shift, ALPHA_COMB_FCN_mask);
+               //if (context->radeon.radeonScreen->chip_family == CHIP_FAMILY_R600)
+               //      evergreen->CB_BLEND_CONTROL.u32All = blend_reg;
+               //else
+                       evergreen->CB_BLEND0_CONTROL.u32All = blend_reg;
+               return;
+       }
+
+       SETfield(blend_reg,
+                evergreenblend_factor(ctx->Color.BlendSrcRGB, GL_TRUE),
+                COLOR_SRCBLEND_shift, COLOR_SRCBLEND_mask);
+       SETfield(blend_reg,
+                evergreenblend_factor(ctx->Color.BlendDstRGB, GL_FALSE),
+                COLOR_DESTBLEND_shift, COLOR_DESTBLEND_mask);
+
+       switch (ctx->Color.BlendEquationRGB) {
+       case GL_FUNC_ADD:
+               eqn = COMB_DST_PLUS_SRC;
+               break;
+       case GL_FUNC_SUBTRACT:
+               eqn = COMB_SRC_MINUS_DST;
+               break;
+       case GL_FUNC_REVERSE_SUBTRACT:
+               eqn = COMB_DST_MINUS_SRC;
+               break;
+       case GL_MIN:
+               eqn = COMB_MIN_DST_SRC;
+               SETfield(blend_reg,
+                        BLEND_ONE,
+                        COLOR_SRCBLEND_shift, COLOR_SRCBLEND_mask);
+               SETfield(blend_reg,
+                        BLEND_ONE,
+                        COLOR_DESTBLEND_shift, COLOR_DESTBLEND_mask);
+               break;
+       case GL_MAX:
+               eqn = COMB_MAX_DST_SRC;
+               SETfield(blend_reg,
+                        BLEND_ONE,
+                        COLOR_SRCBLEND_shift, COLOR_SRCBLEND_mask);
+               SETfield(blend_reg,
+                        BLEND_ONE,
+                        COLOR_DESTBLEND_shift, COLOR_DESTBLEND_mask);
+               break;
+
+       default:
+               fprintf(stderr,
+                       "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
+                       __FUNCTION__, __LINE__, ctx->Color.BlendEquationRGB);
+               return;
+       }
+       SETfield(blend_reg,
+                eqn, COLOR_COMB_FCN_shift, COLOR_COMB_FCN_mask);
+
+       SETfield(blend_reg,
+                evergreenblend_factor(ctx->Color.BlendSrcA, GL_TRUE),
+                ALPHA_SRCBLEND_shift, ALPHA_SRCBLEND_mask);
+       SETfield(blend_reg,
+                evergreenblend_factor(ctx->Color.BlendDstA, GL_FALSE),
+                ALPHA_DESTBLEND_shift, ALPHA_DESTBLEND_mask);
+
+       switch (ctx->Color.BlendEquationA) {
+       case GL_FUNC_ADD:
+               eqnA = COMB_DST_PLUS_SRC;
+               break;
+       case GL_FUNC_SUBTRACT:
+               eqnA = COMB_SRC_MINUS_DST;
+               break;
+       case GL_FUNC_REVERSE_SUBTRACT:
+               eqnA = COMB_DST_MINUS_SRC;
+               break;
+       case GL_MIN:
+               eqnA = COMB_MIN_DST_SRC;
+               SETfield(blend_reg,
+                        BLEND_ONE,
+                        ALPHA_SRCBLEND_shift, ALPHA_SRCBLEND_mask);
+               SETfield(blend_reg,
+                        BLEND_ONE,
+                        ALPHA_DESTBLEND_shift, ALPHA_DESTBLEND_mask);
+               break;
+       case GL_MAX:
+               eqnA = COMB_MAX_DST_SRC;
+               SETfield(blend_reg,
+                        BLEND_ONE,
+                        ALPHA_SRCBLEND_shift, ALPHA_SRCBLEND_mask);
+               SETfield(blend_reg,
+                        BLEND_ONE,
+                        ALPHA_DESTBLEND_shift, ALPHA_DESTBLEND_mask);
+               break;
+       default:
+               fprintf(stderr,
+                       "[%s:%u] Invalid A blend equation (0x%04x).\n",
+                       __FUNCTION__, __LINE__, ctx->Color.BlendEquationA);
+               return;
+       }
+
+       SETfield(blend_reg,
+                eqnA, ALPHA_COMB_FCN_shift, ALPHA_COMB_FCN_mask);
+
+       SETbit(blend_reg, SEPARATE_ALPHA_BLEND_bit);
+
+    SETbit(blend_reg, EG_CB_BLENDX_CONTROL_ENABLE_bit);
+       
+    evergreen->CB_BLEND0_CONTROL.u32All = blend_reg;   
+}
+
+static void evergreenBlendEquationSeparate(GLcontext * ctx,
+                                                     GLenum modeRGB, GLenum modeA) //same
+{
+       evergreenSetBlendState(ctx);
+}
+
+static void evergreenBlendFuncSeparate(GLcontext * ctx,
+                                 GLenum sfactorRGB, GLenum dfactorRGB,
+                                 GLenum sfactorA, GLenum dfactorA) //same
+{
+       evergreenSetBlendState(ctx);
+}
+
+static GLuint evergreen_translate_logicop(GLenum logicop) //same
+{
+       switch (logicop) {
+       case GL_CLEAR:
+               return 0x00;
+       case GL_SET:
+               return 0xff;
+       case GL_COPY:
+               return 0xcc;
+       case GL_COPY_INVERTED:
+               return 0x33;
+       case GL_NOOP:
+               return 0xaa;
+       case GL_INVERT:
+               return 0x55;
+       case GL_AND:
+               return 0x88;
+       case GL_NAND:
+               return 0x77;
+       case GL_OR:
+               return 0xee;
+       case GL_NOR:
+               return 0x11;
+       case GL_XOR:
+               return 0x66;
+       case GL_EQUIV:
+               return 0x99;
+       case GL_AND_REVERSE:
+               return 0x44;
+       case GL_AND_INVERTED:
+               return 0x22;
+       case GL_OR_REVERSE:
+               return 0xdd;
+       case GL_OR_INVERTED:
+               return 0xbb;
+       default:
+               fprintf(stderr, "unknown blend logic operation %x\n", logicop);
+               return 0xcc;
+       }
+}
+
+static void evergreenSetLogicOpState(GLcontext *ctx) //diff : CB_COLOR_CONTROL.ROP3 is actually same bits.
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+
+       EVERGREEN_STATECHANGE(context, cb);
+
+       if (RGBA_LOGICOP_ENABLED(ctx))
+               SETfield(evergreen->CB_COLOR_CONTROL.u32All,
+                        evergreen_translate_logicop(ctx->Color.LogicOp), 
+             EG_CB_COLOR_CONTROL__ROP3_shift, 
+             EG_CB_COLOR_CONTROL__ROP3_mask);
+       else
+               SETfield(evergreen->CB_COLOR_CONTROL.u32All, 0xCC, 
+             EG_CB_COLOR_CONTROL__ROP3_shift, 
+             EG_CB_COLOR_CONTROL__ROP3_mask);
+}
+
+static void evergreenClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq ) //same , but PA_CL_UCP_0_ offset diff 
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       GLint p;
+       GLint *ip;
+
+       p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
+       ip = (GLint *)ctx->Transform._ClipUserPlane[p];
+
+       EVERGREEN_STATECHANGE(context, pa);
+
+       evergreen->ucp[p].PA_CL_UCP_0_X.u32All = ip[0];
+       evergreen->ucp[p].PA_CL_UCP_0_Y.u32All = ip[1];
+       evergreen->ucp[p].PA_CL_UCP_0_Z.u32All = ip[2];
+       evergreen->ucp[p].PA_CL_UCP_0_W.u32All = ip[3];
+}
+
+static void evergreenSetClipPlaneState(GLcontext * ctx, GLenum cap, GLboolean state) //diff in func calls
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       GLuint p;
+
+       p = cap - GL_CLIP_PLANE0;
+
+       EVERGREEN_STATECHANGE(context, pa);
+
+       if (state) {
+               evergreen->PA_CL_CLIP_CNTL.u32All |= (UCP_ENA_0_bit << p);
+               evergreen->ucp[p].enabled = GL_TRUE;
+               evergreenClipPlane(ctx, cap, NULL);
+       } else {
+               evergreen->PA_CL_CLIP_CNTL.u32All &= ~(UCP_ENA_0_bit << p);
+               evergreen->ucp[p].enabled = GL_FALSE;
+       }
+}
+
+static void evergreenSetDBRenderState(GLcontext * ctx)
+{    
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+    struct evergreen_fragment_program *fp =
+            (struct evergreen_fragment_program *)(ctx->FragmentProgram._Current);
+       
+    EVERGREEN_STATECHANGE(context, db);
+
+    SETbit(evergreen->DB_SHADER_CONTROL.u32All, 
+           DUAL_EXPORT_ENABLE_bit);
+    SETfield(evergreen->DB_SHADER_CONTROL.u32All, EARLY_Z_THEN_LATE_Z, 
+             Z_ORDER_shift, 
+             Z_ORDER_mask);
+       /* XXX need to enable htile for hiz/s */
+    SETfield(evergreen->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, 
+             FORCE_HIZ_ENABLE_shift, 
+             FORCE_HIZ_ENABLE_mask);
+    SETfield(evergreen->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, 
+             FORCE_HIS_ENABLE0_shift, 
+             FORCE_HIS_ENABLE0_mask);
+    SETfield(evergreen->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, 
+             FORCE_HIS_ENABLE1_shift, 
+             FORCE_HIS_ENABLE1_mask);
+
+    if (context->radeon.query.current)
+    {
+        SETbit(evergreen->DB_RENDER_OVERRIDE.u32All, NOOP_CULL_DISABLE_bit);        
+        SETbit(evergreen->DB_COUNT_CONTROL.u32All, 
+               EG_DB_COUNT_CONTROL__PERFECT_ZPASS_COUNTS_bit);        
+    }
+    else
+    {
+        CLEARbit(evergreen->DB_RENDER_OVERRIDE.u32All, NOOP_CULL_DISABLE_bit);        
+        CLEARbit(evergreen->DB_COUNT_CONTROL.u32All, 
+                 EG_DB_COUNT_CONTROL__PERFECT_ZPASS_COUNTS_bit);        
+    }
+
+    if (fp)
+    {
+        if (fp->r700Shader.killIsUsed)
+        {
+            SETbit(evergreen->DB_SHADER_CONTROL.u32All, KILL_ENABLE_bit);
+        }
+        else
+        {
+            CLEARbit(evergreen->DB_SHADER_CONTROL.u32All, KILL_ENABLE_bit);
+        }
+
+        if (fp->r700Shader.depthIsExported)
+        {
+            SETbit(evergreen->DB_SHADER_CONTROL.u32All, Z_EXPORT_ENABLE_bit);
+        }
+        else
+        {
+            CLEARbit(evergreen->DB_SHADER_CONTROL.u32All, Z_EXPORT_ENABLE_bit);
+        }
+    }    
+}
+
+void evergreenUpdateShaderStates(GLcontext * ctx)
+{
+       evergreenSetDBRenderState(ctx);
+       evergreenUpdateTextureState(ctx);
+}
+
+static void evergreenSetDepthState(GLcontext * ctx) //same
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+
+       EVERGREEN_STATECHANGE(context, db);
+
+    if (ctx->Depth.Test)
+    {
+        SETbit(evergreen->DB_DEPTH_CONTROL.u32All, Z_ENABLE_bit);
+        if (ctx->Depth.Mask)
+        {
+            SETbit(evergreen->DB_DEPTH_CONTROL.u32All, Z_WRITE_ENABLE_bit);
+        }
+        else
+        {
+            CLEARbit(evergreen->DB_DEPTH_CONTROL.u32All, Z_WRITE_ENABLE_bit);
+        }
+
+        switch (ctx->Depth.Func)
+        {
+        case GL_NEVER:
+            SETfield(evergreen->DB_DEPTH_CONTROL.u32All, FRAG_NEVER,
+                     ZFUNC_shift, ZFUNC_mask);
+            break;
+        case GL_LESS:
+            SETfield(evergreen->DB_DEPTH_CONTROL.u32All, FRAG_LESS,
+                     ZFUNC_shift, ZFUNC_mask);
+            break;
+        case GL_EQUAL:
+            SETfield(evergreen->DB_DEPTH_CONTROL.u32All, FRAG_EQUAL,
+                     ZFUNC_shift, ZFUNC_mask);
+            break;
+        case GL_LEQUAL:
+            SETfield(evergreen->DB_DEPTH_CONTROL.u32All, FRAG_LEQUAL,
+                     ZFUNC_shift, ZFUNC_mask);
+            break;
+        case GL_GREATER:
+            SETfield(evergreen->DB_DEPTH_CONTROL.u32All, FRAG_GREATER,
+                     ZFUNC_shift, ZFUNC_mask);
+            break;
+        case GL_NOTEQUAL:
+            SETfield(evergreen->DB_DEPTH_CONTROL.u32All, FRAG_NOTEQUAL,
+                     ZFUNC_shift, ZFUNC_mask);
+            break;
+        case GL_GEQUAL:
+            SETfield(evergreen->DB_DEPTH_CONTROL.u32All, FRAG_GEQUAL,
+                     ZFUNC_shift, ZFUNC_mask);
+            break;
+        case GL_ALWAYS:
+            SETfield(evergreen->DB_DEPTH_CONTROL.u32All, FRAG_ALWAYS,
+                     ZFUNC_shift, ZFUNC_mask);
+            break;
+        default:
+            SETfield(evergreen->DB_DEPTH_CONTROL.u32All, FRAG_ALWAYS,
+                     ZFUNC_shift, ZFUNC_mask);
+            break;
+        }
+    }
+    else    
+    {
+        CLEARbit(evergreen->DB_DEPTH_CONTROL.u32All, Z_ENABLE_bit);
+        CLEARbit(evergreen->DB_DEPTH_CONTROL.u32All, Z_WRITE_ENABLE_bit);
+    }
+}
+
+static void evergreenSetStencilState(GLcontext * ctx, GLboolean state)  //same
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       GLboolean hw_stencil = GL_FALSE;
+
+       if (ctx->DrawBuffer) {
+               struct radeon_renderbuffer *rrbStencil
+                       = radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
+               hw_stencil = (rrbStencil && rrbStencil->bo);
+       }
+
+       if (hw_stencil) {
+               EVERGREEN_STATECHANGE(context, db);
+               if (state) {
+                       SETbit(evergreen->DB_DEPTH_CONTROL.u32All, STENCIL_ENABLE_bit);
+                       SETbit(evergreen->DB_DEPTH_CONTROL.u32All, BACKFACE_ENABLE_bit);
+               } else
+                       CLEARbit(evergreen->DB_DEPTH_CONTROL.u32All, STENCIL_ENABLE_bit);
+       }
+}
+
+static void evergreenUpdateCulling(GLcontext * ctx) //same
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+
+    EVERGREEN_STATECHANGE(context, pa);
+
+    CLEARbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, FACE_bit);
+    CLEARbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, CULL_FRONT_bit);
+    CLEARbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, CULL_BACK_bit);
+
+    if (ctx->Polygon.CullFlag)
+    {
+        switch (ctx->Polygon.CullFaceMode)
+        {
+        case GL_FRONT:
+            SETbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, CULL_FRONT_bit);
+            CLEARbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, CULL_BACK_bit);
+            break;
+        case GL_BACK:
+            CLEARbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, CULL_FRONT_bit);
+            SETbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, CULL_BACK_bit);
+            break;
+        case GL_FRONT_AND_BACK:
+            SETbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, CULL_FRONT_bit);
+            SETbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, CULL_BACK_bit);
+            break;
+        default:
+            CLEARbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, CULL_FRONT_bit);
+            CLEARbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, CULL_BACK_bit);
+            break;
+        }
+    }
+
+    switch (ctx->Polygon.FrontFace)
+    {
+        case GL_CW:
+            SETbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, FACE_bit);
+            break;
+        case GL_CCW:
+            CLEARbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, FACE_bit);
+            break;
+        default:
+            CLEARbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, FACE_bit); /* default: ccw */
+            break;
+    }
+
+    /* Winding is inverted when rendering to FBO */
+    if (ctx->DrawBuffer && ctx->DrawBuffer->Name)
+           evergreen->PA_SU_SC_MODE_CNTL.u32All ^= FACE_bit;
+}
+
+static void evergreenSetPolygonOffsetState(GLcontext * ctx, GLboolean state) //same
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+
+       EVERGREEN_STATECHANGE(context, pa);
+
+       if (state) {
+               SETbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, POLY_OFFSET_FRONT_ENABLE_bit);
+               SETbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, POLY_OFFSET_BACK_ENABLE_bit);
+               SETbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, POLY_OFFSET_PARA_ENABLE_bit);
+       } else {
+               CLEARbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, POLY_OFFSET_FRONT_ENABLE_bit);
+               CLEARbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, POLY_OFFSET_BACK_ENABLE_bit);
+               CLEARbit(evergreen->PA_SU_SC_MODE_CNTL.u32All, POLY_OFFSET_PARA_ENABLE_bit);
+       }
+}
+
+static void evergreenUpdateLineStipple(GLcontext * ctx) //diff
+{
+       /* TODO */
+}
+
+void evergreenSetScissor(context_t *context) //diff
+{
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       unsigned x1, y1, x2, y2;
+       int id = 0;
+       struct radeon_renderbuffer *rrb;
+
+       rrb = radeon_get_colorbuffer(&context->radeon);
+       if (!rrb || !rrb->bo) {
+               return;
+       }
+       if (context->radeon.state.scissor.enabled) {
+               x1 = context->radeon.state.scissor.rect.x1;
+               y1 = context->radeon.state.scissor.rect.y1;
+               x2 = context->radeon.state.scissor.rect.x2;
+               y2 = context->radeon.state.scissor.rect.y2;
+               /* r600 has exclusive BR scissors */
+               if (context->radeon.radeonScreen->kernel_mm) {
+                       x2++;
+                       y2++;
+               }
+       } else {
+               if (context->radeon.radeonScreen->driScreen->dri2.enabled) {
+                       x1 = 0;
+                       y1 = 0;
+                       x2 = rrb->base.Width;
+                       y2 = rrb->base.Height;
+               } else {
+                       x1 = rrb->dPriv->x;
+                       y1 = rrb->dPriv->y;
+                       x2 = rrb->dPriv->x + rrb->dPriv->w;
+                       y2 = rrb->dPriv->y + rrb->dPriv->h;
+               }
+       }
+
+       EVERGREEN_STATECHANGE(context, pa);
+
+       /* screen */
+    /* TODO : check WINDOW_OFFSET_DISABLE */
+       //SETbit(evergreen->PA_SC_SCREEN_SCISSOR_TL.u32All, WINDOW_OFFSET_DISABLE_bit);
+       SETfield(evergreen->PA_SC_SCREEN_SCISSOR_TL.u32All, x1,
+                PA_SC_SCREEN_SCISSOR_TL__TL_X_shift, EG_PA_SC_SCREEN_SCISSOR_TL__TL_X_mask);
+       SETfield(evergreen->PA_SC_SCREEN_SCISSOR_TL.u32All, y1,
+                PA_SC_SCREEN_SCISSOR_TL__TL_Y_shift, EG_PA_SC_SCREEN_SCISSOR_TL__TL_Y_mask);
+
+       SETfield(evergreen->PA_SC_SCREEN_SCISSOR_BR.u32All, x2,
+                PA_SC_SCREEN_SCISSOR_BR__BR_X_shift, EG_PA_SC_SCREEN_SCISSOR_BR__BR_X_mask);
+       SETfield(evergreen->PA_SC_SCREEN_SCISSOR_BR.u32All, y2,
+                PA_SC_SCREEN_SCISSOR_BR__BR_Y_shift, EG_PA_SC_SCREEN_SCISSOR_BR__BR_Y_mask);
+
+       /* window */
+       SETbit(evergreen->PA_SC_WINDOW_SCISSOR_TL.u32All, WINDOW_OFFSET_DISABLE_bit);
+       SETfield(evergreen->PA_SC_WINDOW_SCISSOR_TL.u32All, x1,
+                PA_SC_WINDOW_SCISSOR_TL__TL_X_shift, EG_PA_SC_WINDOW_SCISSOR_TL__TL_X_mask);
+       SETfield(evergreen->PA_SC_WINDOW_SCISSOR_TL.u32All, y1,
+                PA_SC_WINDOW_SCISSOR_TL__TL_Y_shift, EG_PA_SC_WINDOW_SCISSOR_TL__TL_Y_mask);
+
+       SETfield(evergreen->PA_SC_WINDOW_SCISSOR_BR.u32All, x2,
+                PA_SC_WINDOW_SCISSOR_BR__BR_X_shift, EG_PA_SC_WINDOW_SCISSOR_BR__BR_X_mask);
+       SETfield(evergreen->PA_SC_WINDOW_SCISSOR_BR.u32All, y2,
+                PA_SC_WINDOW_SCISSOR_BR__BR_Y_shift, EG_PA_SC_WINDOW_SCISSOR_BR__BR_Y_mask);
+
+
+       SETfield(evergreen->PA_SC_CLIPRECT_0_TL.u32All, x1,
+                PA_SC_CLIPRECT_0_TL__TL_X_shift, EG_PA_SC_CLIPRECT_0_TL__TL_X_mask);
+       SETfield(evergreen->PA_SC_CLIPRECT_0_TL.u32All, y1,
+                PA_SC_CLIPRECT_0_TL__TL_Y_shift, EG_PA_SC_CLIPRECT_0_TL__TL_Y_mask);
+       SETfield(evergreen->PA_SC_CLIPRECT_0_BR.u32All, x2,
+                PA_SC_CLIPRECT_0_BR__BR_X_shift, EG_PA_SC_CLIPRECT_0_BR__BR_X_mask);
+       SETfield(evergreen->PA_SC_CLIPRECT_0_BR.u32All, y2,
+                PA_SC_CLIPRECT_0_BR__BR_Y_shift, EG_PA_SC_CLIPRECT_0_BR__BR_Y_mask);
+
+       evergreen->PA_SC_CLIPRECT_1_TL.u32All = evergreen->PA_SC_CLIPRECT_0_TL.u32All;
+       evergreen->PA_SC_CLIPRECT_1_BR.u32All = evergreen->PA_SC_CLIPRECT_0_BR.u32All;
+       evergreen->PA_SC_CLIPRECT_2_TL.u32All = evergreen->PA_SC_CLIPRECT_0_TL.u32All;
+       evergreen->PA_SC_CLIPRECT_2_BR.u32All = evergreen->PA_SC_CLIPRECT_0_BR.u32All;
+       evergreen->PA_SC_CLIPRECT_3_TL.u32All = evergreen->PA_SC_CLIPRECT_0_TL.u32All;
+       evergreen->PA_SC_CLIPRECT_3_BR.u32All = evergreen->PA_SC_CLIPRECT_0_BR.u32All;
+
+       /* more....2d clip */
+       SETbit(evergreen->PA_SC_GENERIC_SCISSOR_TL.u32All, WINDOW_OFFSET_DISABLE_bit);
+       SETfield(evergreen->PA_SC_GENERIC_SCISSOR_TL.u32All, x1,
+                PA_SC_GENERIC_SCISSOR_TL__TL_X_shift, EG_PA_SC_GENERIC_SCISSOR_TL__TL_X_mask);
+       SETfield(evergreen->PA_SC_GENERIC_SCISSOR_TL.u32All, y1,
+                PA_SC_GENERIC_SCISSOR_TL__TL_Y_shift, EG_PA_SC_GENERIC_SCISSOR_TL__TL_Y_mask);
+       SETfield(evergreen->PA_SC_GENERIC_SCISSOR_BR.u32All, x2,
+                PA_SC_GENERIC_SCISSOR_BR__BR_X_shift, EG_PA_SC_GENERIC_SCISSOR_BR__BR_X_mask);
+       SETfield(evergreen->PA_SC_GENERIC_SCISSOR_BR.u32All, y2,
+                PA_SC_GENERIC_SCISSOR_BR__BR_Y_shift, EG_PA_SC_GENERIC_SCISSOR_BR__BR_Y_mask);
+
+       SETbit(evergreen->viewport[id].PA_SC_VPORT_SCISSOR_0_TL.u32All, WINDOW_OFFSET_DISABLE_bit);
+       SETfield(evergreen->viewport[id].PA_SC_VPORT_SCISSOR_0_TL.u32All, x1,
+                PA_SC_VPORT_SCISSOR_0_TL__TL_X_shift, EG_PA_SC_VPORT_SCISSOR_0_TL__TL_X_mask);
+       SETfield(evergreen->viewport[id].PA_SC_VPORT_SCISSOR_0_TL.u32All, y1,
+                PA_SC_VPORT_SCISSOR_0_TL__TL_Y_shift, EG_PA_SC_VPORT_SCISSOR_0_TL__TL_Y_mask);
+       SETfield(evergreen->viewport[id].PA_SC_VPORT_SCISSOR_0_BR.u32All, x2,
+                PA_SC_VPORT_SCISSOR_0_BR__BR_X_shift, EG_PA_SC_VPORT_SCISSOR_0_BR__BR_X_mask);
+       SETfield(evergreen->viewport[id].PA_SC_VPORT_SCISSOR_0_BR.u32All, y2,
+                PA_SC_VPORT_SCISSOR_0_BR__BR_Y_shift, EG_PA_SC_VPORT_SCISSOR_0_BR__BR_Y_mask);
+
+    id = 1;
+    SETbit(evergreen->viewport[id].PA_SC_VPORT_SCISSOR_0_TL.u32All, WINDOW_OFFSET_DISABLE_bit);
+       SETfield(evergreen->viewport[id].PA_SC_VPORT_SCISSOR_0_TL.u32All, x1,
+                PA_SC_VPORT_SCISSOR_0_TL__TL_X_shift, EG_PA_SC_VPORT_SCISSOR_0_TL__TL_X_mask);
+       SETfield(evergreen->viewport[id].PA_SC_VPORT_SCISSOR_0_TL.u32All, y1,
+                PA_SC_VPORT_SCISSOR_0_TL__TL_Y_shift, EG_PA_SC_VPORT_SCISSOR_0_TL__TL_Y_mask);
+       SETfield(evergreen->viewport[id].PA_SC_VPORT_SCISSOR_0_BR.u32All, x2,
+                PA_SC_VPORT_SCISSOR_0_BR__BR_X_shift, EG_PA_SC_VPORT_SCISSOR_0_BR__BR_X_mask);
+       SETfield(evergreen->viewport[id].PA_SC_VPORT_SCISSOR_0_BR.u32All, y2,
+                PA_SC_VPORT_SCISSOR_0_BR__BR_Y_shift, EG_PA_SC_VPORT_SCISSOR_0_BR__BR_Y_mask);
+
+       evergreen->viewport[id].enabled = GL_TRUE;
+}
+
+static void evergreenUpdateWindow(GLcontext * ctx, int id) //diff in calling evergreenSetScissor
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       __DRIdrawable *dPriv = radeon_get_drawable(&context->radeon);
+       GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0;
+       GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0;
+       const GLfloat *v = ctx->Viewport._WindowMap.m;
+       const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+       const GLboolean render_to_fbo = (ctx->DrawBuffer->Name != 0);
+       GLfloat y_scale, y_bias;
+
+       if (render_to_fbo) {
+               y_scale = 1.0;
+               y_bias = 0;
+       } else {
+               y_scale = -1.0;
+               y_bias = yoffset;
+       }
+
+       GLfloat sx = v[MAT_SX];
+       GLfloat tx = v[MAT_TX] + xoffset;
+       GLfloat sy = v[MAT_SY] * y_scale;
+       GLfloat ty = (v[MAT_TY] * y_scale) + y_bias;
+       GLfloat sz = v[MAT_SZ] * depthScale;
+       GLfloat tz = v[MAT_TZ] * depthScale;
+
+       EVERGREEN_STATECHANGE(context, pa);
+       
+
+       evergreen->viewport[id].PA_CL_VPORT_XSCALE.f32All  = sx;
+       evergreen->viewport[id].PA_CL_VPORT_XOFFSET.f32All = tx;
+
+       evergreen->viewport[id].PA_CL_VPORT_YSCALE.f32All  = sy;
+       evergreen->viewport[id].PA_CL_VPORT_YOFFSET.f32All = ty;
+
+       evergreen->viewport[id].PA_CL_VPORT_ZSCALE.f32All  = sz;
+       evergreen->viewport[id].PA_CL_VPORT_ZOFFSET.f32All = tz;
+
+       if (ctx->Transform.DepthClamp) {
+               evergreen->viewport[id].PA_SC_VPORT_ZMIN_0.f32All = MIN2(ctx->Viewport.Near, ctx->Viewport.Far);
+               evergreen->viewport[id].PA_SC_VPORT_ZMAX_0.f32All = MAX2(ctx->Viewport.Near, ctx->Viewport.Far);
+               SETbit(evergreen->PA_CL_CLIP_CNTL.u32All, ZCLIP_NEAR_DISABLE_bit);
+               SETbit(evergreen->PA_CL_CLIP_CNTL.u32All, ZCLIP_FAR_DISABLE_bit);
+       } else {
+               evergreen->viewport[id].PA_SC_VPORT_ZMIN_0.f32All = 0.0;
+               evergreen->viewport[id].PA_SC_VPORT_ZMAX_0.f32All = 1.0;
+               CLEARbit(evergreen->PA_CL_CLIP_CNTL.u32All, ZCLIP_NEAR_DISABLE_bit);
+               CLEARbit(evergreen->PA_CL_CLIP_CNTL.u32All, ZCLIP_FAR_DISABLE_bit);
+       }
+
+       evergreen->viewport[id].enabled = GL_TRUE;
+
+       evergreenSetScissor(context);
+}
+
+static void evergreenEnable(GLcontext * ctx, GLenum cap, GLboolean state) //diff in func calls
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+
+       switch (cap) {
+       case GL_TEXTURE_1D:
+       case GL_TEXTURE_2D:
+       case GL_TEXTURE_3D:
+               /* empty */
+               break;
+       case GL_FOG:
+               /* empty */
+               break;
+       case GL_ALPHA_TEST:
+               evergreenSetAlphaState(ctx);
+               break;
+       case GL_COLOR_LOGIC_OP:
+               evergreenSetLogicOpState(ctx);
+               /* fall-through, because logic op overrides blending */
+       case GL_BLEND:
+               evergreenSetBlendState(ctx);
+               break;
+       case GL_CLIP_PLANE0:
+       case GL_CLIP_PLANE1:
+       case GL_CLIP_PLANE2:
+       case GL_CLIP_PLANE3:
+       case GL_CLIP_PLANE4:
+       case GL_CLIP_PLANE5:
+               evergreenSetClipPlaneState(ctx, cap, state);
+               break;
+       case GL_DEPTH_TEST:
+               evergreenSetDepthState(ctx);
+               break;
+       case GL_STENCIL_TEST:
+               evergreenSetStencilState(ctx, state);
+               break;
+       case GL_CULL_FACE:
+               evergreenUpdateCulling(ctx);
+               break;
+       case GL_POLYGON_OFFSET_POINT:
+       case GL_POLYGON_OFFSET_LINE:
+       case GL_POLYGON_OFFSET_FILL:
+               evergreenSetPolygonOffsetState(ctx, state);
+               break;
+       case GL_SCISSOR_TEST:
+               radeon_firevertices(&context->radeon);
+               context->radeon.state.scissor.enabled = state;
+               radeonUpdateScissor(ctx);
+               break;
+       case GL_LINE_STIPPLE:
+               evergreenUpdateLineStipple(ctx);
+               break;
+       case GL_DEPTH_CLAMP:
+               evergreenUpdateWindow(ctx, 0);
+               break;
+       default:
+               break;
+       }
+
+}
+
+static void evergreenColorMask(GLcontext * ctx,
+                         GLboolean r, GLboolean g, GLboolean b, GLboolean a) //same
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       unsigned int mask = ((r ? 1 : 0) |
+                            (g ? 2 : 0) |
+                            (b ? 4 : 0) |
+                            (a ? 8 : 0));
+
+       if (mask != evergreen->CB_TARGET_MASK.u32All) {
+               EVERGREEN_STATECHANGE(context, cb);
+               SETfield(evergreen->CB_TARGET_MASK.u32All, mask, TARGET0_ENABLE_shift, TARGET0_ENABLE_mask);
+       }
+}
+
+static void evergreenDepthFunc(GLcontext * ctx, GLenum func) //same
+{
+    evergreenSetDepthState(ctx);
+}
+
+static void evergreenDepthMask(GLcontext * ctx, GLboolean mask) //same
+{
+    evergreenSetDepthState(ctx);
+}
+
+static void evergreenCullFace(GLcontext * ctx, GLenum mode) //same
+{
+    evergreenUpdateCulling(ctx);
+}
+
+static void evergreenFogfv(GLcontext * ctx, GLenum pname, const GLfloat * param) //same
+{
+}
+
+static void evergreenUpdatePolygonMode(GLcontext * ctx) //same
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+
+       EVERGREEN_STATECHANGE(context, pa);
+
+       SETfield(evergreen->PA_SU_SC_MODE_CNTL.u32All, X_DISABLE_POLY_MODE, POLY_MODE_shift, POLY_MODE_mask);
+
+       /* Only do something if a polygon mode is wanted, default is GL_FILL */
+       if (ctx->Polygon.FrontMode != GL_FILL ||
+           ctx->Polygon.BackMode != GL_FILL) {
+               GLenum f, b;
+
+               /* Handle GL_CW (clock wise and GL_CCW (counter clock wise)
+                * correctly by selecting the correct front and back face
+                */
+               f = ctx->Polygon.FrontMode;
+               b = ctx->Polygon.BackMode;
+
+               /* Enable polygon mode */
+               SETfield(evergreen->PA_SU_SC_MODE_CNTL.u32All, X_DUAL_MODE, POLY_MODE_shift, POLY_MODE_mask);
+
+               switch (f) {
+               case GL_LINE:
+                       SETfield(evergreen->PA_SU_SC_MODE_CNTL.u32All, X_DRAW_LINES,
+                                POLYMODE_FRONT_PTYPE_shift, POLYMODE_FRONT_PTYPE_mask);
+                       break;
+               case GL_POINT:
+                       SETfield(evergreen->PA_SU_SC_MODE_CNTL.u32All, X_DRAW_POINTS,
+                                POLYMODE_FRONT_PTYPE_shift, POLYMODE_FRONT_PTYPE_mask);
+                       break;
+               case GL_FILL:
+                       SETfield(evergreen->PA_SU_SC_MODE_CNTL.u32All, X_DRAW_TRIANGLES,
+                                POLYMODE_FRONT_PTYPE_shift, POLYMODE_FRONT_PTYPE_mask);
+                       break;
+               }
+
+               switch (b) {
+               case GL_LINE:
+                       SETfield(evergreen->PA_SU_SC_MODE_CNTL.u32All, X_DRAW_LINES,
+                                POLYMODE_BACK_PTYPE_shift, POLYMODE_BACK_PTYPE_mask);
+                       break;
+               case GL_POINT:
+                       SETfield(evergreen->PA_SU_SC_MODE_CNTL.u32All, X_DRAW_POINTS,
+                                POLYMODE_BACK_PTYPE_shift, POLYMODE_BACK_PTYPE_mask);
+                       break;
+               case GL_FILL:
+                       SETfield(evergreen->PA_SU_SC_MODE_CNTL.u32All, X_DRAW_TRIANGLES,
+                                POLYMODE_BACK_PTYPE_shift, POLYMODE_BACK_PTYPE_mask);
+                       break;
+               }
+       }
+}
+
+static void evergreenFrontFace(GLcontext * ctx, GLenum mode) //same
+{
+    evergreenUpdateCulling(ctx);
+    evergreenUpdatePolygonMode(ctx);
+}
+
+static void evergreenShadeModel(GLcontext * ctx, GLenum mode) //same
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+
+       EVERGREEN_STATECHANGE(context, spi);
+
+       /* also need to set/clear FLAT_SHADE bit per param in SPI_PS_INPUT_CNTL_[0-31] */
+       switch (mode) {
+       case GL_FLAT:
+               SETbit(evergreen->SPI_INTERP_CONTROL_0.u32All, FLAT_SHADE_ENA_bit);
+               break;
+       case GL_SMOOTH:
+               CLEARbit(evergreen->SPI_INTERP_CONTROL_0.u32All, FLAT_SHADE_ENA_bit);
+               break;
+       default:
+               return;
+       }
+}
+
+static void evergreenLogicOpcode(GLcontext *ctx, GLenum logicop) //diff
+{
+       if (RGBA_LOGICOP_ENABLED(ctx))
+               evergreenSetLogicOpState(ctx);
+}
+
+static void evergreenPointSize(GLcontext * ctx, GLfloat size) //same
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+
+       EVERGREEN_STATECHANGE(context, pa);
+
+       /* We need to clamp to user defined range here, because
+        * the HW clamping happens only for per vertex point size. */
+       size = CLAMP(size, ctx->Point.MinSize, ctx->Point.MaxSize);
+
+       /* same size limits for AA, non-AA points */
+       size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);
+
+       /* format is 12.4 fixed point */
+       SETfield(evergreen->PA_SU_POINT_SIZE.u32All, (int)(size * 8.0),
+                PA_SU_POINT_SIZE__HEIGHT_shift, PA_SU_POINT_SIZE__HEIGHT_mask);
+       SETfield(evergreen->PA_SU_POINT_SIZE.u32All, (int)(size * 8.0),
+                PA_SU_POINT_SIZE__WIDTH_shift, PA_SU_POINT_SIZE__WIDTH_mask);
+
+}
+
+static void evergreenPointParameter(GLcontext * ctx, GLenum pname, const GLfloat * param) //same
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+
+       EVERGREEN_STATECHANGE(context, pa);
+
+       /* format is 12.4 fixed point */
+       switch (pname) {
+       case GL_POINT_SIZE_MIN:
+               SETfield(evergreen->PA_SU_POINT_MINMAX.u32All, (int)(ctx->Point.MinSize * 8.0),
+                        MIN_SIZE_shift, MIN_SIZE_mask);
+               evergreenPointSize(ctx, ctx->Point.Size);
+               break;
+       case GL_POINT_SIZE_MAX:
+               SETfield(evergreen->PA_SU_POINT_MINMAX.u32All, (int)(ctx->Point.MaxSize * 8.0),
+                        MAX_SIZE_shift, MAX_SIZE_mask);
+               evergreenPointSize(ctx, ctx->Point.Size);
+               break;
+       case GL_POINT_DISTANCE_ATTENUATION:
+               break;
+       case GL_POINT_FADE_THRESHOLD_SIZE:
+               break;
+       default:
+               break;
+       }
+}
+
+static int evergreen_translate_stencil_func(int func) //same
+{
+       switch (func) {
+       case GL_NEVER:
+               return REF_NEVER;
+       case GL_LESS:
+               return REF_LESS;
+       case GL_EQUAL:
+               return REF_EQUAL;
+       case GL_LEQUAL:
+               return REF_LEQUAL;
+       case GL_GREATER:
+               return REF_GREATER;
+       case GL_NOTEQUAL:
+               return REF_NOTEQUAL;
+       case GL_GEQUAL:
+               return REF_GEQUAL;
+       case GL_ALWAYS:
+               return REF_ALWAYS;
+       }
+       return 0;
+}
+
+static void evergreenStencilFuncSeparate(GLcontext * ctx, GLenum face,
+                                   GLenum func, GLint ref, GLuint mask) //same
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       const unsigned back = ctx->Stencil._BackFace;
+
+       
+       EVERGREEN_STATECHANGE(context, db);
+
+       //front
+       SETfield(evergreen->DB_STENCILREFMASK.u32All, ctx->Stencil.Ref[0],
+                STENCILREF_shift, STENCILREF_mask);
+       SETfield(evergreen->DB_STENCILREFMASK.u32All, ctx->Stencil.ValueMask[0],
+                STENCILMASK_shift, STENCILMASK_mask);
+
+       SETfield(evergreen->DB_DEPTH_CONTROL.u32All, evergreen_translate_stencil_func(ctx->Stencil.Function[0]),
+                STENCILFUNC_shift, STENCILFUNC_mask);
+
+       //back
+       SETfield(evergreen->DB_STENCILREFMASK_BF.u32All, ctx->Stencil.Ref[back],
+                STENCILREF_BF_shift, STENCILREF_BF_mask);
+       SETfield(evergreen->DB_STENCILREFMASK_BF.u32All, ctx->Stencil.ValueMask[back],
+                STENCILMASK_BF_shift, STENCILMASK_BF_mask);
+
+       SETfield(evergreen->DB_DEPTH_CONTROL.u32All, evergreen_translate_stencil_func(ctx->Stencil.Function[back]),
+                STENCILFUNC_BF_shift, STENCILFUNC_BF_mask);
+}
+
+static void evergreenStencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask) //same
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       const unsigned back = ctx->Stencil._BackFace;
+
+       EVERGREEN_STATECHANGE(context, db);
+
+       // front
+       SETfield(evergreen->DB_STENCILREFMASK.u32All, ctx->Stencil.WriteMask[0],
+                STENCILWRITEMASK_shift, STENCILWRITEMASK_mask);
+
+       // back
+       SETfield(evergreen->DB_STENCILREFMASK_BF.u32All, ctx->Stencil.WriteMask[back],
+                STENCILWRITEMASK_BF_shift, STENCILWRITEMASK_BF_mask);
+
+}
+
+static int evergreen_translate_stencil_op(int op) //same
+{
+       switch (op) {
+       case GL_KEEP:
+               return STENCIL_KEEP;
+       case GL_ZERO:
+               return STENCIL_ZERO;
+       case GL_REPLACE:
+               return STENCIL_REPLACE;
+       case GL_INCR:
+               return STENCIL_INCR_CLAMP;
+       case GL_DECR:
+               return STENCIL_DECR_CLAMP;
+       case GL_INCR_WRAP_EXT:
+               return STENCIL_INCR_WRAP;
+       case GL_DECR_WRAP_EXT:
+               return STENCIL_DECR_WRAP;
+       case GL_INVERT:
+               return STENCIL_INVERT;
+       default:
+               WARN_ONCE("Do not know how to translate stencil op");
+               return STENCIL_KEEP;
+       }
+       return 0;
+}
+
+static void evergreenStencilOpSeparate(GLcontext * ctx, GLenum face,
+                                 GLenum fail, GLenum zfail, GLenum zpass) //same
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       const unsigned back = ctx->Stencil._BackFace;
+
+       EVERGREEN_STATECHANGE(context, db);
+
+       SETfield(evergreen->DB_DEPTH_CONTROL.u32All, evergreen_translate_stencil_op(ctx->Stencil.FailFunc[0]),
+                STENCILFAIL_shift, STENCILFAIL_mask);
+       SETfield(evergreen->DB_DEPTH_CONTROL.u32All, evergreen_translate_stencil_op(ctx->Stencil.ZFailFunc[0]),
+                STENCILZFAIL_shift, STENCILZFAIL_mask);
+       SETfield(evergreen->DB_DEPTH_CONTROL.u32All, evergreen_translate_stencil_op(ctx->Stencil.ZPassFunc[0]),
+                STENCILZPASS_shift, STENCILZPASS_mask);
+
+       SETfield(evergreen->DB_DEPTH_CONTROL.u32All, evergreen_translate_stencil_op(ctx->Stencil.FailFunc[back]),
+                STENCILFAIL_BF_shift, STENCILFAIL_BF_mask);
+       SETfield(evergreen->DB_DEPTH_CONTROL.u32All, evergreen_translate_stencil_op(ctx->Stencil.ZFailFunc[back]),
+                STENCILZFAIL_BF_shift, STENCILZFAIL_BF_mask);
+       SETfield(evergreen->DB_DEPTH_CONTROL.u32All, evergreen_translate_stencil_op(ctx->Stencil.ZPassFunc[back]),
+                STENCILZPASS_BF_shift, STENCILZPASS_BF_mask);
+}
+
+static void evergreenViewport(GLcontext * ctx,
+                         GLint x,
+                         GLint y,
+                        GLsizei width,
+                         GLsizei height) //diff in evergreenUpdateWindow
+{
+       evergreenUpdateWindow(ctx, 0);
+
+       radeon_viewport(ctx, x, y, width, height);
+}
+
+static void evergreenDepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval) //diff in evergreenUpdateWindow
+{
+       evergreenUpdateWindow(ctx, 0);
+}
+
+static void evergreenLineWidth(GLcontext * ctx, GLfloat widthf) //same
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+    uint32_t lineWidth = (uint32_t)((widthf * 0.5) * (1 << 4));
+
+    EVERGREEN_STATECHANGE(context, pa);
+
+    if (lineWidth > 0xFFFF)
+           lineWidth = 0xFFFF;
+    SETfield(evergreen->PA_SU_LINE_CNTL.u32All,(uint16_t)lineWidth,
+            PA_SU_LINE_CNTL__WIDTH_shift, PA_SU_LINE_CNTL__WIDTH_mask);
+}
+
+static void evergreenLineStipple(GLcontext *ctx, GLint factor, GLushort pattern) //same
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+
+    EVERGREEN_STATECHANGE(context, pa);
+
+    SETfield(evergreen->PA_SC_LINE_STIPPLE.u32All, pattern, LINE_PATTERN_shift, LINE_PATTERN_mask);
+    SETfield(evergreen->PA_SC_LINE_STIPPLE.u32All, (factor-1), REPEAT_COUNT_shift, REPEAT_COUNT_mask);
+    SETfield(evergreen->PA_SC_LINE_STIPPLE.u32All, 1, AUTO_RESET_CNTL_shift, AUTO_RESET_CNTL_mask);
+}
+
+static void evergreenPolygonOffset(GLcontext * ctx, GLfloat factor, GLfloat units) //diff :
+                                                                    //all register here offset diff, bits same
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+       GLfloat constant = units;
+       GLchar depth = 0;
+
+       EVERGREEN_STATECHANGE(context, pa);
+
+       switch (ctx->Visual.depthBits) {
+       case 16:
+               constant *= 4.0;
+               depth = -16;
+               break;
+       case 24:
+               constant *= 2.0;
+               depth = -24;
+               break;
+       }
+
+       factor *= 12.0;
+       SETfield(evergreen->PA_SU_POLY_OFFSET_DB_FMT_CNTL.u32All, depth,
+                POLY_OFFSET_NEG_NUM_DB_BITS_shift, POLY_OFFSET_NEG_NUM_DB_BITS_mask);
+       //evergreen->PA_SU_POLY_OFFSET_CLAMP.f32All = constant; //???
+       evergreen->PA_SU_POLY_OFFSET_FRONT_SCALE.f32All = factor;
+       evergreen->PA_SU_POLY_OFFSET_FRONT_OFFSET.f32All = constant;
+       evergreen->PA_SU_POLY_OFFSET_BACK_SCALE.f32All = factor;
+       evergreen->PA_SU_POLY_OFFSET_BACK_OFFSET.f32All = constant;
+}
+
+static void evergreenPolygonMode(GLcontext * ctx, GLenum face, GLenum mode) //same
+{
+       (void)face;
+       (void)mode;
+
+       evergreenUpdatePolygonMode(ctx);
+}
+
+static void evergreenRenderMode(GLcontext * ctx, GLenum mode) //same
+{
+}
+
+//TODO : move to kernel.
+static void evergreenInitSQConfig(GLcontext * ctx)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context); 
+    
+    uint32_t  uSqNumCfInsts, uMaxGPRs, uMaxThreads, uMaxStackEntries, uPSThreadCount, uOtherThreadCount;
+    uint32_t  NUM_PS_GPRS, NUM_VS_GPRS, NUM_GS_GPRS, NUM_ES_GPRS, NUM_HS_GPRS, NUM_LS_GPRS, NUM_CLAUSE_TEMP_GPRS;
+    GLboolean bVC_ENABLE = GL_TRUE;
+
+    R600_STATECHANGE(context, sq);
+
+    switch (context->radeon.radeonScreen->chip_family) 
+    {
+    case CHIP_FAMILY_CEDAR:
+           uSqNumCfInsts       = 1;
+        bVC_ENABLE = GL_FALSE;
+        uMaxGPRs = 256;
+        uPSThreadCount = 96;
+        uMaxThreads = 192;
+        uMaxStackEntries = 256;
+           break;
+    case CHIP_FAMILY_REDWOOD:
+           uSqNumCfInsts       = 2;
+        bVC_ENABLE = GL_TRUE;
+        uMaxGPRs = 256;
+        uPSThreadCount = 128;
+        uMaxThreads = 248;
+        uMaxStackEntries = 256;
+           break;
+    case CHIP_FAMILY_JUNIPER:
+        uSqNumCfInsts       = 2;
+        bVC_ENABLE = GL_TRUE;
+        uMaxGPRs = 256;
+        uPSThreadCount = 128;
+        uMaxThreads = 248;
+        uMaxStackEntries = 512;
+           break;
+    case CHIP_FAMILY_CYPRESS:
+           uSqNumCfInsts       = 2;
+        bVC_ENABLE = GL_TRUE;
+        uMaxGPRs = 256;
+        uPSThreadCount = 128;
+        uMaxThreads = 248;
+        uMaxStackEntries = 512;
+           break;
+    case CHIP_FAMILY_HEMLOCK:
+           uSqNumCfInsts       = 2;//?
+        bVC_ENABLE = GL_TRUE;
+        uMaxGPRs = 256;
+        uPSThreadCount = 128;
+        uMaxThreads = 248;
+        uMaxStackEntries = 512;
+           break;
+    default:
+        uSqNumCfInsts       = 2;
+        bVC_ENABLE = GL_TRUE;
+        uMaxGPRs = 256;
+        uPSThreadCount = 128;
+        uMaxThreads = 248;
+        uMaxStackEntries = 512;
+           break;
+    }
+
+    evergreen->evergreen_config.SQ_DYN_GPR_CNTL_PS_FLUSH_REQ.u32All   = 0;
+
+    evergreen->evergreen_config.SPI_CONFIG_CNTL.u32All   = 0;
+    evergreen->evergreen_config.SPI_CONFIG_CNTL_1.u32All = 0;
+    SETfield(evergreen->evergreen_config.SPI_CONFIG_CNTL_1.u32All, 4, 
+             EG_SPI_CONFIG_CNTL_1__VTX_DONE_DELAY_shift, 
+             EG_SPI_CONFIG_CNTL_1__VTX_DONE_DELAY_mask);
+
+    evergreen->evergreen_config.CP_PERFMON_CNTL.u32All = 0;
+    
+    evergreen->evergreen_config.SQ_MS_FIFO_SIZES.u32All = 0;
+    SETfield(evergreen->evergreen_config.SQ_MS_FIFO_SIZES.u32All, 16 * uSqNumCfInsts, 
+             EG_SQ_MS_FIFO_SIZES__CACHE_FIFO_SIZE_shift, 
+             EG_SQ_MS_FIFO_SIZES__CACHE_FIFO_SIZE_mask);
+    SETfield(evergreen->evergreen_config.SQ_MS_FIFO_SIZES.u32All, 0x4, 
+             EG_SQ_MS_FIFO_SIZES__FETCH_FIFO_HIWATER_shift, 
+             EG_SQ_MS_FIFO_SIZES__FETCH_FIFO_HIWATER_mask);
+    SETfield(evergreen->evergreen_config.SQ_MS_FIFO_SIZES.u32All, 0xE0, 
+             EG_SQ_MS_FIFO_SIZES__DONE_FIFO_HIWATER_shift, 
+             EG_SQ_MS_FIFO_SIZES__DONE_FIFO_HIWATER_mask);
+    SETfield(evergreen->evergreen_config.SQ_MS_FIFO_SIZES.u32All, 0x8, 
+             EG_SQ_MS_FIFO_SIZES__ALU_UPDATE_FIFO_HIWATER_shift, 
+             EG_SQ_MS_FIFO_SIZES__ALU_UPDATE_FIFO_HIWATER_mask);
+    
+    if(bVC_ENABLE == GL_TRUE)
+    {
+        SETbit(evergreen->evergreen_config.SQ_CONFIG.u32All, 
+               EG_SQ_CONFIG__VC_ENABLE_bit);
+    }
+    else
+    {
+        CLEARbit(evergreen->evergreen_config.SQ_CONFIG.u32All, 
+                 EG_SQ_CONFIG__VC_ENABLE_bit);
+    }
+    SETbit(evergreen->evergreen_config.SQ_CONFIG.u32All, 
+           EG_SQ_CONFIG__EXPORT_SRC_C_bit);
+    SETfield(evergreen->evergreen_config.SQ_CONFIG.u32All, 0, 
+             EG_SQ_CONFIG__PS_PRIO_shift, 
+             EG_SQ_CONFIG__PS_PRIO_mask);
+    SETfield(evergreen->evergreen_config.SQ_CONFIG.u32All, 1, 
+             EG_SQ_CONFIG__VS_PRIO_shift, 
+             EG_SQ_CONFIG__VS_PRIO_mask);
+    SETfield(evergreen->evergreen_config.SQ_CONFIG.u32All, 2, 
+             EG_SQ_CONFIG__GS_PRIO_shift, 
+             EG_SQ_CONFIG__GS_PRIO_mask);
+    SETfield(evergreen->evergreen_config.SQ_CONFIG.u32All, 3, 
+             EG_SQ_CONFIG__ES_PRIO_shift, 
+             EG_SQ_CONFIG__ES_PRIO_mask);
+
+    NUM_CLAUSE_TEMP_GPRS = 4; 
+    NUM_PS_GPRS = ((uMaxGPRs-(4*2))*12/32); // 93
+    NUM_VS_GPRS = ((uMaxGPRs-(4*2))*6/32);  // 46    
+    NUM_GS_GPRS = ((uMaxGPRs-(4*2))*4/32);  // 31
+    NUM_ES_GPRS = ((uMaxGPRs-(4*2))*4/32);  // 31
+    NUM_HS_GPRS = ((uMaxGPRs-(4*2))*3/32);  // 23
+    NUM_LS_GPRS = ((uMaxGPRs-(4*2))*3/32);  // 23
+
+    evergreen->evergreen_config.SQ_GPR_RESOURCE_MGMT_1.u32All = 0;
+    evergreen->evergreen_config.SQ_GPR_RESOURCE_MGMT_2.u32All = 0;
+    evergreen->evergreen_config.SQ_GPR_RESOURCE_MGMT_3.u32All = 0;
+
+    SETfield(evergreen->evergreen_config.SQ_GPR_RESOURCE_MGMT_1.u32All, NUM_PS_GPRS, 
+             NUM_PS_GPRS_shift, NUM_PS_GPRS_mask);
+    SETfield(evergreen->evergreen_config.SQ_GPR_RESOURCE_MGMT_1.u32All, NUM_VS_GPRS, 
+             NUM_VS_GPRS_shift, NUM_VS_GPRS_mask);
+    SETfield(evergreen->evergreen_config.SQ_GPR_RESOURCE_MGMT_1.u32All, NUM_CLAUSE_TEMP_GPRS,
+                NUM_CLAUSE_TEMP_GPRS_shift, NUM_CLAUSE_TEMP_GPRS_mask);
+    SETfield(evergreen->evergreen_config.SQ_GPR_RESOURCE_MGMT_2.u32All, NUM_GS_GPRS, 
+             NUM_GS_GPRS_shift, NUM_GS_GPRS_mask);
+    SETfield(evergreen->evergreen_config.SQ_GPR_RESOURCE_MGMT_2.u32All, NUM_ES_GPRS, 
+             NUM_ES_GPRS_shift, NUM_ES_GPRS_mask);
+    SETfield(evergreen->evergreen_config.SQ_GPR_RESOURCE_MGMT_3.u32All, NUM_HS_GPRS, 
+             NUM_PS_GPRS_shift, NUM_PS_GPRS_mask);
+    SETfield(evergreen->evergreen_config.SQ_GPR_RESOURCE_MGMT_3.u32All, NUM_LS_GPRS, 
+             NUM_VS_GPRS_shift, NUM_VS_GPRS_mask);
+
+    uOtherThreadCount = (((uMaxThreads-uPSThreadCount)/6)/8)*8;
+    evergreen->evergreen_config.SQ_THREAD_RESOURCE_MGMT.u32All = 0;
+    evergreen->evergreen_config.SQ_THREAD_RESOURCE_MGMT_2.u32All = 0;
+    SETfield(evergreen->evergreen_config.SQ_THREAD_RESOURCE_MGMT.u32All, uPSThreadCount,
+            NUM_PS_THREADS_shift, NUM_PS_THREADS_mask);
+    SETfield(evergreen->evergreen_config.SQ_THREAD_RESOURCE_MGMT.u32All, uOtherThreadCount,
+            NUM_VS_THREADS_shift, NUM_VS_THREADS_mask);
+    SETfield(evergreen->evergreen_config.SQ_THREAD_RESOURCE_MGMT.u32All, uOtherThreadCount,
+            NUM_GS_THREADS_shift, NUM_GS_THREADS_mask);
+    SETfield(evergreen->evergreen_config.SQ_THREAD_RESOURCE_MGMT.u32All, uOtherThreadCount,
+            NUM_ES_THREADS_shift, NUM_ES_THREADS_mask);
+    SETfield(evergreen->evergreen_config.SQ_THREAD_RESOURCE_MGMT_2.u32All, uOtherThreadCount,
+            NUM_PS_THREADS_shift, NUM_PS_THREADS_mask);
+    SETfield(evergreen->evergreen_config.SQ_THREAD_RESOURCE_MGMT_2.u32All, uOtherThreadCount,
+            NUM_VS_THREADS_shift, NUM_VS_THREADS_mask);
+
+    uMaxStackEntries = ((uMaxStackEntries*1)/6);
+    evergreen->evergreen_config.SQ_STACK_RESOURCE_MGMT_1.u32All = 0;
+    evergreen->evergreen_config.SQ_STACK_RESOURCE_MGMT_2.u32All = 0;
+    evergreen->evergreen_config.SQ_STACK_RESOURCE_MGMT_3.u32All = 0;
+    SETfield(evergreen->evergreen_config.SQ_STACK_RESOURCE_MGMT_1.u32All, uMaxStackEntries,
+                NUM_PS_STACK_ENTRIES_shift, NUM_PS_STACK_ENTRIES_mask);
+    SETfield(evergreen->evergreen_config.SQ_STACK_RESOURCE_MGMT_1.u32All, uMaxStackEntries,
+                NUM_VS_STACK_ENTRIES_shift, NUM_VS_STACK_ENTRIES_mask);    
+    SETfield(evergreen->evergreen_config.SQ_STACK_RESOURCE_MGMT_2.u32All, uMaxStackEntries,
+                NUM_GS_STACK_ENTRIES_shift, NUM_GS_STACK_ENTRIES_mask);
+    SETfield(evergreen->evergreen_config.SQ_STACK_RESOURCE_MGMT_2.u32All, uMaxStackEntries,
+                NUM_ES_STACK_ENTRIES_shift, NUM_ES_STACK_ENTRIES_mask);
+    SETfield(evergreen->evergreen_config.SQ_STACK_RESOURCE_MGMT_3.u32All, uMaxStackEntries,
+                NUM_PS_STACK_ENTRIES_shift, NUM_PS_STACK_ENTRIES_mask);
+    SETfield(evergreen->evergreen_config.SQ_STACK_RESOURCE_MGMT_3.u32All, uMaxStackEntries,
+                NUM_VS_STACK_ENTRIES_shift, NUM_VS_STACK_ENTRIES_mask); 
+
+    evergreen->evergreen_config.PA_SC_FORCE_EOV_MAX_CNTS.u32All = 0;
+    SETfield(evergreen->evergreen_config.PA_SC_FORCE_EOV_MAX_CNTS.u32All, 4095,
+                EG_PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_CLK_CNT_shift, 
+             EG_PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_CLK_CNT_mask); 
+    SETfield(evergreen->evergreen_config.PA_SC_FORCE_EOV_MAX_CNTS.u32All, 255,
+                EG_PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_REZ_CNT_shift, 
+             EG_PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_REZ_CNT_mask); 
+    
+    evergreen->evergreen_config.VGT_CACHE_INVALIDATION.u32All = 0;
+    SETfield(evergreen->evergreen_config.VGT_CACHE_INVALIDATION.u32All, 2,
+                EG_VGT_CACHE_INVALIDATION__CACHE_INVALIDATION_shift, 
+             EG_VGT_CACHE_INVALIDATION__CACHE_INVALIDATION_mask); 
+   
+    evergreen->evergreen_config.VGT_GS_VERTEX_REUSE.u32All = 0;
+    SETfield(evergreen->evergreen_config.VGT_GS_VERTEX_REUSE.u32All, 16,
+                VERT_REUSE_shift, 
+             VERT_REUSE_mask); 
+
+    evergreen->evergreen_config.PA_SC_LINE_STIPPLE_STATE.u32All = 0;
+
+    evergreen->evergreen_config.PA_CL_ENHANCE.u32All = 0;
+    SETbit(evergreen->evergreen_config.PA_CL_ENHANCE.u32All, 
+           CLIP_VTX_REORDER_ENA_bit);
+    SETfield(evergreen->evergreen_config.PA_CL_ENHANCE.u32All, 3,
+                NUM_CLIP_SEQ_shift, 
+             NUM_CLIP_SEQ_mask);     
+}
+
+void evergreenInitState(GLcontext * ctx) //diff
+{
+    context_t *context = R700_CONTEXT(ctx);
+    EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+
+    int id = 0;
+    
+    //calloc should have done this
+    memset(evergreen, 0, sizeof(EVERGREEN_CHIP_CONTEXT));
+    
+    // Disable window clipping and offset:
+    SETfield(evergreen->PA_SC_WINDOW_OFFSET.u32All, 0,
+                EG_PA_SC_WINDOW_OFFSET__WINDOW_X_OFFSET_shift, EG_PA_SC_WINDOW_OFFSET__WINDOW_X_OFFSET_mask);
+    SETfield(evergreen->PA_SC_WINDOW_OFFSET.u32All, 0,
+                EG_PA_SC_WINDOW_OFFSET__WINDOW_Y_OFFSET_shift, EG_PA_SC_WINDOW_OFFSET__WINDOW_Y_OFFSET_mask);
+
+    SETbit(evergreen->PA_SC_WINDOW_SCISSOR_TL.u32All, WINDOW_OFFSET_DISABLE_bit);    
+        
+    evergreen->PA_SC_CLIPRECT_RULE.u32All = 0x0000FFFF;
+
+    evergreen->PA_SC_EDGERULE.u32All = 0xAAAAAAAA;
+
+    // Set up Z min/max:
+    evergreen->viewport[id].PA_SC_VPORT_ZMIN_0.f32All = 0.0; 
+    evergreen->viewport[id].PA_SC_VPORT_ZMAX_0.f32All = 1.0;
+
+    SETfield(evergreen->CB_TARGET_MASK.u32All, 0xF, TARGET0_ENABLE_shift, TARGET0_ENABLE_mask);
+    SETfield(evergreen->CB_SHADER_MASK.u32All, 0xF, OUTPUT0_ENABLE_shift, OUTPUT0_ENABLE_mask);
+    
+    SETfield(evergreen->SPI_BARYC_CNTL.u32All, 1,
+                EG_SPI_BARYC_CNTL__PERSP_CENTROID_ENA_shift, 
+         EG_SPI_BARYC_CNTL__PERSP_CENTROID_ENA_mask);
+    SETfield(evergreen->SPI_BARYC_CNTL.u32All, 1,
+                EG_SPI_BARYC_CNTL__LINEAR_CENTROID_ENA_shift, 
+         EG_SPI_BARYC_CNTL__LINEAR_CENTROID_ENA_mask);
+    
+    // Turn off vgt reuse:
+    evergreen->VGT_REUSE_OFF.u32All = 0;
+    SETbit(evergreen->VGT_REUSE_OFF.u32All, REUSE_OFF_bit);    
+
+    // Specify offsetting and clamp values for vertices:
+    evergreen->VGT_MAX_VTX_INDX.u32All      = 0xFFFFFF;
+    evergreen->VGT_MIN_VTX_INDX.u32All      = 0;
+    evergreen->VGT_INDX_OFFSET.u32All       = 0;
+
+    evergreen->VGT_DMA_NUM_INSTANCES.u32All = 1;
+
+    // Do not alpha blend:
+    SETfield(evergreen->SX_ALPHA_TEST_CONTROL.u32All, REF_NEVER,
+                        ALPHA_FUNC_shift, ALPHA_FUNC_mask);
+    CLEARbit(evergreen->SX_ALPHA_TEST_CONTROL.u32All, ALPHA_TEST_ENABLE_bit);    
+
+    evergreen->SPI_VS_OUT_ID_0.u32All  = 0x03020100;
+    evergreen->SPI_VS_OUT_ID_1.u32All  = 0x07060504;
+    
+    evergreen->SPI_PS_INPUT_CNTL[0].u32All  = 0x00000800;
+    evergreen->SPI_PS_INPUT_CNTL[1].u32All  = 0x00000801;
+    evergreen->SPI_PS_INPUT_CNTL[2].u32All  = 0x00000802;
+
+
+    // Depth buffer currently disabled:    
+    evergreen->DB_DEPTH_CONTROL.u32All = 0;
+    SETbit(evergreen->DB_DEPTH_CONTROL.u32All, Z_WRITE_ENABLE_bit);
+    SETfield(evergreen->DB_DEPTH_CONTROL.u32All, FRAG_ALWAYS,
+                     ZFUNC_shift, ZFUNC_mask);    
+
+    evergreen->DB_Z_READ_BASE.u32All = 0;
+    evergreen->DB_Z_WRITE_BASE.u32All = 0;
+
+    evergreen->DB_DEPTH_CLEAR.f32All = 1.0;
+
+    evergreen->DB_DEPTH_VIEW.u32All = 0;
+
+    evergreen->DB_SHADER_CONTROL.u32All = 0;
+    SETbit(evergreen->DB_SHADER_CONTROL.u32All, EG_DB_SHADER_CONTROL__DUAL_EXPORT_ENABLE_bit);    
+
+    evergreen->DB_Z_INFO.u32All = 0;
+    SETfield(evergreen->DB_Z_INFO.u32All   , ARRAY_1D_TILED_THIN1,
+        EG_DB_Z_INFO__ARRAY_MODE_shift, EG_DB_Z_INFO__ARRAY_MODE_mask);
+    SETfield(evergreen->DB_Z_INFO.u32All       , EG_Z_24,
+        EG_DB_Z_INFO__FORMAT_shift, EG_DB_Z_INFO__FORMAT_mask);
+    SETfield(evergreen->DB_Z_INFO.u32All   , EG_ADDR_SURF_TILE_SPLIT_256B,
+        EG_DB_Z_INFO__TILE_SPLIT_shift, EG_DB_Z_INFO__TILE_SPLIT_mask);
+    SETfield(evergreen->DB_Z_INFO.u32All    , EG_ADDR_SURF_8_BANK,
+        EG_DB_Z_INFO__NUM_BANKS_shift, EG_DB_Z_INFO__NUM_BANKS_mask);
+    SETfield(evergreen->DB_Z_INFO.u32All   , EG_ADDR_SURF_BANK_WIDTH_1,
+        EG_DB_Z_INFO__BANK_WIDTH_shift, EG_DB_Z_INFO__BANK_WIDTH_mask);
+    SETfield(evergreen->DB_Z_INFO.u32All  , EG_ADDR_SURF_BANK_HEIGHT_1,
+        EG_DB_Z_INFO__BANK_HEIGHT_shift, EG_DB_Z_INFO__BANK_HEIGHT_mask);
+
+    evergreen->DB_STENCIL_INFO.u32All = 0;
+    CLEARbit(evergreen->DB_STENCIL_INFO.u32All, EG_DB_STENCIL_INFO__FORMAT_bit);
+    SETfield(evergreen->DB_STENCIL_INFO.u32All, EG_ADDR_SURF_TILE_SPLIT_256B,
+        EG_DB_STENCIL_INFO__TILE_SPLIT_shift, EG_DB_STENCIL_INFO__TILE_SPLIT_mask);
+
+    evergreen->DB_RENDER_CONTROL.u32All = 0;
+
+    evergreen->DB_RENDER_OVERRIDE.u32All = 0;
+    SETfield(evergreen->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, FORCE_HIZ_ENABLE_shift, FORCE_HIZ_ENABLE_mask);
+       SETfield(evergreen->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, FORCE_HIS_ENABLE0_shift, FORCE_HIS_ENABLE0_mask);
+       SETfield(evergreen->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, FORCE_HIS_ENABLE1_shift, FORCE_HIS_ENABLE1_mask);
+
+    // Disable ROP3 modes by setting src to dst copy:
+    SETfield(evergreen->CB_COLOR_CONTROL.u32All, 0xCC, 
+             EG_CB_COLOR_CONTROL__ROP3_shift, 
+             EG_CB_COLOR_CONTROL__ROP3_mask);    
+    SETfield(evergreen->CB_COLOR_CONTROL.u32All, EG_CB_NORMAL,
+             EG_CB_COLOR_CONTROL__MODE_shift,
+             EG_CB_COLOR_CONTROL__MODE_mask);
+
+    SETfield(evergreen->CB_BLEND0_CONTROL.u32All,
+                        BLEND_ONE, COLOR_SRCBLEND_shift, COLOR_SRCBLEND_mask);
+       
+       SETfield(evergreen->CB_BLEND0_CONTROL.u32All,
+                    BLEND_ONE, ALPHA_SRCBLEND_shift, ALPHA_SRCBLEND_mask);
+
+    //evergreen->PA_CL_CLIP_CNTL.CLIP_DISABLE = 1;
+    
+    SETbit(evergreen->PA_CL_CLIP_CNTL.u32All, DX_LINEAR_ATTR_CLIP_ENA_bit);
+
+    // Set up the culling control register:
+    SETfield(evergreen->PA_SU_SC_MODE_CNTL.u32All, 2,
+             POLYMODE_FRONT_PTYPE_shift, POLYMODE_FRONT_PTYPE_mask); // draw using triangles
+    SETfield(evergreen->PA_SU_SC_MODE_CNTL.u32All, 2,
+                                POLYMODE_BACK_PTYPE_shift, POLYMODE_BACK_PTYPE_mask); // draw using triangles
+        
+    // Do scale XY or X by 1/W0. eg:    
+    evergreen->bEnablePerspective = GL_TRUE;
+    
+    CLEARbit(evergreen->PA_CL_VTE_CNTL.u32All, VTX_XY_FMT_bit);
+    CLEARbit(evergreen->PA_CL_VTE_CNTL.u32All, VTX_Z_FMT_bit);
+    SETbit(evergreen->PA_CL_VTE_CNTL.u32All, VTX_W0_FMT_bit);
+
+    // Enable viewport scaling for all three axis:
+    SETbit(evergreen->PA_CL_VTE_CNTL.u32All, VPORT_X_SCALE_ENA_bit);
+    SETbit(evergreen->PA_CL_VTE_CNTL.u32All, VPORT_X_OFFSET_ENA_bit);
+    SETbit(evergreen->PA_CL_VTE_CNTL.u32All, VPORT_Y_SCALE_ENA_bit);
+    SETbit(evergreen->PA_CL_VTE_CNTL.u32All, VPORT_Y_OFFSET_ENA_bit);
+    SETbit(evergreen->PA_CL_VTE_CNTL.u32All, VPORT_Z_SCALE_ENA_bit);
+    SETbit(evergreen->PA_CL_VTE_CNTL.u32All, VPORT_Z_OFFSET_ENA_bit);
+
+    // Set up point sizes and min/max values:
+    SETfield(evergreen->PA_SU_POINT_SIZE.u32All, 0x8,
+                PA_SU_POINT_SIZE__HEIGHT_shift, PA_SU_POINT_SIZE__HEIGHT_mask);
+       SETfield(evergreen->PA_SU_POINT_SIZE.u32All, 0x8,
+                PA_SU_POINT_SIZE__WIDTH_shift, PA_SU_POINT_SIZE__WIDTH_mask);
+    CLEARfield(evergreen->PA_SU_POINT_MINMAX.u32All, MIN_SIZE_mask);
+    SETfield(evergreen->PA_SU_POINT_MINMAX.u32All, 0x8000, MAX_SIZE_shift, MAX_SIZE_mask);
+    SETfield(evergreen->PA_SU_LINE_CNTL.u32All,0x8,
+            PA_SU_LINE_CNTL__WIDTH_shift, PA_SU_LINE_CNTL__WIDTH_mask);   
+
+    // Set up line control:
+    evergreen->PA_SC_LINE_CNTL.u32All = 0;
+    CLEARbit(evergreen->PA_SC_LINE_CNTL.u32All, EXPAND_LINE_WIDTH_bit);
+    SETbit(evergreen->PA_SC_LINE_CNTL.u32All, LAST_PIXEL_bit);    
+
+    // Set up vertex control:
+    evergreen->PA_SU_VTX_CNTL.u32All               = 0;
+    CLEARfield(evergreen->PA_SU_VTX_CNTL.u32All, QUANT_MODE_mask);  
+    SETbit(evergreen->PA_SU_VTX_CNTL.u32All, PIX_CENTER_bit);
+    SETfield(evergreen->PA_SU_VTX_CNTL.u32All, X_ROUND_TO_EVEN,
+             PA_SU_VTX_CNTL__ROUND_MODE_shift, PA_SU_VTX_CNTL__ROUND_MODE_mask);
+        
+    // to 1.0 = no guard band:
+    evergreen->PA_CL_GB_VERT_CLIP_ADJ.u32All  = 0x3F800000;  // 1.0
+    evergreen->PA_CL_GB_VERT_DISC_ADJ.u32All  = 0x3F800000;  // 1.0
+    evergreen->PA_CL_GB_HORZ_CLIP_ADJ.u32All  = 0x3F800000;  // 1.0
+    evergreen->PA_CL_GB_HORZ_DISC_ADJ.u32All  = 0x3F800000;  // 1.0
+
+    // Diable color compares:    
+    SETfield(evergreen->CB_CLRCMP_CONTROL.u32All, CLRCMP_DRAW_ALWAYS,
+             CLRCMP_FCN_SRC_shift, CLRCMP_FCN_SRC_mask);
+    SETfield(evergreen->CB_CLRCMP_CONTROL.u32All, CLRCMP_DRAW_ALWAYS,
+             CLRCMP_FCN_DST_shift, CLRCMP_FCN_DST_mask);
+    SETfield(evergreen->CB_CLRCMP_CONTROL.u32All, CLRCMP_SEL_SRC,
+             CLRCMP_FCN_SEL_shift, CLRCMP_FCN_SEL_mask);
+
+    // Zero out source:
+    evergreen->CB_CLRCMP_SRC.u32All = 0x00000000;
+
+    // Put a compare color in for error checking:
+    evergreen->CB_CLRCMP_DST.u32All = 0x000000FF;
+
+    // Set up color compare mask:
+    evergreen->CB_CLRCMP_MSK.u32All = 0xFFFFFFFF;
+
+    // Enable all samples for multi-sample anti-aliasing:
+    evergreen->PA_SC_AA_MASK.u32All = 0xFFFFFFFF;
+    // Turn off AA:
+    evergreen->PA_SC_AA_CONFIG.u32All = 0;
+    
+    SETfield(evergreen->VGT_OUT_DEALLOC_CNTL.u32All, 16,
+             DEALLOC_DIST_shift, DEALLOC_DIST_mask);
+    SETfield(evergreen->VGT_VERTEX_REUSE_BLOCK_CNTL.u32All, 14,
+             VTX_REUSE_DEPTH_shift, VTX_REUSE_DEPTH_mask);
+        
+    evergreen->SX_MISC.u32All = 0;
+
+    SETfield(evergreen->render_target[id].CB_COLOR0_INFO.u32All, 1,
+             EG_CB_COLOR0_INFO__SOURCE_FORMAT_shift, EG_CB_COLOR0_INFO__SOURCE_FORMAT_mask);
+    SETbit(evergreen->render_target[id].CB_COLOR0_INFO.u32All, EG_CB_COLOR0_INFO__BLEND_CLAMP_bit);
+    SETfield(evergreen->render_target[id].CB_COLOR0_INFO.u32All, 0,
+             EG_CB_COLOR0_INFO__NUMBER_TYPE_shift, EG_CB_COLOR0_INFO__NUMBER_TYPE_mask);
+    
+    SETfield(evergreen->render_target[id].CB_COLOR0_INFO.u32All, SWAP_STD,
+             EG_CB_COLOR0_INFO__COMP_SWAP_shift, EG_CB_COLOR0_INFO__COMP_SWAP_mask);
+
+    evergreen->render_target[id].CB_COLOR0_VIEW.u32All   = 0;
+    evergreen->render_target[id].CB_COLOR0_CMASK.u32All   = 0;
+    evergreen->render_target[id].CB_COLOR0_FMASK.u32All  = 0;
+    evergreen->render_target[id].CB_COLOR0_FMASK_SLICE.u32All   = 0; 
+
+    evergreenInitSQConfig(ctx);
+
+    context->radeon.hw.all_dirty = GL_TRUE;
+}
+
+void evergreenInitStateFuncs(radeonContextPtr radeon, struct dd_function_table *functions)
+{
+       functions->UpdateState = evergreenInvalidateState;
+       functions->AlphaFunc = evergreenAlphaFunc;
+       functions->BlendColor = evergreenBlendColor;
+       functions->BlendEquationSeparate = evergreenBlendEquationSeparate;
+       functions->BlendFuncSeparate = evergreenBlendFuncSeparate;
+       functions->Enable = evergreenEnable;
+       functions->ColorMask = evergreenColorMask;
+       functions->DepthFunc = evergreenDepthFunc;
+       functions->DepthMask = evergreenDepthMask;
+       functions->CullFace = evergreenCullFace;
+       functions->Fogfv = evergreenFogfv;
+       functions->FrontFace = evergreenFrontFace;
+       functions->ShadeModel = evergreenShadeModel;
+       functions->LogicOpcode = evergreenLogicOpcode;
+
+       /* ARB_point_parameters */
+       functions->PointParameterfv = evergreenPointParameter;
+
+       /* Stencil related */
+       functions->StencilFuncSeparate = evergreenStencilFuncSeparate;
+       functions->StencilMaskSeparate = evergreenStencilMaskSeparate;
+       functions->StencilOpSeparate = evergreenStencilOpSeparate;
+
+       /* Viewport related */
+       functions->Viewport = evergreenViewport;
+       functions->DepthRange = evergreenDepthRange;
+       functions->PointSize = evergreenPointSize;
+       functions->LineWidth = evergreenLineWidth;
+       functions->LineStipple = evergreenLineStipple;
+
+       functions->PolygonOffset = evergreenPolygonOffset;
+       functions->PolygonMode = evergreenPolygonMode;
+
+       functions->RenderMode = evergreenRenderMode;
+
+       functions->ClipPlane = evergreenClipPlane;
+
+       functions->Scissor = radeonScissor;
+
+       functions->DrawBuffer = radeonDrawBuffer;
+       functions->ReadBuffer = radeonReadBuffer;
+
+       if (radeon->radeonScreen->kernel_mm) {
+               functions->CopyPixels = _mesa_meta_CopyPixels;
+               functions->DrawPixels = _mesa_meta_DrawPixels;
+               functions->ReadPixels = radeonReadPixels;
+       }
+}
+
+
diff --git a/src/mesa/drivers/dri/r600/evergreen_state.h b/src/mesa/drivers/dri/r600/evergreen_state.h
new file mode 100644 (file)
index 0000000..ffdb56b
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008-2009  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#ifndef _EVERGREEN_STATE_H_
+#define _EVERGREEN_STATE_H_
+
+#include "main/mtypes.h"
+
+#include "r600_context.h"
+
+extern void evergreenUpdateStateParameters(GLcontext * ctx, GLuint new_state);
+extern void evergreenUpdateShaders(GLcontext * ctx);
+extern void evergreenUpdateShaderStates(GLcontext * ctx);
+
+extern void evergreeUpdateShaders(GLcontext * ctx);
+
+extern void evergreenUpdateViewportOffset(GLcontext * ctx);
+
+extern void evergreenInitState(GLcontext * ctx);
+extern void evergreenInitStateFuncs (radeonContextPtr radeon, struct dd_function_table *functions);
+
+extern void evergreenSetScissor(context_t *context);
+
+#endif /* _EVERGREEN_STATE_H_ */
diff --git a/src/mesa/drivers/dri/r600/evergreen_tex.c b/src/mesa/drivers/dri/r600/evergreen_tex.c
new file mode 100644 (file)
index 0000000..8b42045
--- /dev/null
@@ -0,0 +1,1551 @@
+/*
+ * Copyright (C) 2008-2010  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/enums.h"
+#include "main/image.h"
+#include "main/teximage.h"
+#include "main/mipmap.h"
+#include "main/simple_list.h"
+#include "main/texstore.h"
+#include "main/texobj.h"
+
+#include "texmem.h"
+
+#include "r600_context.h"
+#include "radeon_mipmap_tree.h"
+#include "evergreen_diff.h"
+#include "evergreen_tex.h"
+#include "evergreen_fragprog.h"
+#include "evergreen_vertprog.h"
+
+#include "r600_tex.h"
+
+static unsigned int evergreen_translate_wrap_mode(GLenum wrapmode)
+{
+       switch(wrapmode) {
+       case GL_REPEAT: return SQ_TEX_WRAP;
+       case GL_CLAMP: return SQ_TEX_CLAMP_HALF_BORDER;
+       case GL_CLAMP_TO_EDGE: return SQ_TEX_CLAMP_LAST_TEXEL;
+       case GL_CLAMP_TO_BORDER: return SQ_TEX_CLAMP_BORDER;
+       case GL_MIRRORED_REPEAT: return SQ_TEX_MIRROR;
+       case GL_MIRROR_CLAMP_EXT: return SQ_TEX_MIRROR_ONCE_HALF_BORDER;
+       case GL_MIRROR_CLAMP_TO_EDGE_EXT: return SQ_TEX_MIRROR_ONCE_LAST_TEXEL;
+       case GL_MIRROR_CLAMP_TO_BORDER_EXT: return SQ_TEX_MIRROR_ONCE_BORDER;
+       default:
+               radeon_error("bad wrap mode in %s", __FUNCTION__);
+               return 0;
+       }
+}
+
+static GLboolean evergreenGetTexFormat(struct gl_texture_object *tObj, gl_format mesa_format)
+{
+       radeonTexObj *t = radeon_tex_obj(tObj);
+
+       CLEARfield(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+       CLEARfield(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+       CLEARfield(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+       CLEARfield(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+       CLEARbit(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__FORCE_DEGAMMA_bit);
+
+       SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
+                    FORMAT_COMP_X_shift, 
+             FORMAT_COMP_X_mask);
+       SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
+                    FORMAT_COMP_Y_shift, 
+             FORMAT_COMP_Y_mask);
+       SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
+                    FORMAT_COMP_Z_shift, 
+             FORMAT_COMP_Z_mask);
+       SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
+                    FORMAT_COMP_W_shift, 
+             FORMAT_COMP_W_mask);
+       
+       SETfield(t->SQ_TEX_RESOURCE1, ARRAY_LINEAR_GENERAL,
+                    EG_SQ_TEX_RESOURCE_WORD1_0__ARRAY_MODE_shift,
+                    EG_SQ_TEX_RESOURCE_WORD1_0__ARRAY_MODE_mask);
+
+       switch (mesa_format) /* This is mesa format. */
+       {
+       case MESA_FORMAT_RGBA8888:
+       case MESA_FORMAT_SIGNED_RGBA8888:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8_8_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               if (mesa_format == MESA_FORMAT_SIGNED_RGBA8888) {
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_SIGNED,
+                                FORMAT_COMP_X_shift, FORMAT_COMP_X_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_SIGNED,
+                                FORMAT_COMP_Y_shift, FORMAT_COMP_Y_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_SIGNED,
+                                FORMAT_COMP_Z_shift, FORMAT_COMP_Z_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_SIGNED,
+                                FORMAT_COMP_W_shift, FORMAT_COMP_W_mask);
+               }
+               break;
+       case MESA_FORMAT_RGBA8888_REV:
+       case MESA_FORMAT_SIGNED_RGBA8888_REV:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8_8_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               if (mesa_format == MESA_FORMAT_SIGNED_RGBA8888_REV) {
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_SIGNED,
+                                FORMAT_COMP_X_shift, FORMAT_COMP_X_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_SIGNED,
+                                FORMAT_COMP_Y_shift, FORMAT_COMP_Y_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_SIGNED,
+                                FORMAT_COMP_Z_shift, FORMAT_COMP_Z_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_SIGNED,
+                                FORMAT_COMP_W_shift, FORMAT_COMP_W_mask);
+               }
+               break;
+       case MESA_FORMAT_ARGB8888:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8_8_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_XRGB8888:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8_8_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_XRGB8888_REV:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8_8_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_ARGB8888_REV:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8_8_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_RGB888:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_RGB565:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_5_6_5,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_RGB565_REV:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_5_6_5,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_ARGB4444:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_4_4_4_4,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_ARGB4444_REV:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_4_4_4_4,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_ARGB1555:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_1_5_5_5,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_ARGB1555_REV:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_1_5_5_5,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_AL88:
+       case MESA_FORMAT_AL88_REV: /* TODO : Check this. */
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_RGB332:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_3_3_2,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_A8: /* ZERO, ZERO, ZERO, X */
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_L8: /* X, X, X, ONE */
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_I8: /* X, X, X, X */
+       case MESA_FORMAT_CI8:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;          
+       case MESA_FORMAT_RGB_DXT1: /* not supported yet */
+       case MESA_FORMAT_RGBA_DXT1: /* not supported yet */
+       case MESA_FORMAT_RGBA_DXT3: /* not supported yet */
+       case MESA_FORMAT_RGBA_DXT5: /* not supported yet */
+               return GL_FALSE;
+
+       case MESA_FORMAT_RGBA_FLOAT32:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_32_32_32_32_FLOAT,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_RGBA_FLOAT16:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_16_16_16_16_FLOAT,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_RGB_FLOAT32: /* X, Y, Z, ONE */
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_32_32_32_FLOAT,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_RGB_FLOAT16:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_16_16_16_FLOAT,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_ALPHA_FLOAT32: /* ZERO, ZERO, ZERO, X */
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_32_FLOAT,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_ALPHA_FLOAT16: /* ZERO, ZERO, ZERO, X */
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_16_FLOAT,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_LUMINANCE_FLOAT32: /* X, X, X, ONE */
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_32_FLOAT,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_LUMINANCE_FLOAT16: /* X, X, X, ONE */
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_16_FLOAT,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_32_32_FLOAT,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_16_16_FLOAT,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_INTENSITY_FLOAT32: /* X, X, X, X */
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_32_FLOAT,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_INTENSITY_FLOAT16: /* X, X, X, X */
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_16_FLOAT,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               break;
+       case MESA_FORMAT_Z16:
+       case MESA_FORMAT_X8_Z24:
+       case MESA_FORMAT_S8_Z24:
+       case MESA_FORMAT_Z24_S8:
+       case MESA_FORMAT_Z32:
+       case MESA_FORMAT_S8:            
+        CLEARbit(t->SQ_TEX_RESOURCE0, EG_SQ_TEX_RESOURCE_WORD0_0__NDTO_bit);        
+               SETfield(t->SQ_TEX_RESOURCE1, ARRAY_1D_TILED_THIN1,
+                            EG_SQ_TEX_RESOURCE_WORD1_0__ARRAY_MODE_shift,
+                            EG_SQ_TEX_RESOURCE_WORD1_0__ARRAY_MODE_mask);
+               switch (mesa_format) {
+               case MESA_FORMAT_Z16:
+                       SETfield(t->SQ_TEX_RESOURCE7, FMT_16,
+                                    EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                     EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+                       break;
+               case MESA_FORMAT_X8_Z24:
+               case MESA_FORMAT_S8_Z24:
+                       SETfield(t->SQ_TEX_RESOURCE7, FMT_8_24,
+                                    EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                     EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+                       break;
+               case MESA_FORMAT_Z24_S8:
+                       SETfield(t->SQ_TEX_RESOURCE7, FMT_24_8,
+                                    EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                     EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+                       break;
+               case MESA_FORMAT_Z32:
+                       SETfield(t->SQ_TEX_RESOURCE7, FMT_32,
+                                    EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                     EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+                       break;
+               case MESA_FORMAT_S8:
+                       SETfield(t->SQ_TEX_RESOURCE7, FMT_8,
+                                    EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                     EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+                       break;
+               default:
+                       break;
+               };
+               switch (tObj->DepthMode) {
+               case GL_LUMINANCE:  /* X, X, X, ONE */
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+                       break;
+               case GL_INTENSITY:  /* X, X, X, X */
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+                       break;
+               case GL_ALPHA:     /* ZERO, ZERO, ZERO, X */
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_0,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+                       break;
+               default:
+                       return GL_FALSE;
+               }
+               break;
+       /* EXT_texture_sRGB */
+       case MESA_FORMAT_SRGBA8:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8_8_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               SETbit(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__FORCE_DEGAMMA_bit);
+               break;
+       case MESA_FORMAT_SLA8:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               SETbit(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__FORCE_DEGAMMA_bit);
+               break;
+       case MESA_FORMAT_SL8: /* X, X, X, ONE */
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               SETbit(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__FORCE_DEGAMMA_bit);
+               break;
+       default:
+               /* Not supported format */
+               return GL_FALSE;
+       };
+
+       return GL_TRUE;
+}
+
+static GLuint evergreen_translate_shadow_func(GLenum func)
+{
+   switch (func) {
+   case GL_NEVER:
+      return SQ_TEX_DEPTH_COMPARE_NEVER;
+   case GL_LESS:
+      return SQ_TEX_DEPTH_COMPARE_LESS;
+   case GL_LEQUAL:
+      return SQ_TEX_DEPTH_COMPARE_LESSEQUAL;
+   case GL_GREATER:
+      return SQ_TEX_DEPTH_COMPARE_GREATER;
+   case GL_GEQUAL:
+      return SQ_TEX_DEPTH_COMPARE_GREATEREQUAL;
+   case GL_NOTEQUAL:
+      return SQ_TEX_DEPTH_COMPARE_NOTEQUAL;
+   case GL_EQUAL:
+      return SQ_TEX_DEPTH_COMPARE_EQUAL;
+   case GL_ALWAYS:
+      return SQ_TEX_DEPTH_COMPARE_ALWAYS;
+   default:
+      WARN_ONCE("Unknown shadow compare function! %d", func);
+      return 0;
+   }
+}
+
+static void evergreenUpdateTexWrap(radeonTexObjPtr t)
+{
+       struct gl_texture_object *tObj = &t->base;
+
+    SETfield(t->SQ_TEX_SAMPLER0, evergreen_translate_wrap_mode(tObj->WrapS),
+             EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_shift, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_mask);
+
+       if (tObj->Target != GL_TEXTURE_1D) 
+    {
+               SETfield(t->SQ_TEX_SAMPLER0, evergreen_translate_wrap_mode(tObj->WrapT),
+                            EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_Y_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_Y_mask);
+
+               if (tObj->Target == GL_TEXTURE_3D)
+                       SETfield(t->SQ_TEX_SAMPLER0, evergreen_translate_wrap_mode(tObj->WrapR),
+                                    EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_Z_shift, 
+                     EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_Z_mask);
+       }
+}
+
+static void evergreenSetTexDefaultState(radeonTexObjPtr t)
+{       
+    /* Init text object to default states. */
+    t->SQ_TEX_RESOURCE0 = 0;
+    t->SQ_TEX_RESOURCE1 = 0;
+    t->SQ_TEX_RESOURCE2 = 0;
+    t->SQ_TEX_RESOURCE3 = 0;
+    t->SQ_TEX_RESOURCE4 = 0;
+    t->SQ_TEX_RESOURCE5 = 0;
+    t->SQ_TEX_RESOURCE6 = 0;
+    t->SQ_TEX_RESOURCE7 = 0;
+
+    SETfield(t->SQ_TEX_RESOURCE0, SQ_TEX_DIM_2D, 
+             EG_SQ_TEX_RESOURCE_WORD0_0__DIM_shift, 
+             EG_SQ_TEX_RESOURCE_WORD0_0__DIM_mask);
+
+    CLEARbit(t->SQ_TEX_RESOURCE0, EG_SQ_TEX_RESOURCE_WORD0_0__NDTO_bit);
+
+    SETfield(t->SQ_TEX_RESOURCE1, ARRAY_LINEAR_GENERAL,
+             EG_SQ_TEX_RESOURCE_WORD1_0__ARRAY_MODE_shift, 
+             EG_SQ_TEX_RESOURCE_WORD1_0__ARRAY_MODE_mask);       
+        
+    SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
+             FORMAT_COMP_X_shift, FORMAT_COMP_X_mask);
+    SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
+             FORMAT_COMP_Y_shift, FORMAT_COMP_Y_mask);
+    SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
+             FORMAT_COMP_Z_shift, FORMAT_COMP_Z_mask);
+    SETfield(t->SQ_TEX_RESOURCE4, SQ_FORMAT_COMP_UNSIGNED,
+             FORMAT_COMP_W_shift, FORMAT_COMP_W_mask);
+    SETfield(t->SQ_TEX_RESOURCE4, SQ_NUM_FORMAT_NORM,
+             SQ_TEX_RESOURCE_WORD4_0__NUM_FORMAT_ALL_shift, SQ_TEX_RESOURCE_WORD4_0__NUM_FORMAT_ALL_mask);
+    CLEARbit(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__SRF_MODE_ALL_bit);
+    CLEARbit(t->SQ_TEX_RESOURCE4, SQ_TEX_RESOURCE_WORD4_0__FORCE_DEGAMMA_bit);
+    SETfield(t->SQ_TEX_RESOURCE4, SQ_ENDIAN_NONE,
+             SQ_TEX_RESOURCE_WORD4_0__ENDIAN_SWAP_shift, SQ_TEX_RESOURCE_WORD4_0__ENDIAN_SWAP_mask);
+        
+    SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                    SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift,
+                    SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                    SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift,
+                    SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                    SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift,
+                    SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                    SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift,
+                    SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+    SETfield(t->SQ_TEX_RESOURCE4, 0, 
+             BASE_LEVEL_shift, 
+             BASE_LEVEL_mask); /* mip-maps */            
+
+    SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8_8_8,
+             EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+             EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+    SETfield(t->SQ_TEX_RESOURCE7, SQ_TEX_VTX_VALID_TEXTURE,
+             EG_SQ_TEX_RESOURCE_WORD7_0__TYPE_shift, 
+             EG_SQ_TEX_RESOURCE_WORD7_0__TYPE_mask);
+
+    /* Initialize sampler registers */
+    t->SQ_TEX_SAMPLER0 = 0;
+    SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_WRAP, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_shift,
+                EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_mask);
+    SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_WRAP, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_shift, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_mask);
+    SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_WRAP, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_shift, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__CLAMP_X_mask);
+    SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_XY_FILTER_POINT, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__XY_MAG_FILTER_shift, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__XY_MAG_FILTER_mask);
+    SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_XY_FILTER_POINT, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_shift, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_mask);
+    SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_Z_FILTER_NONE, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__Z_FILTER_shift, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__Z_FILTER_mask);
+    SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_Z_FILTER_NONE, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_shift, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_mask);
+    SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_BORDER_COLOR_TRANS_BLACK, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__BORDER_COLOR_TYPE_shift, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__BORDER_COLOR_TYPE_mask);
+
+    t->SQ_TEX_SAMPLER1 = 0;
+    SETfield(t->SQ_TEX_SAMPLER1, 0x7ff, 
+             EG_SQ_TEX_SAMPLER_WORD1_0__MAX_LOD_shift, 
+             EG_SQ_TEX_SAMPLER_WORD1_0__MAX_LOD_mask);
+
+    t->SQ_TEX_SAMPLER2 = 0;
+    SETbit(t->SQ_TEX_SAMPLER2, EG_SQ_TEX_SAMPLER_WORD2_0__TYPE_bit);
+}
+
+static void evergreenSetTexFilter(radeonTexObjPtr t, GLenum minf, GLenum magf, GLfloat anisotropy)
+{
+       /* Force revalidation to account for switches from/to mipmapping. */
+       t->validated = GL_FALSE;
+
+       /* Note that EXT_texture_filter_anisotropic is extremely vague about
+        * how anisotropic filtering interacts with the "normal" filter modes.
+        * When anisotropic filtering is enabled, we override min and mag
+        * filter settings completely. This includes driconf's settings.
+        */
+       if (anisotropy >= 2.0 && (minf != GL_NEAREST) && (magf != GL_NEAREST)) {
+               /*t->pp_txfilter |= R300_TX_MAG_FILTER_ANISO
+                       | R300_TX_MIN_FILTER_ANISO
+                       | R300_TX_MIN_FILTER_MIP_LINEAR
+                       | aniso_filter(anisotropy);*/
+               radeon_print(RADEON_TEXTURE, RADEON_NORMAL, "Using maximum anisotropy of %f\n", anisotropy);
+               return;
+       }
+
+       switch (minf) 
+    {
+       case GL_NEAREST:
+               SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Point,
+                            EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_mask);
+               SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_None,
+                            EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_mask);
+               break;
+       case GL_LINEAR:
+               SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Linear,
+                            EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_mask);
+               SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_None,
+                            EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_mask);
+               break;
+       case GL_NEAREST_MIPMAP_NEAREST:
+               SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Point,
+                            EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_mask);
+               SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_Point,
+                            EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_mask);
+               break;
+       case GL_NEAREST_MIPMAP_LINEAR:
+               SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Point,
+                            EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_mask);
+               SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_Linear,
+                            EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_mask);
+               break;
+       case GL_LINEAR_MIPMAP_NEAREST:
+               SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Linear,
+                            EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_mask);
+               SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_Point,
+                            EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_mask);
+               break;
+       case GL_LINEAR_MIPMAP_LINEAR:
+               SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Linear,
+                            EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__XY_MIN_FILTER_mask);
+               SETfield(t->SQ_TEX_SAMPLER0, TEX_MipFilter_Linear,
+                            EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__MIP_FILTER_mask);
+               break;
+       }
+
+       /* Note we don't have 3D mipmaps so only use the mag filter setting
+        * to set the 3D texture filter mode.
+        */
+       switch (magf) 
+    {
+       case GL_NEAREST:
+               SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Point,
+                            EG_SQ_TEX_SAMPLER_WORD0_0__XY_MAG_FILTER_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__XY_MAG_FILTER_mask);
+               break;
+       case GL_LINEAR:
+               SETfield(t->SQ_TEX_SAMPLER0, TEX_XYFilter_Linear,
+                            EG_SQ_TEX_SAMPLER_WORD0_0__XY_MAG_FILTER_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__XY_MAG_FILTER_mask);
+               break;
+       }
+}
+
+static void evergreenSetTexBorderColor(radeonTexObjPtr t, const GLfloat color[4])
+{
+       t->TD_PS_SAMPLER0_BORDER_ALPHA = *((uint32_t*)&(color[3]));
+       t->TD_PS_SAMPLER0_BORDER_RED = *((uint32_t*)&(color[2]));
+       t->TD_PS_SAMPLER0_BORDER_GREEN = *((uint32_t*)&(color[1]));
+       t->TD_PS_SAMPLER0_BORDER_BLUE = *((uint32_t*)&(color[0]));
+
+    SETfield(t->SQ_TEX_SAMPLER0, SQ_TEX_BORDER_COLOR_REGISTER,
+                    EG_SQ_TEX_SAMPLER_WORD0_0__BORDER_COLOR_TYPE_shift, 
+             EG_SQ_TEX_SAMPLER_WORD0_0__BORDER_COLOR_TYPE_mask);
+}
+
+static void evergreenSetDepthTexMode(struct gl_texture_object *tObj)
+{
+       radeonTexObjPtr t;
+
+       if (!tObj)
+               return;
+
+       t = radeon_tex_obj(tObj);
+
+       if(!evergreenGetTexFormat(tObj, tObj->Image[0][tObj->BaseLevel]->TexFormat))
+         t->validated = GL_FALSE;
+}
+
+static INLINE uint32_t
+EG_S_FIXED(float value, uint32_t frac_bits)
+{
+   return value * (1 << frac_bits);
+}
+
+static GLboolean evergreen_setup_hardware_state(GLcontext * ctx, struct gl_texture_object *texObj, int unit)
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+       radeonTexObj *t = radeon_tex_obj(texObj);
+       const struct gl_texture_image *firstImage;
+       GLuint uTexelPitch, row_align;
+
+       if (context->radeon.radeonScreen->driScreen->dri2.enabled &&
+           t->image_override &&
+           t->bo)
+               return GL_TRUE;
+
+       firstImage = t->base.Image[0][t->minLod];
+
+       if (!t->image_override) {        
+               if (!evergreenGetTexFormat(texObj, firstImage->TexFormat)) {
+                       radeon_warning("unsupported texture format in %s\n",
+                                      __FUNCTION__);
+                       return GL_FALSE;
+               }        
+       }
+
+    switch (texObj->Target) 
+    {
+    case GL_TEXTURE_1D:
+        SETfield(t->SQ_TEX_RESOURCE0, SQ_TEX_DIM_1D, 
+                 EG_SQ_TEX_RESOURCE_WORD0_0__DIM_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD0_0__DIM_mask);
+        SETfield(t->SQ_TEX_RESOURCE1, 0, 
+                 EG_SQ_TEX_RESOURCE_WORD1_0__TEX_DEPTH_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD1_0__TEX_DEPTH_mask);
+        break;
+    case GL_TEXTURE_2D:
+    case GL_TEXTURE_RECTANGLE_NV:
+        SETfield(t->SQ_TEX_RESOURCE0, SQ_TEX_DIM_2D, 
+                 EG_SQ_TEX_RESOURCE_WORD0_0__DIM_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD0_0__DIM_mask);
+        SETfield(t->SQ_TEX_RESOURCE1, 0, 
+                 EG_SQ_TEX_RESOURCE_WORD1_0__TEX_DEPTH_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD1_0__TEX_DEPTH_mask);
+        break;
+    case GL_TEXTURE_3D:
+        SETfield(t->SQ_TEX_RESOURCE0, SQ_TEX_DIM_3D, 
+                 EG_SQ_TEX_RESOURCE_WORD0_0__DIM_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD0_0__DIM_mask);
+        SETfield(t->SQ_TEX_RESOURCE1, (firstImage->Depth - 1), // ???
+                    EG_SQ_TEX_RESOURCE_WORD1_0__TEX_DEPTH_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD1_0__TEX_DEPTH_mask);
+        break;
+    case GL_TEXTURE_CUBE_MAP:
+        SETfield(t->SQ_TEX_RESOURCE0, SQ_TEX_DIM_CUBEMAP, 
+                 EG_SQ_TEX_RESOURCE_WORD0_0__DIM_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD0_0__DIM_mask);
+        SETfield(t->SQ_TEX_RESOURCE1, 0, 
+                 EG_SQ_TEX_RESOURCE_WORD1_0__TEX_DEPTH_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD1_0__TEX_DEPTH_mask);
+        break;
+    default:
+        radeon_error("unexpected texture target type in %s\n", __FUNCTION__);
+        return GL_FALSE;
+    }
+
+    row_align = context->radeon.texture_row_align - 1;
+    uTexelPitch = (_mesa_format_row_stride(firstImage->TexFormat, firstImage->Width) + row_align) & ~row_align;
+    uTexelPitch = uTexelPitch / _mesa_get_format_bytes(firstImage->TexFormat);
+    uTexelPitch = (uTexelPitch + R700_TEXEL_PITCH_ALIGNMENT_MASK)
+                    & ~R700_TEXEL_PITCH_ALIGNMENT_MASK;
+
+       /* min pitch is 8 */
+       if (uTexelPitch < 8)
+               uTexelPitch = 8;
+
+       SETfield(t->SQ_TEX_RESOURCE0, (uTexelPitch/8)-1, 
+             EG_SQ_TEX_RESOURCE_WORD0_0__PITCH_shift, 
+             EG_SQ_TEX_RESOURCE_WORD0_0__PITCH_mask);
+       SETfield(t->SQ_TEX_RESOURCE0, firstImage->Width - 1,
+                    EG_SQ_TEX_RESOURCE_WORD0_0__TEX_WIDTH_shift, 
+             EG_SQ_TEX_RESOURCE_WORD0_0__TEX_WIDTH_mask);
+       SETfield(t->SQ_TEX_RESOURCE1, firstImage->Height - 1,
+                    EG_SQ_TEX_RESOURCE_WORD1_0__TEX_HEIGHT_shift, 
+             EG_SQ_TEX_RESOURCE_WORD1_0__TEX_HEIGHT_mask);
+
+       t->SQ_TEX_RESOURCE2 = get_base_teximage_offset(t) / 256;
+
+       t->SQ_TEX_RESOURCE3 = radeon_miptree_image_offset(t->mt, 0, t->minLod + 1) / 256;
+
+       SETfield(t->SQ_TEX_RESOURCE4, 0, BASE_LEVEL_shift, BASE_LEVEL_mask);
+       SETfield(t->SQ_TEX_RESOURCE5, t->maxLod - t->minLod, LAST_LEVEL_shift, LAST_LEVEL_mask);
+    
+       SETfield(t->SQ_TEX_SAMPLER1,
+                    EG_S_FIXED(CLAMP(t->base.MinLod - t->minLod, 0, 15), 6),
+                    EG_SQ_TEX_SAMPLER_WORD1_0__MIN_LOD_shift, 
+             EG_SQ_TEX_SAMPLER_WORD1_0__MIN_LOD_mask);
+       SETfield(t->SQ_TEX_SAMPLER1,
+                    EG_S_FIXED(CLAMP(t->base.MaxLod - t->minLod, 0, 15), 6),
+                    EG_SQ_TEX_SAMPLER_WORD1_0__MAX_LOD_shift, 
+             EG_SQ_TEX_SAMPLER_WORD1_0__MAX_LOD_mask);
+       SETfield(t->SQ_TEX_SAMPLER2,
+                    EG_S_FIXED(CLAMP(ctx->Texture.Unit[unit].LodBias + t->base.LodBias, -16, 16), 6),
+                    EG_SQ_TEX_SAMPLER_WORD2_0__LOD_BIAS_shift, 
+             EG_SQ_TEX_SAMPLER_WORD2_0__LOD_BIAS_mask);
+
+       if(texObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB)
+       {
+               SETfield(t->SQ_TEX_SAMPLER0, evergreen_translate_shadow_func(texObj->CompareFunc), 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__DCF_shift, 
+                 EG_SQ_TEX_SAMPLER_WORD0_0__DCF_mask);
+       }
+       else
+       {
+               CLEARfield(t->SQ_TEX_SAMPLER0, EG_SQ_TEX_SAMPLER_WORD0_0__DCF_mask);
+       }
+
+       return GL_TRUE;
+}
+
+void evergreenSetTexOffset(__DRIcontext * pDRICtx, GLint texname,
+                     unsigned long long offset, GLint depth, GLuint pitch)
+{
+       context_t *rmesa = pDRICtx->driverPrivate;
+       struct gl_texture_object *tObj =
+           _mesa_lookup_texture(rmesa->radeon.glCtx, texname);
+       radeonTexObjPtr t = radeon_tex_obj(tObj);
+       const struct gl_texture_image *firstImage;
+       uint32_t pitch_val, size, row_align;
+
+       if (!tObj)
+               return;
+
+       t->image_override = GL_TRUE;
+
+       if (!offset)
+               return;
+
+       firstImage = t->base.Image[0][t->minLod];
+       row_align = rmesa->radeon.texture_row_align - 1;
+       size = ((_mesa_format_row_stride(firstImage->TexFormat, firstImage->Width) + row_align) & ~row_align) * firstImage->Height;
+       if (t->bo) {
+               radeon_bo_unref(t->bo);
+               t->bo = NULL;
+       }
+       t->bo = radeon_legacy_bo_alloc_fake(rmesa->radeon.radeonScreen->bom, size, offset);
+       t->override_offset = offset;
+       pitch_val = pitch;
+       switch (depth) {
+       case 32:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8_8_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               pitch_val /= 4;
+               break;
+       case 24:
+       default:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8_8_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               pitch_val /= 4;
+               break;
+       case 16:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_5_6_5,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               pitch_val /= 2;
+               break;
+       }
+
+       pitch_val = (pitch_val + R700_TEXEL_PITCH_ALIGNMENT_MASK)
+               & ~R700_TEXEL_PITCH_ALIGNMENT_MASK;
+
+       /* min pitch is 8 */
+       if (pitch_val < 8)
+               pitch_val = 8;
+
+       SETfield(t->SQ_TEX_RESOURCE0, (pitch_val/8)-1, 
+             EG_SQ_TEX_RESOURCE_WORD0_0__PITCH_shift, 
+             EG_SQ_TEX_RESOURCE_WORD0_0__PITCH_mask);
+}
+
+void evergreenSetTexBuffer(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_format, __DRIdrawable *dPriv)
+{
+       struct gl_texture_unit *texUnit;
+       struct gl_texture_object *texObj;
+       struct gl_texture_image *texImage;
+       struct radeon_renderbuffer *rb;
+       radeon_texture_image *rImage;
+       radeonContextPtr radeon;
+       context_t *rmesa;
+       struct radeon_framebuffer *rfb;
+       radeonTexObjPtr t;
+       uint32_t pitch_val;
+       uint32_t internalFormat, type, format;
+
+       type = GL_BGRA;
+       format = GL_UNSIGNED_BYTE;
+       internalFormat = (glx_texture_format == __DRI_TEXTURE_FORMAT_RGB ? 3 : 4);
+
+       radeon = pDRICtx->driverPrivate;
+       rmesa = pDRICtx->driverPrivate;
+
+       rfb = dPriv->driverPrivate;
+        texUnit = &radeon->glCtx->Texture.Unit[radeon->glCtx->Texture.CurrentUnit];
+       texObj = _mesa_select_tex_object(radeon->glCtx, texUnit, target);
+        texImage = _mesa_get_tex_image(radeon->glCtx, texObj, target, 0);
+
+       rImage = get_radeon_texture_image(texImage);
+       t = radeon_tex_obj(texObj);
+        if (t == NULL) {
+           return;
+       }
+
+       radeon_update_renderbuffers(pDRICtx, dPriv, GL_TRUE);
+       rb = rfb->color_rb[0];
+       if (rb->bo == NULL) {
+               /* Failed to BO for the buffer */
+               return;
+       }
+
+       _mesa_lock_texture(radeon->glCtx, texObj);
+       if (t->bo) {
+               radeon_bo_unref(t->bo);
+               t->bo = NULL;
+       }
+       if (rImage->bo) {
+               radeon_bo_unref(rImage->bo);
+               rImage->bo = NULL;
+       }
+
+       radeon_miptree_unreference(&t->mt);
+       radeon_miptree_unreference(&rImage->mt);
+
+       _mesa_init_teximage_fields(radeon->glCtx, target, texImage,
+                                  rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
+       texImage->RowStride = rb->pitch / rb->cpp;
+
+       rImage->bo = rb->bo;
+       radeon_bo_ref(rImage->bo);
+       t->bo = rb->bo;
+       radeon_bo_ref(t->bo);
+       t->image_override = GL_TRUE;
+       t->override_offset = 0;
+       pitch_val = rb->pitch;
+       switch (rb->cpp) {
+       case 4:
+               if (glx_texture_format == __DRI_TEXTURE_FORMAT_RGB) {
+                       SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8_8_8,
+                                    EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                     EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               } else {
+                       SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8_8_8,
+                                    EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                     EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+                       SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                                SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               }
+               pitch_val /= 4;
+               break;
+       case 3:
+       default:
+               // FMT_8_8_8 ???
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_8_8_8_8,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_W,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               pitch_val /= 4;
+               break;
+       case 2:
+               SETfield(t->SQ_TEX_RESOURCE7, FMT_5_6_5,
+                            EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_shift, 
+                 EG_SQ_TEX_RESOURCE_WORD7_0__DATA_FORMAT_mask);
+
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Z,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_X_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_Y,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Y_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_X,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_Z_mask);
+               SETfield(t->SQ_TEX_RESOURCE4, SQ_SEL_1,
+                        SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_shift, SQ_TEX_RESOURCE_WORD4_0__DST_SEL_W_mask);
+               pitch_val /= 2;
+               break;
+       }
+
+       pitch_val = (pitch_val + R700_TEXEL_PITCH_ALIGNMENT_MASK)
+               & ~R700_TEXEL_PITCH_ALIGNMENT_MASK;
+
+       /* min pitch is 8 */
+       if (pitch_val < 8)
+               pitch_val = 8;
+
+       SETfield(t->SQ_TEX_RESOURCE0, (pitch_val/8)-1, 
+             EG_SQ_TEX_RESOURCE_WORD0_0__PITCH_shift, 
+             EG_SQ_TEX_RESOURCE_WORD0_0__PITCH_mask);
+       SETfield(t->SQ_TEX_RESOURCE0, rb->base.Width - 1,
+                    EG_SQ_TEX_RESOURCE_WORD0_0__TEX_WIDTH_shift, 
+             EG_SQ_TEX_RESOURCE_WORD0_0__TEX_WIDTH_mask);
+       SETfield(t->SQ_TEX_RESOURCE1, rb->base.Height - 1,
+                    EG_SQ_TEX_RESOURCE_WORD1_0__TEX_HEIGHT_shift, 
+             EG_SQ_TEX_RESOURCE_WORD1_0__TEX_HEIGHT_mask);
+
+       t->validated = GL_TRUE;
+       _mesa_unlock_texture(radeon->glCtx, texObj);
+       return;
+}
+
+void evergreenUpdateTextureState(GLcontext * ctx)
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+    EVERGREEN_CHIP_CONTEXT * evergreen = GET_EVERGREEN_CHIP(context);  
+       struct gl_texture_unit *texUnit;
+       struct radeon_tex_obj *t;
+       GLuint    unit;
+
+       EVERGREEN_STATECHANGE(context, tx);    
+
+       for (unit = 0; unit < R700_MAX_TEXTURE_UNITS; unit++) {
+               texUnit = &ctx->Texture.Unit[unit];
+               t = radeon_tex_obj(ctx->Texture.Unit[unit]._Current);
+               evergreen->textures[unit] = NULL;
+               if (texUnit->_ReallyEnabled) {
+                       if (!t)
+                               continue;
+                       evergreen->textures[unit] = t;
+               }
+       }
+}
+
+static GLboolean evergreen_validate_texture(GLcontext * ctx, struct gl_texture_object *texObj, int unit)
+{
+       radeonTexObj *t = radeon_tex_obj(texObj);
+
+       if (!radeon_validate_texture_miptree(ctx, texObj))
+               return GL_FALSE;
+
+       /* Configure the hardware registers (more precisely, the cached version
+        * of the hardware registers). */
+       if (!evergreen_setup_hardware_state(ctx, texObj, unit))
+               return GL_FALSE;
+
+       t->validated = GL_TRUE;
+       return GL_TRUE;
+}
+
+GLboolean evergreenValidateBuffers(GLcontext * ctx)
+{
+       context_t *rmesa = EVERGREEN_CONTEXT(ctx);
+       struct radeon_renderbuffer *rrb;
+       struct radeon_bo *pbo;
+       int i;
+       int ret;
+
+       radeon_cs_space_reset_bos(rmesa->radeon.cmdbuf.cs);
+
+       rrb = radeon_get_colorbuffer(&rmesa->radeon);
+       /* color buffer */
+       if (rrb && rrb->bo) {
+               radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs,
+                                                 rrb->bo, 0,
+                                                 RADEON_GEM_DOMAIN_VRAM);
+       }
+
+       /* depth buffer */
+       rrb = radeon_get_depthbuffer(&rmesa->radeon);
+       if (rrb && rrb->bo) {
+               radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs,
+                                                 rrb->bo, 0,
+                                                 RADEON_GEM_DOMAIN_VRAM);
+       }
+       
+       for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) {
+               radeonTexObj *t;
+
+               if (!ctx->Texture.Unit[i]._ReallyEnabled)
+                       continue;
+
+               if (!evergreen_validate_texture(ctx, ctx->Texture.Unit[i]._Current, i)) {
+                       radeon_warning("failed to validate texture for unit %d.\n", i);
+               }
+               t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
+               if (t->image_override && t->bo)
+                       radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs,
+                                                         t->bo,
+                                                         RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+               else if (t->mt->bo)
+                       radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs,
+                                                         t->mt->bo,
+                                                         RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
+       }
+
+       pbo = (struct radeon_bo *)evergreenGetActiveFpShaderBo(ctx);
+       if (pbo) {
+               radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, pbo,
+                                                 RADEON_GEM_DOMAIN_GTT, 0);
+       }
+
+       pbo = (struct radeon_bo *)evergreenGetActiveVpShaderBo(ctx);
+       if (pbo) {
+               radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, pbo,
+                                                 RADEON_GEM_DOMAIN_GTT, 0);
+       }
+
+       pbo = (struct radeon_bo *)evergreenGetActiveFpShaderConstBo(ctx);
+       if (pbo) {
+               radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, pbo,
+                                                 RADEON_GEM_DOMAIN_GTT, 0);
+       }
+
+       pbo = (struct radeon_bo *)evergreenGetActiveVpShaderConstBo(ctx);
+       if (pbo) {
+               radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, pbo,
+                                                 RADEON_GEM_DOMAIN_GTT, 0);
+       }
+       
+       ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, first_elem(&rmesa->radeon.dma.reserved)->bo, RADEON_GEM_DOMAIN_GTT, 0);
+       if (ret)
+               return GL_FALSE;
+       return GL_TRUE;
+}
+
+static struct gl_texture_object *evergreenNewTextureObject(GLcontext * ctx,
+                                                     GLuint name,
+                                                     GLenum target)
+{
+       context_t* rmesa = EVERGREEN_CONTEXT(ctx);
+       radeonTexObj * t = CALLOC_STRUCT(radeon_tex_obj);
+
+
+       radeon_print(RADEON_STATE | RADEON_TEXTURE, RADEON_NORMAL,
+               "%s( %p (target = %s) )\n", __FUNCTION__,
+                       t, _mesa_lookup_enum_by_nr(target));
+
+       _mesa_initialize_texture_object(&t->base, name, target);
+       t->base.MaxAnisotropy = rmesa->radeon.initialMaxAnisotropy;
+    
+       evergreenSetTexDefaultState(t);
+       evergreenUpdateTexWrap(t);
+       evergreenSetTexFilter(t, t->base.MinFilter, t->base.MagFilter, t->base.MaxAnisotropy);
+       evergreenSetTexBorderColor(t, t->base.BorderColor.f);
+
+       return &t->base;
+}
+
+static void evergreenDeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
+{
+       context_t              * rmesa     = EVERGREEN_CONTEXT(ctx);
+    EVERGREEN_CHIP_CONTEXT * evergreen = GET_EVERGREEN_CHIP(rmesa);
+       radeonTexObj* t = radeon_tex_obj(texObj);
+
+       radeon_print(RADEON_STATE | RADEON_TEXTURE, RADEON_NORMAL,
+               "%s( %p (target = %s) )\n", __FUNCTION__,
+                       (void *)texObj,
+                       _mesa_lookup_enum_by_nr(texObj->Target));
+
+       if (rmesa) {
+               int i;
+               radeon_firevertices(&rmesa->radeon);
+
+               for(i = 0; i < R700_MAX_TEXTURE_UNITS; ++i)
+                       if (evergreen->textures[i] == t)
+                               evergreen->textures[i] = 0;
+       }
+
+       if (t->bo) {
+               radeon_bo_unref(t->bo);
+               t->bo = NULL;
+       }
+
+       radeon_miptree_unreference(&t->mt);
+
+       _mesa_delete_texture_object(ctx, texObj);
+}
+
+static void evergreenTexParameter(GLcontext * ctx, GLenum target,
+                            struct gl_texture_object *texObj,
+                            GLenum pname, const GLfloat * params)
+{
+    radeonTexObj* t = radeon_tex_obj(texObj);
+       GLenum baseFormat;
+
+       radeon_print(RADEON_STATE | RADEON_TEXTURE, RADEON_VERBOSE,
+                       "%s( %s )\n", __FUNCTION__,
+                       _mesa_lookup_enum_by_nr(pname));
+
+       switch (pname) {
+       case GL_TEXTURE_MIN_FILTER:
+       case GL_TEXTURE_MAG_FILTER:
+       case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+               evergreenSetTexFilter(t, texObj->MinFilter, texObj->MagFilter, texObj->MaxAnisotropy);
+               break;
+
+       case GL_TEXTURE_WRAP_S:
+       case GL_TEXTURE_WRAP_T:
+       case GL_TEXTURE_WRAP_R:
+               evergreenUpdateTexWrap(t);
+               break;
+
+       case GL_TEXTURE_BORDER_COLOR:
+               evergreenSetTexBorderColor(t, texObj->BorderColor.f);
+               break;
+
+       case GL_TEXTURE_BASE_LEVEL:
+       case GL_TEXTURE_MAX_LEVEL:
+       case GL_TEXTURE_MIN_LOD:
+       case GL_TEXTURE_MAX_LOD:
+               t->validated = GL_FALSE;
+               break;
+
+       case GL_DEPTH_TEXTURE_MODE:
+               if (!texObj->Image[0][texObj->BaseLevel])
+                       return;
+               baseFormat = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
+               if (baseFormat == GL_DEPTH_COMPONENT ||
+                   baseFormat == GL_DEPTH_STENCIL) {
+                       evergreenSetDepthTexMode(texObj);
+                       break;
+               } else {
+                       /* If the texture isn't a depth texture, changing this
+                        * state won't cause any changes to the hardware.
+                        * Don't force a flush of texture state.
+                        */
+                       return;
+               }
+
+       default:
+               return;
+       }
+}
+
+void evergreenInitTextureFuncs(radeonContextPtr radeon, struct dd_function_table *functions)
+{
+       /* Note: we only plug in the functions we implement in the driver
+        * since _mesa_init_driver_functions() was already called.
+        */
+       functions->NewTextureImage = radeonNewTextureImage;
+       functions->FreeTexImageData = radeonFreeTexImageData;
+       functions->MapTexture = radeonMapTexture;
+       functions->UnmapTexture = radeonUnmapTexture;
+
+       functions->ChooseTextureFormat = radeonChooseTextureFormat_mesa;
+       functions->TexImage1D = radeonTexImage1D;
+       functions->TexImage2D = radeonTexImage2D;
+       functions->TexImage3D = radeonTexImage3D;
+       functions->TexSubImage1D = radeonTexSubImage1D;
+       functions->TexSubImage2D = radeonTexSubImage2D;
+       functions->TexSubImage3D = radeonTexSubImage3D;
+       functions->GetTexImage = radeonGetTexImage;
+       functions->GetCompressedTexImage = radeonGetCompressedTexImage;
+       functions->NewTextureObject = evergreenNewTextureObject;
+       functions->DeleteTexture = evergreenDeleteTexture;
+       functions->IsTextureResident = driIsTextureResident;
+
+       functions->TexParameter = evergreenTexParameter;
+
+       functions->CompressedTexImage2D = radeonCompressedTexImage2D;
+       functions->CompressedTexSubImage2D = radeonCompressedTexSubImage2D;
+
+       if (radeon->radeonScreen->kernel_mm) {
+               functions->CopyTexImage2D = radeonCopyTexImage2D;
+               functions->CopyTexSubImage2D = radeonCopyTexSubImage2D;
+       }
+
+       functions->GenerateMipmap = radeonGenerateMipmap;
+
+       driInitTextureFormats();
+}
diff --git a/src/mesa/drivers/dri/r600/evergreen_tex.h b/src/mesa/drivers/dri/r600/evergreen_tex.h
new file mode 100644 (file)
index 0000000..b43508a
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008-2010  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+#ifndef _EVERGREEN_TEX_H_
+#define _EVERGREEN_TEX_H_
+
+extern GLboolean evergreenValidateBuffers(GLcontext * ctx);
+
+extern void evergreenUpdateTextureState(GLcontext * ctx);
+extern void evergreenInitTextureFuncs(radeonContextPtr radeon, struct dd_function_table *functions);
+extern void evergreenSetTexOffset(__DRIcontext * pDRICtx, GLint texname,
+                                         unsigned long long offset, GLint depth, GLuint pitch);
+extern void evergreenSetTexBuffer(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_format, __DRIdrawable *dPriv);
+
+#endif   /* _EVERGREEN_TEX_H_ */
diff --git a/src/mesa/drivers/dri/r600/evergreen_vertprog.c b/src/mesa/drivers/dri/r600/evergreen_vertprog.c
new file mode 100644 (file)
index 0000000..4f3db00
--- /dev/null
@@ -0,0 +1,736 @@
+/*
+ * Copyright (C) 2008-2009  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "tnl/t_context.h"
+#include "program/program.h"
+#include "program/prog_parameter.h"
+#include "program/prog_statevars.h"
+
+#include "radeon_debug.h"
+#include "r600_context.h"
+#include "r600_cmdbuf.h"
+#include "r600_emit.h"
+#include "program/programopt.h"
+
+#include "evergreen_vertprog.h"
+
+unsigned int evergreen_Map_Vertex_Output(r700_AssemblerBase       *pAsm, 
+                                                  struct gl_vertex_program *mesa_vp,
+                                                  unsigned int unStart)
+{
+    unsigned int i;
+       unsigned int unBit;
+       unsigned int unTotal = unStart;
+
+    //!!!!!!! THE ORDER MATCH FS INPUT
+
+       unBit = 1 << VERT_RESULT_HPOS;
+       if(mesa_vp->Base.OutputsWritten & unBit)
+       {
+               pAsm->ucVP_OutputMap[VERT_RESULT_HPOS] = unTotal++;
+       }
+
+       unBit = 1 << VERT_RESULT_COL0;
+       if(mesa_vp->Base.OutputsWritten & unBit)
+       {
+               pAsm->ucVP_OutputMap[VERT_RESULT_COL0] = unTotal++;
+       }
+
+       unBit = 1 << VERT_RESULT_COL1;
+       if(mesa_vp->Base.OutputsWritten & unBit)
+       {
+               pAsm->ucVP_OutputMap[VERT_RESULT_COL1] = unTotal++;
+       }
+
+       //TODO : dealing back face.
+       unBit = 1 << VERT_RESULT_BFC0;
+       if(mesa_vp->Base.OutputsWritten & unBit)
+       {
+               pAsm->ucVP_OutputMap[VERT_RESULT_BFC0] = unTotal++;
+       }
+
+       unBit = 1 << VERT_RESULT_BFC1;
+       if(mesa_vp->Base.OutputsWritten & unBit)
+       {
+               pAsm->ucVP_OutputMap[VERT_RESULT_BFC1] = unTotal++;
+       }
+
+       //TODO : dealing fog.
+       unBit = 1 << VERT_RESULT_FOGC;
+       if(mesa_vp->Base.OutputsWritten & unBit)
+       {
+               pAsm->ucVP_OutputMap[VERT_RESULT_FOGC] = unTotal++;
+       }
+
+       //TODO : dealing point size.
+       unBit = 1 << VERT_RESULT_PSIZ;
+       if(mesa_vp->Base.OutputsWritten & unBit)
+       {
+               pAsm->ucVP_OutputMap[VERT_RESULT_PSIZ] = unTotal++;
+       }
+
+       for(i=0; i<8; i++)
+       {
+               unBit = 1 << (VERT_RESULT_TEX0 + i);
+               if(mesa_vp->Base.OutputsWritten & unBit)
+               {
+                       pAsm->ucVP_OutputMap[VERT_RESULT_TEX0 + i] = unTotal++;
+               }
+       }
+
+    for(i=VERT_RESULT_VAR0; i<VERT_RESULT_MAX; i++)
+       {
+               unBit = 1 << i;
+               if(mesa_vp->Base.OutputsWritten & unBit)
+               {
+                       pAsm->ucVP_OutputMap[i] = unTotal++;
+               }
+       }
+
+       return (unTotal - unStart);
+}
+
+unsigned int evergreen_Map_Vertex_Input(r700_AssemblerBase       *pAsm, 
+                                         struct gl_vertex_program *mesa_vp,
+                                         unsigned int unStart)
+{
+       int i;
+       unsigned int unBit;
+       unsigned int unTotal = unStart;
+       for(i=0; i<VERT_ATTRIB_MAX; i++)
+       {
+               unBit = 1 << i;
+               if(mesa_vp->Base.InputsRead & unBit)
+               {
+                       pAsm->ucVP_AttributeMap[i] = unTotal++;
+               }
+       }
+       return (unTotal - unStart);
+}
+
+GLboolean evergreen_Process_Vertex_Program_Vfetch_Instructions(
+                                               struct evergreen_vertex_program *vp,
+                                               struct gl_vertex_program   *mesa_vp)
+{
+       int i;
+    unsigned int unBit;
+       VTX_FETCH_METHOD vtxFetchMethod;
+       vtxFetchMethod.bEnableMini          = GL_FALSE;
+       vtxFetchMethod.mega_fetch_remainder = 0;
+
+       for(i=0; i<VERT_ATTRIB_MAX; i++)
+       {
+               unBit = 1 << i;
+               if(mesa_vp->Base.InputsRead & unBit)
+               {
+                       assemble_vfetch_instruction(&vp->r700AsmCode,
+                                                   i,
+                                                   vp->r700AsmCode.ucVP_AttributeMap[i],
+                                                   vp->aos_desc[i].size,
+                                                   vp->aos_desc[i].type,
+                                                   &vtxFetchMethod);
+               }
+       }
+       
+       return GL_TRUE;
+}
+
+GLboolean evergreen_Process_Vertex_Program_Vfetch_Instructions2(
+    GLcontext *ctx,
+       struct evergreen_vertex_program *vp,
+       struct gl_vertex_program   *mesa_vp)
+{
+    int i;
+    context_t *context = R700_CONTEXT(ctx);
+
+    VTX_FETCH_METHOD vtxFetchMethod;
+       vtxFetchMethod.bEnableMini          = GL_FALSE;
+       vtxFetchMethod.mega_fetch_remainder = 0;
+
+    for(i=0; i<context->nNumActiveAos; i++)
+    {
+        EG_assemble_vfetch_instruction(&vp->r700AsmCode,
+                                      vp->r700AsmCode.ucVP_AttributeMap[context->stream_desc[i].element],
+                                      context->stream_desc[i].type,
+                                      context->stream_desc[i].size,
+                                      context->stream_desc[i].element,
+                                      context->stream_desc[i]._signed,
+                                      context->stream_desc[i].normalize,
+                                      context->stream_desc[i].format,
+                                     &vtxFetchMethod);
+    }
+
+    return GL_TRUE;
+}
+
+void evergreen_Map_Vertex_Program(GLcontext *ctx,
+                        struct evergreen_vertex_program *vp,
+                                               struct gl_vertex_program   *mesa_vp)
+{
+    GLuint ui;
+    r700_AssemblerBase *pAsm = &(vp->r700AsmCode);
+       unsigned int num_inputs;
+
+       // R0 will always be used for index into vertex buffer
+       pAsm->number_used_registers = 1;
+       pAsm->starting_vfetch_register_number = pAsm->number_used_registers;
+
+    // Map Inputs: Add 1 to mapping since R0 is used for index
+       num_inputs = evergreen_Map_Vertex_Input(pAsm, mesa_vp, pAsm->number_used_registers);
+       pAsm->number_used_registers += num_inputs;
+
+       // Create VFETCH instructions for inputs
+        if (GL_TRUE != evergreen_Process_Vertex_Program_Vfetch_Instructions2(ctx, vp, mesa_vp) )
+       {
+               radeon_error("Calling evergreen_Process_Vertex_Program_Vfetch_Instructions2 return error. \n");
+               return;
+       }
+
+       // Map Outputs
+       pAsm->number_of_exports = evergreen_Map_Vertex_Output(pAsm, mesa_vp, pAsm->number_used_registers);
+
+       pAsm->starting_export_register_number = pAsm->number_used_registers;
+
+       pAsm->number_used_registers += pAsm->number_of_exports;
+
+    pAsm->pucOutMask = (unsigned char*) MALLOC(pAsm->number_of_exports);
+
+    for(ui=0; ui<pAsm->number_of_exports; ui++)
+    {
+        pAsm->pucOutMask[ui] = 0x0;
+    }
+
+    /* Map temporary registers (GPRs) */
+    pAsm->starting_temp_register_number = pAsm->number_used_registers;
+
+    if(mesa_vp->Base.NumNativeTemporaries >= mesa_vp->Base.NumTemporaries)
+    {   /* arb uses NumNativeTemporaries */
+        pAsm->number_used_registers += mesa_vp->Base.NumNativeTemporaries;
+    }
+    else
+    {   /* fix func t_vp uses NumTemporaries */
+        pAsm->number_used_registers += mesa_vp->Base.NumTemporaries;
+    }
+
+    pAsm->flag_reg_index = pAsm->number_used_registers++;
+
+    pAsm->uFirstHelpReg = pAsm->number_used_registers;
+}
+
+GLboolean evergreen_Find_Instruction_Dependencies_vp(struct evergreen_vertex_program *vp,
+                                                               struct gl_vertex_program   *mesa_vp)
+{
+    GLuint i, j;
+    GLint * puiTEMPwrites;
+    struct prog_instruction *pILInst;
+    InstDeps         *pInstDeps;
+
+    puiTEMPwrites = (GLint*) MALLOC(sizeof(GLuint)*mesa_vp->Base.NumTemporaries);
+    for(i=0; i<mesa_vp->Base.NumTemporaries; i++)
+    {
+        puiTEMPwrites[i] = -1;
+    }
+
+    pInstDeps = (InstDeps*)MALLOC(sizeof(InstDeps)*mesa_vp->Base.NumInstructions);
+
+    for(i=0; i<mesa_vp->Base.NumInstructions; i++)
+    {
+        pInstDeps[i].nDstDep = -1;
+        pILInst = &(mesa_vp->Base.Instructions[i]);
+
+        //Dst
+        if(pILInst->DstReg.File == PROGRAM_TEMPORARY)
+        {
+            //Set lastwrite for the temp
+            puiTEMPwrites[pILInst->DstReg.Index] = i;
+        }
+
+        //Src
+        for(j=0; j<3; j++)
+        {
+            if(pILInst->SrcReg[j].File == PROGRAM_TEMPORARY)
+            {
+                //Set dep.
+                pInstDeps[i].nSrcDeps[j] = puiTEMPwrites[pILInst->SrcReg[j].Index];
+            }
+            else
+            {
+                pInstDeps[i].nSrcDeps[j] = -1;
+            }
+        }
+    }
+
+    vp->r700AsmCode.pInstDeps = pInstDeps;
+
+    FREE(puiTEMPwrites);
+
+    return GL_TRUE;
+}
+
+struct evergreen_vertex_program* evergreenTranslateVertexShader(GLcontext *ctx,
+                                                     struct gl_vertex_program *mesa_vp)
+{
+       context_t *context = EVERGREEN_CONTEXT(ctx);
+
+       struct evergreen_vertex_program *vp;
+       unsigned int i;
+
+       vp = calloc(1, sizeof(*vp));
+       vp->mesa_program = _mesa_clone_vertex_program(ctx, mesa_vp);
+    
+    vp->constbo0 = NULL;
+
+       if (mesa_vp->IsPositionInvariant)
+       {
+                _mesa_insert_mvp_code(ctx, vp->mesa_program);
+        }
+
+       for(i=0; i<context->nNumActiveAos; i++)
+       {
+               vp->aos_desc[i].size   = context->stream_desc[i].size;
+               vp->aos_desc[i].stride = context->stream_desc[i].stride;
+               vp->aos_desc[i].type   = context->stream_desc[i].type;
+               vp->aos_desc[i].format = context->stream_desc[i].format;
+       }
+
+       if (context->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV770)
+       {
+               vp->r700AsmCode.bR6xx = 1;
+       }
+
+       //Init_Program
+       Init_r700_AssemblerBase(SPT_VP, &(vp->r700AsmCode), &(vp->r700Shader) );
+        
+    vp->r700AsmCode.bUseMemConstant = GL_TRUE;  
+    vp->r700AsmCode.unAsic = 8;
+
+       evergreen_Map_Vertex_Program(ctx, vp, vp->mesa_program );
+
+       if(GL_FALSE == evergreen_Find_Instruction_Dependencies_vp(vp, vp->mesa_program))
+       {
+               return NULL;
+       }
+
+    InitShaderProgram(&(vp->r700AsmCode));
+
+    for(i=0; i < MAX_SAMPLERS; i++)
+    {
+        vp->r700AsmCode.SamplerUnits[i] = vp->mesa_program->Base.SamplerUnits[i];
+    }
+
+    vp->r700AsmCode.unCurNumILInsts = vp->mesa_program->Base.NumInstructions;
+
+       if(GL_FALSE == AssembleInstr(0,
+                                 0,
+                                 vp->mesa_program->Base.NumInstructions,
+                                 &(vp->mesa_program->Base.Instructions[0]),
+                                 &(vp->r700AsmCode)) )
+       {
+               return NULL;
+       }
+
+    if(GL_FALSE == Process_Vertex_Exports(&(vp->r700AsmCode), vp->mesa_program->Base.OutputsWritten) )
+    {
+        return NULL;
+    }
+
+    if( GL_FALSE == RelocProgram(&(vp->r700AsmCode), &(vp->mesa_program->Base)) )
+    {
+        return GL_FALSE;
+    }
+
+    vp->r700Shader.nRegs = (vp->r700AsmCode.number_used_registers == 0) ? 0 
+                         : (vp->r700AsmCode.number_used_registers - 1);
+
+       vp->r700Shader.nParamExports = vp->r700AsmCode.number_of_exports;
+
+    vp->translated = GL_TRUE;
+
+       return vp;
+}
+
+void evergreenSelectVertexShader(GLcontext *ctx)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    struct evergreen_vertex_program_cont *vpc;
+    struct evergreen_vertex_program *vp;
+    unsigned int i;
+    GLboolean match;
+    GLbitfield InputsRead;
+
+    vpc = (struct evergreen_vertex_program_cont *)ctx->VertexProgram._Current;
+
+    InputsRead = vpc->mesa_program.Base.InputsRead;
+    if (vpc->mesa_program.IsPositionInvariant)
+    {
+       InputsRead |= VERT_BIT_POS;
+    }
+
+    for (vp = vpc->progs; vp; vp = vp->next)
+    {
+       match = GL_TRUE;
+       for(i=0; i<context->nNumActiveAos; i++)
+       {
+               if (vp->aos_desc[i].size != context->stream_desc[i].size ||
+                   vp->aos_desc[i].format != context->stream_desc[i].format)
+               {
+                       match = GL_FALSE;
+                       break;
+               }
+       }
+       if (match)
+       {
+               context->selected_vp = vp;
+               return;
+       }
+    }
+
+    vp = evergreenTranslateVertexShader(ctx, &(vpc->mesa_program));
+    if(!vp)
+    {
+       radeon_error("Failed to translate vertex shader. \n");
+       return;
+    }
+    vp->next = vpc->progs;
+    vpc->progs = vp;
+    context->selected_vp = vp;
+    return;
+}
+
+int evergreen_getTypeSize(GLenum type)
+{
+    switch (type) 
+    {
+    case GL_DOUBLE:
+        return sizeof(GLdouble);
+    case GL_FLOAT:
+        return sizeof(GLfloat);
+    case GL_INT:
+        return sizeof(GLint);
+    case GL_UNSIGNED_INT:
+        return sizeof(GLuint);
+    case GL_SHORT:
+        return sizeof(GLshort);
+    case GL_UNSIGNED_SHORT:
+        return sizeof(GLushort);
+    case GL_BYTE:
+        return sizeof(GLbyte);
+    case GL_UNSIGNED_BYTE:
+        return sizeof(GLubyte);
+    default:
+        assert(0);
+        return 0;
+    }
+}
+
+static void evergreenTranslateAttrib(GLcontext *ctx, GLuint unLoc, int count, const struct gl_client_array *input)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    
+    StreamDesc * pStreamDesc = &(context->stream_desc[context->nNumActiveAos]);
+
+       GLuint stride;
+
+       stride = (input->StrideB == 0) ? evergreen_getTypeSize(input->Type) * input->Size 
+                                   : input->StrideB;
+
+    if (input->Type == GL_DOUBLE || input->Type == GL_UNSIGNED_INT || input->Type == GL_INT ||
+#if MESA_BIG_ENDIAN
+        evergreen_getTypeSize(input->Type) != 4 ||
+#endif
+        stride < 4) 
+    {
+        pStreamDesc->type = GL_FLOAT;
+
+        if (input->StrideB == 0) 
+        {
+               pStreamDesc->stride = 0;
+        } 
+        else 
+        {
+               pStreamDesc->stride = sizeof(GLfloat) * input->Size;
+        }
+        pStreamDesc->dwords = input->Size;
+        pStreamDesc->is_named_bo = GL_FALSE;
+    } 
+    else 
+    {
+        pStreamDesc->type = input->Type;
+        pStreamDesc->dwords = (evergreen_getTypeSize(input->Type) * input->Size + 3)/ 4;
+        if (!input->BufferObj->Name) 
+        {
+            if (input->StrideB == 0) 
+            {
+                pStreamDesc->stride = 0;
+            } 
+            else 
+            {
+                pStreamDesc->stride = (evergreen_getTypeSize(pStreamDesc->type) * input->Size + 3) & ~3;
+            }
+
+            pStreamDesc->is_named_bo = GL_FALSE;
+        }
+    }
+
+       pStreamDesc->size = input->Size;
+       pStreamDesc->dst_loc = context->nNumActiveAos;
+       pStreamDesc->element = unLoc;
+       pStreamDesc->format = input->Format;
+
+       switch (pStreamDesc->type) 
+       { //GetSurfaceFormat
+       case GL_FLOAT:
+               pStreamDesc->_signed = 0;
+               pStreamDesc->normalize = GL_FALSE;
+               break;
+       case GL_SHORT:
+               pStreamDesc->_signed = 1;
+               pStreamDesc->normalize = input->Normalized;
+               break;
+       case GL_BYTE:
+               pStreamDesc->_signed = 1;
+               pStreamDesc->normalize = input->Normalized;
+               break;
+       case GL_UNSIGNED_SHORT:
+               pStreamDesc->_signed = 0;
+               pStreamDesc->normalize = input->Normalized;
+               break;
+       case GL_UNSIGNED_BYTE:
+               pStreamDesc->_signed = 0;
+               pStreamDesc->normalize = input->Normalized;
+               break;
+       default:
+       case GL_INT:
+       case GL_UNSIGNED_INT:
+       case GL_DOUBLE: 
+               assert(0);
+               break;
+       }
+       context->nNumActiveAos++;
+}
+
+void evergreenSetVertexFormat(GLcontext *ctx, const struct gl_client_array *arrays[], int count)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    struct evergreen_vertex_program *vpc
+           = (struct evergreen_vertex_program *)ctx->VertexProgram._Current;
+
+    struct gl_vertex_program * mesa_vp = (struct gl_vertex_program *)&(vpc->mesa_program);
+    unsigned int unLoc = 0;
+    unsigned int unBit = mesa_vp->Base.InputsRead;
+    context->nNumActiveAos = 0;
+
+    if (mesa_vp->IsPositionInvariant)
+    {
+        unBit |= VERT_BIT_POS;
+    }
+
+    while(unBit) 
+    {
+        if(unBit & 1)
+        {
+            evergreenTranslateAttrib(ctx, unLoc, count, arrays[unLoc]);
+        }
+
+        unBit >>= 1;
+        ++unLoc;
+    }
+    context->radeon.tcl.aos_count = context->nNumActiveAos;
+}
+
+void * evergreenGetActiveVpShaderBo(GLcontext * ctx)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    struct evergreen_vertex_program *vp = context->selected_vp;;
+
+    if (vp)
+       return vp->shaderbo;
+    else
+       return NULL;
+}
+
+void * evergreenGetActiveVpShaderConstBo(GLcontext * ctx)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    struct evergreen_vertex_program *vp = context->selected_vp;;
+
+    if (vp)
+       return vp->constbo0;
+    else
+       return NULL;
+}
+
+GLboolean evergreenSetupVertexProgram(GLcontext * ctx)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+    struct evergreen_vertex_program *vp = context->selected_vp;
+
+    if(GL_FALSE == vp->loaded)
+    {
+           if(vp->r700Shader.bNeedsAssembly == GL_TRUE)
+           {
+                   Assemble( &(vp->r700Shader) );
+           }
+
+        /* Load vp to gpu */
+        r600EmitShader(ctx,
+                       &(vp->shaderbo),
+                       (GLvoid *)(vp->r700Shader.pProgram),
+                       vp->r700Shader.uShaderBinaryDWORDSize,
+                       "VS");
+   
+        vp->loaded = GL_TRUE;
+    }
+
+    EVERGREEN_STATECHANGE(context, vs);      
+    
+    /* TODO : enable this after MemUse fixed *=
+    (context->chipobj.MemUse)(context, vp->shadercode.buf->id);
+    */       
+
+    evergreen->SQ_PGM_RESOURCES_VS.u32All = 0;
+    SETbit(evergreen->SQ_PGM_RESOURCES_VS.u32All, PGM_RESOURCES__PRIME_CACHE_ON_DRAW_bit);
+    
+    evergreen->vs.SQ_ALU_CONST_CACHE_VS_0.u32All = 0; /* set from buffer object. */
+    
+    evergreen->vs.SQ_PGM_START_VS.u32All = 0;
+
+    SETfield(evergreen->SQ_PGM_RESOURCES_VS.u32All, vp->r700Shader.nRegs + 1,
+             NUM_GPRS_shift, NUM_GPRS_mask);
+
+    if(vp->r700Shader.uStackSize) /* we don't use branch for now, it should be zero. */
+       {
+        SETfield(evergreen->SQ_PGM_RESOURCES_VS.u32All, vp->r700Shader.uStackSize,
+                 STACK_SIZE_shift, STACK_SIZE_mask);
+    }
+
+    EVERGREEN_STATECHANGE(context, spi);
+
+    SETfield(evergreen->SPI_VS_OUT_CONFIG.u32All,
+            vp->r700Shader.nParamExports ? (vp->r700Shader.nParamExports - 1) : 0,
+             VS_EXPORT_COUNT_shift, VS_EXPORT_COUNT_mask);
+    SETfield(evergreen->SPI_PS_IN_CONTROL_0.u32All, vp->r700Shader.nParamExports,
+             NUM_INTERP_shift, NUM_INTERP_mask);
+
+    /*
+    SETbit(evergreen->SPI_PS_IN_CONTROL_0.u32All, PERSP_GRADIENT_ENA_bit);
+    CLEARbit(evergreen->SPI_PS_IN_CONTROL_0.u32All, LINEAR_GRADIENT_ENA_bit);
+    */
+
+    return GL_TRUE;
+}
+
+GLboolean evergreenSetupVPconstants(GLcontext * ctx)
+{
+    context_t *context = EVERGREEN_CONTEXT(ctx);
+    EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context);
+    struct evergreen_vertex_program *vp = context->selected_vp;
+
+    struct gl_program_parameter_list *paramList;
+    unsigned int unNumParamData;
+    unsigned int ui;
+
+    /* sent out shader constants. */
+    paramList = vp->mesa_program->Base.Parameters;
+
+    if(NULL != paramList) {
+        /* vp->mesa_program was cloned, not updated by glsl shader api. */
+        /* _mesa_reference_program has already checked glsl shProg is ok and set ctx->VertexProgem._Current */
+        /* so, use ctx->VertexProgem._Current */       
+        struct gl_program_parameter_list *paramListOrginal = 
+                         ctx->VertexProgram._Current->Base.Parameters;
+         
+           _mesa_load_state_parameters(ctx, paramList);
+
+           if (paramList->NumParameters > EVERGREEN_MAX_DX9_CONSTS)
+                   return GL_FALSE;
+
+           EVERGREEN_STATECHANGE(context, vs);
+
+           evergreen->vs.num_consts = paramList->NumParameters;
+
+           unNumParamData = paramList->NumParameters;
+
+           for(ui=0; ui<unNumParamData; ui++) {
+            if(paramList->Parameters[ui].Type == PROGRAM_UNIFORM) 
+            {
+                evergreen->vs.consts[ui][0].f32All = paramListOrginal->ParameterValues[ui][0];
+                       evergreen->vs.consts[ui][1].f32All = paramListOrginal->ParameterValues[ui][1];
+                       evergreen->vs.consts[ui][2].f32All = paramListOrginal->ParameterValues[ui][2];
+                       evergreen->vs.consts[ui][3].f32All = paramListOrginal->ParameterValues[ui][3];
+            }
+            else
+            {
+                       evergreen->vs.consts[ui][0].f32All = paramList->ParameterValues[ui][0];
+                       evergreen->vs.consts[ui][1].f32All = paramList->ParameterValues[ui][1];
+                       evergreen->vs.consts[ui][2].f32All = paramList->ParameterValues[ui][2];
+                       evergreen->vs.consts[ui][3].f32All = paramList->ParameterValues[ui][3];
+            }
+           }
+
+        radeonAllocDmaRegion(&context->radeon, 
+                             &context->vp_Constbo, 
+                             &context->vp_bo_offset, 
+                             256, 
+                             256);        
+        r600EmitShaderConsts(ctx,
+                             context->vp_Constbo,
+                             context->vp_bo_offset,
+                             (GLvoid *)&(evergreen->vs.consts[0][0]),
+                             unNumParamData * 4 * 4);
+    } else
+           evergreen->vs.num_consts = 0;
+
+    COMPILED_SUB * pCompiledSub;
+    GLuint uj;
+    GLuint unConstOffset = evergreen->vs.num_consts;
+    for(ui=0; ui<vp->r700AsmCode.unNumPresub; ui++)
+    {
+        pCompiledSub = vp->r700AsmCode.presubs[ui].pCompiledSub;
+
+        evergreen->vs.num_consts += pCompiledSub->NumParameters;
+
+        for(uj=0; uj<pCompiledSub->NumParameters; uj++)
+        {
+            evergreen->vs.consts[uj + unConstOffset][0].f32All = pCompiledSub->ParameterValues[uj][0];
+                   evergreen->vs.consts[uj + unConstOffset][1].f32All = pCompiledSub->ParameterValues[uj][1];
+                   evergreen->vs.consts[uj + unConstOffset][2].f32All = pCompiledSub->ParameterValues[uj][2];
+                   evergreen->vs.consts[uj + unConstOffset][3].f32All = pCompiledSub->ParameterValues[uj][3];
+        }
+        unConstOffset += pCompiledSub->NumParameters;
+    }
+}
\ No newline at end of file
diff --git a/src/mesa/drivers/dri/r600/evergreen_vertprog.h b/src/mesa/drivers/dri/r600/evergreen_vertprog.h
new file mode 100644 (file)
index 0000000..5853902
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2008-2009  Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) 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:
+ *   Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
+
+
+#ifndef _EVERGREEN_VERTPROG_H_
+#define _EVERGREEN_VERTPROG_H_
+
+#include "main/glheader.h"
+#include "main/mtypes.h" 
+
+#include "r700_shader.h"
+#include "r700_assembler.h"
+
+typedef struct evergreenArrayDesc //TEMP
+{
+       GLint size;   //number of data element
+       GLenum type;  //data element type
+       GLsizei stride;
+       GLenum format; //GL_RGBA or GL_BGRA
+} evergreenArrayDesc;
+
+struct evergreen_vertex_program 
+{
+    struct gl_vertex_program *mesa_program; /* Must be first */
+
+    struct evergreen_vertex_program *next;
+
+    r700_AssemblerBase r700AsmCode;
+    R700_Shader        r700Shader;
+
+    GLboolean translated;
+    GLboolean loaded;
+
+    void * shaderbo;
+
+       GLuint K0used;
+    void * constbo0;
+
+    evergreenArrayDesc              aos_desc[VERT_ATTRIB_MAX];
+};
+
+struct evergreen_vertex_program_cont
+{
+    struct gl_vertex_program mesa_program;
+
+    struct evergreen_vertex_program *progs;
+};
+
+//Internal
+unsigned int evergreen_Map_Vertex_Output(r700_AssemblerBase       *pAsm, 
+                              struct gl_vertex_program *mesa_vp,
+                              unsigned int unStart);
+unsigned int evergreen_Map_Vertex_Input(r700_AssemblerBase       *pAsm, 
+                             struct gl_vertex_program *mesa_vp,
+                             unsigned int unStart);
+GLboolean evergreen_Process_Vertex_Program_Vfetch_Instructions(
+       struct evergreen_vertex_program *vp,
+       struct gl_vertex_program   *mesa_vp);
+GLboolean evergreen_Process_Vertex_Program_Vfetch_Instructions2(
+    GLcontext *ctx,
+       struct evergreen_vertex_program *vp,
+       struct gl_vertex_program   *mesa_vp);
+void evergreen_Map_Vertex_Program(GLcontext *ctx,
+            struct evergreen_vertex_program *vp,
+                       struct gl_vertex_program   *mesa_vp);
+GLboolean evergreen_Find_Instruction_Dependencies_vp(struct evergreen_vertex_program *vp,
+                                          struct gl_vertex_program   *mesa_vp);
+
+struct evergreen_vertex_program* evergreenTranslateVertexShader(GLcontext *ctx,
+                                                     struct gl_vertex_program   *mesa_vp);
+
+/* Interface */
+extern void evergreenSelectVertexShader(GLcontext *ctx);
+extern void evergreenSetVertexFormat(GLcontext *ctx, const struct gl_client_array *arrays[], int count);
+
+extern GLboolean evergreenSetupVertexProgram(GLcontext * ctx);
+
+extern GLboolean evergreenSetupVPconstants(GLcontext * ctx);
+
+extern void * evergreenGetActiveVpShaderBo(GLcontext * ctx);
+
+extern void * evergreenGetActiveVpShaderConstBo(GLcontext * ctx);
+
+extern int evergreen_getTypeSize(GLenum type);
+
+#endif /* _EVERGREEN_VERTPROG_H_ */
index 27acff9c166d7cab65ae64e95259ac7ed6ad87f8..ef47ae1c05671cc3e854670244c25a8a4884a817 100644 (file)
@@ -1454,7 +1454,7 @@ set_default_state(context_t *context)
            SETbit(sq_dyn_gpr_cntl_ps_flush_req, VS_PC_LIMIT_ENABLE_bit);
     }
 
-    BEGIN_BATCH_NO_AUTOSTATE(117);
+    BEGIN_BATCH_NO_AUTOSTATE(120);
     R600_OUT_BATCH_REGSEQ(SQ_CONFIG, 6);
     R600_OUT_BATCH(sq_config);
     R600_OUT_BATCH(sq_gpr_resource_mgmt_1);
@@ -1499,9 +1499,10 @@ set_default_state(context_t *context)
     R600_OUT_BATCH_REGVAL(PA_SU_VTX_CNTL, (PIX_CENTER_bit) |
         (X_ROUND_TO_EVEN << PA_SU_VTX_CNTL__ROUND_MODE_shift) |
         (X_1_256TH << QUANT_MODE_shift));
+    R600_OUT_BATCH_REGVAL(PA_SC_AA_CONFIG, 0);
 
     R600_OUT_BATCH_REGSEQ(VGT_MAX_VTX_INDX, 4);
-    R600_OUT_BATCH(2048);
+    R600_OUT_BATCH(0xffffff);
     R600_OUT_BATCH(0);
     R600_OUT_BATCH(0);
     R600_OUT_BATCH(0);
@@ -1614,7 +1615,7 @@ unsigned r600_blit(GLcontext *ctx,
     /* Flush is needed to make sure that source buffer has correct data */
     radeonFlush(ctx);
 
-    rcommonEnsureCmdBufSpace(&context->radeon, 308, __FUNCTION__);
+    rcommonEnsureCmdBufSpace(&context->radeon, 311, __FUNCTION__);
 
     /* load shaders */
     load_shaders(context->radeon.glCtx);
@@ -1623,7 +1624,7 @@ unsigned r600_blit(GLcontext *ctx,
         return GL_FALSE;
 
     /* set clear state */
-    /* 117 */
+    /* 120 */
     set_default_state(context);
 
     /* shaders */
index 8013553f679eeb0f03d4301b52ef4af5f8ee37d9..b3331fc8b8883eed097d5eb6170e25edf681f2a1 100644 (file)
@@ -473,7 +473,14 @@ void r600InitCmdBuf(context_t *r600) /* from rcommonInitCmdBuf */
        radeonContextPtr rmesa = &r600->radeon;
        GLuint size;
 
-       r600InitAtoms(r600);
+    if(r600->radeon.radeonScreen->chip_family >= CHIP_FAMILY_CEDAR)
+    {
+        evergreenInitAtoms(r600);
+    }
+    else
+    {
+        r600InitAtoms(r600);
+    }  
 
        /* Initialize command buffer */
        size = 256 * driQueryOptioni(&rmesa->optionCache,
index 78fccd0b6010e431de64c2ac09683d7346aa5d3b..801bb013f6ed9587be5fb740452e801e1cbd01cb 100644 (file)
@@ -190,6 +190,46 @@ do {                                                               \
 #define R600_OUT_BATCH_REGSEQ(reg, count)      \
        R600_OUT_BATCH_REGS((reg), (count))
 
+/* evergreen */ 
+#define EVERGREEN_OUT_BATCH_REGS(reg, num)                                     \
+do {                                                           \
+       if ((reg) >= R600_SET_CONFIG_REG_OFFSET && (reg) < R600_SET_CONFIG_REG_END) { \
+               R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CONFIG_REG, (num)));      \
+               R600_OUT_BATCH(((reg) - R600_SET_CONFIG_REG_OFFSET) >> 2);      \
+       } else if ((reg) >= R600_SET_CONTEXT_REG_OFFSET && (reg) < R600_SET_CONTEXT_REG_END) { \
+               R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CONTEXT_REG, (num)));     \
+               R600_OUT_BATCH(((reg) - R600_SET_CONTEXT_REG_OFFSET) >> 2);     \
+       } else if ((reg) >= EG_SET_RESOURCE_OFFSET && (reg) < EG_SET_RESOURCE_END) { \
+               R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_RESOURCE, (num)));        \
+               R600_OUT_BATCH(((reg) - EG_SET_RESOURCE_OFFSET) >> 2);  \
+    } else if ((reg) >= EG_SET_LOOP_CONST_OFFSET && (reg) < EG_SET_LOOP_CONST_END) { \
+               R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_LOOP_CONST, (num)));      \
+               R600_OUT_BATCH(((reg) - EG_SET_LOOP_CONST_OFFSET) >> 2);        \
+       } else if ((reg) >= R600_SET_SAMPLER_OFFSET && (reg) < R600_SET_SAMPLER_END) { \
+               R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_SAMPLER, (num))); \
+               R600_OUT_BATCH(((reg) - R600_SET_SAMPLER_OFFSET) >> 2); \
+       } else if ((reg) >= R600_SET_CTL_CONST_OFFSET && (reg) < R600_SET_CTL_CONST_END) { \
+               R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_CTL_CONST, (num)));       \
+               R600_OUT_BATCH(((reg) - R600_SET_CTL_CONST_OFFSET) >> 2);       \
+       } else if ((reg) >= EG_SET_BOOL_CONST_OFFSET && (reg) < EG_SET_BOOL_CONST_END) { \
+               R600_OUT_BATCH(CP_PACKET3(R600_IT_SET_BOOL_CONST, (num)));      \
+               R600_OUT_BATCH(((reg) - EG_SET_BOOL_CONST_OFFSET) >> 2);        \
+       } else {                                                        \
+               R600_OUT_BATCH(CP_PACKET0((reg), (num))); \
+       }                                                               \
+} while (0)
+
+/** Single register write to command buffer; requires 3 dwords for most things. */
+#define EVERGREEN_OUT_BATCH_REGVAL(reg, val)           \
+       EVERGREEN_OUT_BATCH_REGS((reg), 1);             \
+       R600_OUT_BATCH((val))
+
+/** Continuous register range write to command buffer; requires 1 dword,
+ * expects count dwords afterwards for register contents. */
+#define EVERGREEN_OUT_BATCH_REGSEQ(reg, count) \
+           EVERGREEN_OUT_BATCH_REGS((reg), (count))
+
+
 extern void r600InitCmdBuf(context_t *r600);
 
 #endif                         /* __R600_CMDBUF_H__ */
index 389b0412baa74e7884ce3b6673b8ed1a1ee5aedb..bb959e7d2d919fff421fa62a3e05883f4b83e508 100644 (file)
@@ -66,6 +66,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r700_state.h"
 #include "r700_ioctl.h"
 
+#include "evergreen_context.h"
+#include "evergreen_state.h"
+#include "evergreen_tex.h"
+#include "evergreen_ioctl.h"
+#include "evergreen_oglprog.h"
 
 #include "utils.h"
 
@@ -247,6 +252,19 @@ static void r600_init_vtbl(radeonContextPtr radeon)
 
 static void r600InitConstValues(GLcontext *ctx, radeonScreenPtr screen)
 {
+    context_t         *context = R700_CONTEXT(ctx);
+    R700_CHIP_CONTEXT *r700    = (R700_CHIP_CONTEXT*)(&context->hw);
+
+    if(  (context->radeon.radeonScreen->chip_family >= CHIP_FAMILY_CEDAR)
+       &&(context->radeon.radeonScreen->chip_family <= CHIP_FAMILY_HEMLOCK) )
+    {
+        r700->bShaderUseMemConstant = GL_TRUE;
+    }
+    else
+    {
+        r700->bShaderUseMemConstant = GL_FALSE;
+    }
+
        ctx->Const.MaxTextureImageUnits = 16;
        /* 8 per clause on r6xx, 16 on r7xx
         * but I think mesa only supports 8 at the moment
@@ -381,18 +399,45 @@ GLboolean r600CreateContext(gl_api api,
        r600ParseOptions(r600, screen);
 
        r600->radeon.radeonScreen = screen;
-       r600_init_vtbl(&r600->radeon);
 
+    if(screen->chip_family >= CHIP_FAMILY_CEDAR)
+    {
+           evergreen_init_vtbl(&r600->radeon);
+    }
+    else
+    {
+        r600_init_vtbl(&r600->radeon);
+    }
+    
        /* Init default driver functions then plug in our R600-specific functions
         * (the texture functions are especially important)
         */
        _mesa_init_driver_functions(&functions);
 
-       r700InitStateFuncs(&r600->radeon, &functions);
-       r600InitTextureFuncs(&r600->radeon, &functions);
-       r700InitShaderFuncs(&functions);
+    if(screen->chip_family >= CHIP_FAMILY_CEDAR)
+    {
+        evergreenCreateChip(r600);
+        evergreenInitStateFuncs(&r600->radeon, &functions);
+           evergreenInitTextureFuncs(&r600->radeon, &functions);
+           evergreenInitShaderFuncs(&functions);
+    }
+    else
+    {
+           r700InitStateFuncs(&r600->radeon, &functions);
+           r600InitTextureFuncs(&r600->radeon, &functions);
+           r700InitShaderFuncs(&functions);
+    }
+    
        radeonInitQueryObjFunctions(&functions);
-       r700InitIoctlFuncs(&functions);
+
+    if(screen->chip_family >= CHIP_FAMILY_CEDAR)
+    {
+        evergreenInitIoctlFuncs(&functions);
+    }
+    else
+    {
+           r700InitIoctlFuncs(&functions);
+    }
        radeonInitBufferObjectFuncs(&functions);
 
        if (!radeonInitContext(&r600->radeon, &functions,
@@ -435,16 +480,46 @@ GLboolean r600CreateContext(gl_api api,
 
        radeon_init_debug();
 
-       r700InitDraw(ctx);
+    if(screen->chip_family >= CHIP_FAMILY_CEDAR)
+    {
+        evergreenInitDraw(ctx);
+    }
+    else
+    {
+           r700InitDraw(ctx);
+    }
 
        radeon_fbo_init(&r600->radeon);
        radeonInitSpanFuncs( ctx );
        r600InitCmdBuf(r600);
-       r700InitState(r600->radeon.glCtx);
+
+    if(screen->chip_family >= CHIP_FAMILY_CEDAR)
+    {
+        evergreenInitState(r600->radeon.glCtx);
+    }
+    else
+    {
+           r700InitState(r600->radeon.glCtx);
+    }
 
        r600InitGLExtensions(ctx);
 
        return GL_TRUE;
 }
 
+void r600DestroyContext(__DRIcontext *driContextPriv )
+{
+    void      *pChip;
+    context_t *context = (context_t *) driContextPriv->driverPrivate;
+
+    assert(context);
+
+    pChip = context->pChip;
+
+    /* destroy context first, free pChip, in case there are things flush to asic. */
+    radeonDestroyContext(driContextPriv);
+
+    FREE(pChip);
+}
+
 
index 063dd7c49a1a702f45aa8f00a25e8f0a2a23902c..6a831966487133fcb9f2faf4cab8f20531592123 100644 (file)
@@ -53,6 +53,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r700_oglprog.h"
 #include "r700_vertprog.h"
 
+#include "evergreen_chip.h"
+
 struct r600_context;
 typedef struct r600_context context_t;
 
@@ -63,6 +65,10 @@ typedef struct r600_context context_t;
 #include "tnl_dd/t_dd_vertex.h"
 #undef TAG
 
+#define FORCE_CF_TEX_BARRIER    1
+
+/* #define GENERATE_SHADER_FOR_2D  1 */
+
 #define R600_FALLBACK_NONE 0
 #define R600_FALLBACK_TCL 1
 #define R600_FALLBACK_RAST 2
@@ -103,6 +109,24 @@ struct r600_hw_state {
        struct radeon_state_atom tx_brdr_clr;
 };
 
+struct evergreen_hw_state {
+    struct radeon_state_atom one_time_init;
+    struct radeon_state_atom init;
+       struct radeon_state_atom pa;
+       struct radeon_state_atom vgt;
+       struct radeon_state_atom tp;
+       struct radeon_state_atom sq;
+    struct radeon_state_atom vs;
+       struct radeon_state_atom spi;
+       struct radeon_state_atom sx;
+    struct radeon_state_atom tx;
+       struct radeon_state_atom db;
+       struct radeon_state_atom cb;
+    struct radeon_state_atom vtx;
+       struct radeon_state_atom cp;    
+    struct radeon_state_atom timestamp;
+};
+
 typedef struct StreamDesc
 {
        GLint   size;   //number of data element
@@ -141,6 +165,9 @@ struct r600_context {
 
        struct r600_hw_state atoms;
 
+    struct evergreen_hw_state evergreen_atoms;
+    void * pChip;
+
        struct r700_vertex_program *selected_vp;
 
        /* Vertex buffers
@@ -150,16 +177,29 @@ struct r600_context {
     struct r700_index_buffer ind_buf;
        struct radeon_bo *blit_bo;
        GLboolean blit_bo_loaded;
+
+    /* Shader const buffer */
+    struct radeon_bo * vp_Constbo;
+    int                vp_bo_offset;
+    struct radeon_bo * fp_Constbo;
+    int                fp_bo_offset;
 };
 
+#define EVERGREEN_CONTEXT(ctx)         ((context_t *)(ctx->DriverCtx))
+
 #define R700_CONTEXT(ctx)              ((context_t *)(ctx->DriverCtx))
 #define GL_CONTEXT(context)     ((GLcontext *)(context->radeon.glCtx))
 
+#define GET_EVERGREEN_CHIP(context) ((EVERGREEN_CHIP_CONTEXT*)(context->pChip))
+
 extern GLboolean r600CreateContext(gl_api api,
                                   const __GLcontextModes * glVisual,
                                   __DRIcontext * driContextPriv,
                                   void *sharedContextPrivate);
 
+extern void r600DestroyContext(__DRIcontext *driContextPriv );
+extern void evergreenCreateChip(context_t *context);
+
 #define R700_CONTEXT_STATES(context) ((R700_CHIP_CONTEXT *)(&context->hw))
 
 #define R600_NEWPRIM( rmesa )                  \
@@ -175,6 +215,13 @@ do {                                                       \
        r600->radeon.hw.is_dirty = GL_TRUE;                     \
 } while(0)
 
+#define EVERGREEN_STATECHANGE(r600, ATOM)       \
+do {                                            \
+       R600_NEWPRIM(r600);                         \
+       r600->evergreen_atoms.ATOM.dirty = GL_TRUE;     \
+       r600->radeon.hw.is_dirty = GL_TRUE;         \
+} while(0)
+
 extern GLboolean r700SyncSurf(context_t *context,
                              struct radeon_bo *pbo,
                              uint32_t read_domain,
@@ -187,6 +234,9 @@ extern void r700Start3D(context_t *context);
 extern void r600InitAtoms(context_t *context);
 extern void r700InitDraw(GLcontext *ctx);
 
+extern void evergreenInitAtoms(context_t *context);
+extern void evergreenInitDraw(GLcontext *ctx);
+
 #define RADEON_D_CAPTURE 0
 #define RADEON_D_PLAYBACK 1
 #define RADEON_D_PLAYBACK_RAW 2
index 1eb89a53058903eed0de4dee8f0ba3f2e40b3683..a840106c144c32c7f0f85b473b697eb0738ca71c 100644 (file)
@@ -49,6 +49,71 @@ void r600EmitCacheFlush(context_t *rmesa)
 {
 }
 
+GLboolean r600AllocShaderConsts(GLcontext * ctx,
+                                void ** constbo,                        
+                                int sizeinBYTE,
+                                char * szShaderUsage)
+{
+       radeonContextPtr radeonctx = RADEON_CONTEXT(ctx);
+       struct radeon_bo * pbo;
+
+    if(sizeinBYTE < 64) /* SQ_ALU_CONST_BUFFER_SIZE need 64 bytes at least to be non 0 */
+    {
+        sizeinBYTE = 64;
+    }    
+
+shader_again_alloc:
+       pbo = radeon_bo_open(radeonctx->radeonScreen->bom,
+                       0,
+                       sizeinBYTE,
+                       256,
+                       RADEON_GEM_DOMAIN_GTT,
+                       0);
+
+       radeon_print(RADEON_SHADER, RADEON_NORMAL, "%s %p size %d: %s\n", __func__, pbo, sizeinBYTE, szShaderUsage);
+
+       if (!pbo) {
+               radeon_print(RADEON_MEMORY | RADEON_CS, RADEON_IMPORTANT, "No memory for buffer object. Flushing command buffer.\n");
+               rcommonFlushCmdBuf(radeonctx, __FUNCTION__);
+               goto shader_again_alloc;
+       }
+
+       radeon_cs_space_add_persistent_bo(radeonctx->cmdbuf.cs,
+                       pbo,
+                       RADEON_GEM_DOMAIN_GTT, 0);
+
+       if (radeon_cs_space_check_with_bo(radeonctx->cmdbuf.cs,
+                               pbo,
+                               RADEON_GEM_DOMAIN_GTT, 0)) {
+               radeon_error("failure to revalidate BOs - badness\n");
+               return GL_FALSE;
+       }
+
+       *constbo = (void*)pbo;
+
+       return GL_TRUE;
+}
+GLboolean r600EmitShaderConsts(GLcontext * ctx,
+                               void * constbo,
+                               int    bo_offset,
+                               GLvoid * data,
+                               int sizeinBYTE)
+{      
+       struct radeon_bo * pbo = (struct radeon_bo *)constbo;
+       uint8_t *out;
+
+       radeon_bo_map(pbo, 1);
+
+       out = (uint8_t*)(pbo->ptr);
+    out = (uint8_t*)ADD_POINTERS(pbo->ptr, bo_offset);
+
+       memcpy(out, data, sizeinBYTE);
+
+       radeon_bo_unmap(pbo);
+
+       return GL_TRUE;
+}
+
 GLboolean r600EmitShader(GLcontext * ctx,
                          void ** shaderbo,
                         GLvoid * data,
index 661774d11ea94c119bda8fe2b24ff87f33dab40f..259561539fae583542724b7b12f65c60dcdf1e96 100644 (file)
@@ -52,4 +52,14 @@ extern GLboolean r600EmitShader(GLcontext * ctx,
 extern GLboolean r600DeleteShader(GLcontext * ctx, 
                                  void * shaderbo);
 
+extern GLboolean r600AllocShaderConsts(GLcontext * ctx,
+                                void ** constbo,                        
+                                int sizeinBYTE,
+                                char * szShaderUsage);
+GLboolean r600EmitShaderConsts(GLcontext * ctx,
+                               void * constbo,
+                               int    bo_offset,
+                               GLvoid * data,
+                               int sizeinBYTE);
+
 #endif
index ba3690b70ed80b5acb1e37b37857e7f5c80740df..fd928cfe5d2c9ed04ee3fbcb7c383fe224309bda 100644 (file)
@@ -50,6 +50,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r700_fragprog.h"
 #include "r700_vertprog.h"
 
+#include "evergreen_tex.h"
+
 void r600UpdateTextureState(GLcontext * ctx);
 
 void r600UpdateTextureState(GLcontext * ctx)
@@ -878,6 +880,18 @@ GLboolean r600ValidateBuffers(GLcontext * ctx)
                                                  RADEON_GEM_DOMAIN_GTT, 0);
        }
 
+       pbo = (struct radeon_bo *)r700GetActiveFpShaderConstBo(ctx);
+       if (pbo) {
+               radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, pbo,
+                                                 RADEON_GEM_DOMAIN_GTT, 0);
+       }
+
+       pbo = (struct radeon_bo *)r700GetActiveVpShaderConstBo(ctx);
+       if (pbo) {
+               radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, pbo,
+                                                 RADEON_GEM_DOMAIN_GTT, 0);
+       }       
+
        ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, first_elem(&rmesa->radeon.dma.reserved)->bo, RADEON_GEM_DOMAIN_GTT, 0);
        if (ret)
                return GL_FALSE;
@@ -897,6 +911,12 @@ void r600SetTexOffset(__DRIcontext * pDRICtx, GLint texname,
        if (!tObj)
                return;
 
+    if(rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_CEDAR)
+    {
+        evergreenSetTexOffset(pDRICtx, texname, offset, depth, pitch);
+        return;
+    }    
+
        t->image_override = GL_TRUE;
 
        if (!offset)
@@ -989,6 +1009,12 @@ void r600SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_fo
        radeon = pDRICtx->driverPrivate;
        rmesa = pDRICtx->driverPrivate;
 
+    if(rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_CEDAR)
+    {
+        evergreenSetTexBuffer(pDRICtx, target, glx_texture_format, dPriv);
+        return;
+    }   
+
        rfb = dPriv->driverPrivate;
         texUnit = &radeon->glCtx->Texture.Unit[radeon->glCtx->Texture.CurrentUnit];
        texObj = _mesa_select_tex_object(radeon->glCtx, texUnit, target);
index 9c954cbf70c676e2617ba7ae8e22d8395f65d7b1..45ff9c06249d93fad3e85e1e9600b6e048bdbc0b 100644 (file)
@@ -38,6 +38,7 @@
 #include "r600_context.h"
 
 #include "r700_assembler.h"
+#include "evergreen_sq.h"
 
 #define USE_CF_FOR_CONTINUE_BREAK 1
 #define USE_CF_FOR_POP_AFTER      1
@@ -258,6 +259,18 @@ GLboolean is_reduction_opcode(PVSDWORD* dest)
     return GL_FALSE;
 }
 
+GLboolean EG_is_reduction_opcode(PVSDWORD* dest)
+{
+    if (dest->dst.op3 == 0) 
+    {
+        if ( (dest->dst.opcode == EG_OP2_INST_DOT4 || dest->dst.opcode == EG_OP2_INST_DOT4_IEEE || dest->dst.opcode == EG_OP2_INST_CUBE) ) 
+        {
+            return GL_TRUE;
+        }
+    }
+    return GL_FALSE;
+}
+
 GLuint GetSurfaceFormat(GLenum eType, GLuint nChannels, GLuint * pClient_size)
 {
     GLuint format = FMT_INVALID;
@@ -423,6 +436,60 @@ unsigned int r700GetNumOperands(GLuint opcode, GLuint nIsOp3)
     return 3;
 }
 
+unsigned int EG_GetNumOperands(GLuint opcode, GLuint nIsOp3) 
+{
+    if(nIsOp3 > 0)
+    {
+        return 3;
+    }
+
+    switch (opcode)
+    {
+    case EG_OP2_INST_ADD:
+    case EG_OP2_INST_KILLE:
+    case EG_OP2_INST_KILLGT:
+    case EG_OP2_INST_KILLGE:
+    case EG_OP2_INST_KILLNE:
+    case EG_OP2_INST_MUL: 
+    case EG_OP2_INST_MAX:
+    case EG_OP2_INST_MIN:
+    //case EG_OP2_INST_MAX_DX10:
+    //case EG_OP2_INST_MIN_DX10:
+    case EG_OP2_INST_SETE: 
+    case EG_OP2_INST_SETNE:
+    case EG_OP2_INST_SETGT:
+    case EG_OP2_INST_SETGE:
+    case EG_OP2_INST_PRED_SETE:
+    case EG_OP2_INST_PRED_SETGT:
+    case EG_OP2_INST_PRED_SETGE:
+    case EG_OP2_INST_PRED_SETNE:
+    case EG_OP2_INST_DOT4:
+    case EG_OP2_INST_DOT4_IEEE:
+    case EG_OP2_INST_CUBE:
+        return 2;  
+
+    case EG_OP2_INST_MOV: 
+    //case SQ_OP2_INST_MOVA_FLOOR:
+    case EG_OP2_INST_FRACT:
+    case EG_OP2_INST_FLOOR:
+    case EG_OP2_INST_TRUNC:
+    case EG_OP2_INST_EXP_IEEE:
+    case EG_OP2_INST_LOG_CLAMPED:
+    case EG_OP2_INST_LOG_IEEE:
+    case EG_OP2_INST_RECIP_IEEE:
+    case EG_OP2_INST_RECIPSQRT_IEEE:
+    case EG_OP2_INST_FLT_TO_INT:
+    case EG_OP2_INST_SIN:
+    case EG_OP2_INST_COS:
+        return 1;
+        
+    default: radeon_error(
+                   "Need instruction operand number for %x.\n", opcode); 
+    };
+
+    return 3;
+}
+
 int Init_r700_AssemblerBase(SHADER_PIPE_TYPE spt, r700_AssemblerBase* pAsm, R700_Shader* pShader)
 {
     GLuint i;
@@ -718,21 +785,55 @@ GLboolean add_vfetch_instruction(r700_AssemblerBase*     pAsm,
                        return GL_FALSE;
                }
 
-               pAsm->cf_current_vtx_clause_ptr->m_Word1.f.pop_count        = 0x0;
-               pAsm->cf_current_vtx_clause_ptr->m_Word1.f.cf_const         = 0x0;
-               pAsm->cf_current_vtx_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
-               pAsm->cf_current_vtx_clause_ptr->m_Word1.f.count            = 0x0;
-               pAsm->cf_current_vtx_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-               pAsm->cf_current_vtx_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
-               pAsm->cf_current_vtx_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_VTX;
-               pAsm->cf_current_vtx_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
-               pAsm->cf_current_vtx_clause_ptr->m_Word1.f.barrier          = 0x1;
+        if(8 == pAsm->unAsic)
+        {
+            SETfield(pAsm->cf_current_vtx_clause_ptr->m_Word1.val, EG_CF_INST_VC,
+                     EG_CF_WORD1__CF_INST_shift, EG_CF_WORD1__CF_INST_mask);
+            SETfield(pAsm->cf_current_vtx_clause_ptr->m_Word1.val, 0,
+                     EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask); 
+            SETfield(pAsm->cf_current_vtx_clause_ptr->m_Word1.val, 0,
+                     EG_CF_WORD1__CF_CONST_shift, EG_CF_WORD1__CF_CONST_mask);
+            SETfield(pAsm->cf_current_vtx_clause_ptr->m_Word1.val, SQ_CF_COND_ACTIVE,
+                     EG_CF_WORD1__COND_shift, EG_CF_WORD1__COND_mask);
+            SETfield(pAsm->cf_current_vtx_clause_ptr->m_Word1.val, 0,
+                     EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+            SETfield(pAsm->cf_current_vtx_clause_ptr->m_Word1.val, 0,
+                     EG_CF_WORD1__VPM_shift, EG_CF_WORD1__VPM_bit);
+            SETfield(pAsm->cf_current_vtx_clause_ptr->m_Word1.val, 0,
+                     EG_CF_WORD1__EOP_shift, EG_CF_WORD1__EOP_bit); 
+            SETfield(pAsm->cf_current_vtx_clause_ptr->m_Word1.val, 0,
+                     EG_CF_WORD1__WQM_shift, EG_CF_WORD1__WQM_bit);
+            SETfield(pAsm->cf_current_vtx_clause_ptr->m_Word1.val, 1,
+                     EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+        }
+        else
+        {
+                   pAsm->cf_current_vtx_clause_ptr->m_Word1.f.pop_count        = 0x0;
+                   pAsm->cf_current_vtx_clause_ptr->m_Word1.f.cf_const         = 0x0;
+                   pAsm->cf_current_vtx_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
+                   pAsm->cf_current_vtx_clause_ptr->m_Word1.f.count            = 0x0;
+                   pAsm->cf_current_vtx_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+                   pAsm->cf_current_vtx_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
+                   pAsm->cf_current_vtx_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_VTX;
+                   pAsm->cf_current_vtx_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+                   pAsm->cf_current_vtx_clause_ptr->m_Word1.f.barrier          = 0x1;
+        }
 
                LinkVertexInstruction(pAsm->cf_current_vtx_clause_ptr, vertex_instruction_ptr );
        }
        else
        {
-               pAsm->cf_current_vtx_clause_ptr->m_Word1.f.count++;
+        if(8 == pAsm->unAsic)
+        {
+            unsigned int count = GETbits(pAsm->cf_current_vtx_clause_ptr->m_Word1.val, 
+                                         EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask) + 1;
+            SETfield(pAsm->cf_current_vtx_clause_ptr->m_Word1.val, count,
+                     EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+        }
+        else
+        {
+                   pAsm->cf_current_vtx_clause_ptr->m_Word1.f.count++;
+        }
        }
 
        AddVTXInstruction(pAsm->pR700Shader, vertex_instruction_ptr);
@@ -767,20 +868,59 @@ GLboolean add_tex_instruction(r700_AssemblerBase*     pAsm,
             radeon_error("Could not allocate a new TEX CF instruction.\n");
                        return GL_FALSE;
                }
-        
-        pAsm->cf_current_tex_clause_ptr->m_Word1.f.pop_count        = 0x0;
-        pAsm->cf_current_tex_clause_ptr->m_Word1.f.cf_const         = 0x0;
-        pAsm->cf_current_tex_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
 
-        pAsm->cf_current_tex_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-        pAsm->cf_current_tex_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
-        pAsm->cf_current_tex_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_TEX;
-        pAsm->cf_current_tex_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
-        pAsm->cf_current_tex_clause_ptr->m_Word1.f.barrier          = 0x0;   //0x1;
+        if(8 == pAsm->unAsic)
+        {
+            SETfield(pAsm->cf_current_tex_clause_ptr->m_Word1.val, EG_CF_INST_TC,
+                     EG_CF_WORD1__CF_INST_shift, EG_CF_WORD1__CF_INST_mask);
+            SETfield(pAsm->cf_current_tex_clause_ptr->m_Word1.val, 0,
+                     EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask); 
+            SETfield(pAsm->cf_current_tex_clause_ptr->m_Word1.val, 0,
+                     EG_CF_WORD1__CF_CONST_shift, EG_CF_WORD1__CF_CONST_mask);
+            SETfield(pAsm->cf_current_tex_clause_ptr->m_Word1.val, SQ_CF_COND_ACTIVE,
+                     EG_CF_WORD1__COND_shift, EG_CF_WORD1__COND_mask);
+            SETfield(pAsm->cf_current_tex_clause_ptr->m_Word1.val, 0,
+                     EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+            SETfield(pAsm->cf_current_tex_clause_ptr->m_Word1.val, 0,
+                     EG_CF_WORD1__VPM_shift, EG_CF_WORD1__VPM_bit);
+            SETfield(pAsm->cf_current_tex_clause_ptr->m_Word1.val, 0,
+                     EG_CF_WORD1__EOP_shift, EG_CF_WORD1__EOP_bit); 
+            SETfield(pAsm->cf_current_tex_clause_ptr->m_Word1.val, 0,
+                     EG_CF_WORD1__WQM_shift, EG_CF_WORD1__WQM_bit);
+#ifdef FORCE_CF_TEX_BARRIER
+            SETfield(pAsm->cf_current_tex_clause_ptr->m_Word1.val, 1,
+                     EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+#else
+            SETfield(pAsm->cf_current_tex_clause_ptr->m_Word1.val, 0,
+                     EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+#endif
+        }
+        else
+        {        
+            pAsm->cf_current_tex_clause_ptr->m_Word1.f.pop_count        = 0x0;
+            pAsm->cf_current_tex_clause_ptr->m_Word1.f.cf_const         = 0x0;
+            pAsm->cf_current_tex_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
+
+            pAsm->cf_current_tex_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+            pAsm->cf_current_tex_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
+            pAsm->cf_current_tex_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_TEX;
+            pAsm->cf_current_tex_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+            pAsm->cf_current_tex_clause_ptr->m_Word1.f.barrier          = 0x0;   //0x1;
+        }
     }
     else 
-    {        
-        pAsm->cf_current_tex_clause_ptr->m_Word1.f.count++;
+    {      
+        if(8 == pAsm->unAsic)
+        {
+            unsigned int count = GETbits(pAsm->cf_current_tex_clause_ptr->m_Word1.val, 
+                                         EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask) + 1;
+            SETfield(pAsm->cf_current_vtx_clause_ptr->m_Word1.val, count,
+                     EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+        }
+        else
+        {        
+            pAsm->cf_current_tex_clause_ptr->m_Word1.f.count++;
+        }
     }
 
     // If this clause constains any TEX instruction that is dependent on a previous instruction, 
@@ -891,6 +1031,188 @@ GLboolean assemble_vfetch_instruction(r700_AssemblerBase* pAsm,
        return GL_TRUE;
 }
 
+GLboolean EG_assemble_vfetch_instruction(r700_AssemblerBase* pAsm,
+                                       GLuint              destination_register,                                                                      
+                                       GLenum              type,
+                                       GLint               size,
+                                       GLubyte             element,
+                                       GLuint              _signed,
+                                       GLboolean           normalize,
+                                       GLenum              format,
+                                       VTX_FETCH_METHOD  * pFetchMethod)
+{
+    GLuint client_size_inbyte;
+       GLuint data_format;
+    GLuint mega_fetch_count;
+       GLuint is_mega_fetch_flag;
+
+    GLuint dst_sel_x, dst_sel_y, dst_sel_z, dst_sel_w;
+
+    R700VertexGenericFetch*   vfetch_instruction_ptr;
+       R700VertexGenericFetch*   assembled_vfetch_instruction_ptr 
+                                     = pAsm->vfetch_instruction_ptr_array[element];
+
+    if (assembled_vfetch_instruction_ptr == NULL) 
+       {
+               vfetch_instruction_ptr = (R700VertexGenericFetch*) CALLOC_STRUCT(R700VertexGenericFetch);
+               if (vfetch_instruction_ptr == NULL) 
+               {
+                       return GL_FALSE;
+               }
+        Init_R700VertexGenericFetch(vfetch_instruction_ptr);
+    }
+       else 
+       {
+               vfetch_instruction_ptr = assembled_vfetch_instruction_ptr;
+       }
+
+    data_format = GetSurfaceFormat(type, size, &client_size_inbyte);   
+
+       if(GL_TRUE == pFetchMethod->bEnableMini) //More conditions here
+       {
+               //TODO : mini fetch
+               mega_fetch_count = 0;
+               is_mega_fetch_flag = 0;
+       }
+       else
+       {
+               mega_fetch_count = MEGA_FETCH_BYTES - 1;
+               is_mega_fetch_flag       = 0x1;
+               pFetchMethod->mega_fetch_remainder = MEGA_FETCH_BYTES - client_size_inbyte;
+       }
+
+    SETfield(vfetch_instruction_ptr->m_Word0.val, EG_VC_INST_FETCH,
+             EG_VTX_WORD0__VC_INST_shift,
+             EG_VTX_WORD0__VC_INST_mask);
+    SETfield(vfetch_instruction_ptr->m_Word0.val, EG_VTX_FETCH_VERTEX_DATA,
+             EG_VTX_WORD0__FETCH_TYPE_shift,
+             EG_VTX_WORD0__FETCH_TYPE_mask);
+    CLEARbit(vfetch_instruction_ptr->m_Word0.val, 
+             EG_VTX_WORD0__FWQ_bit);
+    SETfield(vfetch_instruction_ptr->m_Word0.val, element,
+             EG_VTX_WORD0__BUFFER_ID_shift,
+             EG_VTX_WORD0__BUFFER_ID_mask);
+    SETfield(vfetch_instruction_ptr->m_Word0.val, 0x0,
+             EG_VTX_WORD0__SRC_GPR_shift,
+             EG_VTX_WORD0__SRC_GPR_mask);
+    SETfield(vfetch_instruction_ptr->m_Word0.val, SQ_ABSOLUTE,
+             EG_VTX_WORD0__SRC_REL_shift,
+             EG_VTX_WORD0__SRC_REL_bit);
+    SETfield(vfetch_instruction_ptr->m_Word0.val, SQ_SEL_X,
+             EG_VTX_WORD0__SRC_SEL_X_shift,
+             EG_VTX_WORD0__SRC_SEL_X_mask);
+    SETfield(vfetch_instruction_ptr->m_Word0.val, mega_fetch_count,
+             EG_VTX_WORD0__MFC_shift,
+             EG_VTX_WORD0__MFC_mask);
+                       
+       if(format == GL_BGRA)
+       {        
+               dst_sel_x        = (size < 1) ? SQ_SEL_0 : SQ_SEL_Z;
+               dst_sel_y        = (size < 2) ? SQ_SEL_0 : SQ_SEL_Y;
+               dst_sel_z        = (size < 3) ? SQ_SEL_0 : SQ_SEL_X;
+               dst_sel_w        = (size < 4) ? SQ_SEL_1 : SQ_SEL_W;
+       }
+       else
+       {
+               dst_sel_x        = (size < 1) ? SQ_SEL_0 : SQ_SEL_X;
+               dst_sel_y        = (size < 2) ? SQ_SEL_0 : SQ_SEL_Y;
+               dst_sel_z        = (size < 3) ? SQ_SEL_0 : SQ_SEL_Z;
+               dst_sel_w        = (size < 4) ? SQ_SEL_1 : SQ_SEL_W;
+
+       }
+    SETfield(vfetch_instruction_ptr->m_Word1.val, dst_sel_x,
+             EG_VTX_WORD1__DST_SEL_X_shift,
+             EG_VTX_WORD1__DST_SEL_X_mask);
+    SETfield(vfetch_instruction_ptr->m_Word1.val, dst_sel_y,
+             EG_VTX_WORD1__DST_SEL_Y_shift,
+             EG_VTX_WORD1__DST_SEL_Y_mask);
+    SETfield(vfetch_instruction_ptr->m_Word1.val, dst_sel_z,
+             EG_VTX_WORD1__DST_SEL_Z_shift,
+             EG_VTX_WORD1__DST_SEL_Z_mask);
+    SETfield(vfetch_instruction_ptr->m_Word1.val, dst_sel_w,
+             EG_VTX_WORD1__DST_SEL_W_shift,
+             EG_VTX_WORD1__DST_SEL_W_mask);
+    
+    SETfield(vfetch_instruction_ptr->m_Word1.val, 0, /* use format here, in r6/r7, format used set in const, need to use same */
+             EG_VTX_WORD1__UCF_shift,
+             EG_VTX_WORD1__UCF_bit);
+    SETfield(vfetch_instruction_ptr->m_Word1.val, data_format,
+             EG_VTX_WORD1__DATA_FORMAT_shift,
+             EG_VTX_WORD1__DATA_FORMAT_mask);  
+#ifdef TEST_VFETCH
+    SETfield(vfetch_instruction_ptr->m_Word1.val, SQ_FORMAT_COMP_SIGNED,
+                 EG_VTX_WORD1__FCA_shift,
+                 EG_VTX_WORD1__FCA_bit);
+#else
+    if(1 == _signed)
+    {
+        SETfield(vfetch_instruction_ptr->m_Word1.val, SQ_FORMAT_COMP_SIGNED,
+                 EG_VTX_WORD1__FCA_shift,
+                 EG_VTX_WORD1__FCA_bit);        
+    }
+    else
+    {
+        SETfield(vfetch_instruction_ptr->m_Word1.val, SQ_FORMAT_COMP_UNSIGNED,
+                 EG_VTX_WORD1__FCA_shift,
+                 EG_VTX_WORD1__FCA_bit);           
+    }
+#endif /* TEST_VFETCH */
+
+    if(GL_TRUE == normalize)
+    {
+        SETfield(vfetch_instruction_ptr->m_Word1.val, SQ_NUM_FORMAT_NORM,
+                 EG_VTX_WORD1__NFA_shift,
+                 EG_VTX_WORD1__NFA_mask);          
+    }
+    else
+    {
+        SETfield(vfetch_instruction_ptr->m_Word1.val, SQ_NUM_FORMAT_SCALED,
+                 EG_VTX_WORD1__NFA_shift,
+                 EG_VTX_WORD1__NFA_mask);        
+    }
+
+       /* Destination register */
+    SETfield(vfetch_instruction_ptr->m_Word1.val, destination_register,
+             EG_VTX_WORD1_GPR__DST_GPR_shift,
+             EG_VTX_WORD1_GPR__DST_GPR_mask);
+       SETfield(vfetch_instruction_ptr->m_Word1.val, SQ_ABSOLUTE,
+             EG_VTX_WORD1_GPR__DST_REL_shift,
+             EG_VTX_WORD1_GPR__DST_REL_bit); 
+       
+
+    SETfield(vfetch_instruction_ptr->m_Word2.val, 0,
+             EG_VTX_WORD2__OFFSET_shift,
+             EG_VTX_WORD2__OFFSET_mask); 
+    SETfield(vfetch_instruction_ptr->m_Word2.val, SQ_ENDIAN_NONE,
+             EG_VTX_WORD2__ENDIAN_SWAP_shift,
+             EG_VTX_WORD2__ENDIAN_SWAP_mask);
+    SETfield(vfetch_instruction_ptr->m_Word2.val, 0,
+             EG_VTX_WORD2__CBNS_shift,
+             EG_VTX_WORD2__CBNS_bit);
+    SETfield(vfetch_instruction_ptr->m_Word2.val, is_mega_fetch_flag,
+             EG_VTX_WORD2__MEGA_FETCH_shift,
+             EG_VTX_WORD2__MEGA_FETCH_mask);
+       
+       if (assembled_vfetch_instruction_ptr == NULL) 
+       {
+               if ( GL_FALSE == add_vfetch_instruction(pAsm, (R700VertexInstruction *)vfetch_instruction_ptr) ) 
+        {   
+                       return GL_FALSE;
+               }
+
+               if (pAsm->vfetch_instruction_ptr_array[element] != NULL) 
+               {
+                       return GL_FALSE;
+               }
+               else 
+               {
+                       pAsm->vfetch_instruction_ptr_array[element] = vfetch_instruction_ptr;
+               }
+       }
+
+       return GL_TRUE;
+}
+
 GLboolean assemble_vfetch_instruction2(r700_AssemblerBase* pAsm,
                                        GLuint              destination_register,                                                                      
                                        GLenum              type,
@@ -1357,7 +1679,7 @@ GLboolean assemble_src(r700_AssemblerBase *pAsm,
             break;      
         case PROGRAM_INPUT:
             setaddrmode_PVSSRC(&(pAsm->S[fld].src), ADDR_ABSOLUTE); 
-            pAsm->S[fld].src.rtype = SRC_REG_INPUT;
+            pAsm->S[fld].src.rtype = SRC_REG_GPR;
             switch (pAsm->currentShaderType)
             {
             case SPT_FP:
@@ -1368,6 +1690,19 @@ GLboolean assemble_src(r700_AssemblerBase *pAsm,
                 break;
             }
             break;      
+        case PROGRAM_OUTPUT:
+            setaddrmode_PVSSRC(&(pAsm->S[fld].src), ADDR_ABSOLUTE);
+            pAsm->S[fld].src.rtype = SRC_REG_GPR;
+            switch (pAsm->currentShaderType)
+            {
+            case SPT_FP:
+                pAsm->S[fld].src.reg = pAsm->uiFP_OutputMap[pILInst->SrcReg[src].Index];
+                break;
+            case SPT_VP:
+                pAsm->S[fld].src.reg = pAsm->ucVP_OutputMap[pILInst->SrcReg[src].Index];
+                break;
+            }
+            break;
         default:
             radeon_error("Invalid source argument type : %d \n", pILInst->SrcReg[src].File);
             return GL_FALSE;
@@ -1521,7 +1856,7 @@ GLboolean tex_src(r700_AssemblerBase *pAsm)
                         bValidTexCoord = GL_TRUE;
                         pAsm->S[0].src.reg   =
                             pAsm->ucVP_AttributeMap[pILInst->SrcReg[0].Index];
-                        pAsm->S[0].src.rtype = SRC_REG_INPUT;
+                        pAsm->S[0].src.rtype = SRC_REG_GPR;
                         break;
                 }
             }
@@ -1544,7 +1879,7 @@ GLboolean tex_src(r700_AssemblerBase *pAsm)
                         bValidTexCoord = GL_TRUE;
                         pAsm->S[0].src.reg   =
                             pAsm->uiFP_AttributeMap[pILInst->SrcReg[0].Index];
-                        pAsm->S[0].src.rtype = SRC_REG_INPUT;
+                        pAsm->S[0].src.rtype = SRC_REG_GPR;
                         break;
                     case FRAG_ATTRIB_FACE:
                         fprintf(stderr, "FRAG_ATTRIB_FACE unsupported\n");
@@ -1560,7 +1895,7 @@ GLboolean tex_src(r700_AssemblerBase *pAsm)
                                    bValidTexCoord = GL_TRUE;
                     pAsm->S[0].src.reg   =
                         pAsm->uiFP_AttributeMap[pILInst->SrcReg[0].Index];
-                    pAsm->S[0].src.rtype = SRC_REG_INPUT;
+                    pAsm->S[0].src.rtype = SRC_REG_GPR;
                 }
             }
 
@@ -1606,19 +1941,68 @@ GLboolean assemble_tex_instruction(r700_AssemblerBase *pAsm, GLboolean normalize
     texture_coordinate_source = &(pAsm->S[0].src);
     texture_unit_source       = &(pAsm->S[1].src);
 
-    tex_instruction_ptr->m_Word0.f.tex_inst         = pAsm->D.dst.opcode;
-    tex_instruction_ptr->m_Word0.f.bc_frac_mode     = 0x0;
-    tex_instruction_ptr->m_Word0.f.fetch_whole_quad = 0x0;
-    tex_instruction_ptr->m_Word0.f.alt_const        = 0;
-
-    if(SPT_VP == pAsm->currentShaderType)
+    if(8 == pAsm->unAsic) /* evergreen */
     {
-        tex_instruction_ptr->m_Word0.f.resource_id      = texture_unit_source->reg + VERT_ATTRIB_MAX;
-        pAsm->unVetTexBits |= 1 << texture_unit_source->reg;
+    
+        SETfield(tex_instruction_ptr->m_Word0.val, pAsm->D.dst.opcode,
+                 EG_TEX_WORD0__TEX_INST_shift,
+                 EG_TEX_WORD0__TEX_INST_mask);
+
+        if(  (SQ_TEX_INST_GET_GRADIENTS_H == pAsm->D.dst.opcode)
+           ||(SQ_TEX_INST_GET_GRADIENTS_V == pAsm->D.dst.opcode) )
+        {
+            /* Use fine texel derivative calculation rather than use quad derivative */
+            SETfield(tex_instruction_ptr->m_Word0.val, 1,
+                     EG_TEX_WORD0__INST_MOD_shift,
+                     EG_TEX_WORD0__INST_MOD_mask);
+        }
+        else
+        {
+            SETfield(tex_instruction_ptr->m_Word0.val, 0,
+                     EG_TEX_WORD0__INST_MOD_shift,
+                     EG_TEX_WORD0__INST_MOD_mask);
+        }
+
+        CLEARbit(tex_instruction_ptr->m_Word0.val, EG_TEX_WORD0__FWQ_bit);                 
+
+        if(SPT_VP == pAsm->currentShaderType)
+        {
+            SETfield(tex_instruction_ptr->m_Word0.val, (texture_unit_source->reg + VERT_ATTRIB_MAX),
+                     EG_TEX_WORD0__RESOURCE_ID_shift,
+                     EG_TEX_WORD0__RESOURCE_ID_mask);
+            pAsm->unVetTexBits |= 1 << texture_unit_source->reg;
+        }
+        else
+        {
+            SETfield(tex_instruction_ptr->m_Word0.val, texture_unit_source->reg,
+                     EG_TEX_WORD0__RESOURCE_ID_shift,
+                     EG_TEX_WORD0__RESOURCE_ID_mask);
+        }
+        
+        CLEARbit(tex_instruction_ptr->m_Word0.val, EG_TEX_WORD0__ALT_CONST_bit);
+        SETfield(tex_instruction_ptr->m_Word0.val, 0,
+                 EG_TEX_WORD0__RIM_shift,
+                 EG_TEX_WORD0__RIM_mask);
+        SETfield(tex_instruction_ptr->m_Word0.val, 0,
+                 EG_TEX_WORD0__SIM_shift,
+                 EG_TEX_WORD0__SIM_mask);
     }
     else
     {
-        tex_instruction_ptr->m_Word0.f.resource_id      = texture_unit_source->reg;
+        tex_instruction_ptr->m_Word0.f.tex_inst         = pAsm->D.dst.opcode;
+        tex_instruction_ptr->m_Word0.f.bc_frac_mode     = 0x0;
+        tex_instruction_ptr->m_Word0.f.fetch_whole_quad = 0x0;
+        tex_instruction_ptr->m_Word0.f.alt_const        = 0;
+
+        if(SPT_VP == pAsm->currentShaderType)
+        {
+            tex_instruction_ptr->m_Word0.f.resource_id      = texture_unit_source->reg + VERT_ATTRIB_MAX;
+            pAsm->unVetTexBits |= 1 << texture_unit_source->reg;
+        }
+        else
+        {
+            tex_instruction_ptr->m_Word0.f.resource_id      = texture_unit_source->reg;
+        }
     }
 
     tex_instruction_ptr->m_Word1.f.lod_bias     = 0x0;
@@ -1644,8 +2028,20 @@ GLboolean assemble_tex_instruction(r700_AssemblerBase *pAsm, GLboolean normalize
     if ( (pAsm->D.dst.rtype == DST_REG_TEMPORARY) || 
          (pAsm->D.dst.rtype == DST_REG_OUT) ) 
     {
-        tex_instruction_ptr->m_Word0.f.src_gpr    = texture_coordinate_source->reg;
-        tex_instruction_ptr->m_Word0.f.src_rel    = SQ_ABSOLUTE;
+        if(8 == pAsm->unAsic) /* evergreen */
+        {
+            SETfield(tex_instruction_ptr->m_Word0.val, texture_coordinate_source->reg,
+                     EG_TEX_WORD0__SRC_GPR_shift,
+                     EG_TEX_WORD0__SRC_GPR_mask);
+            SETfield(tex_instruction_ptr->m_Word0.val, SQ_ABSOLUTE,
+                     EG_TEX_WORD0__SRC_REL_shift,
+                     EG_TEX_WORD0__SRC_REL_bit);
+        }
+        else
+        {
+            tex_instruction_ptr->m_Word0.f.src_gpr    = texture_coordinate_source->reg;
+            tex_instruction_ptr->m_Word0.f.src_rel    = SQ_ABSOLUTE;
+        }
 
         tex_instruction_ptr->m_Word1.f.dst_gpr    = pAsm->D.dst.reg;
         tex_instruction_ptr->m_Word1.f.dst_rel    = SQ_ABSOLUTE;
@@ -1696,7 +2092,8 @@ void initialize(r700_AssemblerBase *pAsm)
 GLboolean assemble_alu_src(R700ALUInstruction*  alu_instruction_ptr,
                            int                  source_index,
                            PVSSRC*              pSource,
-                           BITS                 scalar_channel_index)
+                           BITS                 scalar_channel_index,
+                           r700_AssemblerBase  *pAsm)
 {
     BITS src_sel;
     BITS src_rel;
@@ -1745,14 +2142,23 @@ GLboolean assemble_alu_src(R700ALUInstruction*  alu_instruction_ptr,
     else 
     {
         if ( (pSource->rtype == SRC_REG_TEMPORARY) || 
-             (pSource->rtype == SRC_REG_INPUT)
+             (pSource->rtype == SRC_REG_GPR)
         ) 
         {
             src_sel = pSource->reg;
         }
         else if (pSource->rtype == SRC_REG_CONSTANT)
         {
-            src_sel = pSource->reg + CFILE_REGISTER_OFFSET;            
+            /* TODO : 4 const buffers */
+            if(GL_TRUE == pAsm->bUseMemConstant) 
+            {
+                src_sel = pSource->reg + SQ_ALU_SRC_KCACHE0_BASE;
+                pAsm->kcacheUsed = SQ_ALU_SRC_KCACHE0_BASE;
+            }
+            else
+            {
+                src_sel = pSource->reg + CFILE_REGISTER_OFFSET;   
+            }
         }
         else if (pSource->rtype == SRC_REC_LITERAL)
         {
@@ -1902,6 +2308,17 @@ GLboolean add_alu_instruction(r700_AssemblerBase* pAsm,
         pAsm->cf_current_alu_clause_ptr->m_Word1.f.count += (GetInstructionSize(alu_instruction_ptr->m_ShaderInstType) / 2);
     }
 
+    /* TODO : handle 4 bufs */
+    if( (pAsm->kcacheUsed > 0) && (GL_TRUE == pAsm->bUseMemConstant) )
+    {
+        pAsm->cf_current_alu_clause_ptr->m_Word0.f.kcache_bank0 = 0x0;
+        pAsm->cf_current_alu_clause_ptr->m_Word0.f.kcache_bank1 = 0x0;
+        pAsm->cf_current_alu_clause_ptr->m_Word0.f.kcache_mode0 = SQ_CF_KCACHE_LOCK_2;
+        pAsm->cf_current_alu_clause_ptr->m_Word1.f.kcache_mode1 = SQ_CF_KCACHE_NOP;
+        pAsm->cf_current_alu_clause_ptr->m_Word1.f.kcache_addr0 = 0x0;
+        pAsm->cf_current_alu_clause_ptr->m_Word1.f.kcache_addr1 = 0x0;
+    }
+
     // If this clause constains any instruction that is forward dependent on a TEX instruction, 
     // set the whole_quad_mode for this clause
     if ( pAsm->pInstDeps[pAsm->uiCurInst].nDstDep > (-1) ) 
@@ -1925,6 +2342,80 @@ GLboolean add_alu_instruction(r700_AssemblerBase* pAsm,
     return GL_TRUE;
 }
 
+GLboolean EG_add_ps_interp(r700_AssemblerBase* pAsm)
+{
+    R700ALUInstruction * alu_instruction_ptr = NULL;
+
+    int          ui;
+    unsigned int uj;
+    unsigned int unWord0Temp = 0x380C00;
+    unsigned int unWord1Temp = 0x146B10;    //SQ_SEL_X
+
+    if(pAsm->uIIns > 0)
+    {                
+        for(ui=(pAsm->uIIns-1); ui>=0; ui--)
+        {                        
+            for(uj=0; uj<8; uj++)
+            {
+                alu_instruction_ptr = (R700ALUInstruction*) CALLOC_STRUCT(R700ALUInstruction);
+                Init_R700ALUInstruction(alu_instruction_ptr);
+                alu_instruction_ptr->m_Word0.val = unWord0Temp;  
+                alu_instruction_ptr->m_Word1.val = unWord1Temp;
+
+                if(uj < 4)
+                {
+                    SETfield(alu_instruction_ptr->m_Word1.val, EG_OP2_INST_INTERP_ZW,
+                             EG_ALU_WORD1_OP2__ALU_INST_shift, EG_ALU_WORD1_OP2__ALU_INST_mask);
+                }
+                else
+                {
+                    SETfield(alu_instruction_ptr->m_Word1.val, EG_OP2_INST_INTERP_XY,
+                             EG_ALU_WORD1_OP2__ALU_INST_shift, EG_ALU_WORD1_OP2__ALU_INST_mask);
+                }
+                if( (uj > 1) && (uj < 6) )
+                {
+                    SETfield(alu_instruction_ptr->m_Word1.val, 1,
+                             EG_ALU_WORD1_OP2__WRITE_MASK_shift, EG_ALU_WORD1_OP2__WRITE_MASK_bit);
+                }
+                else
+                {
+                    SETfield(alu_instruction_ptr->m_Word1.val, 0,
+                             EG_ALU_WORD1_OP2__WRITE_MASK_shift, EG_ALU_WORD1_OP2__WRITE_MASK_bit);
+                }
+                if( (uj > 1) && (uj < 6) )
+                {
+                    SETfield(alu_instruction_ptr->m_Word1.val, ui,
+                             EG_ALU_WORD1__DST_GPR_shift, EG_ALU_WORD1__DST_GPR_mask);
+                }  
+                else
+                {
+                    SETfield(alu_instruction_ptr->m_Word1.val, 111,
+                             EG_ALU_WORD1__DST_GPR_shift, EG_ALU_WORD1__DST_GPR_mask);
+                }                
+
+                SETfield(alu_instruction_ptr->m_Word1.val, (uj % 4),
+                         EG_ALU_WORD1__DST_CHAN_shift, EG_ALU_WORD1__DST_CHAN_mask);
+                SETfield(alu_instruction_ptr->m_Word0.val, (1 - (uj % 2)),
+                         EG_ALU_WORD0__SRC0_CHAN_shift, EG_ALU_WORD0__SRC0_CHAN_mask);
+                SETfield(alu_instruction_ptr->m_Word0.val, (EG_ALU_SRC_PARAM_BASE + ui),
+                         EG_ALU_WORD0__SRC1_SEL_shift, EG_ALU_WORD0__SRC1_SEL_mask);
+                if(3 == (uj % 4))
+                {
+                    SETfield(alu_instruction_ptr->m_Word0.val, 1,
+                             EG_ALU_WORD0__LAST_shift, EG_ALU_WORD0__LAST_bit);
+                }
+
+                if(GL_FALSE == add_alu_instruction(pAsm, alu_instruction_ptr, 4) )
+                {            
+                    return GL_FALSE;
+                }
+            }            
+        }
+    }
+
+    return GL_TRUE;
+}
+
 void get_src_properties(R700ALUInstruction*  alu_instruction_ptr,
                         int                  source_index,
                         BITS*                psrc_sel,
@@ -2175,8 +2666,16 @@ GLboolean check_scalar(r700_AssemblerBase* pAsm,
     BITS src_neg [3] = {0,0,0};
 
     GLuint swizzle_key;
+    GLuint number_of_operands;
 
-    GLuint number_of_operands = r700GetNumOperands(pAsm->D.dst.opcode, pAsm->D.dst.op3);
+    if(8 == pAsm->unAsic)
+    {
+        number_of_operands = EG_GetNumOperands(pAsm->D.dst.opcode, pAsm->D.dst.op3);
+    }
+    else
+    {
+        number_of_operands = r700GetNumOperands(pAsm->D.dst.opcode, pAsm->D.dst.op3);
+    }
 
     for (src=0; src<number_of_operands; src++) 
     {
@@ -2264,8 +2763,16 @@ GLboolean check_vector(r700_AssemblerBase* pAsm,
     BITS src_neg [3] = {0,0,0};
 
     GLuint swizzle_key;
+    GLuint number_of_operands;
 
-    GLuint number_of_operands = r700GetNumOperands(pAsm->D.dst.opcode, pAsm->D.dst.op3);
+    if(8 == pAsm->unAsic)
+    {
+        number_of_operands = EG_GetNumOperands(pAsm->D.dst.opcode, pAsm->D.dst.op3);
+    }
+    else
+    {
+        number_of_operands = r700GetNumOperands(pAsm->D.dst.opcode, pAsm->D.dst.op3);
+    }
 
     for (src=0; src<number_of_operands; src++) 
     {
@@ -2345,12 +2852,23 @@ GLboolean assemble_alu_instruction(r700_AssemblerBase *pAsm)
     PVSSRC * pcurrent_source;
     int    current_source_index;
     GLuint contiguous_slots_needed;
+    GLuint uNumSrc;
+    GLboolean bSplitInst;
+    
+    if(8 == pAsm->unAsic)
+    {
+        uNumSrc = EG_GetNumOperands(pAsm->D.dst.opcode, pAsm->D.dst.op3);
+    }
+    else
+    {
+        uNumSrc = r700GetNumOperands(pAsm->D.dst.opcode, pAsm->D.dst.op3);
+    }
 
-    GLuint    uNumSrc = r700GetNumOperands(pAsm->D.dst.opcode, pAsm->D.dst.op3);
     //GLuint    channel_swizzle, j;
     //GLuint    chan_counter[4] = {0, 0, 0, 0};
     //PVSSRC *  pSource[3];
-    GLboolean bSplitInst = GL_FALSE;
+    bSplitInst       = GL_FALSE;
+    pAsm->kcacheUsed = 0;
 
     if (1 == pAsm->D.dst.math) 
     {
@@ -2384,7 +2902,7 @@ GLboolean assemble_alu_instruction(r700_AssemblerBase *pAsm)
                     default: channel_swizzle = SQ_SEL_MASK; break;
                 }
                 if ( ((pSource[j]->rtype == SRC_REG_TEMPORARY) || 
-                     (pSource[j]->rtype == SRC_REG_INPUT))
+                     (pSource[j]->rtype == SRC_REG_GPR))
                      && (channel_swizzle <= SQ_SEL_W) )
                 {                    
                     chan_counter[channel_swizzle]++;                        
@@ -2449,7 +2967,8 @@ GLboolean assemble_alu_instruction(r700_AssemblerBase *pAsm)
         if (GL_FALSE == assemble_alu_src(alu_instruction_ptr,
                                          current_source_index,
                                          pcurrent_source, 
-                                         scalar_channel_index) )     
+                                         scalar_channel_index,
+                                         pAsm) )     
         {            
             return GL_FALSE;
         }
@@ -2463,7 +2982,8 @@ GLboolean assemble_alu_instruction(r700_AssemblerBase *pAsm)
             if (GL_FALSE == assemble_alu_src(alu_instruction_ptr,
                                              current_source_index,
                                              pcurrent_source, 
-                                             scalar_channel_index) ) 
+                                             scalar_channel_index,
+                                             pAsm) ) 
             {                
                 return GL_FALSE;
             }
@@ -2546,7 +3066,8 @@ GLboolean assemble_alu_instruction(r700_AssemblerBase *pAsm)
             if ( GL_FALSE == assemble_alu_src(alu_instruction_ptr,
                                               current_source_index,
                                               pcurrent_source, 
-                                              scalar_channel_index) ) 
+                                              scalar_channel_index,
+                                              pAsm) ) 
             {
                 return GL_FALSE;
             }
@@ -2987,7 +3508,14 @@ GLboolean assemble_DOT(r700_AssemblerBase *pAsm)
         return GL_FALSE;
     }
  
-    pAsm->D.dst.opcode = SQ_OP2_INST_DOT4;  
+    if(8 == pAsm->unAsic)
+    {
+        pAsm->D.dst.opcode = EG_OP2_INST_DOT4;
+    }
+    else
+    {
+        pAsm->D.dst.opcode = SQ_OP2_INST_DOT4;  
+    }
 
     if( GL_FALSE == assemble_dst(pAsm) )
     {
@@ -3004,7 +3532,14 @@ GLboolean assemble_DOT(r700_AssemblerBase *pAsm)
         return GL_FALSE;
     }
 
-    if(OPCODE_DP3 == pAsm->pILInst[pAsm->uiCurInst].Opcode)
+    if(OPCODE_DP2 == pAsm->pILInst[pAsm->uiCurInst].Opcode)
+    {
+       zerocomp_PVSSRC(&(pAsm->S[0].src),2);
+       zerocomp_PVSSRC(&(pAsm->S[0].src),3);
+       zerocomp_PVSSRC(&(pAsm->S[1].src),2);
+       zerocomp_PVSSRC(&(pAsm->S[1].src),3);
+    }
+    else if(OPCODE_DP3 == pAsm->pILInst[pAsm->uiCurInst].Opcode)
     {
         zerocomp_PVSSRC(&(pAsm->S[0].src), 3);
         zerocomp_PVSSRC(&(pAsm->S[1].src), 3);
@@ -3062,6 +3597,11 @@ GLboolean assemble_DST(r700_AssemblerBase *pAsm)
 
 GLboolean assemble_EX2(r700_AssemblerBase *pAsm)
 {
+    if(8 == pAsm->unAsic)
+    {
+        return assemble_math_function(pAsm, EG_OP2_INST_EXP_IEEE);
+    }
+
     return assemble_math_function(pAsm, SQ_OP2_INST_EXP_IEEE);
 }
 
@@ -3094,7 +3634,14 @@ GLboolean assemble_EXP(r700_AssemblerBase *pAsm)
             return GL_FALSE;
         }
 
-        pAsm->D.dst.opcode = SQ_OP2_INST_EXP_IEEE;
+        if(8 == pAsm->unAsic)
+        {
+            pAsm->D.dst.opcode = EG_OP2_INST_EXP_IEEE;
+        }
+        else
+        {
+            pAsm->D.dst.opcode = SQ_OP2_INST_EXP_IEEE;
+        }
         pAsm->D.dst.math = 1;
 
         if( GL_FALSE == assemble_dst(pAsm) )
@@ -3143,7 +3690,14 @@ GLboolean assemble_EXP(r700_AssemblerBase *pAsm)
     // EX2     dst.z,    a.x
 
     if ((pAsm->pILInst->DstReg.WriteMask >> 2) & 0x1) {
-        pAsm->D.dst.opcode = SQ_OP2_INST_EXP_IEEE;
+        if(8 == pAsm->unAsic)
+        {
+            pAsm->D.dst.opcode = EG_OP2_INST_EXP_IEEE;
+        }
+        else
+        {
+            pAsm->D.dst.opcode = SQ_OP2_INST_EXP_IEEE;
+        }
         pAsm->D.dst.math = 1;
 
         if( GL_FALSE == assemble_dst(pAsm) )
@@ -3218,6 +3772,11 @@ GLboolean assemble_FLR(r700_AssemblerBase *pAsm)
 
 GLboolean assemble_FLR_INT(r700_AssemblerBase *pAsm)
 {
+    if(8 == pAsm->unAsic)
+    {
+        return assemble_math_function(pAsm, EG_OP2_INST_FLT_TO_INT);
+    }
+
     return assemble_math_function(pAsm, SQ_OP2_INST_FLT_TO_INT);
 }
 
@@ -3300,6 +3859,11 @@ GLboolean assemble_KIL(r700_AssemblerBase *pAsm, GLuint opcode)
 
 GLboolean assemble_LG2(r700_AssemblerBase *pAsm) 
 { 
+    if(8 == pAsm->unAsic)
+    {
+        return assemble_math_function(pAsm, EG_OP2_INST_LOG_IEEE);
+    }
+
     return assemble_math_function(pAsm, SQ_OP2_INST_LOG_IEEE);
 }
 
@@ -3339,7 +3903,14 @@ GLboolean assemble_LRP(r700_AssemblerBase *pAsm)
            return GL_FALSE;
     }
 
-    pAsm->D.dst.opcode = SQ_OP3_INST_MULADD;
+    if(8 == pAsm->unAsic)
+    {
+        pAsm->D.dst.opcode = EG_OP3_INST_MULADD;
+    }
+    else
+    {
+        pAsm->D.dst.opcode = SQ_OP3_INST_MULADD;
+    }
     pAsm->D.dst.op3    = 1;
 
     pAsm->D.dst.rtype = DST_REG_TEMPORARY;
@@ -3437,7 +4008,14 @@ GLboolean assemble_LOG(r700_AssemblerBase *pAsm)
     // LG2     tmp2.x,   tmp1.x
     // FLOOR   tmp3.x,   tmp2.x
 
-    pAsm->D.dst.opcode = SQ_OP2_INST_LOG_IEEE;
+    if(8 == pAsm->unAsic)
+    {
+        pAsm->D.dst.opcode = EG_OP2_INST_LOG_IEEE;
+    }
+    else
+    {
+        pAsm->D.dst.opcode = SQ_OP2_INST_LOG_IEEE;
+    }
     pAsm->D.dst.math = 1;
 
     setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
@@ -3528,7 +4106,14 @@ GLboolean assemble_LOG(r700_AssemblerBase *pAsm)
         return GL_FALSE;
     }
 
-    pAsm->D.dst.opcode = SQ_OP2_INST_EXP_IEEE;
+    if(8 == pAsm->unAsic)
+    {
+        pAsm->D.dst.opcode = EG_OP2_INST_EXP_IEEE;
+    }
+    else
+    {
+        pAsm->D.dst.opcode = SQ_OP2_INST_EXP_IEEE;
+    }
     pAsm->D.dst.math = 1;
 
     if( GL_FALSE == assemble_dst(pAsm) )
@@ -3610,7 +4195,14 @@ GLboolean assemble_MAD(struct r700_AssemblerBase *pAsm)
         return GL_FALSE;
     }
 
-       pAsm->D.dst.opcode = SQ_OP3_INST_MULADD;  
+    if(8 == pAsm->unAsic)
+    {
+        pAsm->D.dst.opcode = EG_OP3_INST_MULADD;
+    }
+    else
+    {
+           pAsm->D.dst.opcode = SQ_OP3_INST_MULADD;  
+    }
        pAsm->D.dst.op3     = 1; 
 
        tmp = (-1);
@@ -3778,7 +4370,14 @@ GLboolean assemble_LIT(r700_AssemblerBase *pAsm)
     swizzleagain_PVSSRC(&(pAsm->S[0].src), SQ_SEL_Y, SQ_SEL_Y, SQ_SEL_Y, SQ_SEL_Y);
 
     /* dst.z = log(src.y) */
-    pAsm->D.dst.opcode   = SQ_OP2_INST_LOG_CLAMPED;
+    if(8 == pAsm->unAsic)
+    {
+        pAsm->D.dst.opcode   = EG_OP2_INST_LOG_CLAMPED;
+    }
+    else
+    {
+        pAsm->D.dst.opcode   = SQ_OP2_INST_LOG_CLAMPED;
+    }
     pAsm->D.dst.math     = 1;
     pAsm->D.dst.rtype    = dstType;
     pAsm->D.dst.reg      = dstReg;
@@ -3809,7 +4408,14 @@ GLboolean assemble_LIT(r700_AssemblerBase *pAsm)
     swizzleagain_PVSSRC(&(pAsm->S[2].src), SQ_SEL_X, SQ_SEL_X, SQ_SEL_X, SQ_SEL_X);
 
     /* tmp.x = amd MUL_LIT(src.w, dst.z, src.x ) */
-    pAsm->D.dst.opcode   = SQ_OP3_INST_MUL_LIT;
+    if(8 == pAsm->unAsic)
+    {
+        pAsm->D.dst.opcode = EG_OP3_INST_MUL_LIT;
+    }
+    else
+    {
+        pAsm->D.dst.opcode = SQ_OP3_INST_MUL_LIT;
+    }
     pAsm->D.dst.math     = 1;
     pAsm->D.dst.op3      = 1;
     pAsm->D.dst.rtype    = DST_REG_TEMPORARY;
@@ -3842,7 +4448,14 @@ GLboolean assemble_LIT(r700_AssemblerBase *pAsm)
     }
 
     /* dst.z = exp(tmp.x) */
-    pAsm->D.dst.opcode   = SQ_OP2_INST_EXP_IEEE;
+    if(8 == pAsm->unAsic)
+    {
+        pAsm->D.dst.opcode   = EG_OP2_INST_EXP_IEEE;
+    }
+    else
+    {
+        pAsm->D.dst.opcode   = SQ_OP2_INST_EXP_IEEE;
+    }
     pAsm->D.dst.math     = 1;
     pAsm->D.dst.rtype    = dstType;
     pAsm->D.dst.reg      = dstReg;
@@ -3997,7 +4610,14 @@ GLboolean assemble_POW(r700_AssemblerBase *pAsm)
     tmp = gethelpr(pAsm);
 
     // LG2 tmp.x,     a.swizzle
-    pAsm->D.dst.opcode = SQ_OP2_INST_LOG_IEEE;  
+    if(8 == pAsm->unAsic)
+    {
+        pAsm->D.dst.opcode = EG_OP2_INST_LOG_IEEE;
+    }
+    else
+    {
+        pAsm->D.dst.opcode = SQ_OP2_INST_LOG_IEEE;  
+    }
     pAsm->D.dst.math = 1;
 
     setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
@@ -4041,7 +4661,14 @@ GLboolean assemble_POW(r700_AssemblerBase *pAsm)
 
     // EX2 dst.mask,          tmp.x
     // EX2 tmp.x,             tmp.x
-    pAsm->D.dst.opcode = SQ_OP2_INST_EXP_IEEE;
+    if(8 == pAsm->unAsic)
+    {
+        pAsm->D.dst.opcode = EG_OP2_INST_EXP_IEEE;
+    }
+    else
+    {
+        pAsm->D.dst.opcode = SQ_OP2_INST_EXP_IEEE;
+    }
     pAsm->D.dst.math = 1;
 
     setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
@@ -4085,11 +4712,21 @@ GLboolean assemble_POW(r700_AssemblerBase *pAsm)
  
 GLboolean assemble_RCP(r700_AssemblerBase *pAsm) 
 {
+    if(8 == pAsm->unAsic)
+    {
+        return assemble_math_function(pAsm, EG_OP2_INST_RECIP_IEEE);
+    }
+
     return assemble_math_function(pAsm, SQ_OP2_INST_RECIP_IEEE);
 }
  
 GLboolean assemble_RSQ(r700_AssemblerBase *pAsm) 
 {
+    if(8 == pAsm->unAsic)
+    {
+        return assemble_math_function(pAsm, EG_OP2_INST_RECIPSQRT_IEEE);
+    }
+
     return assemble_math_function(pAsm, SQ_OP2_INST_RECIPSQRT_IEEE);
 }
  
@@ -4175,7 +4812,14 @@ GLboolean assemble_SCS(r700_AssemblerBase *pAsm)
     }
 
     // COS dst.x,    a.x
-    pAsm->D.dst.opcode = SQ_OP2_INST_COS;
+    if(8 == pAsm->unAsic)
+    {
+        pAsm->D.dst.opcode = EG_OP2_INST_COS;
+    }
+    else
+    {
+        pAsm->D.dst.opcode = SQ_OP2_INST_COS;
+    }
     pAsm->D.dst.math = 1;
 
     assemble_dst(pAsm);
@@ -4194,7 +4838,14 @@ GLboolean assemble_SCS(r700_AssemblerBase *pAsm)
     }
 
     // SIN dst.y,    a.x
-    pAsm->D.dst.opcode = SQ_OP2_INST_SIN;
+    if(8 == pAsm->unAsic)
+    {
+        pAsm->D.dst.opcode = EG_OP2_INST_SIN;
+    }
+    else
+    {
+        pAsm->D.dst.opcode = SQ_OP2_INST_SIN;
+    }
     pAsm->D.dst.math = 1;
 
     assemble_dst(pAsm);
@@ -4349,6 +5000,65 @@ GLboolean assemble_SLT(r700_AssemblerBase *pAsm)
     return GL_TRUE;
 }
  
+GLboolean assemble_SSG(r700_AssemblerBase *pAsm)
+{
+    checkop1(pAsm);
+    
+    GLuint tmp = gethelpr(pAsm);
+    /* tmp = (src > 0 ? 1 : src) */
+    pAsm->D.dst.opcode = SQ_OP3_INST_CNDGT;
+    pAsm->D.dst.op3    = 1;
+    pAsm->D.dst.rtype = DST_REG_TEMPORARY;
+    pAsm->D.dst.reg   = tmp;
+
+    if( GL_FALSE == assemble_src(pAsm, 0, -1) )
+    {
+        return GL_FALSE;
+    }
+
+    setswizzle_PVSSRC(&(pAsm->S[1].src), SQ_SEL_1);
+
+    if( GL_FALSE == assemble_src(pAsm, 0, 2) )
+    {
+        return GL_FALSE;
+    }
+
+    if( GL_FALSE == next_ins(pAsm) )
+    {
+        return GL_FALSE;
+    }
+
+    /* dst = (-tmp > 0 ? -1 : tmp) */
+    pAsm->D.dst.opcode = SQ_OP3_INST_CNDGT;
+    pAsm->D.dst.op3    = 1;
+
+    if( GL_FALSE == assemble_dst(pAsm) )
+    {
+        return GL_FALSE;
+    }
+
+    setaddrmode_PVSSRC(&(pAsm->S[0].src), ADDR_ABSOLUTE);
+    pAsm->S[0].src.rtype = SRC_REG_TEMPORARY;
+    pAsm->S[0].src.reg   = tmp;
+    noswizzle_PVSSRC(&(pAsm->S[0].src));
+    neg_PVSSRC(&(pAsm->S[0].src));
+
+    setswizzle_PVSSRC(&(pAsm->S[1].src), SQ_SEL_1);
+    neg_PVSSRC(&(pAsm->S[1].src));
+
+    setaddrmode_PVSSRC(&(pAsm->S[2].src), ADDR_ABSOLUTE);
+    pAsm->S[2].src.rtype = SRC_REG_TEMPORARY;
+    pAsm->S[2].src.reg   = tmp;
+    noswizzle_PVSSRC(&(pAsm->S[2].src));
+
+    if( GL_FALSE == next_ins(pAsm) )
+    {
+        return GL_FALSE;
+    }
+
+    return GL_TRUE;
+}
+
 GLboolean assemble_STP(r700_AssemblerBase *pAsm) 
 {
     return GL_TRUE;
@@ -4387,7 +5097,14 @@ GLboolean assemble_TEX(r700_AssemblerBase *pAsm)
     if (pAsm->pILInst[pAsm->uiCurInst].Opcode == OPCODE_TXP)
     {
         GLuint tmp = gethelpr(pAsm);
-        pAsm->D.dst.opcode = SQ_OP2_INST_RECIP_IEEE;
+        if(8 == pAsm->unAsic)
+        {
+            pAsm->D.dst.opcode = EG_OP2_INST_RECIP_IEEE;
+        }
+        else
+        {
+            pAsm->D.dst.opcode = SQ_OP2_INST_RECIP_IEEE;
+        }
         pAsm->D.dst.math = 1;
         setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
         pAsm->D.dst.rtype = DST_REG_TEMPORARY;
@@ -4437,7 +5154,14 @@ GLboolean assemble_TEX(r700_AssemblerBase *pAsm)
         GLuint tmp2 = gethelpr(pAsm);
         
         /* tmp1.xyzw = CUBE(R0.zzxy, R0.yxzz) */
-        pAsm->D.dst.opcode = SQ_OP2_INST_CUBE;
+        if(8 == pAsm->unAsic)
+        {
+            pAsm->D.dst.opcode = EG_OP2_INST_CUBE;
+        }
+        else
+        {
+            pAsm->D.dst.opcode = SQ_OP2_INST_CUBE;
+        }
         setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
         pAsm->D.dst.rtype = DST_REG_TEMPORARY;
         pAsm->D.dst.reg   = tmp1;
@@ -4462,7 +5186,14 @@ GLboolean assemble_TEX(r700_AssemblerBase *pAsm)
         }
  
         /* tmp1.z = RCP_e(|tmp1.z|) */
-        pAsm->D.dst.opcode = SQ_OP2_INST_RECIP_IEEE;
+        if(8 == pAsm->unAsic)
+        {
+            pAsm->D.dst.opcode = EG_OP2_INST_RECIP_IEEE;
+        }
+        else
+        {
+            pAsm->D.dst.opcode = SQ_OP2_INST_RECIP_IEEE;
+        }
         pAsm->D.dst.math = 1;
         setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
         pAsm->D.dst.rtype = DST_REG_TEMPORARY;
@@ -4481,7 +5212,14 @@ GLboolean assemble_TEX(r700_AssemblerBase *pAsm)
          * MULADD R0.y,  R0.y,  PS1,  (0x3FC00000, 1.5f).x
          * muladd has no writemask, have to use another temp 
          */
-        pAsm->D.dst.opcode = SQ_OP3_INST_MULADD;
+        if(8 == pAsm->unAsic)
+        {
+            pAsm->D.dst.opcode = EG_OP3_INST_MULADD;
+        }
+        else
+        {
+            pAsm->D.dst.opcode = SQ_OP3_INST_MULADD;
+        }
         pAsm->D.dst.op3    = 1;
         setaddrmode_PVSDST(&(pAsm->D.dst), ADDR_ABSOLUTE);
         pAsm->D.dst.rtype = DST_REG_TEMPORARY;
@@ -4668,7 +5406,14 @@ GLboolean assemble_XPD(r700_AssemblerBase *pAsm)
         return GL_FALSE;
     }
 
-    pAsm->D.dst.opcode = SQ_OP3_INST_MULADD;
+    if(8 == pAsm->unAsic)
+    {
+        pAsm->D.dst.opcode = EG_OP3_INST_MULADD;
+    }
+    else
+    {
+        pAsm->D.dst.opcode = SQ_OP3_INST_MULADD;
+    }
     pAsm->D.dst.op3    = 1;
 
     if(0xF != pAsm->pILInst[pAsm->uiCurInst].DstReg.WriteMask)
@@ -4825,16 +5570,49 @@ GLboolean jumpToOffest(r700_AssemblerBase *pAsm, GLuint pops, GLint offset)
         return GL_FALSE;
     }
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = pops;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
+    if(8 == pAsm->unAsic)
+    {
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 EG_CF_INST_JUMP,
+                 EG_CF_WORD1__CF_INST_shift, EG_CF_WORD1__CF_INST_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 pops,
+                 EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__CF_CONST_shift, EG_CF_WORD1__CF_CONST_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 SQ_CF_COND_ACTIVE,
+                 EG_CF_WORD1__COND_shift, EG_CF_WORD1__COND_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__VPM_shift, EG_CF_WORD1__VPM_bit);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__EOP_shift, EG_CF_WORD1__EOP_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__WQM_shift, EG_CF_WORD1__WQM_bit);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+    }
+    else
+    {
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = pops;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_JUMP;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_JUMP;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+    }
 
     pAsm->cf_current_cf_clause_ptr->m_Word0.f.addr = pAsm->cf_current_cf_clause_ptr->m_uIndex + offset;
 
@@ -4848,17 +5626,50 @@ GLboolean pops(r700_AssemblerBase *pAsm, GLuint pops)
         return GL_FALSE;
     }
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = pops;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
+    if(8 == pAsm->unAsic)
+    {
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 EG_CF_INST_POP,
+                 EG_CF_WORD1__CF_INST_shift, EG_CF_WORD1__CF_INST_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 pops,
+                 EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__CF_CONST_shift, EG_CF_WORD1__CF_CONST_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 SQ_CF_COND_ACTIVE,
+                 EG_CF_WORD1__COND_shift, EG_CF_WORD1__COND_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__EOP_shift, EG_CF_WORD1__EOP_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__VPM_shift, EG_CF_WORD1__VPM_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__WQM_shift, EG_CF_WORD1__WQM_bit);                               
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+    }
+    else
+    {
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = pops;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_POP;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_POP;
  
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+    }
     pAsm->cf_current_cf_clause_ptr->m_Word0.f.addr             = pAsm->cf_current_cf_clause_ptr->m_uIndex + 1;
 
     return GL_TRUE;
@@ -4876,23 +5687,66 @@ GLboolean assemble_IF(r700_AssemblerBase *pAsm, GLboolean bHasElse)
         return GL_FALSE;
     }
 
-    if(GL_TRUE != bHasElse)
-    {
-        pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count = 1; 
+    if(8 == pAsm->unAsic)
+     { 
+        if(GL_TRUE != bHasElse)
+        {            
+            SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                     1,
+                     EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask);
+        }
+        else
+        {            
+            SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                     0,
+                     EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask);
+        }
+
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 EG_CF_INST_JUMP,
+                 EG_CF_WORD1__CF_INST_shift, EG_CF_WORD1__CF_INST_mask);         
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__CF_CONST_shift, EG_CF_WORD1__CF_CONST_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 SQ_CF_COND_ACTIVE,
+                 EG_CF_WORD1__COND_shift, EG_CF_WORD1__COND_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__EOP_shift, EG_CF_WORD1__EOP_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__VPM_shift, EG_CF_WORD1__VPM_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__WQM_shift, EG_CF_WORD1__WQM_bit);                               
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
     }
     else
     {
-        pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count = 0;
-    }
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
+        if(GL_TRUE != bHasElse)
+        {
+            pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count = 1; 
+        }
+        else
+        {
+            pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count = 0;
+        }
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_JUMP;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_JUMP;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+    }
 
     pAsm->FCSP++;
        pAsm->fc_stack[pAsm->FCSP].type  = FC_IF;
@@ -4919,16 +5773,49 @@ GLboolean assemble_ELSE(r700_AssemblerBase *pAsm)
         return GL_FALSE;
     }
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 1; ///
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
+    if(8 == pAsm->unAsic)
+    {                  
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask);        
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 EG_CF_INST_ELSE,
+                 EG_CF_WORD1__CF_INST_shift, EG_CF_WORD1__CF_INST_mask);         
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__CF_CONST_shift, EG_CF_WORD1__CF_CONST_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 SQ_CF_COND_ACTIVE,
+                 EG_CF_WORD1__COND_shift, EG_CF_WORD1__COND_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__EOP_shift, EG_CF_WORD1__EOP_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__VPM_shift, EG_CF_WORD1__VPM_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__WQM_shift, EG_CF_WORD1__WQM_bit);                               
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+    }
+    else
+    {
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 1; ///
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_ELSE;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_ELSE;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+    }
 
     pAsm->fc_stack[pAsm->FCSP].mid = (R700ControlFlowGenericClause **)_mesa_realloc( (void *)pAsm->fc_stack[pAsm->FCSP].mid,
                                                                                      0,
@@ -4988,17 +5875,49 @@ GLboolean assemble_BGNLOOP(r700_AssemblerBase *pAsm)
         return GL_FALSE;
     }
 
-    
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
+    if(8 == pAsm->unAsic)
+    {                  
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask);        
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 EG_CF_INST_LOOP_START_NO_AL,
+                 EG_CF_WORD1__CF_INST_shift, EG_CF_WORD1__CF_INST_mask);         
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__CF_CONST_shift, EG_CF_WORD1__CF_CONST_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 SQ_CF_COND_ACTIVE,
+                 EG_CF_WORD1__COND_shift, EG_CF_WORD1__COND_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__EOP_shift, EG_CF_WORD1__EOP_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__VPM_shift, EG_CF_WORD1__VPM_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__WQM_shift, EG_CF_WORD1__WQM_bit);                               
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+    }
+    else
+    {
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_LOOP_START_NO_AL;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_LOOP_START_NO_AL;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+    }
 
     pAsm->FCSP++;
        pAsm->fc_stack[pAsm->FCSP].type  = FC_LOOP;
@@ -5039,18 +5958,50 @@ GLboolean assemble_BRK(r700_AssemblerBase *pAsm)
         return GL_FALSE;
     }
 
-    
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 1;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
+    if(8 == pAsm->unAsic)
+    {                  
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask);        
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 EG_CF_INST_LOOP_BREAK,
+                 EG_CF_WORD1__CF_INST_shift, EG_CF_WORD1__CF_INST_mask);         
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__CF_CONST_shift, EG_CF_WORD1__CF_CONST_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 SQ_CF_COND_ACTIVE,
+                 EG_CF_WORD1__COND_shift, EG_CF_WORD1__COND_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__EOP_shift, EG_CF_WORD1__EOP_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__VPM_shift, EG_CF_WORD1__VPM_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__WQM_shift, EG_CF_WORD1__WQM_bit);                               
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+    }
+    else
+    {
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_LOOP_BREAK;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_LOOP_BREAK;
  
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+    }
 
     pAsm->fc_stack[unFCSP].mid = (R700ControlFlowGenericClause **)_mesa_realloc( 
                                               (void *)pAsm->fc_stack[unFCSP].mid,
@@ -5064,18 +6015,52 @@ GLboolean assemble_BRK(r700_AssemblerBase *pAsm)
         return GL_FALSE;
     }
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 1;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
+    if(8 == pAsm->unAsic)
+    {                  
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask);        
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 EG_CF_INST_POP,
+                 EG_CF_WORD1__CF_INST_shift, EG_CF_WORD1__CF_INST_mask);         
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__CF_CONST_shift, EG_CF_WORD1__CF_CONST_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 SQ_CF_COND_ACTIVE,
+                 EG_CF_WORD1__COND_shift, EG_CF_WORD1__COND_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__EOP_shift, EG_CF_WORD1__EOP_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__VPM_shift, EG_CF_WORD1__VPM_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__WQM_shift, EG_CF_WORD1__WQM_bit);                               
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+    }
+    else
+    {
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_POP;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_POP;
  
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
-    pAsm->cf_current_cf_clause_ptr->m_Word0.f.addr             = pAsm->cf_current_cf_clause_ptr->m_uIndex + 1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+    }
+
+    pAsm->cf_current_cf_clause_ptr->m_Word0.f.addr = pAsm->cf_current_cf_clause_ptr->m_uIndex + 1;
 
     checkStackDepth(pAsm, FC_PUSH_VPM, GL_TRUE);
 
@@ -5109,18 +6094,50 @@ GLboolean assemble_CONT(r700_AssemblerBase *pAsm)
         return GL_FALSE;
     }
 
-    
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 1;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
+    if(8 == pAsm->unAsic)
+    {                  
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask);        
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 EG_CF_INST_LOOP_CONTINUE,
+                 EG_CF_WORD1__CF_INST_shift, EG_CF_WORD1__CF_INST_mask);         
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__CF_CONST_shift, EG_CF_WORD1__CF_CONST_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 SQ_CF_COND_ACTIVE,
+                 EG_CF_WORD1__COND_shift, EG_CF_WORD1__COND_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__EOP_shift, EG_CF_WORD1__EOP_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__VPM_shift, EG_CF_WORD1__VPM_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__WQM_shift, EG_CF_WORD1__WQM_bit);                               
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+    }
+    else
+    {
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_LOOP_CONTINUE;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_LOOP_CONTINUE;
  
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+    }
 
     pAsm->fc_stack[unFCSP].mid = (R700ControlFlowGenericClause **)_mesa_realloc( 
                                               (void *)pAsm->fc_stack[unFCSP].mid,
@@ -5134,17 +6151,51 @@ GLboolean assemble_CONT(r700_AssemblerBase *pAsm)
         return GL_FALSE;
     }
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 1;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
+    if(8 == pAsm->unAsic)
+    {                  
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask);        
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 EG_CF_INST_POP,
+                 EG_CF_WORD1__CF_INST_shift, EG_CF_WORD1__CF_INST_mask);         
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__CF_CONST_shift, EG_CF_WORD1__CF_CONST_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 SQ_CF_COND_ACTIVE,
+                 EG_CF_WORD1__COND_shift, EG_CF_WORD1__COND_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__EOP_shift, EG_CF_WORD1__EOP_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__VPM_shift, EG_CF_WORD1__VPM_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__WQM_shift, EG_CF_WORD1__WQM_bit);                               
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+    }
+    else
+    {
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_POP;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_POP;
  
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+    }
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
     pAsm->cf_current_cf_clause_ptr->m_Word0.f.addr             = pAsm->cf_current_cf_clause_ptr->m_uIndex + 1;
 
     checkStackDepth(pAsm, FC_PUSH_VPM, GL_TRUE);
@@ -5163,17 +6214,49 @@ GLboolean assemble_ENDLOOP(r700_AssemblerBase *pAsm)
         return GL_FALSE;
     }
 
-    
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
+    if(8 == pAsm->unAsic)
+    {                  
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask);        
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 EG_CF_INST_LOOP_END,
+                 EG_CF_WORD1__CF_INST_shift, EG_CF_WORD1__CF_INST_mask);         
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__CF_CONST_shift, EG_CF_WORD1__CF_CONST_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 SQ_CF_COND_ACTIVE,
+                 EG_CF_WORD1__COND_shift, EG_CF_WORD1__COND_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__EOP_shift, EG_CF_WORD1__EOP_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__VPM_shift, EG_CF_WORD1__VPM_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__WQM_shift, EG_CF_WORD1__WQM_bit);                               
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+    }
+    else
+    {
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_LOOP_END;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_LOOP_END;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+    }
 
     pAsm->cf_current_cf_clause_ptr->m_Word0.f.addr   = pAsm->fc_stack[pAsm->FCSP].first->m_uIndex + 1;
     pAsm->fc_stack[pAsm->FCSP].first->m_Word0.f.addr = pAsm->cf_current_cf_clause_ptr->m_uIndex + 1;
@@ -5235,17 +6318,51 @@ void add_return_inst(r700_AssemblerBase *pAsm)
     {
         return;
     }
-    //pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 1;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_RETURN;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+    if(8 == pAsm->unAsic)
+    {                  
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask);        
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 EG_CF_INST_RETURN,
+                 EG_CF_WORD1__CF_INST_shift, EG_CF_WORD1__CF_INST_mask);         
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__CF_CONST_shift, EG_CF_WORD1__CF_CONST_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 SQ_CF_COND_ACTIVE,
+                 EG_CF_WORD1__COND_shift, EG_CF_WORD1__COND_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__EOP_shift, EG_CF_WORD1__EOP_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__VPM_shift, EG_CF_WORD1__VPM_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__WQM_shift, EG_CF_WORD1__WQM_bit);                               
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+    }
+    else
+    {
+        //pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
+
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_RETURN;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+    }
 }
 
 GLboolean assemble_BGNSUB(r700_AssemblerBase *pAsm, GLint nILindex, GLuint uiIL_Shift)
@@ -5368,17 +6485,50 @@ GLboolean assemble_CAL(r700_AssemblerBase *pAsm,
         return GL_FALSE;
     }
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.call_count       = 1;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
+    if(8 == pAsm->unAsic)
+    {                  
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask);        
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 EG_CF_INST_CALL,
+                 EG_CF_WORD1__CF_INST_shift, EG_CF_WORD1__CF_INST_mask);         
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__CF_CONST_shift, EG_CF_WORD1__CF_CONST_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 SQ_CF_COND_ACTIVE,
+                 EG_CF_WORD1__COND_shift, EG_CF_WORD1__COND_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__EOP_shift, EG_CF_WORD1__EOP_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__VPM_shift, EG_CF_WORD1__VPM_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__WQM_shift, EG_CF_WORD1__WQM_bit);                               
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+    }
+    else
+    {
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.call_count       = 1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_CALL;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_CALL;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+    }
 
     /* Put in caller */
     if( (pAsm->unCallerArrayPointer + 1) > pAsm->unCallerArraySize )
@@ -5579,16 +6729,49 @@ GLboolean breakLoopOnFlag(r700_AssemblerBase *pAsm, GLuint unFCSP)
         return GL_FALSE;
     }
     
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 1;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
+    if(8 == pAsm->unAsic)
+    {                  
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__POP_COUNT_shift, EG_CF_WORD1__POP_COUNT_mask);        
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 EG_CF_INST_LOOP_BREAK,
+                 EG_CF_WORD1__CF_INST_shift, EG_CF_WORD1__CF_INST_mask);         
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__CF_CONST_shift, EG_CF_WORD1__CF_CONST_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 SQ_CF_COND_ACTIVE,
+                 EG_CF_WORD1__COND_shift, EG_CF_WORD1__COND_mask);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__EOP_shift, EG_CF_WORD1__EOP_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__VPM_shift, EG_CF_WORD1__VPM_bit); 
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_WORD1__WQM_shift, EG_CF_WORD1__WQM_bit);                               
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__BARRIER_shift, EG_CF_WORD1__BARRIER_bit);
+        SETfield(pAsm->cf_current_cf_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_WORD1__COUNT_shift, EG_CF_WORD1__COUNT_mask);
+    }
+    else
+    {
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.pop_count        = 1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_const         = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cond             = SQ_CF_COND_ACTIVE;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_LOOP_BREAK;
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0; 
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_LOOP_BREAK;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
 
-    pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+        pAsm->cf_current_cf_clause_ptr->m_Word1.f.barrier          = 0x1;
+    }
 
     pAsm->fc_stack[unFCSP].mid = (R700ControlFlowGenericClause **)_mesa_realloc( 
                                               (void *)pAsm->fc_stack[unFCSP].mid,
@@ -5677,10 +6860,19 @@ GLboolean AssembleInstr(GLuint uiFirstInst,
                 return GL_FALSE;
             break;  
         case OPCODE_COS: 
-            if ( GL_FALSE == assemble_TRIG(pR700AsmCode, SQ_OP2_INST_COS) ) 
-                return GL_FALSE;
+            if(8 == pR700AsmCode->unAsic)
+            {
+                if ( GL_FALSE == assemble_TRIG(pR700AsmCode, EG_OP2_INST_COS) ) 
+                    return GL_FALSE;
+            }
+            else
+            {
+                if ( GL_FALSE == assemble_TRIG(pR700AsmCode, SQ_OP2_INST_COS) ) 
+                    return GL_FALSE;
+            }
             break;  
 
+        case OPCODE_DP2:
         case OPCODE_DP3: 
         case OPCODE_DP4: 
         case OPCODE_DPH: 
@@ -5794,8 +6986,16 @@ GLboolean AssembleInstr(GLuint uiFirstInst,
                 return GL_FALSE;
             break;  
         case OPCODE_SIN: 
-            if ( GL_FALSE == assemble_TRIG(pR700AsmCode, SQ_OP2_INST_SIN) ) 
-                return GL_FALSE;
+            if(8 == pR700AsmCode->unAsic)
+            {
+                if ( GL_FALSE == assemble_TRIG(pR700AsmCode, EG_OP2_INST_SIN) ) 
+                    return GL_FALSE;
+            }
+            else
+            {
+                if ( GL_FALSE == assemble_TRIG(pR700AsmCode, SQ_OP2_INST_SIN) ) 
+                    return GL_FALSE;
+            }
             break;  
         case OPCODE_SCS: 
             if ( GL_FALSE == assemble_SCS(pR700AsmCode) ) 
@@ -5872,6 +7072,13 @@ GLboolean AssembleInstr(GLuint uiFirstInst,
         //        return GL_FALSE;
         //    break;
 
+        case OPCODE_SSG:
+            if ( GL_FALSE == assemble_SSG(pR700AsmCode) )
+            {
+                return GL_FALSE;
+            }
+            break;
+
         case OPCODE_SWZ: 
             if ( GL_FALSE == assemble_MOV(pR700AsmCode) ) 
             {
@@ -6006,7 +7213,7 @@ GLboolean AssembleInstr(GLuint uiFirstInst,
             return GL_TRUE;
 
         default:
-            radeon_error("internal: unknown instruction\n");
+            radeon_error("r600: unknown instruction %d\n", pILInst[i].Opcode);
             return GL_FALSE;
         }
     }
@@ -6016,7 +7223,15 @@ GLboolean AssembleInstr(GLuint uiFirstInst,
 
 GLboolean InitShaderProgram(r700_AssemblerBase * pAsm)
 {
+#ifndef GENERATE_SHADER_FOR_2D
     setRetInLoopFlag(pAsm, SQ_SEL_0);
+#endif
+
+    if((SPT_FP == pAsm->currentShaderType) && (8 == pAsm->unAsic))
+    {
+        EG_add_ps_interp(pAsm);
+    }
+
     pAsm->alu_x_opcode = SQ_CF_INST_ALU;
     return GL_TRUE;
 }
@@ -6039,6 +7254,7 @@ GLboolean RelocProgram(r700_AssemblerBase * pAsm, struct gl_program * pILProg)
 
     plstCFmain = pAsm->CALLSTACK[0].plstCFInstructions_local;
 
+#ifndef GENERATE_SHADER_FOR_2D
     /* remove flags init if they are not used */
     if((pAsm->unCFflags & HAS_LOOPRET) == 0)
     {
@@ -6069,6 +7285,7 @@ GLboolean RelocProgram(r700_AssemblerBase * pAsm, struct gl_program * pILProg)
             pInst = pInst->pNextInst;
         };
     }
+#endif /* GENERATE_SHADER_FOR_2D */
 
     if(pAsm->CALLSTACK[0].max > 0)
     {
@@ -6175,13 +7392,20 @@ GLboolean RelocProgram(r700_AssemblerBase * pAsm, struct gl_program * pILProg)
                         }
                         else
                         {
-                            if(pAsm->bR6xx)
+                            if(8 == pAsm->unAsic)
                             {
-                                uNumSrc = r700GetNumOperands(pALU->m_Word1_OP2.f6.alu_inst, 0);
+                                 uNumSrc = EG_GetNumOperands(pALU->m_Word1_OP2.f.alu_inst, 0);
                             }
                             else
                             {
-                                uNumSrc = r700GetNumOperands(pALU->m_Word1_OP2.f.alu_inst, 0);
+                                if(pAsm->bR6xx)
+                                {
+                                    uNumSrc = r700GetNumOperands(pALU->m_Word1_OP2.f6.alu_inst, 0);
+                                }
+                                else
+                                {
+                                    uNumSrc = r700GetNumOperands(pALU->m_Word1_OP2.f.alu_inst, 0);
+                                }
                             }
                             if(2 == uNumSrc)
                             {   /* 2 srcs */
@@ -6472,12 +7696,42 @@ GLboolean Process_Export(r700_AssemblerBase* pAsm,
     pAsm->cf_current_export_clause_ptr->m_Word0.f.index_gpr   = 0x0;
     pAsm->cf_current_export_clause_ptr->m_Word0.f.elem_size   = 0x3; 
 
-    pAsm->cf_current_export_clause_ptr->m_Word1.f.burst_count      = (export_count - 1);
-    pAsm->cf_current_export_clause_ptr->m_Word1.f.end_of_program   = 0x0;
-    pAsm->cf_current_export_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
-    pAsm->cf_current_export_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_EXPORT;  // _DONE
-    pAsm->cf_current_export_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
-    pAsm->cf_current_export_clause_ptr->m_Word1.f.barrier          = 0x1;
+    if(8 == pAsm->unAsic)
+    {
+        SETfield(pAsm->cf_current_export_clause_ptr->m_Word1.val, 
+                 (export_count - 1),
+                 EG_CF_ALLOC_EXPORT_WORD1__BURST_COUNT_shift,
+                 EG_CF_ALLOC_EXPORT_WORD1__BURST_COUNT_mask);
+        SETfield(pAsm->cf_current_export_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_ALLOC_EXPORT_WORD1__EOP_shift,
+                 EG_CF_ALLOC_EXPORT_WORD1__EOP_bit);
+        SETfield(pAsm->cf_current_export_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_ALLOC_EXPORT_WORD1__VPM_shift,
+                 EG_CF_ALLOC_EXPORT_WORD1__VPM_bit);
+        SETfield(pAsm->cf_current_export_clause_ptr->m_Word1.val, 
+                 EG_CF_INST_EXPORT,
+                 EG_CF_WORD1__CF_INST_shift, 
+                 EG_CF_WORD1__CF_INST_mask);
+        SETfield(pAsm->cf_current_export_clause_ptr->m_Word1.val, 
+                 0,
+                 EG_CF_ALLOC_EXPORT_WORD1__MARK_shift,
+                 EG_CF_ALLOC_EXPORT_WORD1__MARK_bit);
+        SETfield(pAsm->cf_current_export_clause_ptr->m_Word1.val, 
+                 1,
+                 EG_CF_ALLOC_EXPORT_WORD1__BARRIER_shift,
+                 EG_CF_ALLOC_EXPORT_WORD1__BARRIER_bit);
+    }
+    else
+    {
+        pAsm->cf_current_export_clause_ptr->m_Word1.f.burst_count      = (export_count - 1);
+        pAsm->cf_current_export_clause_ptr->m_Word1.f.end_of_program   = 0x0;
+        pAsm->cf_current_export_clause_ptr->m_Word1.f.valid_pixel_mode = 0x0;
+        pAsm->cf_current_export_clause_ptr->m_Word1.f.cf_inst          = SQ_CF_INST_EXPORT;  // _DONE
+        pAsm->cf_current_export_clause_ptr->m_Word1.f.whole_quad_mode  = 0x0;
+        pAsm->cf_current_export_clause_ptr->m_Word1.f.barrier          = 0x1;
+    }
 
     if (export_count == 1) 
     {
@@ -6605,8 +7859,22 @@ GLboolean Process_Fragment_Exports(r700_AssemblerBase *pR700AsmCode,
     
     if(pR700AsmCode->cf_last_export_ptr != NULL) 
     {
-        pR700AsmCode->cf_last_export_ptr->m_Word1.f.cf_inst        = SQ_CF_INST_EXPORT_DONE;
-        pR700AsmCode->cf_last_export_ptr->m_Word1.f.end_of_program = 0x1;
+        if(8 == pR700AsmCode->unAsic)
+        {            
+            SETfield(pR700AsmCode->cf_last_export_ptr->m_Word1.val, 
+                     1,
+                     EG_CF_ALLOC_EXPORT_WORD1__EOP_shift,
+                     EG_CF_ALLOC_EXPORT_WORD1__EOP_bit);            
+            SETfield(pR700AsmCode->cf_last_export_ptr->m_Word1.val, 
+                     EG_CF_INST_EXPORT_DONE,
+                     EG_CF_WORD1__CF_INST_shift, 
+                     EG_CF_WORD1__CF_INST_mask);
+        }
+        else
+        {
+            pR700AsmCode->cf_last_export_ptr->m_Word1.f.cf_inst        = SQ_CF_INST_EXPORT_DONE;
+            pR700AsmCode->cf_last_export_ptr->m_Word1.f.end_of_program = 0x1;
+        }
     }
 
     return GL_TRUE;
@@ -6652,7 +7920,17 @@ GLboolean Process_Vertex_Exports(r700_AssemblerBase *pR700AsmCode,
         export_count--;
     }
 
-    pR700AsmCode->cf_last_export_ptr->m_Word1.f.cf_inst = SQ_CF_INST_EXPORT_DONE;
+    if(8 == pR700AsmCode->unAsic)
+    {                                   
+        SETfield(pR700AsmCode->cf_last_export_ptr->m_Word1.val, 
+                 EG_CF_INST_EXPORT_DONE,
+                 EG_CF_WORD1__CF_INST_shift, 
+                 EG_CF_WORD1__CF_INST_mask);
+    }
+    else
+    {
+        pR700AsmCode->cf_last_export_ptr->m_Word1.f.cf_inst = SQ_CF_INST_EXPORT_DONE;
+    }
 
 
     pR700AsmCode->number_of_exports = export_count;
@@ -6747,7 +8025,17 @@ GLboolean Process_Vertex_Exports(r700_AssemblerBase *pR700AsmCode,
     // At least one param should be exported
     if (export_count) 
     {
-        pR700AsmCode->cf_last_export_ptr->m_Word1.f.cf_inst = SQ_CF_INST_EXPORT_DONE;    
+        if(8 == pR700AsmCode->unAsic)
+        {                                   
+            SETfield(pR700AsmCode->cf_last_export_ptr->m_Word1.val, 
+                     EG_CF_INST_EXPORT_DONE,
+                     EG_CF_WORD1__CF_INST_shift, 
+                     EG_CF_WORD1__CF_INST_mask);
+        }
+        else
+        {
+            pR700AsmCode->cf_last_export_ptr->m_Word1.f.cf_inst = SQ_CF_INST_EXPORT_DONE;    
+        }
     }
     else
     {
@@ -6765,7 +8053,17 @@ GLboolean Process_Vertex_Exports(r700_AssemblerBase *pR700AsmCode,
         pR700AsmCode->cf_last_export_ptr->m_Word1_SWIZ.f.sel_y = SQ_SEL_0;
         pR700AsmCode->cf_last_export_ptr->m_Word1_SWIZ.f.sel_z = SQ_SEL_0;
         pR700AsmCode->cf_last_export_ptr->m_Word1_SWIZ.f.sel_w = SQ_SEL_1;
-        pR700AsmCode->cf_last_export_ptr->m_Word1.f.cf_inst = SQ_CF_INST_EXPORT_DONE;
+        if(8 == pR700AsmCode->unAsic)
+        {                                   
+            SETfield(pR700AsmCode->cf_last_export_ptr->m_Word1.val, 
+                     EG_CF_INST_EXPORT_DONE,
+                     EG_CF_WORD1__CF_INST_shift, 
+                     EG_CF_WORD1__CF_INST_mask);
+        }
+        else
+        {
+            pR700AsmCode->cf_last_export_ptr->m_Word1.f.cf_inst = SQ_CF_INST_EXPORT_DONE;
+        }
     }
 
     pR700AsmCode->cf_last_export_ptr->m_Word1.f.end_of_program = 0x1;
index dbc6cdb1903ea5ab7333d6c9508dd6f1cc558d33..d357b0e3ec01990f6c575437ad6484b563ab1cf1 100644 (file)
@@ -108,7 +108,7 @@ typedef enum AddressMode
 typedef enum SrcRegisterType 
 {
     SRC_REG_TEMPORARY      = 0,
-    SRC_REG_INPUT          = 1,
+    SRC_REG_GPR            = 1,
     SRC_REG_CONSTANT       = 2,
     SRC_REG_ALT_TEMPORARY  = 3,
     SRC_REC_LITERAL        = 4, 
@@ -464,6 +464,10 @@ typedef struct r700_AssemblerBase
     GLuint             uiCurInst;
     GLubyte SamplerUnits[MAX_SAMPLERS];
     GLboolean   bR6xx;
+
+    /* TODO : merge bR6xx */
+    GLuint  unAsic;
+
     /* helper to decide which type of instruction to assemble */
     GLboolean is_tex;
     /* we inserted helper intructions and need barrier on next TEX ins */ 
@@ -489,6 +493,9 @@ typedef struct r700_AssemblerBase
 
     GLuint    shadow_regs[R700_MAX_TEXTURE_UNITS];
 
+    GLboolean bUseMemConstant;
+    GLuint    kcacheUsed;        
+
 } r700_AssemblerBase;
 
 //Internal use
@@ -512,6 +519,8 @@ GLuint GetSurfaceFormat(GLenum eType, GLuint nChannels, GLuint * pClient_size);
 
 unsigned int r700GetNumOperands(GLuint opcode, GLuint nIsOp3);
 
+unsigned int EG_GetNumOperands(GLuint opcode, GLuint nIsOp3);
+
 GLboolean IsTex(gl_inst_opcode Opcode);
 GLboolean IsAlu(gl_inst_opcode Opcode);
 int check_current_clause(r700_AssemblerBase* pAsm,
@@ -535,6 +544,18 @@ GLboolean assemble_vfetch_instruction2(r700_AssemblerBase* pAsm,
                                        GLboolean           normalize,
                                        GLenum              format,
                                        VTX_FETCH_METHOD  * pFetchMethod);
+
+GLboolean EG_assemble_vfetch_instruction(r700_AssemblerBase* pAsm,
+                                       GLuint              destination_register,                                                                      
+                                       GLenum              type,
+                                       GLint               size,
+                                       GLubyte             element,
+                                       GLuint              _signed,
+                                       GLboolean           normalize,
+                                       GLenum              format,
+                                       VTX_FETCH_METHOD  * pFetchMethod);
+//-----------------------
+
 GLboolean cleanup_vfetch_instructions(r700_AssemblerBase* pAsm);
 GLuint gethelpr(r700_AssemblerBase* pAsm);
 void resethelpr(r700_AssemblerBase* pAsm);
@@ -553,8 +574,10 @@ GLboolean assemble_tex_instruction(r700_AssemblerBase *pAsm, GLboolean normalize
 void initialize(r700_AssemblerBase *pAsm);
 GLboolean assemble_alu_src(R700ALUInstruction*  alu_instruction_ptr,
                            int                  source_index,
-                           PVSSRC*              pSource,
-                           BITS                 scalar_channel_index);
+                           PVSSRC*              pSource,                           
+                           BITS                 scalar_channel_index,
+                           r700_AssemblerBase  *pAsm);
+
 GLboolean add_alu_instruction(r700_AssemblerBase* pAsm,
                               R700ALUInstruction* alu_instruction_ptr,
                               GLuint              contiguous_slots_needed);
@@ -625,6 +648,7 @@ GLboolean assemble_LOGIC_PRED(r700_AssemblerBase *pAsm, BITS opcode);
 GLboolean assemble_TRIG(r700_AssemblerBase *pAsm, BITS opcode);
 
 GLboolean assemble_SLT(r700_AssemblerBase *pAsm);
+GLboolean assemble_SSG(r700_AssemblerBase *pAsm);
 GLboolean assemble_STP(r700_AssemblerBase *pAsm);
 GLboolean assemble_TEX(r700_AssemblerBase *pAsm);
 GLboolean assemble_XPD(r700_AssemblerBase *pAsm);
@@ -663,6 +687,7 @@ GLboolean callPreSub(r700_AssemblerBase* pAsm,
                      COMPILED_SUB * pCompiledSub,                                            
                      GLshort uOutReg,
                      GLshort uNumValidSrc);
+GLboolean EG_add_ps_interp(r700_AssemblerBase* pAsm);
 
 //Interface
 GLboolean AssembleInstr(GLuint uiFirstInst,
index bf8063391a28b9444b63f96dbb7ffa6cd37f47bb..71f1af7562632a1e3d3acdf9aa76606034fa18ea 100644 (file)
@@ -173,7 +173,6 @@ static void r700SetupVTXConstants(GLcontext  * ctx,
 {
     context_t *context = R700_CONTEXT(ctx);
     struct radeon_aos * paos = (struct radeon_aos *)pAos;
-    unsigned int nVBsize;
     BATCH_LOCALS(&context->radeon);
 
     unsigned int uSQ_VTX_CONSTANT_WORD0_0;
@@ -194,18 +193,8 @@ static void r700SetupVTXConstants(GLcontext  * ctx,
     else
            r700SyncSurf(context, paos->bo, RADEON_GEM_DOMAIN_GTT, 0, VC_ACTION_ENA_bit);
 
-    if(0 == pStreamDesc->stride)
-    {
-        nVBsize = paos->count * pStreamDesc->size * getTypeSize(pStreamDesc->type);
-    }
-    else
-    {
-        nVBsize = (paos->count - 1) * pStreamDesc->stride
-                  + pStreamDesc->size * getTypeSize(pStreamDesc->type);
-    }
-
     uSQ_VTX_CONSTANT_WORD0_0 = paos->offset;
-    uSQ_VTX_CONSTANT_WORD1_0 = nVBsize - 1;
+    uSQ_VTX_CONSTANT_WORD1_0 = paos->bo->size - paos->offset - 1;
 
     SETfield(uSQ_VTX_CONSTANT_WORD2_0, 0, BASE_ADDRESS_HI_shift, BASE_ADDRESS_HI_mask); /* TODO */
     SETfield(uSQ_VTX_CONSTANT_WORD2_0, pStreamDesc->stride, SQ_VTX_CONSTANT_WORD2_0__STRIDE_shift,
@@ -721,6 +710,7 @@ static void r700SendPSState(GLcontext *ctx, struct radeon_state_atom *atom)
     context_t *context = R700_CONTEXT(ctx);
     R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
     struct radeon_bo * pbo;
+    struct radeon_bo * pbo_const;
     BATCH_LOCALS(&context->radeon);
     radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
 
@@ -750,6 +740,9 @@ static void r700SendPSState(GLcontext *ctx, struct radeon_state_atom *atom)
     R600_OUT_BATCH_REGVAL(SQ_LOOP_CONST_0, 0x01000FFF);
     END_BATCH();
 
+    pbo_const = (struct radeon_bo *)r700GetActiveFpShaderConstBo(GL_CONTEXT(context));
+    //TODO : set up shader const
+
     COMMIT_BATCH();
 
 }
@@ -759,13 +752,14 @@ static void r700SendVSState(GLcontext *ctx, struct radeon_state_atom *atom)
     context_t *context = R700_CONTEXT(ctx);
     R700_CHIP_CONTEXT *r700 = R700_CONTEXT_STATES(context);
     struct radeon_bo * pbo;
+    struct radeon_bo * pbo_const;
     BATCH_LOCALS(&context->radeon);
     radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s\n", __func__);
 
     pbo = (struct radeon_bo *)r700GetActiveVpShaderBo(GL_CONTEXT(context));
 
     if (!pbo)
-           return;
+        return;
 
     r700SyncSurf(context, pbo, RADEON_GEM_DOMAIN_GTT, 0, SH_ACTION_ENA_bit);
 
@@ -788,6 +782,29 @@ static void r700SendVSState(GLcontext *ctx, struct radeon_state_atom *atom)
     //R600_OUT_BATCH_REGVAL((SQ_LOOP_CONST_0 + (SQ_LOOP_CONST_vs<2)), 0x0100000F);
     END_BATCH();
 
+    /* TODO : handle 4 bufs */
+    if(GL_TRUE == r700->bShaderUseMemConstant)
+    {
+           pbo_const = (struct radeon_bo *)r700GetActiveVpShaderConstBo(GL_CONTEXT(context));
+        if(NULL != pbo_const)
+        {
+            r700SyncSurf(context, pbo_const, RADEON_GEM_DOMAIN_GTT, 0, SH_ACTION_ENA_bit); /* TODO : Check kc bit. */
+
+            BEGIN_BATCH_NO_AUTOSTATE(3);            
+            R600_OUT_BATCH_REGVAL(SQ_ALU_CONST_BUFFER_SIZE_VS_0, (r700->vs.num_consts * 4)/16 );    
+            END_BATCH();
+
+            BEGIN_BATCH_NO_AUTOSTATE(3 + 2);            
+            R600_OUT_BATCH_REGSEQ(SQ_ALU_CONST_CACHE_VS_0, 1);
+            R600_OUT_BATCH(r700->vs.SQ_ALU_CONST_CACHE_VS_0.u32All);
+            R600_OUT_BATCH_RELOC(r700->vs.SQ_ALU_CONST_CACHE_VS_0.u32All,
+                         pbo_const,
+                         r700->vs.SQ_ALU_CONST_CACHE_VS_0.u32All,
+                         RADEON_GEM_DOMAIN_GTT, 0, 0);
+            END_BATCH();
+        }
+    }
+    
     COMMIT_BATCH();
 }
 
@@ -1558,45 +1575,55 @@ static void r600_init_query_stateobj(radeonContextPtr radeon, int SZ)
 
 void r600InitAtoms(context_t *context)
 {
-       radeon_print(RADEON_STATE, RADEON_NORMAL, "%s %p\n", __func__, context);
-       context->radeon.hw.max_state_size = 10 + 5 + 14; /* start 3d, idle, cb/db flush */
-
-       /* Setup the atom linked list */
-       make_empty_list(&context->radeon.hw.atomlist);
-       context->radeon.hw.atomlist.name = "atom-list";
-
-       ALLOC_STATE(sq, always, 34, r700SendSQConfig);
-       ALLOC_STATE(db, always, 17, r700SendDBState);
-       ALLOC_STATE(stencil, always, 4, r700SendStencilState);
-       ALLOC_STATE(db_target, always, 16, r700SendDepthTargetState);
-       ALLOC_STATE(sc, always, 15, r700SendSCState);
-       ALLOC_STATE(scissor, always, 22, r700SendScissorState);
-       ALLOC_STATE(aa, always, 12, r700SendAAState);
-       ALLOC_STATE(cl, always, 12, r700SendCLState);
-       ALLOC_STATE(gb, always, 6, r700SendGBState);
-       ALLOC_STATE(ucp, ucp, (R700_MAX_UCP * 6), r700SendUCPState);
-       ALLOC_STATE(su, always, 9, r700SendSUState);
-       ALLOC_STATE(poly, always, 10, r700SendPolyState);
-       ALLOC_STATE(cb, cb, 18, r700SendCBState);
-       ALLOC_STATE(clrcmp, always, 6, r700SendCBCLRCMPState);
-       ALLOC_STATE(cb_target, always, 31, r700SendRenderTargetState);
-       ALLOC_STATE(blnd, blnd, (6 + (R700_MAX_RENDER_TARGETS * 3)), r700SendCBBlendState);
-       ALLOC_STATE(blnd_clr, always, 6, r700SendCBBlendColorState);
-       ALLOC_STATE(sx, always, 9, r700SendSXState);
-       ALLOC_STATE(vgt, always, 41, r700SendVGTState);
-       ALLOC_STATE(spi, always, (59 + R700_MAX_SHADER_EXPORTS), r700SendSPIState);
-       ALLOC_STATE(vpt, always, 16, r700SendViewportState);
-       ALLOC_STATE(fs, always, 18, r700SendFSState);
-       ALLOC_STATE(vs, always, 21, r700SendVSState);
-       ALLOC_STATE(ps, always, 24, r700SendPSState);
-       ALLOC_STATE(vs_consts, vs_consts, (2 + (R700_MAX_DX9_CONSTS * 4)), r700SendVSConsts);
-       ALLOC_STATE(ps_consts, ps_consts, (2 + (R700_MAX_DX9_CONSTS * 4)), r700SendPSConsts);
-       ALLOC_STATE(vtx, vtx, (VERT_ATTRIB_MAX * 18), r700SendVTXState);
-       ALLOC_STATE(tx, tx, (R700_TEXTURE_NUMBERUNITS * 20), r700SendTexState);
-       ALLOC_STATE(tx_smplr, tx, (R700_TEXTURE_NUMBERUNITS * 5), r700SendTexSamplerState);
-       ALLOC_STATE(tx_brdr_clr, tx, (R700_TEXTURE_NUMBERUNITS * 6), r700SendTexBorderColorState);
-       r600_init_query_stateobj(&context->radeon, 6 * 2);
-
-       context->radeon.hw.is_dirty = GL_TRUE;
-       context->radeon.hw.all_dirty = GL_TRUE;
+    R700_CHIP_CONTEXT *r700    = (R700_CHIP_CONTEXT*)(&context->hw);
+    radeon_print(RADEON_STATE, RADEON_NORMAL, "%s %p\n", __func__, context);
+    context->radeon.hw.max_state_size = 10 + 5 + 14; /* start 3d, idle, cb/db flush */
+
+    /* Setup the atom linked list */
+    make_empty_list(&context->radeon.hw.atomlist);
+    context->radeon.hw.atomlist.name = "atom-list";
+
+    ALLOC_STATE(sq, always, 34, r700SendSQConfig);
+    ALLOC_STATE(db, always, 17, r700SendDBState);
+    ALLOC_STATE(stencil, always, 4, r700SendStencilState);
+    ALLOC_STATE(db_target, always, 16, r700SendDepthTargetState);
+    ALLOC_STATE(sc, always, 15, r700SendSCState);
+    ALLOC_STATE(scissor, always, 22, r700SendScissorState);
+    ALLOC_STATE(aa, always, 12, r700SendAAState);
+    ALLOC_STATE(cl, always, 12, r700SendCLState);
+    ALLOC_STATE(gb, always, 6, r700SendGBState);
+    ALLOC_STATE(ucp, ucp, (R700_MAX_UCP * 6), r700SendUCPState);
+    ALLOC_STATE(su, always, 9, r700SendSUState);
+    ALLOC_STATE(poly, always, 10, r700SendPolyState);
+    ALLOC_STATE(cb, cb, 18, r700SendCBState);
+    ALLOC_STATE(clrcmp, always, 6, r700SendCBCLRCMPState);
+    ALLOC_STATE(cb_target, always, 31, r700SendRenderTargetState);
+    ALLOC_STATE(blnd, blnd, (6 + (R700_MAX_RENDER_TARGETS * 3)), r700SendCBBlendState);
+    ALLOC_STATE(blnd_clr, always, 6, r700SendCBBlendColorState);
+    ALLOC_STATE(sx, always, 9, r700SendSXState);
+    ALLOC_STATE(vgt, always, 41, r700SendVGTState);
+    ALLOC_STATE(spi, always, (59 + R700_MAX_SHADER_EXPORTS), r700SendSPIState);
+    ALLOC_STATE(vpt, always, 16, r700SendViewportState);
+    ALLOC_STATE(fs, always, 18, r700SendFSState);
+    if(GL_TRUE == r700->bShaderUseMemConstant)
+    {
+        ALLOC_STATE(vs, always, 36, r700SendVSState);
+           ALLOC_STATE(ps, always, 24, r700SendPSState); /* TODO : not imp yet, fix later. */
+    }
+    else
+    {
+        ALLOC_STATE(vs, always, 21, r700SendVSState);
+        ALLOC_STATE(ps, always, 24, r700SendPSState);
+        ALLOC_STATE(vs_consts, vs_consts, (2 + (R700_MAX_DX9_CONSTS * 4)), r700SendVSConsts);
+        ALLOC_STATE(ps_consts, ps_consts, (2 + (R700_MAX_DX9_CONSTS * 4)), r700SendPSConsts);
+    }
+
+    ALLOC_STATE(vtx, vtx, (VERT_ATTRIB_MAX * 18), r700SendVTXState);
+    ALLOC_STATE(tx, tx, (R700_TEXTURE_NUMBERUNITS * 20), r700SendTexState);
+    ALLOC_STATE(tx_smplr, tx, (R700_TEXTURE_NUMBERUNITS * 5), r700SendTexSamplerState);
+    ALLOC_STATE(tx_brdr_clr, tx, (R700_TEXTURE_NUMBERUNITS * 6), r700SendTexBorderColorState);
+    r600_init_query_stateobj(&context->radeon, 6 * 2);
+
+    context->radeon.hw.is_dirty = GL_TRUE;
+    context->radeon.hw.all_dirty = GL_TRUE;
 }
index 0b6b72f8501737039c342d27c9c6d00045022215..ebf1840a79501e1d10975d821fc8eba47f3f354f 100644 (file)
@@ -43,6 +43,8 @@
 #define SETbit(x, bit)                 ( (x) |= (bit) )
 #define CLEARbit(x, bit)               ( (x) &= ~(bit) )
 
+#define GETbits(x, shift, mask)  ( ((x) & (mask)) >> (shift) )
+
 #define R700_TEXTURE_NUMBERUNITS 16
 #define R700_MAX_RENDER_TARGETS  8
 #define R700_MAX_VIEWPORTS       16
@@ -238,6 +240,9 @@ typedef struct _VS_STATE_STRUCT
        union UINT_FLOAT                SQ_PGM_CF_OFFSET_VS       ;  /* 0xA234 */
        GLboolean                         dirty;
        int                             num_consts;
+
+    union UINT_FLOAT                SQ_ALU_CONST_CACHE_VS_0;
+
        union UINT_FLOAT                consts[R700_MAX_DX9_CONSTS][4];
 } VS_STATE_STRUCT;
 
@@ -499,6 +504,8 @@ typedef struct _R700_CHIP_CONTEXT
 
        GLboolean                       bEnablePerspective;
 
+    GLboolean                       bShaderUseMemConstant;
+
 } R700_CHIP_CONTEXT;
 
 #endif /* _R700_CHIP_H_ */
index f9d84b6ed68946ec27bda626f8e7e94fc7a25bfc..6fdd93a3302c2584c0ffd4f8a0fbf52c66a66c31 100644 (file)
@@ -362,6 +362,9 @@ GLboolean r700TranslateFragmentShader(struct r700_fragment_program *fp,
                                                             struct gl_fragment_program   *mesa_fp,
                                  GLcontext *ctx) 
 {
+    context_t *context = R700_CONTEXT(ctx);      
+    R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+
        GLuint    number_of_colors_exported;
        GLboolean z_enabled = GL_FALSE;
        GLuint    unBit, shadow_unit;
@@ -373,6 +376,17 @@ GLboolean r700TranslateFragmentShader(struct r700_fragment_program *fp,
     //Init_Program
        Init_r700_AssemblerBase( SPT_FP, &(fp->r700AsmCode), &(fp->r700Shader) );
 
+    if(GL_TRUE == r700->bShaderUseMemConstant)
+    {
+        fp->r700AsmCode.bUseMemConstant = GL_TRUE;
+    }
+    else
+    {
+        fp->r700AsmCode.bUseMemConstant = GL_FALSE;
+    }
+
+    fp->r700AsmCode.unAsic = 7;
+
     if(mesa_fp->Base.InputsRead & FRAG_BIT_WPOS)
     {
         insert_wpos_code(ctx, mesa_fp);
@@ -481,6 +495,14 @@ void * r700GetActiveFpShaderBo(GLcontext * ctx)
     return fp->shaderbo;
 }
 
+void * r700GetActiveFpShaderConstBo(GLcontext * ctx)
+{
+    struct r700_fragment_program *fp = (struct r700_fragment_program *)
+                                          (ctx->FragmentProgram._Current);
+
+    return fp->constbo0;
+}
+
 GLboolean r700SetupFragmentProgram(GLcontext * ctx)
 {
     context_t *context = R700_CONTEXT(ctx);
@@ -768,6 +790,17 @@ GLboolean r700SetupFragmentProgram(GLcontext * ctx)
                        r700->ps.consts[ui][2].f32All = paramList->ParameterValues[ui][2];
                        r700->ps.consts[ui][3].f32All = paramList->ParameterValues[ui][3];
            }
+
+        /* Load fp constants to gpu */
+        if( (GL_TRUE == r700->bShaderUseMemConstant) && (unNumParamData > 0) )
+        {
+            r600EmitShader(ctx,
+                           &(fp->constbo0),
+                           (GLvoid *)&(paramList->ParameterValues[0][0]),
+                           unNumParamData * 4,
+                           "FS Const");
+        }
+
     } else
            r700->ps.num_consts = 0;
 
index 39c59c9201df9e56ae9f590b43e23ad85c3baf3a..aaa6043d5d8bdbe4d3949ee6d5cda11c22bb76ea 100644 (file)
@@ -43,6 +43,9 @@ struct r700_fragment_program
 
     void * shaderbo;
 
+       GLuint k0used;
+    void * constbo0;
+
        GLboolean WritesDepth;
        GLuint optimization;
 };
@@ -67,4 +70,6 @@ extern GLboolean r700SetupFragmentProgram(GLcontext * ctx);
 
 extern void *    r700GetActiveFpShaderBo(GLcontext * ctx);
 
+extern void *    r700GetActiveFpShaderConstBo(GLcontext * ctx);
+
 #endif /*_R700_FRAGPROG_H_*/
index 835179251153ddc6d9019b48e9cfccac51c23613..e0c9179004d27b1e53d274b9da079214e16f4e43 100644 (file)
@@ -48,6 +48,12 @@ static void freeVertProgCache(GLcontext *ctx, struct r700_vertex_program_cont *c
                tmp = vp->next;
                /* Release DMA region */
                r600DeleteShader(ctx, vp->shaderbo);
+
+        if(NULL != vp->constbo0)
+        {
+                   r600DeleteShader(ctx, vp->constbo0);
+        }
+
                /* Clean up */
                Clean_Up_Assembler(&(vp->r700AsmCode));
                Clean_Up_Shader(&(vp->r700Shader));
@@ -79,6 +85,7 @@ static struct gl_program *r700NewProgram(GLcontext * ctx,
                                              &vpc->mesa_program,
                                                                 target, 
                                              id);
+        
            break;
     case GL_FRAGMENT_PROGRAM_NV:
     case GL_FRAGMENT_PROGRAM_ARB:
@@ -92,6 +99,8 @@ static struct gl_program *r700NewProgram(GLcontext * ctx,
 
         fp->shaderbo   = NULL;
 
+               fp->constbo0   = NULL;
+
            break;
     default:
            _mesa_problem(ctx, "Bad target in r700NewProgram");
@@ -121,6 +130,11 @@ static void r700DeleteProgram(GLcontext * ctx, struct gl_program *prog)
 
         r600DeleteShader(ctx, fp->shaderbo);
 
+        if(NULL != fp->constbo0)
+        {
+                   r600DeleteShader(ctx, fp->constbo0);
+        }
+
         /* Clean up */
         Clean_Up_Assembler(&(fp->r700AsmCode));
         Clean_Up_Shader(&(fp->r700Shader));
@@ -145,6 +159,13 @@ r700ProgramStringNotify(GLcontext * ctx, GLenum target, struct gl_program *prog)
                break;
        case GL_FRAGMENT_PROGRAM_ARB:
                r600DeleteShader(ctx, fp->shaderbo);
+
+        if(NULL != fp->constbo0)
+        {
+                   r600DeleteShader(ctx, fp->constbo0);
+                   fp->constbo0   = NULL;
+        }
+
                Clean_Up_Assembler(&(fp->r700AsmCode));
                Clean_Up_Shader(&(fp->r700Shader));
                fp->translated = GL_FALSE;
index c5771f9fd0baef60ed8e86b3537090c453b97fbd..f90c69c41664229beb2fc68373b4ef6168e7a592 100644 (file)
@@ -644,6 +644,7 @@ static void r700SetupStreams(GLcontext *ctx, const struct gl_client_array *input
 #endif
             ) 
         {
+            assert(count);
             r700ConvertAttrib(ctx, count, input[i], &context->stream_desc[index]);
         } 
         else 
index 5ea8918611ca01cd8604cb825e8a256579291c14..925b4ffe6dd1e2f0485ff2e3b4188841c73c37ba 100644 (file)
@@ -1580,7 +1580,16 @@ static void r700InitSQConfig(GLcontext * ctx)
            CLEARbit(r700->sq_config.SQ_CONFIG.u32All, VC_ENABLE_bit);
     else
            SETbit(r700->sq_config.SQ_CONFIG.u32All, VC_ENABLE_bit);
-    SETbit(r700->sq_config.SQ_CONFIG.u32All, DX9_CONSTS_bit);
+
+    if(GL_TRUE == r700->bShaderUseMemConstant)
+    {
+        CLEARbit(r700->sq_config.SQ_CONFIG.u32All, DX9_CONSTS_bit);
+    }
+    else
+    {
+        SETbit(r700->sq_config.SQ_CONFIG.u32All, DX9_CONSTS_bit);
+    }
+
     SETbit(r700->sq_config.SQ_CONFIG.u32All, ALU_INST_PREFER_VECTOR_bit);
     SETfield(r700->sq_config.SQ_CONFIG.u32All, ps_prio, PS_PRIO_shift, PS_PRIO_mask);
     SETfield(r700->sq_config.SQ_CONFIG.u32All, vs_prio, VS_PRIO_shift, VS_PRIO_mask);
@@ -1689,8 +1698,9 @@ void r700InitState(GLcontext * ctx) //-------------------
            SETbit(r700->PA_SC_MODE_CNTL.u32All, FORCE_EOV_CNTDWN_ENABLE_bit);
     }
 
-    /* Do scale XY and Z by 1/W0. */
-    r700->bEnablePerspective = GL_TRUE;
+    /* Do scale XY and Z by 1/W0. */   
+    r700->bEnablePerspective = GL_TRUE;    
+
     CLEARbit(r700->PA_CL_VTE_CNTL.u32All, VTX_XY_FMT_bit);
     CLEARbit(r700->PA_CL_VTE_CNTL.u32All, VTX_Z_FMT_bit);
     SETbit(r700->PA_CL_VTE_CNTL.u32All, VTX_W0_FMT_bit);
index 6a2a09eaf1ab92595f285671f162b09130322f7b..7ed4b7d23870030c2ac3a3c5e8082911c25f0b02 100644 (file)
@@ -305,12 +305,17 @@ struct r700_vertex_program* r700TranslateVertexShader(GLcontext *ctx,
                                                      struct gl_vertex_program *mesa_vp)
 {
        context_t *context = R700_CONTEXT(ctx);
+
+    R700_CHIP_CONTEXT *r700 = (R700_CHIP_CONTEXT*)(&context->hw);
+
        struct r700_vertex_program *vp;
        unsigned int i;
 
        vp = calloc(1, sizeof(*vp));
        vp->mesa_program = _mesa_clone_vertex_program(ctx, mesa_vp);
 
+    vp->constbo0 = NULL;
+
        if (mesa_vp->IsPositionInvariant)
        {
                 _mesa_insert_mvp_code(ctx, vp->mesa_program);
@@ -331,6 +336,18 @@ struct r700_vertex_program* r700TranslateVertexShader(GLcontext *ctx,
 
        //Init_Program
        Init_r700_AssemblerBase(SPT_VP, &(vp->r700AsmCode), &(vp->r700Shader) );
+
+    if(GL_TRUE == r700->bShaderUseMemConstant)
+    {
+        vp->r700AsmCode.bUseMemConstant = GL_TRUE;
+    }
+    else
+    {
+        vp->r700AsmCode.bUseMemConstant = GL_FALSE;
+    }
+
+    vp->r700AsmCode.unAsic = 7;
+
        Map_Vertex_Program(ctx, vp, vp->mesa_program );
 
        if(GL_FALSE == Find_Instruction_Dependencies_vp(vp, vp->mesa_program))
@@ -576,6 +593,17 @@ void * r700GetActiveVpShaderBo(GLcontext * ctx)
        return NULL;
 }
 
+void * r700GetActiveVpShaderConstBo(GLcontext * ctx)
+{
+    context_t *context = R700_CONTEXT(ctx);
+    struct r700_vertex_program *vp = context->selected_vp;;
+
+    if (vp)
+       return vp->constbo0;
+    else
+       return NULL;
+}
+
 GLboolean r700SetupVertexProgram(GLcontext * ctx)
 {
     context_t *context = R700_CONTEXT(ctx);
@@ -600,6 +628,19 @@ GLboolean r700SetupVertexProgram(GLcontext * ctx)
                        vp->r700Shader.uShaderBinaryDWORDSize,
                        "VS");
 
+        if(GL_TRUE == r700->bShaderUseMemConstant)
+        {
+            paramList = vp->mesa_program->Base.Parameters;
+            if(NULL != paramList)
+            {
+                unNumParamData = paramList->NumParameters;
+                r600AllocShaderConsts(ctx,
+                               &(vp->constbo0),                       
+                               unNumParamData *4*4,
+                               "VSCON");
+            }
+        }        
+
         vp->loaded = GL_TRUE;
     }
 
@@ -616,7 +657,9 @@ GLboolean r700SetupVertexProgram(GLcontext * ctx)
     r700->vs.SQ_PGM_RESOURCES_VS.u32All = 0;
     SETbit(r700->vs.SQ_PGM_RESOURCES_VS.u32All, PGM_RESOURCES__PRIME_CACHE_ON_DRAW_bit);
 
-    r700->vs.SQ_PGM_START_VS.u32All = 0; /* set from buffer object. */
+    r700->vs.SQ_ALU_CONST_CACHE_VS_0.u32All = 0; /* set from buffer object. */
+    
+    r700->vs.SQ_PGM_START_VS.u32All = 0;
 
     SETfield(r700->vs.SQ_PGM_RESOURCES_VS.u32All, vp->r700Shader.nRegs + 1,
              NUM_GPRS_shift, NUM_GPRS_mask);
@@ -687,6 +730,16 @@ GLboolean r700SetupVertexProgram(GLcontext * ctx)
                        r700->vs.consts[ui][3].f32All = paramList->ParameterValues[ui][3];
             }
            }
+
+        /* Load vp constants to gpu */
+        if(GL_TRUE == r700->bShaderUseMemConstant)
+        {
+            r600EmitShaderConsts(ctx,
+                           vp->constbo0,
+                           0,
+                           (GLvoid *)&(r700->vs.consts[0][0]),
+                           unNumParamData * 4 * 4);
+        }
     } else
            r700->vs.num_consts = 0;
 
index 645c9ac84aae4e7346e4e6f8e53cd3e7d67066ab..9acdc8e3501b1a31e9fdc0fa9b06b7660b2c4bb9 100644 (file)
@@ -56,6 +56,9 @@ struct r700_vertex_program
 
     void * shaderbo;
 
+       GLuint K0used;
+    void * constbo0;
+
     ArrayDesc              aos_desc[VERT_ATTRIB_MAX];
 };
 
@@ -97,6 +100,8 @@ extern GLboolean r700SetupVertexProgram(GLcontext * ctx);
 
 extern void *    r700GetActiveVpShaderBo(GLcontext * ctx);
 
+extern void * r700GetActiveVpShaderConstBo(GLcontext * ctx);
+
 extern int getTypeSize(GLenum type);
 
 #endif /* _R700_VERTPROG_H_ */
index 7d54fabebbc0c821457d7e31feafa13521bbfd75..61106fbc43f5b6777a9ecae5baa09d802270c75d 100644 (file)
 #define PCI_CHIP_RV740_94B5             0x94B5
 #define PCI_CHIP_RV740_94B9             0x94B9
 
+#define PCI_CHIP_CEDAR_68E0             0x68E0
+#define PCI_CHIP_CEDAR_68E1             0x68E1
+#define PCI_CHIP_CEDAR_68E4             0x68E4
+#define PCI_CHIP_CEDAR_68E5             0x68E5
+#define PCI_CHIP_CEDAR_68E8             0x68E8
+#define PCI_CHIP_CEDAR_68E9             0x68E9
+#define PCI_CHIP_CEDAR_68F1             0x68F1
+#define PCI_CHIP_CEDAR_68F8             0x68F8
+#define PCI_CHIP_CEDAR_68F9             0x68F9
+#define PCI_CHIP_CEDAR_68FE             0x68FE
+
+#define PCI_CHIP_REDWOOD_68C0           0x68C0
+#define PCI_CHIP_REDWOOD_68C1           0x68C1
+#define PCI_CHIP_REDWOOD_68C8           0x68C8
+#define PCI_CHIP_REDWOOD_68C9           0x68C9
+#define PCI_CHIP_REDWOOD_68D8           0x68D8
+#define PCI_CHIP_REDWOOD_68D9           0x68D9
+#define PCI_CHIP_REDWOOD_68DA           0x68DA
+#define PCI_CHIP_REDWOOD_68DE           0x68DE
+
+#define PCI_CHIP_JUNIPER_68A0           0x68A0
+#define PCI_CHIP_JUNIPER_68A1           0x68A1
+#define PCI_CHIP_JUNIPER_68A8           0x68A8
+#define PCI_CHIP_JUNIPER_68A9           0x68A9
+#define PCI_CHIP_JUNIPER_68B0           0x68B0
+#define PCI_CHIP_JUNIPER_68B8           0x68B8
+#define PCI_CHIP_JUNIPER_68B9           0x68B9
+#define PCI_CHIP_JUNIPER_68BE           0x68BE
+
+#define PCI_CHIP_CYPRESS_6880           0x6880
+#define PCI_CHIP_CYPRESS_6888           0x6888
+#define PCI_CHIP_CYPRESS_6889           0x6889
+#define PCI_CHIP_CYPRESS_688A           0x688A
+#define PCI_CHIP_CYPRESS_6898           0x6898
+#define PCI_CHIP_CYPRESS_6899           0x6899
+#define PCI_CHIP_CYPRESS_689E           0x689E
+
+#define PCI_CHIP_HEMLOCK_689C           0x689C
+#define PCI_CHIP_HEMLOCK_689D           0x689D
+
 enum {
    CHIP_FAMILY_R100,
    CHIP_FAMILY_RV100,
@@ -438,6 +478,11 @@ enum {
    CHIP_FAMILY_RV730,
    CHIP_FAMILY_RV710,
    CHIP_FAMILY_RV740,
+   CHIP_FAMILY_CEDAR,
+   CHIP_FAMILY_REDWOOD,
+   CHIP_FAMILY_JUNIPER,
+   CHIP_FAMILY_CYPRESS,
+   CHIP_FAMILY_HEMLOCK,
    CHIP_FAMILY_LAST
 };
 
index 92663bf66d74477033a4e0d9d7c7983997449f0c..07f7cba354e9e6a7e2fe411cd91bc1c73218c191 100644 (file)
@@ -93,6 +93,11 @@ static const char* get_chip_family_name(int chip_family)
        case CHIP_FAMILY_RV730: return "RV730";
        case CHIP_FAMILY_RV710: return "RV710";
        case CHIP_FAMILY_RV740: return "RV740";
+       case CHIP_FAMILY_CEDAR: return "CEDAR";
+       case CHIP_FAMILY_REDWOOD: return "REDWOOD";
+       case CHIP_FAMILY_JUNIPER: return "JUNIPER";
+       case CHIP_FAMILY_CYPRESS: return "CYPRESS";
+       case CHIP_FAMILY_HEMLOCK: return "HEMLOCK";
        default: return "unknown";
        }
 }
index f06e5fdf244713e709888e55159c39d3456252b4..024e31f8ec7dc1c023bc27f11270f50c5810762b 100644 (file)
@@ -244,6 +244,8 @@ struct radeon_tex_obj {
        GLuint SQ_TEX_RESOURCE5;
        GLuint SQ_TEX_RESOURCE6;
 
+    GLuint SQ_TEX_RESOURCE7;
+
        GLuint SQ_TEX_SAMPLER0;
        GLuint SQ_TEX_SAMPLER1;
        GLuint SQ_TEX_SAMPLER2;
index 517485091a21bbb12ccbb65d4895a0365f567004..0597d4250de0072fff4cc8a0f8567b0dc4925f72 100644 (file)
@@ -609,6 +609,7 @@ radeon_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
 
 void radeon_fbo_init(struct radeon_context *radeon)
 {
+#if FEATURE_EXT_framebuffer_object
   radeon->glCtx->Driver.NewFramebuffer = radeon_new_framebuffer;
   radeon->glCtx->Driver.NewRenderbuffer = radeon_new_renderbuffer;
   radeon->glCtx->Driver.BindFramebuffer = radeon_bind_framebuffer;
@@ -617,7 +618,10 @@ void radeon_fbo_init(struct radeon_context *radeon)
   radeon->glCtx->Driver.FinishRenderTexture = radeon_finish_render_texture;
   radeon->glCtx->Driver.ResizeBuffers = radeon_resize_buffers;
   radeon->glCtx->Driver.ValidateFramebuffer = radeon_validate_framebuffer;
+#endif
+#if FEATURE_EXT_framebuffer_blit
   radeon->glCtx->Driver.BlitFramebuffer = _mesa_meta_BlitFramebuffer;
+#endif
 }
 
   
index c6e5f110ea314f92abff4e7b767ec44de3968d37..ddfde3edaf758005a28732434522e84850ef6f52 100644 (file)
@@ -199,10 +199,10 @@ static void calculate_miptree_layout_r300(radeonContextPtr rmesa, radeon_mipmap_
 
                for(face = 0; face < mt->faces; face++)
                        compute_tex_image_offset(rmesa, mt, face, level, &curOffset);
-               /* r600 cube levels seems to be aligned to 8 faces but
-                * we have separate register for 1'st level offset so add
+               /* from r700? cube levels seems to be aligned to 8 faces,
+                * as we have separate register for 1'st level offset add
                 * 2 image alignment after 1'st mip level */
-               if(rmesa->radeonScreen->chip_family >= CHIP_FAMILY_R600 &&
+               if(rmesa->radeonScreen->chip_family >= CHIP_FAMILY_RV770 &&
                   mt->target == GL_TEXTURE_CUBE_MAP && level >= 1)
                        curOffset += 2 * mt->levels[level].size;
        }
index fa97a19302c4fef972549221f3aac3fe6dc23348..2ea77e56c7ead5bef0f1aab0c35b2ed6372906e2 100644 (file)
@@ -916,6 +916,61 @@ static int radeon_set_screen_flags(radeonScreenPtr screen, int device_id)
       screen->chip_flags = RADEON_CHIPSET_TCL;
       break;
 
+    case PCI_CHIP_CEDAR_68E0:
+    case PCI_CHIP_CEDAR_68E1:
+    case PCI_CHIP_CEDAR_68E4:
+    case PCI_CHIP_CEDAR_68E5:
+    case PCI_CHIP_CEDAR_68E8:
+    case PCI_CHIP_CEDAR_68E9:
+    case PCI_CHIP_CEDAR_68F1:
+    case PCI_CHIP_CEDAR_68F8:
+    case PCI_CHIP_CEDAR_68F9:
+    case PCI_CHIP_CEDAR_68FE:
+       screen->chip_family = CHIP_FAMILY_CEDAR;
+       screen->chip_flags = RADEON_CHIPSET_TCL;
+       break;
+
+    case PCI_CHIP_REDWOOD_68C0:
+    case PCI_CHIP_REDWOOD_68C1:
+    case PCI_CHIP_REDWOOD_68C8:
+    case PCI_CHIP_REDWOOD_68C9:
+    case PCI_CHIP_REDWOOD_68D8:
+    case PCI_CHIP_REDWOOD_68D9:
+    case PCI_CHIP_REDWOOD_68DA:
+    case PCI_CHIP_REDWOOD_68DE:
+       screen->chip_family = CHIP_FAMILY_REDWOOD;
+       screen->chip_flags = RADEON_CHIPSET_TCL;
+       break;
+
+    case PCI_CHIP_JUNIPER_68A0:
+    case PCI_CHIP_JUNIPER_68A1:
+    case PCI_CHIP_JUNIPER_68A8:
+    case PCI_CHIP_JUNIPER_68A9:
+    case PCI_CHIP_JUNIPER_68B0:
+    case PCI_CHIP_JUNIPER_68B8:
+    case PCI_CHIP_JUNIPER_68B9:
+    case PCI_CHIP_JUNIPER_68BE:
+       screen->chip_family = CHIP_FAMILY_JUNIPER;
+       screen->chip_flags = RADEON_CHIPSET_TCL;
+       break;
+
+    case PCI_CHIP_CYPRESS_6880:
+    case PCI_CHIP_CYPRESS_6888:
+    case PCI_CHIP_CYPRESS_6889:
+    case PCI_CHIP_CYPRESS_688A:
+    case PCI_CHIP_CYPRESS_6898:
+    case PCI_CHIP_CYPRESS_6899:
+    case PCI_CHIP_CYPRESS_689E:
+       screen->chip_family = CHIP_FAMILY_CYPRESS;
+       screen->chip_flags = RADEON_CHIPSET_TCL;
+       break;
+
+    case PCI_CHIP_HEMLOCK_689C:
+    case PCI_CHIP_HEMLOCK_689D:
+       screen->chip_family = CHIP_FAMILY_HEMLOCK;
+       screen->chip_flags = RADEON_CHIPSET_TCL;
+       break;
+
    default:
       fprintf(stderr, "unknown chip id 0x%x, can't guess.\n",
              device_id);
@@ -1116,7 +1171,7 @@ radeonCreateScreen( __DRIscreen *sPriv )
             }
         }
         else
-        {
+        {            
             screen->fbLocation = (temp & 0xffff) << 16;
         }
    }
diff --git a/src/mesa/drivers/glslcompiler/Makefile b/src/mesa/drivers/glslcompiler/Makefile
deleted file mode 100644 (file)
index 6da9f93..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-# Makefile for stand-alone GL-SL compiler
-
-TOP = ../../../..
-
-include $(TOP)/configs/current
-
-
-PROGRAM = glslcompiler
-
-OBJECTS = \
-       glslcompiler.o \
-       ../common/driverfuncs.o \
-       ../../libmesa.a \
-       $(TOP)/src/mapi/glapi/libglapi.a
-
-INCLUDES = \
-       -I$(TOP)/include \
-       -I$(TOP)/include/GL/internal \
-       -I$(TOP)/src/mapi \
-       -I$(TOP)/src/mesa \
-       -I$(TOP)/src/mesa/main \
-       -I$(TOP)/src/mesa/glapi \
-       -I$(TOP)/src/mesa/math \
-       -I$(TOP)/src/mesa/transform \
-       -I$(TOP)/src/mesa/shader \
-       -I$(TOP)/src/mesa/swrast \
-       -I$(TOP)/src/mesa/swrast_setup \
-
-
-default: $(PROGRAM)
-       $(INSTALL) $(PROGRAM) $(TOP)/bin
-
-
-glslcompiler: $(OBJECTS)
-       $(CC) $(OBJECTS) $(GL_LIB_DEPS) -o $@
-
-
-glslcompiler.o: glslcompiler.c
-       $(CC) -c $(INCLUDES) $(CFLAGS) glslcompiler.c -o $@
-
-
-clean:
-       -rm -f *.o *~ $(PROGRAM)
diff --git a/src/mesa/drivers/glslcompiler/glslcompiler.c b/src/mesa/drivers/glslcompiler/glslcompiler.c
deleted file mode 100644 (file)
index 7259bf4..0000000
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 1999-2007  Brian Paul, Tungsten Graphics, 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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \mainpage
- *
- * Stand-alone Shading Language compiler.  
- * Basically, a command-line program which accepts GLSL shaders and emits
- * vertex/fragment programs (GPU instructions).
- *
- * This file is basically just a Mesa device driver but instead of building
- * a shared library we build an executable.
- *
- * We can emit programs in three different formats:
- *  1. ARB-style (GL_ARB_vertex/fragment_program)
- *  2. NV-style (GL_NV_vertex/fragment_program)
- *  3. debug-style (a slightly more sophisticated, internal format)
- *
- * Note that the ARB and NV program languages can't express all the
- * features that might be used by a fragment program (examples being
- * uniform and varying vars).  So, the ARB/NV programs that are
- * emitted aren't always legal programs in those languages.
- */
-
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/extensions.h"
-#include "main/framebuffer.h"
-#include "main/shaderapi.h"
-#include "main/shaderobj.h"
-#include "program/prog_print.h"
-#include "drivers/common/driverfuncs.h"
-#include "tnl/tnl.h"
-#include "tnl/t_context.h"
-#include "tnl/t_pipeline.h"
-#include "swrast/swrast.h"
-#include "swrast_setup/swrast_setup.h"
-#include "vbo/vbo.h"
-
-
-static const char *Prog = "glslcompiler";
-
-
-struct options {
-   GLboolean LineNumbers;
-   GLboolean Link;
-   gl_prog_print_mode Mode;
-   const char *VertFile;
-   const char *FragFile;
-   const char *GeoFile;
-   const char *OutputFile;
-   GLboolean Params;
-   struct gl_sl_pragmas Pragmas;
-};
-
-static struct options Options;
-
-
-/**
- * GLSL compiler driver context. (kind of an artificial thing for now)
- */
-struct compiler_context
-{
-   GLcontext MesaContext;
-   int foo;
-};
-
-typedef struct compiler_context CompilerContext;
-
-
-
-static void
-UpdateState(GLcontext *ctx, GLuint new_state)
-{
-   /* easy - just propogate */
-   _swrast_InvalidateState( ctx, new_state );
-   _swsetup_InvalidateState( ctx, new_state );
-   _tnl_InvalidateState( ctx, new_state );
-   _vbo_InvalidateState( ctx, new_state );
-}
-
-
-
-static GLboolean
-CreateContext(void)
-{
-   struct dd_function_table ddFuncs;
-   GLvisual *vis;
-   GLframebuffer *buf;
-   GLcontext *ctx;
-   CompilerContext *cc;
-
-   vis = _mesa_create_visual(GL_FALSE, GL_FALSE, /* RGB */
-                             8, 8, 8, 8,  /* color */
-                             0, 0,  /* z, stencil */
-                             0, 0, 0, 0, 1);  /* accum */
-   buf = _mesa_create_framebuffer(vis);
-
-   cc = calloc(1, sizeof(*cc));
-   if (!vis || !buf || !cc) {
-      if (vis)
-         _mesa_destroy_visual(vis);
-      if (buf)
-         _mesa_destroy_framebuffer(buf);
-      free(cc);
-      return GL_FALSE;
-   }
-
-   _mesa_init_driver_functions(&ddFuncs);
-   ddFuncs.GetString = NULL;/*get_string;*/
-   ddFuncs.UpdateState = UpdateState;
-   ddFuncs.GetBufferSize = NULL;
-
-   ctx = &cc->MesaContext;
-   _mesa_initialize_context(ctx, vis, NULL, &ddFuncs, cc);
-   _mesa_enable_sw_extensions(ctx);
-
-   if (!_swrast_CreateContext( ctx ) ||
-       !_vbo_CreateContext( ctx ) ||
-       !_tnl_CreateContext( ctx ) ||
-       !_swsetup_CreateContext( ctx )) {
-      _mesa_destroy_visual(vis);
-      _mesa_destroy_framebuffer(buf);
-      _mesa_free_context_data(ctx);
-      free(cc);
-      return GL_FALSE;
-   }
-   TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
-   _swsetup_Wakeup( ctx );
-
-   /* Override the context's default pragma settings */
-   ctx->Shader.DefaultPragmas = Options.Pragmas;
-
-   _mesa_make_current(ctx, buf, buf);
-
-   return GL_TRUE;
-}
-
-
-static void
-LoadAndCompileShader(GLuint shader, const char *text)
-{
-   GLint stat;
-   _mesa_ShaderSourceARB(shader, 1, (const GLchar **) &text, NULL);
-   _mesa_CompileShaderARB(shader);
-   _mesa_GetShaderiv(shader, GL_COMPILE_STATUS, &stat);
-   if (!stat) {
-      GLchar log[1000];
-      GLsizei len;
-      _mesa_GetShaderInfoLog(shader, 1000, &len, log);
-      fprintf(stderr, "%s: problem compiling shader: %s\n", Prog, log);
-      exit(1);
-   }
-   else {
-      printf("Shader compiled OK\n");
-   }
-}
-
-
-/**
- * Read a shader from a file.
- */
-static void
-ReadShader(GLuint shader, const char *filename)
-{
-   const int max = 100*1000;
-   int n;
-   char *buffer = (char*) malloc(max);
-   FILE *f = fopen(filename, "r");
-   if (!f) {
-      fprintf(stderr, "%s: Unable to open shader file %s\n", Prog, filename);
-      exit(1);
-   }
-
-   n = fread(buffer, 1, max, f);
-   /*
-   printf("%s: read %d bytes from shader file %s\n", Prog, n, filename);
-   */
-   if (n > 0) {
-      buffer[n] = 0;
-      LoadAndCompileShader(shader, buffer);
-   }
-
-   fclose(f);
-   free(buffer);
-}
-
-
-static void
-CheckLink(GLuint v_shader, GLuint f_shader)
-{
-   GLuint prog;
-   GLint stat;
-
-   prog = _mesa_CreateProgram();
-
-   _mesa_AttachShader(prog, v_shader);
-   _mesa_AttachShader(prog, f_shader);
-
-   _mesa_LinkProgramARB(prog);
-   _mesa_GetProgramiv(prog, GL_LINK_STATUS, &stat);
-   if (!stat) {
-      GLchar log[1000];
-      GLsizei len;
-      _mesa_GetProgramInfoLog(prog, 1000, &len, log);
-      fprintf(stderr, "Linker error:\n%s\n", log);
-   }
-   else {
-      fprintf(stderr, "Link success!\n");
-   }
-}
-
-
-static void
-PrintShaderInstructions(GLuint shader, FILE *f)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
-   struct gl_program *prog = sh->Program;
-   _mesa_fprint_program_opt(stdout, prog, Options.Mode, Options.LineNumbers);
-   if (Options.Params)
-      _mesa_print_program_parameters(ctx, prog);
-}
-
-
-static GLuint
-CompileShader(const char *filename, GLenum type)
-{
-   GLuint shader;
-
-   assert(type == GL_FRAGMENT_SHADER ||
-          type == GL_VERTEX_SHADER ||
-          type == GL_GEOMETRY_SHADER_ARB);
-
-   shader = _mesa_CreateShader(type);
-   ReadShader(shader, filename);
-
-   return shader;
-}
-
-
-static void
-Usage(void)
-{
-   printf("Mesa GLSL stand-alone compiler\n");
-   printf("Usage:\n");
-   printf("  --vs FILE          vertex shader input filename\n");
-   printf("  --fs FILE          fragment shader input filename\n");
-   printf("  --gs FILE          geometry shader input filename\n");
-   printf("  --arb              emit ARB-style instructions\n");
-   printf("  --nv               emit NV-style instructions\n");
-   printf("  --link             run linker\n");
-   printf("  --debug            force #pragma debug(on)\n");
-   printf("  --nodebug          force #pragma debug(off)\n");
-   printf("  --opt              force #pragma optimize(on)\n");
-   printf("  --noopt            force #pragma optimize(off)\n");
-   printf("  --number, -n       emit line numbers (if --arb or --nv)\n");
-   printf("  --output, -o FILE  output filename\n");
-   printf("  --params           also emit program parameter info\n");
-   printf("  --help             display this information\n");
-}
-
-
-static void
-ParseOptions(int argc, char *argv[])
-{
-   int i;
-
-   Options.LineNumbers = GL_FALSE;
-   Options.Mode = PROG_PRINT_DEBUG;
-   Options.VertFile = NULL;
-   Options.FragFile = NULL;
-   Options.GeoFile = NULL;
-   Options.OutputFile = NULL;
-   Options.Params = GL_FALSE;
-   Options.Pragmas.IgnoreOptimize = GL_FALSE;
-   Options.Pragmas.IgnoreDebug = GL_FALSE;
-   Options.Pragmas.Debug = GL_FALSE;
-   Options.Pragmas.Optimize = GL_TRUE;
-
-   if (argc == 1) {
-      Usage();
-      exit(0);
-   }
-
-   for (i = 1; i < argc; i++) {
-      if (strcmp(argv[i], "--vs") == 0) {
-         Options.VertFile = argv[i + 1];
-         i++;
-      }
-      else if (strcmp(argv[i], "--fs") == 0) {
-         Options.FragFile = argv[i + 1];
-         i++;
-      }
-      else if (strcmp(argv[i], "--gs") == 0) {
-         Options.GeoFile = argv[i + 1];
-         i++;
-      }
-      else if (strcmp(argv[i], "--arb") == 0) {
-         Options.Mode = PROG_PRINT_ARB;
-      }
-      else if (strcmp(argv[i], "--nv") == 0) {
-         Options.Mode = PROG_PRINT_NV;
-      }
-      else if (strcmp(argv[i], "--link") == 0) {
-         Options.Link = GL_TRUE;
-      }
-      else if (strcmp(argv[i], "--debug") == 0) {
-         Options.Pragmas.IgnoreDebug = GL_TRUE;
-         Options.Pragmas.Debug = GL_TRUE;
-      }
-      else if (strcmp(argv[i], "--nodebug") == 0) {
-         Options.Pragmas.IgnoreDebug = GL_TRUE;
-         Options.Pragmas.Debug = GL_FALSE;
-      }
-      else if (strcmp(argv[i], "--opt") == 0) {
-         Options.Pragmas.IgnoreOptimize = GL_TRUE;
-         Options.Pragmas.Optimize = GL_TRUE;
-      }
-      else if (strcmp(argv[i], "--noopt") == 0) {
-         Options.Pragmas.IgnoreOptimize = GL_TRUE;
-         Options.Pragmas.Optimize = GL_FALSE;
-      }
-      else if (strcmp(argv[i], "--number") == 0 ||
-               strcmp(argv[i], "-n") == 0) {
-         Options.LineNumbers = GL_TRUE;
-      }
-      else if (strcmp(argv[i], "--output") == 0 ||
-               strcmp(argv[i], "-o") == 0) {
-         Options.OutputFile = argv[i + 1];
-         i++;
-      }
-      else if (strcmp(argv[i], "--params") == 0) {
-         Options.Params = GL_TRUE;
-      }
-      else if (strcmp(argv[i], "--help") == 0) {
-         Usage();
-         exit(0);
-      }
-      else {
-         printf("Unknown option: %s\n", argv[i]);
-         Usage();
-         exit(1);
-      }
-   }
-
-   if (Options.Mode == PROG_PRINT_DEBUG) {
-      /* always print line numbers when emitting debug-style output */
-      Options.LineNumbers = GL_TRUE;
-   }
-}
-
-
-int
-main(int argc, char *argv[])
-{
-   GLuint v_shader = 0, f_shader = 0, g_shader = 0;
-
-   ParseOptions(argc, argv);
-
-   if (!CreateContext()) {
-      fprintf(stderr, "%s: Failed to create compiler context\n", Prog);
-      exit(1);
-   }
-
-   if (Options.VertFile) {
-      v_shader = CompileShader(Options.VertFile, GL_VERTEX_SHADER);
-   }
-
-   if (Options.FragFile) {
-      f_shader = CompileShader(Options.FragFile, GL_FRAGMENT_SHADER);
-   }
-
-   if (Options.GeoFile) {
-      g_shader = CompileShader(Options.GeoFile, GL_GEOMETRY_SHADER_ARB);
-   }
-
-
-   if (v_shader || f_shader || g_shader) {
-      if (Options.OutputFile) {
-         FILE *f;
-         fclose(stdout);
-         /*stdout =*/ f = freopen(Options.OutputFile, "w", stdout);
-         if (!f) {
-            fprintf(stderr, "freopen error\n");
-         }
-      }
-      if (stdout && v_shader) {
-         PrintShaderInstructions(v_shader, stdout);
-      }
-      if (stdout && f_shader) {
-         PrintShaderInstructions(f_shader, stdout);
-      }
-      if (stdout && g_shader) {
-         PrintShaderInstructions(g_shader, stdout);
-      }
-      if (Options.OutputFile) {
-         fclose(stdout);
-      }
-   }
-
-   if (Options.Link) {
-      if (!v_shader || !f_shader) {
-         fprintf(stderr,
-                 "--link option requires both a vertex and fragment shader.\n");
-         exit(1);
-      }
-
-      CheckLink(v_shader, f_shader);
-   }
-
-   return 0;
-}
index c6b4a040851b45149e57930d60c3732fd7699256..39ab09af805bf4c79804c2471b4b9f78f31a7fe4 100644 (file)
@@ -23,8 +23,7 @@ INCLUDE_DIRS = \
 CORE_MESA = \
        $(TOP)/src/mesa/libmesa.a \
        $(TOP)/src/mapi/glapi/libglapi.a \
-       $(TOP)/src/glsl/cl/libglslcl.a \
-       $(TOP)/src/glsl/pp/libglslpp.a
+       $(TOP)/src/glsl/libglsl.a
 
 .c.o:
        $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
@@ -37,9 +36,9 @@ default: $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_NAME)
 # sources. We can also build libOSMesa16/libOSMesa32 by setting
 # -DCHAN_BITS=16/32.
 $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_NAME): $(OBJECTS) $(CORE_MESA)
-       $(MKLIB) -o $(OSMESA_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
+       $(MKLIB) -o $(OSMESA_LIB) -linker '$(CXX)' -ldflags '$(LDFLAGS)' \
                -major $(MESA_MAJOR) -minor $(MESA_MINOR) -patch $(MESA_TINY) \
-               -install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \
+               -install $(TOP)/$(LIB_DIR) -cplusplus $(MKLIB_OPTIONS) \
                -id $(INSTALL_LIB_DIR)/lib$(OSMESA_LIB).$(MESA_MAJOR).dylib \
                $(OSMESA_LIB_DEPS) $(OBJECTS) $(CORE_MESA)
 
index b5b0c1f11a872af629996f1ac23a3e59accd0254..f759da0a9795d4702d5cc72b61328fe625a106d9 100644 (file)
@@ -57,9 +57,10 @@ default: $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME)
 
 
 $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME): $(OBJECTS) $(CORE_MESA)
-       @ $(MKLIB) -o $(GL_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
+       @ $(MKLIB) -o $(GL_LIB) -linker '$(CXX)' -ldflags '$(LDFLAGS)' \
                -major $(GL_MAJOR) -minor $(GL_MINOR) -patch $(GL_TINY) \
-               -install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \
+               -install $(TOP)/$(LIB_DIR) \
+               -cplusplus $(MKLIB_OPTIONS) \
                -id $(INSTALL_LIB_DIR)/lib$(GL_LIB).$(GL_MAJOR).dylib \
                $(GL_LIB_DEPS) $(OBJECTS) $(CORE_MESA)
 
index 63740f07edca68f0c9bf300201a8858aac03dcbd..c2b74b23cb404d229173d946acc0f86f03baa33a 100644 (file)
@@ -55,6 +55,8 @@ _mesa_init_accum_dispatch(struct _glapi_table *disp);
 
 #else /* FEATURE_accum */
 
+#include "main/compiler.h"
+
 #define _MESA_INIT_ACCUM_FUNCTIONS(driver, impl) do { } while (0)
 
 static INLINE void
index 6b48a17663030866d5321cd4a5f90c8384576fc2..83b28a65b77380ee6f296feaaf2e3a971e53df67 100644 (file)
@@ -48,6 +48,8 @@ _mesa_init_attrib_dispatch(struct _glapi_table *disp);
 
 #else /* FEATURE_attrib_stack */
 
+#include "main/compiler.h"
+
 static INLINE void
 _mesa_PushClientAttrib( GLbitfield mask )
 {
index 4e232b5731f6fca2283b61c717af494e8b0e3193..4797f29b4dc96c4220cb940e5f12f8f27a259f01 100644 (file)
@@ -590,7 +590,7 @@ bind_buffer_object(GLcontext *ctx, GLenum target, GLuint buffer)
 
    bindTarget = get_buffer_target(ctx, target);
    if (!bindTarget) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target 0x%x)");
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target 0x%x)", target);
       return;
    }
 
@@ -1553,27 +1553,27 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
 
    if (readOffset < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glCopyBuffserSubData(readOffset = %d)", readOffset);
+                  "glCopyBuffserSubData(readOffset = %d)", (int) readOffset);
       return;
    }
 
    if (writeOffset < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glCopyBuffserSubData(writeOffset = %d)", writeOffset);
+                  "glCopyBuffserSubData(writeOffset = %d)", (int) writeOffset);
       return;
    }
 
    if (readOffset + size > src->Size) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "glCopyBuffserSubData(readOffset + size = %d)",
-                  readOffset, size);
+                  (int) (readOffset + size));
       return;
    }
 
    if (writeOffset + size > dst->Size) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "glCopyBuffserSubData(writeOffset + size = %d)",
-                  writeOffset, size);
+                  (int) (writeOffset + size));
       return;
    }
 
@@ -1617,13 +1617,13 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
 
    if (offset < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glMapBufferRange(offset = %ld)", offset);
+                  "glMapBufferRange(offset = %ld)", (long)offset);
       return NULL;
    }
 
    if (length < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glMapBufferRange(length = %ld)", length);
+                  "glMapBufferRange(length = %ld)", (long)length);
       return NULL;
    }
 
@@ -1708,13 +1708,13 @@ _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
 
    if (offset < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glMapBufferRange(offset = %ld)", offset);
+                  "glMapBufferRange(offset = %ld)", (long)offset);
       return;
    }
 
    if (length < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glMapBufferRange(length = %ld)", length);
+                  "glMapBufferRange(length = %ld)", (long)length);
       return;
    }
 
@@ -1746,8 +1746,8 @@ _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
 
    if (offset + length > bufObj->Length) {
       _mesa_error(ctx, GL_INVALID_VALUE,
-             "glMapBufferRange(offset %ld + length %ld > mapped length %ld)",
-             offset, length, bufObj->Length);
+                 "glMapBufferRange(offset %ld + length %ld > mapped length %ld)",
+                 (long)offset, (long)length, (long)bufObj->Length);
       return;
    }
 
index 652fb5824631c6ca6984f2ff7da9144d1b262ee5..744f092d9348001eb6a1c4b9cfce2614066894de 100644 (file)
@@ -53,6 +53,8 @@ _mesa_init_colortable_dispatch(struct _glapi_table *disp);
 
 #else /* FEATURE_colortable */
 
+#include "main/compiler.h"
+
 #define _MESA_INIT_COLORTABLE_FUNCTIONS(driver, impl) do { } while (0)
 
 static INLINE void GLAPIENTRY
index e0507ccf8643dfc029836f61e7095787f06f1b5d..ded69c3106ca00b3bac2211d06c3d7c3b79812cd 100644 (file)
@@ -316,6 +316,11 @@ static INLINE GLuint CPU_TO_LE32(GLuint x)
 #endif
 #endif
 
+#if (__GNUC__ >= 3)
+#define PRINTFLIKE(f, a) __attribute__ ((format(__printf__, f, a)))
+#else
+#define PRINTFLIKE(f, a)
+#endif
 
 #ifndef NULL
 #define NULL 0
index b01fed1781ec97a0a6ab351c97d74b98896c6914..8e34ec4124f9bb4f8363286a715f51aa01ba6fb0 100644 (file)
 #include "sparc/sparc.h"
 #endif
 
+#include "glsl_parser_extras.h"
+
+
+
 #ifndef MESA_VERBOSE
 int MESA_VERBOSE = 0;
 #endif
@@ -339,16 +343,16 @@ _mesa_destroy_visual( GLvisual *vis )
 static void
 dummy_enum_func(void)
 {
-   gl_buffer_index bi;
-   gl_colortable_index ci;
-   gl_face_index fi;
-   gl_frag_attrib fa;
-   gl_frag_result fr;
-   gl_texture_index ti;
-   gl_vert_attrib va;
-   gl_vert_result vr;
-   gl_geom_attrib ga;
-   gl_geom_result gr;
+   gl_buffer_index bi = BUFFER_FRONT_LEFT;
+   gl_colortable_index ci = COLORTABLE_PRECONVOLUTION;
+   gl_face_index fi = FACE_POS_X;
+   gl_frag_attrib fa = FRAG_ATTRIB_WPOS;
+   gl_frag_result fr = FRAG_RESULT_DEPTH;
+   gl_texture_index ti = TEXTURE_2D_ARRAY_INDEX;
+   gl_vert_attrib va = VERT_ATTRIB_POS;
+   gl_vert_result vr = VERT_RESULT_HPOS;
+   gl_geom_attrib ga = GEOM_ATTRIB_POSITION;
+   gl_geom_result gr = GEOM_RESULT_POS;
 
    (void) bi;
    (void) ci;
@@ -434,6 +438,11 @@ one_time_init( GLcontext *ctx )
    }
    _glthread_UNLOCK_MUTEX(OneTimeLock);
 
+   /* Hopefully atexit() is widely available.  If not, we may need some
+    * #ifdef tests here.
+    */
+   atexit(_mesa_destroy_shader_compiler);
+
    dummy_enum_func();
 }
 
@@ -1695,7 +1704,7 @@ _mesa_valid_to_render(GLcontext *ctx, const char *where)
       /* using shaders */
       if (!ctx->Shader.CurrentProgram->LinkStatus) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "%s(shader not linked), where");
+                     "%s(shader not linked)", where);
          return GL_FALSE;
       }
 #if 0 /* not normally enabled */
index 59492bc7c54b1a82807a8f52fa52050249804213..d1401885df43c1e7b9462947a4404497822e9023 100644 (file)
@@ -70,6 +70,8 @@ _mesa_init_convolve_dispatch(struct _glapi_table *disp);
 
 #else /* FEATURE_convolve */
 
+#include "main/compiler.h"
+
 #define _MESA_INIT_CONVOLVE_FUNCTIONS(driver, impl) do { } while (0)
 
 static INLINE void GLAPIENTRY
diff --git a/src/mesa/main/core.h b/src/mesa/main/core.h
new file mode 100644 (file)
index 0000000..ea6e6bf
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * 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:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+
+/**
+ * \file core.h
+ * The public header of core mesa.
+ *
+ * This file is the (only) public header of core mesa.  It is supposed to be
+ * used by GLX, WGL, and GLSL.  It is important that headers directly or
+ * indirectly included here do not perform feature tests (#if FEATURE_xxx).
+ */
+
+
+#ifndef CORE_H
+#define CORE_H
+
+
+#include "main/glheader.h"
+#include "main/compiler.h"
+#include "main/imports.h"
+#include "main/macros.h"
+
+#include "main/version.h" /* for MESA_VERSION_STRING */
+#include "main/context.h" /* for _mesa_share_state */
+#include "main/mtypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* for GLSL */
+#include "program/prog_parameter.h"
+#include "program/prog_uniform.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* CORE_H */
index 825073ca886cd0c068f8344285ee9d7416e8a177..8a20a6636324922990fde4d7dabd9897125e4a0b 100644 (file)
@@ -36,7 +36,7 @@
 struct gl_pixelstore_attrib;
 struct gl_display_list;
 
-#if FEATURE_ARB_vertex_buffer_object
+/* GL_ARB_vertex_buffer_object */
 /* Modifies GL_MAP_UNSYNCHRONIZED_BIT to allow driver to fail (return
  * NULL) if buffer is unavailable for immediate mapping.
  *
@@ -49,7 +49,6 @@ struct gl_display_list;
  * respect the contents of already referenced data.
  */
 #define MESA_MAP_NOWAIT_BIT       0x0040
-#endif
 
 
 /**
@@ -595,6 +594,27 @@ struct dd_function_table {
    
    /*@}*/
 
+   /**
+    * \name GLSL shader/program functions.
+    */
+   /*@{*/
+   /**
+    * Called when a shader is compiled.
+    *
+    * Note that not all shader objects get ShaderCompile called on
+    * them.  Notably, the shaders containing builtin functions do not
+    * have CompileShader() called, so if lowering passes are done they
+    * need to also be performed in LinkShader().
+    */
+   GLboolean (*CompileShader)(GLcontext *ctx, struct gl_shader *shader);
+   /**
+    * Called when a shader program is linked.
+    *
+    * This gives drivers an opportunity to clone the IR and make their
+    * own transformations on it for the purposes of code generation.
+    */
+   GLboolean (*LinkShader)(GLcontext *ctx, struct gl_shader_program *shader);
+   /*@}*/
 
    /**
     * \name State-changing functions.
@@ -709,7 +729,6 @@ struct dd_function_table {
    /**
     * \name Vertex/pixel buffer object functions
     */
-#if FEATURE_ARB_vertex_buffer_object
    /*@{*/
    void (*BindBuffer)( GLcontext *ctx, GLenum target,
                       struct gl_buffer_object *obj );
@@ -753,12 +772,10 @@ struct dd_function_table {
    GLboolean (*UnmapBuffer)( GLcontext *ctx, GLenum target,
                             struct gl_buffer_object *obj );
    /*@}*/
-#endif
 
    /**
     * \name Functions for GL_APPLE_object_purgeable
     */
-#if FEATURE_APPLE_object_purgeable
    /*@{*/
    /* variations on ObjectPurgeable */
    GLenum (*BufferObjectPurgeable)( GLcontext *ctx, struct gl_buffer_object *obj, GLenum option );
@@ -770,12 +787,10 @@ struct dd_function_table {
    GLenum (*RenderObjectUnpurgeable)( GLcontext *ctx, struct gl_renderbuffer *obj, GLenum option );
    GLenum (*TextureObjectUnpurgeable)( GLcontext *ctx, struct gl_texture_object *obj, GLenum option );
    /*@}*/
-#endif
 
    /**
-    * \name Functions for GL_EXT_framebuffer_object
+    * \name Functions for GL_EXT_framebuffer_{object,blit}.
     */
-#if FEATURE_EXT_framebuffer_object
    /*@{*/
    struct gl_framebuffer * (*NewFramebuffer)(GLcontext *ctx, GLuint name);
    struct gl_renderbuffer * (*NewRenderbuffer)(GLcontext *ctx, GLuint name);
@@ -794,13 +809,10 @@ struct dd_function_table {
    void (*ValidateFramebuffer)(GLcontext *ctx,
                                struct gl_framebuffer *fb);
    /*@}*/
-#endif
-#if FEATURE_EXT_framebuffer_blit
    void (*BlitFramebuffer)(GLcontext *ctx,
                            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                            GLbitfield mask, GLenum filter);
-#endif
 
    /**
     * \name Query objects
@@ -955,7 +967,6 @@ struct dd_function_table {
    void (*EndCallList)( GLcontext *ctx );
 
 
-#if FEATURE_ARB_sync
    /**
     * \name GL_ARB_sync interfaces
     */
@@ -969,14 +980,12 @@ struct dd_function_table {
    void (*ServerWaitSync)(GLcontext *, struct gl_sync_object *,
                          GLbitfield, GLuint64);
    /*@}*/
-#endif
 
    /** GL_NV_conditional_render */
    void (*BeginConditionalRender)(GLcontext *ctx, struct gl_query_object *q,
                                   GLenum mode);
    void (*EndConditionalRender)(GLcontext *ctx, struct gl_query_object *q);
 
-#if FEATURE_OES_draw_texture
    /**
     * \name GL_OES_draw_texture interface
     */
@@ -984,9 +993,10 @@ struct dd_function_table {
    void (*DrawTex)(GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z,
                    GLfloat width, GLfloat height);
    /*@}*/
-#endif
 
-#if FEATURE_OES_EGL_image
+   /**
+    * \name GL_OES_EGL_image interface
+    */
    void (*EGLImageTargetTexture2D)(GLcontext *ctx, GLenum target,
                                   struct gl_texture_object *texObj,
                                   struct gl_texture_image *texImage,
@@ -994,9 +1004,10 @@ struct dd_function_table {
    void (*EGLImageTargetRenderbufferStorage)(GLcontext *ctx,
                                             struct gl_renderbuffer *rb,
                                             void *image_handle);
-#endif
 
-#if FEATURE_EXT_transform_feedback
+   /**
+    * \name GL_EXT_transform_feedback interface
+    */
    struct gl_transform_feedback_object *
         (*NewTransformFeedback)(GLcontext *ctx, GLuint name);
    void (*DeleteTransformFeedback)(GLcontext *ctx,
@@ -1011,7 +1022,6 @@ struct dd_function_table {
                                    struct gl_transform_feedback_object *obj);
    void (*DrawTransformFeedback)(GLcontext *ctx, GLenum mode,
                                  struct gl_transform_feedback_object *obj);
-#endif
 };
 
 
@@ -1094,7 +1104,7 @@ typedef struct {
    void (GLAPIENTRYP VertexAttrib3fvNV)( GLuint index, const GLfloat *v );
    void (GLAPIENTRYP VertexAttrib4fNV)( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w );
    void (GLAPIENTRYP VertexAttrib4fvNV)( GLuint index, const GLfloat *v );
-#if FEATURE_ARB_vertex_program
+   /* GL_ARB_vertex_program */
    void (GLAPIENTRYP VertexAttrib1fARB)( GLuint index, GLfloat x );
    void (GLAPIENTRYP VertexAttrib1fvARB)( GLuint index, const GLfloat *v );
    void (GLAPIENTRYP VertexAttrib2fARB)( GLuint index, GLfloat x, GLfloat y );
@@ -1103,7 +1113,6 @@ typedef struct {
    void (GLAPIENTRYP VertexAttrib3fvARB)( GLuint index, const GLfloat *v );
    void (GLAPIENTRYP VertexAttrib4fARB)( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w );
    void (GLAPIENTRYP VertexAttrib4fvARB)( GLuint index, const GLfloat *v );
-#endif
    /*@}*/
 
    void (GLAPIENTRYP Rectf)( GLfloat, GLfloat, GLfloat, GLfloat );
index 885e718a767872687c3d586cb65f4f985d12c1fe..dbaa841645717911d585237617fbd57e2061b097 100644 (file)
@@ -359,7 +359,7 @@ _mesa_new_z24_renderbuffer_wrapper(GLcontext *ctx,
           dsrb->Format == MESA_FORMAT_X8_Z24);
    ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
 
-   z24rb = _mesa_new_renderbuffer(ctx, 0);
+   z24rb = ctx->Driver.NewRenderbuffer(ctx, 0);
    if (!z24rb)
       return NULL;
 
@@ -645,7 +645,7 @@ _mesa_new_s8_renderbuffer_wrapper(GLcontext *ctx, struct gl_renderbuffer *dsrb)
           dsrb->Format == MESA_FORMAT_S8_Z24);
    ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
 
-   s8rb = _mesa_new_renderbuffer(ctx, 0);
+   s8rb = ctx->Driver.NewRenderbuffer(ctx, 0);
    if (!s8rb)
       return NULL;
 
index 727414d529f83bd8fa37c95f6cff2c7eddbfe26d..5042e14a540a335b1d8d49809be6243bdd864d35 100644 (file)
@@ -6070,8 +6070,15 @@ exec_GetAttribLocationARB(GLuint program, const GLchar *name)
    FLUSH_VERTICES(ctx, 0);
    return CALL_GetAttribLocationARB(ctx->Exec, (program, name));
 }
-/* XXX more shader functions needed here */
 
+static GLint GLAPIENTRY
+exec_GetUniformLocationARB(GLuint program, const GLchar *name)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   FLUSH_VERTICES(ctx, 0);
+   return CALL_GetUniformLocationARB(ctx->Exec, (program, name));
+}
+/* XXX more shader functions needed here */
 
 
 #if FEATURE_EXT_framebuffer_blit
@@ -9491,6 +9498,7 @@ _mesa_create_save_table(void)
    /* ARB 30/31/32. GL_ARB_shader_objects, GL_ARB_vertex/fragment_shader */
    SET_BindAttribLocationARB(table, exec_BindAttribLocationARB);
    SET_GetAttribLocationARB(table, exec_GetAttribLocationARB);
+   SET_GetUniformLocationARB(table, exec_GetUniformLocationARB);
    /* XXX additional functions need to be implemented here! */
 
    /* 299. GL_EXT_blend_equation_separate */
index f8255facc5e6f7be818919ce46c79d2245e1f4c8..d3f5c5cb4e50c1b86818f34ecac2366a1c8bb8fc 100644 (file)
@@ -81,6 +81,8 @@ extern void _mesa_init_dlist_dispatch(struct _glapi_table *disp);
 
 #else /* FEATURE_dlist */
 
+#include "main/compiler.h"
+
 #define _MESA_INIT_DLIST_FUNCTIONS(driver, impl) do { } while (0)
 #define _MESA_INIT_DLIST_VTXFMT(vfmt, impl) do { } while (0)
 
index 9a8f5a6f5e01f1d4b63f3d7478b679be0480b991..ecb34bb5cdf0f1783fc018f87496f2eb4a787705 100644 (file)
@@ -215,6 +215,10 @@ extern void _mesa_error(void *ctx, GLenum error, const char *fmtString, ... );
 #ifdef IN_DRI_DRIVER
 #define _GLAPI_USE_REMAP_TABLE
 #endif
+/* glapi uses GLAPIENTRY while GLES headers define GL_APIENTRY */
+#ifndef GLAPIENTRY
+#define GLAPIENTRY GL_APIENTRY
+#endif
 #include "%sapi/glapi/glapitable.h"
 #include "%sapi/glapi/glapioffsets.h"
 #include "%sapi/glapi/glapidispatch.h"
@@ -603,13 +607,15 @@ for funcName in keys:
     # are complete; remove the extra ", " at the front of each.
     passthroughDeclarationString = passthroughDeclarationString[2:]
     passthroughCallString = passthroughCallString[2:]
+    if not passthroughDeclarationString:
+        passthroughDeclarationString = "void"
 
     # The Mesa functions are scattered across all the Mesa
     # header files.  The easiest way to manage declarations
     # is to create them ourselves.
     if funcName in allSpecials:
         print "/* this function is special and is defined elsewhere */"
-    print "extern %s GLAPIENTRY %s(%s);" % (returnType, passthroughFuncName, passthroughDeclarationString)
+    print "extern %s GL_APIENTRY %s(%s);" % (returnType, passthroughFuncName, passthroughDeclarationString)
 
     # A function may be a core function (i.e. it exists in
     # the core specification), a core addition (extension
@@ -662,7 +668,7 @@ for funcName in keys:
             print
             continue
 
-        print "static %s %s(%s)" % (returnType, fullFuncName, declarationString)
+        print "static %s GL_APIENTRY %s(%s)" % (returnType, fullFuncName, declarationString)
         print "{"
 
         # Start printing our code pieces.  Start with any local
index 19a1eebe6e9e6903be8cff3273b1083277cd1f8f..c9862ca29e640050e6567c0adb98ea05d4a4c64f 100644 (file)
@@ -969,7 +969,7 @@ _mesa_get_extension_count(GLcontext *ctx)
 
    if (0)
       _mesa_debug(ctx, "%u of %d extensions enabled\n", ctx->Extensions.Count,
-                  Elements(default_extensions));
+                  (int) Elements(default_extensions));
 
    return ctx->Extensions.Count;
 }
index 9a84e5a79cff835aa3f14fd8c680f1d8decd3ddb..f80dd8599362ade9cc3dc46ec40ee71b8b5e93f0 100644 (file)
@@ -93,6 +93,8 @@ delete_dummy_framebuffer(struct gl_framebuffer *fb)
 void
 _mesa_init_fbobjects(GLcontext *ctx)
 {
+   _glthread_INIT_MUTEX(DummyFramebuffer.Mutex);
+   _glthread_INIT_MUTEX(DummyRenderbuffer.Mutex);
    DummyFramebuffer.Delete = delete_dummy_framebuffer;
    DummyRenderbuffer.Delete = delete_dummy_renderbuffer;
 }
index 3e8283ed23faac6a942b70a90ef529db3e1393ca..0762930044d62c9eccc3a13e45ef769587d57e42 100644 (file)
@@ -63,6 +63,8 @@ _mesa_init_feedback_dispatch(struct _glapi_table *disp);
 
 #else /* FEATURE_feedback */
 
+#include "main/compiler.h"
+
 #define _MESA_INIT_FEEDBACK_FUNCTIONS(driver, impl) do { } while (0)
 
 static INLINE void
index 90449cc04f083ea571b453f348e614771e5415e3..112d7a00883e78368c35d38adeaadc50a609d992 100644 (file)
@@ -939,6 +939,18 @@ _mesa_is_format_compressed(gl_format format)
 }
 
 
+/**
+ * Determine if the given format represents a packed depth/stencil buffer.
+ */
+GLboolean
+_mesa_is_format_packed_depth_stencil(gl_format format)
+{
+   const struct gl_format_info *info = _mesa_get_format_info(format);
+
+   return info->BaseFormat == GL_DEPTH_STENCIL;
+}
+
+
 /**
  * Return color encoding for given format.
  * \return GL_LINEAR or GL_SRGB
index ad176caaa0fd59ea316f5b6d05abd80c05bfa092..e9467f486bffe8d4ffa8f276e1bf53c9db48e0d9 100644 (file)
@@ -190,6 +190,9 @@ _mesa_get_format_block_size(gl_format format, GLuint *bw, GLuint *bh);
 extern GLboolean
 _mesa_is_format_compressed(gl_format format);
 
+extern GLboolean
+_mesa_is_format_packed_depth_stencil(gl_format format);
+
 extern GLenum
 _mesa_get_format_color_encoding(gl_format format);
 
index e0aac26f62b692e122c9d2d8800cf121b821242c..a98c09cfbf3411d8c762ac644f20714fc62ce394 100644 (file)
@@ -611,7 +611,7 @@ _mesa_update_depth_buffer(GLcontext *ctx,
 
    depthRb = fb->Attachment[attIndex].Renderbuffer;
 
-   if (depthRb && depthRb->_BaseFormat == GL_DEPTH_STENCIL) {
+   if (depthRb && _mesa_is_format_packed_depth_stencil(depthRb->Format)) {
       /* The attached depth buffer is a GL_DEPTH_STENCIL renderbuffer */
       if (!fb->_DepthBuffer
           || fb->_DepthBuffer->Wrapped != depthRb
@@ -652,7 +652,7 @@ _mesa_update_stencil_buffer(GLcontext *ctx,
 
    stencilRb = fb->Attachment[attIndex].Renderbuffer;
 
-   if (stencilRb && stencilRb->_BaseFormat == GL_DEPTH_STENCIL) {
+   if (stencilRb && _mesa_is_format_packed_depth_stencil(stencilRb->Format)) {
       /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */
       if (!fb->_StencilBuffer
           || fb->_StencilBuffer->Wrapped != stencilRb
index 632dadd1a5d5f419096d0907cd8c542f6d7594f0..a3cb5ec168ff78d0fa43557440c2ec60831826d8 100644 (file)
@@ -1661,16 +1661,22 @@ check_extra(GLcontext *ctx, const char *func, const struct value_desc *d)
    for (e = d->extra; *e != EXTRA_END; e++)
       switch (*e) {
       case EXTRA_VERSION_30:
-        if (version < 30)
-           return GL_FALSE;
+        if (version >= 30) {
+           total++;
+           enabled++;
+        }
         break;
       case EXTRA_VERSION_31:
-        if (version < 31)
-           return GL_FALSE;
+        if (version >= 31) {
+           total++;
+           enabled++;
+        }
         break;
       case EXTRA_VERSION_32:
-        if (version < 32)
-           return GL_FALSE;
+        if (version >= 32) {
+           total++;
+           enabled++;
+        }
         break;
       case EXTRA_NEW_BUFFERS:
         if (ctx->NewState & _NEW_BUFFERS)
index 7961ad7e7dd048774cc84baaf3a7f9a1f2ed4198..5e4fcd599c39c7fbe230303de2d1da5f353e0c31 100644 (file)
@@ -31,7 +31,7 @@
 #include "extensions.h"
 
 static const GLubyte *
-shading_laguage_version(GLcontext *ctx)
+shading_language_version(GLcontext *ctx)
 {
    switch (ctx->API) {
 #if FEATURE_ARB_shading_language_100
@@ -98,7 +98,7 @@ _mesa_GetString( GLenum name )
          return (const GLubyte *) ctx->Extensions.String;
 #if FEATURE_ARB_shading_language_100 || FEATURE_ES2
       case GL_SHADING_LANGUAGE_VERSION:
-        return shading_laguage_version(ctx);
+        return shading_language_version(ctx);
 #endif
 #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program || \
     FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
index 9c2ffd66d69908dc74ce0b19c520e448ee684c77..751f2065011ea986a01d74c0fac300285be1ff49 100644 (file)
@@ -116,6 +116,42 @@ typedef union { GLfloat f; GLint i; } fi_type;
 #endif
 
 
+/**
+ * \name Work-arounds for platforms that lack C99 math functions
+ */
+/*@{*/
+#if (!defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE < 600)) && !defined(_ISOC99_SOURCE) \
+   && (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)) \
+   && (!defined(_MSC_VER) || (_MSC_VER < 1400))
+#define acosf(f) ((float) acos(f))
+#define asinf(f) ((float) asin(f))
+#define atan2f(x,y) ((float) atan2(x,y))
+#define atanf(f) ((float) atan(f))
+#define cielf(f) ((float) ciel(f))
+#define cosf(f) ((float) cos(f))
+#define coshf(f) ((float) cosh(f))
+#define expf(f) ((float) exp(f))
+#define exp2f(f) ((float) exp2(f))
+#define floorf(f) ((float) floor(f))
+#define logf(f) ((float) log(f))
+#define log2f(f) ((float) log2(f))
+#define powf(x,y) ((float) pow(x,y))
+#define sinf(f) ((float) sin(f))
+#define sinhf(f) ((float) sinh(f))
+#define sqrtf(f) ((float) sqrt(f))
+#define tanf(f) ((float) tan(f))
+#define tanhf(f) ((float) tanh(f))
+#endif
+
+#if defined(_MSC_VER)
+static INLINE float truncf(float x) { return x < 0.0f ? ceilf(x) : floorf(x); }
+static INLINE float exp2f(float x) { return powf(2.0f, x); }
+static INLINE float log2f(float x) { return logf(x) * 1.442695041f; }
+static INLINE int isblank(int ch) { return ch == ' ' || ch == '\t'; }
+#define strtoll(p, e, b) _strtoi64(p, e, b)
+#endif
+/*@}*/
+
 /***
  *** LOG2: Log base 2 of float
  ***/
@@ -530,19 +566,25 @@ extern unsigned int
 _mesa_str_checksum(const char *str);
 
 extern int
-_mesa_snprintf( char *str, size_t size, const char *fmt, ... );
+_mesa_snprintf( char *str, size_t size, const char *fmt, ... ) PRINTFLIKE(3, 4);
 
 extern void
-_mesa_warning( __GLcontext *gc, const char *fmtString, ... );
+_mesa_warning( __GLcontext *gc, const char *fmtString, ... ) PRINTFLIKE(2, 3);
 
 extern void
-_mesa_problem( const __GLcontext *ctx, const char *fmtString, ... );
+_mesa_problem( const __GLcontext *ctx, const char *fmtString, ... ) PRINTFLIKE(2, 3);
 
 extern void
-_mesa_error( __GLcontext *ctx, GLenum error, const char *fmtString, ... );
+_mesa_error( __GLcontext *ctx, GLenum error, const char *fmtString, ... ) PRINTFLIKE(3, 4);
 
 extern void
-_mesa_debug( const __GLcontext *ctx, const char *fmtString, ... );
+_mesa_debug( const __GLcontext *ctx, const char *fmtString, ... ) PRINTFLIKE(2, 3);
+
+
+#if defined(_MSC_VER) && !defined(snprintf)
+#define snprintf _snprintf
+#endif
+
 
 #ifdef __cplusplus
 }
index c0c29f78893875e6152183e74f382b3baea6bc76..678d17a2a3654b84ecec4c6b53a6b0c060546ebb 100644 (file)
@@ -1005,21 +1005,28 @@ make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
    const GLint dstRowBytes = bpt * dstRowStride;
    const GLubyte *srcA, *srcB;
    GLubyte *dst;
-   GLint row;
+   GLint row, srcRowStep;
 
    /* Compute src and dst pointers, skipping any border */
    srcA = srcPtr + border * ((srcWidth + 1) * bpt);
-   if (srcHeight > 1) 
+   if (srcHeight > 1 && srcHeight > dstHeight) {
+      /* sample from two source rows */
       srcB = srcA + srcRowBytes;
-   else
+      srcRowStep = 2;
+   }
+   else {
+      /* sample from one source row */
       srcB = srcA;
+      srcRowStep = 1;
+   }
+
    dst = dstPtr + border * ((dstWidth + 1) * bpt);
 
    for (row = 0; row < dstHeightNB; row++) {
       do_row(datatype, comps, srcWidthNB, srcA, srcB,
              dstWidthNB, dst);
-      srcA += 2 * srcRowBytes;
-      srcB += 2 * srcRowBytes;
+      srcA += srcRowStep * srcRowBytes;
+      srcB += srcRowStep * srcRowBytes;
       dst += dstRowBytes;
    }
 
index 8d92892ad7d41980131c03117c8fe403a672065b..d44eff69cceb2ad18439a4bde2d99d7007d21004 100644 (file)
@@ -1632,10 +1632,9 @@ struct gl_array_attrib
 
    GLbitfield NewState;                /**< mask of _NEW_ARRAY_* values */
 
-#if FEATURE_ARB_vertex_buffer_object
+   /* GL_ARB_vertex_buffer_object */
    struct gl_buffer_object *ArrayBufferObj;
    struct gl_buffer_object *ElementArrayBufferObj;
-#endif
 };
 
 
@@ -2084,6 +2083,15 @@ struct gl_shader
    struct gl_program *Program;  /**< Post-compile assembly code */
    GLchar *InfoLog;
    struct gl_sl_pragmas Pragmas;
+
+   unsigned Version;       /**< GLSL version used for linking */
+
+   struct exec_list *ir;
+   struct glsl_symbol_table *symbols;
+
+   /** Shaders containing built-in functions that are used for linking. */
+   struct gl_shader *builtins_to_link[16];
+   unsigned num_builtins_to_link;
 };
 
 
@@ -2129,6 +2137,16 @@ struct gl_shader_program
    GLboolean Validated;
    GLboolean _Used;        /**< Ever used for drawing? */
    GLchar *InfoLog;
+
+   unsigned Version;       /**< GLSL version used for linking */
+
+   /**
+    * Per-stage shaders resulting from the first stage of linking.
+    */
+   /*@{*/
+   GLuint _NumLinkedShaders;
+   struct gl_shader *_LinkedShaders[2];
+   /*@}*/
 };   
 
 
@@ -2154,6 +2172,11 @@ struct gl_shader_state
    GLboolean EmitCondCodes;             /**< Use condition codes? */
    GLboolean EmitComments;              /**< Annotated instructions */
    GLboolean EmitNVTempInitialization;  /**< 0-fill NV temp registers */
+   /**
+    * Attempts to flatten all ir_if (OPCODE_IF) for GPUs that can't
+    * support control flow.
+    */
+   GLboolean EmitNoIfs;
    void *MemPool;
    GLbitfield Flags;                    /**< Mask of GLSL_x flags */
    struct gl_sl_pragmas DefaultPragmas; /**< Default #pragma settings */
@@ -2240,39 +2263,26 @@ struct gl_shared_state
     */
    /*@{*/
    struct _mesa_HashTable *Programs; /**< All vertex/fragment programs */
-#if FEATURE_ARB_vertex_program
    struct gl_vertex_program *DefaultVertexProgram;
-#endif
-#if FEATURE_ARB_fragment_program
    struct gl_fragment_program *DefaultFragmentProgram;
-#endif
-#if FEATURE_ARB_geometry_shader4
    struct gl_geometry_program *DefaultGeometryProgram;
-#endif
    /*@}*/
 
-#if FEATURE_ATI_fragment_shader
+   /* GL_ATI_fragment_shader */
    struct _mesa_HashTable *ATIShaders;
    struct ati_fragment_shader *DefaultFragmentShader;
-#endif
 
-#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object
    struct _mesa_HashTable *BufferObjects;
-#endif
 
-#if FEATURE_ARB_shader_objects
    /** Table of both gl_shader and gl_shader_program objects */
    struct _mesa_HashTable *ShaderObjects;
-#endif
 
-#if FEATURE_EXT_framebuffer_object
+   /* GL_EXT_framebuffer_object */
    struct _mesa_HashTable *RenderBuffers;
    struct _mesa_HashTable *FrameBuffers;
-#endif
 
-#if FEATURE_ARB_sync
+   /* GL_ARB_sync */
    struct simple_node SyncObjects;
-#endif
 
    void *DriverData;  /**< Device driver shared state */
 };
@@ -2507,14 +2517,13 @@ struct gl_program_constants
    GLuint MaxNativeParameters;
    /* For shaders */
    GLuint MaxUniformComponents;
-#if FEATURE_ARB_geometry_shader4
+   /* GL_ARB_geometry_shader4 */
    GLuint MaxGeometryTextureImageUnits;
    GLuint MaxGeometryVaryingComponents;
    GLuint MaxVertexVaryingComponents;
    GLuint MaxGeometryUniformComponents;
    GLuint MaxGeometryOutputVertices;
    GLuint MaxGeometryTotalOutputComponents;
-#endif
 };
 
 
@@ -2762,12 +2771,8 @@ struct gl_extensions
    GLboolean SGIS_texture_lod;
    GLboolean TDFX_texture_compression_FXT1;
    GLboolean S3_s3tc;
-#if FEATURE_OES_EGL_image
    GLboolean OES_EGL_image;
-#endif
-#if FEATURE_OES_draw_texture
    GLboolean OES_draw_texture;
-#endif /* FEATURE_OES_draw_texture */
    /** The extension string */
    const GLubyte *String;
    /** Number of supported extensions */
@@ -3208,9 +3213,8 @@ struct __GLcontextRec
 
    struct gl_meta_state *Meta;  /**< for "meta" operations */
 
-#if FEATURE_EXT_framebuffer_object
+   /* GL_EXT_framebuffer_object */
    struct gl_renderbuffer *CurrentRenderbuffer;
-#endif
 
    GLenum ErrorValue;        /**< Last error code */
 
index 32aaa79f7fb2416b4064b2c295fcc95b0974d2a4..36236eb9a75fb3f5259a5feeacd78d97e085e23c 100644 (file)
@@ -72,7 +72,8 @@ fpclassify(double x)
 
 #elif defined(__APPLE__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \
      defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
-     (defined(__sun) && defined(__C99FEATURES__)) || defined(__MINGW32__)
+     (defined(__sun) && defined(__C99FEATURES__)) || defined(__MINGW32__) || \
+     (defined(__sun) && defined(__GNUC__))
 
 /* fpclassify is available. */
 
index 9cb2391035de4949d518bdabdf8e4c5b6b29be36..cc350c93b9780f8adeb8412ec790f4dcdd979a3c 100644 (file)
@@ -46,8 +46,7 @@
 #include "program/program.h"
 #include "program/prog_parameter.h"
 #include "program/prog_uniform.h"
-#include "slang/slang_compile.h"
-#include "slang/slang_link.h"
+#include "talloc.h"
 
 
 /** Define this to enable shader substitution (see below) */
@@ -99,6 +98,7 @@ _mesa_init_shader_state(GLcontext *ctx)
    ctx->Shader.EmitContReturn = GL_TRUE;
    ctx->Shader.EmitCondCodes = GL_FALSE;
    ctx->Shader.EmitComments = GL_FALSE;
+   ctx->Shader.EmitNoIfs = GL_FALSE;
    ctx->Shader.Flags = get_shader_flags();
 
    /* Default pragma settings */
@@ -800,7 +800,7 @@ compile_shader(GLcontext *ctx, GLuint shaderObj)
    /* this call will set the sh->CompileStatus field to indicate if
     * compilation was successful.
     */
-   (void) _slang_compile(ctx, sh);
+   _mesa_glsl_compile_shader(ctx, sh);
 }
 
 
@@ -826,7 +826,7 @@ link_program(GLcontext *ctx, GLuint program)
 
    FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
-   _slang_link(ctx, program, shProg);
+   _mesa_glsl_link_shader(ctx, shProg);
 
    /* debug code */
    if (0) {
@@ -1051,9 +1051,9 @@ validate_program(GLcontext *ctx, GLuint program)
    if (!shProg->Validated) {
       /* update info log */
       if (shProg->InfoLog) {
-         free(shProg->InfoLog);
+         talloc_free(shProg->InfoLog);
       }
-      shProg->InfoLog = _mesa_strdup(errMsg);
+      shProg->InfoLog = talloc_strdup(shProg, errMsg);
    }
 }
 
index 14bbb2e4bc34470405b8ccb69e54536b63438004..59198d788bd093ca3df8e55a414863e3c89e39f9 100644 (file)
@@ -36,7 +36,7 @@
 #include "program/program.h"
 #include "program/prog_parameter.h"
 #include "program/prog_uniform.h"
-
+#include "talloc.h"
 
 /**********************************************************************/
 /*** Shader object functions                                        ***/
@@ -87,22 +87,27 @@ _mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
    }
 }
 
+void
+_mesa_init_shader(GLcontext *ctx, struct gl_shader *shader)
+{
+   shader->RefCount = 1;
+}
 
 /**
  * Allocate a new gl_shader object, initialize it.
  * Called via ctx->Driver.NewShader()
  */
-static struct gl_shader *
+struct gl_shader *
 _mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
 {
    struct gl_shader *shader;
    assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER ||
           type == GL_GEOMETRY_SHADER_ARB);
-   shader = CALLOC_STRUCT(gl_shader);
+   shader = talloc_zero(NULL, struct gl_shader);
    if (shader) {
       shader->Type = type;
       shader->Name = name;
-      shader->RefCount = 1;
+      _mesa_init_shader(ctx, shader);
    }
    return shader;
 }
@@ -113,14 +118,12 @@ _mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
  * Called via ctx->Driver.DeleteShader().
  */
 static void
-__mesa_delete_shader(GLcontext *ctx, struct gl_shader *sh)
+_mesa_delete_shader(GLcontext *ctx, struct gl_shader *sh)
 {
    if (sh->Source)
       free((void *) sh->Source);
-   if (sh->InfoLog)
-      free(sh->InfoLog);
    _mesa_reference_program(ctx, &sh->Program, NULL);
-   free(sh);
+   talloc_free(sh);
 }
 
 
@@ -226,6 +229,18 @@ _mesa_reference_shader_program(GLcontext *ctx,
    }
 }
 
+void
+_mesa_init_shader_program(GLcontext *ctx, struct gl_shader_program *prog)
+{
+   prog->Type = GL_SHADER_PROGRAM_MESA;
+   prog->RefCount = 1;
+   prog->Attributes = _mesa_new_parameter_list();
+#if FEATURE_ARB_geometry_shader4
+   prog->Geom.VerticesOut = 0;
+   prog->Geom.InputType = GL_TRIANGLES;
+   prog->Geom.OutputType = GL_TRIANGLE_STRIP;
+#endif
+}
 
 /**
  * Allocate a new gl_shader_program object, initialize it.
@@ -235,17 +250,10 @@ static struct gl_shader_program *
 _mesa_new_shader_program(GLcontext *ctx, GLuint name)
 {
    struct gl_shader_program *shProg;
-   shProg = CALLOC_STRUCT(gl_shader_program);
+   shProg = talloc_zero(NULL, struct gl_shader_program);
    if (shProg) {
-      shProg->Type = GL_SHADER_PROGRAM_MESA;
       shProg->Name = name;
-      shProg->RefCount = 1;
-      shProg->Attributes = _mesa_new_parameter_list();
-#if FEATURE_ARB_geometry_shader4
-      shProg->Geom.VerticesOut = 0;
-      shProg->Geom.InputType = GL_TRIANGLES;
-      shProg->Geom.OutputType = GL_TRIANGLE_STRIP;
-#endif
+      _mesa_init_shader_program(ctx, shProg);
    }
    return shProg;
 }
@@ -305,7 +313,7 @@ _mesa_free_shader_program_data(GLcontext *ctx,
    }
 
    if (shProg->InfoLog) {
-      free(shProg->InfoLog);
+      talloc_free(shProg->InfoLog);
       shProg->InfoLog = NULL;
    }
 
@@ -316,6 +324,12 @@ _mesa_free_shader_program_data(GLcontext *ctx,
    free(shProg->TransformFeedback.VaryingNames);
    shProg->TransformFeedback.VaryingNames = NULL;
    shProg->TransformFeedback.NumVarying = 0;
+
+
+   for (i = 0; i < shProg->_NumLinkedShaders; i++) {
+      ctx->Driver.DeleteShader(ctx, shProg->_LinkedShaders[i]);
+   }
+   shProg->_NumLinkedShaders = 0;
 }
 
 
@@ -324,11 +338,11 @@ _mesa_free_shader_program_data(GLcontext *ctx,
  * Called via ctx->Driver.DeleteShaderProgram().
  */
 static void
-__mesa_delete_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
+_mesa_delete_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
 {
    _mesa_free_shader_program_data(ctx, shProg);
 
-   free(shProg);
+   talloc_free(shProg);
 }
 
 
@@ -386,7 +400,9 @@ void
 _mesa_init_shader_object_functions(struct dd_function_table *driver)
 {
    driver->NewShader = _mesa_new_shader;
-   driver->DeleteShader = __mesa_delete_shader;
+   driver->DeleteShader = _mesa_delete_shader;
    driver->NewShaderProgram = _mesa_new_shader_program;
-   driver->DeleteShaderProgram = __mesa_delete_shader_program;
+   driver->DeleteShaderProgram = _mesa_delete_shader_program;
+   driver->CompileShader = _mesa_ir_compile_shader;
+   driver->LinkShader = _mesa_ir_link_shader;
 }
index d6b37b45963c31e1f3c8ba193ff06a977a5b2c19..48000463752b8d8bf2c8787d7e8dcca793d41dd2 100644 (file)
 #define SHADEROBJ_H
 
 
-#include "glheader.h"
-#include "mtypes.h"
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "program/ir_to_mesa.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * Internal functions
+ */
+
+extern void
+_mesa_init_shader_state(GLcontext * ctx);
+
+extern void
+_mesa_free_shader_state(GLcontext *ctx);
 
 
 extern void
@@ -47,6 +61,14 @@ extern void
 _mesa_reference_shader_program(GLcontext *ctx,
                                struct gl_shader_program **ptr,
                                struct gl_shader_program *shProg);
+extern void
+_mesa_init_shader(GLcontext *ctx, struct gl_shader *shader);
+
+extern struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
+
+extern void
+_mesa_init_shader_program(GLcontext *ctx, struct gl_shader_program *prog);
 
 extern struct gl_shader_program *
 _mesa_lookup_shader_program(GLcontext *ctx, GLuint name);
@@ -74,5 +96,8 @@ _mesa_init_shader_state(GLcontext *ctx);
 extern void
 _mesa_free_shader_state(GLcontext *ctx);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif /* SHADEROBJ_H */
index cbe004518a0dbb237bc7621eeb481b1a3d462358..ea7e503cf3bad94947b07dc8386888f66de3ffc1 100644 (file)
@@ -288,6 +288,10 @@ free_shared_state(GLcontext *ctx, struct gl_shared_state *shared)
 {
    GLuint i;
 
+   /* Free the dummy/fallback texture object */
+   if (shared->FallbackTex)
+      ctx->Driver.DeleteTexture(ctx, shared->FallbackTex);
+
    /*
     * Free display lists
     */
index c70792cab616d5548feef73c162302cfce848c1d..8e05980262582030bd0703c5a537a491bf71038b 100644 (file)
@@ -149,7 +149,6 @@ _mesa_init_texture_s3tc( GLcontext *ctx )
    }
    if (dxtlibhandle) {
       ctx->Mesa_DXTn = GL_TRUE;
-      _mesa_warning(ctx, "software DXTn compression/decompression available");
    }
 #else
    (void) ctx;
index f86f1911d1daea8702d7eb61649f1c4d33210698..5c8c1fd225f47f5dba82192ae454961a3bce054e 100644 (file)
@@ -455,14 +455,14 @@ _mesa_BindBufferRange(GLenum target, GLuint index,
 
    if ((size <= 0) || (size & 0x3)) {
       /* must be positive and multiple of four */
-      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size%d)", size);
+      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size%d)", (int) size);
       return;
    }  
 
    if (offset & 0x3) {
       /* must be multiple of four */
       _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glBindBufferRange(offset=%d)", offset);
+                  "glBindBufferRange(offset=%d)", (int) offset);
       return;
    }  
 
@@ -475,7 +475,8 @@ _mesa_BindBufferRange(GLenum target, GLuint index,
 
    if (offset + size >= bufObj->Size) {
       _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glBindBufferRange(offset + size > buffer size)", size);
+                  "glBindBufferRange(offset + size %d > buffer size %d)",
+                 (int) (offset + size), (int) (bufObj->Size));
       return;
    }  
 
index d68a7768df55eef74618f5213edd3ee47381c60b..a5d7da51f07042450520af1d6b9596aacd7ce052 100644 (file)
@@ -454,17 +454,12 @@ _mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location,
  * The return value will encode two values, the uniform location and an
  * offset (used for arrays, structs).
  */
-static GLint
-_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
+GLint
+_mesa_get_uniform_location(GLcontext *ctx, struct gl_shader_program *shProg,
+                          const GLchar *name)
 {
    GLint offset = 0, location = -1;
 
-   struct gl_shader_program *shProg =
-      _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation");
-
-   if (!shProg)
-      return -1;
-
    if (shProg->LinkStatus == GL_FALSE) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
       return -1;
@@ -751,11 +746,11 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program,
 /**
  * Called via glUniform*() functions.
  */
-static void
-_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
+void
+_mesa_uniform(GLcontext *ctx, struct gl_shader_program *shProg,
+             GLint location, GLsizei count,
               const GLvoid *values, GLenum type)
 {
-   struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
    struct gl_uniform *uniform;
    GLint elems, offset;
 
@@ -923,12 +918,12 @@ set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
  * Called by glUniformMatrix*() functions.
  * Note: cols=2, rows=4  ==>  array[2] of vec4
  */
-static void
-_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
+void
+_mesa_uniform_matrix(GLcontext *ctx, struct gl_shader_program *shProg,
+                    GLint cols, GLint rows,
                      GLint location, GLsizei count,
                      GLboolean transpose, const GLfloat *values)
 {
-   struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
    struct gl_uniform *uniform;
    GLint offset;
 
@@ -999,7 +994,7 @@ void GLAPIENTRY
 _mesa_Uniform1fARB(GLint location, GLfloat v0)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, 1, &v0, GL_FLOAT);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, &v0, GL_FLOAT);
 }
 
 void GLAPIENTRY
@@ -1009,7 +1004,7 @@ _mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1)
    GLfloat v[2];
    v[0] = v0;
    v[1] = v1;
-   _mesa_uniform(ctx, location, 1, v, GL_FLOAT_VEC2);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_FLOAT_VEC2);
 }
 
 void GLAPIENTRY
@@ -1020,7 +1015,7 @@ _mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
    v[0] = v0;
    v[1] = v1;
    v[2] = v2;
-   _mesa_uniform(ctx, location, 1, v, GL_FLOAT_VEC3);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_FLOAT_VEC3);
 }
 
 void GLAPIENTRY
@@ -1033,14 +1028,14 @@ _mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
    v[1] = v1;
    v[2] = v2;
    v[3] = v3;
-   _mesa_uniform(ctx, location, 1, v, GL_FLOAT_VEC4);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_FLOAT_VEC4);
 }
 
 void GLAPIENTRY
 _mesa_Uniform1iARB(GLint location, GLint v0)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, 1, &v0, GL_INT);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, &v0, GL_INT);
 }
 
 void GLAPIENTRY
@@ -1050,7 +1045,7 @@ _mesa_Uniform2iARB(GLint location, GLint v0, GLint v1)
    GLint v[2];
    v[0] = v0;
    v[1] = v1;
-   _mesa_uniform(ctx, location, 1, v, GL_INT_VEC2);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_INT_VEC2);
 }
 
 void GLAPIENTRY
@@ -1061,7 +1056,7 @@ _mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2)
    v[0] = v0;
    v[1] = v1;
    v[2] = v2;
-   _mesa_uniform(ctx, location, 1, v, GL_INT_VEC3);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_INT_VEC3);
 }
 
 void GLAPIENTRY
@@ -1073,63 +1068,63 @@ _mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
    v[1] = v1;
    v[2] = v2;
    v[3] = v3;
-   _mesa_uniform(ctx, location, 1, v, GL_INT_VEC4);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_INT_VEC4);
 }
 
 void GLAPIENTRY
 _mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_FLOAT);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT);
 }
 
 void GLAPIENTRY
 _mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_FLOAT_VEC2);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT_VEC2);
 }
 
 void GLAPIENTRY
 _mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_FLOAT_VEC3);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT_VEC3);
 }
 
 void GLAPIENTRY
 _mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_FLOAT_VEC4);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT_VEC4);
 }
 
 void GLAPIENTRY
 _mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_INT);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT);
 }
 
 void GLAPIENTRY
 _mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_INT_VEC2);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT_VEC2);
 }
 
 void GLAPIENTRY
 _mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_INT_VEC3);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT_VEC3);
 }
 
 void GLAPIENTRY
 _mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_INT_VEC4);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT_VEC4);
 }
 
 
@@ -1138,7 +1133,7 @@ void GLAPIENTRY
 _mesa_Uniform1ui(GLint location, GLuint v0)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, 1, &v0, GL_UNSIGNED_INT);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, &v0, GL_UNSIGNED_INT);
 }
 
 void GLAPIENTRY
@@ -1148,7 +1143,7 @@ _mesa_Uniform2ui(GLint location, GLuint v0, GLuint v1)
    GLuint v[2];
    v[0] = v0;
    v[1] = v1;
-   _mesa_uniform(ctx, location, 1, v, GL_UNSIGNED_INT_VEC2);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_UNSIGNED_INT_VEC2);
 }
 
 void GLAPIENTRY
@@ -1159,7 +1154,7 @@ _mesa_Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
    v[0] = v0;
    v[1] = v1;
    v[2] = v2;
-   _mesa_uniform(ctx, location, 1, v, GL_UNSIGNED_INT_VEC3);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_UNSIGNED_INT_VEC3);
 }
 
 void GLAPIENTRY
@@ -1171,35 +1166,35 @@ _mesa_Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
    v[1] = v1;
    v[2] = v2;
    v[3] = v3;
-   _mesa_uniform(ctx, location, 1, v, GL_UNSIGNED_INT_VEC4);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_UNSIGNED_INT_VEC4);
 }
 
 void GLAPIENTRY
 _mesa_Uniform1uiv(GLint location, GLsizei count, const GLuint *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_UNSIGNED_INT);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT);
 }
 
 void GLAPIENTRY
 _mesa_Uniform2uiv(GLint location, GLsizei count, const GLuint *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_UNSIGNED_INT_VEC2);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT_VEC2);
 }
 
 void GLAPIENTRY
 _mesa_Uniform3uiv(GLint location, GLsizei count, const GLuint *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_UNSIGNED_INT_VEC3);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT_VEC3);
 }
 
 void GLAPIENTRY
 _mesa_Uniform4uiv(GLint location, GLsizei count, const GLuint *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_UNSIGNED_INT_VEC4);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT_VEC4);
 }
 
 
@@ -1209,7 +1204,8 @@ _mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose,
                           const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 2, 2, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+                       2, 2, location, count, transpose, value);
 }
 
 void GLAPIENTRY
@@ -1217,7 +1213,8 @@ _mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose,
                           const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 3, 3, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+                       3, 3, location, count, transpose, value);
 }
 
 void GLAPIENTRY
@@ -1225,7 +1222,8 @@ _mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose,
                           const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 4, 4, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+                       4, 4, location, count, transpose, value);
 }
 
 
@@ -1237,7 +1235,8 @@ _mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose,
                          const GLfloat *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 2, 3, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+                       2, 3, location, count, transpose, value);
 }
 
 void GLAPIENTRY
@@ -1245,7 +1244,8 @@ _mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose,
                          const GLfloat *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 3, 2, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+                       3, 2, location, count, transpose, value);
 }
 
 void GLAPIENTRY
@@ -1253,7 +1253,8 @@ _mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose,
                          const GLfloat *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 2, 4, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+                       2, 4, location, count, transpose, value);
 }
 
 void GLAPIENTRY
@@ -1261,7 +1262,8 @@ _mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose,
                          const GLfloat *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 4, 2, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+                       4, 2, location, count, transpose, value);
 }
 
 void GLAPIENTRY
@@ -1269,7 +1271,8 @@ _mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose,
                          const GLfloat *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 3, 4, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+                       3, 4, location, count, transpose, value);
 }
 
 void GLAPIENTRY
@@ -1277,7 +1280,8 @@ _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
                          const GLfloat *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 4, 3, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+                       4, 3, location, count, transpose, value);
 }
 
 
@@ -1300,8 +1304,16 @@ _mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint *params)
 GLint GLAPIENTRY
 _mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name)
 {
+   struct gl_shader_program *shProg;
+
    GET_CURRENT_CONTEXT(ctx);
-   return _mesa_get_uniform_location(ctx, programObj, name);
+
+   shProg = _mesa_lookup_shader_program_err(ctx, programObj,
+                                           "glGetUniformLocation");
+   if (!shProg)
+      return -1;
+
+   return _mesa_get_uniform_location(ctx, shProg, name);
 }
 
 
index ef98fe16bb1dc884b434de0cf3575eb748c49d23..f823c6144474d8e7170f220f52e61734cde1779c 100644 (file)
@@ -150,7 +150,20 @@ _mesa_GetUniformivARB(GLhandleARB, GLint, GLint *);
 extern GLint GLAPIENTRY
 _mesa_GetUniformLocationARB(GLhandleARB, const GLcharARB *);
 
-
+GLint
+_mesa_get_uniform_location(GLcontext *ctx, struct gl_shader_program *shProg,
+                          const GLchar *name);
+
+void
+_mesa_uniform(GLcontext *ctx, struct gl_shader_program *shader_program,
+             GLint location, GLsizei count,
+              const GLvoid *values, GLenum type);
+
+void
+_mesa_uniform_matrix(GLcontext *ctx, struct gl_shader_program *shProg,
+                    GLint cols, GLint rows,
+                     GLint location, GLsizei count,
+                     GLboolean transpose, const GLfloat *values);
 
 extern void
 _mesa_update_shader_textures_used(struct gl_program *prog);
index fa6ba2bfdfcd8a27fba1a845711a81857016a50d..f7ef366c1a0312574c444b5adfa741761e8c2374 100644 (file)
@@ -142,6 +142,23 @@ hash_table_insert(struct hash_table *ht, void *data, const void *key)
     insert_at_head(& ht->buckets[bucket], & node->link);
 }
 
+void
+hash_table_remove(struct hash_table *ht, const void *key)
+{
+    const unsigned hash_value = (*ht->hash)(key);
+    const unsigned bucket = hash_value % ht->num_buckets;
+    struct node *node;
+
+    foreach(node, & ht->buckets[bucket]) {
+       struct hash_node *hn = (struct hash_node *) node;
+
+       if ((*ht->compare)(hn->key, key) == 0) {
+         remove_from_list(node);
+         free(node);
+         return;
+       }
+    }
+}
 
 unsigned
 hash_table_string_hash(const void *key)
@@ -157,3 +174,17 @@ hash_table_string_hash(const void *key)
 
     return hash;
 }
+
+
+unsigned
+hash_table_pointer_hash(const void *key)
+{
+   return (unsigned)((uintptr_t) key / sizeof(void *));
+}
+
+
+int
+hash_table_pointer_compare(const void *key1, const void *key2)
+{
+   return key1 == key2 ? 0 : 1;
+}
index e750906f961a2f5518c54049457829ea083af129..f1c4fdcd1fa8101d942c3a1377b03f68b8998a70 100644 (file)
@@ -36,6 +36,10 @@ struct hash_table;
 typedef unsigned (*hash_func_t)(const void *key);
 typedef int (*hash_compare_func_t)(const void *key1, const void *key2);
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
  * Hash table constructor
  *
@@ -88,6 +92,10 @@ extern void *hash_table_find(struct hash_table *ht, const void *key);
 extern void hash_table_insert(struct hash_table *ht, void *data,
     const void *key);
 
+/**
+ * Remove a specific element from a hash table.
+ */
+extern void hash_table_remove(struct hash_table *ht, const void *key);
 
 /**
  * Compute hash value of a string
@@ -112,4 +120,31 @@ extern unsigned hash_table_string_hash(const void *key);
  */
 #define hash_table_string_compare ((hash_compare_func_t) strcmp)
 
+
+/**
+ * Compute hash value of a pointer
+ *
+ * \param key  Pointer to be used as a hash key
+ *
+ * \note
+ * The memory pointed to by \c key is \b never accessed.  The value of \c key
+ * itself is used as the hash key
+ *
+ * \sa hash_table_pointer_compare
+ */
+unsigned
+hash_table_pointer_hash(const void *key);
+
+
+/**
+ * Compare two pointers used as keys
+ *
+ * \sa hash_table_pointer_hash
+ */
+int
+hash_table_pointer_compare(const void *key1, const void *key2);
+
+#ifdef __cplusplus
+}
+#endif
 #endif /* HASH_TABLE_H */
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
new file mode 100644 (file)
index 0000000..f0e14b8
--- /dev/null
@@ -0,0 +1,2796 @@
+/*
+ * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2008  VMware, Inc.   All Rights Reserved.
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * \file ir_to_mesa.cpp
+ *
+ * Translates the IR to ARB_fragment_program text if possible,
+ * printing the result
+ */
+
+#include <stdio.h>
+#include "main/compiler.h"
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_print_visitor.h"
+#include "ir_expression_flattening.h"
+#include "glsl_types.h"
+#include "glsl_parser_extras.h"
+#include "../glsl/program.h"
+#include "ir_optimization.h"
+#include "ast.h"
+
+extern "C" {
+#include "main/mtypes.h"
+#include "main/shaderapi.h"
+#include "main/shaderobj.h"
+#include "main/uniforms.h"
+#include "program/hash_table.h"
+#include "program/prog_instruction.h"
+#include "program/prog_optimize.h"
+#include "program/prog_print.h"
+#include "program/program.h"
+#include "program/prog_uniform.h"
+#include "program/prog_parameter.h"
+}
+
+static int swizzle_for_size(int size);
+
+/**
+ * This struct is a corresponding struct to Mesa prog_src_register, with
+ * wider fields.
+ */
+typedef struct ir_to_mesa_src_reg {
+   ir_to_mesa_src_reg(int file, int index, const glsl_type *type)
+   {
+      this->file = file;
+      this->index = index;
+      if (type && (type->is_scalar() || type->is_vector() || type->is_matrix()))
+        this->swizzle = swizzle_for_size(type->vector_elements);
+      else
+        this->swizzle = SWIZZLE_XYZW;
+      this->negate = 0;
+      this->reladdr = NULL;
+   }
+
+   ir_to_mesa_src_reg()
+   {
+      this->file = PROGRAM_UNDEFINED;
+      this->index = 0;
+      this->swizzle = 0;
+      this->negate = 0;
+      this->reladdr = NULL;
+   }
+
+   int file; /**< PROGRAM_* from Mesa */
+   int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
+   GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */
+   int negate; /**< NEGATE_XYZW mask from mesa */
+   /** Register index should be offset by the integer in this reg. */
+   ir_to_mesa_src_reg *reladdr;
+} ir_to_mesa_src_reg;
+
+typedef struct ir_to_mesa_dst_reg {
+   int file; /**< PROGRAM_* from Mesa */
+   int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */
+   int writemask; /**< Bitfield of WRITEMASK_[XYZW] */
+   GLuint cond_mask:4;
+   /** Register index should be offset by the integer in this reg. */
+   ir_to_mesa_src_reg *reladdr;
+} ir_to_mesa_dst_reg;
+
+extern ir_to_mesa_src_reg ir_to_mesa_undef;
+
+class ir_to_mesa_instruction : public exec_node {
+public:
+   /* Callers of this talloc-based new need not call delete. It's
+    * easier to just talloc_free 'ctx' (or any of its ancestors). */
+   static void* operator new(size_t size, void *ctx)
+   {
+      void *node;
+
+      node = talloc_zero_size(ctx, size);
+      assert(node != NULL);
+
+      return node;
+   }
+
+   enum prog_opcode op;
+   ir_to_mesa_dst_reg dst_reg;
+   ir_to_mesa_src_reg src_reg[3];
+   /** Pointer to the ir source this tree came from for debugging */
+   ir_instruction *ir;
+   GLboolean cond_update;
+   int sampler; /**< sampler index */
+   int tex_target; /**< One of TEXTURE_*_INDEX */
+   GLboolean tex_shadow;
+
+   class function_entry *function; /* Set on OPCODE_CAL or OPCODE_BGNSUB */
+};
+
+class variable_storage : public exec_node {
+public:
+   variable_storage(ir_variable *var, int file, int index)
+      : file(file), index(index), var(var)
+   {
+      /* empty */
+   }
+
+   int file;
+   int index;
+   ir_variable *var; /* variable that maps to this, if any */
+};
+
+class function_entry : public exec_node {
+public:
+   ir_function_signature *sig;
+
+   /**
+    * identifier of this function signature used by the program.
+    *
+    * At the point that Mesa instructions for function calls are
+    * generated, we don't know the address of the first instruction of
+    * the function body.  So we make the BranchTarget that is called a
+    * small integer and rewrite them during set_branchtargets().
+    */
+   int sig_id;
+
+   /**
+    * Pointer to first instruction of the function body.
+    *
+    * Set during function body emits after main() is processed.
+    */
+   ir_to_mesa_instruction *bgn_inst;
+
+   /**
+    * Index of the first instruction of the function body in actual
+    * Mesa IR.
+    *
+    * Set after convertion from ir_to_mesa_instruction to prog_instruction.
+    */
+   int inst;
+
+   /** Storage for the return value. */
+   ir_to_mesa_src_reg return_reg;
+};
+
+class ir_to_mesa_visitor : public ir_visitor {
+public:
+   ir_to_mesa_visitor();
+   ~ir_to_mesa_visitor();
+
+   function_entry *current_function;
+
+   GLcontext *ctx;
+   struct gl_program *prog;
+   struct gl_shader_program *shader_program;
+
+   int next_temp;
+
+   variable_storage *find_variable_storage(ir_variable *var);
+
+   function_entry *get_function_signature(ir_function_signature *sig);
+
+   ir_to_mesa_src_reg get_temp(const glsl_type *type);
+   void reladdr_to_temp(ir_instruction *ir,
+                       ir_to_mesa_src_reg *reg, int *num_reladdr);
+
+   struct ir_to_mesa_src_reg src_reg_for_float(float val);
+
+   /**
+    * \name Visit methods
+    *
+    * As typical for the visitor pattern, there must be one \c visit method for
+    * each concrete subclass of \c ir_instruction.  Virtual base classes within
+    * the hierarchy should not have \c visit methods.
+    */
+   /*@{*/
+   virtual void visit(ir_variable *);
+   virtual void visit(ir_loop *);
+   virtual void visit(ir_loop_jump *);
+   virtual void visit(ir_function_signature *);
+   virtual void visit(ir_function *);
+   virtual void visit(ir_expression *);
+   virtual void visit(ir_swizzle *);
+   virtual void visit(ir_dereference_variable  *);
+   virtual void visit(ir_dereference_array *);
+   virtual void visit(ir_dereference_record *);
+   virtual void visit(ir_assignment *);
+   virtual void visit(ir_constant *);
+   virtual void visit(ir_call *);
+   virtual void visit(ir_return *);
+   virtual void visit(ir_discard *);
+   virtual void visit(ir_texture *);
+   virtual void visit(ir_if *);
+   /*@}*/
+
+   struct ir_to_mesa_src_reg result;
+
+   /** List of variable_storage */
+   exec_list variables;
+
+   /** List of function_entry */
+   exec_list function_signatures;
+   int next_signature_id;
+
+   /** List of ir_to_mesa_instruction */
+   exec_list instructions;
+
+   ir_to_mesa_instruction *ir_to_mesa_emit_op0(ir_instruction *ir,
+                                              enum prog_opcode op);
+
+   ir_to_mesa_instruction *ir_to_mesa_emit_op1(ir_instruction *ir,
+                                              enum prog_opcode op,
+                                              ir_to_mesa_dst_reg dst,
+                                              ir_to_mesa_src_reg src0);
+
+   ir_to_mesa_instruction *ir_to_mesa_emit_op2(ir_instruction *ir,
+                                              enum prog_opcode op,
+                                              ir_to_mesa_dst_reg dst,
+                                              ir_to_mesa_src_reg src0,
+                                              ir_to_mesa_src_reg src1);
+
+   ir_to_mesa_instruction *ir_to_mesa_emit_op3(ir_instruction *ir,
+                                              enum prog_opcode op,
+                                              ir_to_mesa_dst_reg dst,
+                                              ir_to_mesa_src_reg src0,
+                                              ir_to_mesa_src_reg src1,
+                                              ir_to_mesa_src_reg src2);
+
+   void ir_to_mesa_emit_scalar_op1(ir_instruction *ir,
+                                  enum prog_opcode op,
+                                  ir_to_mesa_dst_reg dst,
+                                  ir_to_mesa_src_reg src0);
+
+   void ir_to_mesa_emit_scalar_op2(ir_instruction *ir,
+                                  enum prog_opcode op,
+                                  ir_to_mesa_dst_reg dst,
+                                  ir_to_mesa_src_reg src0,
+                                  ir_to_mesa_src_reg src1);
+
+   GLboolean try_emit_mad(ir_expression *ir,
+                         int mul_operand);
+
+   int get_sampler_uniform_value(ir_dereference *deref);
+
+   void *mem_ctx;
+};
+
+ir_to_mesa_src_reg ir_to_mesa_undef = ir_to_mesa_src_reg(PROGRAM_UNDEFINED, 0, NULL);
+
+ir_to_mesa_dst_reg ir_to_mesa_undef_dst = {
+   PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP, COND_TR, NULL,
+};
+
+ir_to_mesa_dst_reg ir_to_mesa_address_reg = {
+   PROGRAM_ADDRESS, 0, WRITEMASK_X, COND_TR, NULL
+};
+
+static void fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3);
+
+static void fail_link(struct gl_shader_program *prog, const char *fmt, ...)
+   {
+      va_list args;
+      va_start(args, fmt);
+      prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, args);
+      va_end(args);
+
+      prog->LinkStatus = GL_FALSE;
+   }
+
+static int swizzle_for_size(int size)
+{
+   int size_swizzles[4] = {
+      MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
+      MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y),
+      MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z),
+      MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
+   };
+
+   return size_swizzles[size - 1];
+}
+
+ir_to_mesa_instruction *
+ir_to_mesa_visitor::ir_to_mesa_emit_op3(ir_instruction *ir,
+                                       enum prog_opcode op,
+                                       ir_to_mesa_dst_reg dst,
+                                       ir_to_mesa_src_reg src0,
+                                       ir_to_mesa_src_reg src1,
+                                       ir_to_mesa_src_reg src2)
+{
+   ir_to_mesa_instruction *inst = new(mem_ctx) ir_to_mesa_instruction();
+   int num_reladdr = 0;
+
+   /* If we have to do relative addressing, we want to load the ARL
+    * reg directly for one of the regs, and preload the other reladdr
+    * sources into temps.
+    */
+   num_reladdr += dst.reladdr != NULL;
+   num_reladdr += src0.reladdr != NULL;
+   num_reladdr += src1.reladdr != NULL;
+   num_reladdr += src2.reladdr != NULL;
+
+   reladdr_to_temp(ir, &src2, &num_reladdr);
+   reladdr_to_temp(ir, &src1, &num_reladdr);
+   reladdr_to_temp(ir, &src0, &num_reladdr);
+
+   if (dst.reladdr) {
+      ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg,
+                          *dst.reladdr);
+
+      num_reladdr--;
+   }
+   assert(num_reladdr == 0);
+
+   inst->op = op;
+   inst->dst_reg = dst;
+   inst->src_reg[0] = src0;
+   inst->src_reg[1] = src1;
+   inst->src_reg[2] = src2;
+   inst->ir = ir;
+
+   inst->function = NULL;
+
+   this->instructions.push_tail(inst);
+
+   return inst;
+}
+
+
+ir_to_mesa_instruction *
+ir_to_mesa_visitor::ir_to_mesa_emit_op2(ir_instruction *ir,
+                                       enum prog_opcode op,
+                                       ir_to_mesa_dst_reg dst,
+                                       ir_to_mesa_src_reg src0,
+                                       ir_to_mesa_src_reg src1)
+{
+   return ir_to_mesa_emit_op3(ir, op, dst, src0, src1, ir_to_mesa_undef);
+}
+
+ir_to_mesa_instruction *
+ir_to_mesa_visitor::ir_to_mesa_emit_op1(ir_instruction *ir,
+                                       enum prog_opcode op,
+                                       ir_to_mesa_dst_reg dst,
+                                       ir_to_mesa_src_reg src0)
+{
+   assert(dst.writemask != 0);
+   return ir_to_mesa_emit_op3(ir, op, dst,
+                             src0, ir_to_mesa_undef, ir_to_mesa_undef);
+}
+
+ir_to_mesa_instruction *
+ir_to_mesa_visitor::ir_to_mesa_emit_op0(ir_instruction *ir,
+                                       enum prog_opcode op)
+{
+   return ir_to_mesa_emit_op3(ir, op, ir_to_mesa_undef_dst,
+                             ir_to_mesa_undef,
+                             ir_to_mesa_undef,
+                             ir_to_mesa_undef);
+}
+
+inline ir_to_mesa_dst_reg
+ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg reg)
+{
+   ir_to_mesa_dst_reg dst_reg;
+
+   dst_reg.file = reg.file;
+   dst_reg.index = reg.index;
+   dst_reg.writemask = WRITEMASK_XYZW;
+   dst_reg.cond_mask = COND_TR;
+   dst_reg.reladdr = reg.reladdr;
+
+   return dst_reg;
+}
+
+inline ir_to_mesa_src_reg
+ir_to_mesa_src_reg_from_dst(ir_to_mesa_dst_reg reg)
+{
+   return ir_to_mesa_src_reg(reg.file, reg.index, NULL);
+}
+
+/**
+ * Emits Mesa scalar opcodes to produce unique answers across channels.
+ *
+ * Some Mesa opcodes are scalar-only, like ARB_fp/vp.  The src X
+ * channel determines the result across all channels.  So to do a vec4
+ * of this operation, we want to emit a scalar per source channel used
+ * to produce dest channels.
+ */
+void
+ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op2(ir_instruction *ir,
+                                              enum prog_opcode op,
+                                              ir_to_mesa_dst_reg dst,
+                                              ir_to_mesa_src_reg orig_src0,
+                                              ir_to_mesa_src_reg orig_src1)
+{
+   int i, j;
+   int done_mask = ~dst.writemask;
+
+   /* Mesa RCP is a scalar operation splatting results to all channels,
+    * like ARB_fp/vp.  So emit as many RCPs as necessary to cover our
+    * dst channels.
+    */
+   for (i = 0; i < 4; i++) {
+      GLuint this_mask = (1 << i);
+      ir_to_mesa_instruction *inst;
+      ir_to_mesa_src_reg src0 = orig_src0;
+      ir_to_mesa_src_reg src1 = orig_src1;
+
+      if (done_mask & this_mask)
+        continue;
+
+      GLuint src0_swiz = GET_SWZ(src0.swizzle, i);
+      GLuint src1_swiz = GET_SWZ(src1.swizzle, i);
+      for (j = i + 1; j < 4; j++) {
+        if (!(done_mask & (1 << j)) &&
+            GET_SWZ(src0.swizzle, j) == src0_swiz &&
+            GET_SWZ(src1.swizzle, j) == src1_swiz) {
+           this_mask |= (1 << j);
+        }
+      }
+      src0.swizzle = MAKE_SWIZZLE4(src0_swiz, src0_swiz,
+                                  src0_swiz, src0_swiz);
+      src1.swizzle = MAKE_SWIZZLE4(src1_swiz, src1_swiz,
+                                 src1_swiz, src1_swiz);
+
+      inst = ir_to_mesa_emit_op2(ir, op,
+                                dst,
+                                src0,
+                                src1);
+      inst->dst_reg.writemask = this_mask;
+      done_mask |= this_mask;
+   }
+}
+
+void
+ir_to_mesa_visitor::ir_to_mesa_emit_scalar_op1(ir_instruction *ir,
+                                              enum prog_opcode op,
+                                              ir_to_mesa_dst_reg dst,
+                                              ir_to_mesa_src_reg src0)
+{
+   ir_to_mesa_src_reg undef = ir_to_mesa_undef;
+
+   undef.swizzle = SWIZZLE_XXXX;
+
+   ir_to_mesa_emit_scalar_op2(ir, op, dst, src0, undef);
+}
+
+struct ir_to_mesa_src_reg
+ir_to_mesa_visitor::src_reg_for_float(float val)
+{
+   ir_to_mesa_src_reg src_reg(PROGRAM_CONSTANT, -1, NULL);
+
+   src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters,
+                                             &val, 1, &src_reg.swizzle);
+
+   return src_reg;
+}
+
+static int
+type_size(const struct glsl_type *type)
+{
+   unsigned int i;
+   int size;
+
+   switch (type->base_type) {
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_FLOAT:
+   case GLSL_TYPE_BOOL:
+      if (type->is_matrix()) {
+        return type->matrix_columns;
+      } else {
+        /* Regardless of size of vector, it gets a vec4. This is bad
+         * packing for things like floats, but otherwise arrays become a
+         * mess.  Hopefully a later pass over the code can pack scalars
+         * down if appropriate.
+         */
+        return 1;
+      }
+   case GLSL_TYPE_ARRAY:
+      return type_size(type->fields.array) * type->length;
+   case GLSL_TYPE_STRUCT:
+      size = 0;
+      for (i = 0; i < type->length; i++) {
+        size += type_size(type->fields.structure[i].type);
+      }
+      return size;
+   case GLSL_TYPE_SAMPLER:
+      /* Samplers take up one slot in UNIFORMS[], but they're baked in
+       * at link time.
+       */
+      return 1;
+   default:
+      assert(0);
+      return 0;
+   }
+}
+
+/**
+ * In the initial pass of codegen, we assign temporary numbers to
+ * intermediate results.  (not SSA -- variable assignments will reuse
+ * storage).  Actual register allocation for the Mesa VM occurs in a
+ * pass over the Mesa IR later.
+ */
+ir_to_mesa_src_reg
+ir_to_mesa_visitor::get_temp(const glsl_type *type)
+{
+   ir_to_mesa_src_reg src_reg;
+   int swizzle[4];
+   int i;
+
+   src_reg.file = PROGRAM_TEMPORARY;
+   src_reg.index = next_temp;
+   src_reg.reladdr = NULL;
+   next_temp += type_size(type);
+
+   if (type->is_array() || type->is_record()) {
+      src_reg.swizzle = SWIZZLE_NOOP;
+   } else {
+      for (i = 0; i < type->vector_elements; i++)
+        swizzle[i] = i;
+      for (; i < 4; i++)
+        swizzle[i] = type->vector_elements - 1;
+      src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1],
+                                     swizzle[2], swizzle[3]);
+   }
+   src_reg.negate = 0;
+
+   return src_reg;
+}
+
+variable_storage *
+ir_to_mesa_visitor::find_variable_storage(ir_variable *var)
+{
+   
+   variable_storage *entry;
+
+   foreach_iter(exec_list_iterator, iter, this->variables) {
+      entry = (variable_storage *)iter.get();
+
+      if (entry->var == var)
+        return entry;
+   }
+
+   return NULL;
+}
+
+struct statevar_element {
+   const char *field;
+   int tokens[STATE_LENGTH];
+   int swizzle;
+   bool array_indexed;
+};
+
+static struct statevar_element gl_DepthRange_elements[] = {
+   {"near", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX},
+   {"far", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY},
+   {"diff", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ},
+};
+
+static struct statevar_element gl_ClipPlane_elements[] = {
+   {NULL, {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW}
+};
+
+static struct statevar_element gl_Point_elements[] = {
+   {"size", {STATE_POINT_SIZE}, SWIZZLE_XXXX},
+   {"sizeMin", {STATE_POINT_SIZE}, SWIZZLE_YYYY},
+   {"sizeMax", {STATE_POINT_SIZE}, SWIZZLE_ZZZZ},
+   {"fadeThresholdSize", {STATE_POINT_SIZE}, SWIZZLE_WWWW},
+   {"distanceConstantAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX},
+   {"distanceLinearAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY},
+   {"distanceQuadraticAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ},
+};
+
+static struct statevar_element gl_FrontMaterial_elements[] = {
+   {"emission", {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW},
+   {"ambient", {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
+   {"diffuse", {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
+   {"specular", {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
+   {"shininess", {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX},
+};
+
+static struct statevar_element gl_BackMaterial_elements[] = {
+   {"emission", {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW},
+   {"ambient", {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
+   {"diffuse", {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
+   {"specular", {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
+   {"shininess", {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX},
+};
+
+static struct statevar_element gl_LightSource_elements[] = {
+   {"ambient", {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
+   {"diffuse", {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
+   {"specular", {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
+   {"position", {STATE_LIGHT, 0, STATE_POSITION}, SWIZZLE_XYZW},
+   {"halfVector", {STATE_LIGHT, 0, STATE_HALF_VECTOR}, SWIZZLE_XYZW},
+   {"spotDirection", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_XYZW},
+   {"spotCosCutoff", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_WWWW},
+   {"spotCutoff", {STATE_LIGHT, 0, STATE_SPOT_CUTOFF}, SWIZZLE_XXXX},
+   {"spotExponent", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_WWWW},
+   {"constantAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_XXXX},
+   {"linearAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_YYYY},
+   {"quadraticAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ},
+};
+
+static struct statevar_element gl_LightModel_elements[] = {
+   {"ambient", {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW},
+};
+
+static struct statevar_element gl_FrontLightModelProduct_elements[] = {
+   {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW},
+};
+
+static struct statevar_element gl_BackLightModelProduct_elements[] = {
+   {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW},
+};
+
+static struct statevar_element gl_FrontLightProduct_elements[] = {
+   {"ambient", {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
+   {"diffuse", {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
+   {"specular", {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
+};
+
+static struct statevar_element gl_BackLightProduct_elements[] = {
+   {"ambient", {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
+   {"diffuse", {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
+   {"specular", {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
+};
+
+static struct statevar_element gl_TextureEnvColor_elements[] = {
+   {NULL, {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW},
+};
+
+static struct statevar_element gl_EyePlaneS_elements[] = {
+   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW},
+};
+
+static struct statevar_element gl_EyePlaneT_elements[] = {
+   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW},
+};
+
+static struct statevar_element gl_EyePlaneR_elements[] = {
+   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW},
+};
+
+static struct statevar_element gl_EyePlaneQ_elements[] = {
+   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW},
+};
+
+static struct statevar_element gl_ObjectPlaneS_elements[] = {
+   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW},
+};
+
+static struct statevar_element gl_ObjectPlaneT_elements[] = {
+   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW},
+};
+
+static struct statevar_element gl_ObjectPlaneR_elements[] = {
+   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW},
+};
+
+static struct statevar_element gl_ObjectPlaneQ_elements[] = {
+   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW},
+};
+
+static struct statevar_element gl_Fog_elements[] = {
+   {"color", {STATE_FOG_COLOR}, SWIZZLE_XYZW},
+   {"density", {STATE_FOG_PARAMS}, SWIZZLE_XXXX},
+   {"start", {STATE_FOG_PARAMS}, SWIZZLE_YYYY},
+   {"end", {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ},
+   {"scale", {STATE_FOG_PARAMS}, SWIZZLE_WWWW},
+};
+
+#define MATRIX(name, statevar, modifier)                       \
+   static struct statevar_element name ## _elements[] = {              \
+      { NULL, { statevar, 0, 0, 0, modifier}, SWIZZLE_XYZW },          \
+      { NULL, { statevar, 0, 1, 1, modifier}, SWIZZLE_XYZW },          \
+      { NULL, { statevar, 0, 2, 2, modifier}, SWIZZLE_XYZW },          \
+      { NULL, { statevar, 0, 3, 3, modifier}, SWIZZLE_XYZW },          \
+   }
+
+MATRIX(gl_ModelViewMatrix,
+       STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE);
+MATRIX(gl_ModelViewMatrixInverse,
+       STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS);
+MATRIX(gl_ModelViewMatrixTranspose,
+       STATE_MODELVIEW_MATRIX, 0);
+MATRIX(gl_ModelViewMatrixInverseTranspose,
+       STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE);
+
+MATRIX(gl_ProjectionMatrix,
+       STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE);
+MATRIX(gl_ProjectionMatrixInverse,
+       STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS);
+MATRIX(gl_ProjectionMatrixTranspose,
+       STATE_PROJECTION_MATRIX, 0);
+MATRIX(gl_ProjectionMatrixInverseTranspose,
+       STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE);
+
+MATRIX(gl_ModelViewProjectionMatrix,
+       STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE);
+MATRIX(gl_ModelViewProjectionMatrixInverse,
+       STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS);
+MATRIX(gl_ModelViewProjectionMatrixTranspose,
+       STATE_MVP_MATRIX, 0);
+MATRIX(gl_ModelViewProjectionMatrixInverseTranspose,
+       STATE_MVP_MATRIX, STATE_MATRIX_INVERSE);
+
+MATRIX(gl_TextureMatrix,
+       STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE);
+MATRIX(gl_TextureMatrixInverse,
+       STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS);
+MATRIX(gl_TextureMatrixTranspose,
+       STATE_TEXTURE_MATRIX, 0);
+MATRIX(gl_TextureMatrixInverseTranspose,
+       STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE);
+
+static struct statevar_element gl_NormalMatrix_elements[] = {
+   { NULL, { STATE_MODELVIEW_MATRIX, 0, 0, 0, STATE_MATRIX_INVERSE},
+     SWIZZLE_XYZW },
+   { NULL, { STATE_MODELVIEW_MATRIX, 0, 1, 1, STATE_MATRIX_INVERSE},
+     SWIZZLE_XYZW },
+   { NULL, { STATE_MODELVIEW_MATRIX, 0, 2, 2, STATE_MATRIX_INVERSE},
+     SWIZZLE_XYZW },
+};
+
+#undef MATRIX
+
+#define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)}
+
+static struct {
+   const char *name;
+   struct statevar_element *elements;
+   int num_elements;
+} statevars[] = {
+   STATEVAR(gl_DepthRange),
+   STATEVAR(gl_ClipPlane),
+   STATEVAR(gl_Point),
+   STATEVAR(gl_FrontMaterial),
+   STATEVAR(gl_BackMaterial),
+   STATEVAR(gl_LightSource),
+   STATEVAR(gl_LightModel),
+   STATEVAR(gl_FrontLightModelProduct),
+   STATEVAR(gl_BackLightModelProduct),
+   STATEVAR(gl_FrontLightProduct),
+   STATEVAR(gl_BackLightProduct),
+   STATEVAR(gl_TextureEnvColor),
+   STATEVAR(gl_EyePlaneS),
+   STATEVAR(gl_EyePlaneT),
+   STATEVAR(gl_EyePlaneR),
+   STATEVAR(gl_EyePlaneQ),
+   STATEVAR(gl_ObjectPlaneS),
+   STATEVAR(gl_ObjectPlaneT),
+   STATEVAR(gl_ObjectPlaneR),
+   STATEVAR(gl_ObjectPlaneQ),
+   STATEVAR(gl_Fog),
+
+   STATEVAR(gl_ModelViewMatrix),
+   STATEVAR(gl_ModelViewMatrixInverse),
+   STATEVAR(gl_ModelViewMatrixTranspose),
+   STATEVAR(gl_ModelViewMatrixInverseTranspose),
+
+   STATEVAR(gl_ProjectionMatrix),
+   STATEVAR(gl_ProjectionMatrixInverse),
+   STATEVAR(gl_ProjectionMatrixTranspose),
+   STATEVAR(gl_ProjectionMatrixInverseTranspose),
+
+   STATEVAR(gl_ModelViewProjectionMatrix),
+   STATEVAR(gl_ModelViewProjectionMatrixInverse),
+   STATEVAR(gl_ModelViewProjectionMatrixTranspose),
+   STATEVAR(gl_ModelViewProjectionMatrixInverseTranspose),
+
+   STATEVAR(gl_TextureMatrix),
+   STATEVAR(gl_TextureMatrixInverse),
+   STATEVAR(gl_TextureMatrixTranspose),
+   STATEVAR(gl_TextureMatrixInverseTranspose),
+
+   STATEVAR(gl_NormalMatrix),
+};
+
+void
+ir_to_mesa_visitor::visit(ir_variable *ir)
+{
+   if (strcmp(ir->name, "gl_FragCoord") == 0) {
+      struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog;
+
+      fp->OriginUpperLeft = ir->origin_upper_left;
+      fp->PixelCenterInteger = ir->pixel_center_integer;
+   }
+
+   if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) {
+      unsigned int i;
+
+      struct variable_storage *entry;
+      entry = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY,
+                                           this->next_temp);
+      this->variables.push_tail(entry);
+      this->next_temp += type_size(ir->type);
+
+      for (i = 0; i < Elements(statevars); i++) {
+        if (strcmp(ir->name, statevars[i].name) == 0)
+           break;
+      }
+
+      if (i == Elements(statevars)) {
+        fail_link(this->shader_program,
+                  "Failed to find builtin uniform `%s'\n", ir->name);
+        return;
+      }
+
+      ir_to_mesa_dst_reg dst =
+        ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg(PROGRAM_TEMPORARY,
+                                                       entry->index, NULL));
+
+      int array_count;
+      if (ir->type->is_array()) {
+        array_count = ir->type->length;
+      } else {
+        array_count = 1;
+      }
+
+      for (int a = 0; a < array_count; a++) {
+        for (int j = 0; j < statevars[i].num_elements; j++) {
+           struct statevar_element *element = &statevars[i].elements[j];
+           int tokens[STATE_LENGTH];
+
+           memcpy(tokens, element->tokens, sizeof(element->tokens));
+           if (ir->type->is_array()) {
+              tokens[1] = a;
+           }
+
+           int index = _mesa_add_state_reference(this->prog->Parameters,
+                                                 (gl_state_index *)tokens);
+           ir_to_mesa_src_reg src(PROGRAM_STATE_VAR, index, NULL);
+           src.swizzle = element->swizzle;
+           ir_to_mesa_emit_op1(ir, OPCODE_MOV, dst, src);
+           /* even a float takes up a whole vec4 reg in a struct/array. */
+           dst.index++;
+        }
+      }
+      if (dst.index != entry->index + type_size(ir->type)) {
+        fail_link(this->shader_program,
+                  "failed to load builtin uniform `%s'  (%d/%d regs loaded)\n",
+                  ir->name, dst.index - entry->index,
+                  type_size(ir->type));
+      }
+   }
+}
+
+void
+ir_to_mesa_visitor::visit(ir_loop *ir)
+{
+   assert(!ir->from);
+   assert(!ir->to);
+   assert(!ir->increment);
+   assert(!ir->counter);
+
+   ir_to_mesa_emit_op0(NULL, OPCODE_BGNLOOP);
+   visit_exec_list(&ir->body_instructions, this);
+   ir_to_mesa_emit_op0(NULL, OPCODE_ENDLOOP);
+}
+
+void
+ir_to_mesa_visitor::visit(ir_loop_jump *ir)
+{
+   switch (ir->mode) {
+   case ir_loop_jump::jump_break:
+      ir_to_mesa_emit_op0(NULL, OPCODE_BRK);
+      break;
+   case ir_loop_jump::jump_continue:
+      ir_to_mesa_emit_op0(NULL, OPCODE_CONT);
+      break;
+   }
+}
+
+
+void
+ir_to_mesa_visitor::visit(ir_function_signature *ir)
+{
+   assert(0);
+   (void)ir;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_function *ir)
+{
+   /* Ignore function bodies other than main() -- we shouldn't see calls to
+    * them since they should all be inlined before we get to ir_to_mesa.
+    */
+   if (strcmp(ir->name, "main") == 0) {
+      const ir_function_signature *sig;
+      exec_list empty;
+
+      sig = ir->matching_signature(&empty);
+
+      assert(sig);
+
+      foreach_iter(exec_list_iterator, iter, sig->body) {
+        ir_instruction *ir = (ir_instruction *)iter.get();
+
+        ir->accept(this);
+      }
+   }
+}
+
+GLboolean
+ir_to_mesa_visitor::try_emit_mad(ir_expression *ir, int mul_operand)
+{
+   int nonmul_operand = 1 - mul_operand;
+   ir_to_mesa_src_reg a, b, c;
+
+   ir_expression *expr = ir->operands[mul_operand]->as_expression();
+   if (!expr || expr->operation != ir_binop_mul)
+      return false;
+
+   expr->operands[0]->accept(this);
+   a = this->result;
+   expr->operands[1]->accept(this);
+   b = this->result;
+   ir->operands[nonmul_operand]->accept(this);
+   c = this->result;
+
+   this->result = get_temp(ir->type);
+   ir_to_mesa_emit_op3(ir, OPCODE_MAD,
+                      ir_to_mesa_dst_reg_from_src(this->result), a, b, c);
+
+   return true;
+}
+
+void
+ir_to_mesa_visitor::reladdr_to_temp(ir_instruction *ir,
+                                   ir_to_mesa_src_reg *reg, int *num_reladdr)
+{
+   if (!reg->reladdr)
+      return;
+
+   ir_to_mesa_emit_op1(ir, OPCODE_ARL, ir_to_mesa_address_reg, *reg->reladdr);
+
+   if (*num_reladdr != 1) {
+      ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
+
+      ir_to_mesa_emit_op1(ir, OPCODE_MOV,
+                         ir_to_mesa_dst_reg_from_src(temp), *reg);
+      *reg = temp;
+   }
+
+   (*num_reladdr)--;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_expression *ir)
+{
+   unsigned int operand;
+   struct ir_to_mesa_src_reg op[2];
+   struct ir_to_mesa_src_reg result_src;
+   struct ir_to_mesa_dst_reg result_dst;
+   const glsl_type *vec4_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 4, 1);
+   const glsl_type *vec3_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 3, 1);
+   const glsl_type *vec2_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 2, 1);
+
+   /* Quick peephole: Emit OPCODE_MAD(a, b, c) instead of ADD(MUL(a, b), c)
+    */
+   if (ir->operation == ir_binop_add) {
+      if (try_emit_mad(ir, 1))
+        return;
+      if (try_emit_mad(ir, 0))
+        return;
+   }
+
+   for (operand = 0; operand < ir->get_num_operands(); operand++) {
+      this->result.file = PROGRAM_UNDEFINED;
+      ir->operands[operand]->accept(this);
+      if (this->result.file == PROGRAM_UNDEFINED) {
+        ir_print_visitor v;
+        printf("Failed to get tree for expression operand:\n");
+        ir->operands[operand]->accept(&v);
+        exit(1);
+      }
+      op[operand] = this->result;
+
+      /* Matrix expression operands should have been broken down to vector
+       * operations already.
+       */
+      assert(!ir->operands[operand]->type->is_matrix());
+   }
+
+   this->result.file = PROGRAM_UNDEFINED;
+
+   /* Storage for our result.  Ideally for an assignment we'd be using
+    * the actual storage for the result here, instead.
+    */
+   result_src = get_temp(ir->type);
+   /* convenience for the emit functions below. */
+   result_dst = ir_to_mesa_dst_reg_from_src(result_src);
+   /* Limit writes to the channels that will be used by result_src later.
+    * This does limit this temp's use as a temporary for multi-instruction
+    * sequences.
+    */
+   result_dst.writemask = (1 << ir->type->vector_elements) - 1;
+
+   switch (ir->operation) {
+   case ir_unop_logic_not:
+      ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst,
+                         op[0], src_reg_for_float(0.0));
+      break;
+   case ir_unop_neg:
+      op[0].negate = ~op[0].negate;
+      result_src = op[0];
+      break;
+   case ir_unop_abs:
+      ir_to_mesa_emit_op1(ir, OPCODE_ABS, result_dst, op[0]);
+      break;
+   case ir_unop_sign:
+      ir_to_mesa_emit_op1(ir, OPCODE_SSG, result_dst, op[0]);
+      break;
+   case ir_unop_rcp:
+      ir_to_mesa_emit_scalar_op1(ir, OPCODE_RCP, result_dst, op[0]);
+      break;
+
+   case ir_unop_exp2:
+      ir_to_mesa_emit_scalar_op1(ir, OPCODE_EX2, result_dst, op[0]);
+      break;
+   case ir_unop_exp:
+   case ir_unop_log:
+      assert(!"not reached: should be handled by ir_explog_to_explog2");
+      break;
+   case ir_unop_log2:
+      ir_to_mesa_emit_scalar_op1(ir, OPCODE_LG2, result_dst, op[0]);
+      break;
+   case ir_unop_sin:
+      ir_to_mesa_emit_scalar_op1(ir, OPCODE_SIN, result_dst, op[0]);
+      break;
+   case ir_unop_cos:
+      ir_to_mesa_emit_scalar_op1(ir, OPCODE_COS, result_dst, op[0]);
+      break;
+
+   case ir_unop_dFdx:
+      ir_to_mesa_emit_op1(ir, OPCODE_DDX, result_dst, op[0]);
+      break;
+   case ir_unop_dFdy:
+      ir_to_mesa_emit_op1(ir, OPCODE_DDY, result_dst, op[0]);
+      break;
+
+   case ir_binop_add:
+      ir_to_mesa_emit_op2(ir, OPCODE_ADD, result_dst, op[0], op[1]);
+      break;
+   case ir_binop_sub:
+      ir_to_mesa_emit_op2(ir, OPCODE_SUB, result_dst, op[0], op[1]);
+      break;
+
+   case ir_binop_mul:
+      ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, op[0], op[1]);
+      break;
+   case ir_binop_div:
+      assert(!"not reached: should be handled by ir_div_to_mul_rcp");
+   case ir_binop_mod:
+      assert(!"ir_binop_mod should have been converted to b * fract(a/b)");
+      break;
+
+   case ir_binop_less:
+      ir_to_mesa_emit_op2(ir, OPCODE_SLT, result_dst, op[0], op[1]);
+      break;
+   case ir_binop_greater:
+      ir_to_mesa_emit_op2(ir, OPCODE_SGT, result_dst, op[0], op[1]);
+      break;
+   case ir_binop_lequal:
+      ir_to_mesa_emit_op2(ir, OPCODE_SLE, result_dst, op[0], op[1]);
+      break;
+   case ir_binop_gequal:
+      ir_to_mesa_emit_op2(ir, OPCODE_SGE, result_dst, op[0], op[1]);
+      break;
+   case ir_binop_equal:
+      /* "==" operator producing a scalar boolean. */
+      if (ir->operands[0]->type->is_vector() ||
+         ir->operands[1]->type->is_vector()) {
+        ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
+        ir_to_mesa_emit_op2(ir, OPCODE_SNE,
+                            ir_to_mesa_dst_reg_from_src(temp), op[0], op[1]);
+        ir_to_mesa_emit_op2(ir, OPCODE_DP4, result_dst, temp, temp);
+        ir_to_mesa_emit_op2(ir, OPCODE_SEQ,
+                            result_dst, result_src, src_reg_for_float(0.0));
+      } else {
+        ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
+      }
+      break;
+   case ir_binop_nequal:
+      /* "!=" operator producing a scalar boolean. */
+      if (ir->operands[0]->type->is_vector() ||
+         ir->operands[1]->type->is_vector()) {
+        ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type);
+        ir_to_mesa_emit_op2(ir, OPCODE_SNE,
+                            ir_to_mesa_dst_reg_from_src(temp), op[0], op[1]);
+        ir_to_mesa_emit_op2(ir, OPCODE_DP4, result_dst, temp, temp);
+        ir_to_mesa_emit_op2(ir, OPCODE_SNE,
+                            result_dst, result_src, src_reg_for_float(0.0));
+      } else {
+        ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]);
+      }
+      break;
+
+   case ir_unop_any:
+      switch (ir->operands[0]->type->vector_elements) {
+      case 4:
+        ir_to_mesa_emit_op2(ir, OPCODE_DP4, result_dst, op[0], op[0]);
+        break;
+      case 3:
+        ir_to_mesa_emit_op2(ir, OPCODE_DP3, result_dst, op[0], op[0]);
+        break;
+      case 2:
+        ir_to_mesa_emit_op2(ir, OPCODE_DP2, result_dst, op[0], op[0]);
+        break;
+      default:
+        assert(!"unreached: ir_unop_any of non-bvec");
+        break;
+      }
+      ir_to_mesa_emit_op2(ir, OPCODE_SNE,
+                         result_dst, result_src, src_reg_for_float(0.0));
+      break;
+
+   case ir_binop_logic_xor:
+      ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]);
+      break;
+
+   case ir_binop_logic_or:
+      /* This could be a saturated add and skip the SNE. */
+      ir_to_mesa_emit_op2(ir, OPCODE_ADD,
+                         result_dst,
+                         op[0], op[1]);
+
+      ir_to_mesa_emit_op2(ir, OPCODE_SNE,
+                         result_dst,
+                         result_src, src_reg_for_float(0.0));
+      break;
+
+   case ir_binop_logic_and:
+      /* the bool args are stored as float 0.0 or 1.0, so "mul" gives us "and". */
+      ir_to_mesa_emit_op2(ir, OPCODE_MUL,
+                         result_dst,
+                         op[0], op[1]);
+      break;
+
+   case ir_binop_dot:
+      if (ir->operands[0]->type == vec4_type) {
+        assert(ir->operands[1]->type == vec4_type);
+        ir_to_mesa_emit_op2(ir, OPCODE_DP4,
+                            result_dst,
+                            op[0], op[1]);
+      } else if (ir->operands[0]->type == vec3_type) {
+        assert(ir->operands[1]->type == vec3_type);
+        ir_to_mesa_emit_op2(ir, OPCODE_DP3,
+                            result_dst,
+                            op[0], op[1]);
+      } else if (ir->operands[0]->type == vec2_type) {
+        assert(ir->operands[1]->type == vec2_type);
+        ir_to_mesa_emit_op2(ir, OPCODE_DP2,
+                            result_dst,
+                            op[0], op[1]);
+      }
+      break;
+
+   case ir_binop_cross:
+      ir_to_mesa_emit_op2(ir, OPCODE_XPD, result_dst, op[0], op[1]);
+      break;
+
+   case ir_unop_sqrt:
+      /* sqrt(x) = x * rsq(x). */
+      ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]);
+      ir_to_mesa_emit_op2(ir, OPCODE_MUL, result_dst, result_src, op[0]);
+      /* For incoming channels <= 0, set the result to 0. */
+      op[0].negate = ~op[0].negate;
+      ir_to_mesa_emit_op3(ir, OPCODE_CMP, result_dst,
+                         op[0], result_src, src_reg_for_float(0.0));
+      break;
+   case ir_unop_rsq:
+      ir_to_mesa_emit_scalar_op1(ir, OPCODE_RSQ, result_dst, op[0]);
+      break;
+   case ir_unop_i2f:
+   case ir_unop_b2f:
+   case ir_unop_b2i:
+      /* Mesa IR lacks types, ints are stored as truncated floats. */
+      result_src = op[0];
+      break;
+   case ir_unop_f2i:
+      ir_to_mesa_emit_op1(ir, OPCODE_TRUNC, result_dst, op[0]);
+      break;
+   case ir_unop_f2b:
+   case ir_unop_i2b:
+      ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst,
+                         op[0], src_reg_for_float(0.0));
+      break;
+   case ir_unop_trunc:
+      ir_to_mesa_emit_op1(ir, OPCODE_TRUNC, result_dst, op[0]);
+      break;
+   case ir_unop_ceil:
+      op[0].negate = ~op[0].negate;
+      ir_to_mesa_emit_op1(ir, OPCODE_FLR, result_dst, op[0]);
+      result_src.negate = ~result_src.negate;
+      break;
+   case ir_unop_floor:
+      ir_to_mesa_emit_op1(ir, OPCODE_FLR, result_dst, op[0]);
+      break;
+   case ir_unop_fract:
+      ir_to_mesa_emit_op1(ir, OPCODE_FRC, result_dst, op[0]);
+      break;
+
+   case ir_binop_min:
+      ir_to_mesa_emit_op2(ir, OPCODE_MIN, result_dst, op[0], op[1]);
+      break;
+   case ir_binop_max:
+      ir_to_mesa_emit_op2(ir, OPCODE_MAX, result_dst, op[0], op[1]);
+      break;
+   case ir_binop_pow:
+      ir_to_mesa_emit_scalar_op2(ir, OPCODE_POW, result_dst, op[0], op[1]);
+      break;
+
+   case ir_unop_bit_not:
+   case ir_unop_u2f:
+   case ir_binop_lshift:
+   case ir_binop_rshift:
+   case ir_binop_bit_and:
+   case ir_binop_bit_xor:
+   case ir_binop_bit_or:
+      assert(!"GLSL 1.30 features unsupported");
+      break;
+   }
+
+   this->result = result_src;
+}
+
+
+void
+ir_to_mesa_visitor::visit(ir_swizzle *ir)
+{
+   ir_to_mesa_src_reg src_reg;
+   int i;
+   int swizzle[4];
+
+   /* Note that this is only swizzles in expressions, not those on the left
+    * hand side of an assignment, which do write masking.  See ir_assignment
+    * for that.
+    */
+
+   ir->val->accept(this);
+   src_reg = this->result;
+   assert(src_reg.file != PROGRAM_UNDEFINED);
+
+   for (i = 0; i < 4; i++) {
+      if (i < ir->type->vector_elements) {
+        switch (i) {
+        case 0:
+           swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.x);
+           break;
+        case 1:
+           swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.y);
+           break;
+        case 2:
+           swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.z);
+           break;
+        case 3:
+           swizzle[i] = GET_SWZ(src_reg.swizzle, ir->mask.w);
+           break;
+        }
+      } else {
+        /* If the type is smaller than a vec4, replicate the last
+         * channel out.
+         */
+        swizzle[i] = swizzle[ir->type->vector_elements - 1];
+      }
+   }
+
+   src_reg.swizzle = MAKE_SWIZZLE4(swizzle[0],
+                                  swizzle[1],
+                                  swizzle[2],
+                                  swizzle[3]);
+
+   this->result = src_reg;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
+{
+   variable_storage *entry = find_variable_storage(ir->var);
+
+   if (!entry) {
+      switch (ir->var->mode) {
+      case ir_var_uniform:
+        entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_UNIFORM,
+                                              ir->var->location);
+        this->variables.push_tail(entry);
+        break;
+      case ir_var_in:
+      case ir_var_out:
+      case ir_var_inout:
+        /* The linker assigns locations for varyings and attributes,
+         * including deprecated builtins (like gl_Color), user-assign
+         * generic attributes (glBindVertexLocation), and
+         * user-defined varyings.
+         *
+         * FINISHME: We would hit this path for function arguments.  Fix!
+         */
+        assert(ir->var->location != -1);
+        if (ir->var->mode == ir_var_in ||
+            ir->var->mode == ir_var_inout) {
+           entry = new(mem_ctx) variable_storage(ir->var,
+                                                 PROGRAM_INPUT,
+                                                 ir->var->location);
+
+           if (this->prog->Target == GL_VERTEX_PROGRAM_ARB &&
+               ir->var->location >= VERT_ATTRIB_GENERIC0) {
+              _mesa_add_attribute(prog->Attributes,
+                                  ir->var->name,
+                                  _mesa_sizeof_glsl_type(ir->var->type->gl_type),
+                                  ir->var->type->gl_type,
+                                  ir->var->location - VERT_ATTRIB_GENERIC0);
+           }
+        } else {
+           entry = new(mem_ctx) variable_storage(ir->var,
+                                                 PROGRAM_OUTPUT,
+                                                 ir->var->location);
+        }
+
+        break;
+      case ir_var_auto:
+      case ir_var_temporary:
+        entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_TEMPORARY,
+                                              this->next_temp);
+        this->variables.push_tail(entry);
+
+        next_temp += type_size(ir->var->type);
+        break;
+      }
+
+      if (!entry) {
+        printf("Failed to make storage for %s\n", ir->var->name);
+        exit(1);
+      }
+   }
+
+   this->result = ir_to_mesa_src_reg(entry->file, entry->index, ir->var->type);
+}
+
+void
+ir_to_mesa_visitor::visit(ir_dereference_array *ir)
+{
+   ir_constant *index;
+   ir_to_mesa_src_reg src_reg;
+   int element_size = type_size(ir->type);
+
+   index = ir->array_index->constant_expression_value();
+
+   ir->array->accept(this);
+   src_reg = this->result;
+
+   if (index) {
+      src_reg.index += index->value.i[0] * element_size;
+   } else {
+      ir_to_mesa_src_reg array_base = this->result;
+      /* Variable index array dereference.  It eats the "vec4" of the
+       * base of the array and an index that offsets the Mesa register
+       * index.
+       */
+      ir->array_index->accept(this);
+
+      ir_to_mesa_src_reg index_reg;
+
+      if (element_size == 1) {
+        index_reg = this->result;
+      } else {
+        index_reg = get_temp(glsl_type::float_type);
+
+        ir_to_mesa_emit_op2(ir, OPCODE_MUL,
+                            ir_to_mesa_dst_reg_from_src(index_reg),
+                            this->result, src_reg_for_float(element_size));
+      }
+
+      src_reg.reladdr = talloc(mem_ctx, ir_to_mesa_src_reg);
+      memcpy(src_reg.reladdr, &index_reg, sizeof(index_reg));
+   }
+
+   /* If the type is smaller than a vec4, replicate the last channel out. */
+   if (ir->type->is_scalar() || ir->type->is_vector())
+      src_reg.swizzle = swizzle_for_size(ir->type->vector_elements);
+   else
+      src_reg.swizzle = SWIZZLE_NOOP;
+
+   this->result = src_reg;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_dereference_record *ir)
+{
+   unsigned int i;
+   const glsl_type *struct_type = ir->record->type;
+   int offset = 0;
+
+   ir->record->accept(this);
+
+   for (i = 0; i < struct_type->length; i++) {
+      if (strcmp(struct_type->fields.structure[i].name, ir->field) == 0)
+        break;
+      offset += type_size(struct_type->fields.structure[i].type);
+   }
+   this->result.swizzle = swizzle_for_size(ir->type->vector_elements);
+   this->result.index += offset;
+}
+
+/**
+ * We want to be careful in assignment setup to hit the actual storage
+ * instead of potentially using a temporary like we might with the
+ * ir_dereference handler.
+ */
+static struct ir_to_mesa_dst_reg
+get_assignment_lhs(ir_dereference *ir, ir_to_mesa_visitor *v)
+{
+   /* The LHS must be a dereference.  If the LHS is a variable indexed array
+    * access of a vector, it must be separated into a series conditional moves
+    * before reaching this point (see ir_vec_index_to_cond_assign).
+    */
+   assert(ir->as_dereference());
+   ir_dereference_array *deref_array = ir->as_dereference_array();
+   if (deref_array) {
+      assert(!deref_array->array->type->is_vector());
+   }
+
+   /* Use the rvalue deref handler for the most part.  We'll ignore
+    * swizzles in it and write swizzles using writemask, though.
+    */
+   ir->accept(v);
+   return ir_to_mesa_dst_reg_from_src(v->result);
+}
+
+void
+ir_to_mesa_visitor::visit(ir_assignment *ir)
+{
+   struct ir_to_mesa_dst_reg l;
+   struct ir_to_mesa_src_reg r;
+   int i;
+
+   ir->rhs->accept(this);
+   r = this->result;
+
+   l = get_assignment_lhs(ir->lhs, this);
+
+   /* FINISHME: This should really set to the correct maximal writemask for each
+    * FINISHME: component written (in the loops below).  This case can only
+    * FINISHME: occur for matrices, arrays, and structures.
+    */
+   if (ir->write_mask == 0) {
+      assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector());
+      l.writemask = WRITEMASK_XYZW;
+   } else if (ir->lhs->type->is_scalar()) {
+      /* FINISHME: This hack makes writing to gl_FragData, which lives in the
+       * FINISHME: W component of fragment shader output zero, work correctly.
+       */
+      l.writemask = WRITEMASK_XYZW;
+   } else {
+      assert(ir->lhs->type->is_vector());
+      l.writemask = ir->write_mask;
+   }
+
+   assert(l.file != PROGRAM_UNDEFINED);
+   assert(r.file != PROGRAM_UNDEFINED);
+
+   if (ir->condition) {
+      ir_to_mesa_src_reg condition;
+
+      ir->condition->accept(this);
+      condition = this->result;
+
+      /* We use the OPCODE_CMP (a < 0 ? b : c) for conditional moves,
+       * and the condition we produced is 0.0 or 1.0.  By flipping the
+       * sign, we can choose which value OPCODE_CMP produces without
+       * an extra computing the condition.
+       */
+      condition.negate = ~condition.negate;
+      for (i = 0; i < type_size(ir->lhs->type); i++) {
+        ir_to_mesa_emit_op3(ir, OPCODE_CMP, l,
+                            condition, r, ir_to_mesa_src_reg_from_dst(l));
+        l.index++;
+        r.index++;
+      }
+   } else {
+      for (i = 0; i < type_size(ir->lhs->type); i++) {
+        ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+        l.index++;
+        r.index++;
+      }
+   }
+}
+
+
+void
+ir_to_mesa_visitor::visit(ir_constant *ir)
+{
+   ir_to_mesa_src_reg src_reg;
+   GLfloat stack_vals[4] = { 0 };
+   GLfloat *values = stack_vals;
+   unsigned int i;
+
+   /* Unfortunately, 4 floats is all we can get into
+    * _mesa_add_unnamed_constant.  So, make a temp to store an
+    * aggregate constant and move each constant value into it.  If we
+    * get lucky, copy propagation will eliminate the extra moves.
+    */
+
+   if (ir->type->base_type == GLSL_TYPE_STRUCT) {
+      ir_to_mesa_src_reg temp_base = get_temp(ir->type);
+      ir_to_mesa_dst_reg temp = ir_to_mesa_dst_reg_from_src(temp_base);
+
+      foreach_iter(exec_list_iterator, iter, ir->components) {
+        ir_constant *field_value = (ir_constant *)iter.get();
+        int size = type_size(field_value->type);
+
+        assert(size > 0);
+
+        field_value->accept(this);
+        src_reg = this->result;
+
+        for (i = 0; i < (unsigned int)size; i++) {
+           ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, src_reg);
+
+           src_reg.index++;
+           temp.index++;
+        }
+      }
+      this->result = temp_base;
+      return;
+   }
+
+   if (ir->type->is_array()) {
+      ir_to_mesa_src_reg temp_base = get_temp(ir->type);
+      ir_to_mesa_dst_reg temp = ir_to_mesa_dst_reg_from_src(temp_base);
+      int size = type_size(ir->type->fields.array);
+
+      assert(size > 0);
+
+      for (i = 0; i < ir->type->length; i++) {
+        ir->array_elements[i]->accept(this);
+        src_reg = this->result;
+        for (int j = 0; j < size; j++) {
+           ir_to_mesa_emit_op1(ir, OPCODE_MOV, temp, src_reg);
+
+           src_reg.index++;
+           temp.index++;
+        }
+      }
+      this->result = temp_base;
+      return;
+   }
+
+   if (ir->type->is_matrix()) {
+      ir_to_mesa_src_reg mat = get_temp(ir->type);
+      ir_to_mesa_dst_reg mat_column = ir_to_mesa_dst_reg_from_src(mat);
+
+      for (i = 0; i < ir->type->matrix_columns; i++) {
+        assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+        values = &ir->value.f[i * ir->type->vector_elements];
+
+        src_reg = ir_to_mesa_src_reg(PROGRAM_CONSTANT, -1, NULL);
+        src_reg.index = _mesa_add_unnamed_constant(this->prog->Parameters,
+                                               values,
+                                               ir->type->vector_elements,
+                                               &src_reg.swizzle);
+        ir_to_mesa_emit_op1(ir, OPCODE_MOV, mat_column, src_reg);
+
+        mat_column.index++;
+      }
+
+      this->result = mat;
+      return;
+   }
+
+   src_reg.file = PROGRAM_CONSTANT;
+   switch (ir->type->base_type) {
+   case GLSL_TYPE_FLOAT:
+      values = &ir->value.f[0];
+      break;
+   case GLSL_TYPE_UINT:
+      for (i = 0; i < ir->type->vector_elements; i++) {
+        values[i] = ir->value.u[i];
+      }
+      break;
+   case GLSL_TYPE_INT:
+      for (i = 0; i < ir->type->vector_elements; i++) {
+        values[i] = ir->value.i[i];
+      }
+      break;
+   case GLSL_TYPE_BOOL:
+      for (i = 0; i < ir->type->vector_elements; i++) {
+        values[i] = ir->value.b[i];
+      }
+      break;
+   default:
+      assert(!"Non-float/uint/int/bool constant");
+   }
+
+   this->result = ir_to_mesa_src_reg(PROGRAM_CONSTANT, -1, ir->type);
+   this->result.index = _mesa_add_unnamed_constant(this->prog->Parameters,
+                                                  values,
+                                                  ir->type->vector_elements,
+                                                  &this->result.swizzle);
+}
+
+function_entry *
+ir_to_mesa_visitor::get_function_signature(ir_function_signature *sig)
+{
+   function_entry *entry;
+
+   foreach_iter(exec_list_iterator, iter, this->function_signatures) {
+      entry = (function_entry *)iter.get();
+
+      if (entry->sig == sig)
+        return entry;
+   }
+
+   entry = talloc(mem_ctx, function_entry);
+   entry->sig = sig;
+   entry->sig_id = this->next_signature_id++;
+   entry->bgn_inst = NULL;
+
+   /* Allocate storage for all the parameters. */
+   foreach_iter(exec_list_iterator, iter, sig->parameters) {
+      ir_variable *param = (ir_variable *)iter.get();
+      variable_storage *storage;
+
+      storage = find_variable_storage(param);
+      assert(!storage);
+
+      storage = new(mem_ctx) variable_storage(param, PROGRAM_TEMPORARY,
+                                             this->next_temp);
+      this->variables.push_tail(storage);
+
+      this->next_temp += type_size(param->type);
+   }
+
+   if (!sig->return_type->is_void()) {
+      entry->return_reg = get_temp(sig->return_type);
+   } else {
+      entry->return_reg = ir_to_mesa_undef;
+   }
+
+   this->function_signatures.push_tail(entry);
+   return entry;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_call *ir)
+{
+   ir_to_mesa_instruction *call_inst;
+   ir_function_signature *sig = ir->get_callee();
+   function_entry *entry = get_function_signature(sig);
+   int i;
+
+   /* Process in parameters. */
+   exec_list_iterator sig_iter = sig->parameters.iterator();
+   foreach_iter(exec_list_iterator, iter, *ir) {
+      ir_rvalue *param_rval = (ir_rvalue *)iter.get();
+      ir_variable *param = (ir_variable *)sig_iter.get();
+
+      if (param->mode == ir_var_in ||
+         param->mode == ir_var_inout) {
+        variable_storage *storage = find_variable_storage(param);
+        assert(storage);
+
+        param_rval->accept(this);
+        ir_to_mesa_src_reg r = this->result;
+
+        ir_to_mesa_dst_reg l;
+        l.file = storage->file;
+        l.index = storage->index;
+        l.reladdr = NULL;
+        l.writemask = WRITEMASK_XYZW;
+        l.cond_mask = COND_TR;
+
+        for (i = 0; i < type_size(param->type); i++) {
+           ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+           l.index++;
+           r.index++;
+        }
+      }
+
+      sig_iter.next();
+   }
+   assert(!sig_iter.has_next());
+
+   /* Emit call instruction */
+   call_inst = ir_to_mesa_emit_op1(ir, OPCODE_CAL,
+                                  ir_to_mesa_undef_dst, ir_to_mesa_undef);
+   call_inst->function = entry;
+
+   /* Process out parameters. */
+   sig_iter = sig->parameters.iterator();
+   foreach_iter(exec_list_iterator, iter, *ir) {
+      ir_rvalue *param_rval = (ir_rvalue *)iter.get();
+      ir_variable *param = (ir_variable *)sig_iter.get();
+
+      if (param->mode == ir_var_out ||
+         param->mode == ir_var_inout) {
+        variable_storage *storage = find_variable_storage(param);
+        assert(storage);
+
+        ir_to_mesa_src_reg r;
+        r.file = storage->file;
+        r.index = storage->index;
+        r.reladdr = NULL;
+        r.swizzle = SWIZZLE_NOOP;
+        r.negate = 0;
+
+        param_rval->accept(this);
+        ir_to_mesa_dst_reg l = ir_to_mesa_dst_reg_from_src(this->result);
+
+        for (i = 0; i < type_size(param->type); i++) {
+           ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+           l.index++;
+           r.index++;
+        }
+      }
+
+      sig_iter.next();
+   }
+   assert(!sig_iter.has_next());
+
+   /* Process return value. */
+   this->result = entry->return_reg;
+}
+
+class get_sampler_name : public ir_hierarchical_visitor
+{
+public:
+   get_sampler_name(ir_to_mesa_visitor *mesa, ir_dereference *last)
+   {
+      this->mem_ctx = mesa->mem_ctx;
+      this->mesa = mesa;
+      this->name = NULL;
+      this->offset = 0;
+      this->last = last;
+   }
+
+   virtual ir_visitor_status visit(ir_dereference_variable *ir)
+   {
+      this->name = ir->var->name;
+      return visit_continue;
+   }
+
+   virtual ir_visitor_status visit_leave(ir_dereference_record *ir)
+   {
+      this->name = talloc_asprintf(mem_ctx, "%s.%s", name, ir->field);
+      return visit_continue;
+   }
+
+   virtual ir_visitor_status visit_leave(ir_dereference_array *ir)
+   {
+      ir_constant *index = ir->array_index->as_constant();
+      int i;
+
+      if (index) {
+        i = index->value.i[0];
+      } else {
+        /* GLSL 1.10 and 1.20 allowed variable sampler array indices,
+         * while GLSL 1.30 requires that the array indices be
+         * constant integer expressions.  We don't expect any driver
+         * to actually work with a really variable array index, so
+         * all that would work would be an unrolled loop counter that ends
+         * up being constant above.
+         */
+        mesa->shader_program->InfoLog =
+           talloc_asprintf_append(mesa->shader_program->InfoLog,
+                                  "warning: Variable sampler array index "
+                                  "unsupported.\nThis feature of the language "
+                                  "was removed in GLSL 1.20 and is unlikely "
+                                  "to be supported for 1.10 in Mesa.\n");
+        i = 0;
+      }
+      if (ir != last) {
+        this->name = talloc_asprintf(mem_ctx, "%s[%d]", name, i);
+      } else {
+        offset = i;
+      }
+      return visit_continue;
+   }
+
+   ir_to_mesa_visitor *mesa;
+   const char *name;
+   void *mem_ctx;
+   int offset;
+   ir_dereference *last;
+};
+
+int
+ir_to_mesa_visitor::get_sampler_uniform_value(ir_dereference *sampler)
+{
+   get_sampler_name getname(this, sampler);
+
+   sampler->accept(&getname);
+
+   GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1,
+                                             getname.name);
+
+   if (index < 0) {
+      fail_link(this->shader_program,
+               "failed to find sampler named %s.\n", getname.name);
+      return 0;
+   }
+
+   index += getname.offset;
+
+   return this->prog->Parameters->ParameterValues[index][0];
+}
+
+void
+ir_to_mesa_visitor::visit(ir_texture *ir)
+{
+   ir_to_mesa_src_reg result_src, coord, lod_info, projector;
+   ir_to_mesa_dst_reg result_dst, coord_dst;
+   ir_to_mesa_instruction *inst = NULL;
+   prog_opcode opcode = OPCODE_NOP;
+
+   ir->coordinate->accept(this);
+
+   /* Put our coords in a temp.  We'll need to modify them for shadow,
+    * projection, or LOD, so the only case we'd use it as is is if
+    * we're doing plain old texturing.  Mesa IR optimization should
+    * handle cleaning up our mess in that case.
+    */
+   coord = get_temp(glsl_type::vec4_type);
+   coord_dst = ir_to_mesa_dst_reg_from_src(coord);
+   ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst,
+                      this->result);
+
+   if (ir->projector) {
+      ir->projector->accept(this);
+      projector = this->result;
+   }
+
+   /* Storage for our result.  Ideally for an assignment we'd be using
+    * the actual storage for the result here, instead.
+    */
+   result_src = get_temp(glsl_type::vec4_type);
+   result_dst = ir_to_mesa_dst_reg_from_src(result_src);
+
+   switch (ir->op) {
+   case ir_tex:
+      opcode = OPCODE_TEX;
+      break;
+   case ir_txb:
+      opcode = OPCODE_TXB;
+      ir->lod_info.bias->accept(this);
+      lod_info = this->result;
+      break;
+   case ir_txl:
+      opcode = OPCODE_TXL;
+      ir->lod_info.lod->accept(this);
+      lod_info = this->result;
+      break;
+   case ir_txd:
+   case ir_txf:
+      assert(!"GLSL 1.30 features unsupported");
+      break;
+   }
+
+   if (ir->projector) {
+      if (opcode == OPCODE_TEX) {
+        /* Slot the projector in as the last component of the coord. */
+        coord_dst.writemask = WRITEMASK_W;
+        ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst, projector);
+        coord_dst.writemask = WRITEMASK_XYZW;
+        opcode = OPCODE_TXP;
+      } else {
+        ir_to_mesa_src_reg coord_w = coord;
+        coord_w.swizzle = SWIZZLE_WWWW;
+
+        /* For the other TEX opcodes there's no projective version
+         * since the last slot is taken up by lod info.  Do the
+         * projective divide now.
+         */
+        coord_dst.writemask = WRITEMASK_W;
+        ir_to_mesa_emit_op1(ir, OPCODE_RCP, coord_dst, projector);
+
+        coord_dst.writemask = WRITEMASK_XYZ;
+        ir_to_mesa_emit_op2(ir, OPCODE_MUL, coord_dst, coord, coord_w);
+
+        coord_dst.writemask = WRITEMASK_XYZW;
+        coord.swizzle = SWIZZLE_XYZW;
+      }
+   }
+
+   if (ir->shadow_comparitor) {
+      /* Slot the shadow value in as the second to last component of the
+       * coord.
+       */
+      ir->shadow_comparitor->accept(this);
+      coord_dst.writemask = WRITEMASK_Z;
+      ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst, this->result);
+      coord_dst.writemask = WRITEMASK_XYZW;
+   }
+
+   if (opcode == OPCODE_TXL || opcode == OPCODE_TXB) {
+      /* Mesa IR stores lod or lod bias in the last channel of the coords. */
+      coord_dst.writemask = WRITEMASK_W;
+      ir_to_mesa_emit_op1(ir, OPCODE_MOV, coord_dst, lod_info);
+      coord_dst.writemask = WRITEMASK_XYZW;
+   }
+
+   inst = ir_to_mesa_emit_op1(ir, opcode, result_dst, coord);
+
+   if (ir->shadow_comparitor)
+      inst->tex_shadow = GL_TRUE;
+
+   inst->sampler = get_sampler_uniform_value(ir->sampler);
+
+   const glsl_type *sampler_type = ir->sampler->type;
+
+   switch (sampler_type->sampler_dimensionality) {
+   case GLSL_SAMPLER_DIM_1D:
+      inst->tex_target = (sampler_type->sampler_array)
+        ? TEXTURE_1D_ARRAY_INDEX : TEXTURE_1D_INDEX;
+      break;
+   case GLSL_SAMPLER_DIM_2D:
+      inst->tex_target = (sampler_type->sampler_array)
+        ? TEXTURE_2D_ARRAY_INDEX : TEXTURE_2D_INDEX;
+      break;
+   case GLSL_SAMPLER_DIM_3D:
+      inst->tex_target = TEXTURE_3D_INDEX;
+      break;
+   case GLSL_SAMPLER_DIM_CUBE:
+      inst->tex_target = TEXTURE_CUBE_INDEX;
+      break;
+   case GLSL_SAMPLER_DIM_RECT:
+      inst->tex_target = TEXTURE_RECT_INDEX;
+      break;
+   case GLSL_SAMPLER_DIM_BUF:
+      assert(!"FINISHME: Implement ARB_texture_buffer_object");
+      break;
+   default:
+      assert(!"Should not get here.");
+   }
+
+   this->result = result_src;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_return *ir)
+{
+   if (ir->get_value()) {
+      ir_to_mesa_dst_reg l;
+      int i;
+
+      assert(current_function);
+
+      ir->get_value()->accept(this);
+      ir_to_mesa_src_reg r = this->result;
+
+      l = ir_to_mesa_dst_reg_from_src(current_function->return_reg);
+
+      for (i = 0; i < type_size(current_function->sig->return_type); i++) {
+        ir_to_mesa_emit_op1(ir, OPCODE_MOV, l, r);
+        l.index++;
+        r.index++;
+      }
+   }
+
+   ir_to_mesa_emit_op0(ir, OPCODE_RET);
+}
+
+void
+ir_to_mesa_visitor::visit(ir_discard *ir)
+{
+   struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog;
+
+   assert(ir->condition == NULL); /* FINISHME */
+
+   ir_to_mesa_emit_op0(ir, OPCODE_KIL_NV);
+   fp->UsesKill = GL_TRUE;
+}
+
+void
+ir_to_mesa_visitor::visit(ir_if *ir)
+{
+   ir_to_mesa_instruction *cond_inst, *if_inst, *else_inst = NULL;
+   ir_to_mesa_instruction *prev_inst;
+
+   prev_inst = (ir_to_mesa_instruction *)this->instructions.get_tail();
+
+   ir->condition->accept(this);
+   assert(this->result.file != PROGRAM_UNDEFINED);
+
+   if (ctx->Shader.EmitCondCodes) {
+      cond_inst = (ir_to_mesa_instruction *)this->instructions.get_tail();
+
+      /* See if we actually generated any instruction for generating
+       * the condition.  If not, then cook up a move to a temp so we
+       * have something to set cond_update on.
+       */
+      if (cond_inst == prev_inst) {
+        ir_to_mesa_src_reg temp = get_temp(glsl_type::bool_type);
+        cond_inst = ir_to_mesa_emit_op1(ir->condition, OPCODE_MOV,
+                                        ir_to_mesa_dst_reg_from_src(temp),
+                                        result);
+      }
+      cond_inst->cond_update = GL_TRUE;
+
+      if_inst = ir_to_mesa_emit_op0(ir->condition, OPCODE_IF);
+      if_inst->dst_reg.cond_mask = COND_NE;
+   } else {
+      if_inst = ir_to_mesa_emit_op1(ir->condition,
+                                   OPCODE_IF, ir_to_mesa_undef_dst,
+                                   this->result);
+   }
+
+   this->instructions.push_tail(if_inst);
+
+   visit_exec_list(&ir->then_instructions, this);
+
+   if (!ir->else_instructions.is_empty()) {
+      else_inst = ir_to_mesa_emit_op0(ir->condition, OPCODE_ELSE);
+      visit_exec_list(&ir->else_instructions, this);
+   }
+
+   if_inst = ir_to_mesa_emit_op1(ir->condition, OPCODE_ENDIF,
+                                ir_to_mesa_undef_dst, ir_to_mesa_undef);
+}
+
+ir_to_mesa_visitor::ir_to_mesa_visitor()
+{
+   result.file = PROGRAM_UNDEFINED;
+   next_temp = 1;
+   next_signature_id = 1;
+   current_function = NULL;
+   mem_ctx = talloc_new(NULL);
+}
+
+ir_to_mesa_visitor::~ir_to_mesa_visitor()
+{
+   talloc_free(mem_ctx);
+}
+
+static struct prog_src_register
+mesa_src_reg_from_ir_src_reg(ir_to_mesa_src_reg reg)
+{
+   struct prog_src_register mesa_reg;
+
+   mesa_reg.File = reg.file;
+   assert(reg.index < (1 << INST_INDEX_BITS) - 1);
+   mesa_reg.Index = reg.index;
+   mesa_reg.Swizzle = reg.swizzle;
+   mesa_reg.RelAddr = reg.reladdr != NULL;
+   mesa_reg.Negate = reg.negate;
+   mesa_reg.Abs = 0;
+   mesa_reg.HasIndex2 = GL_FALSE;
+   mesa_reg.RelAddr2 = 0;
+   mesa_reg.Index2 = 0;
+
+   return mesa_reg;
+}
+
+static void
+set_branchtargets(ir_to_mesa_visitor *v,
+                 struct prog_instruction *mesa_instructions,
+                 int num_instructions)
+{
+   int if_count = 0, loop_count = 0;
+   int *if_stack, *loop_stack;
+   int if_stack_pos = 0, loop_stack_pos = 0;
+   int i, j;
+
+   for (i = 0; i < num_instructions; i++) {
+      switch (mesa_instructions[i].Opcode) {
+      case OPCODE_IF:
+        if_count++;
+        break;
+      case OPCODE_BGNLOOP:
+        loop_count++;
+        break;
+      case OPCODE_BRK:
+      case OPCODE_CONT:
+        mesa_instructions[i].BranchTarget = -1;
+        break;
+      default:
+        break;
+      }
+   }
+
+   if_stack = talloc_zero_array(v->mem_ctx, int, if_count);
+   loop_stack = talloc_zero_array(v->mem_ctx, int, loop_count);
+
+   for (i = 0; i < num_instructions; i++) {
+      switch (mesa_instructions[i].Opcode) {
+      case OPCODE_IF:
+        if_stack[if_stack_pos] = i;
+        if_stack_pos++;
+        break;
+      case OPCODE_ELSE:
+        mesa_instructions[if_stack[if_stack_pos - 1]].BranchTarget = i;
+        if_stack[if_stack_pos - 1] = i;
+        break;
+      case OPCODE_ENDIF:
+        mesa_instructions[if_stack[if_stack_pos - 1]].BranchTarget = i;
+        if_stack_pos--;
+        break;
+      case OPCODE_BGNLOOP:
+        loop_stack[loop_stack_pos] = i;
+        loop_stack_pos++;
+        break;
+      case OPCODE_ENDLOOP:
+        loop_stack_pos--;
+        /* Rewrite any breaks/conts at this nesting level (haven't
+         * already had a BranchTarget assigned) to point to the end
+         * of the loop.
+         */
+        for (j = loop_stack[loop_stack_pos]; j < i; j++) {
+           if (mesa_instructions[j].Opcode == OPCODE_BRK ||
+               mesa_instructions[j].Opcode == OPCODE_CONT) {
+              if (mesa_instructions[j].BranchTarget == -1) {
+                 mesa_instructions[j].BranchTarget = i;
+              }
+           }
+        }
+        /* The loop ends point at each other. */
+        mesa_instructions[i].BranchTarget = loop_stack[loop_stack_pos];
+        mesa_instructions[loop_stack[loop_stack_pos]].BranchTarget = i;
+        break;
+      case OPCODE_CAL:
+        foreach_iter(exec_list_iterator, iter, v->function_signatures) {
+           function_entry *entry = (function_entry *)iter.get();
+
+           if (entry->sig_id == mesa_instructions[i].BranchTarget) {
+              mesa_instructions[i].BranchTarget = entry->inst;
+              break;
+           }
+        }
+        break;
+      default:
+        break;
+      }
+   }
+}
+
+static void
+print_program(struct prog_instruction *mesa_instructions,
+             ir_instruction **mesa_instruction_annotation,
+             int num_instructions)
+{
+   ir_instruction *last_ir = NULL;
+   int i;
+   int indent = 0;
+
+   for (i = 0; i < num_instructions; i++) {
+      struct prog_instruction *mesa_inst = mesa_instructions + i;
+      ir_instruction *ir = mesa_instruction_annotation[i];
+
+      fprintf(stdout, "%3d: ", i);
+
+      if (last_ir != ir && ir) {
+        int j;
+
+        for (j = 0; j < indent; j++) {
+           fprintf(stdout, " ");
+        }
+        ir->print();
+        printf("\n");
+        last_ir = ir;
+
+        fprintf(stdout, "     "); /* line number spacing. */
+      }
+
+      indent = _mesa_fprint_instruction_opt(stdout, mesa_inst, indent,
+                                           PROG_PRINT_DEBUG, NULL);
+   }
+}
+
+static void
+count_resources(struct gl_program *prog)
+{
+   unsigned int i;
+
+   prog->SamplersUsed = 0;
+
+   for (i = 0; i < prog->NumInstructions; i++) {
+      struct prog_instruction *inst = &prog->Instructions[i];
+
+      if (_mesa_is_tex_instruction(inst->Opcode)) {
+        prog->SamplerTargets[inst->TexSrcUnit] =
+           (gl_texture_index)inst->TexSrcTarget;
+        prog->SamplersUsed |= 1 << inst->TexSrcUnit;
+        if (inst->TexShadow) {
+           prog->ShadowSamplers |= 1 << inst->TexSrcUnit;
+        }
+      }
+   }
+
+   _mesa_update_shader_textures_used(prog);
+}
+
+struct uniform_sort {
+   struct gl_uniform *u;
+   int pos;
+};
+
+/* The shader_program->Uniforms list is almost sorted in increasing
+ * uniform->{Frag,Vert}Pos locations, but not quite when there are
+ * uniforms shared between targets.  We need to add parameters in
+ * increasing order for the targets.
+ */
+static int
+sort_uniforms(const void *a, const void *b)
+{
+   struct uniform_sort *u1 = (struct uniform_sort *)a;
+   struct uniform_sort *u2 = (struct uniform_sort *)b;
+
+   return u1->pos - u2->pos;
+}
+
+/* Add the uniforms to the parameters.  The linker chose locations
+ * in our parameters lists (which weren't created yet), which the
+ * uniforms code will use to poke values into our parameters list
+ * when uniforms are updated.
+ */
+static void
+add_uniforms_to_parameters_list(struct gl_shader_program *shader_program,
+                               struct gl_shader *shader,
+                               struct gl_program *prog)
+{
+   unsigned int i;
+   unsigned int next_sampler = 0, num_uniforms = 0;
+   struct uniform_sort *sorted_uniforms;
+
+   sorted_uniforms = talloc_array(NULL, struct uniform_sort,
+                                 shader_program->Uniforms->NumUniforms);
+
+   for (i = 0; i < shader_program->Uniforms->NumUniforms; i++) {
+      struct gl_uniform *uniform = shader_program->Uniforms->Uniforms + i;
+      int parameter_index = -1;
+
+      switch (shader->Type) {
+      case GL_VERTEX_SHADER:
+        parameter_index = uniform->VertPos;
+        break;
+      case GL_FRAGMENT_SHADER:
+        parameter_index = uniform->FragPos;
+        break;
+      case GL_GEOMETRY_SHADER:
+        parameter_index = uniform->GeomPos;
+        break;
+      }
+
+      /* Only add uniforms used in our target. */
+      if (parameter_index != -1) {
+        sorted_uniforms[num_uniforms].pos = parameter_index;
+        sorted_uniforms[num_uniforms].u = uniform;
+        num_uniforms++;
+      }
+   }
+
+   qsort(sorted_uniforms, num_uniforms, sizeof(struct uniform_sort),
+        sort_uniforms);
+
+   for (i = 0; i < num_uniforms; i++) {
+      struct gl_uniform *uniform = sorted_uniforms[i].u;
+      int parameter_index = sorted_uniforms[i].pos;
+      const glsl_type *type = uniform->Type;
+      unsigned int size;
+
+      if (type->is_vector() ||
+         type->is_scalar()) {
+        size = type->vector_elements;
+      } else {
+        size = type_size(type) * 4;
+      }
+
+      gl_register_file file;
+      if (type->is_sampler() ||
+         (type->is_array() && type->fields.array->is_sampler())) {
+        file = PROGRAM_SAMPLER;
+      } else {
+        file = PROGRAM_UNIFORM;
+      }
+
+      GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1,
+                                                uniform->Name);
+
+      if (index < 0) {
+        index = _mesa_add_parameter(prog->Parameters, file,
+                                    uniform->Name, size, type->gl_type,
+                                    NULL, NULL, 0x0);
+
+        /* Sampler uniform values are stored in prog->SamplerUnits,
+         * and the entry in that array is selected by this index we
+         * store in ParameterValues[].
+         */
+        if (file == PROGRAM_SAMPLER) {
+           for (unsigned int j = 0; j < size / 4; j++)
+              prog->Parameters->ParameterValues[index + j][0] = next_sampler++;
+        }
+
+        /* The location chosen in the Parameters list here (returned
+         * from _mesa_add_uniform) has to match what the linker chose.
+         */
+        if (index != parameter_index) {
+           fail_link(shader_program, "Allocation of uniform `%s' to target "
+                     "failed (%d vs %d)\n",
+                     uniform->Name, index, parameter_index);
+        }
+      }
+   }
+
+   talloc_free(sorted_uniforms);
+}
+
+static void
+set_uniform_initializer(GLcontext *ctx, void *mem_ctx,
+                       struct gl_shader_program *shader_program,
+                       const char *name, const glsl_type *type,
+                       ir_constant *val)
+{
+   if (type->is_record()) {
+      ir_constant *field_constant;
+
+      field_constant = (ir_constant *)val->components.get_head();
+
+      for (unsigned int i = 0; i < type->length; i++) {
+        const glsl_type *field_type = type->fields.structure[i].type;
+        const char *field_name = talloc_asprintf(mem_ctx, "%s.%s", name,
+                                           type->fields.structure[i].name);
+        set_uniform_initializer(ctx, mem_ctx, shader_program, field_name,
+                                field_type, field_constant);
+        field_constant = (ir_constant *)field_constant->next;
+      }
+      return;
+   }
+
+   int loc = _mesa_get_uniform_location(ctx, shader_program, name);
+
+   if (loc == -1) {
+      fail_link(shader_program,
+               "Couldn't find uniform for initializer %s\n", name);
+      return;
+   }
+
+   for (unsigned int i = 0; i < (type->is_array() ? type->length : 1); i++) {
+      ir_constant *element;
+      const glsl_type *element_type;
+      if (type->is_array()) {
+        element = val->array_elements[i];
+        element_type = type->fields.array;
+      } else {
+        element = val;
+        element_type = type;
+      }
+
+      void *values;
+
+      if (element_type->base_type == GLSL_TYPE_BOOL) {
+        int *conv = talloc_array(mem_ctx, int, element_type->components());
+        for (unsigned int j = 0; j < element_type->components(); j++) {
+           conv[j] = element->value.b[j];
+        }
+        values = (void *)conv;
+        element_type = glsl_type::get_instance(GLSL_TYPE_INT,
+                                               element_type->vector_elements,
+                                               1);
+      } else {
+        values = &element->value;
+      }
+
+      if (element_type->is_matrix()) {
+        _mesa_uniform_matrix(ctx, shader_program,
+                             element_type->matrix_columns,
+                             element_type->vector_elements,
+                             loc, 1, GL_FALSE, (GLfloat *)values);
+        loc += element_type->matrix_columns;
+      } else {
+        _mesa_uniform(ctx, shader_program, loc, element_type->matrix_columns,
+                      values, element_type->gl_type);
+        loc += type_size(element_type);
+      }
+   }
+}
+
+static void
+set_uniform_initializers(GLcontext *ctx,
+                        struct gl_shader_program *shader_program)
+{
+   void *mem_ctx = NULL;
+
+   for (unsigned int i = 0; i < shader_program->_NumLinkedShaders; i++) {
+      struct gl_shader *shader = shader_program->_LinkedShaders[i];
+      foreach_iter(exec_list_iterator, iter, *shader->ir) {
+        ir_instruction *ir = (ir_instruction *)iter.get();
+        ir_variable *var = ir->as_variable();
+
+        if (!var || var->mode != ir_var_uniform || !var->constant_value)
+           continue;
+
+        if (!mem_ctx)
+           mem_ctx = talloc_new(NULL);
+
+        set_uniform_initializer(ctx, mem_ctx, shader_program, var->name,
+                                var->type, var->constant_value);
+      }
+   }
+
+   talloc_free(mem_ctx);
+}
+
+struct gl_program *
+get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program,
+                struct gl_shader *shader)
+{
+   ir_to_mesa_visitor v;
+   struct prog_instruction *mesa_instructions, *mesa_inst;
+   ir_instruction **mesa_instruction_annotation;
+   int i;
+   struct gl_program *prog;
+   GLenum target;
+   const char *target_string;
+   GLboolean progress;
+
+   switch (shader->Type) {
+   case GL_VERTEX_SHADER:
+      target = GL_VERTEX_PROGRAM_ARB;
+      target_string = "vertex";
+      break;
+   case GL_FRAGMENT_SHADER:
+      target = GL_FRAGMENT_PROGRAM_ARB;
+      target_string = "fragment";
+      break;
+   default:
+      assert(!"should not be reached");
+      return NULL;
+   }
+
+   validate_ir_tree(shader->ir);
+
+   prog = ctx->Driver.NewProgram(ctx, target, shader_program->Name);
+   if (!prog)
+      return NULL;
+   prog->Parameters = _mesa_new_parameter_list();
+   prog->Varying = _mesa_new_parameter_list();
+   prog->Attributes = _mesa_new_parameter_list();
+   v.ctx = ctx;
+   v.prog = prog;
+   v.shader_program = shader_program;
+
+   add_uniforms_to_parameters_list(shader_program, shader, prog);
+
+   /* Emit Mesa IR for main(). */
+   visit_exec_list(shader->ir, &v);
+   v.ir_to_mesa_emit_op0(NULL, OPCODE_END);
+
+   /* Now emit bodies for any functions that were used. */
+   do {
+      progress = GL_FALSE;
+
+      foreach_iter(exec_list_iterator, iter, v.function_signatures) {
+        function_entry *entry = (function_entry *)iter.get();
+
+        if (!entry->bgn_inst) {
+           v.current_function = entry;
+
+           entry->bgn_inst = v.ir_to_mesa_emit_op0(NULL, OPCODE_BGNSUB);
+           entry->bgn_inst->function = entry;
+
+           visit_exec_list(&entry->sig->body, &v);
+
+           ir_to_mesa_instruction *last;
+           last = (ir_to_mesa_instruction *)v.instructions.get_tail();
+           if (last->op != OPCODE_RET)
+              v.ir_to_mesa_emit_op0(NULL, OPCODE_RET);
+
+           ir_to_mesa_instruction *end;
+           end = v.ir_to_mesa_emit_op0(NULL, OPCODE_ENDSUB);
+           end->function = entry;
+
+           progress = GL_TRUE;
+        }
+      }
+   } while (progress);
+
+   prog->NumTemporaries = v.next_temp;
+
+   int num_instructions = 0;
+   foreach_iter(exec_list_iterator, iter, v.instructions) {
+      num_instructions++;
+   }
+
+   mesa_instructions =
+      (struct prog_instruction *)calloc(num_instructions,
+                                       sizeof(*mesa_instructions));
+   mesa_instruction_annotation = talloc_array(v.mem_ctx, ir_instruction *,
+                                             num_instructions);
+
+   mesa_inst = mesa_instructions;
+   i = 0;
+   foreach_iter(exec_list_iterator, iter, v.instructions) {
+      ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get();
+
+      mesa_inst->Opcode = inst->op;
+      mesa_inst->CondUpdate = inst->cond_update;
+      mesa_inst->DstReg.File = inst->dst_reg.file;
+      mesa_inst->DstReg.Index = inst->dst_reg.index;
+      mesa_inst->DstReg.CondMask = inst->dst_reg.cond_mask;
+      mesa_inst->DstReg.WriteMask = inst->dst_reg.writemask;
+      mesa_inst->DstReg.RelAddr = inst->dst_reg.reladdr != NULL;
+      mesa_inst->SrcReg[0] = mesa_src_reg_from_ir_src_reg(inst->src_reg[0]);
+      mesa_inst->SrcReg[1] = mesa_src_reg_from_ir_src_reg(inst->src_reg[1]);
+      mesa_inst->SrcReg[2] = mesa_src_reg_from_ir_src_reg(inst->src_reg[2]);
+      mesa_inst->TexSrcUnit = inst->sampler;
+      mesa_inst->TexSrcTarget = inst->tex_target;
+      mesa_inst->TexShadow = inst->tex_shadow;
+      mesa_instruction_annotation[i] = inst->ir;
+
+      /* Set IndirectRegisterFiles. */
+      if (mesa_inst->DstReg.RelAddr)
+         prog->IndirectRegisterFiles |= 1 << mesa_inst->DstReg.File;
+
+      for (unsigned src = 0; src < 3; src++)
+         if (mesa_inst->SrcReg[src].RelAddr)
+            prog->IndirectRegisterFiles |= 1 << mesa_inst->SrcReg[src].File;
+
+      if (ctx->Shader.EmitNoIfs && mesa_inst->Opcode == OPCODE_IF) {
+        fail_link(shader_program, "Couldn't flatten if statement\n");
+      }
+
+      switch (mesa_inst->Opcode) {
+      case OPCODE_BGNSUB:
+        inst->function->inst = i;
+        mesa_inst->Comment = strdup(inst->function->sig->function_name());
+        break;
+      case OPCODE_ENDSUB:
+        mesa_inst->Comment = strdup(inst->function->sig->function_name());
+        break;
+      case OPCODE_CAL:
+        mesa_inst->BranchTarget = inst->function->sig_id; /* rewritten later */
+        break;
+      case OPCODE_ARL:
+        prog->NumAddressRegs = 1;
+        break;
+      default:
+        break;
+      }
+
+      mesa_inst++;
+      i++;
+   }
+
+   set_branchtargets(&v, mesa_instructions, num_instructions);
+
+   if (ctx->Shader.Flags & GLSL_DUMP) {
+      printf("\n");
+      printf("GLSL IR for linked %s program %d:\n", target_string,
+            shader_program->Name);
+      _mesa_print_ir(shader->ir, NULL);
+      printf("\n");
+      printf("\n");
+      printf("Mesa IR for linked %s program %d:\n", target_string,
+            shader_program->Name);
+      print_program(mesa_instructions, mesa_instruction_annotation,
+                   num_instructions);
+   }
+
+   prog->Instructions = mesa_instructions;
+   prog->NumInstructions = num_instructions;
+
+   do_set_program_inouts(shader->ir, prog);
+   count_resources(prog);
+
+   _mesa_reference_program(ctx, &shader->Program, prog);
+
+   if ((ctx->Shader.Flags & GLSL_NO_OPT) == 0) {
+      _mesa_optimize_program(ctx, prog);
+   }
+
+   return prog;
+}
+
+extern "C" {
+GLboolean
+_mesa_ir_compile_shader(GLcontext *ctx, struct gl_shader *shader)
+{
+   assert(shader->CompileStatus);
+   (void) ctx;
+
+   return GL_TRUE;
+}
+
+GLboolean
+_mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
+{
+   assert(prog->LinkStatus);
+
+   for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+      bool progress;
+      exec_list *ir = prog->_LinkedShaders[i]->ir;
+
+      do {
+        progress = false;
+
+        /* Lowering */
+        do_mat_op_to_vec(ir);
+        do_mod_to_fract(ir);
+        do_div_to_mul_rcp(ir);
+        do_explog_to_explog2(ir);
+
+        progress = do_common_optimization(ir, true) || progress;
+
+        if (ctx->Shader.EmitNoIfs)
+           progress = do_if_to_cond_assign(ir) || progress;
+
+        progress = do_vec_index_to_cond_assign(ir) || progress;
+      } while (progress);
+
+      validate_ir_tree(ir);
+   }
+
+   for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+      struct gl_program *linked_prog;
+      bool ok = true;
+
+      linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]);
+
+      switch (prog->_LinkedShaders[i]->Type) {
+      case GL_VERTEX_SHADER:
+        _mesa_reference_vertprog(ctx, &prog->VertexProgram,
+                                 (struct gl_vertex_program *)linked_prog);
+        ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
+                                             linked_prog);
+        break;
+      case GL_FRAGMENT_SHADER:
+        _mesa_reference_fragprog(ctx, &prog->FragmentProgram,
+                                 (struct gl_fragment_program *)linked_prog);
+        ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
+                                             linked_prog);
+        break;
+      }
+      if (!ok) {
+        return GL_FALSE;
+      }
+      _mesa_reference_program(ctx, &linked_prog, NULL);
+   }
+
+   return GL_TRUE;
+}
+
+void
+_mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader)
+{
+   struct _mesa_glsl_parse_state *state =
+      new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);
+
+   const char *source = shader->Source;
+   state->error = preprocess(state, &source, &state->info_log,
+                            &ctx->Extensions);
+
+   if (ctx->Shader.Flags & GLSL_DUMP) {
+      printf("GLSL source for shader %d:\n", shader->Name);
+      printf("%s\n", shader->Source);
+   }
+
+   if (!state->error) {
+     _mesa_glsl_lexer_ctor(state, source);
+     _mesa_glsl_parse(state);
+     _mesa_glsl_lexer_dtor(state);
+   }
+
+   talloc_free(shader->ir);
+   shader->ir = new(shader) exec_list;
+   if (!state->error && !state->translation_unit.is_empty())
+      _mesa_ast_to_hir(shader->ir, state);
+
+   if (!state->error && !shader->ir->is_empty()) {
+      validate_ir_tree(shader->ir);
+
+      /* Do some optimization at compile time to reduce shader IR size
+       * and reduce later work if the same shader is linked multiple times
+       */
+      while (do_common_optimization(shader->ir, false))
+        ;
+
+      validate_ir_tree(shader->ir);
+   }
+
+   shader->symbols = state->symbols;
+
+   shader->CompileStatus = !state->error;
+   shader->InfoLog = state->info_log;
+   shader->Version = state->language_version;
+   memcpy(shader->builtins_to_link, state->builtins_to_link,
+         sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link);
+   shader->num_builtins_to_link = state->num_builtins_to_link;
+
+   if (ctx->Shader.Flags & GLSL_LOG) {
+      _mesa_write_shader_to_file(shader);
+   }
+
+   if (ctx->Shader.Flags & GLSL_DUMP) {
+      if (shader->CompileStatus) {
+        printf("GLSL IR for shader %d:\n", shader->Name);
+        _mesa_print_ir(shader->ir, NULL);
+        printf("\n\n");
+      } else {
+        printf("GLSL shader %d failed to compile.\n", shader->Name);
+      }
+      if (shader->InfoLog && shader->InfoLog[0] != 0) {
+        printf("GLSL shader %d info log:\n", shader->Name);
+        printf("%s\n", shader->InfoLog);
+      }
+   }
+
+   /* Retain any live IR, but trash the rest. */
+   reparent_ir(shader->ir, shader->ir);
+
+   talloc_free(state);
+
+   if (shader->CompileStatus) {
+      if (!ctx->Driver.CompileShader(ctx, shader))
+        shader->CompileStatus = GL_FALSE;
+   }
+}
+
+void
+_mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
+{
+   unsigned int i;
+
+   _mesa_clear_shader_program_data(ctx, prog);
+
+   prog->LinkStatus = GL_TRUE;
+
+   for (i = 0; i < prog->NumShaders; i++) {
+      if (!prog->Shaders[i]->CompileStatus) {
+        fail_link(prog, "linking with uncompiled shader");
+        prog->LinkStatus = GL_FALSE;
+      }
+   }
+
+   prog->Varying = _mesa_new_parameter_list();
+   _mesa_reference_vertprog(ctx, &prog->VertexProgram, NULL);
+   _mesa_reference_fragprog(ctx, &prog->FragmentProgram, NULL);
+
+   if (prog->LinkStatus) {
+      link_shaders(ctx, prog);
+   }
+
+   if (prog->LinkStatus) {
+      if (!ctx->Driver.LinkShader(ctx, prog)) {
+        prog->LinkStatus = GL_FALSE;
+      }
+   }
+
+   set_uniform_initializers(ctx, prog);
+
+   if (ctx->Shader.Flags & GLSL_DUMP) {
+      if (!prog->LinkStatus) {
+        printf("GLSL shader program %d failed to link\n", prog->Name);
+      }
+
+      if (prog->InfoLog && prog->InfoLog[0] != 0) {
+        printf("GLSL shader program %d info log:\n", prog->Name);
+        printf("%s\n", prog->InfoLog);
+      }
+   }
+}
+
+} /* extern "C" */
diff --git a/src/mesa/program/ir_to_mesa.h b/src/mesa/program/ir_to_mesa.h
new file mode 100644 (file)
index 0000000..ecaacde
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "main/config.h"
+#include "main/mtypes.h"
+
+void _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *sh);
+void _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog);
+GLboolean _mesa_ir_compile_shader(GLcontext *ctx, struct gl_shader *shader);
+GLboolean _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog);
+
+#ifdef __cplusplus
+}
+#endif
index 1670c91b6ad571757961a711b1bcd753311a0f8b..2ae5bc572af3ec08f402601408160f92b7ff9e12 100644 (file)
@@ -771,6 +771,13 @@ _mesa_execute_program(GLcontext * ctx,
             result[2] = a[2] < 0.0F ? b[2] : c[2];
             result[3] = a[3] < 0.0F ? b[3] : c[3];
             store_vector4(inst, machine, result);
+            if (DEBUG_PROG) {
+               printf("CMP (%g %g %g %g) = (%g %g %g %g) < 0 ? (%g %g %g %g) : (%g %g %g %g)\n",
+                      result[0], result[1], result[2], result[3],
+                      a[0], a[1], a[2], a[3],
+                      b[0], b[1], b[2], b[3],
+                      c[0], c[1], c[2], c[3]);
+            }
          }
          break;
       case OPCODE_COS:
@@ -1679,6 +1686,22 @@ _mesa_execute_program(GLcontext * ctx,
             store_vector4(inst, machine, color);
          }
          break;
+      case OPCODE_TXL:
+         /* Texel lookup with explicit LOD */
+         {
+            GLfloat texcoord[4], color[4], lod;
+
+            fetch_vector4(&inst->SrcReg[0], machine, texcoord);
+
+            /* texcoord[3] is the LOD */
+            lod = texcoord[3];
+
+           machine->FetchTexelLod(ctx, texcoord, lod,
+                                  machine->Samplers[inst->TexSrcUnit], color);
+
+            store_vector4(inst, machine, color);
+         }
+         break;
       case OPCODE_TXP:         /* GL_ARB_fragment_program only */
          /* Texture lookup w/ projective divide */
          {
@@ -1842,7 +1865,11 @@ _mesa_execute_program(GLcontext * ctx,
 
       numExec++;
       if (numExec > maxExec) {
-         _mesa_problem(ctx, "Infinite loop detected in fragment program");
+        static GLboolean reported = GL_FALSE;
+        if (!reported) {
+           _mesa_problem(ctx, "Infinite loop detected in fragment program");
+           reported = GL_TRUE;
+        }
          return GL_TRUE;
       }
 
index 098b366ab56a1c11fcd8b6d69eb960bf9ee2aa69..ca90de7ce1c6a4295e6eef1cb17c14f5017a4ca3 100644 (file)
@@ -401,7 +401,7 @@ struct prog_instruction
    /**
     * For BRA and CAL instructions, the location to jump to.
     * For BGNLOOP, points to ENDLOOP (and vice-versa).
-    * For BRK, points to BGNLOOP (which points to ENDLOOP).
+    * For BRK, points to ENDLOOP
     * For IF, points to ELSE or ENDIF.
     * For ELSE, points to ENDIF.
     */
index c78187c983d12a334939e9c47834e4800c4b6070..0dc779073db53ecfa36ac3e1220bd506103916e1 100644 (file)
 
 
 #define MAX_LOOP_NESTING 50
-
+/* MAX_PROGRAM_TEMPS is a low number (256), and we want to be able to
+ * register allocate many temporary values into that small number of
+ * temps.  So allow large temporary indices coming into the register
+ * allocator.
+ */
+#define REG_ALLOCATE_MAX_PROGRAM_TEMPS ((1 << INST_INDEX_BITS) - 1)
 
 static GLboolean dbg = GL_FALSE;
 
@@ -233,7 +238,7 @@ replace_regs(struct gl_program *prog, gl_register_file file, const GLint map[])
 static GLboolean
 _mesa_remove_dead_code_global(struct gl_program *prog)
 {
-   GLboolean tempRead[MAX_PROGRAM_TEMPS][4];
+   GLboolean tempRead[REG_ALLOCATE_MAX_PROGRAM_TEMPS][4];
    GLboolean *removeInst; /* per-instruction removal flag */
    GLuint i, rem = 0, comp;
 
@@ -258,7 +263,7 @@ _mesa_remove_dead_code_global(struct gl_program *prog)
          if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
             const GLuint index = inst->SrcReg[j].Index;
             GLuint read_mask;
-            ASSERT(index < MAX_PROGRAM_TEMPS);
+            ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS);
            read_mask = get_src_arg_mask(inst, j, NO_MASK);
 
             if (inst->SrcReg[j].RelAddr) {
@@ -281,7 +286,7 @@ _mesa_remove_dead_code_global(struct gl_program *prog)
       /* check dst reg */
       if (inst->DstReg.File == PROGRAM_TEMPORARY) {
          const GLuint index = inst->DstReg.Index;
-         ASSERT(index < MAX_PROGRAM_TEMPS);
+         ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS);
 
          if (inst->DstReg.RelAddr) {
             if (dbg)
@@ -753,7 +758,11 @@ _mesa_remove_extra_moves(struct gl_program *prog)
          nesting--;
          break;
       case OPCODE_MOV:
-         if (i > 0 && can_downward_mov_be_modifed(mov) && nesting == 0) {
+         if (i > 0 &&
+             can_downward_mov_be_modifed(mov) &&
+             mov->SrcReg[0].File == PROGRAM_TEMPORARY &&
+             nesting == 0)
+         {
 
             /* see if this MOV can be removed */
             const GLuint id = mov->SrcReg[0].Index;
@@ -826,7 +835,7 @@ struct interval
 struct interval_list
 {
    GLuint Num;
-   struct interval Intervals[MAX_PROGRAM_TEMPS];
+   struct interval Intervals[REG_ALLOCATE_MAX_PROGRAM_TEMPS];
 };
 
 
@@ -913,15 +922,33 @@ sort_interval_list_by_start(struct interval_list *list)
 #endif
 }
 
+struct loop_info
+{
+   GLuint Start, End;  /**< Start, end instructions of loop */
+};
 
 /**
  * Update the intermediate interval info for register 'index' and
  * instruction 'ic'.
  */
 static void
-update_interval(GLint intBegin[], GLint intEnd[], GLuint index, GLuint ic)
+update_interval(GLint intBegin[], GLint intEnd[],
+               struct loop_info *loopStack, GLuint loopStackDepth,
+               GLuint index, GLuint ic)
 {
-   ASSERT(index < MAX_PROGRAM_TEMPS);
+   int i;
+
+   /* If the register is used in a loop, extend its lifetime through the end
+    * of the outermost loop that doesn't contain its definition.
+    */
+   for (i = 0; i < loopStackDepth; i++) {
+      if (intBegin[index] < loopStack[i].Start) {
+        ic = loopStack[i].End;
+        break;
+      }
+   }
+
+   ASSERT(index < REG_ALLOCATE_MAX_PROGRAM_TEMPS);
    if (intBegin[index] == -1) {
       ASSERT(intEnd[index] == -1);
       intBegin[index] = intEnd[index] = ic;
@@ -938,18 +965,14 @@ update_interval(GLint intBegin[], GLint intEnd[], GLuint index, GLuint ic)
 GLboolean
 _mesa_find_temp_intervals(const struct prog_instruction *instructions,
                           GLuint numInstructions,
-                          GLint intBegin[MAX_PROGRAM_TEMPS],
-                          GLint intEnd[MAX_PROGRAM_TEMPS])
+                          GLint intBegin[REG_ALLOCATE_MAX_PROGRAM_TEMPS],
+                          GLint intEnd[REG_ALLOCATE_MAX_PROGRAM_TEMPS])
 {
-   struct loop_info
-   {
-      GLuint Start, End;  /**< Start, end instructions of loop */
-   };
    struct loop_info loopStack[MAX_LOOP_NESTING];
    GLuint loopStackDepth = 0;
    GLuint i;
 
-   for (i = 0; i < MAX_PROGRAM_TEMPS; i++){
+   for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++){
       intBegin[i] = intEnd[i] = -1;
    }
 
@@ -975,24 +998,16 @@ _mesa_find_temp_intervals(const struct prog_instruction *instructions,
                const GLuint index = inst->SrcReg[j].Index;
                if (inst->SrcReg[j].RelAddr)
                   return GL_FALSE;
-               update_interval(intBegin, intEnd, index, i);
-               if (loopStackDepth > 0) {
-                  /* extend temp register's interval to end of loop */
-                  GLuint loopEnd = loopStack[loopStackDepth - 1].End;
-                  update_interval(intBegin, intEnd, index, loopEnd);
-               }
+               update_interval(intBegin, intEnd, loopStack, loopStackDepth,
+                              index, i);
             }
          }
          if (inst->DstReg.File == PROGRAM_TEMPORARY) {
             const GLuint index = inst->DstReg.Index;
             if (inst->DstReg.RelAddr)
                return GL_FALSE;
-            update_interval(intBegin, intEnd, index, i);
-            if (loopStackDepth > 0) {
-               /* extend temp register's interval to end of loop */
-               GLuint loopEnd = loopStack[loopStackDepth - 1].End;
-               update_interval(intBegin, intEnd, index, loopEnd);
-            }
+            update_interval(intBegin, intEnd, loopStack, loopStackDepth,
+                           index, i);
          }
       }
    }
@@ -1012,7 +1027,8 @@ static GLboolean
 find_live_intervals(struct gl_program *prog,
                     struct interval_list *liveIntervals)
 {
-   GLint intBegin[MAX_PROGRAM_TEMPS], intEnd[MAX_PROGRAM_TEMPS];
+   GLint intBegin[REG_ALLOCATE_MAX_PROGRAM_TEMPS];
+   GLint intEnd[REG_ALLOCATE_MAX_PROGRAM_TEMPS];
    GLuint i;
 
    /*
@@ -1032,7 +1048,7 @@ find_live_intervals(struct gl_program *prog,
 
    /* Build live intervals list from intermediate arrays */
    liveIntervals->Num = 0;
-   for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+   for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++) {
       if (intBegin[i] >= 0) {
          struct interval inv;
          inv.Reg = i;
@@ -1068,10 +1084,10 @@ find_live_intervals(struct gl_program *prog,
 
 /** Scan the array of used register flags to find free entry */
 static GLint
-alloc_register(GLboolean usedRegs[MAX_PROGRAM_TEMPS])
+alloc_register(GLboolean usedRegs[REG_ALLOCATE_MAX_PROGRAM_TEMPS])
 {
    GLuint k;
-   for (k = 0; k < MAX_PROGRAM_TEMPS; k++) {
+   for (k = 0; k < REG_ALLOCATE_MAX_PROGRAM_TEMPS; k++) {
       if (!usedRegs[k]) {
          usedRegs[k] = GL_TRUE;
          return k;
@@ -1093,8 +1109,8 @@ static void
 _mesa_reallocate_registers(struct gl_program *prog)
 {
    struct interval_list liveIntervals;
-   GLint registerMap[MAX_PROGRAM_TEMPS];
-   GLboolean usedRegs[MAX_PROGRAM_TEMPS];
+   GLint registerMap[REG_ALLOCATE_MAX_PROGRAM_TEMPS];
+   GLboolean usedRegs[REG_ALLOCATE_MAX_PROGRAM_TEMPS];
    GLuint i;
    GLint maxTemp = -1;
 
@@ -1103,7 +1119,7 @@ _mesa_reallocate_registers(struct gl_program *prog)
       _mesa_print_program(prog);
    }
 
-   for (i = 0; i < MAX_PROGRAM_TEMPS; i++){
+   for (i = 0; i < REG_ALLOCATE_MAX_PROGRAM_TEMPS; i++){
       registerMap[i] = -1;
       usedRegs[i] = GL_FALSE;
    }
index aac488c79ab659e708e09f974edc9e23446b2972..6bf8a081b0299202c43281cef385d5f0f2b26548 100644 (file)
@@ -284,93 +284,6 @@ _mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
    return pos;
 }
 
-
-/**
- * Add a uniform to the parameter list.
- * Note that if the uniform is an array, size may be greater than
- * what's implied by the datatype.
- * \param name  uniform's name
- * \param size  number of floats to allocate
- * \param datatype  GL_FLOAT_VEC3, GL_FLOAT_MAT4, etc.
- */
-GLint
-_mesa_add_uniform(struct gl_program_parameter_list *paramList,
-                  const char *name, GLuint size, GLenum datatype,
-                  const GLfloat *values)
-{
-   GLint i = _mesa_lookup_parameter_index(paramList, -1, name);
-   ASSERT(datatype != GL_NONE);
-   if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_UNIFORM) {
-      ASSERT(paramList->Parameters[i].Size == size);
-      ASSERT(paramList->Parameters[i].DataType == datatype);
-      /* already in list */
-      return i;
-   }
-   else {
-      i = _mesa_add_parameter(paramList, PROGRAM_UNIFORM, name,
-                              size, datatype, values, NULL, 0x0);
-      return i;
-   }
-}
-
-
-/**
- * Mark the named uniform as 'used'.
- */
-void
-_mesa_use_uniform(struct gl_program_parameter_list *paramList,
-                  const char *name)
-{
-   GLuint i;
-   for (i = 0; i < paramList->NumParameters; i++) {
-      struct gl_program_parameter *p = paramList->Parameters + i;
-      if ((p->Type == PROGRAM_UNIFORM || p->Type == PROGRAM_SAMPLER) &&
-          strcmp(p->Name, name) == 0) {
-         p->Used = GL_TRUE;
-         /* Note that large uniforms may occupy several slots so we're
-          * not done searching yet.
-          */
-      }
-   }
-}
-
-
-/**
- * Add a sampler to the parameter list.
- * \param name  uniform's name
- * \param datatype  GL_SAMPLER_2D, GL_SAMPLER_2D_RECT_ARB, etc.
- * \param index  the sampler number (as seen in TEX instructions)
- * \return  sampler index (starting at zero) or -1 if error
- */
-GLint
-_mesa_add_sampler(struct gl_program_parameter_list *paramList,
-                  const char *name, GLenum datatype)
-{
-   GLint i = _mesa_lookup_parameter_index(paramList, -1, name);
-   if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_SAMPLER) {
-      ASSERT(paramList->Parameters[i].Size == 1);
-      ASSERT(paramList->Parameters[i].DataType == datatype);
-      /* already in list */
-      return (GLint) paramList->ParameterValues[i][0];
-   }
-   else {
-      GLuint i;
-      const GLint size = 1; /* a sampler is basically a texture unit number */
-      GLfloat value[4];
-      GLint numSamplers = 0;
-      for (i = 0; i < paramList->NumParameters; i++) {
-         if (paramList->Parameters[i].Type == PROGRAM_SAMPLER)
-            numSamplers++;
-      }
-      value[0] = (GLfloat) numSamplers;
-      value[1] = value[2] = value[3] = 0.0F;
-      (void) _mesa_add_parameter(paramList, PROGRAM_SAMPLER, name,
-                                 size, datatype, value, NULL, 0x0);
-      return numSamplers;
-   }
-}
-
-
 /**
  * Add parameter representing a varying variable.
  */
@@ -569,8 +482,10 @@ _mesa_lookup_parameter_constant(const struct gl_program_parameter_list *list,
    assert(vSize >= 1);
    assert(vSize <= 4);
 
-   if (!list)
-      return -1;
+   if (!list) {
+      *posOut = -1;
+      return GL_FALSE;
+   }
 
    for (i = 0; i < list->NumParameters; i++) {
       if (list->Parameters[i].Type == PROGRAM_CONSTANT) {
@@ -591,7 +506,7 @@ _mesa_lookup_parameter_constant(const struct gl_program_parameter_list *list,
              if (vSize == 1) {
                 /* look for v[0] anywhere within float[4] value */
                 GLuint j;
-                for (j = 0; j < 4; j++) {
+                for (j = 0; j < list->Parameters[i].Size; j++) {
                    if (list->ParameterValues[i][j] == v[0]) {
                       /* found it */
                       *posOut = i;
@@ -657,7 +572,6 @@ _mesa_clone_parameter_list(const struct gl_program_parameter_list *list)
                                     list->ParameterValues[i], NULL, 0x0);
       ASSERT(j >= 0);
       pCopy = clone->Parameters + j;
-      pCopy->Used = p->Used;
       pCopy->Flags = p->Flags;
       /* copy state indexes */
       if (p->Type == PROGRAM_STATE_VAR) {
index cc3378ae20129629dfcfd8b93ae1c21dc75b3727..10cbbe57a6cb86ad9bd893e3eb258446b2fa459f 100644 (file)
@@ -64,8 +64,7 @@ struct gl_program_parameter
     * The next program parameter's Size will be Size-4 of this parameter.
     */
    GLuint Size;
-   GLboolean Used;          /**< Helper flag for GLSL uniform tracking */
-   GLboolean Initialized;   /**< Has the ParameterValue[] been set? */
+   GLboolean Initialized;   /**< debug: Has the ParameterValue[] been set? */
    GLbitfield Flags;        /**< Bitmask of PROG_PARAM_*_BIT */
    /**
     * A sequence of STATE_* tokens and integers to identify GL state.
@@ -131,19 +130,6 @@ _mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
                            const GLfloat values[4], GLuint size,
                            GLuint *swizzleOut);
 
-extern GLint
-_mesa_add_uniform(struct gl_program_parameter_list *paramList,
-                  const char *name, GLuint size, GLenum datatype,
-                  const GLfloat *values);
-
-extern void
-_mesa_use_uniform(struct gl_program_parameter_list *paramList,
-                  const char *name);
-
-extern GLint
-_mesa_add_sampler(struct gl_program_parameter_list *paramList,
-                  const char *name, GLenum datatype);
-
 extern GLint
 _mesa_add_varying(struct gl_program_parameter_list *paramList,
                   const char *name, GLuint size, GLenum datatype,
index 6056c459e4c6b387bb7aa408dcc05a6c61f69d1f..00aa6de963b6a8fc9b57169f10863faeef520772 100644 (file)
@@ -540,12 +540,12 @@ fprint_comment(FILE *f, const struct prog_instruction *inst)
 }
 
 
-static void
-fprint_alu_instruction(FILE *f,
-                       const struct prog_instruction *inst,
-                       const char *opcode_string, GLuint numRegs,
-                       gl_prog_print_mode mode,
-                       const struct gl_program *prog)
+void
+_mesa_fprint_alu_instruction(FILE *f,
+                            const struct prog_instruction *inst,
+                            const char *opcode_string, GLuint numRegs,
+                            gl_prog_print_mode mode,
+                            const struct gl_program *prog)
 {
    GLuint j;
 
@@ -582,8 +582,8 @@ void
 _mesa_print_alu_instruction(const struct prog_instruction *inst,
                             const char *opcode_string, GLuint numRegs)
 {
-   fprint_alu_instruction(stderr, inst, opcode_string,
-                          numRegs, PROG_PRINT_DEBUG, NULL);
+   _mesa_fprint_alu_instruction(stderr, inst, opcode_string,
+                               numRegs, PROG_PRINT_DEBUG, NULL);
 }
 
 
@@ -791,16 +791,16 @@ _mesa_fprint_instruction_opt(FILE *f,
    default:
       if (inst->Opcode < MAX_OPCODE) {
          /* typical alu instruction */
-         fprint_alu_instruction(f, inst,
-                                _mesa_opcode_string(inst->Opcode),
-                                _mesa_num_inst_src_regs(inst->Opcode),
-                                mode, prog);
+         _mesa_fprint_alu_instruction(f, inst,
+                                     _mesa_opcode_string(inst->Opcode),
+                                     _mesa_num_inst_src_regs(inst->Opcode),
+                                     mode, prog);
       }
       else {
-         fprint_alu_instruction(f, inst,
-                                _mesa_opcode_string(inst->Opcode),
-                                3/*_mesa_num_inst_src_regs(inst->Opcode)*/,
-                                mode, prog);
+         _mesa_fprint_alu_instruction(f, inst,
+                                     _mesa_opcode_string(inst->Opcode),
+                                     3/*_mesa_num_inst_src_regs(inst->Opcode)*/,
+                                     mode, prog);
       }
       break;
    }
@@ -1033,11 +1033,11 @@ _mesa_write_shader_to_file(const struct gl_shader *shader)
 
    fprintf(f, "/* Compile status: %s */\n",
            shader->CompileStatus ? "ok" : "fail");
-   if (!shader->CompileStatus) {
-      fprintf(f, "/* Log Info: */\n");
+   fprintf(f, "/* Log Info: */\n");
+   if (shader->InfoLog) {
       fputs(shader->InfoLog, f);
    }
-   else {
+   if (shader->CompileStatus && shader->Program) {
       fprintf(f, "/* GPU code */\n");
       fprintf(f, "/*\n");
       _mesa_fprint_program_opt(f, shader->Program, PROG_PRINT_DEBUG, GL_TRUE);
index 4667373f37941f3fcc7141a721a33224217c8ee2..78b90aeb4d6fe107ea709dabb83e13b537d36aee 100644 (file)
@@ -65,6 +65,13 @@ _mesa_writemask_string(GLuint writeMask);
 extern void
 _mesa_print_swizzle(GLuint swizzle);
 
+extern void
+_mesa_fprint_alu_instruction(FILE *f,
+                            const struct prog_instruction *inst,
+                            const char *opcode_string, GLuint numRegs,
+                            gl_prog_print_mode mode,
+                            const struct gl_program *prog);
+
 extern void
 _mesa_print_alu_instruction(const struct prog_instruction *inst,
                             const char *opcode_string, GLuint numRegs);
index 5aa9878d43cf0b5796a97ccf981e9352a3dcd046..28acb8871a722f4c10df46c2229297bbe284e56c 100644 (file)
@@ -44,6 +44,10 @@ void
 _mesa_free_uniform_list(struct gl_uniform_list *list)
 {
    GLuint i;
+
+   if (!list)
+      return;
+
    for (i = 0; i < list->NumUniforms; i++) {
       free((void *) list->Uniforms[i].Name);
    }
index 7988d534a7d07b5217c4082feb159c380b520ea4..67f78006eac31a762c529c1d46b9e656af291a97 100644 (file)
@@ -51,10 +51,7 @@ struct gl_uniform
    GLint FragPos;
    GLint GeomPos;
    GLboolean Initialized;   /**< For debug.  Has this uniform been set? */
-#if 0
-   GLenum DataType;         /**< GL_FLOAT, GL_FLOAT_VEC2, etc */
-   GLuint Size;             /**< Number of components (1..4) */
-#endif
+   const struct glsl_type *Type;
 };
 
 
index 6a5d686897425896f7214af74d66d1864e14d043..09e7cb44ef399f68e7a69117ef0e47525e479b83 100644 (file)
@@ -58,7 +58,9 @@ struct symbol {
      */
     int name_space;
 
-    
+    /** Scope depth where this symbol was defined. */
+    unsigned depth;
+
     /**
      * Arbitrary user supplied data.
      */
@@ -73,7 +75,7 @@ struct symbol_header {
     struct symbol_header *next;
 
     /** Symbol name. */
-    const char *name;
+    char *name;
 
     /** Linked list of symbols with the same name. */
     struct symbol *symbols;
@@ -104,6 +106,9 @@ struct _mesa_symbol_table {
 
     /** List of all symbol headers in the table. */
     struct symbol_header *hdr;
+
+    /** Current scope depth. */
+    unsigned depth;
 };
 
 
@@ -157,6 +162,7 @@ _mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table)
     struct symbol *sym = scope->symbols;
 
     table->current_scope = scope->next;
+    table->depth--;
 
     free(scope);
 
@@ -184,6 +190,7 @@ _mesa_symbol_table_push_scope(struct _mesa_symbol_table *table)
     
     scope->next = table->current_scope;
     table->current_scope = scope;
+    table->depth++;
 }
 
 
@@ -261,6 +268,36 @@ _mesa_symbol_table_iterator_next(struct _mesa_symbol_table_iterator *iter)
 }
 
 
+/**
+ * Determine the scope "distance" of a symbol from the current scope
+ *
+ * \return
+ * A non-negative number for the number of scopes between the current scope
+ * and the scope where a symbol was defined.  A value of zero means the current
+ * scope.  A negative number if the symbol does not exist.
+ */
+int
+_mesa_symbol_table_symbol_scope(struct _mesa_symbol_table *table,
+                               int name_space, const char *name)
+{
+    struct symbol_header *const hdr = find_symbol(table, name);
+    struct symbol *sym;
+
+    if (hdr != NULL) {
+       for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) {
+         assert(sym->hdr == hdr);
+
+         if ((name_space == -1) || (sym->name_space == name_space)) {
+            assert(sym->depth <= table->depth);
+            return sym->depth - table->depth;
+         }
+       }
+    }
+
+    return -1;
+}
+
+
 void *
 _mesa_symbol_table_find_symbol(struct _mesa_symbol_table *table,
                                int name_space, const char *name)
@@ -300,21 +337,34 @@ _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,
 
     if (hdr == NULL) {
         hdr = calloc(1, sizeof(*hdr));
-        hdr->name = name;
+        hdr->name = strdup(name);
 
-        hash_table_insert(table->ht, hdr, name);
+        hash_table_insert(table->ht, hdr, hdr->name);
        hdr->next = table->hdr;
        table->hdr = hdr;
     }
 
     check_symbol_table(table);
 
+    /* If the symbol already exists in this namespace at this scope, it cannot
+     * be added to the table.
+     */
+    for (sym = hdr->symbols
+        ; (sym != NULL) && (sym->name_space != name_space)
+        ; sym = sym->next_with_same_name) {
+       /* empty */
+    }
+
+    if (sym && (sym->depth == table->depth))
+       return -1;
+
     sym = calloc(1, sizeof(*sym));
     sym->next_with_same_name = hdr->symbols;
     sym->next_with_same_scope = table->current_scope->symbols;
     sym->hdr = hdr;
     sym->name_space = name_space;
     sym->data = declaration;
+    sym->depth = table->depth;
 
     assert(sym->hdr == hdr);
 
@@ -354,6 +404,7 @@ _mesa_symbol_table_dtor(struct _mesa_symbol_table *table)
 
    for (hdr = table->hdr; hdr != NULL; hdr = next) {
        next = hdr->next;
+       free(hdr->name);
        free(hdr);
    }
 
index 0c054ef13967842eae26ade55ebe29eda0b662f4..1d570fc1a09ecfe4364c832076280296c31a876d 100644 (file)
@@ -33,6 +33,9 @@ extern void _mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table);
 extern int _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *symtab,
     int name_space, const char *name, void *declaration);
 
+extern int _mesa_symbol_table_symbol_scope(struct _mesa_symbol_table *table,
+    int name_space, const char *name);
+
 extern void *_mesa_symbol_table_find_symbol(
     struct _mesa_symbol_table *symtab, int name_space, const char *name);
 
diff --git a/src/mesa/slang/descrip.mms b/src/mesa/slang/descrip.mms
deleted file mode 100644 (file)
index 674b786..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-# Makefile for core library for VMS
-# contributed by Jouk Jansen  joukj@hrem.nano.tudelft.nl
-# Last revision : 3 October 2007
-
-.first
-       define gl [----.include.gl]
-       define math [--.math]
-       define swrast [--.swrast]
-       define array_cache [--.array_cache]
-       define main [--.main]
-       define glapi [--.glapi]
-       define shader [--.shader]
-
-.include [----]mms-config.
-
-##### MACROS #####
-
-VPATH = RCS
-
-INCDIR = [----.include],[--.main],[--.glapi],[-.slang],[-]
-LIBDIR = [----.lib]
-CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
-
-SOURCES = \
-       slang_compile.c
-
-OBJECTS = slang_builtin.obj,slang_codegen.obj,slang_compile.obj,\
-       slang_compile_function.obj,slang_compile_operation.obj,\
-       slang_compile_struct.obj,slang_compile_variable.obj,slang_emit.obj,\
-       slang_ir.obj,slang_label.obj,slang_library_noise.obj,slang_link.obj,\
-       slang_log.obj,slang_mem.obj,slang_preprocess.obj,slang_print.obj,\
-       slang_simplify.obj,slang_storage.obj,slang_typeinfo.obj,\
-       slang_utility.obj,slang_vartable.obj
-
-##### RULES #####
-
-VERSION=Mesa V3.4
-
-##### TARGETS #####
-# Make the library
-$(LIBDIR)$(GL_LIB) : $(OBJECTS)
-  @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
-
-clean :
-       purge
-       delete *.obj;*
-
-slang_builtin.obj : slang_builtin.c
-slang_codegen.obj : slang_codegen.c
-slang_compile.obj : slang_compile.c
-slang_compile_function.obj : slang_compile_function.c
-slang_compile_operation.obj : slang_compile_operation.c
-slang_compile_struct.obj : slang_compile_struct.c
-slang_compile_variable.obj : slang_compile_variable.c
-slang_emit.obj : slang_emit.c
-slang_ir.obj : slang_ir.c
-slang_label.obj : slang_label.c
-slang_library_noise.obj : slang_library_noise.c
-slang_link.obj : slang_link.c
-slang_log.obj : slang_log.c
-slang_mem.obj : slang_mem.c
-slang_print.obj : slang_print.c
-slang_simplify.obj : slang_simplify.c
-slang_storage.obj : slang_storage.c
-slang_typeinfo.obj : slang_typeinfo.c
-slang_utility.obj : slang_utility.c
-slang_vartable.obj : slang_vartable.c
diff --git a/src/mesa/slang/library/.gitignore b/src/mesa/slang/library/.gitignore
deleted file mode 100644 (file)
index 02a89fc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-*_gc.h
diff --git a/src/mesa/slang/library/Makefile b/src/mesa/slang/library/Makefile
deleted file mode 100644 (file)
index f546a03..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-# src/mesa/slang/library/Makefile
-
-TOP = ../../../..
-
-include $(TOP)/configs/current
-
-GLSL_CL = $(TOP)/src/glsl/apps/compile
-
-#
-# targets
-#
-
-.PHONY: default clean
-
-default: builtin
-
-clean:
-       -rm -f *_gc.h
-
-builtin: builtin_110 builtin_120
-
-#
-# builtin library sources
-#
-
-builtin_110: slang_common_builtin_gc.h slang_core_gc.h slang_fragment_builtin_gc.h slang_vertex_builtin_gc.h slang_geometry_builtin_gc.h
-
-builtin_120: slang_120_core_gc.h slang_builtin_120_common_gc.h slang_builtin_120_fragment_gc.h
-
-
-slang_120_core_gc.h: slang_120_core.gc
-       $(GLSL_CL) fragment slang_120_core.gc slang_120_core_gc.h
-
-slang_builtin_120_common_gc.h: slang_builtin_120_common.gc
-       $(GLSL_CL) fragment slang_builtin_120_common.gc slang_builtin_120_common_gc.h
-
-slang_builtin_120_fragment_gc.h: slang_builtin_120_fragment.gc
-       $(GLSL_CL) fragment slang_builtin_120_fragment.gc slang_builtin_120_fragment_gc.h
-
-slang_common_builtin_gc.h: slang_common_builtin.gc
-       $(GLSL_CL) fragment slang_common_builtin.gc slang_common_builtin_gc.h
-
-slang_core_gc.h: slang_core.gc
-       $(GLSL_CL) fragment slang_core.gc slang_core_gc.h
-
-slang_fragment_builtin_gc.h: slang_fragment_builtin.gc
-       $(GLSL_CL) fragment slang_fragment_builtin.gc slang_fragment_builtin_gc.h
-
-slang_vertex_builtin_gc.h: slang_vertex_builtin.gc
-       $(GLSL_CL) vertex slang_vertex_builtin.gc slang_vertex_builtin_gc.h
-
-slang_geometry_builtin_gc.h: slang_geometry_builtin.gc
-       $(GLSL_CL) geometry slang_geometry_builtin.gc slang_geometry_builtin_gc.h
-
diff --git a/src/mesa/slang/library/SConscript b/src/mesa/slang/library/SConscript
deleted file mode 100644 (file)
index 5112cef..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-#######################################################################
-# SConscript for GLSL builtin library
-
-Import('*')
-
-env = env.Clone()
-
-# See also http://www.scons.org/wiki/UsingCodeGenerators
-
-def glsl_compile_emitter(target, source, env):
-       env.Depends(target, glsl_compile)
-       return (target, source)
-
-bld_frag = Builder(
-       action = Action(glsl_compile[0].abspath + ' fragment $SOURCE $TARGET', '$CODEGENCODESTR'),
-       emitter = glsl_compile_emitter,
-       suffix = '.gc',
-       src_suffix = '_gc.h')
-
-bld_vert = Builder(
-       action = Action(glsl_compile[0].abspath + ' vertex $SOURCE $TARGET', '$CODEGENCODESTR'),
-       emitter = glsl_compile_emitter,
-       suffix = '.gc',
-       src_suffix = '_gc.h')
-
-bld_geom = Builder(
-       action = Action(glsl_compile[0].abspath + ' geometry $SOURCE $TARGET', '$CODEGENCODESTR'),
-       emitter = glsl_compile_emitter,
-       suffix = '.gc',
-       src_suffix = '_gc.h')
-
-env['BUILDERS']['bld_frag'] = bld_frag
-env['BUILDERS']['bld_vert'] = bld_vert
-env['BUILDERS']['bld_geom'] = bld_geom
-
-# Generate GLSL builtin library binaries
-env.bld_frag(
-       '#src/mesa/slang/library/slang_core_gc.h',
-       '#src/mesa/slang/library/slang_core.gc')
-env.bld_frag(
-       '#src/mesa/slang/library/slang_common_builtin_gc.h',
-       '#src/mesa/slang/library/slang_common_builtin.gc')
-env.bld_frag(
-       '#src/mesa/slang/library/slang_fragment_builtin_gc.h',
-       '#src/mesa/slang/library/slang_fragment_builtin.gc')
-env.bld_vert(
-       '#src/mesa/slang/library/slang_vertex_builtin_gc.h',
-       '#src/mesa/slang/library/slang_vertex_builtin.gc')
-env.bld_geom(
-       '#src/mesa/slang/library/slang_geometry_builtin_gc.h',
-       '#src/mesa/slang/library/slang_geometry_builtin.gc')
-
-# Generate GLSL 1.20 builtin library binaries
-env.bld_frag(
-       '#src/mesa/slang/library/slang_120_core_gc.h',
-       '#src/mesa/slang/library/slang_120_core.gc')
-env.bld_frag(
-       '#src/mesa/slang/library/slang_builtin_120_common_gc.h',
-       '#src/mesa/slang/library/slang_builtin_120_common.gc')
-env.bld_frag(
-       '#src/mesa/slang/library/slang_builtin_120_fragment_gc.h',
-       '#src/mesa/slang/library/slang_builtin_120_fragment.gc')
diff --git a/src/mesa/slang/library/slang_120_core.gc b/src/mesa/slang/library/slang_120_core.gc
deleted file mode 100644 (file)
index 04c5ec2..0000000
+++ /dev/null
@@ -1,1978 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-//
-// Constructors and operators introduced in GLSL 1.20 - mostly on new
-// (non-square) types of matrices.
-//
-// One important change in the language is that when a matrix is used
-// as an argument to a matrix constructor, it must be the only argument
-// for the constructor. The compiler takes care of it by itself and
-// here we only care to re-introduce constructors for old (square)
-// types of matrices.
-//
-
-//
-// From Shader Spec, ver. 1.20, rev. 6
-//
-
-//// mat2x3: 2 columns of vec3
-
-mat2x3 __constructor(const float f00, const float f10, const float f20,
-                     const float f01, const float f11, const float f21)
-{
-   __retVal[0].x = f00;
-   __retVal[0].y = f10;
-   __retVal[0].z = f20;
-   __retVal[1].x = f01;
-   __retVal[1].y = f11;
-   __retVal[1].z = f21;
-}
-
-mat2x3 __constructor(const float f)
-{
-   __retVal = mat2x3(  f, 0.0, 0.0,
-                     0.0,   f, 0.0);
-}
-
-mat2x3 __constructor(const int  i)
-{
-   const float f = float(i);
-   __retVal = mat2x3(f);
-}
-
-mat2x3 __constructor(const bool b)
-{
-   const float f = float(b);
-   __retVal = mat2x3(f);
-}
-
-mat2x3 __constructor(const vec3 c0, const vec3 c1)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-}
-
-
-
-//// mat2x4: 2 columns of vec4
-
-mat2x4 __constructor(const float f00, const float f10, const float f20, const float f30,
-                     const float f01, const float f11, const float f21, const float f31)
-{
-   __retVal[0].x = f00;
-   __retVal[0].y = f10;
-   __retVal[0].z = f20;
-   __retVal[0].w = f30;
-   __retVal[1].x = f01;
-   __retVal[1].y = f11;
-   __retVal[1].z = f21;
-   __retVal[1].w = f31;
-}
-
-mat2x4 __constructor(const float f)
-{
-   __retVal = mat2x4(  f, 0.0, 0.0, 0.0,
-                     0.0,   f, 0.0, 0.0);
-}
-
-mat2x4 __constructor(const int i)
-{
-   const float f = float(i);
-   __retVal = mat2x4(f);
-}
-
-mat2x4 __constructor(const bool b)
-{
-   const float f = float(b);
-   __retVal = mat2x4(f);
-}
-
-mat2x4 __constructor(const vec4 c0, const vec4 c1)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-}
-
-
-
-//// mat3x2: 3 columns of vec2
-
-mat3x2 __constructor(const float f00, const float f10,
-                     const float f01, const float f11,
-                     const float f02, const float f12)
-{
-   __retVal[0].x = f00;
-   __retVal[0].y = f10;
-   __retVal[1].x = f01;
-   __retVal[1].y = f11;
-   __retVal[2].x = f02;
-   __retVal[2].y = f12;
-}
-
-mat3x2 __constructor(const float f)
-{
-   __retVal = mat3x2(  f, 0.0,
-                     0.0,   f,
-                     0.0, 0.0);
-}
-
-mat3x2 __constructor(const int i)
-{
-   const float f = float(i);
-   __retVal = mat3x2(f);
-}
-
-mat3x2 __constructor(const bool b)
-{
-   const float f = float(b);
-   __retVal = mat3x2(f);
-}
-
-mat3x2 __constructor(const vec2 c0, const vec2 c1, const vec2 c2)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-   __retVal[2] = c2;
-}
-
-
-
-//// mat3x4: 3 columns of vec4
-
-mat3x4 __constructor(const float f00, const float f10, const float f20, const float f30,
-                     const float f01, const float f11, const float f21, const float f31,
-                    const float f02, const float f12, const float f22, const float f32)
-{
-   __retVal[0].x = f00;
-   __retVal[0].y = f10;
-   __retVal[0].z = f20;
-   __retVal[0].w = f30;
-   __retVal[1].x = f01;
-   __retVal[1].y = f11;
-   __retVal[1].z = f21;
-   __retVal[1].w = f31;
-   __retVal[2].x = f02;
-   __retVal[2].y = f12;
-   __retVal[2].z = f22;
-   __retVal[2].w = f32;
-}
-
-mat3x4 __constructor(const float f)
-{
-   __retVal = mat3x4(  f, 0.0, 0.0, 0.0,
-                     0.0,   f, 0.0, 0.0,
-                     0.0, 0.0,   f, 0.0);
-}
-
-mat3x4 __constructor(const int i)
-{
-   const float f = float(i);
-   __retVal = mat3x4(f);
-}
-
-mat3x4 __constructor(const bool b)
-{
-   const float f = float(b);
-   __retVal = mat3x4(f);
-}
-
-mat3x4 __constructor(const vec4 c0, const vec4 c1, const vec4 c2)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-   __retVal[2] = c2;
-}
-
-
-
-//// mat4x2: 4 columns of vec2
-
-mat4x2 __constructor(const float f00, const float f10,
-                     const float f01, const float f11,
-                    const float f02, const float f12,
-                    const float f03, const float f13)
-{
-   __retVal[0].x = f00;
-   __retVal[0].y = f10;
-   __retVal[1].x = f01;
-   __retVal[1].y = f11;
-   __retVal[2].x = f02;
-   __retVal[2].y = f12;
-   __retVal[3].x = f03;
-   __retVal[3].y = f13;
-}
-
-mat4x2 __constructor(const float f)
-{
-   __retVal = mat4x2(  f, 0.0,
-                     0.0,   4,
-                     0.0, 0.0,
-                     0.0, 0.0);
-}
-
-mat4x2 __constructor(const int i)
-{
-   const float f = float(i);
-   __retVal = mat4x2(f);
-}
-
-mat4x2 __constructor(const bool b)
-{
-   const float f = float(b);
-   __retVal = mat4x2(f);
-}
-
-mat4x2 __constructor(const vec2 c0, const vec2 c1, const vec2 c2, const vec2 c3)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-   __retVal[2] = c2;
-   __retVal[3] = c3;
-}
-
-
-
-//// mat4x3: 4 columns of vec3
-
-mat4x3 __constructor(const float f00, const float f10, const float f20,
-                     const float f01, const float f11, const float f21,
-                    const float f02, const float f12, const float f22,
-                    const float f03, const float f13, const float f23)
-{
-   __retVal[0].x = f00;
-   __retVal[0].y = f10;
-   __retVal[0].z = f20;
-   __retVal[1].x = f01;
-   __retVal[1].y = f11;
-   __retVal[1].z = f21;
-   __retVal[2].x = f02;
-   __retVal[2].y = f12;
-   __retVal[2].z = f22;
-   __retVal[3].x = f03;
-   __retVal[3].y = f13;
-   __retVal[3].z = f23;
-}
-
-mat4x3 __constructor(const float f)
-{
-   __retVal = mat4x3(  f, 0.0, 0.0,
-                     0.0,   f, 0.0,
-                     0.0, 0.0,   f,
-                     0.0, 0.0, 0.0);
-}
-
-mat4x3 __constructor(const int i)
-{
-   const float f = float(i);
-   __retVal = mat4x3(f);
-}
-
-mat4x3 __constructor(const bool b)
-{
-   const float f = float(b);
-   __retVal = mat4x3(f);
-}
-
-mat4x3 __constructor(const vec3 c0, const vec3 c1, const vec3 c2, const vec3 c3)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-   __retVal[2] = c2;
-   __retVal[3] = c3;
-}
-
-
-
-//// misc assorted matrix constructors
-
-mat2 __constructor(const mat2 m)
-{
-   __retVal = m;
-}
-
-mat2 __constructor(const mat3x2 m)
-{
-   __retVal = mat2(m[0], m[1]);
-}
-
-mat2 __constructor(const mat4x2 m)
-{
-   __retVal = mat2(m[0], m[1]);
-}
-
-mat2 __constructor(const mat2x3 m)
-{
-   __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-mat2 __constructor(const mat2x4 m)
-{
-   __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-mat2 __constructor(const mat3 m)
-{
-   __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-mat2 __constructor(const mat3x4 m)
-{
-   __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-mat2 __constructor(const mat4x3 m)
-{
-   __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-mat2 __constructor(const mat4 m)
-{
-   __retVal = mat2(m[0].xy, m[1].xy);
-}
-
-
-
-mat2x3 __constructor(const mat2x3 m)
-{
-   __retVal = m;
-}
-
-mat2x3 __constructor(const mat3 m)
-{
-   __retVal = mat2x3(m[0], m[1]);
-}
-
-mat2x3 __constructor(const mat4x3 m)
-{
-   __retVal = mat2x3(m[0], m[1]);
-}
-
-mat2x3 __constructor(const mat2x4 m)
-{
-   __retVal = mat2x3(m[0].xyz, m[1].xyz);
-}
-
-mat2x3 __constructor(const mat3x4 m)
-{
-   __retVal = mat2x3(m[0].xyz, m[1].xyz);
-}
-
-mat2x3 __constructor(const mat4 m)
-{
-   __retVal = mat2x3(m[0].xyz, m[1].xyz);
-}
-
-mat2x3 __constructor(const mat2 m)
-{
-   __retVal = mat2x3(m[0].x, m[0].y, 0.0,
-                     m[1].x, m[1].y, 0.0);
-}
-
-mat2x3 __constructor(const mat3x2 m)
-{
-   __retVal = mat2x3(m[0].x, m[0].y, 0.0,
-                     m[1].x, m[1].y, 0.0);
-}
-
-mat2x3 __constructor(const mat4x2 m)
-{
-   __retVal = mat2x3(m[0].x, m[0].y, 0.0,
-                     m[1].x, m[1].y, 0.0);
-}
-
-
-
-mat2x4 __constructor(const mat2x4 m)
-{
-   __retVal = m;
-}
-
-mat2x4 __constructor(const mat3x4 m)
-{
-   __retVal = mat2x4(m[0], m[1]);
-}
-
-mat2x4 __constructor(const mat4 m)
-{
-   __retVal = mat2x4(m[0], m[1]);
-}
-
-mat2x4 __constructor(const mat2x3 m)
-{
-   __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0,
-                     m[1].x, m[1].y, m[1].z, 0.0);
-}
-
-mat2x4 __constructor(const mat3 m)
-{
-   __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0,
-                     m[1].x, m[1].y, m[1].z, 0.0);
-}
-
-mat2x4 __constructor(const mat4x3 m)
-{
-   __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0,
-                     m[1].x, m[1].y, m[1].z, 0.0);
-}
-
-mat2x4 __constructor(const mat2 m)
-{
-   __retVal = mat2x4(m[0].x, m[1].y, 0.0, 0.0,
-                     m[1].x, m[1].y, 0.0, 0.0);
-}
-
-mat2x4 __constructor(const mat3x2 m)
-{
-   __retVal = mat2x4(m[0].x, m[0].y, 0.0, 0.0,
-                     m[1].x, m[1].y, 0.0, 0.0);
-}
-
-mat2x4 __constructor(const mat4x2 m)
-{
-   __retVal = mat2x4(m[0].x, m[0].y, 0.0, 0.0,
-                     m[1].x, m[1].y, 0.0, 0.0);
-}
-
-
-
-mat3x2 __constructor(const mat3x2 m)
-{
-   __retVal = m;
-}
-
-mat3x2 __constructor(const mat4x2 m)
-{
-   __retVal = mat3x2(m[0], m[1], m[2]);
-}
-
-mat3x2 __constructor(const mat3 m)
-{
-   __retVal = mat3x2(m[0], m[1], m[2]);
-}
-
-mat3x2 __constructor(const mat3x4 m)
-{
-   __retVal = mat3x2(m[0].x, m[0].y,
-                     m[1].x, m[1].y,
-                     m[2].x, m[2].y);
-}
-
-mat3x2 __constructor(const mat4x3 m)
-{
-   __retVal = mat3x2(m[0].x, m[0].y,
-                     m[1].x, m[1].y,
-                     m[2].x, m[2].y);
-}
-
-mat3x2 __constructor(const mat4 m)
-{
-   __retVal = mat3x2(m[0].x, m[0].y,
-                     m[1].x, m[1].y,
-                        0.0,    0.0);
-}
-
-mat3x2 __constructor(const mat2 m)
-{
-   __retVal = mat3x2(m[0], m[1], vec2(0.0));
-}
-
-mat3x2 __constructor(const mat2x3 m)
-{
-   __retVal = mat3x2(m[0].x, m[0].y,
-                     m[1].x, m[1].y,
-                        0.0,    0.0);
-}
-
-mat3x2 __constructor(const mat2x4 m)
-{
-   __retVal = mat3x2(m[0].x, m[0].y,
-                     m[1].x, m[1].y,
-                        0.0,    0.0);
-}
-
-
-
-
-mat3 __constructor(const mat3 m)
-{
-   __retVal = m;
-}
-
-mat3 __constructor(const mat4x3 m)
-{
-   __retVal = mat3 (
-        m[0],
-        m[1],
-        m[2]
-    );
-}
-
-mat3 __constructor(const mat3x4 m)
-{
-   __retVal = mat3 (
-        m[0].xyz,
-        m[1].xyz,
-        m[2].xyz
-    );
-}
-
-mat3 __constructor(const mat4 m)
-{
-   __retVal = mat3 (
-        m[0].xyz,
-        m[1].xyz,
-        m[2].xyz
-    );
-}
-
-mat3 __constructor(const mat2x3 m)
-{
-   __retVal = mat3 (
-        m[0],
-        m[1],
-        0., 0., 1.
-    );
-}
-
-mat3 __constructor(const mat2x4 m)
-{
-   __retVal = mat3 (
-        m[0].xyz,
-        m[1].xyz,
-        0., 0., 1.
-    );
-}
-
-mat3 __constructor(const mat3x2 m)
-{
-   __retVal = mat3 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 1.
-    );
-}
-
-mat3 __constructor(const mat4x2 m)
-{
-   __retVal = mat3 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 1.
-    );
-}
-
-mat3 __constructor(const mat2 m)
-{
-   __retVal = mat3 (
-        m[0], 0.,
-        m[1], 0.,
-        0., 0., 1.
-    );
-}
-
-
-mat3x4 __constructor(const mat3x4 m)
-{
-   __retVal = m;
-}
-
-mat3x4 __constructor(const mat4 m)
-{
-   __retVal = mat3x4 (
-        m[0],
-        m[1],
-        m[2]
-    );
-}
-
-mat3x4 __constructor(const mat3 m)
-{
-   __retVal = mat3x4 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 0.
-    );
-}
-
-mat3x4 __constructor(const mat4x3 m)
-{
-   __retVal = mat3x4 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 0.
-    );
-}
-
-mat3x4 __constructor(const mat2x4 m)
-{
-   __retVal = mat3x4 (
-        m[0],
-        m[1],
-        0., 0., 1., 0.
-    );
-}
-
-mat3x4 __constructor(const mat2x3 m)
-{
-   __retVal = mat3x4 (
-        m[0], 0.,
-        m[1], 0.,
-        0., 0., 1., 0.
-    );
-}
-
-mat3x4 __constructor(const mat3x2 m)
-{
-   __retVal = mat3x4 (
-        m[0], 0., 0.,
-        m[1], 0., 0.,
-        m[2], 1., 0.
-    );
-}
-
-mat3x4 __constructor(const mat4x2 m)
-{
-   __retVal = mat3x4 (
-        m[0], 0., 0.,
-        m[1], 0., 0.,
-        m[2], 1., 0.
-    );
-}
-
-mat3x4 __constructor(const mat2 m)
-{
-   __retVal = mat3x4 (
-        m[0], 0., 0.,
-        m[1], 0., 0.,
-        0., 0., 1., 0.
-    );
-}
-
-
-mat4x2 __constructor(const mat4x2 m)
-{
-   __retVal = m;
-}
-
-mat4x2 __constructor(const mat4x3 m)
-{
-   __retVal = mat4x2 (
-        m[0].xy,
-        m[1].xy,
-        m[2].xy,
-        m[3].xy
-    );
-}
-
-mat4x2 __constructor(const mat4 m)
-{
-   __retVal = mat4x2 (
-        m[0].xy,
-        m[1].xy,
-        m[2].xy,
-        m[3].xy
-    );
-}
-
-mat4x2 __constructor(const mat3x2 m)
-{
-   __retVal = mat4x2 (
-        m[0],
-        m[1],
-        0., 0.
-    );
-}
-
-mat4x2 __constructor(const mat3 m)
-{
-   __retVal = mat4x2 (
-        m[0].xy,
-        m[1].xy,
-        m[2].xy,
-        0., 0.
-    );
-}
-
-mat4x2 __constructor(const mat3x4 m)
-{
-   __retVal = mat4x2 (
-        m[0].xy,
-        m[1].xy,
-        m[2].xy,
-        0., 0.
-    );
-}
-
-mat4x2 __constructor(const mat2 m)
-{
-   __retVal = mat4x2 (
-        m[0],
-        m[1],
-        0., 0.,
-        0., 0.
-    );
-}
-
-mat4x2 __constructor(const mat2x3 m)
-{
-   __retVal = mat4x2 (
-        m[0].xy,
-        m[1].xy,
-        0., 0.,
-        0., 0.
-    );
-}
-
-mat4x2 __constructor(const mat2x4 m)
-{
-   __retVal = mat4x2 (
-        m[0].xy,
-        m[1].xy,
-        0., 0.,
-        0., 0.
-    );
-}
-
-
-mat4x3 __constructor(const mat4x3 m)
-{
-   __retVal = m;
-}
-
-mat4x3 __constructor(const mat4 m)
-{
-   __retVal = mat4x3 (
-        m[0].xyz,
-        m[1].xyz,
-        m[2].xyz,
-        m[3].xyz
-    );
-}
-
-mat4x3 __constructor(const mat3 m)
-{
-   __retVal = mat4x3 (
-        m[0],
-        m[1],
-        m[2],
-        0., 0., 0.
-    );
-}
-
-mat4x3 __constructor(const mat3x4 m)
-{
-   __retVal = mat4x3 (
-        m[0].xyz,
-        m[1].xyz,
-        m[2].xyz,
-        0., 0., 0.
-    );
-}
-
-mat4x3 __constructor(const mat4x2 m)
-{
-   __retVal = mat4x3 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 1.,
-        m[3], 0.
-    );
-}
-
-mat4x3 __constructor(const mat2x3 m)
-{
-   __retVal = mat4x3 (
-        m[0],
-        m[1],
-        0., 0., 1.,
-        0., 0., 0.
-    );
-}
-
-mat4x3 __constructor(const mat3x2 m)
-{
-   __retVal = mat4x3 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 1.,
-        0., 0., 0.
-    );
-}
-
-mat4x3 __constructor(const mat2x4 m)
-{
-   __retVal = mat4x3 (
-        m[0].xyz,
-        m[1].xyz,
-        0., 0., 1.,
-        0., 0., 0.
-    );
-}
-
-mat4x3 __constructor(const mat2 m)
-{
-   __retVal = mat4x3 (
-        m[0], 0.,
-        m[1], 0.,
-        0., 0., 1.,
-        0., 0., 0.
-    );
-}
-
-
-mat4 __constructor(const mat4 m)
-{
-   __retVal = m;
-}
-
-mat4 __constructor(const mat3x4 m)
-{
-   __retVal = mat4 (
-        m[0],
-        m[1],
-        m[2],
-        0., 0., 0., 1.
-    );
-}
-
-mat4 __constructor(const mat4x3 m)
-{
-   __retVal = mat4 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 0.,
-        m[3], 1.
-    );
-}
-
-mat4 __constructor(const mat2x4 m)
-{
-   __retVal = mat4 (
-        m[0],
-        m[1],
-        0., 0., 1., 0.,
-        0., 0., 0., 1.
-    );
-}
-
-mat4 __constructor(const mat4x2 m)
-{
-   __retVal = mat4 (
-        m[0], 0., 0.,
-        m[1], 0., 0.,
-        m[2], 1., 0.,
-        m[3], 0., 1.
-    );
-}
-
-mat4 __constructor(const mat3 m)
-{
-   __retVal = mat4 (
-        m[0], 0.,
-        m[1], 0.,
-        m[2], 0.,
-        0., 0., 0., 1.
-    );
-}
-
-mat4 __constructor(const mat2x3 m)
-{
-   __retVal = mat4 (
-        m[0], 0.,
-        m[1], 0.,
-        0., 0., 1., 0.,
-        0., 0., 0., 1.
-    );
-}
-
-mat4 __constructor(const mat3x2 m)
-{
-   __retVal = mat4 (
-        m[0], 0., 0.,
-        m[1], 0., 0.,
-        m[2], 1., 0.,
-        0., 0., 0., 1.
-    );
-}
-
-mat4 __constructor(const mat2 m)
-{
-   __retVal = mat4 (
-        m[0], 0., 0.,
-        m[1], 0., 0.,
-        0., 0., 1., 0.,
-        0., 0., 0., 1.
-    );
-}
-
-
-void __operator += (inout mat2x3 m, const mat2x3 n) {
-    m[0] += n[0];
-    m[1] += n[1];
-}
-
-void __operator += (inout mat2x4 m, const mat2x4 n) {
-    m[0] += n[0];
-    m[1] += n[1];
-}
-
-void __operator += (inout mat3x2 m, const mat3x2 n) {
-    m[0] += n[0];
-    m[1] += n[1];
-    m[2] += n[2];
-}
-
-void __operator += (inout mat3x4 m, const mat3x4 n) {
-    m[0] += n[0];
-    m[1] += n[1];
-    m[2] += n[2];
-}
-
-void __operator += (inout mat4x2 m, const mat4x2 n) {
-    m[0] += n[0];
-    m[1] += n[1];
-    m[2] += n[2];
-    m[3] += n[3];
-}
-
-void __operator += (inout mat4x3 m, const mat4x3 n) {
-    m[0] += n[0];
-    m[1] += n[1];
-    m[2] += n[2];
-    m[3] += n[3];
-}
-
-
-void __operator -= (inout mat2x3 m, const mat2x3 n) {
-    m[0] -= n[0];
-    m[1] -= n[1];
-}
-
-void __operator -= (inout mat2x4 m, const mat2x4 n) {
-    m[0] -= n[0];
-    m[1] -= n[1];
-}
-
-void __operator -= (inout mat3x2 m, const mat3x2 n) {
-    m[0] -= n[0];
-    m[1] -= n[1];
-    m[2] -= n[2];
-}
-
-void __operator -= (inout mat3x4 m, const mat3x4 n) {
-    m[0] -= n[0];
-    m[1] -= n[1];
-    m[2] -= n[2];
-}
-
-void __operator -= (inout mat4x2 m, const mat4x2 n) {
-    m[0] -= n[0];
-    m[1] -= n[1];
-    m[2] -= n[2];
-    m[3] -= n[3];
-}
-
-void __operator -= (inout mat4x3 m, const mat4x3 n) {
-    m[0] -= n[0];
-    m[1] -= n[1];
-    m[2] -= n[2];
-    m[3] -= n[3];
-}
-
-
-void __operator /= (inout mat2x3 m, const mat2x3 n) {
-    m[0] /= n[0];
-    m[1] /= n[1];
-}
-
-void __operator /= (inout mat2x4 m, const mat2x4 n) {
-    m[0] /= n[0];
-    m[1] /= n[1];
-}
-
-void __operator /= (inout mat3x2 m, const mat3x2 n) {
-    m[0] /= n[0];
-    m[1] /= n[1];
-    m[2] /= n[2];
-}
-
-void __operator /= (inout mat3x4 m, const mat3x4 n) {
-    m[0] /= n[0];
-    m[1] /= n[1];
-    m[2] /= n[2];
-}
-
-void __operator /= (inout mat4x2 m, const mat4x2 n) {
-    m[0] /= n[0];
-    m[1] /= n[1];
-    m[2] /= n[2];
-    m[3] /= n[3];
-}
-
-void __operator /= (inout mat4x3 m, const mat4x3 n) {
-    m[0] /= n[0];
-    m[1] /= n[1];
-    m[2] /= n[2];
-    m[3] /= n[3];
-}
-
-
-vec3 __operator * (const mat2x3 m, const vec2 v)
-{
-   __retVal.x = v.x * m[0].x + v.y * m[1].x;
-   __retVal.y = v.x * m[0].y + v.y * m[1].y;
-   __retVal.z = v.x * m[0].z + v.y * m[1].z;
-}
-
-vec4 __operator * (const mat2x4 m, const vec2 v)
-{
-   __retVal.x = v.x * m[0].x + v.y * m[1].x;
-   __retVal.y = v.x * m[0].y + v.y * m[1].y;
-   __retVal.z = v.x * m[0].z + v.y * m[1].z;
-   __retVal.w = v.x * m[0].w + v.y * m[1].w;
-}
-
-vec2 __operator * (const mat3x2 m, const vec3 v)
-{
-   __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x;
-   __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y;
-}
-
-vec4 __operator * (const mat3x4 m, const vec3 v)
-{
-   __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x;
-   __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y;
-   __retVal.z = v.x * m[0].z + v.y * m[1].z + v.z * m[2].z;
-   __retVal.w = v.x * m[0].w + v.y * m[1].w + v.z * m[2].w;
-}
-
-vec2 __operator * (const mat4x2 m, const vec4 v)
-{
-   __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x + v.w * m[3].x;
-   __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + v.w * m[3].y;
-}
-
-vec3 __operator * (const mat4x3 m, const vec4 v)
-{
-   __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x + v.w * m[3].x;
-   __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + v.w * m[3].y;
-   __retVal.z = v.x * m[0].z + v.y * m[1].z + v.z * m[2].z + v.w * m[3].z;
-}
-
-
-mat3x2 __operator * (const mat2 m, const mat3x2 n)
-{
-   //return mat3x2 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-mat4x2 __operator * (const mat2 m, const mat4x2 n)
-{
-   //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2x3 __operator * (const mat2x3 m, const mat2 n)
-{
-   //return mat2x3 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat3 __operator * (const mat2x3 m, const mat3x2 n)
-{
-   //return mat3 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-mat4x3 __operator * (const mat2x3 m, const mat4x2 n)
-{
-   //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2x4 __operator * (const mat2x4 m, const mat2 n)
-{
-   //return mat2x4 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat3x4 __operator * (const mat2x4 m, const mat3x2 n)
-{
-   //return mat3x4 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-mat4 __operator * (const mat2x4 m, const mat4x2 n)
-{
-   //return mat4 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2 __operator * (const mat3x2 m, const mat2x3 n)
-{
-   //return mat2 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat3x2 __operator * (const mat3x2 m, const mat3 n)
-{
-   //return mat3x2 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-mat4x2 __operator * (const mat3x2 m, const mat4x3 n)
-{
-   //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2x3 __operator * (const mat3 m, const mat2x3 n)
-{
-   //return mat2x3 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat4x3 __operator * (const mat3 m, const mat4x3 n)
-{
-   //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2x4 __operator * (const mat3x4 m, const mat2x3 n)
-{
-   //return mat2x4 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat3x4 __operator * (const mat3x4 m, const mat3 n)
-{
-   //return mat3x4 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-mat4 __operator * (const mat3x4 m, const mat4x3 n)
-{
-   //return mat4 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2 __operator * (const mat4x2 m, const mat2x4 n)
-{
-   //return = mat2 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat3x2 __operator * (const mat4x2 m, const mat3x4 n)
-{
-   //return mat3x2 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-mat4x2 __operator * (const mat4x2 m, const mat4 n)
-{
-   //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2x3 __operator * (const mat4x3 m, const mat2x4 n)
-{
-   //return mat2x3 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat3 __operator * (const mat4x3 m, const mat3x4 n)
-{
-   //return mat3 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-mat4x3 __operator * (const mat4x3 m, const mat4 n)
-{
-   //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-   __retVal[3] = m * n[3];
-}
-
-
-mat2x4 __operator * (const mat4 m, const mat2x4 n)
-{
-   //return mat2x4 (m * n[0], m * n[1]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-}
-
-mat3x4 __operator * (const mat4 m, const mat3x4 n)
-{
-   //return mat3x4 (m * n[0], m * n[1], m * n[2]);
-   __retVal[0] = m * n[0];
-   __retVal[1] = m * n[1];
-   __retVal[2] = m * n[2];
-}
-
-
-void __operator *= (inout mat2x3 m, const mat2 n) {
-    m = m * n;
-}
-
-void __operator *= (inout mat2x4 m, const mat2 n) {
-    m = m * n;
-}
-
-void __operator *= (inout mat3x2 m, const mat3 n) {
-    m = m * n;
-}
-
-void __operator *= (inout mat3x4 m, const mat3 n) {
-    m = m * n;
-}
-
-void __operator *= (inout mat4x2 m, const mat4 n) {
-    m = m * n;
-}
-
-void __operator *= (inout mat4x3 m, const mat4 n) {
-    m = m * n;
-}
-
-
-vec3 __operator * (const vec2 v, const mat3x2 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-   __retVal.z = dot(v, m[2]);
-}
-
-vec4 __operator * (const vec2 v, const mat4x2 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-   __retVal.z = dot(v, m[2]);
-   __retVal.w = dot(v, m[3]);
-}
-
-vec2 __operator * (const vec3 v, const mat2x3 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-}
-
-vec4 __operator * (const vec3 v, const mat4x3 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-   __retVal.z = dot(v, m[2]);
-   __retVal.w = dot(v, m[3]);
-}
-
-vec2 __operator * (const vec4 v, const mat2x4 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-}
-
-vec3 __operator * (const vec4 v, const mat3x4 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-   __retVal.z = dot(v, m[2]);
-}
-
-
-void __operator += (inout mat2x3 m, const float a) {
-    m[0] += a;
-    m[1] += a;
-}
-
-void __operator += (inout mat2x4 m, const float a) {
-    m[0] += a;
-    m[1] += a;
-}
-
-void __operator += (inout mat3x2 m, const float a) {
-    m[0] += a;
-    m[1] += a;
-    m[2] += a;
-}
-
-void __operator += (inout mat3x4 m, const float a) {
-    m[0] += a;
-    m[1] += a;
-    m[2] += a;
-}
-
-void __operator += (inout mat4x2 m, const float a) {
-    m[0] += a;
-    m[1] += a;
-    m[2] += a;
-    m[3] += a;
-}
-
-void __operator += (inout mat4x3 m, const float a) {
-    m[0] += a;
-    m[1] += a;
-    m[2] += a;
-    m[3] += a;
-}
-
-
-void __operator -= (inout mat2x3 m, const float a) {
-    m[0] -= a;
-    m[1] -= a;
-}
-
-void __operator -= (inout mat2x4 m, const float a) {
-    m[0] -= a;
-    m[1] -= a;
-}
-
-void __operator -= (inout mat3x2 m, const float a) {
-    m[0] -= a;
-    m[1] -= a;
-    m[2] -= a;
-}
-
-void __operator -= (inout mat3x4 m, const float a) {
-    m[0] -= a;
-    m[1] -= a;
-    m[2] -= a;
-}
-
-void __operator -= (inout mat4x2 m, const float a) {
-    m[0] -= a;
-    m[1] -= a;
-    m[2] -= a;
-    m[3] -= a;
-}
-
-void __operator -= (inout mat4x3 m, const float a) {
-    m[0] -= a;
-    m[1] -= a;
-    m[2] -= a;
-    m[3] -= a;
-}
-
-
-void __operator *= (inout mat2x3 m, const float a) {
-    m[0] *= a;
-    m[1] *= a;
-}
-
-void __operator *= (inout mat2x4 m, const float a) {
-    m[0] *= a;
-    m[1] *= a;
-}
-
-void __operator *= (inout mat3x2 m, const float a) {
-    m[0] *= a;
-    m[1] *= a;
-    m[2] *= a;
-}
-
-void __operator *= (inout mat3x4 m, const float a) {
-    m[0] *= a;
-    m[1] *= a;
-    m[2] *= a;
-}
-
-void __operator *= (inout mat4x2 m, const float a) {
-    m[0] *= a;
-    m[1] *= a;
-    m[2] *= a;
-    m[3] *= a;
-}
-
-void __operator *= (inout mat4x3 m, const float a) {
-    m[0] *= a;
-    m[1] *= a;
-    m[2] *= a;
-    m[3] *= a;
-}
-
-
-void __operator /= (inout mat2x3 m, const float a) {
-    m[0] /= a;
-    m[1] /= a;
-}
-
-void __operator /= (inout mat2x4 m, const float a) {
-    m[0] /= a;
-    m[1] /= a;
-}
-
-void __operator /= (inout mat3x2 m, const float a) {
-    m[0] /= a;
-    m[1] /= a;
-    m[2] /= a;
-}
-
-void __operator /= (inout mat3x4 m, const float a) {
-    m[0] /= a;
-    m[1] /= a;
-    m[2] /= a;
-}
-
-void __operator /= (inout mat4x2 m, const float a) {
-    m[0] /= a;
-    m[1] /= a;
-    m[2] /= a;
-    m[3] /= a;
-}
-
-void __operator /= (inout mat4x3 m, const float a) {
-    m[0] /= a;
-    m[1] /= a;
-    m[2] /= a;
-    m[3] /= a;
-}
-
-
-mat2x3 __operator + (const mat2x3 m, const mat2x3 n) {
-    return mat2x3 (m[0] + n[0], m[1] + n[1]);
-}
-
-mat2x4 __operator + (const mat2x4 m, const mat2x4 n) {
-    return mat2x4 (m[0] + n[0], m[1] + n[1]);
-}
-
-mat3x2 __operator + (const mat3x2 m, const mat3x2 n) {
-    return mat3x2 (m[0] + n[0], m[1] + n[1], m[2] + n[2]);
-}
-
-mat3x4 __operator + (const mat3x4 m, const mat3x4 n) {
-    return mat3x4 (m[0] + n[0], m[1] + n[1], m[2] + n[2]);
-}
-
-mat4x2 __operator + (const mat4x2 m, const mat4x2 n) {
-    return mat4x2 (m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3]);
-}
-
-mat4x3 __operator + (const mat4x3 m, const mat4x3 n) {
-    return mat4x3 (m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3]);
-}
-
-
-mat2x3 __operator - (const mat2x3 m, const mat2x3 n) {
-    return mat2x3 (m[0] - n[0], m[1] - n[1]);
-}
-
-mat2x4 __operator - (const mat2x4 m, const mat2x4 n) {
-    return mat2x4 (m[0] - n[0], m[1] - n[1]);
-}
-
-mat3x2 __operator - (const mat3x2 m, const mat3x2 n) {
-    return mat3x2 (m[0] - n[0], m[1] - n[1], m[2] - n[2]);
-}
-
-mat3x4 __operator - (const mat3x4 m, const mat3x4 n) {
-    return mat3x4 (m[0] - n[0], m[1] - n[1], m[2] - n[2]);
-}
-
-mat4x2 __operator - (const mat4x2 m, const mat4x2 n) {
-    return mat4x2 (m[0] - n[0], m[1] - n[1], m[2] - n[2], m[3] - n[3]);
-}
-
-mat4x3 __operator - (const mat4x3 m, const mat4x3 n) {
-    return mat4x3 (m[0] - n[0], m[1] - n[1], m[2] - n[2], m[3] - n[3]);
-}
-
-
-mat2x3 __operator / (const mat2x3 m, const mat2x3 n) {
-    return mat2x3 (m[0] / n[0], m[1] / n[1]);
-}
-
-mat2x4 __operator / (const mat2x4 m, const mat2x4 n) {
-    return mat2x4 (m[0] / n[0], m[1] / n[1]);
-}
-
-mat3x2 __operator / (const mat3x2 m, const mat3x2 n) {
-    return mat3x2 (m[0] / n[0], m[1] / n[1], m[2] / n[2]);
-}
-
-mat3x4 __operator / (const mat3x4 m, const mat3x4 n) {
-    return mat3x4 (m[0] / n[0], m[1] / n[1], m[2] / n[2]);
-}
-
-mat4x2 __operator / (const mat4x2 m, const mat4x2 n) {
-    return mat4x2 (m[0] / n[0], m[1] / n[1], m[2] / n[2], m[3] / n[3]);
-}
-
-mat4x3 __operator / (const mat4x3 m, const mat4x3 n) {
-    return mat4x3 (m[0] / n[0], m[1] / n[1], m[2] / n[2], m[3] / n[3]);
-}
-
-
-mat2x3 __operator + (const float a, const mat2x3 n) {
-    return mat2x3 (a + n[0], a + n[1]);
-}
-
-mat2x3 __operator + (const mat2x3 m, const float b) {
-    return mat2x3 (m[0] + b, m[1] + b);
-}
-
-mat2x4 __operator + (const float a, const mat2x4 n) {
-    return mat2x4 (a + n[0], a + n[1]);
-}
-
-mat2x4 __operator + (const mat2x4 m, const float b) {
-    return mat2x4 (m[0] + b, m[1] + b);
-}
-
-mat3x2 __operator + (const float a, const mat3x2 n) {
-    return mat3x2 (a + n[0], a + n[1], a + n[2]);
-}
-
-mat3x2 __operator + (const mat3x2 m, const float b) {
-    return mat3x2 (m[0] + b, m[1] + b, m[2] + b);
-}
-
-mat3x4 __operator + (const float a, const mat3x4 n) {
-    return mat3x4 (a + n[0], a + n[1], a + n[2]);
-}
-
-mat3x4 __operator + (const mat3x4 m, const float b) {
-    return mat3x4 (m[0] + b, m[1] + b, m[2] + b);
-}
-
-mat4x2 __operator + (const mat4x2 m, const float b) {
-    return mat4x2 (m[0] + b, m[1] + b, m[2] + b, m[3] + b);
-}
-
-mat4x2 __operator + (const float a, const mat4x2 n) {
-    return mat4x2 (a + n[0], a + n[1], a + n[2], a + n[3]);
-}
-
-mat4x3 __operator + (const mat4x3 m, const float b) {
-    return mat4x3 (m[0] + b, m[1] + b, m[2] + b, m[3] + b);
-}
-
-mat4x3 __operator + (const float a, const mat4x3 n) {
-    return mat4x3 (a + n[0], a + n[1], a + n[2], a + n[3]);
-}
-
-
-mat2x3 __operator - (const float a, const mat2x3 n) {
-    return mat2x3 (a - n[0], a - n[1]);
-}
-
-mat2x3 __operator - (const mat2x3 m, const float b) {
-    return mat2x3 (m[0] - b, m[1] - b);
-}
-
-mat2x4 __operator - (const float a, const mat2x4 n) {
-    return mat2x4 (a - n[0], a - n[1]);
-}
-
-mat2x4 __operator - (const mat2x4 m, const float b) {
-    return mat2x4 (m[0] - b, m[1] - b);
-}
-
-mat3x2 __operator - (const float a, const mat3x2 n) {
-    return mat3x2 (a - n[0], a - n[1], a - n[2]);
-}
-
-mat3x2 __operator - (const mat3x2 m, const float b) {
-    return mat3x2 (m[0] - b, m[1] - b, m[2] - b);
-}
-
-mat3x4 __operator - (const float a, const mat3x4 n) {
-    return mat3x4 (a - n[0], a - n[1], a - n[2]);
-}
-
-mat3x4 __operator - (const mat3x4 m, const float b) {
-    return mat3x4 (m[0] - b, m[1] - b, m[2] - b);
-}
-
-mat4x2 __operator - (const mat4x2 m, const float b) {
-    return mat4x2 (m[0] - b, m[1] - b, m[2] - b, m[3] - b);
-}
-
-mat4x2 __operator - (const float a, const mat4x2 n) {
-    return mat4x2 (a - n[0], a - n[1], a - n[2], a - n[3]);
-}
-
-mat4x3 __operator - (const mat4x3 m, const float b) {
-    return mat4x3 (m[0] - b, m[1] - b, m[2] - b, m[3] - b);
-}
-
-mat4x3 __operator - (const float a, const mat4x3 n) {
-    return mat4x3 (a - n[0], a - n[1], a - n[2], a - n[3]);
-}
-
-
-mat2x3 __operator * (const float a, const mat2x3 n)
-{
-   //return mat2x3 (a * n[0], a * n[1]);
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-}
-
-mat2x3 __operator * (const mat2x3 m, const float b)
-{
-   //return mat2x3 (m[0] * b, m[1] * b);
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-}
-
-mat2x4 __operator * (const float a, const mat2x4 n)
-{
-   //return mat2x4 (a * n[0], a * n[1]);
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-}
-
-mat2x4 __operator * (const mat2x4 m, const float b)
-{
-   //return mat2x4 (m[0] * b, m[1] * b);
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-}
-
-mat3x2 __operator * (const float a, const mat3x2 n)
-{
-   //return mat3x2 (a * n[0], a * n[1], a * n[2]);
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-   __retVal[2] = a * n[2];
-}
-
-mat3x2 __operator * (const mat3x2 m, const float b)
-{
-   //return mat3x2 (m[0] * b, m[1] * b, m[2] * b);
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-   __retVal[2] = m[2] * b;
-}
-
-mat3x4 __operator * (const float a, const mat3x4 n)
-{
-   //return mat3x4 (a * n[0], a * n[1], a * n[2]);
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-   __retVal[2] = a * n[2];
-}
-
-mat3x4 __operator * (const mat3x4 m, const float b)
-{
-   //return mat3x4 (m[0] * b, m[1] * b, m[2] * b);
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-   __retVal[2] = m[2] * b;
-}
-
-mat4x2 __operator * (const mat4x2 m, const float b)
-{
-   //return mat4x2 (m[0] * b, m[1] * b, m[2] * b, m[3] * b);
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-   __retVal[2] = m[2] * b;
-   __retVal[3] = m[3] * b;
-}
-
-mat4x2 __operator * (const float a, const mat4x2 n)
-{
-   //return mat4x2 (a * n[0], a * n[1], a * n[2], a * n[3]);
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-   __retVal[2] = a * n[2];
-   __retVal[3] = a * n[3];
-}
-
-mat4x3 __operator * (const mat4x3 m, const float b)
-{
-   //return mat4x3 (m[0] * b, m[1] * b, m[2] * b, m[3] * b);
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-   __retVal[2] = m[2] * b;
-   __retVal[3] = m[3] * b;
-}
-
-mat4x3 __operator * (const float a, const mat4x3 n)
-{
-   //return mat4x3 (a * n[0], a * n[1], a * n[2], a * n[3]);
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-   __retVal[2] = a * n[2];
-   __retVal[3] = a * n[3];
-}
-
-
-mat2x3 __operator / (const float a, const mat2x3 n)
-{
-   //return mat2x3 (a / n[0], a / n[1]);
-   const float inv = 1.0 / a;
-   __retVal[0] = inv * n[0];
-   __retVal[1] = inv * n[1];
-}
-
-mat2x3 __operator / (const mat2x3 m, const float b)
-{
-   //return mat2x3 (m[0] / b, m[1] / b);
-   const float inv = 1.0 / b;
-   __retVal[0] = m[0] * inv;
-   __retVal[1] = m[1] * inv;
-}
-
-mat2x4 __operator / (const float a, const mat2x4 n)
-{
-   //return mat2x4 (a / n[0], a / n[1]);
-   const float inv = 1.0 / a;
-   __retVal[0] = inv * n[0];
-   __retVal[1] = inv * n[1];
-}
-
-mat2x4 __operator / (const mat2x4 m, const float b)
-{
-   //return mat2x4 (m[0] / b, m[1] / b);
-   const float inv = 1.0 / b;
-   __retVal[0] = m[0] * inv;
-   __retVal[1] = m[1] * inv;
-}
-
-mat3x2 __operator / (const float a, const mat3x2 n)
-{
-   //return mat3x2 (a / n[0], a / n[1], a / n[2]);
-   const float inv = 1.0 / a;
-   __retVal[0] = inv * n[0];
-   __retVal[1] = inv * n[1];
-   __retVal[2] = inv * n[2];
-}
-
-mat3x2 __operator / (const mat3x2 m, const float b)
-{
-   //return mat3x2 (m[0] / b, m[1] / b, m[2] / b);
-   const float inv = 1.0 / b;
-   __retVal[0] = m[0] * inv;
-   __retVal[1] = m[1] * inv;
-   __retVal[2] = m[2] * inv;
-}
-
-mat3x4 __operator / (const float a, const mat3x4 n)
-{
-   //return mat3x4 (a / n[0], a / n[1], a / n[2]);
-   const float inv = 1.0 / a;
-   __retVal[0] = inv * n[0];
-   __retVal[1] = inv * n[1];
-   __retVal[2] = inv * n[2];
-}
-
-mat3x4 __operator / (const mat3x4 m, const float b)
-{
-   //return mat3x4 (m[0] / b, m[1] / b, m[2] / b);
-   const float inv = 1.0 / b;
-   __retVal[0] = m[0] * inv;
-   __retVal[1] = m[1] * inv;
-   __retVal[2] = m[2] * inv;
-}
-
-mat4x2 __operator / (const mat4x2 m, const float b)
-{
-   //return mat4x2 (m[0] / b, m[1] / b, m[2] / b, m[3] / b);
-   const float inv = 1.0 / b;
-   __retVal[0] = m[0] * inv;
-   __retVal[1] = m[1] * inv;
-   __retVal[2] = m[2] * inv;
-   __retVal[3] = m[3] * inv;
-}
-
-mat4x2 __operator / (const float a, const mat4x2 n)
-{
-   //return mat4x2 (a / n[0], a / n[1], a / n[2], a / n[3]);
-   const float inv = 1.0 / a;
-   __retVal[0] = inv * n[0];
-   __retVal[1] = inv * n[1];
-   __retVal[2] = inv * n[2];
-   __retVal[3] = inv * n[3];
-}
-
-mat4x3 __operator / (const mat4x3 m, const float b)
-{
-   //return mat4x3 (m[0] / b, m[1] / b, m[2] / b, m[3] / b);
-   const float inv = 1.0 / b;
-   __retVal[0] = m[0] * inv;
-   __retVal[1] = m[1] * inv;
-   __retVal[2] = m[2] * inv;
-   __retVal[3] = m[3] * inv;
-}
-
-mat4x3 __operator / (const float a, const mat4x3 n)
-{
-   //return mat4x3 (a / n[0], a / n[1], a / n[2], a / n[3]);
-   const float inv = 1.0 / a;
-   __retVal[0] = inv * n[0];
-   __retVal[1] = inv * n[1];
-   __retVal[2] = inv * n[2];
-   __retVal[3] = inv * n[3];
-}
-
-
-mat2x3 __operator - (const mat2x3 m) {
-    return mat2x3 (-m[0], -m[1]);
-}
-
-mat2x4 __operator - (const mat2x4 m) {
-    return mat2x4 (-m[0], -m[1]);
-}
-
-mat3x2 __operator - (const mat3x2 m) {
-    return mat3x2 (-m[0], -m[1], -m[2]);
-}
-
-mat3x4 __operator - (const mat3x4 m) {
-    return mat3x4 (-m[0], -m[1], -m[2]);
-}
-
-mat4x2 __operator - (const mat4x2 m) {
-    return mat4x2 (-m[0], -m[1], -m[2], -m[3]);
-}
-
-mat4x3 __operator - (const mat4x3 m) {
-    return mat4x3 (-m[0], -m[1], -m[2], -m[3]);
-}
-
-
-void __operator -- (inout mat2x3 m) {
-    --m[0];
-    --m[1];
-}
-
-void __operator -- (inout mat2x4 m) {
-    --m[0];
-    --m[1];
-}
-
-void __operator -- (inout mat3x2 m) {
-    --m[0];
-    --m[1];
-    --m[2];
-}
-
-void __operator -- (inout mat3x4 m) {
-    --m[0];
-    --m[1];
-    --m[2];
-}
-
-void __operator -- (inout mat4x2 m) {
-    --m[0];
-    --m[1];
-    --m[2];
-    --m[3];
-}
-
-void __operator -- (inout mat4x3 m) {
-    --m[0];
-    --m[1];
-    --m[2];
-    --m[3];
-}
-
-
-void __operator ++ (inout mat2x3 m) {
-    ++m[0];
-    ++m[1];
-}
-
-void __operator ++ (inout mat2x4 m) {
-    ++m[0];
-    ++m[1];
-}
-
-void __operator ++ (inout mat3x2 m) {
-    ++m[0];
-    ++m[1];
-    ++m[2];
-}
-
-void __operator ++ (inout mat3x4 m) {
-    ++m[0];
-    ++m[1];
-    ++m[2];
-}
-
-void __operator ++ (inout mat4x2 m) {
-    ++m[0];
-    ++m[1];
-    ++m[2];
-    ++m[3];
-}
-
-void __operator ++ (inout mat4x3 m) {
-    ++m[0];
-    ++m[1];
-    ++m[2];
-    ++m[3];
-}
-
diff --git a/src/mesa/slang/library/slang_builtin_120_common.gc b/src/mesa/slang/library/slang_builtin_120_common.gc
deleted file mode 100644 (file)
index c6264c3..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.6
- *
- * Copyright (C) 2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-//
-// From Shader Spec, ver. 1.20, rev. 6
-//
-
-//
-// 8.5 Matrix Functions
-//
-
-mat2x3 matrixCompMult (mat2x3 m, mat2x3 n) {
-    return mat2x3 (m[0] * n[0], m[1] * n[1]);
-}
-
-mat2x4 matrixCompMult (mat2x4 m, mat2x4 n) {
-    return mat2x4 (m[0] * n[0], m[1] * n[1]);
-}
-
-mat3x2 matrixCompMult (mat3x2 m, mat3x2 n) {
-    return mat3x2 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
-}
-
-mat3x4 matrixCompMult (mat3x4 m, mat3x4 n) {
-    return mat3x4 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
-}
-
-mat4x2 matrixCompMult (mat4x2 m, mat4x2 n) {
-    return mat4x2 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
-}
-
-mat4x3 matrixCompMult (mat4x3 m, mat4x3 n) {
-    return mat4x3 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
-}
-
-mat2 outerProduct (vec2 c, vec2 r) {
-    return mat2 (
-        c.x * r.x, c.y * r.x,
-        c.x * r.y, c.y * r.y
-    );
-}
-
-mat3 outerProduct (vec3 c, vec3 r) {
-    return mat3 (
-        c.x * r.x, c.y * r.x, c.z * r.x,
-        c.x * r.y, c.y * r.y, c.z * r.y,
-        c.x * r.z, c.y * r.z, c.z * r.z
-    );
-}
-
-mat4 outerProduct (vec4 c, vec4 r) {
-    return mat4 (
-        c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x,
-        c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y,
-        c.x * r.z, c.y * r.z, c.z * r.z, c.w * r.z,
-        c.x * r.w, c.y * r.w, c.z * r.w, c.w * r.w
-    );
-}
-
-mat2x3 outerProduct (vec3 c, vec2 r) {
-    return mat2x3 (
-        c.x * r.x, c.y * r.x, c.z * r.x,
-        c.x * r.y, c.y * r.y, c.z * r.y
-    );
-}
-
-mat3x2 outerProduct (vec2 c, vec3 r) {
-    return mat3x2 (
-        c.x * r.x, c.y * r.x,
-        c.x * r.y, c.y * r.y,
-        c.x * r.z, c.y * r.z
-    );
-}
-
-mat2x4 outerProduct (vec4 c, vec2 r) {
-    return mat2x4 (
-        c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x,
-        c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y
-    );
-}
-
-mat4x2 outerProduct (vec2 c, vec4 r) {
-    return mat4x2 (
-        c.x * r.x, c.y * r.x,
-        c.x * r.y, c.y * r.y,
-        c.x * r.z, c.y * r.z,
-        c.x * r.w, c.y * r.w
-    );
-}
-
-mat3x4 outerProduct (vec4 c, vec3 r) {
-    return mat3x4 (
-        c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x,
-        c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y,
-        c.x * r.z, c.y * r.z, c.z * r.z, c.w * r.z
-    );
-}
-
-mat4x3 outerProduct (vec3 c, vec4 r) {
-    return mat4x3 (
-        c.x * r.x, c.y * r.x, c.z * r.x,
-        c.x * r.y, c.y * r.y, c.z * r.y,
-        c.x * r.z, c.y * r.z, c.z * r.z,
-        c.x * r.w, c.y * r.w, c.z * r.w
-    );
-}
-
-mat2 transpose (mat2 m) {
-    return mat2 (
-        m[0].x, m[1].x,
-        m[0].y, m[1].y
-    );
-}
-
-mat3 transpose (mat3 m) {
-    return mat3 (
-        m[0].x, m[1].x, m[2].x,
-        m[0].y, m[1].y, m[2].y,
-        m[0].z, m[1].z, m[2].z
-    );
-}
-
-mat4 transpose (mat4 m) {
-    return mat4 (
-        m[0].x, m[1].x, m[2].x, m[3].x,
-        m[0].y, m[1].y, m[2].y, m[3].y,
-        m[0].z, m[1].z, m[2].z, m[3].z,
-        m[0].w, m[1].w, m[2].w, m[3].w
-    );
-}
-
-mat2x3 transpose (mat3x2 m) {
-    return mat2x3 (
-        m[0].x, m[1].x, m[2].x,
-        m[0].y, m[1].y, m[2].y
-    );
-}
-
-mat3x2 transpose (mat2x3 m) {
-    return mat3x2 (
-        m[0].x, m[1].x,
-        m[0].y, m[1].y,
-        m[0].z, m[1].z
-    );
-}
-
-mat2x4 transpose (mat4x2 m) {
-    return mat2x4 (
-        m[0].x, m[1].x, m[2].x, m[3].x,
-        m[0].y, m[1].y, m[2].y, m[3].y
-    );
-}
-
-mat4x2 transpose (mat2x4 m) {
-    return mat4x2 (
-        m[0].x, m[1].x,
-        m[0].y, m[1].y,
-        m[0].z, m[1].z,
-        m[0].w, m[1].w
-    );
-}
-
-mat3x4 transpose (mat4x3 m) {
-    return mat3x4 (
-        m[0].x, m[1].x, m[2].x, m[3].x,
-        m[0].y, m[1].y, m[2].y, m[3].y,
-        m[0].z, m[1].z, m[2].z, m[3].z
-    );
-}
-
-mat4x3 transpose (mat3x4 m) {
-    return mat4x3 (
-        m[0].x, m[1].x, m[2].x,
-        m[0].y, m[1].y, m[2].y,
-        m[0].z, m[1].z, m[2].z,
-        m[0].w, m[1].w, m[2].w
-    );
-}
-
diff --git a/src/mesa/slang/library/slang_builtin_120_fragment.gc b/src/mesa/slang/library/slang_builtin_120_fragment.gc
deleted file mode 100644 (file)
index 7d51604..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-//
-// From Shader Spec, ver. 1.20, rev. 6
-//
-
-varying vec2 gl_PointCoord;
-
diff --git a/src/mesa/slang/library/slang_common_builtin.gc b/src/mesa/slang/library/slang_common_builtin.gc
deleted file mode 100644 (file)
index 1f5ddbc..0000000
+++ /dev/null
@@ -1,1887 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.3
- *
- * Copyright (C) 2006  Brian Paul   All Rights Reserved.
- * Copyright (C) 2008  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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-//
-// From Shader Spec, ver. 1.10, rev. 59
-//
-
-// Note: the values assigned to these constants here aren't actually used.
-// They're set by the compiler according to the GL context limits.
-// See slang_simplify.c
-const int gl_MaxLights = 8;
-const int gl_MaxClipPlanes = 6;
-const int gl_MaxTextureUnits = 8;
-const int gl_MaxTextureCoords = 8;
-const int gl_MaxVertexAttribs = 16;
-const int gl_MaxVertexUniformComponents = 512;
-const int gl_MaxVaryingFloats = 32;
-const int gl_MaxVertexTextureImageUnits = 0;
-const int gl_MaxCombinedTextureImageUnits = 2;
-const int gl_MaxTextureImageUnits = 2;
-const int gl_MaxFragmentUniformComponents = 64;
-const int gl_MaxDrawBuffers = 1;
-
-uniform mat4 gl_ModelViewMatrix;
-uniform mat4 gl_ProjectionMatrix;
-uniform mat4 gl_ModelViewProjectionMatrix;
-uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];
-
-uniform mat3 gl_NormalMatrix;
-
-uniform mat4 gl_ModelViewMatrixInverse;
-uniform mat4 gl_ProjectionMatrixInverse;
-uniform mat4 gl_ModelViewProjectionMatrixInverse;
-uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];
-
-uniform mat4 gl_ModelViewMatrixTranspose;
-uniform mat4 gl_ProjectionMatrixTranspose;
-uniform mat4 gl_ModelViewProjectionMatrixTranspose;
-uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];
-
-uniform mat4 gl_ModelViewMatrixInverseTranspose;
-uniform mat4 gl_ProjectionMatrixInverseTranspose;
-uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;
-uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];
-
-uniform float gl_NormalScale;
-
-struct gl_DepthRangeParameters {
-    float near;
-    float far;
-    float diff;
-};
-
-uniform gl_DepthRangeParameters gl_DepthRange;
-
-uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];
-
-struct gl_PointParameters {
-    float size;
-    float sizeMin;
-    float sizeMax;
-    float fadeThresholdSize;
-    float distanceConstantAttenuation;
-    float distanceLinearAttenuation;
-    float distanceQuadraticAttenuation;
-};
-
-uniform gl_PointParameters gl_Point;
-
-struct gl_MaterialParameters {
-    vec4 emission;
-    vec4 ambient;
-    vec4 diffuse;
-    vec4 specular;
-    float shininess;
-};
-
-uniform gl_MaterialParameters gl_FrontMaterial;
-uniform gl_MaterialParameters gl_BackMaterial;
-
-/* NOTE: the order of these fields is significant!
- * See the definition of the lighting state vars such as STATE_SPOT_DIRECTION.
- */
-struct gl_LightSourceParameters {
-    vec4 ambient;
-    vec4 diffuse;
-    vec4 specular;
-    vec4 position;
-    vec4 halfVector;
-    vec3 spotDirection;
-    float spotCosCutoff;
-
-    float constantAttenuation;
-    float linearAttenuation;
-    float quadraticAttenuation;
-    float spotExponent;
-
-    float spotCutoff;
-};
-
-uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];
-
-struct gl_LightModelParameters {
-    vec4 ambient;
-};
-
-uniform gl_LightModelParameters gl_LightModel;
-
-struct gl_LightModelProducts {
-    vec4 sceneColor;
-};
-
-uniform gl_LightModelProducts gl_FrontLightModelProduct;
-uniform gl_LightModelProducts gl_BackLightModelProduct;
-
-struct gl_LightProducts {
-    vec4 ambient;
-    vec4 diffuse;
-    vec4 specular;
-};
-
-uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];
-uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];
-
-uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits];
-uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];
-uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];
-uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];
-uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];
-uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];
-uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];
-uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];
-uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];
-
-struct gl_FogParameters {
-    vec4 color;
-    float density;
-    float start;
-    float end;
-    float scale;
-};
-
-uniform gl_FogParameters gl_Fog;
-
-
-
-
-
-//
-// 8.1 Angle and Trigonometry Functions
-//
-
-//// radians
-
-float radians(const float deg)
-{
-   const float c = 3.1415926 / 180.0;
-   __asm vec4_multiply __retVal, deg, c;
-}
-
-vec2 radians(const vec2 deg)
-{
-   const float c = 3.1415926 / 180.0;
-   __asm vec4_multiply __retVal.xy, deg.xy, c.xx;
-}
-
-vec3 radians(const vec3 deg)
-{
-   const float c = 3.1415926 / 180.0;
-   __asm vec4_multiply __retVal.xyz, deg.xyz, c.xxx;
-}
-
-vec4 radians(const vec4 deg)
-{
-   const float c = 3.1415926 / 180.0;
-   __asm vec4_multiply __retVal, deg, c.xxxx;
-}
-
-
-//// degrees
-
-float degrees(const float rad)
-{
-   const float c = 180.0 / 3.1415926;
-   __asm vec4_multiply __retVal, rad, c;
-}
-
-vec2 degrees(const vec2 rad)
-{
-   const float c = 180.0 / 3.1415926;
-   __asm vec4_multiply __retVal.xy, rad.xy, c.xx;
-}
-
-vec3 degrees(const vec3 rad)
-{
-   const float c = 180.0 / 3.1415926;
-   __asm vec4_multiply __retVal.xyz, rad.xyz, c.xxx;
-}
-
-vec4 degrees(const vec4 rad)
-{
-   const float c = 180.0 / 3.1415926;
-   __asm vec4_multiply __retVal, rad, c.xxxx;
-}
-
-
-//// sin
-
-float sin(const float radians)
-{
-   __asm float_sine __retVal, radians;
-}
-
-vec2 sin(const vec2 radians)
-{
-   __asm float_sine __retVal.x, radians.x;
-   __asm float_sine __retVal.y, radians.y;
-}
-
-vec3 sin(const vec3 radians)
-{
-   __asm float_sine __retVal.x, radians.x;
-   __asm float_sine __retVal.y, radians.y;
-   __asm float_sine __retVal.z, radians.z;
-}
-
-vec4 sin(const vec4 radians)
-{
-   __asm float_sine __retVal.x, radians.x;
-   __asm float_sine __retVal.y, radians.y;
-   __asm float_sine __retVal.z, radians.z;
-   __asm float_sine __retVal.w, radians.w;
-}
-
-
-//// cos
-
-float cos(const float radians)
-{
-   __asm float_cosine __retVal, radians;
-}
-
-vec2 cos(const vec2 radians)
-{
-   __asm float_cosine __retVal.x, radians.x;
-   __asm float_cosine __retVal.y, radians.y;
-}
-
-vec3 cos(const vec3 radians)
-{
-   __asm float_cosine __retVal.x, radians.x;
-   __asm float_cosine __retVal.y, radians.y;
-   __asm float_cosine __retVal.z, radians.z;
-}
-
-vec4 cos(const vec4 radians)
-{
-   __asm float_cosine __retVal.x, radians.x;
-   __asm float_cosine __retVal.y, radians.y;
-   __asm float_cosine __retVal.z, radians.z;
-   __asm float_cosine __retVal.w, radians.w;
-}
-
-
-
-//// tan
-
-float tan(const float angle)
-{
-   const float s = sin(angle);
-   const float c = cos(angle);
-   return s / c;
-}
-
-vec2 tan(const vec2 angle)
-{
-   const vec2 s = sin(angle);
-   const vec2 c = cos(angle);
-   return s / c;
-}
-
-vec3 tan(const vec3 angle)
-{
-   const vec3 s = sin(angle);
-   const vec3 c = cos(angle);
-   return s / c;
-}
-
-vec4 tan(const vec4 angle)
-{
-   const vec4 s = sin(angle);
-   const vec4 c = cos(angle);
-   return s / c;
-}
-
-
-
-float asin(const float x)
-{
-   const float a0 = 1.5707288;  // PI/2?
-   const float a1 = -0.2121144;
-   const float a2 = 0.0742610;
-   //const float a3 = -0.0187293;
-   const float halfPi = 3.1415926 * 0.5;
-   const float y = abs(x);
-   // three terms seem to be enough:
-   __retVal = (halfPi - sqrt(1.0 - y) * (a0 + y * (a1 + a2 * y))) * sign(x);
-   // otherwise, try four:
-   //__retVal = (halfPi - sqrt(1.0 - y) * (a0 + y * (a1 + y * (a2 + y * a3)))) * sign(x);
-}
-
-vec2 asin(const vec2 v)
-{
-   __retVal.x = asin(v.x);
-   __retVal.y = asin(v.y);
-}
-
-vec3 asin(const vec3 v)
-{
-   __retVal.x = asin(v.x);
-   __retVal.y = asin(v.y);
-   __retVal.z = asin(v.z);
-}
-
-vec4 asin(const vec4 v)
-{
-   __retVal.x = asin(v.x);
-   __retVal.y = asin(v.y);
-   __retVal.z = asin(v.z);
-   __retVal.w = asin(v.w);
-}
-
-float acos(const float x)
-{
-   const float halfPi = 3.1415926 * 0.5;
-   __retVal = halfPi - asin(x);
-}
-
-vec2 acos(const vec2 v)
-{
-   __retVal.x = acos(v.x);
-   __retVal.y = acos(v.y);
-}
-
-vec3 acos(const vec3 v)
-{
-   __retVal.x = acos(v.x);
-   __retVal.y = acos(v.y);
-   __retVal.z = acos(v.z);
-}
-
-vec4 acos(const vec4 v)
-{
-   __retVal.x = acos(v.x);
-   __retVal.y = acos(v.y);
-   __retVal.z = acos(v.z);
-   __retVal.w = acos(v.w);
-}
-
-float atan(const float x)
-{
-   __retVal = asin(x * inversesqrt(x * x + 1.0));
-}
-
-vec2 atan(const vec2 y_over_x)
-{
-   __retVal.x = atan(y_over_x.x);
-   __retVal.y = atan(y_over_x.y);
-}
-
-vec3 atan(const vec3 y_over_x)
-{
-   __retVal.x = atan(y_over_x.x);
-   __retVal.y = atan(y_over_x.y);
-   __retVal.z = atan(y_over_x.z);
-}
-
-vec4 atan(const vec4 y_over_x)
-{
-   __retVal.x = atan(y_over_x.x);
-   __retVal.y = atan(y_over_x.y);
-   __retVal.z = atan(y_over_x.z);
-   __retVal.w = atan(y_over_x.w);
-}
-
-float atan(const float y, const float x)
-{
-   float r;
-   if (abs(x) > 1.0e-4) {
-      r = atan(y / x);
-      if (x < 0.0) {
-         r = r + 3.141593 - 6.283186 * float(y < 0.0);
-      }
-   }
-   else {
-      r = sign(y) * 1.5707965;  // pi/2
-   }
-   return r;
-}
-
-vec2 atan(const vec2 u, const vec2 v)
-{
-   __retVal.x = atan(u.x, v.x);
-   __retVal.y = atan(u.y, v.y);
-}
-
-vec3 atan(const vec3 u, const vec3 v)
-{
-   __retVal.x = atan(u.x, v.x);
-   __retVal.y = atan(u.y, v.y);
-   __retVal.z = atan(u.z, v.z);
-}
-
-vec4 atan(const vec4 u, const vec4 v)
-{
-   __retVal.x = atan(u.x, v.x);
-   __retVal.y = atan(u.y, v.y);
-   __retVal.z = atan(u.z, v.z);
-   __retVal.w = atan(u.w, v.w);
-}
-
-
-//
-// 8.2 Exponential Functions
-//
-
-//// pow
-
-float pow(const float a, const float b)
-{
-   __asm float_power __retVal, a, b;
-}
-
-vec2 pow(const vec2 a, const vec2 b)
-{
-   __asm float_power __retVal.x, a.x, b.x;
-   __asm float_power __retVal.y, a.y, b.y;
-}
-
-vec3 pow(const vec3 a, const vec3 b)
-{
-   __asm float_power __retVal.x, a.x, b.x;
-   __asm float_power __retVal.y, a.y, b.y;
-   __asm float_power __retVal.z, a.z, b.z;
-}
-
-vec4 pow(const vec4 a, const vec4 b)
-{
-   __asm float_power __retVal.x, a.x, b.x;
-   __asm float_power __retVal.y, a.y, b.y;
-   __asm float_power __retVal.z, a.z, b.z;
-   __asm float_power __retVal.w, a.w, b.w;
-}
-
-
-//// exp
-
-float exp(const float a)
-{
-   // NOTE: log2(e) = 1.44269502
-   float t = a * 1.44269502;
-   __asm float_exp2 __retVal, t;
-}
-
-vec2 exp(const vec2 a)
-{
-   vec2 t = a * 1.44269502;
-   __asm float_exp2 __retVal.x, t.x;
-   __asm float_exp2 __retVal.y, t.y;
-}
-
-vec3 exp(const vec3 a)
-{
-   vec3 t = a * 1.44269502;
-   __asm float_exp2 __retVal.x, t.x;
-   __asm float_exp2 __retVal.y, t.y;
-   __asm float_exp2 __retVal.z, t.z;
-}
-
-vec4 exp(const vec4 a)
-{
-   vec4 t = a * 1.44269502;
-   __asm float_exp2 __retVal.x, t.x;
-   __asm float_exp2 __retVal.y, t.y;
-   __asm float_exp2 __retVal.z, t.z;
-   __asm float_exp2 __retVal.w, t.w;
-}
-
-
-
-//// log2
-
-float log2(const float x)
-{
-   __asm float_log2 __retVal, x;
-}
-
-vec2 log2(const vec2 v)
-{
-   __asm float_log2 __retVal.x, v.x;
-   __asm float_log2 __retVal.y, v.y;
-}
-
-vec3 log2(const vec3 v)
-{
-   __asm float_log2 __retVal.x, v.x;
-   __asm float_log2 __retVal.y, v.y;
-   __asm float_log2 __retVal.z, v.z;
-}
-
-vec4 log2(const vec4 v)
-{
-   __asm float_log2 __retVal.x, v.x;
-   __asm float_log2 __retVal.y, v.y;
-   __asm float_log2 __retVal.z, v.z;
-   __asm float_log2 __retVal.w, v.w;
-}
-
-
-//// log  (natural log)
-
-float log(const float x)
-{
-   // note:  logBaseB(x) = logBaseN(x) / logBaseN(B)
-   // compute log(x) = log2(x) / log2(e)
-   // c = 1.0 / log2(e) = 0.693147181
-   const float c = 0.693147181;
-   return log2(x) * c;
-}
-
-vec2 log(const vec2 v)
-{
-   const float c = 0.693147181;
-   return log2(v) * c;
-}
-
-vec3 log(const vec3 v)
-{
-   const float c = 0.693147181;
-   return log2(v) * c;
-}
-
-vec4 log(const vec4 v)
-{
-   const float c = 0.693147181;
-   return log2(v) * c;
-}
-
-
-//// exp2
-
-float exp2(const float a)
-{
-   __asm float_exp2 __retVal, a;
-}
-
-vec2 exp2(const vec2 a)
-{
-   __asm float_exp2 __retVal.x, a.x;
-   __asm float_exp2 __retVal.y, a.y;
-}
-
-vec3 exp2(const vec3 a)
-{
-   __asm float_exp2 __retVal.x, a.x;
-   __asm float_exp2 __retVal.y, a.y;
-   __asm float_exp2 __retVal.z, a.z;
-}
-
-vec4 exp2(const vec4 a)
-{
-   __asm float_exp2 __retVal.x, a.x;
-   __asm float_exp2 __retVal.y, a.y;
-   __asm float_exp2 __retVal.z, a.z;
-   __asm float_exp2 __retVal.w, a.w;
-}
-
-
-//// sqrt
-
-float sqrt(const float x)
-{
-   const float nx = -x;
-   float r;
-   __asm float_rsq r, x;
-   r = r * x;
-   __asm vec4_cmp __retVal, nx, r, 0.0;
-}
-
-vec2 sqrt(const vec2 x)
-{
-   const vec2 nx = -x, zero = vec2(0.0);
-   vec2 r;
-   __asm float_rsq r.x, x.x;
-   __asm float_rsq r.y, x.y;
-   r = r * x;
-   __asm vec4_cmp __retVal, nx, r, zero;
-}
-
-vec3 sqrt(const vec3 x)
-{
-   const vec3 nx = -x, zero = vec3(0.0);
-   vec3 r;
-   __asm float_rsq r.x, x.x;
-   __asm float_rsq r.y, x.y;
-   __asm float_rsq r.z, x.z;
-   r = r * x;
-   __asm vec4_cmp __retVal, nx, r, zero;
-}
-
-vec4 sqrt(const vec4 x)
-{
-   const vec4 nx = -x, zero = vec4(0.0);
-   vec4 r;
-   __asm float_rsq r.x, x.x;
-   __asm float_rsq r.y, x.y;
-   __asm float_rsq r.z, x.z;
-   __asm float_rsq r.w, x.w;
-   r = r * x;
-   __asm vec4_cmp __retVal, nx, r, zero;
-}
-
-
-//// inversesqrt
-
-float inversesqrt(const float x)
-{
-   __asm float_rsq __retVal.x, x;
-}
-
-vec2 inversesqrt(const vec2 v)
-{
-   __asm float_rsq __retVal.x, v.x;
-   __asm float_rsq __retVal.y, v.y;
-}
-
-vec3 inversesqrt(const vec3 v)
-{
-   __asm float_rsq __retVal.x, v.x;
-   __asm float_rsq __retVal.y, v.y;
-   __asm float_rsq __retVal.z, v.z;
-}
-
-vec4 inversesqrt(const vec4 v)
-{
-   __asm float_rsq __retVal.x, v.x;
-   __asm float_rsq __retVal.y, v.y;
-   __asm float_rsq __retVal.z, v.z;
-   __asm float_rsq __retVal.w, v.w;
-}
-
-
-//// normalize
-
-float normalize(const float x)
-{
-   __retVal = 1.0;
-}
-
-vec2 normalize(const vec2 v)
-{
-   const float s = inversesqrt(dot(v, v));
-   __asm vec4_multiply __retVal.xy, v, s;
-}
-
-vec3 normalize(const vec3 v)
-{
-//   const float s = inversesqrt(dot(v, v));
-//   __retVal = v * s;
-// XXX note, we _could_ use __retVal.w instead of tmp and save a
-// register, but that's actually a compilation error because v is a vec3
-// and the .w suffix is illegal.  Oh well.
-   float tmp;
-   __asm vec3_dot tmp, v, v;
-   __asm float_rsq tmp, tmp;
-   __asm vec4_multiply __retVal.xyz, v, tmp;
-}
-
-vec4 normalize(const vec4 v)
-{
-   float tmp;
-   __asm vec4_dot tmp, v, v;
-   __asm float_rsq tmp, tmp;
-   __asm vec4_multiply __retVal.xyz, v, tmp;
-}
-
-
-
-//
-// 8.3 Common Functions
-//
-
-
-//// abs
-
-float abs(const float a)
-{
-   __asm vec4_abs __retVal, a;
-}
-
-vec2 abs(const vec2 a)
-{
-   __asm vec4_abs __retVal.xy, a;
-}
-
-vec3 abs(const vec3 a)
-{
-   __asm vec4_abs __retVal.xyz, a;
-}
-
-vec4 abs(const vec4 a)
-{
-   __asm vec4_abs __retVal, a;
-}
-
-
-//// sign
-
-float sign(const float x)
-{
-   float p, n;
-   __asm vec4_sgt p, x, 0.0;            // p = (x > 0)
-   __asm vec4_sgt n, 0.0, x;            // n = (x < 0)
-   __asm vec4_subtract __retVal, p, n;  // sign = p - n
-}
-
-vec2 sign(const vec2 v)
-{
-   vec2 p, n;
-   __asm vec4_sgt p.xy, v, 0.0;
-   __asm vec4_sgt n.xy, 0.0, v;
-   __asm vec4_subtract __retVal.xy, p, n;
-}
-
-vec3 sign(const vec3 v)
-{
-   vec3 p, n;
-   __asm vec4_sgt p.xyz, v, 0.0;
-   __asm vec4_sgt n.xyz, 0.0, v;
-   __asm vec4_subtract __retVal.xyz, p, n;
-}
-
-vec4 sign(const vec4 v)
-{
-   vec4 p, n;
-   __asm vec4_sgt p, v, 0.0;
-   __asm vec4_sgt n, 0.0, v;
-   __asm vec4_subtract __retVal, p, n;
-}
-
-
-//// floor
-
-float floor(const float a)
-{
-   __asm vec4_floor __retVal, a;
-}
-
-vec2 floor(const vec2 a)
-{
-   __asm vec4_floor __retVal.xy, a;
-}
-
-vec3 floor(const vec3 a)
-{
-   __asm vec4_floor __retVal.xyz, a;
-}
-
-vec4 floor(const vec4 a)
-{
-   __asm vec4_floor __retVal, a;
-}
-
-
-//// ceil
-
-float ceil(const float a)
-{
-   // XXX this could be improved
-   float b = -a;
-   __asm vec4_floor b, b;
-   __retVal = -b;
-}
-
-vec2 ceil(const vec2 a)
-{
-   vec2 b = -a;
-   __asm vec4_floor b, b;
-   __retVal.xy = -b;
-}
-
-vec3 ceil(const vec3 a)
-{
-   vec3 b = -a;
-   __asm vec4_floor b, b;
-   __retVal.xyz = -b;
-}
-
-vec4 ceil(const vec4 a)
-{
-   vec4 b = -a;
-   __asm vec4_floor b, b;
-   __retVal = -b;
-}
-
-
-//// fract
-
-float fract(const float a)
-{
-   __asm vec4_frac __retVal, a;
-}
-
-vec2 fract(const vec2 a)
-{
-   __asm vec4_frac __retVal.xy, a;
-}
-
-vec3 fract(const vec3 a)
-{
-   __asm vec4_frac __retVal.xyz, a;
-}
-
-vec4 fract(const vec4 a)
-{
-   __asm vec4_frac __retVal, a;
-}
-
-
-//// mod  (very untested!)
-
-float mod(const float a, const float b)
-{
-    float oneOverB;
-    __asm float_rcp oneOverB, b;
-    __retVal = a - b * floor(a * oneOverB);
-}
-
-vec2 mod(const vec2 a, const float b)
-{
-    float oneOverB;
-    __asm float_rcp oneOverB, b;
-    __retVal.xy = a - b * floor(a * oneOverB);
-}
-
-vec3 mod(const vec3 a, const float b)
-{
-    float oneOverB;
-    __asm float_rcp oneOverB, b;
-    __retVal.xyz = a - b * floor(a * oneOverB);
-}
-
-vec4 mod(const vec4 a, const float b)
-{
-    float oneOverB;
-    __asm float_rcp oneOverB, b;
-    __retVal = a - b * floor(a * oneOverB);
-}
-
-vec2 mod(const vec2 a, const vec2 b)
-{
-    vec2 oneOverB;
-    __asm float_rcp oneOverB.x, b.x;
-    __asm float_rcp oneOverB.y, b.y;
-    __retVal = a - b * floor(a * oneOverB);
-}
-
-vec3 mod(const vec3 a, const vec3 b)
-{
-    vec3 oneOverB;
-    __asm float_rcp oneOverB.x, b.x;
-    __asm float_rcp oneOverB.y, b.y;
-    __asm float_rcp oneOverB.z, b.z;
-    __retVal = a - b * floor(a * oneOverB);
-}
-
-vec4 mod(const vec4 a, const vec4 b)
-{
-    vec4 oneOverB;
-    __asm float_rcp oneOverB.x, b.x;
-    __asm float_rcp oneOverB.y, b.y;
-    __asm float_rcp oneOverB.z, b.z;
-    __asm float_rcp oneOverB.w, b.w;
-    __retVal = a - b * floor(a * oneOverB);
-}
-
-
-//// min
-
-float min(const float a, const float b)
-{
-   __asm vec4_min __retVal, a, b;
-}
-
-vec2 min(const vec2 a, const vec2 b)
-{
-   __asm vec4_min __retVal.xy, a.xy, b.xy;
-}
-
-vec3 min(const vec3 a, const vec3 b)
-{
-   __asm vec4_min __retVal.xyz, a.xyz, b.xyz;
-}
-
-vec4 min(const vec4 a, const vec4 b)
-{
-   __asm vec4_min __retVal, a, b;
-}
-
-vec2 min(const vec2 a, const float b)
-{
-   __asm vec4_min __retVal, a.xy, b;
-}
-
-vec3 min(const vec3 a, const float b)
-{
-   __asm vec4_min __retVal, a.xyz, b;
-}
-
-vec4 min(const vec4 a, const float b)
-{
-   __asm vec4_min __retVal, a, b;
-}
-
-
-//// max
-
-float max(const float a, const float b)
-{
-   __asm vec4_max __retVal, a, b;
-}
-
-vec2 max(const vec2 a, const vec2 b)
-{
-   __asm vec4_max __retVal.xy, a.xy, b.xy;
-}
-
-vec3 max(const vec3 a, const vec3 b)
-{
-   __asm vec4_max __retVal.xyz, a.xyz, b.xyz;
-}
-
-vec4 max(const vec4 a, const vec4 b)
-{
-   __asm vec4_max __retVal, a, b;
-}
-
-vec2 max(const vec2 a, const float b)
-{
-   __asm vec4_max __retVal, a.xy, b;
-}
-
-vec3 max(const vec3 a, const float b)
-{
-   __asm vec4_max __retVal, a.xyz, b;
-}
-
-vec4 max(const vec4 a, const float b)
-{
-   __asm vec4_max __retVal, a, b;
-}
-
-
-//// clamp
-
-float clamp(const float val, const float minVal, const float maxVal)
-{
-   __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec2 clamp(const vec2 val, const float minVal, const float maxVal)
-{
-   __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec3 clamp(const vec3 val, const float minVal, const float maxVal)
-{
-   __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec4 clamp(const vec4 val, const float minVal, const float maxVal)
-{
-   __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec2 clamp(const vec2 val, const vec2 minVal, const vec2 maxVal)
-{
-   __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec3 clamp(const vec3 val, const vec3 minVal, const vec3 maxVal)
-{
-   __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-vec4 clamp(const vec4 val, const vec4 minVal, const vec4 maxVal)
-{
-   __asm vec4_clamp __retVal, val, minVal, maxVal;
-}
-
-
-//// mix
-
-float mix(const float x, const float y, const float a)
-{
-   __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec2 mix(const vec2 x, const vec2 y, const float a)
-{
-   __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec3 mix(const vec3 x, const vec3 y, const float a)
-{
-   __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec4 mix(const vec4 x, const vec4 y, const float a)
-{
-   __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec2 mix(const vec2 x, const vec2 y, const vec2 a)
-{
-   __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec3 mix(const vec3 x, const vec3 y, const vec3 a)
-{
-   __asm vec4_lrp __retVal, a, y, x;
-}
-
-vec4 mix(const vec4 x, const vec4 y, const vec4 a)
-{
-   __asm vec4_lrp __retVal, a, y, x;
-}
-
-
-//// step
-
-float step(const float edge, const float x)
-{
-   __asm vec4_sge __retVal, x, edge;
-}
-
-vec2 step(const vec2 edge, const vec2 x)
-{
-   __asm vec4_sge __retVal.xy, x, edge;
-}
-
-vec3 step(const vec3 edge, const vec3 x)
-{
-   __asm vec4_sge __retVal.xyz, x, edge;
-}
-
-vec4 step(const vec4 edge, const vec4 x)
-{
-   __asm vec4_sge __retVal, x, edge;
-}
-
-vec2 step(const float edge, const vec2 v)
-{
-   __asm vec4_sge __retVal.xy, v, edge;
-}
-
-vec3 step(const float edge, const vec3 v)
-{
-   __asm vec4_sge __retVal.xyz, v, edge;
-}
-
-vec4 step(const float edge, const vec4 v)
-{
-   __asm vec4_sge __retVal, v, edge;
-}
-
-
-//// smoothstep
-
-float smoothstep(const float edge0, const float edge1, const float x)
-{
-    float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
-    return t * t * (3.0 - 2.0 * t);
-}
-
-vec2 smoothstep(const vec2 edge0, const vec2 edge1, const vec2 v)
-{
-   vec2 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
-   return t * t * (3.0 - 2.0 * t);
-}
-
-vec3 smoothstep(const vec3 edge0, const vec3 edge1, const vec3 v)
-{
-   vec3 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
-   return t * t * (3.0 - 2.0 * t);
-}
-
-vec4 smoothstep(const vec4 edge0, const vec4 edge1, const vec4 v)
-{
-   vec4 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
-   return t * t * (3.0 - 2.0 * t);
-}
-
-vec2 smoothstep(const float edge0, const float edge1, const vec2 v)
-{
-   vec2 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
-   return t * t * (3.0 - 2.0 * t);
-}
-
-vec3 smoothstep(const float edge0, const float edge1, const vec3 v)
-{
-   vec3 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
-   return t * t * (3.0 - 2.0 * t);
-}
-
-vec4 smoothstep(const float edge0, const float edge1, const vec4 v)
-{
-   vec4 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
-   return t * t * (3.0 - 2.0 * t);
-}
-
-
-
-//
-// 8.4 Geometric Functions
-//
-
-
-//// length
-
-float length(const float x)
-{
-   return abs(x);
-}
-
-float length(const vec2 v)
-{
-   float r;
-   const float p = dot(v, v);      // p = v.x * v.x + v.y * v.y
-   __asm float_rsq r, p;           // r = 1 / sqrt(p)
-   __retVal = p * r;               // p * r = sqrt(p);
-}
-
-float length(const vec3 v)
-{
-   float r;
-   const float p = dot(v, v);      // p = v.x * v.x + v.y * v.y + v.z * v.z
-   __asm float_rsq r, p;           // r = 1 / sqrt(p)
-   __retVal = p * r;               // p * r = sqrt(p);
-}
-
-float length(const vec4 v)
-{
-   float r;
-   const float p = dot(v, v);      // p = v.x * v.x + v.y * v.y + ...
-   __asm float_rsq r, p;           // r = 1 / sqrt(p)
-   __retVal = p * r;               // p * r = sqrt(p);
-}
-
-
-//// distance
-
-float distance(const float x, const float y)
-{
-   const float d = x - y;
-   __retVal = length(d);
-}
-
-float distance(const vec2 v, const vec2 u)
-{
-   const vec2 d2 = v - u;
-   __retVal = length(d2);
-}
-
-float distance(const vec3 v, const vec3 u)
-{
-   const vec3 d3 = v - u;
-   __retVal = length(d3);
-}
-
-float distance(const vec4 v, const vec4 u)
-{
-   const vec4 d4 = v - u;
-   __retVal = length(d4);
-}
-
-
-//// cross
-
-vec3 cross(const vec3 v, const vec3 u)
-{
-   __asm vec3_cross __retVal.xyz, v, u;
-}
-
-
-//// faceforward
-
-float faceforward(const float N, const float I, const float Nref)
-{
-    // this could probably be done better
-    const float d = dot(Nref, I);
-    float s;
-    __asm vec4_sgt s, 0.0, d;  // s = (0.0 > d) ? 1 : 0
-    return mix(-N, N, s);
-}
-
-vec2 faceforward(const vec2 N, const vec2 I, const vec2 Nref)
-{
-    // this could probably be done better
-    const float d = dot(Nref, I);
-    float s;
-    __asm vec4_sgt s, 0.0, d;  // s = (0.0 > d) ? 1 : 0
-    return mix(-N, N, s);
-}
-
-vec3 faceforward(const vec3 N, const vec3 I, const vec3 Nref)
-{
-    // this could probably be done better
-    const float d = dot(Nref, I);
-    float s;
-    __asm vec4_sgt s, 0.0, d;  // s = (0.0 > d) ? 1 : 0
-    return mix(-N, N, s);
-}
-
-vec4 faceforward(const vec4 N, const vec4 I, const vec4 Nref)
-{
-    // this could probably be done better
-    const float d = dot(Nref, I);
-    float s;
-    __asm vec4_sgt s, 0.0, d;  // s = (0.0 > d) ? 1 : 0
-    return mix(-N, N, s);
-}
-
-
-//// reflect
-
-float reflect(const float I, const float N)
-{
-   return I - 2.0 * dot(N, I) * N;
-}
-
-vec2 reflect(const vec2 I, const vec2 N)
-{
-   return I - 2.0 * dot(N, I) * N;
-}
-
-vec3 reflect(const vec3 I, const vec3 N)
-{
-   return I - 2.0 * dot(N, I) * N;
-}
-
-vec4 reflect(const vec4 I, const vec4 N)
-{
-   return I - 2.0 * dot(N, I) * N;
-}
-
-//// refract
-
-float refract(const float I, const float N, const float eta)
-{
-   float n_dot_i = dot(N, I);
-   float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
-   float retval;
-   if (k < 0.0)
-      retval = 0.0;
-   else
-      retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
-   return retval;
-}
-
-vec2 refract(const vec2 I, const vec2 N, const float eta)
-{
-   float n_dot_i = dot(N, I);
-   float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
-   vec2 retval;
-   if (k < 0.0)
-      retval = vec2(0.0);
-   else
-      retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
-   return retval;
-}
-
-vec3 refract(const vec3 I, const vec3 N, const float eta)
-{
-   float n_dot_i = dot(N, I);
-   float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
-   vec3 retval;
-   if (k < 0.0)
-      retval = vec3(0.0);
-   else
-      retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
-   return retval;
-}
-
-vec4 refract(const vec4 I, const vec4 N, const float eta)
-{
-   float n_dot_i = dot(N, I);
-   float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
-   vec4 retval;
-   if (k < 0.0)
-      retval = vec4(0.0);
-   else
-      retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
-   return retval;
-}
-
-
-
-
-//
-// 8.5 Matrix Functions
-//
-
-mat2 matrixCompMult (mat2 m, mat2 n) {
-    return mat2 (m[0] * n[0], m[1] * n[1]);
-}
-
-mat3 matrixCompMult (mat3 m, mat3 n) {
-    return mat3 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
-}
-
-mat4 matrixCompMult (mat4 m, mat4 n) {
-    return mat4 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
-}
-
-
-
-
-//
-// 8.6 Vector Relational Functions
-//
-
-//// lessThan
-
-bvec2 lessThan(const vec2 u, const vec2 v)
-{
-   __asm vec4_slt __retVal.xy, u, v;
-}
-
-bvec3 lessThan(const vec3 u, const vec3 v)
-{
-   __asm vec4_slt __retVal.xyz, u, v;
-}
-
-bvec4 lessThan(const vec4 u, const vec4 v)
-{
-   __asm vec4_slt __retVal, u, v;
-}
-
-bvec2 lessThan(const ivec2 u, const ivec2 v)
-{
-   __asm vec4_slt __retVal.xy, u, v;
-}
-
-bvec3 lessThan(const ivec3 u, const ivec3 v)
-{
-   __asm vec4_slt __retVal.xyz, u, v;
-}
-
-bvec4 lessThan(const ivec4 u, const ivec4 v)
-{
-   __asm vec4_slt __retVal, u, v;
-}
-
-
-//// lessThanEqual
-
-bvec2 lessThanEqual(const vec2 u, const vec2 v)
-{
-   __asm vec4_sle __retVal.xy, u, v;
-}
-
-bvec3 lessThanEqual(const vec3 u, const vec3 v)
-{
-   __asm vec4_sle __retVal.xyz, u, v;
-}
-
-bvec4 lessThanEqual(const vec4 u, const vec4 v)
-{
-   __asm vec4_sle __retVal, u, v;
-}
-
-bvec2 lessThanEqual(const ivec2 u, const ivec2 v)
-{
-   __asm vec4_sle __retVal.xy, u, v;
-}
-
-bvec3 lessThanEqual(const ivec3 u, const ivec3 v)
-{
-   __asm vec4_sle __retVal.xyz, u, v;
-}
-
-bvec4 lessThanEqual(const ivec4 u, const ivec4 v)
-{
-   __asm vec4_sle __retVal, u, v;
-}
-
-
-//// greaterThan
-
-bvec2 greaterThan(const vec2 u, const vec2 v)
-{
-   __asm vec4_sgt __retVal.xy, u, v;
-}
-
-bvec3 greaterThan(const vec3 u, const vec3 v)
-{
-   __asm vec4_sgt __retVal.xyz, u, v;
-}
-
-bvec4 greaterThan(const vec4 u, const vec4 v)
-{
-   __asm vec4_sgt __retVal, u, v;
-}
-
-bvec2 greaterThan(const ivec2 u, const ivec2 v)
-{
-   __asm vec4_sgt __retVal.xy, u.xy, v.xy;
-}
-
-bvec3 greaterThan(const ivec3 u, const ivec3 v)
-{
-   __asm vec4_sgt __retVal.xyz, u, v;
-}
-
-bvec4 greaterThan(const ivec4 u, const ivec4 v)
-{
-   __asm vec4_sgt __retVal, u, v;
-}
-
-
-//// greaterThanEqual
-
-bvec2 greaterThanEqual(const vec2 u, const vec2 v)
-{
-   __asm vec4_sge __retVal.xy, u, v;
-}
-
-bvec3 greaterThanEqual(const vec3 u, const vec3 v)
-{
-   __asm vec4_sge __retVal.xyz, u, v;
-}
-
-bvec4 greaterThanEqual(const vec4 u, const vec4 v)
-{
-   __asm vec4_sge __retVal, u, v;
-}
-
-bvec2 greaterThanEqual(const ivec2 u, const ivec2 v)
-{
-   __asm vec4_sge __retVal.xy, u, v;
-}
-
-bvec3 greaterThanEqual(const ivec3 u, const ivec3 v)
-{
-   __asm vec4_sge __retVal.xyz, u, v;
-}
-
-bvec4 greaterThanEqual(const ivec4 u, const ivec4 v)
-{
-   __asm vec4_sge __retVal, u, v;
-}
-
-
-//// equal
-
-bvec2 equal(const vec2 u, const vec2 v)
-{
-   __asm vec4_seq __retVal.xy, u, v;
-}
-
-bvec3 equal(const vec3 u, const vec3 v)
-{
-   __asm vec4_seq __retVal.xyz, u, v;
-}
-
-bvec4 equal(const vec4 u, const vec4 v)
-{
-   __asm vec4_seq __retVal, u, v;
-}
-
-bvec2 equal(const ivec2 u, const ivec2 v)
-{
-   __asm vec4_seq __retVal.xy, u, v;
-}
-
-bvec3 equal(const ivec3 u, const ivec3 v)
-{
-   __asm vec4_seq __retVal.xyz, u, v;
-}
-
-bvec4 equal(const ivec4 u, const ivec4 v)
-{
-   __asm vec4_seq __retVal, u, v;
-}
-
-bvec2 equal(const bvec2 u, const bvec2 v)
-{
-   __asm vec4_seq __retVal.xy, u, v;
-}
-
-bvec3 equal(const bvec3 u, const bvec3 v)
-{
-   __asm vec4_seq __retVal.xyz, u, v;
-}
-
-bvec4 equal(const bvec4 u, const bvec4 v)
-{
-   __asm vec4_seq __retVal, u, v;
-}
-
-
-
-
-//// notEqual
-
-bvec2 notEqual(const vec2 u, const vec2 v)
-{
-   __asm vec4_sne __retVal.xy, u, v;
-}
-
-bvec3 notEqual(const vec3 u, const vec3 v)
-{
-   __asm vec4_sne __retVal.xyz, u, v;
-}
-
-bvec4 notEqual(const vec4 u, const vec4 v)
-{
-   __asm vec4_sne __retVal, u, v;
-}
-
-bvec2 notEqual(const ivec2 u, const ivec2 v)
-{
-   __asm vec4_sne __retVal.xy, u, v;
-}
-
-bvec3 notEqual(const ivec3 u, const ivec3 v)
-{
-   __asm vec4_sne __retVal.xyz, u, v;
-}
-
-bvec4 notEqual(const ivec4 u, const ivec4 v)
-{
-   __asm vec4_sne __retVal, u, v;
-}
-
-bvec2 notEqual(const bvec2 u, const bvec2 v)
-{
-   __asm vec4_sne __retVal.xy, u, v;
-}
-
-bvec3 notEqual(const bvec3 u, const bvec3 v)
-{
-   __asm vec4_sne __retVal.xyz, u, v;
-}
-
-bvec4 notEqual(const bvec4 u, const bvec4 v)
-{
-   __asm vec4_sne __retVal, u, v;
-}
-
-
-
-//// any
-
-bool any(const bvec2 v)
-{
-   float sum;
-   __asm vec4_add sum.x, v.x, v.y;
-   __asm vec4_sne __retVal.x, sum.x, 0.0;
-}
-
-bool any(const bvec3 v)
-{
-   float sum;
-   __asm vec4_add sum.x, v.x, v.y;
-   __asm vec4_add sum.x, sum.x, v.z;
-   __asm vec4_sne __retVal.x, sum.x, 0.0;
-}
-
-bool any(const bvec4 v)
-{
-   float sum;
-   __asm vec4_add sum.x, v.x, v.y;
-   __asm vec4_add sum.x, sum.x, v.z;
-   __asm vec4_add sum.x, sum.x, v.w;
-   __asm vec4_sne __retVal.x, sum.x, 0.0;
-}
-
-
-//// all
-
-bool all (const bvec2 v)
-{
-   float prod;
-   __asm vec4_multiply prod, v.x, v.y;
-   __asm vec4_sne __retVal, prod, 0.0;
-}
-
-bool all (const bvec3 v)
-{
-   float prod;
-   __asm vec4_multiply prod, v.x, v.y;
-   __asm vec4_multiply prod, prod, v.z;
-   __asm vec4_sne __retVal, prod, 0.0;
-}
-
-bool all (const bvec4 v)
-{
-   float prod;
-   __asm vec4_multiply prod, v.x, v.y;
-   __asm vec4_multiply prod, prod, v.z;
-   __asm vec4_multiply prod, prod, v.w;
-   __asm vec4_sne __retVal, prod, 0.0;
-}
-
-
-
-//// not
-
-bvec2 not (const bvec2 v)
-{
-   __asm vec4_seq __retVal.xy, v, 0.0;
-}
-
-bvec3 not (const bvec3 v)
-{
-   __asm vec4_seq __retVal.xyz, v, 0.0;
-}
-
-bvec4 not (const bvec4 v)
-{
-   __asm vec4_seq __retVal, v, 0.0;
-}
-
-
-
-//// Texture Lookup Functions  (for both fragment and vertex shaders)
-
-vec4 texture1D(const sampler1D sampler, const float coord)
-{
-   __asm vec4_tex_1d __retVal, sampler, coord;
-}
-
-vec4 texture1DProj(const sampler1D sampler, const vec2 coord)
-{
-   // need to swizzle .y into .w
-   __asm vec4_tex_1d_proj __retVal, sampler, coord.xyyy;
-}
-
-vec4 texture1DProj(const sampler1D sampler, const vec4 coord)
-{
-   __asm vec4_tex_1d_proj __retVal, sampler, coord;
-}
-
-
-vec4 texture2D(const sampler2D sampler, const vec2 coord)
-{
-   __asm vec4_tex_2d __retVal, sampler, coord;
-}
-
-vec4 texture2DProj(const sampler2D sampler, const vec3 coord)
-{
-   // need to swizzle 'z' into 'w'.
-   __asm vec4_tex_2d_proj __retVal, sampler, coord.xyzz;
-}
-
-vec4 texture2DProj(const sampler2D sampler, const vec4 coord)
-{
-   __asm vec4_tex_2d_proj __retVal, sampler, coord;
-}
-
-
-vec4 texture3D(const sampler3D sampler, const vec3 coord)
-{
-   __asm vec4_tex_3d __retVal, sampler, coord;
-}
-
-vec4 texture3DProj(const sampler3D sampler, const vec4 coord)
-{
-   __asm vec4_tex_3d_proj __retVal, sampler, coord;
-}
-
-
-vec4 textureCube(const samplerCube sampler, const vec3 coord)
-{
-   __asm vec4_tex_cube __retVal, sampler, coord;
-}
-
-
-
-vec4 shadow1D(const sampler1DShadow sampler, const vec3 coord)
-{
-   __asm vec4_tex_1d_shadow __retVal, sampler, coord;
-}
-
-vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord)
-{
-   // .s and .p will be divided by .q
-   __asm vec4_tex_1d_proj_shadow __retVal, sampler, coord;
-}
-
-vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord)
-{
-   __asm vec4_tex_2d_shadow __retVal, sampler, coord;
-}
-
-vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord)
-{
-   // .s, .t and .p will be divided by .q
-   __asm vec4_tex_2d_proj_shadow __retVal, sampler, coord;
-}
-
-
-//// GL_ARB_texture_rectangle:
-vec4 texture2DRect(const sampler2DRect sampler, const vec2 coord)
-{
-   __asm vec4_tex_rect __retVal, sampler, coord;
-}
-
-vec4 texture2DRectProj(const sampler2DRect sampler, const vec3 coord)
-{
-   // need to swizzle .y into .w
-   __asm vec4_tex_rect_proj __retVal, sampler, coord.xyzz;
-}
-
-vec4 texture2DRectProj(const sampler2DRect sampler, const vec4 coord)
-{
-   __asm vec4_tex_rect_proj __retVal, sampler, ccoord;
-}
-
-vec4 shadow2DRect(const sampler2DRectShadow sampler, const vec3 coord)
-{
-   __asm vec4_tex_rect_shadow __retVal, sampler, coord;
-}
-
-vec4 shadow2DRectProj(const sampler2DRectShadow sampler, const vec4 coord)
-{
-   __asm vec4_tex_rect_proj_shadow __retVal, sampler, coord;
-}
-
-
-
-//// GL_EXT_texture_array
-vec4 texture1DArray(const sampler1DArray sampler, const vec2 coord)
-{
-   __asm vec4_tex_1d_array __retVal, sampler, coord;
-}
-
-vec4 texture2DArray(const sampler2DArray sampler, const vec3 coord)
-{
-   __asm vec4_tex_2d_array __retVal, sampler, coord;
-}
-
-
-//
-// 8.9 Noise Functions
-//
-// AUTHOR: Stefan Gustavson (stegu@itn.liu.se), Nov 26, 2005
-//
-
-float noise1(const float x)
-{
-   __asm float_noise1 __retVal, x;
-}
-
-
-float noise1(const vec2 x)
-{
-    __asm float_noise2 __retVal, x;
-}
-
-float noise1(const vec3 x)
-{
-    __asm float_noise3 __retVal, x;
-}
-
-float noise1(const vec4 x)
-{
-    __asm float_noise4 __retVal, x;
-}
-
-vec2 noise2(const float x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + 19.34);
-}
-
-vec2 noise2(const vec2 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec2(19.34, 7.66));
-}
-
-vec2 noise2(const vec3 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
-}
-
-vec2 noise2(const vec4 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
-}
-
-vec3 noise3(const float x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + 19.34);
-   __retVal.z = noise1(x + 5.47);
-}
-
-vec3 noise3(const vec2 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec2(19.34, 7.66));
-   __retVal.z = noise1(x + vec2(5.47, 17.85));
-}
-
-vec3 noise3(const vec3 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
-   __retVal.z = noise1(x + vec3(5.47, 17.85, 11.04));
-}
-
-vec3 noise3(const vec4 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
-   __retVal.z = noise1(x + vec4(5.47, 17.85, 11.04, 13.19));
-}
-
-vec4 noise4(const float x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + 19.34);
-   __retVal.z = noise1(x + 5.47);
-   __retVal.w = noise1(x + 23.54);
-}
-
-vec4 noise4(const vec2 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec2 (19.34, 7.66));
-   __retVal.z = noise1(x + vec2 (5.47, 17.85));
-   __retVal.w = noise1(x + vec2 (23.54, 29.11));
-}
-
-vec4 noise4(const vec3 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
-   __retVal.z = noise1(x + vec3(5.47, 17.85, 11.04));
-   __retVal.w = noise1(x + vec3(23.54, 29.11, 31.91));
-}
-
-vec4 noise4(const vec4 x)
-{
-   __retVal.x = noise1(x);
-   __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
-   __retVal.z = noise1(x + vec4(5.47, 17.85, 11.04, 13.19));
-   __retVal.w = noise1(x + vec4(23.54, 29.11, 31.91, 37.48));
-}
diff --git a/src/mesa/slang/library/slang_core.gc b/src/mesa/slang/library/slang_core.gc
deleted file mode 100644 (file)
index 0a0d159..0000000
+++ /dev/null
@@ -1,2619 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-//
-// This file defines nearly all constructors and operators for built-in data
-// types, using extended language syntax. In general, compiler treats
-// constructors and operators as ordinary functions with some exceptions.
-// For example, the language does not allow functions to be called in
-// constant expressions - here the exception is made to allow it.
-//
-// Each implementation provides its own version of this file. Each
-// implementation can define the required set of operators and constructors
-// in its own fashion.
-//
-// The extended language syntax is only present when compiling this file.
-// It is implicitly included at the very beginning of the compiled shader,
-// so no built-in functions can be used.
-//
-// To communicate with the implementation, a special extended "__asm" keyword
-// is used, followed by an instruction name (any valid identifier), a
-// destination variable identifier and a list of zero or more source
-// variable identifiers.
-//
-// A variable identifier is a variable name declared earlier in the code
-// (as a function parameter, local or global variable).
-//
-// An instruction name designates an instruction that must be exported
-// by the implementation.  Each instruction receives data from source
-// variable identifiers and returns data in the destination variable
-// identifier.
-//
-// It is up to the implementation how to define a particular operator
-// or constructor. If it is expected to being used rarely, it can be
-// defined in terms of other operators and constructors,
-// for example:
-//
-// ivec2 __operator + (const ivec2 x, const ivec2 y) {
-//    return ivec2 (x[0] + y[0], x[1] + y[1]);
-// }
-//
-// If a particular operator or constructor is expected to be used very
-// often or is an atomic operation (that is, an operation that cannot be
-// expressed in terms of other operations or would create a dependency
-// cycle) it must be defined using one or more __asm constructs.
-//
-// Each implementation must define constructors for all scalar types
-// (bool, float, int).  There are 9 scalar-to-scalar constructors
-// (including identity constructors). However, since the language
-// introduces special constructors (like matrix constructor with a single
-// scalar value), implementations must also implement these cases.
-// The compiler provides the following algorithm when resolving a constructor:
-// - try to find a constructor with a prototype matching ours,
-// - if no constructor is found and this is a scalar-to-scalar constructor,
-//   raise an error,
-// - if a constructor is found, execute it and return,
-// - count the size of the constructor parameter list - if it is less than
-//   the size of our constructor's type, raise an error,
-// - for each parameter in the list do a recursive constructor matching for
-//   appropriate scalar fields in the constructed variable,
-//
-// Each implementation must also define a set of operators that deal with
-// built-in data types.
-// There are four kinds of operators:
-// 1) Operators that are implemented only by the compiler: "()" (function
-//    call), "," (sequence) and "?:" (selection).
-// 2) Operators that are implemented by the compiler by expressing it in
-//    terms of other operators:
-//    - "." (field selection) - translated to subscript access,
-//    - "&&" (logical and) - translated to "<left_expr> ? <right_expr> :
-//      false",
-//    - "||" (logical or) - translated to "<left_expr> ? true : <right_expr>",
-// 3) Operators that can be defined by the implementation and if the required
-//    prototype is not found, standard behaviour is used:
-//    - "==", "!=", "=" (equality, assignment) - compare or assign
-//      matching fields one-by-one;
-//      note that at least operators for scalar data types must be defined
-//      by the implementation to get it work,
-// 4) All other operators not mentioned above. If no required prototype is
-//    found, an error is raised. An implementation must follow the language
-//    specification to provide all valid operator prototypes.
-//
-
-
-
-//// Basic, scalar constructors/casts
-
-int __constructor(const float f)
-{
-   __asm vec4_to_ivec4 __retVal, f;
-}
-
-int __constructor(const bool b)
-{
-   __retVal = b;
-}
-
-int __constructor(const int i)
-{
-   __retVal = i;
-}
-
-bool __constructor(const int i)
-{
-   __asm vec4_sne __retVal, i, 0.0;
-}
-
-bool __constructor(const float f)
-{
-   __asm vec4_sne __retVal, f, 0.0;
-}
-
-bool __constructor(const bool b)
-{
-   __retVal = b;
-}
-
-float __constructor(const int i)
-{
-    __asm ivec4_to_vec4 __retVal, i;
-}
-
-float __constructor(const bool b)
-{
-    __asm ivec4_to_vec4 __retVal, b;
-}
-
-float __constructor(const float f)
-{
-   __retVal = f;
-}
-
-
-//// vec2 constructors
-
-vec2 __constructor(const float x, const float y)
-{
-   __retVal.x = x;
-   __retVal.y = y;
-}
-
-vec2 __constructor(const float f)
-{
-   __asm vec4_move __retVal.xy, f;
-}
-
-vec2 __constructor(const int i)
-{
-   __asm ivec4_to_vec4 __retVal.xy, i;
-}
-
-vec2 __constructor(const bool b)
-{
-   __asm ivec4_to_vec4 __retVal.xy, b;
-}
-
-vec2 __constructor(const bvec2 b)
-{
-//   __retVal = b;
-   __asm ivec4_to_vec4 __retVal.xy, b;
-}
-
-vec2 __constructor(const vec3 v)
-{
-   __asm vec4_move __retVal.xy, v.xy;
-}
-
-vec2 __constructor(const vec4 v)
-{
-   __asm vec4_move __retVal.xy, v.xy;
-}
-
-
-//// vec3 constructors
-
-vec3 __constructor(const float x, const float y, const float z)
-{
-   __retVal.x = x;
-   __retVal.y = y;
-   __retVal.z = z;
-}
-
-vec3 __constructor(const float f)
-{
-   // Note: this could be "__retVal.xyz = f" but that's an illegal assignment
-   __asm vec4_move __retVal.xyz, f;
-}
-
-vec3 __constructor(const int i)
-{
-   __asm ivec4_to_vec4 __retVal.xyz, i;
-}
-
-vec3 __constructor(const bool b)
-{
-   __asm ivec4_to_vec4 __retVal.xyz, b;
-}
-
-vec3 __constructor(const bvec3 b)
-{
-   __asm ivec4_to_vec4 __retVal.xyz, b;
-}
-
-vec3 __constructor(const vec4 v)
-{
-   __asm vec4_move __retVal.xyz, v;
-}
-
-
-//// vec4 constructors
-
-vec4 __constructor(const float x, const float y, const float z, const float w)
-{
-   __retVal.x = x;
-   __retVal.y = y;
-   __retVal.z = z;
-   __retVal.w = w;
-}
-
-vec4 __constructor(const float f)
-{
-   // Note: this could be "__retVal = f" but that's an illegal assignment
-   __asm vec4_move __retVal, f;
-}
-
-vec4 __constructor(const int i)
-{
-   __asm ivec4_to_vec4 __retVal, i;
-}
-
-vec4 __constructor(const bool b)
-{
-   __asm ivec4_to_vec4 __retVal, b;
-}
-
-vec4 __constructor(const bvec4 b)
-{
-   __asm ivec4_to_vec4 __retVal, b;
-}
-
-vec4 __constructor(const ivec4 i)
-{
-   __asm ivec4_to_vec4 __retVal, i;
-}
-
-vec4 __constructor(const vec3 v3, const float f)
-{
-   // XXX this constructor shouldn't be needed anymore
-   __retVal.xyz = v3;
-   __retVal.w = f;
-}
-
-vec4 __constructor(const vec2 v2, const float f1, const float f2)
-{
-   // XXX this constructor shouldn't be needed anymore
-   __retVal.xy = v2;
-   __retVal.z = f1;
-   __retVal.w = f2;
-}
-
-
-//// ivec2 constructors
-
-ivec2 __constructor(const int i, const int j)
-{
-   __retVal.x = i;
-   __retVal.y = j;
-}
-
-ivec2 __constructor(const int i)
-{
-   __asm vec4_move __retVal.xy, i;
-}
-
-ivec2 __constructor(const float f)
-{
-   __asm vec4_to_ivec4 __retVal.xy, f;
-}
-
-ivec2 __constructor(const bool b)
-{
-   __asm vec4_to_ivec4 __retVal.xy, b;
-}
-
-
-//// ivec3 constructors
-
-ivec3 __constructor(const int i, const int j, const int k)
-{
-   __retVal.x = i;
-   __retVal.y = j;
-   __retVal.z = k;
-}
-
-ivec3 __constructor(const int i)
-{
-   __asm vec4_move __retVal.xyz, i;
-}
-
-ivec3 __constructor(const float f)
-{
-   __asm vec4_to_ivec4 __retVal.xyz, f;
-}
-
-ivec3 __constructor(const bool b)
-{
-   __asm vec4_move __retVal.xyz, b;
-}
-
-
-//// ivec4 constructors
-
-ivec4 __constructor(const int x, const int y, const int z, const int w)
-{
-   __retVal.x = x;
-   __retVal.y = y;
-   __retVal.z = z;
-   __retVal.w = w;
-}
-
-ivec4 __constructor(const int i)
-{
-   __asm vec4_move __retVal, i;
-}
-
-ivec4 __constructor(const float f)
-{
-   __asm vec4_to_ivec4 __retVal, f;
-}
-
-ivec4 __constructor(const bool b)
-{
-   __asm vec4_to_ivec4 __retVal, b;
-}
-
-
-//// bvec2 constructors
-
-bvec2 __constructor(const bool b1, const bool b2)
-{
-   __retVal.x = b1;
-   __retVal.y = b2;
-}
-
-bvec2 __constructor(const int i1, const int i2)
-{
-   __asm vec4_sne __retVal.x, i1, 0.0;
-   __asm vec4_sne __retVal.y, i2, 0.0;
-}
-
-
-bvec2 __constructor(const bool b)
-{
-   __asm vec4_move __retVal.xy, b;
-}
-
-bvec2 __constructor(const float f)
-{
-   __asm vec4_sne __retVal.xy, f, 0.0;
-}
-
-bvec2 __constructor(const int i)
-{
-   __asm vec4_sne __retVal.xy, i, 0.0;
-}
-
-bvec2 __constructor(const vec2 v)
-{
-   __asm vec4_sne __retVal.xy, v, 0.0;
-}
-
-bvec2 __constructor(const ivec2 v)
-{
-   __asm vec4_sne __retVal.xy, v, 0.0;
-}
-
-
-
-//// bvec3 constructors
-
-bvec3 __constructor(const bool b1, const bool b2, const bool b3)
-{
-   __retVal.x = b1;
-   __retVal.y = b2;
-   __retVal.z = b3;
-}
-
-bvec3 __constructor(const float f1, const float f2, const float f3)
-{
-   __asm vec4_sne __retVal.x, f1, 0.0;
-   __asm vec4_sne __retVal.y, f2, 0.0;
-   __asm vec4_sne __retVal.z, f3, 0.0;
-}
-
-bvec3 __constructor(const bool b)
-{
-   __asm vec4_move __retVal.xyz, b;
-}
-
-bvec3 __constructor(const float f)
-{
-   __asm vec4_sne __retVal.xyz, f, 0.0;
-}
-
-bvec3 __constructor(const int i)
-{
-   __asm vec4_sne __retVal.xyz, i, 0.0;
-}
-
-bvec3 __constructor(const vec3 v)
-{
-   __asm vec4_sne __retVal.xyz, v, 0.0;
-}
-
-bvec3 __constructor(const ivec3 v)
-{
-   __asm vec4_sne __retVal.xyz, v, 0.0;
-}
-
-
-
-//// bvec4 constructors
-
-bvec4 __constructor(const bool b1, const bool b2, const bool b3, const bool b4)
-{
-   __retVal.x = b1;
-   __retVal.y = b2;
-   __retVal.z = b3;
-   __retVal.w = b4;
-}
-
-bvec4 __constructor(const float f1, const float f2, const float f3, const float f4)
-{
-   const float zero = 0.0;
-   __asm vec4_sne __retVal.x, f1, zero;   
-   __asm vec4_sne __retVal.y, f2, zero;   
-   __asm vec4_sne __retVal.z, f3, zero;   
-   __asm vec4_sne __retVal.w, f4, zero;   
-}
-
-bvec4 __constructor(const bool b)
-{
-   __asm vec4_move __retVal.xyzw, b;
-}
-
-bvec4 __constructor(const float f)
-{
-   __asm vec4_sne __retVal.xyzw, f, 0.0;
-}
-
-bvec4 __constructor(const int i)
-{
-   __asm vec4_sne __retVal.xyzw, i, 0.0;
-}
-
-bvec4 __constructor(const vec4 v)
-{
-   __asm vec4_sne __retVal.xyzw, v, 0.0;
-}
-
-bvec4 __constructor(const ivec4 v)
-{
-   __asm vec4_sne __retVal.xyzw, v, 0.0;
-}
-
-
-
-//// mat2 constructors
-
-mat2 __constructor(const float m00, const float m10,
-                   const float m01, const float m11)
-{
-   __retVal[0].x = m00;
-   __retVal[0].y = m10;
-   __retVal[1].x = m01;
-   __retVal[1].y = m11;
-}
-
-mat2 __constructor(const float f)
-{
-   __retVal[0].x = f;
-   __retVal[0].y = 0.0;
-   __retVal[1].x = 0.0;
-   __retVal[1].y = f;
-}
-
-mat2 __constructor(const int i)
-{
-   return mat2(float(i));
-}
-
-mat2 __constructor(const bool b)
-{
-   return mat2(float(b));
-}
-
-mat2 __constructor(const vec2 c0, const vec2 c1)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-}
-
-
-//// mat3 constructors
-
-mat3 __constructor(const float m00, const float m10, const float m20,
-                   const float m01, const float m11, const float m21,
-                   const float m02, const float m12, const float m22)
-{
-   __retVal[0].x = m00;
-   __retVal[0].y = m10;
-   __retVal[0].z = m20;
-   __retVal[1].x = m01;
-   __retVal[1].y = m11;
-   __retVal[1].z = m21;
-   __retVal[2].x = m02;
-   __retVal[2].y = m12;
-   __retVal[2].z = m22;
-}
-
-mat3 __constructor(const float f)
-{
-   vec2 v = vec2(f, 0.0);
-   __retVal[0] = v.xyy;
-   __retVal[1] = v.yxy;
-   __retVal[2] = v.yyx;
-}
-
-mat3 __constructor(const int i)
-{
-   return mat3(float(i));
-}
-
-mat3 __constructor(const bool b)
-{
-   return mat3(float(b));
-}
-
-mat3 __constructor(const vec3 c0, const vec3 c1, const vec3 c2)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-   __retVal[2] = c2;
-}
-
-
-//// mat4 constructors
-
-mat4 __constructor(const float m00, const float m10, const float m20, const float m30,
-                   const float m01, const float m11, const float m21, const float m31,
-                   const float m02, const float m12, const float m22, const float m32,
-                   const float m03, const float m13, const float m23, const float m33)
-{
-   __retVal[0].x = m00;
-   __retVal[0].y = m10;
-   __retVal[0].z = m20;
-   __retVal[0].w = m30;
-   __retVal[1].x = m01;
-   __retVal[1].y = m11;
-   __retVal[1].z = m21;
-   __retVal[1].w = m31;
-   __retVal[2].x = m02;
-   __retVal[2].y = m12;
-   __retVal[2].z = m22;
-   __retVal[2].w = m32;
-   __retVal[3].x = m03;
-   __retVal[3].y = m13;
-   __retVal[3].z = m23;
-   __retVal[3].w = m33;
-}
-
-
-mat4 __constructor(const float f)
-{
-   vec2 v = vec2(f, 0.0);
-   __retVal[0] = v.xyyy;
-   __retVal[1] = v.yxyy;
-   __retVal[2] = v.yyxy;
-   __retVal[3] = v.yyyx;
-}
-
-mat4 __constructor(const int i)
-{
-   return mat4(float(i));
-}
-
-mat4 __constructor(const bool b)
-{
-   return mat4(float(b));
-}
-
-mat4 __constructor(const vec4 c0, const vec4 c1, const vec4 c2, const vec4 c3)
-{
-   __retVal[0] = c0;
-   __retVal[1] = c1;
-   __retVal[2] = c2;
-   __retVal[3] = c3;
-}
-
-
-
-//// Basic int operators
-
-int __operator + (const int a, const int b)
-{
-   __asm vec4_add __retVal, a, b;
-}
-
-int __operator - (const int a, const int b)
-{
-   __asm vec4_subtract __retVal, a, b;
-}
-
-int __operator * (const int a, const int b)
-{
-   __asm vec4_multiply __retVal, a, b;
-}
-
-int __operator / (const int a, const int b)
-{
-   float bInv, x;
-   __asm float_rcp bInv, b;
-   __asm vec4_multiply x, a, bInv;
-   __asm vec4_to_ivec4 __retVal, x;
-}
-
-
-//// Basic ivec2 operators
-
-ivec2 __operator + (const ivec2 a, const ivec2 b)
-{
-   __asm vec4_add __retVal, a, b;
-}
-
-ivec2 __operator - (const ivec2 a, const ivec2 b)
-{
-   __asm vec4_subtract __retVal, a, b;
-}
-
-ivec2 __operator * (const ivec2 a, const ivec2 b)
-{
-   __asm vec4_multiply __retVal, a, b;
-}
-
-ivec2 __operator / (const ivec2 a, const ivec2 b)
-{
-   vec2 bInv, x;
-   __asm float_rcp bInv.x, b.x;
-   __asm float_rcp bInv.y, b.y;
-   __asm vec4_multiply x, a, bInv;
-   __asm vec4_to_ivec4 __retVal, x;
-}
-
-
-//// Basic ivec3 operators
-
-ivec3 __operator + (const ivec3 a, const ivec3 b)
-{
-   __asm vec4_add __retVal, a, b;
-}
-
-ivec3 __operator - (const ivec3 a, const ivec3 b)
-{
-   __asm vec4_subtract __retVal, a, b;
-}
-
-ivec3 __operator * (const ivec3 a, const ivec3 b)
-{
-   __asm vec4_multiply __retVal, a, b;
-}
-
-ivec3 __operator / (const ivec3 a, const ivec3 b)
-{
-   vec3 bInv, x;
-   __asm float_rcp bInv.x, b.x;
-   __asm float_rcp bInv.y, b.y;
-   __asm float_rcp bInv.z, b.z;
-   __asm vec4_multiply x, a, bInv;
-   __asm vec4_to_ivec4 __retVal, x;
-}
-
-
-//// Basic ivec4 operators
-
-ivec4 __operator + (const ivec4 a, const ivec4 b)
-{
-   __asm vec4_add __retVal, a, b;
-}
-
-ivec4 __operator - (const ivec4 a, const ivec4 b)
-{
-   __asm vec4_subtract __retVal, a, b;
-}
-
-ivec4 __operator * (const ivec4 a, const ivec4 b)
-{
-   __asm vec4_multiply __retVal, a, b;
-}
-
-ivec4 __operator / (const ivec4 a, const ivec4 b)
-{
-   vec4 bInv, x;
-   __asm float_rcp bInv.x, b.x;
-   __asm float_rcp bInv.y, b.y;
-   __asm float_rcp bInv.z, b.z;
-   __asm float_rcp bInv.w, b.w;
-   __asm vec4_multiply x, a, bInv;
-   __asm vec4_to_ivec4 __retVal, x;
-}
-
-
-//// Basic float operators
-
-float __operator + (const float a, const float b)
-{
-   __asm vec4_add __retVal, a, b;
-}
-
-float __operator - (const float a, const float b)
-{
-   __asm vec4_subtract __retVal, a, b;
-}
-
-float __operator * (const float a, const float b)
-{
-    __asm vec4_multiply __retVal, a, b;
-}
-
-float __operator / (const float a, const float b)
-{
-   float bInv;
-   __asm float_rcp bInv.x, b;
-   __asm vec4_multiply __retVal, a, bInv;
-}
-
-
-//// Basic vec2 operators
-
-vec2 __operator + (const vec2 v, const vec2 u)
-{
-   __asm vec4_add __retVal.xy, v, u;
-}
-
-vec2 __operator - (const vec2 v, const vec2 u)
-{
-    __asm vec4_subtract __retVal.xy, v, u;
-}
-
-vec2 __operator * (const vec2 v, const vec2 u)
-{
-    __asm vec4_multiply __retVal.xy, v, u;
-}
-
-vec2 __operator / (const vec2 v, const vec2 u)
-{
-   vec2 w; // = 1 / u
-   __asm float_rcp w.x, u.x;
-   __asm float_rcp w.y, u.y;
-   __asm vec4_multiply __retVal.xy, v, w;
-}
-
-
-//// Basic vec3 operators
-
-vec3 __operator + (const vec3 v, const vec3 u)
-{
-   __asm vec4_add __retVal.xyz, v, u;
-}
-
-vec3 __operator - (const vec3 v, const vec3 u)
-{
-    __asm vec4_subtract __retVal.xyz, v, u;
-}
-
-vec3 __operator * (const vec3 v, const vec3 u)
-{
-    __asm vec4_multiply __retVal.xyz, v, u;
-}
-
-vec3 __operator / (const vec3 v, const vec3 u)
-{
-   vec3 w; // = 1 / u
-   __asm float_rcp w.x, u.x;
-   __asm float_rcp w.y, u.y;
-   __asm float_rcp w.z, u.z;
-   __asm vec4_multiply __retVal.xyz, v, w;
-}
-
-
-//// Basic vec4 operators
-
-vec4 __operator + (const vec4 v, const vec4 u)
-{
-   __asm vec4_add __retVal, v, u;
-}
-
-vec4 __operator - (const vec4 v, const vec4 u)
-{
-    __asm vec4_subtract __retVal, v, u;
-}
-
-vec4 __operator * (const vec4 v, const vec4 u)
-{
-    __asm vec4_multiply __retVal, v, u;
-}
-
-vec4 __operator / (const vec4 v, const vec4 u)
-{
-   vec4 w; // = 1 / u
-   __asm float_rcp w.x, u.x;
-   __asm float_rcp w.y, u.y;
-   __asm float_rcp w.z, u.z;
-   __asm float_rcp w.w, u.w;
-   __asm vec4_multiply __retVal, v, w;
-}
-
-
-
-
-//// Basic vec2/float operators
-
-vec2 __operator + (const float a, const vec2 u)
-{
-   __asm vec4_add __retVal.xy, a, u.xy;
-}
-
-vec2 __operator + (const vec2 v, const float b)
-{
-   __asm vec4_add __retVal.xy, v.xy, b;
-}
-
-vec2 __operator - (const float a, const vec2 u)
-{
-   __asm vec4_subtract __retVal.xy, a, u.xy;
-}
-
-vec2 __operator - (const vec2 v, const float b)
-{
-   __asm vec4_subtract __retVal.xy, v.xy, b;
-}
-
-vec2 __operator * (const float a, const vec2 u)
-{
-   __asm vec4_multiply __retVal.xy, a, u.xy;
-}
-
-vec2 __operator * (const vec2 v, const float b)
-{
-   __asm vec4_multiply __retVal.xy, v.xy, b;
-}
-
-vec2 __operator / (const float a, const vec2 u)
-{
-   vec2 invU;
-   __asm float_rcp invU.x, u.x;
-   __asm float_rcp invU.y, u.y;
-   __asm vec4_multiply __retVal.xy, a, invU.xy;
-}
-
-vec2 __operator / (const vec2 v, const float b)
-{
-   float invB;
-   __asm float_rcp invB, b;
-   __asm vec4_multiply __retVal.xy, v.xy, invB;
-}
-
-
-//// Basic vec3/float operators
-
-vec3 __operator + (const float a, const vec3 u)
-{
-   __asm vec4_add __retVal.xyz, a, u.xyz;
-}
-
-vec3 __operator + (const vec3 v, const float b)
-{
-   __asm vec4_add __retVal.xyz, v.xyz, b;
-}
-
-vec3 __operator - (const float a, const vec3 u)
-{
-   __asm vec4_subtract __retVal.xyz, a, u.xyz;
-}
-
-vec3 __operator - (const vec3 v, const float b)
-{
-   __asm vec4_subtract __retVal.xyz, v.xyz, b;
-}
-
-vec3 __operator * (const float a, const vec3 u)
-{
-   __asm vec4_multiply __retVal.xyz, a, u.xyz;
-}
-
-vec3 __operator * (const vec3 v, const float b)
-{
-   __asm vec4_multiply __retVal.xyz, v.xyz, b;
-}
-
-vec3 __operator / (const float a, const vec3 u)
-{
-   vec3 invU;
-   __asm float_rcp invU.x, u.x;
-   __asm float_rcp invU.y, u.y;
-   __asm float_rcp invU.z, u.z;
-   __asm vec4_multiply __retVal.xyz, a, invU.xyz;
-}
-
-vec3 __operator / (const vec3 v, const float b)
-{
-   float invB;
-   __asm float_rcp invB, b;
-   __asm vec4_multiply __retVal.xyz, v.xyz, invB;
-}
-
-
-//// Basic vec4/float operators
-
-vec4 __operator + (const float a, const vec4 u)
-{
-   __asm vec4_add __retVal, a, u;
-}
-
-vec4 __operator + (const vec4 v, const float b)
-{
-   __asm vec4_add __retVal, v, b;
-}
-
-vec4 __operator - (const float a, const vec4 u)
-{
-   __asm vec4_subtract __retVal, a, u;
-}
-
-vec4 __operator - (const vec4 v, const float b)
-{
-   __asm vec4_subtract __retVal, v, b;
-}
-
-vec4 __operator * (const float a, const vec4 u)
-{
-   __asm vec4_multiply __retVal, a, u;
-}
-
-vec4 __operator * (const vec4 v, const float b)
-{
-   __asm vec4_multiply __retVal, v, b;
-}
-
-vec4 __operator / (const float a, const vec4 u)
-{
-   vec4 invU;
-   __asm float_rcp invU.x, u.x;
-   __asm float_rcp invU.y, u.y;
-   __asm float_rcp invU.z, u.z;
-   __asm float_rcp invU.w, u.w;
-   __asm vec4_multiply __retVal, a, invU;
-}
-
-vec4 __operator / (const vec4 v, const float b)
-{
-   float invB;
-   __asm float_rcp invB, b;
-   __asm vec4_multiply __retVal, v, invB;
-}
-
-
-
-//// Basic ivec2/int operators
-
-ivec2 __operator + (const int a, const ivec2 u)
-{
-   __retVal = ivec2(a) + u;
-}
-
-ivec2 __operator + (const ivec2 v, const int b)
-{
-   __retVal = v + ivec2(b);
-}
-
-ivec2 __operator - (const int a, const ivec2 u)
-{
-   __retVal = ivec2(a) - u;
-}
-
-ivec2 __operator - (const ivec2 v, const int b)
-{
-   __retVal = v - ivec2(b);
-}
-
-ivec2 __operator * (const int a, const ivec2 u)
-{
-   __retVal = ivec2(a) * u;
-}
-
-ivec2 __operator * (const ivec2 v, const int b)
-{
-   __retVal = v * ivec2(b);
-}
-
-ivec2 __operator / (const int a, const ivec2 u)
-{
-   __retVal = ivec2(a) / u;
-}
-
-ivec2 __operator / (const ivec2 v, const int b)
-{
-   __retVal = v / ivec2(b);
-}
-
-
-//// Basic ivec3/int operators
-
-ivec3 __operator + (const int a, const ivec3 u)
-{
-   __retVal = ivec3(a) + u;
-}
-
-ivec3 __operator + (const ivec3 v, const int b)
-{
-   __retVal = v + ivec3(b);
-}
-
-ivec3 __operator - (const int a, const ivec3 u)
-{
-   __retVal = ivec3(a) - u;
-}
-
-ivec3 __operator - (const ivec3 v, const int b)
-{
-   __retVal = v - ivec3(b);
-}
-
-ivec3 __operator * (const int a, const ivec3 u)
-{
-   __retVal = ivec3(a) * u;
-}
-
-ivec3 __operator * (const ivec3 v, const int b)
-{
-   __retVal = v * ivec3(b);
-}
-
-ivec3 __operator / (const int a, const ivec3 u)
-{
-   __retVal = ivec3(a) / u;
-}
-
-ivec3 __operator / (const ivec3 v, const int b)
-{
-   __retVal = v / ivec3(b);
-}
-
-
-//// Basic ivec4/int operators
-
-ivec4 __operator + (const int a, const ivec4 u)
-{
-   __retVal = ivec4(a) + u;
-}
-
-ivec4 __operator + (const ivec4 v, const int b)
-{
-   __retVal = v + ivec4(b);
-}
-
-ivec4 __operator - (const int a, const ivec4 u)
-{
-   __retVal = ivec4(a) - u;
-}
-
-ivec4 __operator - (const ivec4 v, const int b)
-{
-   __retVal = v - ivec4(b);
-}
-
-ivec4 __operator * (const int a, const ivec4 u)
-{
-   __retVal = ivec4(a) * u;
-}
-
-ivec4 __operator * (const ivec4 v, const int b)
-{
-   __retVal = v * ivec4(b);
-}
-
-ivec4 __operator / (const int a, const ivec4 u)
-{
-   __retVal = ivec4(a) / u;
-}
-
-ivec4 __operator / (const ivec4 v, const int b)
-{
-   __retVal = v / ivec4(b);
-}
-
-
-
-
-//// Unary negation operator
-
-int __operator - (const int a)
-{
-   __asm vec4_negate __retVal.x, a;
-}
-
-ivec2 __operator - (const ivec2 v)
-{
-   __asm vec4_negate __retVal, v;
-}
-
-ivec3 __operator - (const ivec3 v)
-{
-   __asm vec4_negate __retVal, v;
-}
-
-ivec4 __operator - (const ivec4 v)
-{
-   __asm vec4_negate __retVal, v;
-}
-
-float __operator - (const float a)
-{
-   __asm vec4_negate __retVal.x, a;
-}
-
-vec2 __operator - (const vec2 v)
-{
-   __asm vec4_negate __retVal.xy, v.xy;
-}
-
-vec3 __operator - (const vec3 v)
-{
-   __asm vec4_negate __retVal.xyz, v.xyz;
-}
-
-vec4 __operator - (const vec4 v)
-{
-   __asm vec4_negate __retVal, v;
-}
-
-mat2 __operator - (const mat2 m)
-{
-   __retVal[0] = -m[0];
-   __retVal[1] = -m[1];
-}
-
-mat3 __operator - (const mat3 m)
-{
-   __retVal[0] = -m[0];
-   __retVal[1] = -m[1];
-   __retVal[2] = -m[2];
-}
-
-mat4 __operator - (const mat4 m)
-{
-   __retVal[0] = -m[0];
-   __retVal[1] = -m[1];
-   __retVal[2] = -m[2];
-   __retVal[3] = -m[3];
-}
-
-
-
-//// dot product
-
-float dot(const float a, const float b)
-{
-   __retVal = a * b;
-}
-
-float dot(const vec2 a, const vec2 b)
-{
-   __retVal = a.x * b.x + a.y * b.y;
-}
-
-float dot(const vec3 a, const vec3 b)
-{
-    __asm vec3_dot __retVal, a, b;
-}
-
-float dot(const vec4 a, const vec4 b)
-{
-    __asm vec4_dot __retVal, a, b;
-}
-
-
-
-//// int assignment operators
-
-int __operator += (inout int a, const int b)
-{
-   a = a + b;
-   return a;
-}
-
-int __operator -= (inout int a, const int b)
-{
-   a = a - b;
-   return a;
-}
-
-int __operator *= (inout int a, const int b)
-{
-   a = a * b;
-   return a;
-}
-
-int __operator /= (inout int a, const int b)
-{
-   a = a / b;
-   return a;
-}
-
-
-//// ivec2 assignment operators
-
-ivec2 __operator += (inout ivec2 v, const ivec2 u)
-{
-   v = v + u;
-   return v;
-}
-
-ivec2 __operator -= (inout ivec2 v, const ivec2 u)
-{
-   v = v - u;
-   return v;
-}
-
-ivec2 __operator *= (inout ivec2 v, const ivec2 u)
-{
-   v = v * u;
-   return v;
-}
-
-ivec2 __operator /= (inout ivec2 v, const ivec2 u)
-{
-   v = v / u;
-   return v;
-}
-
-
-//// ivec3 assignment operators
-
-ivec3 __operator += (inout ivec3 v, const ivec3 u)
-{
-   v = v + u;
-   return v;
-}
-
-ivec3 __operator -= (inout ivec3 v, const ivec3 u)
-{
-   v = v - u;
-   return v;
-}
-
-ivec3 __operator *= (inout ivec3 v, const ivec3 u)
-{
-   v = v * u;
-   return v;
-}
-
-ivec3 __operator /= (inout ivec3 v, const ivec3 u)
-{
-   v = v / u;
-   return v;
-}
-
-
-//// ivec4 assignment operators
-
-ivec4 __operator += (inout ivec4 v, const ivec4 u)
-{
-   v = v + u;
-   return v;
-}
-
-ivec4 __operator -= (inout ivec4 v, const ivec4 u)
-{
-   v = v - u;
-   return v;
-}
-
-ivec4 __operator *= (inout ivec4 v, const ivec4 u)
-{
-   v = v * u;
-   return v;
-}
-
-ivec4 __operator /= (inout ivec4 v, const ivec4 u)
-{
-   v = v / u;
-   return v;
-}
-
-
-//// float assignment operators
-
-float __operator += (inout float a, const float b)
-{
-   a = a + b;
-   return a;
-}
-
-float __operator -= (inout float a, const float b)
-{
-   a = a - b;
-   return a;
-}
-
-float __operator *= (inout float a, const float b)
-{
-   a = a * b;
-   return a;
-}
-
-float __operator /= (inout float a, const float b)
-{
-   a = a / b;
-   return a;
-}
-
-
-//// vec2 assignment operators
-
-vec2 __operator += (inout vec2 v, const vec2 u)
-{
-   v = v + u;
-   return v;
-}
-
-vec2 __operator -= (inout vec2 v, const vec2 u)
-{
-   v = v - u;
-   return v;
-}
-
-vec2 __operator *= (inout vec2 v, const vec2 u)
-{
-   v = v * u;
-   return v;
-}
-
-vec2 __operator /= (inout vec2 v, const vec2 u)
-{
-   v = v / u;
-   return v;
-}
-
-
-//// vec3 assignment operators
-
-vec3 __operator += (inout vec3 v, const vec3 u)
-{
-   v = v + u;
-   return v;
-}
-
-vec3 __operator -= (inout vec3 v, const vec3 u)
-{
-   v = v - u;
-   return v;
-}
-
-vec3 __operator *= (inout vec3 v, const vec3 u)
-{
-   v = v * u;
-   return v;
-}
-
-vec3 __operator /= (inout vec3 v, const vec3 u)
-{
-   v = v / u;
-   return v;
-}
-
-
-//// vec4 assignment operators
-
-vec4 __operator += (inout vec4 v, const vec4 u)
-{
-   v = v + u;
-   return v;
-}
-
-vec4 __operator -= (inout vec4 v, const vec4 u)
-{
-   v = v - u;
-   return v;
-}
-
-vec4 __operator *= (inout vec4 v, const vec4 u)
-{
-   v = v * u;
-   return v;
-}
-
-vec4 __operator /= (inout vec4 v, const vec4 u)
-{
-   v = v / u;
-   return v;
-}
-
-
-
-//// ivec2/int assignment operators
-
-ivec2 __operator += (inout ivec2 v, const int a)
-{
-   v = v + ivec2(a);
-   return v;
-}
-
-ivec2 __operator -= (inout ivec2 v, const int a)
-{
-   v = v - ivec2(a);
-   return v;
-}
-
-ivec2 __operator *= (inout ivec2 v, const int a)
-{
-   v = v * ivec2(a);
-   return v;
-}
-
-ivec2 __operator /= (inout ivec2 v, const int a)
-{
-   v = v / ivec2(a);
-   return v;
-}
-
-
-//// ivec3/int assignment operators
-
-ivec3 __operator += (inout ivec3 v, const int a)
-{
-   v = v + ivec3(a);
-   return v;
-}
-
-ivec3 __operator -= (inout ivec3 v, const int a)
-{
-   v = v - ivec3(a);
-   return v;
-}
-
-ivec3 __operator *= (inout ivec3 v, const int a)
-{
-   v = v * ivec3(a);
-   return v;
-}
-
-ivec4 __operator /= (inout ivec3 v, const int a)
-{
-   v = v / ivec3(a);
-   return v;
-}
-
-
-//// ivec4/int assignment operators
-
-ivec4 __operator += (inout ivec4 v, const int a)
-{
-   v = v + ivec4(a);
-   return v;
-}
-
-ivec4 __operator -= (inout ivec4 v, const int a)
-{
-   v = v - ivec4(a);
-   return v;
-}
-
-ivec4 __operator *= (inout ivec4 v, const int a)
-{
-   v = v * ivec4(a);
-   return v;
-}
-
-ivec4 __operator /= (inout ivec4 v, const int a)
-{
-   v = v / ivec4(a);
-   return v;
-}
-
-
-
-//// vec2/float assignment operators
-
-vec2 __operator += (inout vec2 v, const float a)
-{
-   v = v + vec2(a);
-   return v;
-}
-
-vec2 __operator -= (inout vec2 v, const float a)
-{
-   v = v - vec2(a);
-   return v;
-}
-
-vec2 __operator *= (inout vec2 v, const float a)
-{
-   v = v * vec2(a);
-   return v;
-}
-
-vec2 __operator /= (inout vec2 v, const float a)
-{
-   v = v / vec2(a);
-   return v;
-}
-
-
-//// vec3/float assignment operators
-
-vec3 __operator += (inout vec3 v, const float a)
-{
-   v = v + vec3(a);
-   return v;
-}
-
-vec3 __operator -= (inout vec3 v, const float a)
-{
-   v = v - vec3(a);
-   return v;
-}
-
-vec3 __operator *= (inout vec3 v, const float a)
-{
-   v = v * vec3(a);
-   return v;
-}
-
-vec3 __operator /= (inout vec3 v, const float a)
-{
-   v = v / vec3(a);
-   return v;
-}
-
-
-//// vec4/float assignment operators
-
-vec4 __operator += (inout vec4 v, const float a)
-{
-   v = v + vec4(a);
-   return v;
-}
-
-vec4 __operator -= (inout vec4 v, const float a)
-{
-   v = v - vec4(a);
-   return v;
-}
-
-vec4 __operator *= (inout vec4 v, const float a)
-{
-   v = v * vec4(a);
-   return v;
-}
-
-vec4 __operator /= (inout vec4 v, const float a)
-{
-   v = v / vec4(a);
-   return v;
-}
-
-
-
-
-
-//// Basic mat2 operations
-
-mat2 __operator + (const mat2 m, const mat2 n)
-{
-   __retVal[0] = m[0] + n[0];
-   __retVal[1] = m[1] + n[1];
-}
-
-mat2 __operator - (const mat2 m, const mat2 n)
-{
-   __retVal[0] = m[0] - n[0];
-   __retVal[1] = m[1] - n[1];
-}
-
-mat2 __operator * (const mat2 m, const mat2 n)
-{
-   __retVal[0] = m[0] * n[0].xx + m[1] * n[0].yy;
-   __retVal[1] = m[0] * n[1].xx + m[1] * n[1].yy;
-}
-
-mat2 __operator / (const mat2 m, const mat2 n)
-{
-   __retVal[0] = m[0] / n[0];
-   __retVal[1] = m[1] / n[1];
-}
-
-
-//// Basic mat3 operations
-
-mat3 __operator + (const mat3 m, const mat3 n)
-{
-   __retVal[0] = m[0] + n[0];
-   __retVal[1] = m[1] + n[1];
-   __retVal[2] = m[2] + n[2];
-}
-
-mat3 __operator - (const mat3 m, const mat3 n)
-{
-   __retVal[0] = m[0] - n[0];
-   __retVal[1] = m[1] - n[1];
-   __retVal[2] = m[2] - n[2];
-}
-
-mat3 __operator * (const mat3 m, const mat3 n)
-{
-   __retVal[0] = m[0] * n[0].xxx + m[1] * n[0].yyy + m[2] * n[0].zzz;
-   __retVal[1] = m[0] * n[1].xxx + m[1] * n[1].yyy + m[2] * n[1].zzz;
-   __retVal[2] = m[0] * n[2].xxx + m[1] * n[2].yyy + m[2] * n[2].zzz;
-}
-
-mat3 __operator / (const mat3 m, const mat3 n)
-{
-    __retVal[0] = m[0] / n[0];
-    __retVal[1] = m[1] / n[1];
-    __retVal[2] = m[2] / n[2];
-}
-
-
-//// Basic mat4 operations
-
-mat4 __operator + (const mat4 m, const mat4 n)
-{
-   __retVal[0] = m[0] + n[0];
-   __retVal[1] = m[1] + n[1];
-   __retVal[2] = m[2] + n[2];
-   __retVal[3] = m[3] + n[3];
-}
-
-mat4 __operator - (const mat4 m, const mat4 n)
-{
-   __retVal[0] = m[0] - n[0];
-   __retVal[1] = m[1] - n[1];
-   __retVal[2] = m[2] - n[2];
-   __retVal[3] = m[3] - n[3];
-}
-
-mat4 __operator * (const mat4 m, const mat4 n)
-{
-   __retVal[0] = m[0] * n[0].xxxx + m[1] * n[0].yyyy + m[2] * n[0].zzzz + m[3] * n[0].wwww;
-   __retVal[1] = m[0] * n[1].xxxx + m[1] * n[1].yyyy + m[2] * n[1].zzzz + m[3] * n[1].wwww;
-   __retVal[2] = m[0] * n[2].xxxx + m[1] * n[2].yyyy + m[2] * n[2].zzzz + m[3] * n[2].wwww;
-   __retVal[3] = m[0] * n[3].xxxx + m[1] * n[3].yyyy + m[2] * n[3].zzzz + m[3] * n[3].wwww;
-}
-
-mat4 __operator / (const mat4 m, const mat4 n)
-{
-    __retVal[0] = m[0] / n[0];
-    __retVal[1] = m[1] / n[1];
-    __retVal[2] = m[2] / n[2];
-    __retVal[3] = m[3] / n[3];
-}
-
-
-//// mat2/float operations
-
-mat2 __operator + (const float a, const mat2 n)
-{
-   __retVal[0] = a + n[0];
-   __retVal[1] = a + n[1];
-}
-
-mat2 __operator + (const mat2 m, const float b)
-{
-   __retVal[0] = m[0] + b;
-   __retVal[1] = m[1] + b;
-}
-
-mat2 __operator - (const float a, const mat2 n)
-{
-   __retVal[0] = a - n[0];
-   __retVal[1] = a - n[1];
-}
-
-mat2 __operator - (const mat2 m, const float b)
-{
-   __retVal[0] = m[0] - b;
-   __retVal[1] = m[1] - b;
-}
-
-mat2 __operator * (const float a, const mat2 n)
-{
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-}
-
-mat2 __operator * (const mat2 m, const float b)
-{
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-}
-
-mat2 __operator / (const float a, const mat2 n)
-{
-   __retVal[0] = a / n[0];
-   __retVal[1] = a / n[1];
-}
-
-mat2 __operator / (const mat2 m, const float b)
-{
-   __retVal[0] = m[0] / b;
-   __retVal[1] = m[1] / b;
-}
-
-
-//// mat3/float operations
-
-mat3 __operator + (const float a, const mat3 n)
-{
-   __retVal[0] = a + n[0];
-   __retVal[1] = a + n[1];
-   __retVal[2] = a + n[2];
-}
-
-mat3 __operator + (const mat3 m, const float b)
-{
-   __retVal[0] = m[0] + b;
-   __retVal[1] = m[1] + b;
-   __retVal[2] = m[2] + b;
-}
-
-mat3 __operator - (const float a, const mat3 n)
-{
-   __retVal[0] = a - n[0];
-   __retVal[1] = a - n[1];
-   __retVal[2] = a - n[2];
-}
-
-mat3 __operator - (const mat3 m, const float b)
-{
-   __retVal[0] = m[0] - b;
-   __retVal[1] = m[1] - b;
-   __retVal[2] = m[2] - b;
-}
-
-mat3 __operator * (const float a, const mat3 n)
-{
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-   __retVal[2] = a * n[2];
-}
-
-mat3 __operator * (const mat3 m, const float b)
-{
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-   __retVal[2] = m[2] * b;
-}
-
-mat3 __operator / (const float a, const mat3 n)
-{
-   __retVal[0] = a / n[0];
-   __retVal[1] = a / n[1];
-   __retVal[2] = a / n[2];
-}
-
-mat3 __operator / (const mat3 m, const float b)
-{
-   __retVal[0] = m[0] / b;
-   __retVal[1] = m[1] / b;
-   __retVal[2] = m[2] / b;
-}
-
-
-//// mat4/float operations
-
-mat4 __operator + (const float a, const mat4 n)
-{
-   __retVal[0] = a + n[0];
-   __retVal[1] = a + n[1];
-   __retVal[2] = a + n[2];
-   __retVal[3] = a + n[3];
-}
-
-mat4 __operator + (const mat4 m, const float b)
-{
-   __retVal[0] = m[0] + b;
-   __retVal[1] = m[1] + b;
-   __retVal[2] = m[2] + b;
-   __retVal[3] = m[3] + b;
-}
-
-mat4 __operator - (const float a, const mat4 n)
-{
-   __retVal[0] = a - n[0];
-   __retVal[1] = a - n[1];
-   __retVal[2] = a - n[2];
-   __retVal[3] = a - n[3];
-}
-
-mat4 __operator - (const mat4 m, const float b)
-{
-   __retVal[0] = m[0] - b;
-   __retVal[1] = m[1] - b;
-   __retVal[2] = m[2] - b;
-   __retVal[3] = m[3] - b;
-}
-
-mat4 __operator * (const float a, const mat4 n)
-{
-   __retVal[0] = a * n[0];
-   __retVal[1] = a * n[1];
-   __retVal[2] = a * n[2];
-   __retVal[3] = a * n[3];
-}
-
-mat4 __operator * (const mat4 m, const float b)
-{
-   __retVal[0] = m[0] * b;
-   __retVal[1] = m[1] * b;
-   __retVal[2] = m[2] * b;
-   __retVal[3] = m[3] * b;
-}
-
-mat4 __operator / (const float a, const mat4 n)
-{
-   __retVal[0] = a / n[0];
-   __retVal[1] = a / n[1];
-   __retVal[2] = a / n[2];
-   __retVal[3] = a / n[3];
-}
-
-mat4 __operator / (const mat4 m, const float b)
-{
-   __retVal[0] = m[0] / b;
-   __retVal[1] = m[1] / b;
-   __retVal[2] = m[2] / b;
-   __retVal[3] = m[3] / b;
-}
-
-
-
-//// matrix / vector products
-
-vec2 __operator * (const mat2 m, const vec2 v)
-{
-   __retVal = m[0] * v.xx
-            + m[1] * v.yy;
-}
-
-vec2 __operator * (const vec2 v, const mat2 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-}
-
-vec3 __operator * (const mat3 m, const vec3 v)
-{
-   __retVal = m[0] * v.xxx
-            + m[1] * v.yyy
-            + m[2] * v.zzz;
-}
-
-vec3 __operator * (const vec3 v, const mat3 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-   __retVal.z = dot(v, m[2]);
-}
-
-vec4 __operator * (const mat4 m, const vec4 v)
-{
-   __retVal = m[0] * v.xxxx
-            + m[1] * v.yyyy
-            + m[2] * v.zzzz
-            + m[3] * v.wwww;
-}
-
-vec4 __operator * (const vec4 v, const mat4 m)
-{
-   __retVal.x = dot(v, m[0]);
-   __retVal.y = dot(v, m[1]);
-   __retVal.z = dot(v, m[2]);
-   __retVal.w = dot(v, m[3]);
-}
-
-
-
-//// mat2 assignment operators
-
-mat2 __operator += (inout mat2 m, const mat2 n)
-{
-   m[0] = m[0] + n[0];
-   m[1] = m[1] + n[1];
-   return m;
-}
-
-mat2 __operator -= (inout mat2 m, const mat2 n)
-{
-   m[0] = m[0] - n[0];
-   m[1] = m[1] - n[1];
-   return m;
-}
-
-mat2 __operator *= (inout mat2 m, const mat2 n)
-{
-   m = m * n;
-   return m;
-}
-
-mat2 __operator /= (inout mat2 m, const mat2 n)
-{
-   m[0] = m[0] / n[0];
-   m[1] = m[1] / n[1];
-   return m;
-}
-
-
-//// mat3 assignment operators
-
-mat3 __operator += (inout mat3 m, const mat3 n)
-{
-   m[0] = m[0] + n[0];
-   m[1] = m[1] + n[1];
-   m[2] = m[2] + n[2];
-   return m;
-}
-
-mat3 __operator -= (inout mat3 m, const mat3 n)
-{
-   m[0] = m[0] - n[0];
-   m[1] = m[1] - n[1];
-   m[2] = m[2] - n[2];
-   return m;
-}
-
-mat3 __operator *= (inout mat3 m, const mat3 n)
-{
-   m = m * n;
-   return m;
-}
-
-mat3 __operator /= (inout mat3 m, const mat3 n)
-{
-   m[0] = m[0] / n[0];
-   m[1] = m[1] / n[1];
-   m[2] = m[2] / n[2];
-   return m;
-}
-
-
-// mat4 assignment operators
-
-mat4 __operator += (inout mat4 m, const mat4 n)
-{
-   m[0] = m[0] + n[0];
-   m[1] = m[1] + n[1];
-   m[2] = m[2] + n[2];
-   m[3] = m[3] + n[3];
-   return m;
-}
-
-mat4 __operator -= (inout mat4 m, const mat4 n)
-{
-   m[0] = m[0] - n[0];
-   m[1] = m[1] - n[1];
-   m[2] = m[2] - n[2];
-   m[3] = m[3] - n[3];
-   return m;
-}
-
-mat4 __operator *= (inout mat4 m, const mat4 n)
-{
-   m = m * n;
-   return m;
-}
-
-mat4 __operator /= (inout mat4 m, const mat4 n)
-{
-   m[0] = m[0] / n[0];
-   m[1] = m[1] / n[1];
-   m[2] = m[2] / n[2];
-   m[3] = m[3] / n[3];
-   return m;
-}
-
-
-//// mat2/float assignment operators
-
-mat2 __operator += (inout mat2 m, const float a)
-{
-   vec2 v = vec2(a);
-   m[0] = m[0] + v;
-   m[1] = m[1] + v;
-   return m;
-}
-
-mat2 __operator -= (inout mat2 m, const float a)
-{
-   vec2 v = vec2(a);
-   m[0] = m[0] - v;
-   m[1] = m[1] - v;
-   return m;
-}
-
-mat2 __operator *= (inout mat2 m, const float a)
-{
-   vec2 v = vec2(a);
-   m[0] = m[0] * v;
-   m[1] = m[1] * v;
-   return m;
-}
-
-mat2 __operator /= (inout mat2 m, const float a)
-{
-   vec2 v = vec2(1.0 / a);
-   m[0] = m[0] * v;
-   m[1] = m[1] * v;
-   return m;
-}
-
-
-//// mat3/float assignment operators
-
-mat3 __operator += (inout mat3 m, const float a)
-{
-   vec3 v = vec3(a);
-   m[0] = m[0] + v;
-   m[1] = m[1] + v;
-   m[2] = m[2] + v;
-   return m;
-}
-
-mat3 __operator -= (inout mat3 m, const float a)
-{
-   vec3 v = vec3(a);
-   m[0] = m[0] - v;
-   m[1] = m[1] - v;
-   m[2] = m[2] - v;
-   return m;
-}
-
-mat3 __operator *= (inout mat3 m, const float a)
-{
-   vec3 v = vec3(a);
-   m[0] = m[0] * v;
-   m[1] = m[1] * v;
-   m[2] = m[2] * v;
-   return m;
-}
-
-mat3 __operator /= (inout mat3 m, const float a)
-{
-   vec3 v = vec3(1.0 / a);
-   m[0] = m[0] * v;
-   m[1] = m[1] * v;
-   m[2] = m[2] * v;
-   return m;
-}
-
-
-//// mat4/float assignment operators
-
-mat4 __operator += (inout mat4 m, const float a)
-{
-   vec4 v = vec4(a);
-   m[0] = m[0] + v;
-   m[1] = m[1] + v;
-   m[2] = m[2] + v;
-   m[3] = m[3] + v;
-   return m;
-}
-
-mat4 __operator -= (inout mat4 m, const float a)
-{
-   vec4 v = vec4(a);
-   m[0] = m[0] - v;
-   m[1] = m[1] - v;
-   m[2] = m[2] - v;
-   m[3] = m[3] - v;
-   return m;
-}
-
-mat4 __operator *= (inout mat4 m, const float a)
-{
-   vec4 v = vec4(a);
-   m[0] = m[0] * v;
-   m[1] = m[1] * v;
-   m[2] = m[2] * v;
-   m[3] = m[3] * v;
-   return m;
-}
-
-mat4 __operator /= (inout mat4 m, const float a)
-{
-   vec4 v = vec4(1.0 / a);
-   m[0] = m[0] * v;
-   m[1] = m[1] * v;
-   m[2] = m[2] * v;
-   m[3] = m[3] * v;
-   return m;
-}
-
-
-
-//// vec/mat assignment operators
-
-vec2 __operator *= (inout vec2 v, const mat2 m)
-{
-   v = v * m;
-   return v;
-}
-
-vec3 __operator *= (inout vec3 v, const mat3 m)
-{
-   v = v * m;
-   return v;
-}
-
-vec4 __operator *= (inout vec4 v, const mat4 m)
-{
-   v = v * m;
-   return v;
-}
-
-
-
-//// pre-decrement operators
-
-int __operator --(inout int a)
-{
-    a = a - 1;
-   __retVal = a;
-}
-
-ivec2 __operator --(inout ivec2 v)
-{
-   v = v - ivec2(1);
-   __retVal = v;
-}
-
-ivec3 __operator --(inout ivec3 v)
-{
-   v = v - ivec3(1);
-   __retVal = v;
-}
-
-ivec4 __operator --(inout ivec4 v)
-{
-   v = v - ivec4(1);
-   __retVal = v;
-}
-
-
-float __operator --(inout float a)
-{
-   a = a - 1.0;
-   __retVal = a;
-}
-
-vec2 __operator --(inout vec2 v)
-{
-   v = v - vec2(1.0);
-   __retVal = v;
-}
-
-vec3 __operator --(inout vec3 v)
-{
-   v = v - vec3(1.0);
-   __retVal = v;
-}
-
-vec4 __operator --(inout vec4 v)
-{
-   v = v - vec4(1.0);
-   __retVal = v;
-}
-
-
-mat2 __operator --(inout mat2 m)
-{
-   m[0] = m[0] - vec2(1.0);
-   m[1] = m[1] - vec2(1.0);
-   __retVal = m;
-}
-
-mat3 __operator --(inout mat3 m)
-{
-   m[0] = m[0] - vec3(1.0);
-   m[1] = m[1] - vec3(1.0);
-   m[2] = m[2] - vec3(1.0);
-   __retVal = m;
-}
-
-mat4 __operator --(inout mat4 m)
-{
-   m[0] = m[0] - vec4(1.0);
-   m[1] = m[1] - vec4(1.0);
-   m[2] = m[2] - vec4(1.0);
-   m[3] = m[3] - vec4(1.0);
-   __retVal = m;
-}
-
-
-//// pre-increment operators
-
-int __operator ++(inout int a)
-{
-    a = a + 1;
-    __retVal = a;
-}
-
-ivec2 __operator ++(inout ivec2 v)
-{
-   v = v + ivec2(1);
-   __retVal = v;
-}
-
-ivec3 __operator ++(inout ivec3 v)
-{
-   v = v + ivec3(1);
-   __retVal = v;
-}
-
-ivec4 __operator ++(inout ivec4 v)
-{
-   v = v + ivec4(1);
-   __retVal = v;
-}
-
-
-float __operator ++(inout float a)
-{
-    a = a + 1.0;
-    __retVal = a;
-}
-
-vec2 __operator ++(inout vec2 v)
-{
-   v = v + vec2(1.0);
-   __retVal = v;
-}
-
-vec3 __operator ++(inout vec3 v)
-{
-   v = v + vec3(1.0);
-   __retVal = v;
-}
-
-vec4 __operator ++(inout vec4 v)
-{
-   v = v + vec4(1.0);
-   __retVal = v;
-}
-
-
-mat2 __operator ++(inout mat2 m)
-{
-   m[0] = m[0] + vec2(1.0);
-   m[1] = m[1] + vec2(1.0);
-   __retVal = m;
-}
-
-mat3 __operator ++(inout mat3 m)
-{
-   m[0] = m[0] + vec3(1.0);
-   m[1] = m[1] + vec3(1.0);
-   m[2] = m[2] + vec3(1.0);
-   __retVal = m;
-}
-
-mat4 __operator ++(inout mat4 m)
-{
-   m[0] = m[0] + vec4(1.0);
-   m[1] = m[1] + vec4(1.0);
-   m[2] = m[2] + vec4(1.0);
-   m[3] = m[3] + vec4(1.0);
-   __retVal = m;
-}
-
-
-
-//// post-decrement
-
-int __postDecr(inout int a)
-{
-   __retVal = a;
-   a = a - 1;
-}
-
-ivec2 __postDecr(inout ivec2 v)
-{
-   __retVal = v;
-   v = v - ivec2(1);
-}
-
-ivec3 __postDecr(inout ivec3 v)
-{
-   __retVal = v;
-   v = v - ivec3(1);
-}
-
-ivec4 __postDecr(inout ivec4 v)
-{
-   __retVal = v;
-   v = v - ivec4(1);
-}
-
-
-float __postDecr(inout float a)
-{
-   __retVal = a;
-   a = a - 1.0;
-}
-
-vec2 __postDecr(inout vec2 v)
-{
-   __retVal = v;
-   v = v - vec2(1.0);
-}
-
-vec3 __postDecr(inout vec3 v)
-{
-   __retVal = v;
-   v = v - vec3(1.0);
-}
-
-vec4 __postDecr(inout vec4 v)
-{
-   __retVal = v;
-   v = v - vec4(1.0);
-}
-
-
-mat2 __postDecr(inout mat2 m)
-{
-   __retVal = m;
-   m[0] = m[0] - vec2(1.0);
-   m[1] = m[1] - vec2(1.0);
-}
-
-mat3 __postDecr(inout mat3 m)
-{
-   __retVal = m;
-   m[0] = m[0] - vec3(1.0);
-   m[1] = m[1] - vec3(1.0);
-   m[2] = m[2] - vec3(1.0);
-}
-
-mat4 __postDecr(inout mat4 m)
-{
-   __retVal = m;
-   m[0] = m[0] - vec4(1.0);
-   m[1] = m[1] - vec4(1.0);
-   m[2] = m[2] - vec4(1.0);
-   m[3] = m[3] - vec4(1.0);
-}
-
-
-//// post-increment
-
-float __postIncr(inout float a)
-{
-   __retVal = a;
-   a = a + 1;
-}
-
-vec2 __postIncr(inout vec2 v)
-{
-   __retVal = v;
-   v = v + vec2(1.0);
-}
-
-vec3 __postIncr(inout vec3 v)
-{
-   __retVal = v;
-   v = v + vec3(1.0);
-}
-
-vec4 __postIncr(inout vec4 v)
-{
-   __retVal = v;
-   v = v + vec4(1.0);
-}
-
-
-int __postIncr(inout int a)
-{
-   __retVal = a;
-   a = a + 1;
-}
-
-ivec2 __postIncr(inout ivec2 v)
-{
-   __retVal = v;
-   v = v + ivec2(1);
-}
-
-ivec3 __postIncr(inout ivec3 v)
-{
-   __retVal = v;
-   v = v + ivec3(1);
-}
-
-ivec4 __postIncr(inout ivec4 v)
-{
-   __retVal = v;
-   v = v + ivec3(1);
-}
-
-
-mat2 __postIncr(inout mat2 m)
-{
-   mat2 n = m;
-   m[0] = m[0] + vec2(1.0);
-   m[1] = m[1] + vec2(1.0);
-   return n;
-}
-
-mat3 __postIncr(inout mat3 m)
-{
-   mat3 n = m;
-   m[0] = m[0] + vec3(1.0);
-   m[1] = m[1] + vec3(1.0);
-   m[2] = m[2] + vec3(1.0);
-   return n;
-}
-
-mat4 __postIncr(inout mat4 m)
-{
-   mat4 n = m;
-   m[0] = m[0] + vec4(1.0);
-   m[1] = m[1] + vec4(1.0);
-   m[2] = m[2] + vec4(1.0);
-   m[3] = m[3] + vec4(1.0);
-   return n;
-}
-
-
-
-//// inequality operators
-
-
-// XXX are the inequality operators for floats/ints really needed????
-bool __operator < (const float a, const float b)
-{
-   __asm vec4_sgt __retVal.x, b, a;
-}
-
-
-bool __operator < (const int a, const int b) {
-    return float (a) < float (b);
-}
-
-bool __operator > (const float a, const float b) {
-    bool c;
-    __asm float_less c, b, a;
-    return c;
-}
-
-bool __operator > (const int a, const int b) {
-    return float (a) > float (b);
-}
-
-bool __operator >= (const float a, const float b) {
-    bool g, e;
-    __asm float_less  g, b, a;
-    __asm float_equal e, a, b;
-    return g || e;
-}
-
-bool __operator >= (const int a, const int b) {
-    return float (a) >= float (b);
-}
-
-bool __operator <= (const float a, const float b) {
-    bool g, e;
-    __asm float_less  g, a, b;
-    __asm float_equal e, a, b;
-    return g || e;
-}
-
-bool __operator <= (const int a, const int b) {
-    return float (a) <= float (b);
-}
-
-
-
-//
-// MESA-specific extension functions.
-//
-
-void printMESA (const float f) {
-    __asm float_print f;
-}
-
-void printMESA (const int i) {
-    __asm int_print i;
-}
-
-void printMESA (const bool b) {
-    __asm bool_print b;
-}
-
-void printMESA (const vec2 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-}
-
-void printMESA (const vec3 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-    printMESA (v.z);
-}
-
-void printMESA (const vec4 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-    printMESA (v.z);
-    printMESA (v.w);
-}
-
-void printMESA (const ivec2 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-}
-
-void printMESA (const ivec3 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-    printMESA (v.z);
-}
-
-void printMESA (const ivec4 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-    printMESA (v.z);
-    printMESA (v.w);
-}
-
-void printMESA (const bvec2 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-}
-
-void printMESA (const bvec3 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-    printMESA (v.z);
-}
-
-void printMESA (const bvec4 v) {
-    printMESA (v.x);
-    printMESA (v.y);
-    printMESA (v.z);
-    printMESA (v.w);
-}
-
-void printMESA (const mat2 m) {
-    printMESA (m[0]);
-    printMESA (m[1]);
-}
-
-void printMESA (const mat3 m) {
-    printMESA (m[0]);
-    printMESA (m[1]);
-    printMESA (m[2]);
-}
-
-void printMESA (const mat4 m) {
-    printMESA (m[0]);
-    printMESA (m[1]);
-    printMESA (m[2]);
-    printMESA (m[3]);
-}
-
-void printMESA (const sampler1D e) {
-    __asm int_print e;
-}
-
-void printMESA (const sampler2D e) {
-    __asm int_print e;
-}
-
-void printMESA (const sampler3D e) {
-    __asm int_print e;
-}
-
-void printMESA (const samplerCube e) {
-    __asm int_print e;
-}
-
-void printMESA (const sampler1DShadow e) {
-    __asm int_print e;
-}
-
-void printMESA (const sampler2DShadow e) {
-    __asm int_print e;
-}
-
diff --git a/src/mesa/slang/library/slang_fragment_builtin.gc b/src/mesa/slang/library/slang_fragment_builtin.gc
deleted file mode 100644 (file)
index 54a80ea..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-//
-// From Shader Spec, ver. 1.10, rev. 59
-//
-
-__fixed_input vec4 gl_FragCoord;
-__fixed_input bool gl_FrontFacing;
-__fixed_output vec4 gl_FragColor;
-__fixed_output vec4 gl_FragData[gl_MaxDrawBuffers];
-__fixed_output float gl_FragDepth;
-
-varying vec4 gl_Color;
-varying vec4 gl_SecondaryColor;
-varying vec4 gl_TexCoord[gl_MaxTextureCoords];
-varying float gl_FogFragCoord;
-
-
-
-//// 8.7 Texture Lookup Functions (with bias)
-
-vec4 texture1D(const sampler1D sampler, const float coord, const float bias)
-{
-   vec4 coord4;
-   coord4.x = coord;
-   coord4.w = bias;
-   __asm vec4_tex_1d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture1DProj(const sampler1D sampler, const vec2 coord, const float bias)
-{
-   // do projection here (there's no vec4_texbp1d instruction)
-   vec4 pcoord;
-   pcoord.x = coord.x / coord.y;
-   pcoord.w = bias;
-   __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
-}
-
-vec4 texture1DProj(const sampler1D sampler, const vec4 coord, const float bias)
-{
-   // do projection here (there's no vec4_texbp1d instruction)
-   vec4 pcoord;
-   pcoord.x = coord.x / coord.z;
-   pcoord.w = bias;
-   __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
-}
-
-
-
-
-vec4 texture2D(const sampler2D sampler, const vec2 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xy = coord.xy;
-   coord4.w = bias;
-   __asm vec4_tex_2d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture2DProj(const sampler2D sampler, const vec3 coord, const float bias)
-{
-   // do projection here (there's no vec4_texbp2d instruction)
-   vec4 pcoord;
-   pcoord.xy = coord.xy / coord.z;
-   pcoord.w = bias;
-   __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
-}
-
-vec4 texture2DProj(const sampler2D sampler, const vec4 coord, const float bias)
-{
-   // do projection here (there's no vec4_texbp2d instruction)
-   vec4 pcoord;
-   pcoord.xy = coord.xy / coord.w;
-   pcoord.w = bias;
-   __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
-}
-
-
-
-
-vec4 texture3D(const sampler3D sampler, const vec3 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xyz = coord.xyz;
-   coord4.w = bias;
-   __asm vec4_tex_3d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture3DProj(const sampler3D sampler, const vec4 coord, const float bias)
-{
-   // do projection here (there's no vec4_texbp3d instruction)
-   vec4 pcoord;
-   pcoord.xyz = coord.xyz / coord.w;
-   pcoord.w = bias;
-   __asm vec4_tex_3d_bias __retVal, sampler, pcoord;
-}
-
-
-
-
-vec4 textureCube(const samplerCube sampler, const vec3 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = bias;
-   __asm vec4_tex_cube __retVal, sampler, coord4;
-}
-
-
-
-vec4 shadow1D(const sampler1DShadow sampler, const vec3 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = bias;
-   __asm vec4_tex_1d_bias_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord, const float bias)
-{
-   vec4 pcoord;
-   pcoord.x = coord.x / coord.w;
-   pcoord.z = coord.z;
-   pcoord.w = bias;
-   __asm vec4_tex_1d_bias_shadow __retVal, sampler, pcoord;
-}
-
-vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = bias;
-   __asm vec4_tex_2d_bias_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord, const float bias)
-{
-   vec4 pcoord;
-   pcoord.xy = coord.xy / coord.w;
-   pcoord.z = coord.z;
-   pcoord.w = bias;
-   __asm vec4_tex_2d_bias_shadow __retVal, sampler, pcoord;
-}
-
-
-
-//// GL_EXT_texture_array
-
-vec4 texture1DArray(const sampler1DArray sampler, const vec2 coord)
-{
-   vec4 coord4;
-   coord4.xy = coord;
-   __asm vec4_tex_1d_array __retVal, sampler, coord4;
-}
-
-vec4 texture1DArray(const sampler1DArray sampler, const vec2 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xy = coord;
-   coord4.w = bias;
-   __asm vec4_tex_1d_array_bias __retVal, sampler, coord4;
-}
-
-vec4 texure2DArray(const sampler2DArray sampler, const vec3 coord)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   __asm vec4_tex_2d_array __retVal, sampler, coord4;
-}
-
-vec4 texture2DArray(const sampler2DArray sampler, const vec3 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = bias;
-   __asm vec4_tex_2d_array_bias __retVal, sampler, coord4;
-}
-
-vec4 shadow1DArray(const sampler1DArrayShadow sampler, const vec2 coord)
-{
-   vec4 coord4;
-   coord4.xy = coord;
-   __asm vec4_tex_1d_array_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow1DArray(const sampler1DArrayShadow sampler, const vec2 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xy = coord;
-   coord4.w = bias;
-   __asm vec4_tex_1d_array_bias_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow2DArray(const sampler2DArrayShadow sampler, const vec3 coord)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   __asm vec4_tex_2d_array_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow2DArray(const sampler2DArrayShadow sampler, const vec3 coord, const float bias)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = bias;
-   __asm vec4_tex_2d_array_bias_shadow __retVal, sampler, coord4;
-}
-
-
-
-//
-// 8.8 Fragment Processing Functions
-//
-
-float dFdx(const float p)
-{
-   __asm vec4_ddx __retVal.x, p.xxxx;
-}
-
-vec2 dFdx(const vec2 p)
-{
-   __asm vec4_ddx __retVal.xy, p.xyyy;
-}
-
-vec3 dFdx(const vec3 p)
-{
-   __asm vec4_ddx __retVal.xyz, p.xyzz;
-}
-
-vec4 dFdx(const vec4 p)
-{
-   __asm vec4_ddx __retVal, p;
-}
-
-float dFdy(const float p)
-{
-   __asm vec4_ddy __retVal.x, p.xxxx;
-}
-
-vec2 dFdy(const vec2 p)
-{
-   __asm vec4_ddy __retVal.xy, p.xyyy;
-}
-
-vec3 dFdy(const vec3 p)
-{
-   __asm vec4_ddy __retVal.xyz, p.xyzz;
-}
-
-vec4 dFdy(const vec4 p)
-{
-   __asm vec4_ddy __retVal, p;
-}
-
-float fwidth (const float p)
-{
-   // XXX hand-write with __asm
-   return abs(dFdx(p)) + abs(dFdy(p));
-}
-
-vec2 fwidth(const vec2 p)
-{
-   // XXX hand-write with __asm
-   return abs(dFdx(p)) + abs(dFdy(p));
-}
-
-vec3 fwidth(const vec3 p)
-{
-   // XXX hand-write with __asm
-   return abs(dFdx(p)) + abs(dFdy(p));
-}
-
-vec4 fwidth(const vec4 p)
-{
-   // XXX hand-write with __asm
-   return abs(dFdx(p)) + abs(dFdy(p));
-}
-
diff --git a/src/mesa/slang/library/slang_geometry_builtin.gc b/src/mesa/slang/library/slang_geometry_builtin.gc
deleted file mode 100644 (file)
index 0752491..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-const int _mesa_VerticesInMax = 6;
-
-__fixed_input int gl_PrimitiveIDIn;
-__fixed_output int gl_PrimitiveID;
-__fixed_output int gl_Layer;
-
-
-varying in vec4 gl_FrontColorIn[_mesa_VerticesInMax];
-varying in vec4 gl_BackColorIn[_mesa_VerticesInMax];
-varying in vec4 gl_FrontSecondaryColorIn[_mesa_VerticesInMax];
-varying in vec4 gl_BackSecondaryColorIn[_mesa_VerticesInMax];
-/*varying in vec4 gl_TexCoordIn[_mesa_VerticesInMax][gl_MaxTextureCoords];*/
-varying in float gl_FogFragCoordIn[_mesa_VerticesInMax];
-varying in vec4 gl_PositionIn[_mesa_VerticesInMax];
-varying in float gl_PointSizeIn[_mesa_VerticesInMax];
-varying in vec4 gl_ClipVertexIn[_mesa_VerticesInMax];
-
-varying out vec4 gl_Position;
-varying out vec4 gl_FrontColor;
-varying out vec4 gl_BackColor;
-varying out vec4 gl_FrontSecondaryColor;
-varying out vec4 gl_BackSecondaryColor;
-varying out vec4 gl_TexCoord[gl_MaxTextureCoords];
-varying out float gl_FogFragCoord;
-
-void EmitVertex()
-{
-    __asm emit_vertex;
-}
-
-void EndPrimitive()
-{
-    __asm end_primitive;
-}
diff --git a/src/mesa/slang/library/slang_vertex_builtin.gc b/src/mesa/slang/library/slang_vertex_builtin.gc
deleted file mode 100644 (file)
index 0c67c2e..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-//
-// From Shader Spec, ver. 1.10, rev. 59
-//
-
-__fixed_output vec4 gl_Position;
-__fixed_output float gl_PointSize;
-__fixed_output vec4 gl_ClipVertex;
-
-attribute vec4 gl_Color;
-attribute vec4 gl_SecondaryColor;
-attribute vec3 gl_Normal;
-attribute vec4 gl_Vertex;
-attribute vec4 gl_MultiTexCoord0;
-attribute vec4 gl_MultiTexCoord1;
-attribute vec4 gl_MultiTexCoord2;
-attribute vec4 gl_MultiTexCoord3;
-attribute vec4 gl_MultiTexCoord4;
-attribute vec4 gl_MultiTexCoord5;
-attribute vec4 gl_MultiTexCoord6;
-attribute vec4 gl_MultiTexCoord7;
-attribute float gl_FogCoord;
-
-varying vec4 gl_FrontColor;
-varying vec4 gl_BackColor;
-varying vec4 gl_FrontSecondaryColor;
-varying vec4 gl_BackSecondaryColor;
-varying vec4 gl_TexCoord[gl_MaxTextureCoords];
-varying float gl_FogFragCoord;
-
-//
-// Geometric Functions
-//
-
-vec4 ftransform()
-{
-   __retVal = gl_ModelViewProjectionMatrix[0] * gl_Vertex.xxxx
-            + gl_ModelViewProjectionMatrix[1] * gl_Vertex.yyyy
-            + gl_ModelViewProjectionMatrix[2] * gl_Vertex.zzzz
-            + gl_ModelViewProjectionMatrix[3] * gl_Vertex.wwww;
-}
-
-
-
-//
-// 8.7 Texture Lookup Functions
-// These are pretty much identical to the ones in slang_fragment_builtin.gc
-// When used in a vertex program, the texture sample instructions should not
-// be using a LOD term so it's effectively zero.  Adding 'lod' to that does
-// what we want.
-//
-
-vec4 texture1DLod(const sampler1D sampler, const float coord, const float lod)
-{
-   vec4 coord4;
-   coord4.x = coord;
-   coord4.w = lod;
-   __asm vec4_tex_1d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture1DProjLod(const sampler1D sampler, const vec2 coord, const float lod)
-{
-   vec4 pcoord;
-   pcoord.x = coord.x / coord.y;
-   pcoord.w = lod;
-   __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
-}
-
-vec4 texture1DProjLod(const sampler1D sampler, const vec4 coord, const float lod)
-{
-   vec4 pcoord;
-   pcoord.x = coord.x / coord.z;
-   pcoord.w = lod;
-   __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
-}
-
-
-
-vec4 texture2DLod(const sampler2D sampler, const vec2 coord, const float lod)
-{
-   vec4 coord4;
-   coord4.xy = coord.xy;
-   coord4.w = lod;
-   __asm vec4_tex_2d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture2DProjLod(const sampler2D sampler, const vec3 coord, const float lod)
-{
-   vec4 pcoord;
-   pcoord.xy = coord.xy / coord.z;
-   pcoord.w = lod;
-   __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
-}
-
-vec4 texture2DProjLod(const sampler2D sampler, const vec4 coord, const float lod)
-{
-   vec4 pcoord;
-   pcoord.xy = coord.xy / coord.z;
-   pcoord.w = lod;
-   __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
-}
-
-
-vec4 texture3DLod(const sampler3D sampler, const vec3 coord, const float lod)
-{
-   vec4 coord4;
-   coord4.xyz = coord.xyz;
-   coord4.w = lod;
-   __asm vec4_tex_3d_bias __retVal, sampler, coord4;
-}
-
-vec4 texture3DProjLod(const sampler3D sampler, const vec4 coord, const float lod)
-{
-   // do projection here (there's no vec4_tex_3d_bias_proj instruction)
-   vec4 pcoord;
-   pcoord.xyz = coord.xyz / coord.w;
-   pcoord.w = lod;
-   __asm vec4_tex_3d_bias __retVal, sampler, pcoord;
-}
-
-
-vec4 textureCubeLod(const samplerCube sampler, const vec3 coord, const float lod)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = lod;
-   __asm vec4_tex_cube __retVal, sampler, coord4;
-}
-
-
-vec4 shadow1DLod(const sampler1DShadow sampler, const vec3 coord, const float lod)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = lod;
-   __asm vec4_tex_1d_bias_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow1DProjLod(const sampler1DShadow sampler, const vec4 coord,
-                     const float lod)
-{
-   vec4 pcoord;
-   pcoord.x = coord.x / coord.w;
-   pcoord.z = coord.z;
-   pcoord.w = lod;
-   __asm vec4_tex_1d_bias_shadow __retVal, sampler, pcoord;
-}
-
-
-vec4 shadow2DLod(const sampler2DShadow sampler, const vec3 coord, const float lod)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = lod;
-   __asm vec4_tex_2d_bias_shadow __retVal, sampler, coord4;
-}
-
-vec4 shadow2DProjLod(const sampler2DShadow sampler, const vec4 coord,
-                     const float lod)
-{
-   vec4 pcoord;
-   pcoord.xy = coord.xy / coord.w;
-   pcoord.z = coord.z;
-   pcoord.w = lod;
-   __asm vec4_tex_2d_bias_shadow __retVal, sampler, pcoord;
-}
-
-
-//// GL_EXT_texture_array
-
-vec4 texture1DArrayLod(const sampler1DArray sampler, const vec2 coord, const float lod)
-{
-   vec4 coord4;
-   coord4.xy = coord;
-   coord4.w = lod;
-   __asm vec4_tex_1d_array_bias __retVal, sampler, coord4;
-}
-
-
-vec4 texture2DArrayLod(const sampler2DArray sampler, const vec3 coord, const float lod)
-{
-   vec4 coord4;
-   coord4.xyz = coord;
-   coord4.w = lod;
-   __asm vec4_tex_2d_array_bias __retVal, sampler, coord4;
-}
-
diff --git a/src/mesa/slang/slang_builtin.c b/src/mesa/slang/slang_builtin.c
deleted file mode 100644 (file)
index a7e0efc..0000000
+++ /dev/null
@@ -1,1018 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.3
- *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
- * Copyright (C) 2008  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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_builtin.c
- * Resolve built-in uniform vars.
- * \author Brian Paul
- */
-
-#include "main/imports.h"
-#include "main/mtypes.h"
-#include "program/program.h"
-#include "program/prog_instruction.h"
-#include "program/prog_parameter.h"
-#include "program/prog_statevars.h"
-#include "slang/slang_ir.h"
-#include "slang/slang_builtin.h"
-
-
-/** special state token (see below) */
-#define STATE_ARRAY ((gl_state_index) 0xfffff)
-
-
-/**
- * Lookup GL state given a variable name, 0, 1 or 2 indexes and a field.
- * Allocate room for the state in the given param list and return position
- * in the list.
- * Yes, this is kind of ugly, but it works.
- */
-static GLint
-lookup_statevar(const char *var, GLint index1, GLint index2, const char *field,
-                GLuint *swizzleOut,
-                struct gl_program_parameter_list *paramList)
-{
-   /*
-    * NOTE: The ARB_vertex_program extension specified that matrices get
-    * loaded in registers in row-major order.  With GLSL, we want column-
-    * major order.  So, we need to transpose all matrices here...
-    */
-   static const struct {
-      const char *name;
-      gl_state_index matrix;
-      gl_state_index modifier;
-   } matrices[] = {
-      { "gl_ModelViewMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE },
-      { "gl_ModelViewMatrixInverse", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS },
-      { "gl_ModelViewMatrixTranspose", STATE_MODELVIEW_MATRIX, 0 },
-      { "gl_ModelViewMatrixInverseTranspose", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
-
-      { "gl_ProjectionMatrix", STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE },
-      { "gl_ProjectionMatrixInverse", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS },
-      { "gl_ProjectionMatrixTranspose", STATE_PROJECTION_MATRIX, 0 },
-      { "gl_ProjectionMatrixInverseTranspose", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE },
-
-      { "gl_ModelViewProjectionMatrix", STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE },
-      { "gl_ModelViewProjectionMatrixInverse", STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS },
-      { "gl_ModelViewProjectionMatrixTranspose", STATE_MVP_MATRIX, 0 },
-      { "gl_ModelViewProjectionMatrixInverseTranspose", STATE_MVP_MATRIX, STATE_MATRIX_INVERSE },
-
-      { "gl_TextureMatrix", STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE },
-      { "gl_TextureMatrixInverse", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS },
-      { "gl_TextureMatrixTranspose", STATE_TEXTURE_MATRIX, 0 },
-      { "gl_TextureMatrixInverseTranspose", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE },
-
-      { "gl_NormalMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
-
-      { NULL, 0, 0 }
-   };
-   gl_state_index tokens[STATE_LENGTH];
-   GLuint i;
-   GLboolean isMatrix = GL_FALSE;
-
-   for (i = 0; i < STATE_LENGTH; i++) {
-      tokens[i] = 0;
-   }
-   *swizzleOut = SWIZZLE_NOOP;
-
-   /* first, look if var is a pre-defined matrix */
-   for (i = 0; matrices[i].name; i++) {
-      if (strcmp(var, matrices[i].name) == 0) {
-         tokens[0] = matrices[i].matrix;
-         /* tokens[1], [2] and [3] filled below */
-         tokens[4] = matrices[i].modifier;
-         isMatrix = GL_TRUE;
-         break;
-      }
-   }
-
-   if (isMatrix) {
-      if (tokens[0] == STATE_TEXTURE_MATRIX) {
-         /* texture_matrix[index1][index2] */
-         tokens[1] = index1 >= 0 ? index1 : 0; /* which texture matrix */
-         index1 = index2; /* move matrix row value to index1 */
-      }
-      if (index1 < 0) {
-         /* index1 is unused: prevent extra addition at end of function */
-         index1 = 0;
-      }
-   }
-   else if (strcmp(var, "gl_DepthRange") == 0) {
-      tokens[0] = STATE_DEPTH_RANGE;
-      assert(field);
-      if (strcmp(field, "near") == 0) {
-         *swizzleOut = SWIZZLE_XXXX;
-      }
-      else if (strcmp(field, "far") == 0) {
-         *swizzleOut = SWIZZLE_YYYY;
-      }
-      else if (strcmp(field, "diff") == 0) {
-         *swizzleOut = SWIZZLE_ZZZZ;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_ClipPlane") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_CLIPPLANE;
-      tokens[1] = index1;
-   }
-   else if (strcmp(var, "gl_Point") == 0) {
-      assert(field);
-      if (strcmp(field, "size") == 0) {
-         tokens[0] = STATE_POINT_SIZE;
-         *swizzleOut = SWIZZLE_XXXX;
-      }
-      else if (strcmp(field, "sizeMin") == 0) {
-         tokens[0] = STATE_POINT_SIZE;
-         *swizzleOut = SWIZZLE_YYYY;
-      }
-      else if (strcmp(field, "sizeMax") == 0) {
-         tokens[0] = STATE_POINT_SIZE;
-         *swizzleOut = SWIZZLE_ZZZZ;
-      }
-      else if (strcmp(field, "fadeThresholdSize") == 0) {
-         tokens[0] = STATE_POINT_SIZE;
-         *swizzleOut = SWIZZLE_WWWW;
-      }
-      else if (strcmp(field, "distanceConstantAttenuation") == 0) {
-         tokens[0] = STATE_POINT_ATTENUATION;
-         *swizzleOut = SWIZZLE_XXXX;
-      }
-      else if (strcmp(field, "distanceLinearAttenuation") == 0) {
-         tokens[0] = STATE_POINT_ATTENUATION;
-         *swizzleOut = SWIZZLE_YYYY;
-      }
-      else if (strcmp(field, "distanceQuadraticAttenuation") == 0) {
-         tokens[0] = STATE_POINT_ATTENUATION;
-         *swizzleOut = SWIZZLE_ZZZZ;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_FrontMaterial") == 0 ||
-            strcmp(var, "gl_BackMaterial") == 0) {
-      tokens[0] = STATE_MATERIAL;
-      if (strcmp(var, "gl_FrontMaterial") == 0)
-         tokens[1] = 0;
-      else
-         tokens[1] = 1;
-      assert(field);
-      if (strcmp(field, "emission") == 0) {
-         tokens[2] = STATE_EMISSION;
-      }
-      else if (strcmp(field, "ambient") == 0) {
-         tokens[2] = STATE_AMBIENT;
-      }
-      else if (strcmp(field, "diffuse") == 0) {
-         tokens[2] = STATE_DIFFUSE;
-      }
-      else if (strcmp(field, "specular") == 0) {
-         tokens[2] = STATE_SPECULAR;
-      }
-      else if (strcmp(field, "shininess") == 0) {
-         tokens[2] = STATE_SHININESS;
-         *swizzleOut = SWIZZLE_XXXX;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_LightSource") == 0) {
-      if (!field || index1 < 0)
-         return -1;
-
-      tokens[0] = STATE_LIGHT;
-      tokens[1] = index1;
-
-      if (strcmp(field, "ambient") == 0) {
-         tokens[2] = STATE_AMBIENT;
-      }
-      else if (strcmp(field, "diffuse") == 0) {
-         tokens[2] = STATE_DIFFUSE;
-      }
-      else if (strcmp(field, "specular") == 0) {
-         tokens[2] = STATE_SPECULAR;
-      }
-      else if (strcmp(field, "position") == 0) {
-         tokens[2] = STATE_POSITION;
-      }
-      else if (strcmp(field, "halfVector") == 0) {
-         tokens[2] = STATE_HALF_VECTOR;
-      }
-      else if (strcmp(field, "spotDirection") == 0) {
-         tokens[2] = STATE_SPOT_DIRECTION;
-      }
-      else if (strcmp(field, "spotCosCutoff") == 0) {
-         tokens[2] = STATE_SPOT_DIRECTION;
-         *swizzleOut = SWIZZLE_WWWW;
-      }
-      else if (strcmp(field, "spotCutoff") == 0) {
-         tokens[2] = STATE_SPOT_CUTOFF;
-         *swizzleOut = SWIZZLE_XXXX;
-      }
-      else if (strcmp(field, "spotExponent") == 0) {
-         tokens[2] = STATE_ATTENUATION;
-         *swizzleOut = SWIZZLE_WWWW;
-      }
-      else if (strcmp(field, "constantAttenuation") == 0) {
-         tokens[2] = STATE_ATTENUATION;
-         *swizzleOut = SWIZZLE_XXXX;
-      }
-      else if (strcmp(field, "linearAttenuation") == 0) {
-         tokens[2] = STATE_ATTENUATION;
-         *swizzleOut = SWIZZLE_YYYY;
-      }
-      else if (strcmp(field, "quadraticAttenuation") == 0) {
-         tokens[2] = STATE_ATTENUATION;
-         *swizzleOut = SWIZZLE_ZZZZ;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_LightModel") == 0) {
-      if (strcmp(field, "ambient") == 0) {
-         tokens[0] = STATE_LIGHTMODEL_AMBIENT;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_FrontLightModelProduct") == 0) {
-      if (strcmp(field, "sceneColor") == 0) {
-         tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
-         tokens[1] = 0;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_BackLightModelProduct") == 0) {
-      if (strcmp(field, "sceneColor") == 0) {
-         tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
-         tokens[1] = 1;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_FrontLightProduct") == 0 ||
-            strcmp(var, "gl_BackLightProduct") == 0) {
-      if (index1 < 0 || !field)
-         return -1;
-
-      tokens[0] = STATE_LIGHTPROD;
-      tokens[1] = index1; /* light number */
-      if (strcmp(var, "gl_FrontLightProduct") == 0) {
-         tokens[2] = 0; /* front */
-      }
-      else {
-         tokens[2] = 1; /* back */
-      }
-      if (strcmp(field, "ambient") == 0) {
-         tokens[3] = STATE_AMBIENT;
-      }
-      else if (strcmp(field, "diffuse") == 0) {
-         tokens[3] = STATE_DIFFUSE;
-      }
-      else if (strcmp(field, "specular") == 0) {
-         tokens[3] = STATE_SPECULAR;
-      }
-      else {
-         return -1;
-      }
-   }
-   else if (strcmp(var, "gl_TextureEnvColor") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXENV_COLOR;
-      tokens[1] = index1;
-   }
-   else if (strcmp(var, "gl_EyePlaneS") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_EYE_S;
-   }
-   else if (strcmp(var, "gl_EyePlaneT") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_EYE_T;
-   }
-   else if (strcmp(var, "gl_EyePlaneR") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_EYE_R;
-   }
-   else if (strcmp(var, "gl_EyePlaneQ") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_EYE_Q;
-   }
-   else if (strcmp(var, "gl_ObjectPlaneS") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_OBJECT_S;
-   }
-   else if (strcmp(var, "gl_ObjectPlaneT") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_OBJECT_T;
-   }
-   else if (strcmp(var, "gl_ObjectPlaneR") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_OBJECT_R;
-   }
-   else if (strcmp(var, "gl_ObjectPlaneQ") == 0) {
-      if (index1 < 0)
-         return -1;
-      tokens[0] = STATE_TEXGEN;
-      tokens[1] = index1; /* tex unit */
-      tokens[2] = STATE_TEXGEN_OBJECT_Q;
-   }
-   else if (strcmp(var, "gl_Fog") == 0) {
-      if (strcmp(field, "color") == 0) {
-         tokens[0] = STATE_FOG_COLOR;
-      }
-      else if (strcmp(field, "density") == 0) {
-         tokens[0] = STATE_FOG_PARAMS;
-         *swizzleOut = SWIZZLE_XXXX;
-      }
-      else if (strcmp(field, "start") == 0) {
-         tokens[0] = STATE_FOG_PARAMS;
-         *swizzleOut = SWIZZLE_YYYY;
-      }
-      else if (strcmp(field, "end") == 0) {
-         tokens[0] = STATE_FOG_PARAMS;
-         *swizzleOut = SWIZZLE_ZZZZ;
-      }
-      else if (strcmp(field, "scale") == 0) {
-         tokens[0] = STATE_FOG_PARAMS;
-         *swizzleOut = SWIZZLE_WWWW;
-      }
-      else {
-         return -1;
-      }
-   }
-   else {
-      return -1;
-   }
-
-   if (isMatrix) {
-      /* load all four rows (or columns) of matrix */
-      GLint pos[4];
-      GLuint j;
-      for (j = 0; j < 4; j++) {
-         tokens[2] = tokens[3] = j; /* jth row of matrix */
-         pos[j] = _mesa_add_state_reference(paramList, tokens);
-         assert(pos[j] >= 0);
-         ASSERT(pos[j] >= 0);
-      }
-      return pos[0] + index1;
-   }
-   else {
-      /* allocate a single register */
-      GLint pos = _mesa_add_state_reference(paramList, tokens);
-      ASSERT(pos >= 0);
-      return pos;
-   }
-}
-
-
-
-/**
- * Given a variable name and datatype, emit uniform/constant buffer
- * entries which will store that state variable.
- * For example, if name="gl_LightSource" we'll emit 64 state variable
- * vectors/references and return position where that data starts.  This will
- * allow run-time array indexing into the light source array.
- *
- * Note that this is a recursive function.
- *
- * \return -1 if error, else index of start of data in the program parameter list
- */
-static GLint
-emit_statevars(const char *name, int array_len,
-               const slang_type_specifier *type,
-               gl_state_index tokens[STATE_LENGTH],
-               struct gl_program_parameter_list *paramList)
-{
-   if (type->type == SLANG_SPEC_ARRAY) {
-      GLint i, pos = -1;
-      assert(array_len > 0);
-      if (strcmp(name, "gl_ClipPlane") == 0) {
-         tokens[0] = STATE_CLIPPLANE;
-      }
-      else if (strcmp(name, "gl_LightSource") == 0) {
-         tokens[0] = STATE_LIGHT;
-      }
-      else if (strcmp(name, "gl_FrontLightProduct") == 0) {
-         tokens[0] = STATE_LIGHTPROD;
-         tokens[2] = 0; /* front */
-      }
-      else if (strcmp(name, "gl_BackLightProduct") == 0) {
-         tokens[0] = STATE_LIGHTPROD;
-         tokens[2] = 1; /* back */
-      }
-      else if (strcmp(name, "gl_TextureEnvColor") == 0) {
-         tokens[0] = STATE_TEXENV_COLOR;
-      }
-      else if (strcmp(name, "gl_EyePlaneS") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_EYE_S;
-      }
-      else if (strcmp(name, "gl_EyePlaneT") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_EYE_T;
-      }
-      else if (strcmp(name, "gl_EyePlaneR") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_EYE_R;
-      }
-      else if (strcmp(name, "gl_EyePlaneQ") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_EYE_Q;
-      }
-      else if (strcmp(name, "gl_ObjectPlaneS") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_OBJECT_S;
-      }
-      else if (strcmp(name, "gl_ObjectPlaneT") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_OBJECT_T;
-      }
-      else if (strcmp(name, "gl_ObjectPlaneR") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_OBJECT_R;
-      }
-      else if (strcmp(name, "gl_ObjectPlaneQ") == 0) {
-         tokens[0] = STATE_TEXGEN;
-         tokens[2] = STATE_TEXGEN_OBJECT_Q;
-      }
-      else if (strcmp(name, "gl_TextureMatrix") == 0) {
-         tokens[0] = STATE_TEXTURE_MATRIX;
-         tokens[4] = STATE_MATRIX_TRANSPOSE;
-      }
-      else if (strcmp(name, "gl_TextureMatrixInverse") == 0) {
-         tokens[0] = STATE_TEXTURE_MATRIX;
-         tokens[4] = STATE_MATRIX_INVTRANS;
-      }
-      else if (strcmp(name, "gl_TextureMatrixTranspose") == 0) {
-         tokens[0] = STATE_TEXTURE_MATRIX;
-         tokens[4] = 0;
-      }
-      else if (strcmp(name, "gl_TextureMatrixInverseTranspose") == 0) {
-         tokens[0] = STATE_TEXTURE_MATRIX;
-         tokens[4] = STATE_MATRIX_INVERSE;
-      }
-      else {
-         return -1; /* invalid array name */
-      }
-      /* emit state vars for each array element */
-      for (i = 0; i < array_len; i++) {
-         GLint p;
-         tokens[1] = i;
-         p = emit_statevars(NULL, 0, type->_array, tokens, paramList);
-         if (i == 0)
-            pos = p;
-      }
-      return pos;
-   }
-   else if (type->type == SLANG_SPEC_STRUCT) {
-      const slang_variable_scope *fields = type->_struct->fields;
-      GLuint i, pos = 0;
-      for (i = 0; i < fields->num_variables; i++) {
-         const slang_variable *var = fields->variables[i];
-         GLint p = emit_statevars(var->a_name, 0, &var->type.specifier,
-                                  tokens, paramList);
-         if (i == 0)
-            pos = p;
-      }
-      return pos;
-   }
-   else if (type->type == SLANG_SPEC_MAT4) {
-      /* unroll/emit 4 array rows (or columns) */
-      slang_type_specifier vec4;
-      GLint i, p, pos = -1;
-      vec4.type = SLANG_SPEC_VEC4;
-      for (i = 0; i < 4; i++) {
-         tokens[2] = tokens[3] = i; /* row[i] (or column[i]) of matrix */
-         p = emit_statevars(NULL, 0, &vec4, tokens, paramList);
-         if (pos == -1)
-            pos = p;
-      }
-      return pos;
-   }
-   else {
-      GLint pos;
-      assert(type->type == SLANG_SPEC_VEC4 ||
-             type->type == SLANG_SPEC_VEC3 ||
-             type->type == SLANG_SPEC_VEC2 ||
-             type->type == SLANG_SPEC_FLOAT ||
-             type->type == SLANG_SPEC_IVEC4 ||
-             type->type == SLANG_SPEC_IVEC3 ||
-             type->type == SLANG_SPEC_IVEC2 ||
-             type->type == SLANG_SPEC_INT);
-      if (name) {
-         GLint t;
-
-         if (tokens[0] == STATE_LIGHT)
-            t = 2;
-         else if (tokens[0] == STATE_LIGHTPROD)
-            t = 3;
-         else
-            return -1; /* invalid array name */
-
-         if (strcmp(name, "ambient") == 0) {
-            tokens[t] = STATE_AMBIENT;
-         }
-         else if (strcmp(name, "diffuse") == 0) {
-            tokens[t] = STATE_DIFFUSE;
-         }
-         else if (strcmp(name, "specular") == 0) {
-            tokens[t] = STATE_SPECULAR;
-         }
-         else if (strcmp(name, "position") == 0) {
-            tokens[t] = STATE_POSITION;
-         }
-         else if (strcmp(name, "halfVector") == 0) {
-            tokens[t] = STATE_HALF_VECTOR;
-         }
-         else if (strcmp(name, "spotDirection") == 0) {
-            tokens[t] = STATE_SPOT_DIRECTION; /* xyz components */
-         }
-         else if (strcmp(name, "spotCosCutoff") == 0) {
-            tokens[t] = STATE_SPOT_DIRECTION; /* w component */
-         }
-
-         else if (strcmp(name, "constantAttenuation") == 0) {
-            tokens[t] = STATE_ATTENUATION; /* x component */
-         }
-         else if (strcmp(name, "linearAttenuation") == 0) {
-            tokens[t] = STATE_ATTENUATION; /* y component */
-         }
-         else if (strcmp(name, "quadraticAttenuation") == 0) {
-            tokens[t] = STATE_ATTENUATION; /* z component */
-         }
-         else if (strcmp(name, "spotExponent") == 0) {
-            tokens[t] = STATE_ATTENUATION; /* w = spot exponent */
-         }
-
-         else if (strcmp(name, "spotCutoff") == 0) {
-            tokens[t] = STATE_SPOT_CUTOFF; /* x component */
-         }
-
-         else {
-            return -1; /* invalid field name */
-         }
-      }
-
-      pos = _mesa_add_state_reference(paramList, tokens);
-      return pos;
-   }
-
-   return 1;
-}
-
-
-/**
- * Unroll the named built-in uniform variable into a sequence of state
- * vars in the given parameter list.
- */
-static GLint
-alloc_state_var_array(const slang_variable *var,
-                      struct gl_program_parameter_list *paramList)
-{
-   gl_state_index tokens[STATE_LENGTH];
-   GLuint i;
-   GLint pos;
-
-   /* Initialize the state tokens array.  This is very important.
-    * When we call _mesa_add_state_reference() it'll searches the parameter
-    * list to see if the given statevar token sequence is already present.
-    * This is normally a good thing since it prevents redundant values in the
-    * constant buffer.
-    *
-    * But when we're building arrays of state this can be bad.  For example,
-    * consider this fragment of GLSL code:
-    *   foo = gl_LightSource[3].diffuse;
-    *   ...
-    *   bar = gl_LightSource[i].diffuse;
-    *
-    * When we unroll the gl_LightSource array (for "bar") we want to re-emit
-    * gl_LightSource[3].diffuse and not re-use the first instance (from "foo")
-    * since that would upset the array layout.  We handle this situation by
-    * setting the last token in the state var token array to the special
-    * value STATE_ARRAY.
-    * This token will only be set for array state.  We can hijack the last
-    * element in the array for this since it's never used for light, clipplane
-    * or texture env array state.
-    */
-   for (i = 0; i < STATE_LENGTH; i++)
-      tokens[i] = 0;
-   tokens[STATE_LENGTH - 1] = STATE_ARRAY;
-
-   pos = emit_statevars(var->a_name, var->array_len, &var->type.specifier,
-                        tokens, paramList);
-
-   return pos;
-}
-
-
-
-/**
- * Allocate storage for a pre-defined uniform (a GL state variable).
- * As a memory-saving optimization, we try to only allocate storage for
- * state vars that are actually used.
- *
- * Arrays such as gl_LightSource are handled specially.  For an expression
- * like "gl_LightSource[2].diffuse", we can allocate a single uniform/constant
- * slot and return the index.  In this case, we return direct=TRUE.
- *
- * Buf for something like "gl_LightSource[i].diffuse" we don't know the value
- * of 'i' at compile time so we need to "unroll" the gl_LightSource array
- * into a consecutive sequence of uniform/constant slots so it can be indexed
- * at runtime.  In this case, we return direct=FALSE.
- *
- * Currently, all pre-defined uniforms are in one of these forms:
- *   var
- *   var[i]
- *   var.field
- *   var[i].field
- *   var[i][j]
- *
- * \return -1 upon error, else position in paramList of the state variable/data
- */
-GLint
-_slang_alloc_statevar(slang_ir_node *n,
-                      struct gl_program_parameter_list *paramList,
-                      GLboolean *direct)
-{
-   slang_ir_node *n0 = n;
-   const char *field = NULL;
-   GLint index1 = -1, index2 = -1;
-   GLuint swizzle;
-
-   *direct = GL_TRUE;
-
-   if (n->Opcode == IR_FIELD) {
-      field = n->Field;
-      n = n->Children[0];
-   }
-
-   if (n->Opcode == IR_ELEMENT) {
-      if (n->Children[1]->Opcode == IR_FLOAT) {
-         index1 = (GLint) n->Children[1]->Value[0];
-      }
-      else {
-         *direct = GL_FALSE;
-      }
-      n = n->Children[0];
-   }
-
-   if (n->Opcode == IR_ELEMENT) {
-      /* XXX can only handle constant indexes for now */
-      if (n->Children[1]->Opcode == IR_FLOAT) {
-         /* two-dimensional array index: mat[i][j] */
-         index2 = index1;
-         index1 = (GLint) n->Children[1]->Value[0];
-      }
-      else {
-         *direct = GL_FALSE;
-      }
-      n = n->Children[0];
-   }
-
-   assert(n->Opcode == IR_VAR);
-
-   if (*direct) {
-      const char *var = (const char *) n->Var->a_name;
-      GLint pos =
-         lookup_statevar(var, index1, index2, field, &swizzle, paramList);
-      if (pos >= 0) {
-         /* newly resolved storage for the statevar/constant/uniform */
-         n0->Store->File = PROGRAM_STATE_VAR;
-         n0->Store->Index = pos;
-         n0->Store->Swizzle = swizzle;
-         n0->Store->Parent = NULL;
-         return pos;
-      }
-   }
-
-   *direct = GL_FALSE;
-   return alloc_state_var_array(n->Var, paramList);
-}
-
-
-
-
-#define SWIZZLE_ZWWW MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W)
-
-
-/** Predefined shader inputs */
-struct input_info
-{
-   const char *Name;
-   GLuint Attrib;
-   GLenum Type;
-   GLuint Swizzle;
-   GLboolean Array;
-};
-
-/** Predefined vertex shader inputs/attributes */
-static const struct input_info vertInputs[] = {
-   { "gl_Vertex", VERT_ATTRIB_POS, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_Normal", VERT_ATTRIB_NORMAL, GL_FLOAT_VEC3, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_Color", VERT_ATTRIB_COLOR0, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_SecondaryColor", VERT_ATTRIB_COLOR1, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_FogCoord", VERT_ATTRIB_FOG, GL_FLOAT, SWIZZLE_XXXX, GL_FALSE },
-   { "gl_MultiTexCoord0", VERT_ATTRIB_TEX0, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_MultiTexCoord1", VERT_ATTRIB_TEX1, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_MultiTexCoord2", VERT_ATTRIB_TEX2, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_MultiTexCoord3", VERT_ATTRIB_TEX3, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_MultiTexCoord4", VERT_ATTRIB_TEX4, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_MultiTexCoord5", VERT_ATTRIB_TEX5, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_MultiTexCoord6", VERT_ATTRIB_TEX6, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_MultiTexCoord7", VERT_ATTRIB_TEX7, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE }
-};
-
-static const struct input_info geomInputs[] = {
-   { "gl_PrimitiveIDIn", GEOM_ATTRIB_PRIMITIVE_ID, GL_FLOAT, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_FrontColorIn", GEOM_ATTRIB_COLOR0, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_TRUE },
-   { "gl_BackColorIn", GEOM_ATTRIB_COLOR1, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_TRUE },
-   { "gl_FrontSecondaryColorIn", GEOM_ATTRIB_SECONDARY_COLOR0, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_TRUE },
-   { "gl_BackSecondaryColorIn", GEOM_ATTRIB_SECONDARY_COLOR1, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_TRUE },
-   { "gl_TexCoordIn", GEOM_ATTRIB_TEX_COORD, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_TRUE },
-   { "gl_FogFragCoordIn", GEOM_ATTRIB_FOG_FRAG_COORD, GL_FLOAT, SWIZZLE_NOOP, GL_TRUE },
-   { "gl_PositionIn", GEOM_ATTRIB_POSITION, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_TRUE },
-   { "gl_ClipVertexIn", GEOM_ATTRIB_CLIP_VERTEX, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_TRUE },
-   { "gl_PointSizeIn", GEOM_ATTRIB_POINT_SIZE, GL_FLOAT, SWIZZLE_NOOP, GL_TRUE }
-};
-
-/** Predefined fragment shader inputs */
-static const struct input_info fragInputs[] = {
-   { "gl_FragCoord", FRAG_ATTRIB_WPOS, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_Color", FRAG_ATTRIB_COL0, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_SecondaryColor", FRAG_ATTRIB_COL1, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_TexCoord", FRAG_ATTRIB_TEX0, GL_FLOAT_VEC4, SWIZZLE_NOOP, GL_FALSE },
-   { "gl_FogFragCoord", FRAG_ATTRIB_FOGC, GL_FLOAT, SWIZZLE_XXXX, GL_FALSE },
-   { "gl_FrontFacing", FRAG_ATTRIB_FACE, GL_FLOAT, SWIZZLE_XXXX, GL_FALSE },
-   { "gl_PointCoord", FRAG_ATTRIB_PNTC, GL_FLOAT_VEC2, SWIZZLE_XYZW, GL_FALSE }
-};
-
-
-/**
- * Return the VERT_ATTRIB_* or FRAG_ATTRIB_* value that corresponds to
- * a vertex or fragment program input variable.  Return -1 if the input
- * name is invalid.
- * XXX return size too
- */
-GLint
-_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut,
-                   GLboolean *is_array)
-{
-   const struct input_info *inputs;
-   GLuint i, n;
-
-   switch (target) {
-   case GL_VERTEX_PROGRAM_ARB:
-      inputs = vertInputs;
-      n = Elements(vertInputs);
-      break;
-   case GL_FRAGMENT_PROGRAM_ARB:
-      inputs = fragInputs;
-      n = Elements(fragInputs);
-      break;
-   case MESA_GEOMETRY_PROGRAM:
-      inputs = geomInputs;
-      n = Elements(geomInputs);
-      break;
-   default:
-      _mesa_problem(NULL, "bad target in _slang_input_index");
-      return -1;
-   }
-
-   ASSERT(MAX_TEXTURE_COORD_UNITS == 8); /* if this fails, fix vertInputs above */
-
-   for (i = 0; i < n; i++) {
-      if (strcmp(inputs[i].Name, name) == 0) {
-         /* found */
-         *swizzleOut = inputs[i].Swizzle;
-         if (is_array)
-            *is_array = inputs[i].Array;
-         return inputs[i].Attrib;
-      }
-   }
-   return -1;
-}
-
-
-/**
- * Return name of the given vertex attribute (VERT_ATTRIB_x).
- */
-const char *
-_slang_vert_attrib_name(GLuint attrib)
-{
-   GLuint i;
-   assert(attrib < VERT_ATTRIB_GENERIC0);
-   for (i = 0; Elements(vertInputs); i++) {
-      if (vertInputs[i].Attrib == attrib)
-         return vertInputs[i].Name;
-   }
-   return NULL;
-}
-
-
-/**
- * Return type (GL_FLOAT, GL_FLOAT_VEC2, etc) of the given vertex
- * attribute (VERT_ATTRIB_x).
- */
-GLenum
-_slang_vert_attrib_type(GLuint attrib)
-{
-   GLuint i;
-   assert(attrib < VERT_ATTRIB_GENERIC0);
-   for (i = 0; Elements(vertInputs); i++) {
-      if (vertInputs[i].Attrib == attrib)
-         return vertInputs[i].Type;
-   }
-   return GL_NONE;
-}
-
-
-
-
-
-/** Predefined shader output info */
-struct output_info
-{
-   const char *Name;
-   GLuint Attrib;
-   GLenum Type;
-};
-
-/** Predefined vertex shader outputs */
-static const struct output_info vertOutputs[] = {
-   { "gl_Position", VERT_RESULT_HPOS, GL_FLOAT_VEC4 },
-   { "gl_FrontColor", VERT_RESULT_COL0, GL_FLOAT_VEC4 },
-   { "gl_BackColor", VERT_RESULT_BFC0, GL_FLOAT_VEC4 },
-   { "gl_FrontSecondaryColor", VERT_RESULT_COL1, GL_FLOAT_VEC4 },
-   { "gl_BackSecondaryColor", VERT_RESULT_BFC1, GL_FLOAT_VEC4 },
-   { "gl_TexCoord", VERT_RESULT_TEX0, GL_FLOAT_VEC4 },
-   { "gl_FogFragCoord", VERT_RESULT_FOGC, GL_FLOAT },
-   { "gl_PointSize", VERT_RESULT_PSIZ, GL_FLOAT }
-};
-
-/** Predefined geometry shader outputs */
-static const struct output_info geomOutputs[] = {
-   { "gl_Position", GEOM_RESULT_POS, GL_FLOAT_VEC4 },
-   { "gl_FrontColor", GEOM_RESULT_COL0, GL_FLOAT_VEC4  },
-   { "gl_BackColor", GEOM_RESULT_COL1, GL_FLOAT_VEC4  },
-   { "gl_FrontSecondaryColor", GEOM_RESULT_SCOL0, GL_FLOAT_VEC4  },
-   { "gl_BackSecondaryColor", GEOM_RESULT_SCOL1, GL_FLOAT_VEC4  },
-   { "gl_TexCoord", GEOM_RESULT_TEX0, GL_FLOAT_VEC4  },
-   { "gl_FogFragCoord", GEOM_RESULT_FOGC, GL_FLOAT  },
-   { "gl_ClipVertex", GEOM_RESULT_CLPV, GL_FLOAT_VEC4  },
-   { "gl_PointSize", GEOM_RESULT_PSIZ, GL_FLOAT  },
-   { "gl_PrimitiveID", GEOM_RESULT_PRID, GL_FLOAT  },
-   { "gl_Layer", GEOM_RESULT_LAYR, GL_FLOAT  }
-};
-
-/** Predefined fragment shader outputs */
-static const struct output_info fragOutputs[] = {
-   { "gl_FragColor", FRAG_RESULT_COLOR, GL_FLOAT_VEC4 },
-   { "gl_FragDepth", FRAG_RESULT_DEPTH, GL_FLOAT },
-   { "gl_FragData", FRAG_RESULT_DATA0, GL_FLOAT_VEC4 }
-};
-
-
-/**
- * Return the VERT_RESULT_*, GEOM_RESULT_* or FRAG_RESULT_* value that corresponds
- * to a vertex or fragment program output variable.  Return -1 for an invalid
- * output name.
- */
-GLint
-_slang_output_index(const char *name, GLenum target)
-{
-   const struct output_info *outputs;
-   GLuint i, n;
-
-   switch (target) {
-   case GL_VERTEX_PROGRAM_ARB:
-      outputs = vertOutputs;
-      n = Elements(vertOutputs);
-      break;
-   case GL_FRAGMENT_PROGRAM_ARB:
-      outputs = fragOutputs;
-      n = Elements(fragOutputs);
-      break;
-   case MESA_GEOMETRY_PROGRAM:
-      outputs = geomOutputs;
-      n = Elements(geomOutputs);
-      break;
-   default:
-      _mesa_problem(NULL, "bad target in _slang_output_index");
-      return -1;
-   }
-
-   for (i = 0; i < n; i++) {
-      if (strcmp(outputs[i].Name, name) == 0) {
-         /* found */
-         return outputs[i].Attrib;
-      }
-   }
-   return -1;
-}
-
-
-/**
- * Given a VERT_RESULT_x index, return the corresponding string name.
- */
-const char *
-_slang_vertex_output_name(gl_vert_result index)
-{
-   if (index < Elements(vertOutputs))
-      return vertOutputs[index].Name;
-   else
-      return NULL;
-}
-
-
-/**
- * Given a GEOM_RESULT_x index, return the corresponding string name.
- */
-const char *
-_slang_geometry_output_name(gl_geom_result index)
-{
-   if (index < Elements(geomOutputs))
-      return geomOutputs[index].Name;
-   else
-      return NULL;
-}
-
-
-/**
- * Given a FRAG_RESULT_x index, return the corresponding string name.
- */
-const char *
-_slang_fragment_output_name(gl_frag_result index)
-{
-   if (index < Elements(fragOutputs))
-      return fragOutputs[index].Name;
-   else
-      return NULL;
-}
-
-
-/**
- * Given a VERT_RESULT_x index, return the corresponding varying
- * var's datatype.
- */
-GLenum
-_slang_vertex_output_type(gl_vert_result index)
-{
-   if (index < Elements(vertOutputs))
-      return vertOutputs[index].Type;
-   else
-      return GL_NONE;
-}
diff --git a/src/mesa/slang/slang_builtin.h b/src/mesa/slang/slang_builtin.h
deleted file mode 100644 (file)
index dc92f83..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef SLANG_BUILTIN_H
-#define SLANG_BUILTIN_H
-
-#include "main/glheader.h"
-#include "main/mtypes.h"
-#include "slang_ir.h"
-
-
-extern GLint
-_slang_alloc_statevar(slang_ir_node *n,
-                      struct gl_program_parameter_list *paramList,
-                      GLboolean *direct);
-
-
-extern GLint
-_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut,
-                   GLboolean *is_array);
-
-extern GLint
-_slang_output_index(const char *name, GLenum target);
-
-
-extern const char *
-_slang_vert_attrib_name(GLuint attrib);
-
-extern GLenum
-_slang_vert_attrib_type(GLuint attrib);
-
-
-const char *
-_slang_vertex_output_name(gl_vert_result index);
-
-const char *
-_slang_fragment_output_name(gl_frag_result index);
-
-const char *
-_slang_geometry_output_name(gl_geom_result index);
-
-GLenum
-_slang_vertex_output_type(gl_vert_result index);
-
-
-#endif /* SLANG_BUILTIN_H */
diff --git a/src/mesa/slang/slang_codegen.c b/src/mesa/slang/slang_codegen.c
deleted file mode 100644 (file)
index 95787e4..0000000
+++ /dev/null
@@ -1,5410 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
- * Copyright (C) 2008 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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_codegen.c
- * Generate IR tree from AST.
- * \author Brian Paul
- */
-
-
-/***
- *** NOTES:
- *** The new_() functions return a new instance of a simple IR node.
- *** The gen_() functions generate larger IR trees from the simple nodes.
- ***/
-
-
-
-#include "main/imports.h"
-#include "main/macros.h"
-#include "main/mtypes.h"
-#include "program/program.h"
-#include "program/prog_instruction.h"
-#include "program/prog_parameter.h"
-#include "program/prog_print.h"
-#include "program/prog_statevars.h"
-#include "slang_typeinfo.h"
-#include "slang_builtin.h"
-#include "slang_codegen.h"
-#include "slang_compile.h"
-#include "slang_label.h"
-#include "slang_mem.h"
-#include "slang_simplify.h"
-#include "slang_emit.h"
-#include "slang_vartable.h"
-#include "slang_ir.h"
-#include "slang_print.h"
-
-
-/** Max iterations to unroll */
-const GLuint MAX_FOR_LOOP_UNROLL_ITERATIONS = 32;
-
-/** Max for-loop body size (in slang operations) to unroll */
-const GLuint MAX_FOR_LOOP_UNROLL_BODY_SIZE = 50;
-
-/** Max for-loop body complexity to unroll.
- * We'll compute complexity as the product of the number of iterations
- * and the size of the body.  So long-ish loops with very simple bodies
- * can be unrolled, as well as short loops with larger bodies.
- */
-const GLuint MAX_FOR_LOOP_UNROLL_COMPLEXITY = 256;
-
-
-
-static slang_ir_node *
-_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper);
-
-static void
-slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
-                 GLuint substCount, slang_variable **substOld,
-                slang_operation **substNew, GLboolean isLHS);
-
-
-/**
- * Retrieves type information about an operation.
- * Returns GL_TRUE on success.
- * Returns GL_FALSE otherwise.
- */
-static GLboolean
-typeof_operation(const struct slang_assemble_ctx_ *A,
-                 slang_operation *op,
-                 slang_typeinfo *ti)
-{
-   return _slang_typeof_operation(op, &A->space, ti, A->atoms, A->log);
-}
-
-
-static GLboolean
-is_sampler_type(const slang_fully_specified_type *t)
-{
-   switch (t->specifier.type) {
-   case SLANG_SPEC_SAMPLER_1D:
-   case SLANG_SPEC_SAMPLER_2D:
-   case SLANG_SPEC_SAMPLER_3D:
-   case SLANG_SPEC_SAMPLER_CUBE:
-   case SLANG_SPEC_SAMPLER_1D_SHADOW:
-   case SLANG_SPEC_SAMPLER_2D_SHADOW:
-   case SLANG_SPEC_SAMPLER_RECT:
-   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
-   case SLANG_SPEC_SAMPLER_1D_ARRAY:
-   case SLANG_SPEC_SAMPLER_2D_ARRAY:
-   case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
-   case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
-      return GL_TRUE;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Return the offset (in floats or ints) of the named field within
- * the given struct.  Return -1 if field not found.
- * If field is NULL, return the size of the struct instead.
- */
-static GLint
-_slang_field_offset(const slang_type_specifier *spec, slang_atom field)
-{
-   GLint offset = 0;
-   GLuint i;
-   for (i = 0; i < spec->_struct->fields->num_variables; i++) {
-      const slang_variable *v = spec->_struct->fields->variables[i];
-      const GLuint sz = _slang_sizeof_type_specifier(&v->type.specifier);
-      if (sz > 1) {
-         /* types larger than 1 float are register (4-float) aligned */
-         offset = (offset + 3) & ~3;
-      }
-      if (field && v->a_name == field) {
-         return offset;
-      }
-      offset += sz;
-   }
-   if (field)
-      return -1; /* field not found */
-   else
-      return offset;  /* struct size */
-}
-
-
-/**
- * Return the size (in floats) of the given type specifier.
- * If the size is greater than 4, the size should be a multiple of 4
- * so that the correct number of 4-float registers are allocated.
- * For example, a mat3x2 is size 12 because we want to store the
- * 3 columns in 3 float[4] registers.
- */
-GLuint
-_slang_sizeof_type_specifier(const slang_type_specifier *spec)
-{
-   GLuint sz;
-   switch (spec->type) {
-   case SLANG_SPEC_VOID:
-      sz = 0;
-      break;
-   case SLANG_SPEC_BOOL:
-      sz = 1;
-      break;
-   case SLANG_SPEC_BVEC2:
-      sz = 2;
-      break;
-   case SLANG_SPEC_BVEC3:
-      sz = 3;
-      break;
-   case SLANG_SPEC_BVEC4:
-      sz = 4;
-      break;
-   case SLANG_SPEC_INT:
-      sz = 1;
-      break;
-   case SLANG_SPEC_IVEC2:
-      sz = 2;
-      break;
-   case SLANG_SPEC_IVEC3:
-      sz = 3;
-      break;
-   case SLANG_SPEC_IVEC4:
-      sz = 4;
-      break;
-   case SLANG_SPEC_FLOAT:
-      sz = 1;
-      break;
-   case SLANG_SPEC_VEC2:
-      sz = 2;
-      break;
-   case SLANG_SPEC_VEC3:
-      sz = 3;
-      break;
-   case SLANG_SPEC_VEC4:
-      sz = 4;
-      break;
-   case SLANG_SPEC_MAT2:
-      sz = 2 * 4; /* 2 columns (regs) */
-      break;
-   case SLANG_SPEC_MAT3:
-      sz = 3 * 4;
-      break;
-   case SLANG_SPEC_MAT4:
-      sz = 4 * 4;
-      break;
-   case SLANG_SPEC_MAT23:
-      sz = 2 * 4; /* 2 columns (regs) */
-      break;
-   case SLANG_SPEC_MAT32:
-      sz = 3 * 4; /* 3 columns (regs) */
-      break;
-   case SLANG_SPEC_MAT24:
-      sz = 2 * 4;
-      break;
-   case SLANG_SPEC_MAT42:
-      sz = 4 * 4; /* 4 columns (regs) */
-      break;
-   case SLANG_SPEC_MAT34:
-      sz = 3 * 4;
-      break;
-   case SLANG_SPEC_MAT43:
-      sz = 4 * 4; /* 4 columns (regs) */
-      break;
-   case SLANG_SPEC_SAMPLER_1D:
-   case SLANG_SPEC_SAMPLER_2D:
-   case SLANG_SPEC_SAMPLER_3D:
-   case SLANG_SPEC_SAMPLER_CUBE:
-   case SLANG_SPEC_SAMPLER_1D_SHADOW:
-   case SLANG_SPEC_SAMPLER_2D_SHADOW:
-   case SLANG_SPEC_SAMPLER_RECT:
-   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
-   case SLANG_SPEC_SAMPLER_1D_ARRAY:
-   case SLANG_SPEC_SAMPLER_2D_ARRAY:
-   case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
-   case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
-      sz = 1; /* a sampler is basically just an integer index */
-      break;
-   case SLANG_SPEC_STRUCT:
-      sz = _slang_field_offset(spec, 0); /* special use */
-      if (sz == 1) {
-         /* 1-float structs are actually troublesome to deal with since they
-          * might get placed at R.x, R.y, R.z or R.z.  Return size=2 to
-          * ensure the object is placed at R.x
-          */
-         sz = 2;
-      }
-      else if (sz > 4) {
-         sz = (sz + 3) & ~0x3; /* round up to multiple of four */
-      }
-      break;
-   case SLANG_SPEC_ARRAY:
-      sz = _slang_sizeof_type_specifier(spec->_array);
-      break;
-   default:
-      _mesa_problem(NULL, "Unexpected type in _slang_sizeof_type_specifier()");
-      sz = 0;
-   }
-
-   if (sz > 4) {
-      /* if size is > 4, it should be a multiple of four */
-      assert((sz & 0x3) == 0);
-   }
-   return sz;
-}
-
-
-/**
- * Query variable/array length (number of elements).
- * This is slightly non-trivial because there are two ways to express
- * arrays: "float x[3]" vs. "float[3] x".
- * \return the length of the array for the given variable, or 0 if not an array
- */
-static GLint
-_slang_array_length(const slang_variable *var)
-{
-   if (var->type.array_len > 0) {
-      /* Ex: float[4] x; */
-      return var->type.array_len;
-   }
-   if (var->array_len > 0) {
-      /* Ex: float x[4]; */
-      return var->array_len;
-   }
-   return 0;
-}
-
-
-/**
- * Compute total size of array give size of element, number of elements.
- * \return size in floats
- */
-static GLint
-_slang_array_size(GLint elemSize, GLint arrayLen)
-{
-   GLint total;
-   assert(elemSize > 0);
-   if (arrayLen > 1) {
-      /* round up base type to multiple of 4 */
-      total = ((elemSize + 3) & ~0x3) * MAX2(arrayLen, 1);
-   }
-   else {
-      total = elemSize;
-   }
-   return total;
-}
-
-
-/**
- * Return the TEXTURE_*_INDEX value that corresponds to a sampler type,
- * or -1 if the type is not a sampler.
- */
-static GLint
-sampler_to_texture_index(const slang_type_specifier_type type)
-{
-   switch (type) {
-   case SLANG_SPEC_SAMPLER_1D:
-      return TEXTURE_1D_INDEX;
-   case SLANG_SPEC_SAMPLER_2D:
-      return TEXTURE_2D_INDEX;
-   case SLANG_SPEC_SAMPLER_3D:
-      return TEXTURE_3D_INDEX;
-   case SLANG_SPEC_SAMPLER_CUBE:
-      return TEXTURE_CUBE_INDEX;
-   case SLANG_SPEC_SAMPLER_1D_SHADOW:
-      return TEXTURE_1D_INDEX; /* XXX fix */
-   case SLANG_SPEC_SAMPLER_2D_SHADOW:
-      return TEXTURE_2D_INDEX; /* XXX fix */
-   case SLANG_SPEC_SAMPLER_RECT:
-      return TEXTURE_RECT_INDEX;
-   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
-      return TEXTURE_RECT_INDEX; /* XXX fix */
-   case SLANG_SPEC_SAMPLER_1D_ARRAY:
-      return TEXTURE_1D_ARRAY_INDEX;
-   case SLANG_SPEC_SAMPLER_2D_ARRAY:
-      return TEXTURE_2D_ARRAY_INDEX;
-   case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
-      return TEXTURE_1D_ARRAY_INDEX;
-   case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
-      return TEXTURE_2D_ARRAY_INDEX;
-   default:
-      return -1;
-   }
-}
-
-
-/** helper to build a SLANG_OPER_IDENTIFIER node */
-static void
-slang_operation_identifier(slang_operation *oper,
-                           slang_assemble_ctx *A,
-                           const char *name)
-{
-   oper->type = SLANG_OPER_IDENTIFIER;
-   oper->a_id = slang_atom_pool_atom(A->atoms, name);
-}
-
-
-/**
- * Called when we begin code/IR generation for a new while/do/for loop.
- */
-static void
-push_loop(slang_assemble_ctx *A, slang_operation *loopOper, slang_ir_node *loopIR)
-{
-   A->LoopOperStack[A->LoopDepth] = loopOper;
-   A->LoopIRStack[A->LoopDepth] = loopIR;
-   A->LoopDepth++;
-}
-
-
-/**
- * Called when we end code/IR generation for a new while/do/for loop.
- */
-static void
-pop_loop(slang_assemble_ctx *A)
-{
-   assert(A->LoopDepth > 0);
-   A->LoopDepth--;
-}
-
-
-/**
- * Return pointer to slang_operation for the loop we're currently inside,
- * or NULL if not in a loop.
- */
-static const slang_operation *
-current_loop_oper(const slang_assemble_ctx *A)
-{
-   if (A->LoopDepth > 0)
-      return A->LoopOperStack[A->LoopDepth - 1];
-   else
-      return NULL;
-}
-
-
-/**
- * Return pointer to slang_ir_node for the loop we're currently inside,
- * or NULL if not in a loop.
- */
-static slang_ir_node *
-current_loop_ir(const slang_assemble_ctx *A)
-{
-   if (A->LoopDepth > 0)
-      return A->LoopIRStack[A->LoopDepth - 1];
-   else
-      return NULL;
-}
-
-
-/**********************************************************************/
-
-
-/**
- * Map "_asm foo" to IR_FOO, etc.
- */
-typedef struct
-{
-   const char *Name;
-   slang_ir_opcode Opcode;
-   GLuint HaveRetValue, NumParams;
-} slang_asm_info;
-
-
-static slang_asm_info AsmInfo[] = {
-   /* vec4 binary op */
-   { "vec4_add", IR_ADD, 1, 2 },
-   { "vec4_subtract", IR_SUB, 1, 2 },
-   { "vec4_multiply", IR_MUL, 1, 2 },
-   { "vec4_dot", IR_DOT4, 1, 2 },
-   { "vec3_dot", IR_DOT3, 1, 2 },
-   { "vec2_dot", IR_DOT2, 1, 2 },
-   { "vec3_nrm", IR_NRM3, 1, 1 },
-   { "vec4_nrm", IR_NRM4, 1, 1 },
-   { "vec3_cross", IR_CROSS, 1, 2 },
-   { "vec4_lrp", IR_LRP, 1, 3 },
-   { "vec4_min", IR_MIN, 1, 2 },
-   { "vec4_max", IR_MAX, 1, 2 },
-   { "vec4_cmp", IR_CMP, 1, 3 },
-   { "vec4_clamp", IR_CLAMP, 1, 3 },
-   { "vec4_seq", IR_SEQUAL, 1, 2 },
-   { "vec4_sne", IR_SNEQUAL, 1, 2 },
-   { "vec4_sge", IR_SGE, 1, 2 },
-   { "vec4_sgt", IR_SGT, 1, 2 },
-   { "vec4_sle", IR_SLE, 1, 2 },
-   { "vec4_slt", IR_SLT, 1, 2 },
-   /* vec4 unary */
-   { "vec4_move", IR_MOVE, 1, 1 },
-   { "vec4_floor", IR_FLOOR, 1, 1 },
-   { "vec4_frac", IR_FRAC, 1, 1 },
-   { "vec4_abs", IR_ABS, 1, 1 },
-   { "vec4_negate", IR_NEG, 1, 1 },
-   { "vec4_ddx", IR_DDX, 1, 1 },
-   { "vec4_ddy", IR_DDY, 1, 1 },
-   /* float binary op */
-   { "float_power", IR_POW, 1, 2 },
-   /* texture / sampler */
-   { "vec4_tex_1d", IR_TEX, 1, 2 },
-   { "vec4_tex_1d_bias", IR_TEXB, 1, 2 },  /* 1d w/ bias */
-   { "vec4_tex_1d_proj", IR_TEXP, 1, 2 },  /* 1d w/ projection */
-   { "vec4_tex_2d", IR_TEX, 1, 2 },
-   { "vec4_tex_2d_bias", IR_TEXB, 1, 2 },  /* 2d w/ bias */
-   { "vec4_tex_2d_proj", IR_TEXP, 1, 2 },  /* 2d w/ projection */
-   { "vec4_tex_3d", IR_TEX, 1, 2 },
-   { "vec4_tex_3d_bias", IR_TEXB, 1, 2 },  /* 3d w/ bias */
-   { "vec4_tex_3d_proj", IR_TEXP, 1, 2 },  /* 3d w/ projection */
-   { "vec4_tex_cube", IR_TEX, 1, 2 },      /* cubemap */
-   { "vec4_tex_rect", IR_TEX, 1, 2 },      /* rectangle */
-   { "vec4_tex_rect_bias", IR_TEX, 1, 2 }, /* rectangle w/ projection */
-   { "vec4_tex_1d_array", IR_TEX, 1, 2 },
-   { "vec4_tex_1d_array_bias", IR_TEXB, 1, 2 },
-   { "vec4_tex_1d_array_shadow", IR_TEX, 1, 2 },
-   { "vec4_tex_1d_array_bias_shadow", IR_TEXB, 1, 2 },
-   { "vec4_tex_2d_array", IR_TEX, 1, 2 },
-   { "vec4_tex_2d_array_bias", IR_TEXB, 1, 2 },
-   { "vec4_tex_2d_array_shadow", IR_TEX, 1, 2 },
-   { "vec4_tex_2d_array_bias_shadow", IR_TEXB, 1, 2 },
-
-   /* texture / sampler but with shadow comparison */
-   { "vec4_tex_1d_shadow", IR_TEX_SH, 1, 2 },
-   { "vec4_tex_1d_bias_shadow", IR_TEXB_SH, 1, 2 },
-   { "vec4_tex_1d_proj_shadow", IR_TEXP_SH, 1, 2 },
-   { "vec4_tex_2d_shadow", IR_TEX_SH, 1, 2 },
-   { "vec4_tex_2d_bias_shadow", IR_TEXB_SH, 1, 2 },
-   { "vec4_tex_2d_proj_shadow", IR_TEXP_SH, 1, 2 },
-   { "vec4_tex_rect_shadow", IR_TEX_SH, 1, 2 },
-   { "vec4_tex_rect_proj_shadow", IR_TEXP_SH, 1, 2 },
-
-   /* unary op */
-   { "ivec4_to_vec4", IR_I_TO_F, 1, 1 }, /* int[4] to float[4] */
-   { "vec4_to_ivec4", IR_F_TO_I, 1, 1 },  /* float[4] to int[4] */
-   { "float_exp", IR_EXP, 1, 1 },
-   { "float_exp2", IR_EXP2, 1, 1 },
-   { "float_log2", IR_LOG2, 1, 1 },
-   { "float_rsq", IR_RSQ, 1, 1 },
-   { "float_rcp", IR_RCP, 1, 1 },
-   { "float_sine", IR_SIN, 1, 1 },
-   { "float_cosine", IR_COS, 1, 1 },
-   { "float_noise1", IR_NOISE1, 1, 1},
-   { "float_noise2", IR_NOISE2, 1, 1},
-   { "float_noise3", IR_NOISE3, 1, 1},
-   { "float_noise4", IR_NOISE4, 1, 1},
-
-   { "emit_vertex", IR_EMIT_VERTEX, 0, 0},
-   { "end_primitive", IR_END_PRIMITIVE, 0, 0},
-
-   { NULL, IR_NOP, 0, 0 }
-};
-
-
-static slang_ir_node *
-new_node3(slang_ir_opcode op,
-          slang_ir_node *c0, slang_ir_node *c1, slang_ir_node *c2)
-{
-   slang_ir_node *n = (slang_ir_node *) _slang_alloc(sizeof(slang_ir_node));
-   if (n) {
-      n->Opcode = op;
-      n->Children[0] = c0;
-      n->Children[1] = c1;
-      n->Children[2] = c2;
-      n->InstLocation = -1;
-   }
-   return n;
-}
-
-static slang_ir_node *
-new_node2(slang_ir_opcode op, slang_ir_node *c0, slang_ir_node *c1)
-{
-   return new_node3(op, c0, c1, NULL);
-}
-
-static slang_ir_node *
-new_node1(slang_ir_opcode op, slang_ir_node *c0)
-{
-   return new_node3(op, c0, NULL, NULL);
-}
-
-static slang_ir_node *
-new_node0(slang_ir_opcode op)
-{
-   return new_node3(op, NULL, NULL, NULL);
-}
-
-
-/**
- * Create sequence of two nodes.
- */
-static slang_ir_node *
-new_seq(slang_ir_node *left, slang_ir_node *right)
-{
-   if (!left)
-      return right;
-   if (!right)
-      return left;
-   return new_node2(IR_SEQ, left, right);
-}
-
-static slang_ir_node *
-new_label(slang_label *label)
-{
-   slang_ir_node *n = new_node0(IR_LABEL);
-   assert(label);
-   if (n)
-      n->Label = label;
-   return n;
-}
-
-static slang_ir_node *
-new_float_literal(const float v[4], GLuint size)
-{
-   slang_ir_node *n = new_node0(IR_FLOAT);
-   assert(size <= 4);
-   COPY_4V(n->Value, v);
-   /* allocate a storage object, but compute actual location (Index) later */
-   n->Store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size);
-   return n;
-}
-
-
-static slang_ir_node *
-new_not(slang_ir_node *n)
-{
-   return new_node1(IR_NOT, n);
-}
-
-
-/**
- * Non-inlined function call.
- */
-static slang_ir_node *
-new_function_call(slang_ir_node *code, slang_label *name)
-{
-   slang_ir_node *n = new_node1(IR_CALL, code);
-   assert(name);
-   if (n)
-      n->Label = name;
-   return n;
-}
-
-
-/**
- * Unconditional jump.
- */
-static slang_ir_node *
-new_return(slang_label *dest)
-{
-   slang_ir_node *n = new_node0(IR_RETURN);
-   assert(dest);
-   if (n)
-      n->Label = dest;
-   return n;
-}
-
-
-static slang_ir_node *
-new_loop(slang_ir_node *body)
-{
-   return new_node1(IR_LOOP, body);
-}
-
-
-static slang_ir_node *
-new_break(slang_ir_node *loopNode)
-{
-   slang_ir_node *n = new_node0(IR_BREAK);
-   assert(loopNode);
-   assert(loopNode->Opcode == IR_LOOP);
-   if (n) {
-      /* insert this node at head of linked list of cont/break instructions */
-      n->List = loopNode->List;
-      loopNode->List = n;
-   }
-   return n;
-}
-
-
-/**
- * Make new IR_BREAK_IF_TRUE.
- */
-static slang_ir_node *
-new_break_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
-{
-   slang_ir_node *loopNode = current_loop_ir(A);
-   slang_ir_node *n;
-   assert(loopNode);
-   assert(loopNode->Opcode == IR_LOOP);
-   n = new_node1(IR_BREAK_IF_TRUE, cond);
-   if (n) {
-      /* insert this node at head of linked list of cont/break instructions */
-      n->List = loopNode->List;
-      loopNode->List = n;
-   }
-   return n;
-}
-
-
-/**
- * Make new IR_CONT_IF_TRUE node.
- */
-static slang_ir_node *
-new_cont_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
-{
-   slang_ir_node *loopNode = current_loop_ir(A);
-   slang_ir_node *n;
-   assert(loopNode);
-   assert(loopNode->Opcode == IR_LOOP);
-   n = new_node1(IR_CONT_IF_TRUE, cond);
-   if (n) {
-      n->Parent = loopNode; /* pointer to containing loop */
-      /* insert this node at head of linked list of cont/break instructions */
-      n->List = loopNode->List;
-      loopNode->List = n;
-   }
-   return n;
-}
-
-
-static slang_ir_node *
-new_cond(slang_ir_node *n)
-{
-   slang_ir_node *c = new_node1(IR_COND, n);
-   return c;
-}
-
-
-static slang_ir_node *
-new_if(slang_ir_node *cond, slang_ir_node *ifPart, slang_ir_node *elsePart)
-{
-   return new_node3(IR_IF, cond, ifPart, elsePart);
-}
-
-
-/**
- * New IR_VAR node - a reference to a previously declared variable.
- */
-static slang_ir_node *
-new_var(slang_assemble_ctx *A, slang_variable *var)
-{
-   slang_ir_node *n = new_node0(IR_VAR);
-   if (n) {
-      ASSERT(var);
-      ASSERT(var->store);
-      ASSERT(!n->Store);
-      ASSERT(!n->Var);
-
-      /* Set IR node's Var and Store pointers */
-      n->Var = var;
-      n->Store = var->store;
-   }
-   return n;
-}
-
-
-/**
- * Check if the given function is really just a wrapper for a
- * basic assembly instruction.
- */
-static GLboolean
-slang_is_asm_function(const slang_function *fun)
-{
-   if (fun->body->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE &&
-       fun->body->num_children == 1 &&
-       fun->body->children[0].type == SLANG_OPER_ASM) {
-      return GL_TRUE;
-   }
-   return GL_FALSE;
-}
-
-
-static GLboolean
-_slang_is_noop(const slang_operation *oper)
-{
-   if (!oper ||
-       oper->type == SLANG_OPER_VOID ||
-       (oper->num_children == 1 && oper->children[0].type == SLANG_OPER_VOID))
-      return GL_TRUE;
-   else
-      return GL_FALSE;
-}
-
-
-/**
- * Recursively search tree for a node of the given type.
- */
-#if 0
-static slang_operation *
-_slang_find_node_type(slang_operation *oper, slang_operation_type type)
-{
-   GLuint i;
-   if (oper->type == type)
-      return oper;
-   for (i = 0; i < oper->num_children; i++) {
-      slang_operation *p = _slang_find_node_type(&oper->children[i], type);
-      if (p)
-         return p;
-   }
-   return NULL;
-}
-#endif
-
-
-/**
- * Count the number of operations of the given time rooted at 'oper'.
- */
-static GLuint
-_slang_count_node_type(const slang_operation *oper, slang_operation_type type)
-{
-   GLuint i, count = 0;
-   if (oper->type == type) {
-      return 1;
-   }
-   for (i = 0; i < oper->num_children; i++) {
-      count += _slang_count_node_type(&oper->children[i], type);
-   }
-   return count;
-}
-
-
-/**
- * Check if the 'return' statement found under 'oper' is a "tail return"
- * that can be no-op'd.  For example:
- *
- * void func(void)
- * {
- *    .. do something ..
- *    return;   // this is a no-op
- * }
- *
- * This is used when determining if a function can be inlined.  If the
- * 'return' is not the last statement, we can't inline the function since
- * we still need the semantic behaviour of the 'return' but we don't want
- * to accidentally return from the _calling_ function.  We'd need to use an
- * unconditional branch, but we don't have such a GPU instruction (not
- * always, at least).
- */
-static GLboolean
-_slang_is_tail_return(const slang_operation *oper)
-{
-   GLuint k = oper->num_children;
-
-   while (k > 0) {
-      const slang_operation *last = &oper->children[k - 1];
-      if (last->type == SLANG_OPER_RETURN)
-         return GL_TRUE;
-      else if (last->type == SLANG_OPER_IDENTIFIER ||
-               last->type == SLANG_OPER_LABEL)
-         k--; /* try prev child */
-      else if (last->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE ||
-               last->type == SLANG_OPER_BLOCK_NEW_SCOPE)
-         /* try sub-children */
-         return _slang_is_tail_return(last);
-      else
-         break;
-   }
-
-   return GL_FALSE;
-}
-
-
-/**
- * Generate a variable declaration opeartion.
- * I.e.: generate AST code for "bool flag = false;"
- */
-static void
-slang_generate_declaration(slang_assemble_ctx *A,
-                           slang_variable_scope *scope,
-                           slang_operation *decl,
-                           slang_type_specifier_type type,
-                           const char *name,
-                           GLint initValue)
-{
-   slang_variable *var;
-
-   assert(type == SLANG_SPEC_BOOL ||
-          type == SLANG_SPEC_INT);
-
-   decl->type = SLANG_OPER_VARIABLE_DECL;
-
-   var = slang_variable_scope_grow(scope);
-
-   slang_fully_specified_type_construct(&var->type);
-
-   var->type.specifier.type = type;
-   var->a_name = slang_atom_pool_atom(A->atoms, name);
-   decl->a_id = var->a_name;
-   var->initializer = slang_operation_new(1);
-   slang_operation_literal_bool(var->initializer, initValue);
-}
-
-
-static void
-slang_resolve_variable(slang_operation *oper)
-{
-   if (oper->type == SLANG_OPER_IDENTIFIER && !oper->var) {
-      oper->var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
-   }
-}
-
-
-/**
- * Rewrite AST code for "return expression;".
- *
- * We return values from functions by assinging the returned value to
- * the hidden __retVal variable which is an extra 'out' parameter we add
- * to the function signature.
- * This code basically converts "return expr;" into "__retVal = expr; return;"
- *
- * \return the new AST code.
- */
-static slang_operation *
-gen_return_with_expression(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_operation *blockOper, *assignOper;
-
-   assert(oper->type == SLANG_OPER_RETURN);
-
-   if (A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) {
-      slang_info_log_error(A->log, "illegal return expression");
-      return NULL;
-   }
-
-   blockOper = slang_operation_new(1);
-   blockOper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
-   blockOper->locals->outer_scope = oper->locals->outer_scope;
-   slang_operation_add_children(blockOper, 2);
-
-   if (A->UseReturnFlag) {
-      /* Emit:
-       *    {
-       *       if (__notRetFlag)
-       *          __retVal = expr;
-       *       __notRetFlag = 0;
-       *    }
-       */
-      {
-         slang_operation *ifOper = slang_oper_child(blockOper, 0);
-         ifOper->type = SLANG_OPER_IF;
-         slang_operation_add_children(ifOper, 3);
-         {
-            slang_operation *cond = slang_oper_child(ifOper, 0);
-            cond->type = SLANG_OPER_IDENTIFIER;
-            cond->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
-         }
-         {
-            slang_operation *elseOper = slang_oper_child(ifOper, 2);
-            elseOper->type = SLANG_OPER_VOID;
-         }
-         assignOper = slang_oper_child(ifOper, 1);
-      }
-      {
-         slang_operation *setOper = slang_oper_child(blockOper, 1);
-         setOper->type = SLANG_OPER_ASSIGN;
-         slang_operation_add_children(setOper, 2);
-         {
-            slang_operation *lhs = slang_oper_child(setOper, 0);
-            lhs->type = SLANG_OPER_IDENTIFIER;
-            lhs->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
-         }
-         {
-            slang_operation *rhs = slang_oper_child(setOper, 1);
-            slang_operation_literal_bool(rhs, GL_FALSE);
-         }
-      }
-   }
-   else {
-      /* Emit:
-       *    {
-       *       __retVal = expr;
-       *       return_inlined;
-       *    }
-       */
-      assignOper = slang_oper_child(blockOper, 0);
-      {
-         slang_operation *returnOper = slang_oper_child(blockOper, 1);
-         returnOper->type = SLANG_OPER_RETURN_INLINED;
-         assert(returnOper->num_children == 0);
-      }
-   }
-
-   /* __retVal = expression; */
-   assignOper->type = SLANG_OPER_ASSIGN;
-   slang_operation_add_children(assignOper, 2);
-   {
-      slang_operation *lhs = slang_oper_child(assignOper, 0);
-      lhs->type = SLANG_OPER_IDENTIFIER;
-      lhs->a_id = slang_atom_pool_atom(A->atoms, "__retVal");
-   }
-   {
-      slang_operation *rhs = slang_oper_child(assignOper, 1);
-      slang_operation_copy(rhs, &oper->children[0]);
-   }
-
-   /*blockOper->locals->outer_scope = oper->locals->outer_scope;*/
-
-   /*slang_print_tree(blockOper, 0);*/
-
-   return blockOper;
-}
-
-
-/**
- * Rewrite AST code for "return;" (no expression).
- */
-static slang_operation *
-gen_return_without_expression(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_operation *newRet;
-
-   assert(oper->type == SLANG_OPER_RETURN);
-
-   if (A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) {
-      slang_info_log_error(A->log, "return statement requires an expression");
-      return NULL;
-   }
-
-   if (A->UseReturnFlag) {
-      /* Emit:
-       *    __notRetFlag = 0;
-       */
-      {
-         newRet = slang_operation_new(1);
-         newRet->locals->outer_scope = oper->locals->outer_scope;
-         newRet->type = SLANG_OPER_ASSIGN;
-         slang_operation_add_children(newRet, 2);
-         {
-            slang_operation *lhs = slang_oper_child(newRet, 0);
-            lhs->type = SLANG_OPER_IDENTIFIER;
-            lhs->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
-         }
-         {
-            slang_operation *rhs = slang_oper_child(newRet, 1);
-            slang_operation_literal_bool(rhs, GL_FALSE);
-         }
-      }
-   }
-   else {
-      /* Emit:
-       *    return_inlined;
-       */
-      newRet = slang_operation_new(1);
-      newRet->locals->outer_scope = oper->locals->outer_scope;
-      newRet->type = SLANG_OPER_RETURN_INLINED;
-   }
-
-   /*slang_print_tree(newRet, 0);*/
-
-   return newRet;
-}
-
-
-
-
-/**
- * Replace particular variables (SLANG_OPER_IDENTIFIER) with new expressions.
- */
-static void
-slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
-                 GLuint substCount, slang_variable **substOld,
-                slang_operation **substNew, GLboolean isLHS)
-{
-   switch (oper->type) {
-   case SLANG_OPER_VARIABLE_DECL:
-      {
-         slang_variable *v = _slang_variable_locate(oper->locals,
-                                                    oper->a_id, GL_TRUE);
-         assert(v);
-         if (v->initializer && oper->num_children == 0) {
-            /* set child of oper to copy of initializer */
-            oper->num_children = 1;
-            oper->children = slang_operation_new(1);
-            slang_operation_copy(&oper->children[0], v->initializer);
-         }
-         if (oper->num_children == 1) {
-            /* the initializer */
-            slang_substitute(A, &oper->children[0], substCount,
-                             substOld, substNew, GL_FALSE);
-         }
-      }
-      break;
-   case SLANG_OPER_IDENTIFIER:
-      assert(oper->num_children == 0);
-      if (1/**!isLHS XXX FIX */) {
-         slang_atom id = oper->a_id;
-         slang_variable *v;
-        GLuint i;
-         v = _slang_variable_locate(oper->locals, id, GL_TRUE);
-        if (!v) {
-#if 0
-            if (strcmp((char *) oper->a_id, "__notRetFlag"))
-               _mesa_problem(NULL, "var %s not found!\n", (char *) oper->a_id);
-#endif
-            return;
-        }
-
-        /* look for a substitution */
-        for (i = 0; i < substCount; i++) {
-           if (v == substOld[i]) {
-               /* OK, replace this SLANG_OPER_IDENTIFIER with a new expr */
-#if 0 /* DEBUG only */
-              if (substNew[i]->type == SLANG_OPER_IDENTIFIER) {
-                  assert(substNew[i]->var);
-                  assert(substNew[i]->var->a_name);
-                 printf("Substitute %s with %s in id node %p\n",
-                        (char*)v->a_name, (char*) substNew[i]->var->a_name,
-                        (void*) oper);
-               }
-              else {
-                 printf("Substitute %s with %f in id node %p\n",
-                        (char*)v->a_name, substNew[i]->literal[0],
-                        (void*) oper);
-               }
-#endif
-              slang_operation_copy(oper, substNew[i]);
-              break;
-           }
-        }
-      }
-      break;
-
-   case SLANG_OPER_RETURN:
-      {
-         slang_operation *newReturn;
-         /* generate new 'return' code' */
-         if (slang_oper_child(oper, 0)->type == SLANG_OPER_VOID)
-            newReturn = gen_return_without_expression(A, oper);
-         else
-            newReturn = gen_return_with_expression(A, oper);
-
-         if (!newReturn)
-            return;
-
-         /* do substitutions on the new 'return' code */
-         slang_substitute(A, newReturn,
-                          substCount, substOld, substNew, GL_FALSE);
-
-         /* install new 'return' code */
-         slang_operation_copy(oper, newReturn);
-         slang_operation_destruct(newReturn);
-      }
-      break;
-
-   case SLANG_OPER_ASSIGN:
-   case SLANG_OPER_SUBSCRIPT:
-      /* special case:
-       * child[0] can't have substitutions but child[1] can.
-       */
-      slang_substitute(A, &oper->children[0],
-                       substCount, substOld, substNew, GL_TRUE);
-      slang_substitute(A, &oper->children[1],
-                       substCount, substOld, substNew, GL_FALSE);
-      break;
-   case SLANG_OPER_FIELD:
-      /* XXX NEW - test */
-      slang_substitute(A, &oper->children[0],
-                       substCount, substOld, substNew, GL_TRUE);
-      break;
-   default:
-      {
-         GLuint i;
-         for (i = 0; i < oper->num_children; i++) 
-            slang_substitute(A, &oper->children[i],
-                             substCount, substOld, substNew, GL_FALSE);
-      }
-   }
-}
-
-
-/**
- * Produce inline code for a call to an assembly instruction.
- * This is typically used to compile a call to a built-in function like this:
- *
- * vec4 mix(const vec4 x, const vec4 y, const vec4 a)
- * {
- *    __asm vec4_lrp __retVal, a, y, x;
- * }
- *
- *
- * A call to
- *     r = mix(p1, p2, p3);
- *
- * Becomes:
- *
- *              mov
- *             /   \
- *            r   vec4_lrp
- *                 /  |  \
- *                p3  p2  p1
- *
- * We basically translate a SLANG_OPER_CALL into a SLANG_OPER_ASM.
- */
-static slang_operation *
-slang_inline_asm_function(slang_assemble_ctx *A,
-                          slang_function *fun, slang_operation *oper)
-{
-   const GLuint numArgs = oper->num_children;
-   GLuint i;
-   slang_operation *inlined;
-   const GLboolean haveRetValue = _slang_function_has_return_value(fun);
-   slang_variable **substOld;
-   slang_operation **substNew;
-
-   ASSERT(slang_is_asm_function(fun));
-   ASSERT(fun->param_count == numArgs + haveRetValue);
-
-   /*
-   printf("Inline %s as %s\n",
-          (char*) fun->header.a_name,
-          (char*) fun->body->children[0].a_id);
-   */
-
-   /*
-    * We'll substitute formal params with actual args in the asm call.
-    */
-   substOld = (slang_variable **)
-      _slang_alloc(numArgs * sizeof(slang_variable *));
-   substNew = (slang_operation **)
-      _slang_alloc(numArgs * sizeof(slang_operation *));
-   for (i = 0; i < numArgs; i++) {
-      substOld[i] = fun->parameters->variables[i];
-      substNew[i] = oper->children + i;
-   }
-
-   /* make a copy of the code to inline */
-   inlined = slang_operation_new(1);
-   slang_operation_copy(inlined, &fun->body->children[0]);
-   if (haveRetValue) {
-      /* get rid of the __retVal child */
-      inlined->num_children--;
-      for (i = 0; i < inlined->num_children; i++) {
-         inlined->children[i] = inlined->children[i + 1];
-      }
-   }
-
-   /* now do formal->actual substitutions */
-   slang_substitute(A, inlined, numArgs, substOld, substNew, GL_FALSE);
-
-   _slang_free(substOld);
-   _slang_free(substNew);
-
-#if 0
-   printf("+++++++++++++ inlined asm function %s +++++++++++++\n",
-          (char *) fun->header.a_name);
-   slang_print_tree(inlined, 3);
-   printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n");
-#endif
-
-   return inlined;
-}
-
-
-/**
- * Inline the given function call operation.
- * Return a new slang_operation that corresponds to the inlined code.
- */
-static slang_operation *
-slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
-                          slang_operation *oper, slang_operation *returnOper)
-{
-   typedef enum {
-      SUBST = 1,
-      COPY_IN,
-      COPY_OUT
-   } ParamMode;
-   ParamMode *paramMode;
-   const GLboolean haveRetValue = _slang_function_has_return_value(fun);
-   const GLuint numArgs = oper->num_children;
-   const GLuint totalArgs = numArgs + haveRetValue;
-   slang_operation *args = oper->children;
-   slang_operation *inlined, *top;
-   slang_variable **substOld;
-   slang_operation **substNew;
-   GLuint substCount, numCopyIn, i;
-   slang_function *prevFunction;
-   slang_variable_scope *newScope = NULL;
-
-   /* save / push */
-   prevFunction = A->CurFunction;
-   A->CurFunction = fun;
-
-   /*assert(oper->type == SLANG_OPER_CALL); (or (matrix) multiply, etc) */
-   assert(fun->param_count == totalArgs);
-
-   /* allocate temporary arrays */
-   paramMode = (ParamMode *)
-      _slang_alloc(totalArgs * sizeof(ParamMode));
-   substOld = (slang_variable **)
-      _slang_alloc(totalArgs * sizeof(slang_variable *));
-   substNew = (slang_operation **)
-      _slang_alloc(totalArgs * sizeof(slang_operation *));
-
-#if 0
-   printf("\nInline call to %s  (total vars=%d  nparams=%d)\n",
-         (char *) fun->header.a_name,
-         fun->parameters->num_variables, numArgs);
-#endif
-
-   if (haveRetValue && !returnOper) {
-      /* Create 3-child comma sequence for inlined code:
-       * child[0]:  declare __resultTmp
-       * child[1]:  inlined function body
-       * child[2]:  __resultTmp
-       */
-      slang_operation *commaSeq;
-      slang_operation *declOper = NULL;
-      slang_variable *resultVar;
-
-      commaSeq = slang_operation_new(1);
-      commaSeq->type = SLANG_OPER_SEQUENCE;
-      assert(commaSeq->locals);
-      commaSeq->locals->outer_scope = oper->locals->outer_scope;
-      commaSeq->num_children = 3;
-      commaSeq->children = slang_operation_new(3);
-      /* allocate the return var */
-      resultVar = slang_variable_scope_grow(commaSeq->locals);
-      /*
-      printf("Alloc __resultTmp in scope %p for retval of calling %s\n",
-             (void*)commaSeq->locals, (char *) fun->header.a_name);
-      */
-
-      resultVar->a_name = slang_atom_pool_atom(A->atoms, "__resultTmp");
-      resultVar->type = fun->header.type; /* XXX copy? */
-      resultVar->isTemp = GL_TRUE;
-
-      /* child[0] = __resultTmp declaration */
-      declOper = &commaSeq->children[0];
-      declOper->type = SLANG_OPER_VARIABLE_DECL;
-      declOper->a_id = resultVar->a_name;
-      declOper->locals->outer_scope = commaSeq->locals;
-
-      /* child[1] = function body */
-      inlined = &commaSeq->children[1];
-      inlined->locals->outer_scope = commaSeq->locals;
-
-      /* child[2] = __resultTmp reference */
-      returnOper = &commaSeq->children[2];
-      returnOper->type = SLANG_OPER_IDENTIFIER;
-      returnOper->a_id = resultVar->a_name;
-      returnOper->locals->outer_scope = commaSeq->locals;
-
-      top = commaSeq;
-   }
-   else {
-      top = inlined = slang_operation_new(1);
-      /* XXXX this may be inappropriate!!!! */
-      inlined->locals->outer_scope = oper->locals->outer_scope;
-   }
-
-
-   assert(inlined->locals);
-
-   /* Examine the parameters, look for inout/out params, look for possible
-    * substitutions, etc:
-    *    param type      behaviour
-    *     in             copy actual to local
-    *     const in       substitute param with actual
-    *     out            copy out
-    */
-   substCount = 0;
-   for (i = 0; i < totalArgs; i++) {
-      slang_variable *p = fun->parameters->variables[i];
-      /*
-      printf("Param %d: %s %s \n", i,
-             slang_type_qual_string(p->type.qualifier),
-            (char *) p->a_name);
-      */
-      if (p->type.qualifier == SLANG_QUAL_INOUT ||
-         p->type.qualifier == SLANG_QUAL_OUT) {
-        /* an output param */
-         slang_operation *arg;
-         if (i < numArgs)
-            arg = &args[i];
-         else
-            arg = returnOper;
-        paramMode[i] = SUBST;
-
-        if (arg->type == SLANG_OPER_IDENTIFIER)
-            slang_resolve_variable(arg);
-
-         /* replace parameter 'p' with argument 'arg' */
-        substOld[substCount] = p;
-        substNew[substCount] = arg; /* will get copied */
-        substCount++;
-      }
-      else if (p->type.qualifier == SLANG_QUAL_CONST) {
-        /* a constant input param */
-         if (args[i].type == SLANG_OPER_IDENTIFIER ||
-             args[i].type == SLANG_OPER_LITERAL_FLOAT ||
-             args[i].type == SLANG_OPER_SUBSCRIPT) {
-           /* replace all occurances of this parameter variable with the
-            * actual argument variable or a literal.
-            */
-           paramMode[i] = SUBST;
-            slang_resolve_variable(&args[i]);
-           substOld[substCount] = p;
-           substNew[substCount] = &args[i]; /* will get copied */
-           substCount++;
-        }
-        else {
-           paramMode[i] = COPY_IN;
-        }
-      }
-      else {
-        paramMode[i] = COPY_IN;
-      }
-      assert(paramMode[i]);
-   }
-
-   /* actual code inlining: */
-   slang_operation_copy(inlined, fun->body);
-
-   /*** XXX review this */
-   assert(inlined->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE ||
-          inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE);
-   inlined->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-
-#if 0
-   printf("======================= orig body code ======================\n");
-   printf("=== params scope = %p\n", (void*) fun->parameters);
-   slang_print_tree(fun->body, 8);
-   printf("======================= copied code =========================\n");
-   slang_print_tree(inlined, 8);
-#endif
-
-   /* do parameter substitution in inlined code: */
-   slang_substitute(A, inlined, substCount, substOld, substNew, GL_FALSE);
-
-#if 0
-   printf("======================= subst code ==========================\n");
-   slang_print_tree(inlined, 8);
-   printf("=============================================================\n");
-#endif
-
-   /* New prolog statements: (inserted before the inlined code)
-    * Copy the 'in' arguments.
-    */
-   numCopyIn = 0;
-   for (i = 0; i < numArgs; i++) {
-      if (paramMode[i] == COPY_IN) {
-        slang_variable *p = fun->parameters->variables[i];
-        /* declare parameter 'p' */
-        slang_operation *decl = slang_operation_insert(&inlined->num_children,
-                                                       &inlined->children,
-                                                       numCopyIn);
-
-        decl->type = SLANG_OPER_VARIABLE_DECL;
-         assert(decl->locals);
-         decl->locals->outer_scope = inlined->locals;
-        decl->a_id = p->a_name;
-        decl->num_children = 1;
-        decl->children = slang_operation_new(1);
-
-         /* child[0] is the var's initializer */
-         slang_operation_copy(&decl->children[0], args + i);
-
-         /* add parameter 'p' to the local variable scope here */
-         {
-            slang_variable *pCopy = slang_variable_scope_grow(inlined->locals);
-            pCopy->type = p->type;
-            pCopy->a_name = p->a_name;
-            pCopy->array_len = p->array_len;
-         }
-
-         newScope = inlined->locals;
-        numCopyIn++;
-      }
-   }
-
-   /* Now add copies of the function's local vars to the new variable scope */
-   for (i = totalArgs; i < fun->parameters->num_variables; i++) {
-      slang_variable *p = fun->parameters->variables[i];
-      slang_variable *pCopy = slang_variable_scope_grow(inlined->locals);
-      pCopy->type = p->type;
-      pCopy->a_name = p->a_name;
-      pCopy->array_len = p->array_len;
-   }
-
-
-   /* New epilog statements:
-    * 1. Create end of function label to jump to from return statements.
-    * 2. Copy the 'out' parameter vars
-    */
-   {
-      slang_operation *lab = slang_operation_insert(&inlined->num_children,
-                                                    &inlined->children,
-                                                    inlined->num_children);
-      lab->type = SLANG_OPER_LABEL;
-      lab->label = A->curFuncEndLabel;
-   }
-
-   for (i = 0; i < totalArgs; i++) {
-      if (paramMode[i] == COPY_OUT) {
-        const slang_variable *p = fun->parameters->variables[i];
-        /* actualCallVar = outParam */
-        /*if (i > 0 || !haveRetValue)*/
-        slang_operation *ass = slang_operation_insert(&inlined->num_children,
-                                                      &inlined->children,
-                                                      inlined->num_children);
-        ass->type = SLANG_OPER_ASSIGN;
-        ass->num_children = 2;
-         ass->locals->outer_scope = inlined->locals;
-        ass->children = slang_operation_new(2);
-        ass->children[0] = args[i]; /*XXX copy */
-        ass->children[1].type = SLANG_OPER_IDENTIFIER;
-        ass->children[1].a_id = p->a_name;
-         ass->children[1].locals->outer_scope = ass->locals;
-      }
-   }
-
-   _slang_free(paramMode);
-   _slang_free(substOld);
-   _slang_free(substNew);
-
-   /* Update scoping to use the new local vars instead of the
-    * original function's vars.  This is especially important
-    * for nested inlining.
-    */
-   if (newScope)
-      slang_replace_scope(inlined, fun->parameters, newScope);
-
-#if 0
-   printf("Done Inline call to %s  (total vars=%d  nparams=%d)\n\n",
-         (char *) fun->header.a_name,
-         fun->parameters->num_variables, numArgs);
-   slang_print_tree(top, 0);
-#endif
-
-   /* pop */
-   A->CurFunction = prevFunction;
-
-   return top;
-}
-
-
-/**
- * Insert declaration for "bool __notRetFlag" in given block operation.
- * This is used when we can't emit "early" return statements in subroutines.
- */
-static void
-declare_return_flag(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_operation *decl;
-
-   assert(oper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
-          oper->type == SLANG_OPER_SEQUENCE);
-
-   decl = slang_operation_insert_child(oper, 1);
-
-   slang_generate_declaration(A, oper->locals, decl,
-                              SLANG_SPEC_BOOL, "__notRetFlag", GL_TRUE);
-
-   /*slang_print_tree(oper, 0);*/
-}
-
-
-/**
- * Recursively replace instances of the old node type with the new type.
- */
-static void
-replace_node_type(slang_operation *oper, slang_operation_type oldType,
-                  slang_operation_type newType)
-{
-   GLuint i;
-
-   if (oper->type == oldType)
-      oper->type = newType;
-
-   for (i = 0; i < slang_oper_num_children(oper); i++) {
-      replace_node_type(slang_oper_child(oper, i), oldType, newType);
-   }
-}
-
-
-
-/**
- * Test if the given function body has an "early return".  That is, there's
- * a 'return' statement that's not the very last instruction in the body.
- */
-static GLboolean
-has_early_return(const slang_operation *funcBody)
-{
-   GLuint retCount = _slang_count_node_type(funcBody, SLANG_OPER_RETURN);
-   if (retCount == 0)
-      return GL_FALSE;
-   else if (retCount == 1 && _slang_is_tail_return(funcBody))
-      return GL_FALSE;
-   else
-      return GL_TRUE;
-}
-
-
-/**
- * Emit IR code for a function call.  This does one of two things:
- * 1. Inline the function's code
- * 2. Create an IR for the function's body and create a real call to it.
- */
-static slang_ir_node *
-_slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
-                         slang_operation *oper, slang_operation *dest)
-{
-   slang_ir_node *n;
-   slang_operation *instance;
-   slang_label *prevFuncEndLabel;
-   char name[200];
-
-   prevFuncEndLabel = A->curFuncEndLabel;
-   _mesa_snprintf(name, sizeof(name), "__endOfFunc_%s_", (char *) fun->header.a_name);
-   A->curFuncEndLabel = _slang_label_new(name);
-   assert(A->curFuncEndLabel);
-
-   /*
-    * 'instance' is basically a copy of the function's body with various
-    * transformations.
-    */
-
-   if (slang_is_asm_function(fun) && !dest) {
-      /* assemble assembly function - tree style */
-      instance = slang_inline_asm_function(A, fun, oper);
-   }
-   else {
-      /* non-assembly function */
-      /* We always generate an "inline-able" block of code here.
-       * We may either:
-       *  1. insert the inline code
-       *  2. Generate a call to the "inline" code as a subroutine
-       */
-      const GLboolean earlyReturn = has_early_return(fun->body);
-
-      if (earlyReturn && !A->EmitContReturn) {
-         A->UseReturnFlag = GL_TRUE;
-      }
-
-      instance = slang_inline_function_call(A, fun, oper, dest);
-      if (!instance)
-         return NULL;
-
-      if (earlyReturn) {
-         /* The function we're calling has one or more 'return' statements
-          * that prevent us from inlining the function's code.
-          *
-          * In this case, change the function's body type from
-          * SLANG_OPER_BLOCK_NEW_SCOPE to SLANG_OPER_NON_INLINED_CALL.
-          * During code emit this will result in a true subroutine call.
-          *
-          * Also, convert SLANG_OPER_RETURN_INLINED nodes to SLANG_OPER_RETURN.
-          */
-         slang_operation *callOper;
-
-         assert(instance->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
-                instance->type == SLANG_OPER_SEQUENCE);
-
-         if (_slang_function_has_return_value(fun) && !dest) {
-            assert(instance->children[0].type == SLANG_OPER_VARIABLE_DECL);
-            assert(instance->children[2].type == SLANG_OPER_IDENTIFIER);
-            callOper = &instance->children[1];
-         }
-         else {
-            callOper = instance;
-         }
-
-         if (A->UseReturnFlag) {
-            /* Early returns not supported.  Create a _returnFlag variable
-             * that's set upon 'return' and tested elsewhere to no-op any
-             * remaining instructions in the subroutine.
-             */
-            assert(callOper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
-                   callOper->type == SLANG_OPER_SEQUENCE);
-            declare_return_flag(A, callOper);
-         }
-         else {
-            /* We can emit real 'return' statements.  If we generated any
-             * 'inline return' statements during function instantiation,
-             * change them back to regular 'return' statements.
-             */
-            replace_node_type(instance, SLANG_OPER_RETURN_INLINED,
-                              SLANG_OPER_RETURN);
-         }
-
-         callOper->type = SLANG_OPER_NON_INLINED_CALL;
-         callOper->fun = fun;
-         callOper->label = _slang_label_new_unique((char*) fun->header.a_name);
-      }
-      else {
-         /* If there are any 'return' statements remaining, they're at the
-          * very end of the function and can effectively become no-ops.
-          */
-         replace_node_type(instance, SLANG_OPER_RETURN_INLINED,
-                           SLANG_OPER_VOID);
-      }
-   }
-
-   if (!instance)
-      return NULL;
-
-   /* Replace the function call with the instance block (or new CALL stmt) */
-   slang_operation_destruct(oper);
-   *oper = *instance;
-   _slang_free(instance);
-
-#if 0
-   assert(instance->locals);
-   printf("*** Inlined code for call to %s:\n", (char*) fun->header.a_name);
-   slang_print_tree(oper, 10);
-   printf("\n");
-#endif
-
-   n = _slang_gen_operation(A, oper);
-
-   /*_slang_label_delete(A->curFuncEndLabel);*/
-   A->curFuncEndLabel = prevFuncEndLabel;
-
-   if (A->pragmas->Debug) {
-      char s[1000];
-      _mesa_snprintf(s, sizeof(s), "Call/inline %s()", (char *) fun->header.a_name);
-      n->Comment = _slang_strdup(s);
-   }
-
-   A->UseReturnFlag = GL_FALSE;
-
-   return n;
-}
-
-
-static slang_asm_info *
-slang_find_asm_info(const char *name)
-{
-   GLuint i;
-   for (i = 0; AsmInfo[i].Name; i++) {
-      if (strcmp(AsmInfo[i].Name, name) == 0) {
-         return AsmInfo + i;
-      }
-   }
-   return NULL;
-}
-
-
-/**
- * Some write-masked assignments are simple, but others are hard.
- * Simple example:
- *    vec3 v;
- *    v.xy = vec2(a, b);
- * Hard example:
- *    vec3 v;
- *    v.zy = vec2(a, b);
- * this gets transformed/swizzled into:
- *    v.zy = vec2(a, b).*yx*         (* = don't care)
- * This function helps to determine simple vs. non-simple.
- */
-static GLboolean
-_slang_simple_writemask(GLuint writemask, GLuint swizzle)
-{
-   switch (writemask) {
-   case WRITEMASK_X:
-      return GET_SWZ(swizzle, 0) == SWIZZLE_X;
-   case WRITEMASK_Y:
-      return GET_SWZ(swizzle, 1) == SWIZZLE_Y;
-   case WRITEMASK_Z:
-      return GET_SWZ(swizzle, 2) == SWIZZLE_Z;
-   case WRITEMASK_W:
-      return GET_SWZ(swizzle, 3) == SWIZZLE_W;
-   case WRITEMASK_XY:
-      return (GET_SWZ(swizzle, 0) == SWIZZLE_X)
-         && (GET_SWZ(swizzle, 1) == SWIZZLE_Y);
-   case WRITEMASK_XYZ:
-      return (GET_SWZ(swizzle, 0) == SWIZZLE_X)
-         && (GET_SWZ(swizzle, 1) == SWIZZLE_Y)
-         && (GET_SWZ(swizzle, 2) == SWIZZLE_Z);
-   case WRITEMASK_XYZW:
-      return swizzle == SWIZZLE_NOOP;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Convert the given swizzle into a writemask.  In some cases this
- * is trivial, in other cases, we'll need to also swizzle the right
- * hand side to put components in the right places.
- * See comment above for more info.
- * XXX this function could be simplified and should probably be renamed.
- * \param swizzle  the incoming swizzle
- * \param writemaskOut  returns the writemask
- * \param swizzleOut  swizzle to apply to the right-hand-side
- * \return GL_FALSE for simple writemasks, GL_TRUE for non-simple
- */
-static GLboolean
-swizzle_to_writemask(slang_assemble_ctx *A, GLuint swizzle,
-                     GLuint *writemaskOut, GLuint *swizzleOut)
-{
-   GLuint mask = 0x0, newSwizzle[4];
-   GLint i, size;
-
-   /* make new dst writemask, compute size */
-   for (i = 0; i < 4; i++) {
-      const GLuint swz = GET_SWZ(swizzle, i);
-      if (swz == SWIZZLE_NIL) {
-         /* end */
-         break;
-      }
-      assert(swz <= 3);
-
-      if (swizzle != SWIZZLE_XXXX &&
-          swizzle != SWIZZLE_YYYY &&
-          swizzle != SWIZZLE_ZZZZ &&
-          swizzle != SWIZZLE_WWWW &&
-          (mask & (1 << swz))) {
-         /* a channel can't be specified twice (ex: ".xyyz") */
-         slang_info_log_error(A->log, "Invalid writemask '%s'",
-                              _mesa_swizzle_string(swizzle, 0, 0));
-         return GL_FALSE;
-      }
-
-      mask |= (1 << swz);
-   }
-   assert(mask <= 0xf);
-   size = i;  /* number of components in mask/swizzle */
-
-   *writemaskOut = mask;
-
-   /* make new src swizzle, by inversion */
-   for (i = 0; i < 4; i++) {
-      newSwizzle[i] = i; /*identity*/
-   }
-   for (i = 0; i < size; i++) {
-      const GLuint swz = GET_SWZ(swizzle, i);
-      newSwizzle[swz] = i;
-   }
-   *swizzleOut = MAKE_SWIZZLE4(newSwizzle[0],
-                               newSwizzle[1],
-                               newSwizzle[2],
-                               newSwizzle[3]);
-
-   if (_slang_simple_writemask(mask, *swizzleOut)) {
-      if (size >= 1)
-         assert(GET_SWZ(*swizzleOut, 0) == SWIZZLE_X);
-      if (size >= 2)
-         assert(GET_SWZ(*swizzleOut, 1) == SWIZZLE_Y);
-      if (size >= 3)
-         assert(GET_SWZ(*swizzleOut, 2) == SWIZZLE_Z);
-      if (size >= 4)
-         assert(GET_SWZ(*swizzleOut, 3) == SWIZZLE_W);
-      return GL_TRUE;
-   }
-   else
-      return GL_FALSE;
-}
-
-
-#if 0 /* not used, but don't remove just yet */
-/**
- * Recursively traverse 'oper' to produce a swizzle mask in the event
- * of any vector subscripts and swizzle suffixes.
- * Ex:  for "vec4 v",  "v[2].x" resolves to v.z
- */
-static GLuint
-resolve_swizzle(const slang_operation *oper)
-{
-   if (oper->type == SLANG_OPER_FIELD) {
-      /* writemask from .xyzw suffix */
-      slang_swizzle swz;
-      if (_slang_is_swizzle((char*) oper->a_id, 4, &swz)) {
-         GLuint swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
-                                        swz.swizzle[1],
-                                        swz.swizzle[2],
-                                        swz.swizzle[3]);
-         GLuint child_swizzle = resolve_swizzle(&oper->children[0]);
-         GLuint s = _slang_swizzle_swizzle(child_swizzle, swizzle);
-         return s;
-      }
-      else
-         return SWIZZLE_XYZW;
-   }
-   else if (oper->type == SLANG_OPER_SUBSCRIPT &&
-            oper->children[1].type == SLANG_OPER_LITERAL_INT) {
-      /* writemask from [index] */
-      GLuint child_swizzle = resolve_swizzle(&oper->children[0]);
-      GLuint i = (GLuint) oper->children[1].literal[0];
-      GLuint swizzle;
-      GLuint s;
-      switch (i) {
-      case 0:
-         swizzle = SWIZZLE_XXXX;
-         break;
-      case 1:
-         swizzle = SWIZZLE_YYYY;
-         break;
-      case 2:
-         swizzle = SWIZZLE_ZZZZ;
-         break;
-      case 3:
-         swizzle = SWIZZLE_WWWW;
-         break;
-      default:
-         swizzle = SWIZZLE_XYZW;
-      }
-      s = _slang_swizzle_swizzle(child_swizzle, swizzle);
-      return s;
-   }
-   else {
-      return SWIZZLE_XYZW;
-   }
-}
-#endif
-
-
-#if 0
-/**
- * Recursively descend through swizzle nodes to find the node's storage info.
- */
-static slang_ir_storage *
-get_store(const slang_ir_node *n)
-{
-   if (n->Opcode == IR_SWIZZLE) {
-      return get_store(n->Children[0]);
-   }
-   return n->Store;
-}
-#endif
-
-
-/**
- * Generate IR tree for an asm instruction/operation such as:
- *    __asm vec4_dot __retVal.x, v1, v2;
- */
-static slang_ir_node *
-_slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper,
-               slang_operation *dest)
-{
-   const slang_asm_info *info;
-   slang_ir_node *kids[3], *n;
-   GLuint j, firstOperand;
-
-   assert(oper->type == SLANG_OPER_ASM);
-
-   info = slang_find_asm_info((char *) oper->a_id);
-   if (!info) {
-      _mesa_problem(NULL, "undefined __asm function %s\n",
-                    (char *) oper->a_id);
-      assert(info);
-      return NULL;
-   }
-   assert(info->NumParams <= 3);
-
-   if (info->NumParams == oper->num_children) {
-      /* Storage for result is not specified.
-       * Children[0], [1], [2] are the operands.
-       */
-      firstOperand = 0;
-   }
-   else {
-      /* Storage for result (child[0]) is specified.
-       * Children[1], [2], [3] are the operands.
-       */
-      firstOperand = 1;
-   }
-
-   /* assemble child(ren) */
-   kids[0] = kids[1] = kids[2] = NULL;
-   for (j = 0; j < info->NumParams; j++) {
-      kids[j] = _slang_gen_operation(A, &oper->children[firstOperand + j]);
-      if (!kids[j])
-         return NULL;
-   }
-
-   n = new_node3(info->Opcode, kids[0], kids[1], kids[2]);
-
-   if (firstOperand) {
-      /* Setup n->Store to be a particular location.  Otherwise, storage
-       * for the result (a temporary) will be allocated later.
-       */
-      slang_operation *dest_oper;
-      slang_ir_node *n0;
-
-      dest_oper = &oper->children[0];
-
-      n0 = _slang_gen_operation(A, dest_oper);
-      if (!n0)
-         return NULL;
-
-      assert(!n->Store);
-      n->Store = n0->Store;
-
-      assert(n->Store->File != PROGRAM_UNDEFINED || n->Store->Parent);
-
-      _slang_free(n0);
-   }
-
-   return n;
-}
-
-
-#if 0
-static void
-print_funcs(struct slang_function_scope_ *scope, const char *name)
-{
-   GLuint i;
-   for (i = 0; i < scope->num_functions; i++) {
-      slang_function *f = &scope->functions[i];
-      if (!name || strcmp(name, (char*) f->header.a_name) == 0)
-          printf("  %s (%d args)\n", name, f->param_count);
-
-   }
-   if (scope->outer_scope)
-      print_funcs(scope->outer_scope, name);
-}
-#endif
-
-
-/**
- * Find a function of the given name, taking 'numArgs' arguments.
- * This is the function we'll try to call when there is no exact match
- * between function parameters and call arguments.
- *
- * XXX we should really create a list of candidate functions and try
- * all of them...
- */
-static slang_function *
-_slang_find_function_by_argc(slang_function_scope *scope,
-                             const char *name, int numArgs)
-{
-   while (scope) {
-      GLuint i;
-      for (i = 0; i < scope->num_functions; i++) {
-         slang_function *f = &scope->functions[i];
-         if (strcmp(name, (char*) f->header.a_name) == 0) {
-            int haveRetValue = _slang_function_has_return_value(f);
-            if (numArgs == f->param_count - haveRetValue)
-               return f;
-         }
-      }
-      scope = scope->outer_scope;
-   }
-
-   return NULL;
-}
-
-
-static slang_function *
-_slang_find_function_by_max_argc(slang_function_scope *scope,
-                                 const char *name)
-{
-   slang_function *maxFunc = NULL;
-   GLuint maxArgs = 0;
-
-   while (scope) {
-      GLuint i;
-      for (i = 0; i < scope->num_functions; i++) {
-         slang_function *f = &scope->functions[i];
-         if (strcmp(name, (char*) f->header.a_name) == 0) {
-            if (f->param_count > maxArgs) {
-               maxArgs = f->param_count;
-               maxFunc = f;
-            }
-         }
-      }
-      scope = scope->outer_scope;
-   }
-
-   return maxFunc;
-}
-
-
-/**
- * Generate a new slang_function which is a constructor for a user-defined
- * struct type.
- */
-static slang_function *
-_slang_make_struct_constructor(slang_assemble_ctx *A, slang_struct *str)
-{
-   const GLint numFields = str->fields->num_variables;
-   slang_function *fun = slang_function_new(SLANG_FUNC_CONSTRUCTOR);
-
-   /* function header (name, return type) */
-   fun->header.a_name = str->a_name;
-   fun->header.type.qualifier = SLANG_QUAL_NONE;
-   fun->header.type.specifier.type = SLANG_SPEC_STRUCT;
-   fun->header.type.specifier._struct = str;
-
-   /* function parameters (= struct's fields) */
-   {
-      GLint i;
-      for (i = 0; i < numFields; i++) {
-         /*
-         printf("Field %d: %s\n", i, (char*) str->fields->variables[i]->a_name);
-         */
-         slang_variable *p = slang_variable_scope_grow(fun->parameters);
-         *p = *str->fields->variables[i]; /* copy the variable and type */
-         p->type.qualifier = SLANG_QUAL_CONST;
-      }
-      fun->param_count = fun->parameters->num_variables;
-   }
-
-   /* Add __retVal to params */
-   {
-      slang_variable *p = slang_variable_scope_grow(fun->parameters);
-      slang_atom a_retVal = slang_atom_pool_atom(A->atoms, "__retVal");
-      assert(a_retVal);
-      p->a_name = a_retVal;
-      p->type = fun->header.type;
-      p->type.qualifier = SLANG_QUAL_OUT;
-      fun->param_count++;
-   }
-
-   /* function body is:
-    *    block:
-    *       declare T;
-    *       T.f1 = p1;
-    *       T.f2 = p2;
-    *       ...
-    *       T.fn = pn;
-    *       return T;
-    */
-   {
-      slang_variable_scope *scope;
-      slang_variable *var;
-      GLint i;
-
-      fun->body = slang_operation_new(1);
-      fun->body->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-      fun->body->num_children = numFields + 2;
-      fun->body->children = slang_operation_new(numFields + 2);
-
-      scope = fun->body->locals;
-      scope->outer_scope = fun->parameters;
-
-      /* create local var 't' */
-      var = slang_variable_scope_grow(scope);
-      var->a_name = slang_atom_pool_atom(A->atoms, "t");
-      var->type = fun->header.type;
-
-      /* declare t */
-      {
-         slang_operation *decl;
-
-         decl = &fun->body->children[0];
-         decl->type = SLANG_OPER_VARIABLE_DECL;
-         decl->locals = _slang_variable_scope_new(scope);
-         decl->a_id = var->a_name;
-      }
-
-      /* assign params to fields of t */
-      for (i = 0; i < numFields; i++) {
-         slang_operation *assign = &fun->body->children[1 + i];
-
-         assign->type = SLANG_OPER_ASSIGN;
-         assign->locals = _slang_variable_scope_new(scope);
-         assign->num_children = 2;
-         assign->children = slang_operation_new(2);
-         
-         {
-            slang_operation *lhs = &assign->children[0];
-
-            lhs->type = SLANG_OPER_FIELD;
-            lhs->locals = _slang_variable_scope_new(scope);
-            lhs->num_children = 1;
-            lhs->children = slang_operation_new(1);
-            lhs->a_id = str->fields->variables[i]->a_name;
-
-            lhs->children[0].type = SLANG_OPER_IDENTIFIER;
-            lhs->children[0].a_id = var->a_name;
-            lhs->children[0].locals = _slang_variable_scope_new(scope);
-
-#if 0
-            lhs->children[1].num_children = 1;
-            lhs->children[1].children = slang_operation_new(1);
-            lhs->children[1].children[0].type = SLANG_OPER_IDENTIFIER;
-            lhs->children[1].children[0].a_id = str->fields->variables[i]->a_name;
-            lhs->children[1].children->locals = _slang_variable_scope_new(scope);
-#endif
-         }
-
-         {
-            slang_operation *rhs = &assign->children[1];
-
-            rhs->type = SLANG_OPER_IDENTIFIER;
-            rhs->locals = _slang_variable_scope_new(scope);
-            rhs->a_id = str->fields->variables[i]->a_name;
-         }         
-      }
-
-      /* return t; */
-      {
-         slang_operation *ret = &fun->body->children[numFields + 1];
-
-         ret->type = SLANG_OPER_RETURN;
-         ret->locals = _slang_variable_scope_new(scope);
-         ret->num_children = 1;
-         ret->children = slang_operation_new(1);
-         ret->children[0].type = SLANG_OPER_IDENTIFIER;
-         ret->children[0].a_id = var->a_name;
-         ret->children[0].locals = _slang_variable_scope_new(scope);
-      }
-   }
-   /*
-   slang_print_function(fun, 1);
-   */
-   return fun;
-}
-
-
-/**
- * Find/create a function (constructor) for the given structure name.
- */
-static slang_function *
-_slang_locate_struct_constructor(slang_assemble_ctx *A, const char *name)
-{
-   unsigned int i;
-   for (i = 0; i < A->space.structs->num_structs; i++) {
-      slang_struct *str = &A->space.structs->structs[i];
-      if (strcmp(name, (const char *) str->a_name) == 0) {
-         /* found a structure type that matches the function name */
-         if (!str->constructor) {
-            /* create the constructor function now */
-            str->constructor = _slang_make_struct_constructor(A, str);
-         }
-         return str->constructor;
-      }
-   }
-   return NULL;
-}
-
-
-/**
- * Generate a new slang_function to satisfy a call to an array constructor.
- * Ex:  float[3](1., 2., 3.)
- */
-static slang_function *
-_slang_make_array_constructor(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_type_specifier_type baseType;
-   slang_function *fun;
-   int num_elements;
-
-   fun = slang_function_new(SLANG_FUNC_CONSTRUCTOR);
-   if (!fun)
-      return NULL;
-
-   baseType = slang_type_specifier_type_from_string((char *) oper->a_id);
-
-   num_elements = oper->num_children;
-
-   /* function header, return type */
-   {
-      fun->header.a_name = oper->a_id;
-      fun->header.type.qualifier = SLANG_QUAL_NONE;
-      fun->header.type.specifier.type = SLANG_SPEC_ARRAY;
-      fun->header.type.specifier._array =
-         slang_type_specifier_new(baseType, NULL, NULL);
-      fun->header.type.array_len = num_elements;
-   }
-
-   /* function parameters (= number of elements) */
-   {
-      GLint i;
-      for (i = 0; i < num_elements; i++) {
-         /*
-         printf("Field %d: %s\n", i, (char*) str->fields->variables[i]->a_name);
-         */
-         slang_variable *p = slang_variable_scope_grow(fun->parameters);
-         char name[10];
-         _mesa_snprintf(name, sizeof(name), "p%d", i);
-         p->a_name = slang_atom_pool_atom(A->atoms, name);
-         p->type.qualifier = SLANG_QUAL_CONST;
-         p->type.specifier.type = baseType;
-      }
-      fun->param_count = fun->parameters->num_variables;
-   }
-
-   /* Add __retVal to params */
-   {
-      slang_variable *p = slang_variable_scope_grow(fun->parameters);
-      slang_atom a_retVal = slang_atom_pool_atom(A->atoms, "__retVal");
-      assert(a_retVal);
-      p->a_name = a_retVal;
-      p->type = fun->header.type;
-      p->type.qualifier = SLANG_QUAL_OUT;
-      p->type.specifier.type = baseType;
-      fun->param_count++;
-   }
-
-   /* function body is:
-    *    block:
-    *       declare T;
-    *       T[0] = p0;
-    *       T[1] = p1;
-    *       ...
-    *       T[n] = pn;
-    *       return T;
-    */
-   {
-      slang_variable_scope *scope;
-      slang_variable *var;
-      GLint i;
-
-      fun->body = slang_operation_new(1);
-      fun->body->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-      fun->body->num_children = num_elements + 2;
-      fun->body->children = slang_operation_new(num_elements + 2);
-
-      scope = fun->body->locals;
-      scope->outer_scope = fun->parameters;
-
-      /* create local var 't' */
-      var = slang_variable_scope_grow(scope);
-      var->a_name = slang_atom_pool_atom(A->atoms, "ttt");
-      var->type = fun->header.type;/*XXX copy*/
-
-      /* declare t */
-      {
-         slang_operation *decl;
-
-         decl = &fun->body->children[0];
-         decl->type = SLANG_OPER_VARIABLE_DECL;
-         decl->locals = _slang_variable_scope_new(scope);
-         decl->a_id = var->a_name;
-      }
-
-      /* assign params to elements of t */
-      for (i = 0; i < num_elements; i++) {
-         slang_operation *assign = &fun->body->children[1 + i];
-
-         assign->type = SLANG_OPER_ASSIGN;
-         assign->locals = _slang_variable_scope_new(scope);
-         assign->num_children = 2;
-         assign->children = slang_operation_new(2);
-         
-         {
-            slang_operation *lhs = &assign->children[0];
-
-            lhs->type = SLANG_OPER_SUBSCRIPT;
-            lhs->locals = _slang_variable_scope_new(scope);
-            lhs->num_children = 2;
-            lhs->children = slang_operation_new(2);
-            lhs->children[0].type = SLANG_OPER_IDENTIFIER;
-            lhs->children[0].a_id = var->a_name;
-            lhs->children[0].locals = _slang_variable_scope_new(scope);
-
-            lhs->children[1].type = SLANG_OPER_LITERAL_INT;
-            lhs->children[1].literal[0] = (GLfloat) i;
-         }
-
-         {
-            slang_operation *rhs = &assign->children[1];
-
-            rhs->type = SLANG_OPER_IDENTIFIER;
-            rhs->locals = _slang_variable_scope_new(scope);
-            rhs->a_id = fun->parameters->variables[i]->a_name;
-         }         
-      }
-
-      /* return t; */
-      {
-         slang_operation *ret = &fun->body->children[num_elements + 1];
-
-         ret->type = SLANG_OPER_RETURN;
-         ret->locals = _slang_variable_scope_new(scope);
-         ret->num_children = 1;
-         ret->children = slang_operation_new(1);
-         ret->children[0].type = SLANG_OPER_IDENTIFIER;
-         ret->children[0].a_id = var->a_name;
-         ret->children[0].locals = _slang_variable_scope_new(scope);
-      }
-   }
-
-   /*
-   slang_print_function(fun, 1);
-   */
-
-   return fun;
-}
-
-
-static GLboolean
-_slang_is_vec_mat_type(const char *name)
-{
-   static const char *vecmat_types[] = {
-      "float", "int", "bool",
-      "vec2", "vec3", "vec4",
-      "ivec2", "ivec3", "ivec4",
-      "bvec2", "bvec3", "bvec4",
-      "mat2", "mat3", "mat4",
-      "mat2x3", "mat2x4", "mat3x2", "mat3x4", "mat4x2", "mat4x3",
-      NULL
-   };
-   int i;
-   for (i = 0; vecmat_types[i]; i++)
-      if (strcmp(name, vecmat_types[i]) == 0)
-         return GL_TRUE;
-   return GL_FALSE;
-}
-
-
-/**
- * Assemble a function call, given a particular function name.
- * \param name  the function's name (operators like '*' are possible).
- */
-static slang_ir_node *
-_slang_gen_function_call_name(slang_assemble_ctx *A, const char *name,
-                              slang_operation *oper, slang_operation *dest)
-{
-   slang_operation *params = oper->children;
-   const GLuint param_count = oper->num_children;
-   slang_atom atom;
-   slang_function *fun;
-   slang_ir_node *n;
-
-   atom = slang_atom_pool_atom(A->atoms, name);
-   if (atom == SLANG_ATOM_NULL)
-      return NULL;
-
-   if (oper->array_constructor) {
-      /* this needs special handling */
-      fun = _slang_make_array_constructor(A, oper);
-   }
-   else {
-      /* Try to find function by name and exact argument type matching */
-      GLboolean error = GL_FALSE;
-      fun = _slang_function_locate(A->space.funcs, atom, params, param_count,
-                                   &A->space, A->atoms, A->log, &error);
-      if (error) {
-         slang_info_log_error(A->log,
-                              "Function '%s' not found (check argument types)",
-                              name);
-         return NULL;
-      }
-   }
-
-   if (!fun) {
-      /* Next, try locating a constructor function for a user-defined type */
-      fun = _slang_locate_struct_constructor(A, name);
-   }
-
-   /*
-    * At this point, some heuristics are used to try to find a function
-    * that matches the calling signature by means of casting or "unrolling"
-    * of constructors.
-    */
-
-   if (!fun && _slang_is_vec_mat_type(name)) {
-      /* Next, if this call looks like a vec() or mat() constructor call,
-       * try "unwinding" the args to satisfy a constructor.
-       */
-      fun = _slang_find_function_by_max_argc(A->space.funcs, name);
-      if (fun) {
-         if (!_slang_adapt_call(oper, fun, &A->space, A->atoms, A->log)) {
-            slang_info_log_error(A->log,
-                                 "Function '%s' not found (check argument types)",
-                                 name);
-            return NULL;
-         }
-      }
-   }
-
-   if (!fun && _slang_is_vec_mat_type(name)) {
-      /* Next, try casting args to the types of the formal parameters */
-      int numArgs = oper->num_children;
-      fun = _slang_find_function_by_argc(A->space.funcs, name, numArgs);
-      if (!fun || !_slang_cast_func_params(oper, fun, &A->space, A->atoms, A->log)) {
-         slang_info_log_error(A->log,
-                              "Function '%s' not found (check argument types)",
-                              name);
-         return NULL;
-      }
-      assert(fun);
-   }
-
-   if (!fun) {
-      slang_info_log_error(A->log,
-                           "Function '%s' not found (check argument types)",
-                           name);
-      return NULL;
-   }
-
-   if (!fun->body) {
-      /* The function body may be in another compilation unit.
-       * We'll try concatenating the shaders and recompile at link time.
-       */
-      A->UnresolvedRefs = GL_TRUE;
-      return new_node1(IR_NOP, NULL);
-   }
-
-   /* type checking to be sure function's return type matches 'dest' type */
-   if (dest) {
-      slang_typeinfo t0;
-
-      slang_typeinfo_construct(&t0);
-      typeof_operation(A, dest, &t0);
-
-      if (!slang_type_specifier_equal(&t0.spec, &fun->header.type.specifier)) {
-         slang_info_log_error(A->log,
-                              "Incompatible type returned by call to '%s'",
-                              name);
-         return NULL;
-      }
-   }
-
-   n = _slang_gen_function_call(A, fun, oper, dest);
-
-   if (n && !n->Store && !dest
-       && fun->header.type.specifier.type != SLANG_SPEC_VOID) {
-      /* setup n->Store for the result of the function call */
-      GLint size = _slang_sizeof_type_specifier(&fun->header.type.specifier);
-      n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, size);
-      /*printf("Alloc storage for function result, size %d \n", size);*/
-   }
-
-   if (oper->array_constructor) {
-      /* free the temporary array constructor function now */
-      slang_function_destruct(fun);
-   }
-
-   return n;
-}
-
-
-static slang_ir_node *
-_slang_gen_method_call(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_atom *a_length = slang_atom_pool_atom(A->atoms, "length");
-   slang_ir_node *n;
-   slang_variable *var;
-
-   /* NOTE: In GLSL 1.20, there's only one kind of method
-    * call: array.length().  Anything else is an error.
-    */
-   if (oper->a_id != a_length) {
-      slang_info_log_error(A->log,
-                           "Undefined method call '%s'", (char *) oper->a_id);
-      return NULL;
-   }
-
-   /* length() takes no arguments */
-   if (oper->num_children > 0) {
-      slang_info_log_error(A->log, "Invalid arguments to length() method");
-      return NULL;
-   }
-
-   /* lookup the object/variable */
-   var = _slang_variable_locate(oper->locals, oper->a_obj, GL_TRUE);
-   if (!var || var->type.specifier.type != SLANG_SPEC_ARRAY) {
-      slang_info_log_error(A->log,
-                           "Undefined object '%s'", (char *) oper->a_obj);
-      return NULL;
-   }
-
-   /* Create a float/literal IR node encoding the array length */
-   n = new_node0(IR_FLOAT);
-   if (n) {
-      n->Value[0] = (float) _slang_array_length(var);
-      n->Store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, 1);
-   }
-   return n;
-}
-
-
-static GLboolean
-_slang_is_constant_cond(const slang_operation *oper, GLboolean *value)
-{
-   if (oper->type == SLANG_OPER_LITERAL_FLOAT ||
-       oper->type == SLANG_OPER_LITERAL_INT ||
-       oper->type == SLANG_OPER_LITERAL_BOOL) {
-      if (oper->literal[0])
-         *value = GL_TRUE;
-      else
-         *value = GL_FALSE;
-      return GL_TRUE;
-   }
-   else if (oper->type == SLANG_OPER_EXPRESSION &&
-            oper->num_children == 1) {
-      return _slang_is_constant_cond(&oper->children[0], value);
-   }
-   return GL_FALSE;
-}
-
-
-/**
- * Test if an operation is a scalar or boolean.
- */
-static GLboolean
-_slang_is_scalar_or_boolean(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_typeinfo type;
-   GLint size;
-
-   slang_typeinfo_construct(&type);
-   typeof_operation(A, oper, &type);
-   size = _slang_sizeof_type_specifier(&type.spec);
-   slang_typeinfo_destruct(&type);
-   return size == 1;
-}
-
-
-/**
- * Test if an operation is boolean.
- */
-static GLboolean
-_slang_is_boolean(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_typeinfo type;
-   GLboolean isBool;
-
-   slang_typeinfo_construct(&type);
-   typeof_operation(A, oper, &type);
-   isBool = (type.spec.type == SLANG_SPEC_BOOL);
-   slang_typeinfo_destruct(&type);
-   return isBool;
-}
-
-
-/**
- * Check if a loop contains a 'continue' statement.
- * Stop looking if we find a nested loop.
- */
-static GLboolean
-_slang_loop_contains_continue(const slang_operation *oper)
-{
-   switch (oper->type) {
-   case SLANG_OPER_CONTINUE:
-      return GL_TRUE;
-   case SLANG_OPER_FOR:
-   case SLANG_OPER_DO:
-   case SLANG_OPER_WHILE:
-      /* stop upon finding a nested loop */
-      return GL_FALSE;
-   default:
-       /* recurse */
-      {
-         GLuint i;
-         for (i = 0; i < oper->num_children; i++) {
-            const slang_operation *child = slang_oper_child_const(oper, i);
-            if (_slang_loop_contains_continue(child))
-               return GL_TRUE;
-         }
-      }
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Check if a loop contains a 'continue' or 'break' statement.
- * Stop looking if we find a nested loop.
- */
-static GLboolean
-_slang_loop_contains_continue_or_break(const slang_operation *oper)
-{
-   switch (oper->type) {
-   case SLANG_OPER_CONTINUE:
-   case SLANG_OPER_BREAK:
-      return GL_TRUE;
-   case SLANG_OPER_FOR:
-   case SLANG_OPER_DO:
-   case SLANG_OPER_WHILE:
-      /* stop upon finding a nested loop */
-      return GL_FALSE;
-   default:
-       /* recurse */
-      {
-         GLuint i;
-         for (i = 0; i < oper->num_children; i++) {
-            const slang_operation *child = slang_oper_child_const(oper, i);
-            if (_slang_loop_contains_continue_or_break(child))
-               return GL_TRUE;
-         }
-      }
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Replace 'break' and 'continue' statements inside a do and while loops.
- * This is a recursive helper function used by
- * _slang_gen_do/while_without_continue().
- */
-static void
-replace_break_and_cont(slang_assemble_ctx *A, slang_operation *oper)
-{
-   switch (oper->type) {
-   case SLANG_OPER_BREAK:
-      /* replace 'break' with "_notBreakFlag = false; break" */
-      {
-         slang_operation *block = oper;
-         block->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-         slang_operation_add_children(block, 2);
-         {
-            slang_operation *assign = slang_oper_child(block, 0);
-            assign->type = SLANG_OPER_ASSIGN;
-            slang_operation_add_children(assign, 2);
-            {
-               slang_operation *lhs = slang_oper_child(assign, 0);
-               slang_operation_identifier(lhs, A, "_notBreakFlag");
-            }
-            {
-               slang_operation *rhs = slang_oper_child(assign, 1);
-               slang_operation_literal_bool(rhs, GL_FALSE);
-            }
-         }
-         {
-            slang_operation *brk = slang_oper_child(block, 1);
-            brk->type = SLANG_OPER_BREAK;
-            assert(!brk->children);
-         }
-      }
-      break;
-   case SLANG_OPER_CONTINUE:
-      /* convert continue into a break */
-      oper->type = SLANG_OPER_BREAK;
-      break;
-   case SLANG_OPER_FOR:
-   case SLANG_OPER_DO:
-   case SLANG_OPER_WHILE:
-      /* stop upon finding a nested loop */
-      break;
-   default:
-      /* recurse */
-      {
-         GLuint i;
-         for (i = 0; i < oper->num_children; i++) {
-            replace_break_and_cont(A, slang_oper_child(oper, i));
-         }
-      }
-   }
-}
-
-
-/**
- * Transform a while-loop so that continue statements are converted to breaks.
- * Then do normal IR code generation.
- *
- * Before:
- * 
- * while (LOOPCOND) {
- *    A;
- *    if (IFCOND)
- *       continue;
- *    B;
- *    break;
- *    C;
- * }
- * 
- * After:
- * 
- * {
- *    bool _notBreakFlag = 1;
- *    while (_notBreakFlag && LOOPCOND) {
- *       do {
- *          A;
- *          if (IFCOND) {
- *             break;  // was continue
- *          }
- *          B;
- *          _notBreakFlag = 0; // was
- *          break;             // break
- *          C;
- *       } while (0)
- *    }
- * }
- */
-static slang_ir_node *
-_slang_gen_while_without_continue(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_operation *top;
-   slang_operation *innerBody;
-
-   assert(oper->type == SLANG_OPER_WHILE);
-
-   top = slang_operation_new(1);
-   top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-   top->locals->outer_scope = oper->locals->outer_scope;
-   slang_operation_add_children(top, 2);
-
-   /* declare: bool _notBreakFlag = true */
-   {
-      slang_operation *condDecl = slang_oper_child(top, 0);
-      slang_generate_declaration(A, top->locals, condDecl,
-                                 SLANG_SPEC_BOOL, "_notBreakFlag", GL_TRUE);
-   }
-
-   /* build outer while-loop:  while (_notBreakFlag && LOOPCOND) { ... } */
-   {
-      slang_operation *outerWhile = slang_oper_child(top, 1);
-      outerWhile->type = SLANG_OPER_WHILE;
-      slang_operation_add_children(outerWhile, 2);
-
-      /* _notBreakFlag && LOOPCOND */
-      {
-         slang_operation *cond = slang_oper_child(outerWhile, 0);
-         cond->type = SLANG_OPER_LOGICALAND;
-         slang_operation_add_children(cond, 2);
-         {
-            slang_operation *notBreak = slang_oper_child(cond, 0);
-            slang_operation_identifier(notBreak, A, "_notBreakFlag");
-         }
-         {
-            slang_operation *origCond = slang_oper_child(cond, 1);
-            slang_operation_copy(origCond, slang_oper_child(oper, 0));
-         }
-      }
-
-      /* inner loop */
-      {
-         slang_operation *innerDo = slang_oper_child(outerWhile, 1);
-         innerDo->type = SLANG_OPER_DO;
-         slang_operation_add_children(innerDo, 2);
-
-         /* copy original do-loop body into inner do-loop's body */
-         innerBody = slang_oper_child(innerDo, 0);
-         slang_operation_copy(innerBody, slang_oper_child(oper, 1));
-         innerBody->locals->outer_scope = innerDo->locals;
-
-         /* inner do-loop's condition is constant/false */
-         {
-            slang_operation *constFalse = slang_oper_child(innerDo, 1);
-            slang_operation_literal_bool(constFalse, GL_FALSE);
-         }
-      }
-   }
-
-   /* Finally, in innerBody,
-    *   replace "break" with "_notBreakFlag = 0; break"
-    *   replace "continue" with "break"
-    */
-   replace_break_and_cont(A, innerBody);
-
-   /*slang_print_tree(top, 0);*/
-
-   return _slang_gen_operation(A, top);
-
-   return NULL;
-}
-
-
-/**
- * Generate loop code using high-level IR_LOOP instruction
- */
-static slang_ir_node *
-_slang_gen_while(slang_assemble_ctx * A, slang_operation *oper)
-{
-   /*
-    * LOOP:
-    *    BREAK if !expr (child[0])
-    *    body code (child[1])
-    */
-   slang_ir_node *loop, *breakIf, *body;
-   GLboolean isConst, constTrue = GL_FALSE;
-
-   if (!A->EmitContReturn) {
-      /* We don't want to emit CONT instructions.  If this while-loop has
-       * a continue, translate it away.
-       */
-      if (_slang_loop_contains_continue(slang_oper_child(oper, 1))) {
-         return _slang_gen_while_without_continue(A, oper);
-      }
-   }
-
-   /* type-check expression */
-   if (!_slang_is_boolean(A, &oper->children[0])) {
-      slang_info_log_error(A->log, "scalar/boolean expression expected for 'while'");
-      return NULL;
-   }
-
-   /* Check if loop condition is a constant */
-   isConst = _slang_is_constant_cond(&oper->children[0], &constTrue);
-
-   if (isConst && !constTrue) {
-      /* loop is never executed! */
-      return new_node0(IR_NOP);
-   }
-
-   /* Begin new loop */
-   loop = new_loop(NULL);
-
-   /* save loop state */
-   push_loop(A, oper, loop);
-
-   if (isConst && constTrue) {
-      /* while(nonzero constant), no conditional break */
-      breakIf = NULL;
-   }
-   else {
-      slang_ir_node *cond
-         = new_cond(new_not(_slang_gen_operation(A, &oper->children[0])));
-      breakIf = new_break_if_true(A, cond);
-   }
-   body = _slang_gen_operation(A, &oper->children[1]);
-   loop->Children[0] = new_seq(breakIf, body);
-
-   /* Do infinite loop detection */
-   /* loop->List is head of linked list of break/continue nodes */
-   if (!loop->List && isConst && constTrue) {
-      /* infinite loop detected */
-      pop_loop(A);
-      slang_info_log_error(A->log, "Infinite loop detected!");
-      return NULL;
-   }
-
-   /* restore loop state */
-   pop_loop(A);
-
-   return loop;
-}
-
-
-/**
- * Transform a do-while-loop so that continue statements are converted to breaks.
- * Then do normal IR code generation.
- *
- * Before:
- * 
- * do {
- *    A;
- *    if (IFCOND)
- *       continue;
- *    B;
- *    break;
- *    C;
- * } while (LOOPCOND);
- * 
- * After:
- * 
- * {
- *    bool _notBreakFlag = 1;
- *    do {
- *       do {
- *          A;
- *          if (IFCOND) {
- *             break;  // was continue
- *          }
- *          B;
- *          _notBreakFlag = 0; // was
- *          break;             // break
- *          C;
- *       } while (0)
- *    } while (_notBreakFlag && LOOPCOND);
- * }
- */
-static slang_ir_node *
-_slang_gen_do_without_continue(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_operation *top;
-   slang_operation *innerBody;
-
-   assert(oper->type == SLANG_OPER_DO);
-
-   top = slang_operation_new(1);
-   top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-   top->locals->outer_scope = oper->locals->outer_scope;
-   slang_operation_add_children(top, 2);
-
-   /* declare: bool _notBreakFlag = true */
-   {
-      slang_operation *condDecl = slang_oper_child(top, 0);
-      slang_generate_declaration(A, top->locals, condDecl,
-                                 SLANG_SPEC_BOOL, "_notBreakFlag", GL_TRUE);
-   }
-
-   /* build outer do-loop:  do { ... } while (_notBreakFlag && LOOPCOND) */
-   {
-      slang_operation *outerDo = slang_oper_child(top, 1);
-      outerDo->type = SLANG_OPER_DO;
-      slang_operation_add_children(outerDo, 2);
-
-      /* inner do-loop */
-      {
-         slang_operation *innerDo = slang_oper_child(outerDo, 0);
-         innerDo->type = SLANG_OPER_DO;
-         slang_operation_add_children(innerDo, 2);
-
-         /* copy original do-loop body into inner do-loop's body */
-         innerBody = slang_oper_child(innerDo, 0);
-         slang_operation_copy(innerBody, slang_oper_child(oper, 0));
-         innerBody->locals->outer_scope = innerDo->locals;
-
-         /* inner do-loop's condition is constant/false */
-         {
-            slang_operation *constFalse = slang_oper_child(innerDo, 1);
-            slang_operation_literal_bool(constFalse, GL_FALSE);
-         }
-      }
-
-      /* _notBreakFlag && LOOPCOND */
-      {
-         slang_operation *cond = slang_oper_child(outerDo, 1);
-         cond->type = SLANG_OPER_LOGICALAND;
-         slang_operation_add_children(cond, 2);
-         {
-            slang_operation *notBreak = slang_oper_child(cond, 0);
-            slang_operation_identifier(notBreak, A, "_notBreakFlag");
-         }
-         {
-            slang_operation *origCond = slang_oper_child(cond, 1);
-            slang_operation_copy(origCond, slang_oper_child(oper, 1));
-         }
-      }
-   }
-
-   /* Finally, in innerBody,
-    *   replace "break" with "_notBreakFlag = 0; break"
-    *   replace "continue" with "break"
-    */
-   replace_break_and_cont(A, innerBody);
-
-   /*slang_print_tree(top, 0);*/
-
-   return _slang_gen_operation(A, top);
-}
-
-
-/**
- * Generate IR tree for a do-while loop using high-level LOOP, IF instructions.
- */
-static slang_ir_node *
-_slang_gen_do(slang_assemble_ctx * A, slang_operation *oper)
-{
-   /*
-    * LOOP:
-    *    body code (child[0])
-    *    tail code:
-    *       BREAK if !expr (child[1])
-    */
-   slang_ir_node *loop;
-   GLboolean isConst, constTrue;
-
-   if (!A->EmitContReturn) {
-      /* We don't want to emit CONT instructions.  If this do-loop has
-       * a continue, translate it away.
-       */
-      if (_slang_loop_contains_continue(slang_oper_child(oper, 0))) {
-         return _slang_gen_do_without_continue(A, oper);
-      }
-   }
-
-   /* type-check expression */
-   if (!_slang_is_boolean(A, &oper->children[1])) {
-      slang_info_log_error(A->log, "scalar/boolean expression expected for 'do/while'");
-      return NULL;
-   }
-
-   loop = new_loop(NULL);
-
-   /* save loop state */
-   push_loop(A, oper, loop);
-
-   /* loop body: */
-   loop->Children[0] = _slang_gen_operation(A, &oper->children[0]);
-
-   /* Check if loop condition is a constant */
-   isConst = _slang_is_constant_cond(&oper->children[1], &constTrue);
-   if (isConst && constTrue) {
-      /* do { } while(1)   ==> no conditional break */
-      loop->Children[1] = NULL; /* no tail code */
-   }
-   else {
-      slang_ir_node *cond
-         = new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
-      loop->Children[1] = new_break_if_true(A, cond);
-   }
-
-   /* XXX we should do infinite loop detection, as above */
-
-   /* restore loop state */
-   pop_loop(A);
-
-   return loop;
-}
-
-
-/**
- * Recursively count the number of operations rooted at 'oper'.
- * This gives some kind of indication of the size/complexity of an operation.
- */
-static GLuint
-sizeof_operation(const slang_operation *oper)
-{
-   if (oper) {
-      GLuint count = 1; /* me */
-      GLuint i;
-      for (i = 0; i < oper->num_children; i++) {
-         count += sizeof_operation(&oper->children[i]);
-      }
-      return count;
-   }
-   else {
-      return 0;
-   }
-}
-
-
-/**
- * Determine if a for-loop can be unrolled.
- * At this time, only a rather narrow class of for loops can be unrolled.
- * See code for details.
- * When a loop can't be unrolled because it's too large we'll emit a
- * message to the log.
- */
-static GLboolean
-_slang_can_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
-{
-   GLuint bodySize;
-   GLint start, end;
-   const char *varName;
-   slang_atom varId;
-
-   if (oper->type != SLANG_OPER_FOR)
-      return GL_FALSE;
-
-   assert(oper->num_children == 4);
-
-   if (_slang_loop_contains_continue_or_break(slang_oper_child_const(oper, 3)))
-      return GL_FALSE;
-
-   /* children[0] must be either "int i=constant" or "i=constant" */
-   if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
-      slang_variable *var;
-
-      if (oper->children[0].children[0].type != SLANG_OPER_VARIABLE_DECL)
-         return GL_FALSE;
-
-      varId = oper->children[0].children[0].a_id;
-
-      var = _slang_variable_locate(oper->children[0].children[0].locals,
-                                   varId, GL_TRUE);
-      if (!var)
-         return GL_FALSE;
-      if (!var->initializer)
-         return GL_FALSE;
-      if (var->initializer->type != SLANG_OPER_LITERAL_INT)
-         return GL_FALSE;
-      start = (GLint) var->initializer->literal[0];
-   }
-   else if (oper->children[0].type == SLANG_OPER_EXPRESSION) {
-      if (oper->children[0].children[0].type != SLANG_OPER_ASSIGN)
-         return GL_FALSE;
-      if (oper->children[0].children[0].children[0].type != SLANG_OPER_IDENTIFIER)
-         return GL_FALSE;
-      if (oper->children[0].children[0].children[1].type != SLANG_OPER_LITERAL_INT)
-         return GL_FALSE;
-
-      varId = oper->children[0].children[0].children[0].a_id;
-
-      start = (GLint) oper->children[0].children[0].children[1].literal[0];
-   }
-   else {
-      return GL_FALSE;
-   }
-
-   /* children[1] must be "i<constant" */
-   if (oper->children[1].type != SLANG_OPER_EXPRESSION)
-      return GL_FALSE;
-   if (oper->children[1].children[0].type != SLANG_OPER_LESS)
-      return GL_FALSE;
-   if (oper->children[1].children[0].children[0].type != SLANG_OPER_IDENTIFIER)
-      return GL_FALSE;
-   if (oper->children[1].children[0].children[1].type != SLANG_OPER_LITERAL_INT)
-      return GL_FALSE;
-
-   end = (GLint) oper->children[1].children[0].children[1].literal[0];
-
-   /* children[2] must be "i++" or "++i" */
-   if (oper->children[2].type != SLANG_OPER_POSTINCREMENT &&
-       oper->children[2].type != SLANG_OPER_PREINCREMENT)
-      return GL_FALSE;
-   if (oper->children[2].children[0].type != SLANG_OPER_IDENTIFIER)
-      return GL_FALSE;
-
-   /* make sure the same variable name is used in all places */
-   if ((oper->children[1].children[0].children[0].a_id != varId) ||
-       (oper->children[2].children[0].a_id != varId))
-      return GL_FALSE;
-
-   varName = (const char *) varId;
-
-   /* children[3], the loop body, can't be too large */
-   bodySize = sizeof_operation(&oper->children[3]);
-   if (bodySize > MAX_FOR_LOOP_UNROLL_BODY_SIZE) {
-      slang_info_log_print(A->log,
-                           "Note: 'for (%s ... )' body is too large/complex"
-                           " to unroll",
-                           varName);
-      return GL_FALSE;
-   }
-
-   if (start >= end)
-      return GL_FALSE; /* degenerate case */
-
-   if ((GLuint)(end - start) > MAX_FOR_LOOP_UNROLL_ITERATIONS) {
-      slang_info_log_print(A->log,
-                           "Note: 'for (%s=%d; %s<%d; ++%s)' is too"
-                           " many iterations to unroll",
-                           varName, start, varName, end, varName);
-      return GL_FALSE;
-   }
-
-   if ((end - start) * bodySize > MAX_FOR_LOOP_UNROLL_COMPLEXITY) {
-      slang_info_log_print(A->log,
-                           "Note: 'for (%s=%d; %s<%d; ++%s)' will generate"
-                           " too much code to unroll",
-                           varName, start, varName, end, varName);
-      return GL_FALSE;
-   }
-
-   return GL_TRUE; /* we can unroll the loop */
-}
-
-
-/**
- * Unroll a for-loop.
- * First we determine the number of iterations to unroll.
- * Then for each iteration:
- *   make a copy of the loop body
- *   replace instances of the loop variable with the current iteration value
- *   generate IR code for the body
- * \return pointer to generated IR code or NULL if error, out of memory, etc.
- */
-static slang_ir_node *
-_slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
-{
-   GLint start, end, iter;
-   slang_ir_node *n, *root = NULL;
-   slang_atom varId;
-
-   if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
-      /* for (int i=0; ... */
-      slang_variable *var;
-
-      varId = oper->children[0].children[0].a_id;
-      var = _slang_variable_locate(oper->children[0].children[0].locals,
-                                   varId, GL_TRUE);
-      assert(var);
-      start = (GLint) var->initializer->literal[0];
-   }
-   else {
-      /* for (i=0; ... */
-      varId = oper->children[0].children[0].children[0].a_id;
-      start = (GLint) oper->children[0].children[0].children[1].literal[0];
-   }
-
-   end = (GLint) oper->children[1].children[0].children[1].literal[0];
-
-   for (iter = start; iter < end; iter++) {
-      slang_operation *body;
-
-      /* make a copy of the loop body */
-      body = slang_operation_new(1);
-      if (!body)
-         return NULL;
-
-      if (!slang_operation_copy(body, &oper->children[3]))
-         return NULL;
-
-      /* in body, replace instances of 'varId' with literal 'iter' */
-      {
-         slang_variable *oldVar;
-         slang_operation *newOper;
-
-         oldVar = _slang_variable_locate(oper->locals, varId, GL_TRUE);
-         if (!oldVar) {
-            /* undeclared loop variable */
-            slang_operation_delete(body);
-            return NULL;
-         }
-
-         newOper = slang_operation_new(1);
-         newOper->type = SLANG_OPER_LITERAL_INT;
-         newOper->literal_size = 1;
-         newOper->literal[0] = (GLfloat) iter;
-
-         /* replace instances of the loop variable with newOper */
-         slang_substitute(A, body, 1, &oldVar, &newOper, GL_FALSE);
-      }
-
-      /* do IR codegen for body */
-      n = _slang_gen_operation(A, body);
-      if (!n)
-         return NULL;
-
-      root = new_seq(root, n);
-
-      slang_operation_delete(body);
-   }
-
-   return root;
-}
-
-
-/**
- * Replace 'continue' statement with 'break' inside a for-loop.
- * This is a recursive helper function used by _slang_gen_for_without_continue().
- */
-static void
-replace_continue_with_break(slang_assemble_ctx *A, slang_operation *oper)
-{
-   switch (oper->type) {
-   case SLANG_OPER_CONTINUE:
-      oper->type = SLANG_OPER_BREAK;
-      break;
-   case SLANG_OPER_FOR:
-   case SLANG_OPER_DO:
-   case SLANG_OPER_WHILE:
-      /* stop upon finding a nested loop */
-      break;
-   default:
-      /* recurse */
-      {
-         GLuint i;
-         for (i = 0; i < oper->num_children; i++) {
-            replace_continue_with_break(A, slang_oper_child(oper, i));
-         }
-      }
-   }
-}
-
-
-/**
- * Transform a for-loop so that continue statements are converted to breaks.
- * Then do normal IR code generation.
- *
- * Before:
- * 
- * for (INIT; LOOPCOND; INCR) {
- *    A;
- *    if (IFCOND) {
- *       continue;
- *    }
- *    B;
- * }
- * 
- * After:
- * 
- * {
- *    bool _condFlag = 1;
- *    for (INIT; _condFlag; ) {
- *       for ( ; _condFlag = LOOPCOND; INCR) {
- *          A;
- *          if (IFCOND) {
- *             break;
- *          }
- *          B;
- *       }
- *       if (_condFlag)
- *          INCR;
- *    }
- * }
- */
-static slang_ir_node *
-_slang_gen_for_without_continue(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_operation *top;
-   slang_operation *outerFor, *innerFor, *init, *cond, *incr;
-   slang_operation *lhs, *rhs;
-
-   assert(oper->type == SLANG_OPER_FOR);
-
-   top = slang_operation_new(1);
-   top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-   top->locals->outer_scope = oper->locals->outer_scope;
-   slang_operation_add_children(top, 2);
-
-   /* declare: bool _condFlag = true */
-   {
-      slang_operation *condDecl = slang_oper_child(top, 0);
-      slang_generate_declaration(A, top->locals, condDecl,
-                                 SLANG_SPEC_BOOL, "_condFlag", GL_TRUE);
-   }
-
-   /* build outer loop:  for (INIT; _condFlag; ) { */
-   outerFor = slang_oper_child(top, 1);
-   outerFor->type = SLANG_OPER_FOR;
-   slang_operation_add_children(outerFor, 4);
-
-   init = slang_oper_child(outerFor, 0);
-   slang_operation_copy(init, slang_oper_child(oper, 0));
-
-   cond = slang_oper_child(outerFor, 1);
-   cond->type = SLANG_OPER_IDENTIFIER;
-   cond->a_id = slang_atom_pool_atom(A->atoms, "_condFlag");
-
-   incr = slang_oper_child(outerFor, 2);
-   incr->type = SLANG_OPER_VOID;
-
-   /* body of the outer loop */
-   {
-      slang_operation *block = slang_oper_child(outerFor, 3);
-
-      slang_operation_add_children(block, 2);
-      block->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
-
-      /* build inner loop:  for ( ; _condFlag = LOOPCOND; INCR) { */
-      {
-         innerFor = slang_oper_child(block, 0);
-
-         /* make copy of orig loop */
-         slang_operation_copy(innerFor, oper);
-         assert(innerFor->type == SLANG_OPER_FOR);
-         innerFor->locals->outer_scope = block->locals;
-
-         init = slang_oper_child(innerFor, 0);
-         init->type = SLANG_OPER_VOID; /* leak? */
-
-         cond = slang_oper_child(innerFor, 1);
-         slang_operation_destruct(cond);
-         cond->type = SLANG_OPER_ASSIGN;
-         cond->locals = _slang_variable_scope_new(innerFor->locals);
-         slang_operation_add_children(cond, 2);
-
-         lhs = slang_oper_child(cond, 0);
-         lhs->type = SLANG_OPER_IDENTIFIER;
-         lhs->a_id = slang_atom_pool_atom(A->atoms, "_condFlag");
-
-         rhs = slang_oper_child(cond, 1);
-         slang_operation_copy(rhs, slang_oper_child(oper, 1));
-      }
-
-      /* if (_condFlag) INCR; */
-      {
-         slang_operation *ifop = slang_oper_child(block, 1);
-         ifop->type = SLANG_OPER_IF;
-         slang_operation_add_children(ifop, 2);
-
-         /* re-use cond node build above */
-         slang_operation_copy(slang_oper_child(ifop, 0), cond);
-
-         /* incr node from original for-loop operation */
-         slang_operation_copy(slang_oper_child(ifop, 1),
-                              slang_oper_child(oper, 2));
-      }
-
-      /* finally, replace "continue" with "break" in the inner for-loop */
-      replace_continue_with_break(A, slang_oper_child(innerFor, 3));
-   }
-
-   return _slang_gen_operation(A, top);
-}
-
-
-
-/**
- * Generate IR for a for-loop.  Unrolling will be done when possible.
- */
-static slang_ir_node *
-_slang_gen_for(slang_assemble_ctx * A, slang_operation *oper)
-{
-   GLboolean unroll;
-
-   if (!A->EmitContReturn) {
-      /* We don't want to emit CONT instructions.  If this for-loop has
-       * a continue, translate it away.
-       */
-      if (_slang_loop_contains_continue(slang_oper_child(oper, 3))) {
-         return _slang_gen_for_without_continue(A, oper);
-      }
-   }
-
-   unroll = _slang_can_unroll_for_loop(A, oper);
-   if (unroll) {
-      slang_ir_node *code = _slang_unroll_for_loop(A, oper);
-      if (code)
-         return code;
-   }
-
-   assert(oper->type == SLANG_OPER_FOR);
-
-   /* conventional for-loop code generation */
-   {
-      /*
-       * init code (child[0])
-       * LOOP:
-       *    BREAK if !expr (child[1])
-       *    body code (child[3])
-       *    tail code:
-       *       incr code (child[2])   // XXX continue here
-       */
-      slang_ir_node *loop, *cond, *breakIf, *body, *init, *incr;
-      init = _slang_gen_operation(A, &oper->children[0]);
-      loop = new_loop(NULL);
-
-      /* save loop state */
-      push_loop(A, oper, loop);
-
-      cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
-      breakIf = new_break_if_true(A, cond);
-      body = _slang_gen_operation(A, &oper->children[3]);
-      incr = _slang_gen_operation(A, &oper->children[2]);
-
-      loop->Children[0] = new_seq(breakIf, body);
-      loop->Children[1] = incr;  /* tail code */
-
-      /* restore loop state */
-      pop_loop(A);
-
-      return new_seq(init, loop);
-   }
-}
-
-
-static slang_ir_node *
-_slang_gen_continue(slang_assemble_ctx * A, const slang_operation *oper)
-{
-   slang_ir_node *n, *cont, *incr = NULL, *loopNode;
-
-   assert(oper->type == SLANG_OPER_CONTINUE);
-   loopNode = current_loop_ir(A);
-   assert(loopNode);
-   assert(loopNode->Opcode == IR_LOOP);
-
-   cont = new_node0(IR_CONT);
-   if (cont) {
-      cont->Parent = loopNode;
-      /* insert this node at head of linked list of cont/break instructions */
-      cont->List = loopNode->List;
-      loopNode->List = cont;
-   }
-
-   n = new_seq(incr, cont);
-   return n;
-}
-
-
-/**
- * Determine if the given operation is of a specific type.
- */
-static GLboolean
-is_operation_type(const slang_operation *oper, slang_operation_type type)
-{
-   if (oper->type == type)
-      return GL_TRUE;
-   else if ((oper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
-             oper->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) &&
-            oper->num_children == 1)
-      return is_operation_type(&oper->children[0], type);
-   else
-      return GL_FALSE;
-}
-
-
-/**
- * Generate IR tree for an if/then/else conditional using high-level
- * IR_IF instruction.
- */
-static slang_ir_node *
-_slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
-{
-   /*
-    * eval expr (child[0])
-    * IF expr THEN
-    *    if-body code
-    * ELSE
-    *    else-body code
-    * ENDIF
-    */
-   const GLboolean haveElseClause = !_slang_is_noop(&oper->children[2]);
-   slang_ir_node *ifNode, *cond, *ifBody, *elseBody;
-   GLboolean isConst, constTrue;
-
-   /* type-check expression */
-   if (!_slang_is_boolean(A, &oper->children[0])) {
-      slang_info_log_error(A->log, "boolean expression expected for 'if'");
-      return NULL;
-   }
-
-   if (!_slang_is_scalar_or_boolean(A, &oper->children[0])) {
-      slang_info_log_error(A->log, "scalar/boolean expression expected for 'if'");
-      return NULL;
-   }
-
-   isConst = _slang_is_constant_cond(&oper->children[0], &constTrue);
-   if (isConst) {
-      if (constTrue) {
-         /* if (true) ... */
-         return _slang_gen_operation(A, &oper->children[1]);
-      }
-      else {
-         /* if (false) ... */
-         return _slang_gen_operation(A, &oper->children[2]);
-      }
-   }
-
-   cond = _slang_gen_operation(A, &oper->children[0]);
-   cond = new_cond(cond);
-
-   if (is_operation_type(&oper->children[1], SLANG_OPER_BREAK)
-       && !haveElseClause) {
-      /* Special case: generate a conditional break */
-      ifBody = new_break_if_true(A, cond);
-      return ifBody;
-   }
-   else if (is_operation_type(&oper->children[1], SLANG_OPER_CONTINUE)
-            && !haveElseClause
-            && current_loop_oper(A)
-            && current_loop_oper(A)->type != SLANG_OPER_FOR) {
-      /* Special case: generate a conditional continue */
-      ifBody = new_cont_if_true(A, cond);
-      return ifBody;
-   }
-   else {
-      /* general case */
-      ifBody = _slang_gen_operation(A, &oper->children[1]);
-      if (haveElseClause)
-         elseBody = _slang_gen_operation(A, &oper->children[2]);
-      else
-         elseBody = NULL;
-      ifNode = new_if(cond, ifBody, elseBody);
-      return ifNode;
-   }
-}
-
-
-
-static slang_ir_node *
-_slang_gen_not(slang_assemble_ctx * A, const slang_operation *oper)
-{
-   slang_ir_node *n;
-
-   assert(oper->type == SLANG_OPER_NOT);
-
-   /* type-check expression */
-   if (!_slang_is_scalar_or_boolean(A, &oper->children[0])) {
-      slang_info_log_error(A->log,
-                           "scalar/boolean expression expected for '!'");
-      return NULL;
-   }
-
-   n = _slang_gen_operation(A, &oper->children[0]);
-   if (n)
-      return new_not(n);
-   else
-      return NULL;
-}
-
-
-static slang_ir_node *
-_slang_gen_xor(slang_assemble_ctx * A, const slang_operation *oper)
-{
-   slang_ir_node *n1, *n2;
-
-   assert(oper->type == SLANG_OPER_LOGICALXOR);
-
-   if (!_slang_is_scalar_or_boolean(A, &oper->children[0]) ||
-       !_slang_is_scalar_or_boolean(A, &oper->children[0])) {
-      slang_info_log_error(A->log,
-                           "scalar/boolean expressions expected for '^^'");
-      return NULL;
-   }
-
-   n1 = _slang_gen_operation(A, &oper->children[0]);
-   if (!n1)
-      return NULL;
-   n2 = _slang_gen_operation(A, &oper->children[1]);
-   if (!n2)
-      return NULL;
-   return new_node2(IR_NOTEQUAL, n1, n2);
-}
-
-
-/**
- * Generate IR node for storage of a temporary of given size.
- */
-static slang_ir_node *
-_slang_gen_temporary(GLint size)
-{
-   slang_ir_storage *store;
-   slang_ir_node *n = NULL;
-
-   store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -2, size);
-   if (store) {
-      n = new_node0(IR_VAR_DECL);
-      if (n) {
-         n->Store = store;
-      }
-      else {
-         _slang_free(store);
-      }
-   }
-   return n;
-}
-
-
-/**
- * Generate program constants for an array.
- * Ex: const vec2[3] v = vec2[3](vec2(1,1), vec2(2,2), vec2(3,3));
- * This will allocate and initialize three vector constants, storing
- * the array in constant memory, not temporaries like a non-const array.
- * This can also be used for uniform array initializers.
- * \return GL_TRUE for success, GL_FALSE if failure (semantic error, etc).
- */
-static GLboolean
-make_constant_array(slang_assemble_ctx *A,
-                    slang_variable *var,
-                    slang_operation *initializer)
-{
-   struct gl_program *prog = A->program;
-   const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
-   const char *varName = (char *) var->a_name;
-   const GLuint numElements = initializer->num_children;
-   GLint size;
-   GLuint i, j;
-   GLfloat *values;
-
-   if (!var->store) {
-      var->store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -6, -6);
-   }
-   size = var->store->Size;
-
-   assert(var->type.qualifier == SLANG_QUAL_CONST ||
-          var->type.qualifier == SLANG_QUAL_UNIFORM);
-   assert(initializer->type == SLANG_OPER_CALL);
-   assert(initializer->array_constructor);
-
-   values = (GLfloat *) malloc(numElements * 4 * sizeof(GLfloat));
-
-   /* convert constructor params into ordinary floats */
-   for (i = 0; i < numElements; i++) {
-      const slang_operation *op = &initializer->children[i];
-      if (op->type != SLANG_OPER_LITERAL_FLOAT) {
-         /* unsupported type for this optimization */
-         free(values);
-         return GL_FALSE;
-      }
-      for (j = 0; j < op->literal_size; j++) {
-         values[i * 4 + j] = op->literal[j];
-      }
-      for ( ; j < 4; j++) {
-         values[i * 4 + j] = 0.0f;
-      }
-   }
-
-   /* slightly different paths for constants vs. uniforms */
-   if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
-      var->store->File = PROGRAM_UNIFORM;
-      var->store->Index = _mesa_add_uniform(prog->Parameters, varName,
-                                            size, datatype, values);
-   }
-   else {
-      var->store->File = PROGRAM_CONSTANT;
-      var->store->Index = _mesa_add_named_constant(prog->Parameters, varName,
-                                                   values, size);
-   }
-   assert(var->store->Size == size);
-
-   free(values);
-
-   return GL_TRUE;
-}
-
-
-
-/**
- * Generate IR node for allocating/declaring a variable (either a local or
- * a global).
- * Generally, this involves allocating an slang_ir_storage instance for the
- * variable, choosing a register file (temporary, constant, etc).
- * For ordinary variables we do not yet allocate storage though.  We do that
- * when we find the first actual use of the variable to avoid allocating temp
- * regs that will never get used.
- * At this time, uniforms are always allocated space in this function.
- *
- * \param initializer  Optional initializer expression for the variable.
- */
-static slang_ir_node *
-_slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
-                    slang_operation *initializer)
-{
-   const char *varName = (const char *) var->a_name;
-   const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
-   slang_ir_node *varDecl, *n;
-   slang_ir_storage *store;
-   GLint arrayLen, size, totalSize;  /* if array then totalSize > size */
-   gl_register_file file;
-
-   /*assert(!var->declared);*/
-   var->declared = GL_TRUE;
-
-   /* determine GPU register file for simple cases */
-   if (is_sampler_type(&var->type)) {
-      file = PROGRAM_SAMPLER;
-   }
-   else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
-      file = PROGRAM_UNIFORM;
-   }
-   else {
-      file = PROGRAM_TEMPORARY;
-   }
-
-   size = _slang_sizeof_type_specifier(&var->type.specifier);
-   if (size <= 0) {
-      slang_info_log_error(A->log, "invalid declaration for '%s'", varName);
-      return NULL;
-   }
-
-   arrayLen = _slang_array_length(var);
-   totalSize = _slang_array_size(size, arrayLen);
-
-   /* Allocate IR node for the declaration */
-   varDecl = new_node0(IR_VAR_DECL);
-   if (!varDecl)
-      return NULL;
-
-   /* Allocate slang_ir_storage for this variable if needed.
-    * Note that we may not actually allocate a constant or temporary register
-    * until later.
-    */
-   if (!var->store) {
-      GLint index = -7;  /* TBD / unknown */
-      var->store = _slang_new_ir_storage(file, index, totalSize);
-      if (!var->store)
-         return NULL; /* out of memory */
-   }
-
-   /* set the IR node's Var and Store pointers */
-   varDecl->Var = var;
-   varDecl->Store = var->store;
-
-
-   store = var->store;
-
-   /* if there's an initializer, generate IR for the expression */
-   if (initializer) {
-      slang_ir_node *varRef, *init;
-
-      if (var->type.qualifier == SLANG_QUAL_CONST) {
-         /* if the variable is const, the initializer must be a const
-          * expression as well.
-          */
-#if 0
-         if (!_slang_is_constant_expr(initializer)) {
-            slang_info_log_error(A->log,
-                                 "initializer for %s not constant", varName);
-            return NULL;
-         }
-#endif
-      }
-
-      if (var->type.qualifier == SLANG_QUAL_UNIFORM &&
-          !A->allow_uniform_initializers) {
-         slang_info_log_error(A->log,
-                              "initializer for uniform %s not allowed",
-                              varName);
-         return NULL;
-      }
-
-      /* IR for the variable we're initializing */
-      varRef = new_var(A, var);
-      if (!varRef) {
-         slang_info_log_error(A->log, "out of memory");
-         return NULL;
-      }
-
-      /* constant-folding, etc here */
-      _slang_simplify(initializer, &A->space, A->atoms); 
-
-      /* look for simple constant-valued variables and uniforms */
-      if (var->type.qualifier == SLANG_QUAL_CONST ||
-          var->type.qualifier == SLANG_QUAL_UNIFORM) {
-
-         if (initializer->type == SLANG_OPER_CALL &&
-             initializer->array_constructor) {
-            /* array initializer */
-            if (make_constant_array(A, var, initializer))
-               return varRef;
-         }
-         else if (initializer->type == SLANG_OPER_LITERAL_FLOAT ||
-                  initializer->type == SLANG_OPER_LITERAL_INT) {
-            /* simple float/vector initializer */
-            if (store->File == PROGRAM_UNIFORM) {
-               store->Index = _mesa_add_uniform(A->program->Parameters,
-                                                varName,
-                                                totalSize, datatype,
-                                                initializer->literal);
-               store->Swizzle = _slang_var_swizzle(size, 0);
-               return varRef;
-            }
-#if 0
-            else {
-               store->File = PROGRAM_CONSTANT;
-               store->Index = _mesa_add_named_constant(A->program->Parameters,
-                                                       varName,
-                                                       initializer->literal,
-                                                       totalSize);
-               store->Swizzle = _slang_var_swizzle(size, 0);
-               return varRef;
-            }
-#endif
-         }
-      }
-
-      /* IR for initializer */
-      init = _slang_gen_operation(A, initializer);
-      if (!init)
-         return NULL;
-
-      /* XXX remove this when type checking is added above */
-      if (init->Store && init->Store->Size != totalSize) {
-         slang_info_log_error(A->log, "invalid assignment (wrong types)");
-         return NULL;
-      }
-
-      /* assign RHS to LHS */
-      n = new_node2(IR_COPY, varRef, init);
-      n = new_seq(varDecl, n);
-   }
-   else {
-      /* no initializer */
-      n = varDecl;
-   }
-
-   if (store->File == PROGRAM_UNIFORM && store->Index < 0) {
-      /* always need to allocate storage for uniforms at this point */
-      store->Index = _mesa_add_uniform(A->program->Parameters, varName,
-                                       totalSize, datatype, NULL);
-      store->Swizzle = _slang_var_swizzle(size, 0);
-   }
-
-#if 0
-   printf("%s var %p %s  store=%p index=%d size=%d\n",
-          __FUNCTION__, (void *) var, (char *) varName,
-          (void *) store, store->Index, store->Size);
-#endif
-
-   return n;
-}
-
-
-/**
- * Generate code for a selection expression:   b ? x : y
- * XXX In some cases we could implement a selection expression
- * with an LRP instruction (use the boolean as the interpolant).
- * Otherwise, we use an IF/ELSE/ENDIF construct.
- */
-static slang_ir_node *
-_slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
-{
-   slang_ir_node *cond, *ifNode, *trueExpr, *falseExpr, *trueNode, *falseNode;
-   slang_ir_node *tmpDecl, *tmpVar, *tree;
-   slang_typeinfo type0, type1, type2;
-   int size, isBool, isEqual;
-
-   assert(oper->type == SLANG_OPER_SELECT);
-   assert(oper->num_children == 3);
-
-   /* type of children[0] must be boolean */
-   slang_typeinfo_construct(&type0);
-   typeof_operation(A, &oper->children[0], &type0);
-   isBool = (type0.spec.type == SLANG_SPEC_BOOL);
-   slang_typeinfo_destruct(&type0);
-   if (!isBool) {
-      slang_info_log_error(A->log, "selector type is not boolean");
-      return NULL;
-   }
-
-   slang_typeinfo_construct(&type1);
-   slang_typeinfo_construct(&type2);
-   typeof_operation(A, &oper->children[1], &type1);
-   typeof_operation(A, &oper->children[2], &type2);
-   isEqual = slang_type_specifier_equal(&type1.spec, &type2.spec);
-   slang_typeinfo_destruct(&type1);
-   slang_typeinfo_destruct(&type2);
-   if (!isEqual) {
-      slang_info_log_error(A->log, "incompatible types for ?: operator");
-      return NULL;
-   }
-
-   /* size of x or y's type */
-   size = _slang_sizeof_type_specifier(&type1.spec);
-   assert(size > 0);
-
-   /* temporary var */
-   tmpDecl = _slang_gen_temporary(size);
-
-   /* the condition (child 0) */
-   cond = _slang_gen_operation(A, &oper->children[0]);
-   cond = new_cond(cond);
-
-   /* if-true body (child 1) */
-   tmpVar = new_node0(IR_VAR);
-   tmpVar->Store = tmpDecl->Store;
-   trueExpr = _slang_gen_operation(A, &oper->children[1]);
-   trueNode = new_node2(IR_COPY, tmpVar, trueExpr);
-
-   /* if-false body (child 2) */
-   tmpVar = new_node0(IR_VAR);
-   tmpVar->Store = tmpDecl->Store;
-   falseExpr = _slang_gen_operation(A, &oper->children[2]);
-   falseNode = new_node2(IR_COPY, tmpVar, falseExpr);
-
-   ifNode = new_if(cond, trueNode, falseNode);
-
-   /* tmp var value */
-   tmpVar = new_node0(IR_VAR);
-   tmpVar->Store = tmpDecl->Store;
-
-   tree = new_seq(ifNode, tmpVar);
-   tree = new_seq(tmpDecl, tree);
-
-   /*_slang_print_ir_tree(tree, 10);*/
-   return tree;
-}
-
-
-/**
- * Generate code for &&.
- */
-static slang_ir_node *
-_slang_gen_logical_and(slang_assemble_ctx *A, slang_operation *oper)
-{
-   /* rewrite "a && b" as  "a ? b : false" */
-   slang_operation *select;
-   slang_ir_node *n;
-
-   select = slang_operation_new(1);
-   select->type = SLANG_OPER_SELECT;
-   slang_operation_add_children(select, 3);
-
-   slang_operation_copy(slang_oper_child(select, 0), &oper->children[0]);
-   slang_operation_copy(slang_oper_child(select, 1), &oper->children[1]);
-   slang_operation_literal_bool(slang_oper_child(select, 2), GL_FALSE);
-
-   n = _slang_gen_select(A, select);
-   return n;
-}
-
-
-/**
- * Generate code for ||.
- */
-static slang_ir_node *
-_slang_gen_logical_or(slang_assemble_ctx *A, slang_operation *oper)
-{
-   /* rewrite "a || b" as  "a ? true : b" */
-   slang_operation *select;
-   slang_ir_node *n;
-
-   select = slang_operation_new(1);
-   select->type = SLANG_OPER_SELECT;
-   slang_operation_add_children(select, 3);
-
-   slang_operation_copy(slang_oper_child(select, 0), &oper->children[0]);
-   slang_operation_literal_bool(slang_oper_child(select, 1), GL_TRUE);
-   slang_operation_copy(slang_oper_child(select, 2), &oper->children[1]);
-
-   n = _slang_gen_select(A, select);
-   return n;
-}
-
-
-/**
- * Generate IR tree for a return statement.
- */
-static slang_ir_node *
-_slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
-{
-   assert(oper->type == SLANG_OPER_RETURN);
-   return new_return(A->curFuncEndLabel);
-}
-
-
-#if 0
-/**
- * Determine if the given operation/expression is const-valued.
- */
-static GLboolean
-_slang_is_constant_expr(const slang_operation *oper)
-{
-   slang_variable *var;
-   GLuint i;
-
-   switch (oper->type) {
-   case SLANG_OPER_IDENTIFIER:
-      var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
-      if (var && var->type.qualifier == SLANG_QUAL_CONST)
-         return GL_TRUE;
-      return GL_FALSE;
-   default:
-      for (i = 0; i < oper->num_children; i++) {
-         if (!_slang_is_constant_expr(&oper->children[i]))
-            return GL_FALSE;
-      }
-      return GL_TRUE;
-   }
-}
-#endif
-
-
-/**
- * Check if an assignment of type t1 to t0 is legal.
- * XXX more cases needed.
- */
-static GLboolean
-_slang_assignment_compatible(slang_assemble_ctx *A,
-                             slang_operation *op0,
-                             slang_operation *op1)
-{
-   slang_typeinfo t0, t1;
-   GLuint sz0, sz1;
-
-   if (op0->type == SLANG_OPER_POSTINCREMENT ||
-       op0->type == SLANG_OPER_POSTDECREMENT) {
-      return GL_FALSE;
-   }
-
-   slang_typeinfo_construct(&t0);
-   typeof_operation(A, op0, &t0);
-
-   slang_typeinfo_construct(&t1);
-   typeof_operation(A, op1, &t1);
-
-   sz0 = _slang_sizeof_type_specifier(&t0.spec);
-   sz1 = _slang_sizeof_type_specifier(&t1.spec);
-
-#if 1
-   if (sz0 != sz1) {
-      /*printf("assignment size mismatch %u vs %u\n", sz0, sz1);*/
-      return GL_FALSE;
-   }
-#endif
-
-   if (t0.spec.type == SLANG_SPEC_STRUCT &&
-       t1.spec.type == SLANG_SPEC_STRUCT &&
-       t0.spec._struct->a_name != t1.spec._struct->a_name)
-      return GL_FALSE;
-
-   if (t0.spec.type == SLANG_SPEC_FLOAT &&
-       t1.spec.type == SLANG_SPEC_BOOL)
-      return GL_FALSE;
-
-#if 0 /* not used just yet - causes problems elsewhere */
-   if (t0.spec.type == SLANG_SPEC_INT &&
-       t1.spec.type == SLANG_SPEC_FLOAT)
-      return GL_FALSE;
-#endif
-
-   if (t0.spec.type == SLANG_SPEC_BOOL &&
-       t1.spec.type == SLANG_SPEC_FLOAT)
-      return GL_FALSE;
-
-   if (t0.spec.type == SLANG_SPEC_BOOL &&
-       t1.spec.type == SLANG_SPEC_INT)
-      return GL_FALSE;
-
-   return GL_TRUE;
-}
-
-
-/**
- * Generate IR tree for a local variable declaration.
- * Basically do some error checking and call _slang_gen_var_decl().
- */
-static slang_ir_node *
-_slang_gen_declaration(slang_assemble_ctx *A, slang_operation *oper)
-{
-   const char *varName = (char *) oper->a_id;
-   slang_variable *var;
-   slang_ir_node *varDecl;
-   slang_operation *initializer;
-
-   assert(oper->type == SLANG_OPER_VARIABLE_DECL);
-   assert(oper->num_children <= 1);
-
-
-   /* lookup the variable by name */
-   var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
-   if (!var)
-      return NULL;  /* "shouldn't happen" */
-
-   if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE ||
-       var->type.qualifier == SLANG_QUAL_VARYING ||
-       var->type.qualifier == SLANG_QUAL_UNIFORM) {
-      /* can't declare attribute/uniform vars inside functions */
-      slang_info_log_error(A->log,
-                "local variable '%s' cannot be an attribute/uniform/varying",
-                varName);
-      return NULL;
-   }
-
-#if 0
-   if (v->declared) {
-      slang_info_log_error(A->log, "variable '%s' redeclared", varName);
-      return NULL;
-   }
-#endif
-
-   /* check if the var has an initializer */
-   if (oper->num_children > 0) {
-      assert(oper->num_children == 1);
-      initializer = &oper->children[0];
-   }
-   else if (var->initializer) {
-      initializer = var->initializer;
-   }
-   else {
-      initializer = NULL;
-   }
-
-   if (initializer) {
-      /* check/compare var type and initializer type */
-      if (!_slang_assignment_compatible(A, oper, initializer)) {
-         slang_info_log_error(A->log, "incompatible types in assignment");
-         return NULL;
-      }         
-   }
-   else {
-      if (var->type.qualifier == SLANG_QUAL_CONST) {
-         slang_info_log_error(A->log,
-                       "const-qualified variable '%s' requires initializer",
-                       varName);
-         return NULL;
-      }
-   }
-
-   /* Generate IR node */
-   varDecl = _slang_gen_var_decl(A, var, initializer);
-   if (!varDecl)
-      return NULL;
-
-   return varDecl;
-}
-
-
-/**
- * Generate IR tree for a reference to a variable (such as in an expression).
- * This is different from a variable declaration.
- */
-static slang_ir_node *
-_slang_gen_variable(slang_assemble_ctx * A, slang_operation *oper)
-{
-   /* If there's a variable associated with this oper (from inlining)
-    * use it.  Otherwise, use the oper's var id.
-    */
-   slang_atom name = oper->var ? oper->var->a_name : oper->a_id;
-   slang_variable *var = _slang_variable_locate(oper->locals, name, GL_TRUE);
-   slang_ir_node *n;
-   if (!var || !var->declared) {
-      /* Geometry shaders set gl_VerticesIn at link time
-       * so we need to wait with resolving this variable
-       * until then */
-      if (A->program->Target == MESA_GEOMETRY_PROGRAM &&
-          !strcmp((char*)name, "gl_VerticesIn") ){
-         A->UnresolvedRefs = GL_TRUE;
-         return NULL;
-      }
-      slang_info_log_error(A->log, "undefined variable '%s'", (char *) name);
-      return NULL;
-   }
-   n = new_var(A, var);
-   return n;
-}
-
-
-
-/**
- * Return the number of components actually named by the swizzle.
- * Recall that swizzles may have undefined/don't-care values.
- */
-static GLuint
-swizzle_size(GLuint swizzle)
-{
-   GLuint size = 0, i;
-   for (i = 0; i < 4; i++) {
-      GLuint swz = GET_SWZ(swizzle, i);
-      size += (swz <= 3);
-   }
-   return size;
-}
-
-
-static slang_ir_node *
-_slang_gen_swizzle(slang_ir_node *child, GLuint swizzle)
-{
-   slang_ir_node *n = new_node1(IR_SWIZZLE, child);
-   assert(child);
-   if (n) {
-      assert(!n->Store);
-      n->Store = _slang_new_ir_storage_relative(0,
-                                                swizzle_size(swizzle),
-                                                child->Store);
-      assert(n->Store);
-      n->Store->Swizzle = swizzle;
-   }
-   return n;
-}
-
-
-static GLboolean
-is_store_writable(const slang_assemble_ctx *A, const slang_ir_storage *store)
-{
-   while (store->Parent)
-      store = store->Parent;
-
-   if (!(store->File == PROGRAM_OUTPUT ||
-         store->File == PROGRAM_TEMPORARY ||
-         (store->File == PROGRAM_VARYING &&
-          (A->program->Target == GL_VERTEX_PROGRAM_ARB ||
-           A->program->Target == MESA_GEOMETRY_PROGRAM)))) {
-      return GL_FALSE;
-   }
-   else {
-      return GL_TRUE;
-   }
-}
-
-
-/**
- * Walk up an IR storage path to compute the final swizzle.
- * This is used when we find an expression such as "foo.xz.yx".
- */
-static GLuint
-root_swizzle(const slang_ir_storage *st)
-{
-   GLuint swizzle = st->Swizzle;
-   while (st->Parent) {
-      st = st->Parent;
-      swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
-   }
-   return swizzle;
-}
-
-
-/**
- * Generate IR tree for an assignment (=).
- */
-static slang_ir_node *
-_slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)
-{
-   slang_operation *pred = NULL;
-   slang_ir_node *n = NULL;
-
-   if (oper->children[0].type == SLANG_OPER_IDENTIFIER) {
-      /* Check that var is writeable */
-      const char *varName = (char *) oper->children[0].a_id;
-      slang_variable *var
-         = _slang_variable_locate(oper->children[0].locals,
-                                  oper->children[0].a_id, GL_TRUE);
-      if (!var) {
-         slang_info_log_error(A->log, "undefined variable '%s'", varName);
-         return NULL;
-      }
-
-      if (var->type.qualifier == SLANG_QUAL_CONST ||
-          var->type.qualifier == SLANG_QUAL_ATTRIBUTE ||
-          var->type.qualifier == SLANG_QUAL_UNIFORM ||
-          (var->type.qualifier == SLANG_QUAL_VARYING &&
-           A->program->Target == GL_FRAGMENT_PROGRAM_ARB)) {
-         slang_info_log_error(A->log,
-                              "illegal assignment to read-only variable '%s'",
-                              varName);
-         return NULL;
-      }
-
-      /* check if we need to predicate this assignment based on __notRetFlag */
-      if ((var->is_global ||
-           var->type.qualifier == SLANG_QUAL_OUT ||
-           var->type.qualifier == SLANG_QUAL_INOUT) && A->UseReturnFlag) {
-         /* create predicate, used below */
-         pred = slang_operation_new(1);
-         pred->type = SLANG_OPER_IDENTIFIER;
-         pred->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
-         pred->locals->outer_scope = oper->locals->outer_scope;
-      }
-   }
-
-   if (oper->children[0].type == SLANG_OPER_IDENTIFIER &&
-       oper->children[1].type == SLANG_OPER_CALL) {
-      /* Special case of:  x = f(a, b)
-       * Replace with f(a, b, x)  (where x == hidden __retVal out param)
-       *
-       * XXX this could be even more effective if we could accomodate
-       * cases such as "v.x = f();"  - would help with typical vertex
-       * transformation.
-       */
-      n = _slang_gen_function_call_name(A,
-                                      (const char *) oper->children[1].a_id,
-                                      &oper->children[1], &oper->children[0]);
-   }
-   else {
-      slang_ir_node *lhs, *rhs;
-
-      /* lhs and rhs type checking */
-      if (!_slang_assignment_compatible(A,
-                                        &oper->children[0],
-                                        &oper->children[1])) {
-         slang_info_log_error(A->log, "incompatible types in assignment");
-         return NULL;
-      }
-
-      lhs = _slang_gen_operation(A, &oper->children[0]);
-      if (!lhs) {
-         return NULL;
-      }
-
-      if (!lhs->Store) {
-         slang_info_log_error(A->log,
-                              "invalid left hand side for assignment");
-         return NULL;
-      }
-
-      /* check that lhs is writable */
-      if (!is_store_writable(A, lhs->Store)) {
-         slang_info_log_error(A->log,
-                              "illegal assignment to read-only l-value");
-         return NULL;
-      }
-
-      rhs = _slang_gen_operation(A, &oper->children[1]);
-      if (lhs && rhs) {
-         /* convert lhs swizzle into writemask */
-         const GLuint swizzle = root_swizzle(lhs->Store);
-         GLuint writemask, newSwizzle = 0x0;
-         if (!swizzle_to_writemask(A, swizzle, &writemask, &newSwizzle)) {
-            /* Non-simple writemask, need to swizzle right hand side in
-             * order to put components into the right place.
-             */
-            rhs = _slang_gen_swizzle(rhs, newSwizzle);
-         }
-         n = new_node2(IR_COPY, lhs, rhs);
-      }
-      else {
-         return NULL;
-      }
-   }
-
-   if (n && pred) {
-      /* predicate the assignment code on __notRetFlag */
-      slang_ir_node *top, *cond;
-
-      cond = _slang_gen_operation(A, pred);
-      top = new_if(cond, n, NULL);
-      return top;
-   }
-   return n;
-}
-
-
-/**
- * Generate IR tree for referencing a field in a struct (or basic vector type)
- */
-static slang_ir_node *
-_slang_gen_struct_field(slang_assemble_ctx * A, slang_operation *oper)
-{
-   slang_typeinfo ti;
-
-   /* type of struct */
-   slang_typeinfo_construct(&ti);
-   typeof_operation(A, &oper->children[0], &ti);
-
-   if (_slang_type_is_vector(ti.spec.type)) {
-      /* the field should be a swizzle */
-      const GLuint rows = _slang_type_dim(ti.spec.type);
-      slang_swizzle swz;
-      slang_ir_node *n;
-      GLuint swizzle;
-      if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) {
-         slang_info_log_error(A->log, "Bad swizzle");
-         return NULL;
-      }
-      swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
-                              swz.swizzle[1],
-                              swz.swizzle[2],
-                              swz.swizzle[3]);
-
-      n = _slang_gen_operation(A, &oper->children[0]);
-      /* create new parent node with swizzle */
-      if (n)
-         n = _slang_gen_swizzle(n, swizzle);
-      return n;
-   }
-   else if (   ti.spec.type == SLANG_SPEC_FLOAT
-            || ti.spec.type == SLANG_SPEC_INT
-            || ti.spec.type == SLANG_SPEC_BOOL) {
-      const GLuint rows = 1;
-      slang_swizzle swz;
-      slang_ir_node *n;
-      GLuint swizzle;
-      if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) {
-         slang_info_log_error(A->log, "Bad swizzle");
-      }
-      swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
-                              swz.swizzle[1],
-                              swz.swizzle[2],
-                              swz.swizzle[3]);
-      n = _slang_gen_operation(A, &oper->children[0]);
-      /* create new parent node with swizzle */
-      n = _slang_gen_swizzle(n, swizzle);
-      return n;
-   }
-   else {
-      /* the field is a structure member (base.field) */
-      /* oper->children[0] is the base */
-      /* oper->a_id is the field name */
-      slang_ir_node *base, *n;
-      slang_typeinfo field_ti;
-      GLint fieldSize, fieldOffset = -1;
-
-      /* type of field */
-      slang_typeinfo_construct(&field_ti);
-      typeof_operation(A, oper, &field_ti);
-
-      fieldSize = _slang_sizeof_type_specifier(&field_ti.spec);
-      if (fieldSize > 0)
-         fieldOffset = _slang_field_offset(&ti.spec, oper->a_id);
-
-      if (fieldSize == 0 || fieldOffset < 0) {
-         const char *structName;
-         if (ti.spec._struct)
-            structName = (char *) ti.spec._struct->a_name;
-         else
-            structName = "unknown";
-         slang_info_log_error(A->log,
-                              "\"%s\" is not a member of struct \"%s\"",
-                              (char *) oper->a_id, structName);
-         return NULL;
-      }
-      assert(fieldSize >= 0);
-
-      base = _slang_gen_operation(A, &oper->children[0]);
-      if (!base) {
-         /* error msg should have already been logged */
-         return NULL;
-      }
-
-      n = new_node1(IR_FIELD, base);
-      if (!n)
-         return NULL;
-
-      n->Field = (char *) oper->a_id;
-
-      /* Store the field's offset in storage->Index */
-      n->Store = _slang_new_ir_storage(base->Store->File,
-                                       fieldOffset,
-                                       fieldSize);
-
-      return n;
-   }
-}
-
-
-/**
- * Gen code for array indexing.
- */
-static slang_ir_node *
-_slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper)
-{
-   slang_typeinfo array_ti;
-
-   /* get array's type info */
-   slang_typeinfo_construct(&array_ti);
-   typeof_operation(A, &oper->children[0], &array_ti);
-
-   if (_slang_type_is_vector(array_ti.spec.type)) {
-      /* indexing a simple vector type: "vec4 v; v[0]=p;" */
-      /* translate the index into a swizzle/writemask: "v.x=p" */
-      const GLuint max = _slang_type_dim(array_ti.spec.type);
-      GLint index;
-      slang_ir_node *n;
-
-      index = (GLint) oper->children[1].literal[0];
-      if (oper->children[1].type != SLANG_OPER_LITERAL_INT ||
-          index >= (GLint) max) {
-#if 0
-         slang_info_log_error(A->log, "Invalid array index for vector type");
-         printf("type = %d\n", oper->children[1].type);
-         printf("index = %d, max = %d\n", index, max);
-         printf("array = %s\n", (char*)oper->children[0].a_id);
-         printf("index = %s\n", (char*)oper->children[1].a_id);
-         return NULL;
-#else
-         index = 0;
-#endif
-      }
-
-      n = _slang_gen_operation(A, &oper->children[0]);
-      if (n) {
-         /* use swizzle to access the element */
-         GLuint swizzle = MAKE_SWIZZLE4(SWIZZLE_X + index,
-                                        SWIZZLE_NIL,
-                                        SWIZZLE_NIL,
-                                        SWIZZLE_NIL);
-         n = _slang_gen_swizzle(n, swizzle);
-      }
-      return n;
-   }
-   else {
-      /* conventional array */
-      slang_typeinfo elem_ti;
-      slang_ir_node *elem, *array, *index;
-      GLint elemSize, arrayLen;
-
-      /* size of array element */
-      slang_typeinfo_construct(&elem_ti);
-      typeof_operation(A, oper, &elem_ti);
-      elemSize = _slang_sizeof_type_specifier(&elem_ti.spec);
-
-      if (_slang_type_is_matrix(array_ti.spec.type))
-         arrayLen = _slang_type_dim(array_ti.spec.type);
-      else
-         arrayLen = array_ti.array_len;
-
-      slang_typeinfo_destruct(&array_ti);
-      slang_typeinfo_destruct(&elem_ti);
-
-      if (elemSize <= 0) {
-         /* unknown var or type */
-         slang_info_log_error(A->log, "Undefined variable or type");
-         return NULL;
-      }
-
-      array = _slang_gen_operation(A, &oper->children[0]);
-      index = _slang_gen_operation(A, &oper->children[1]);
-      if (array && index) {
-         /* bounds check */
-         GLint constIndex = -1;
-         if (index->Opcode == IR_FLOAT) {
-            constIndex = (int) index->Value[0];
-            if (constIndex < 0 || constIndex >= arrayLen) {
-               slang_info_log_error(A->log,
-                                "Array index out of bounds (index=%d size=%d)",
-                                 constIndex, arrayLen);
-               _slang_free_ir_tree(array);
-               _slang_free_ir_tree(index);
-               return NULL;
-            }
-         }
-
-         if (!array->Store) {
-            slang_info_log_error(A->log, "Invalid array");
-            return NULL;
-         }
-
-         elem = new_node2(IR_ELEMENT, array, index);
-
-         /* The storage info here will be updated during code emit */
-         elem->Store = _slang_new_ir_storage(array->Store->File,
-                                             array->Store->Index,
-                                             elemSize);
-         elem->Store->Swizzle = _slang_var_swizzle(elemSize, 0);
-         return elem;
-      }
-      else {
-         _slang_free_ir_tree(array);
-         _slang_free_ir_tree(index);
-         return NULL;
-      }
-   }
-}
-
-
-static slang_ir_node *
-_slang_gen_compare(slang_assemble_ctx *A, slang_operation *oper,
-                   slang_ir_opcode opcode)
-{
-   slang_typeinfo t0, t1;
-   slang_ir_node *n;
-   
-   slang_typeinfo_construct(&t0);
-   typeof_operation(A, &oper->children[0], &t0);
-
-   slang_typeinfo_construct(&t1);
-   typeof_operation(A, &oper->children[0], &t1);
-
-   if (t0.spec.type == SLANG_SPEC_ARRAY ||
-       t1.spec.type == SLANG_SPEC_ARRAY) {
-      slang_info_log_error(A->log, "Illegal array comparison");
-      return NULL;
-   }
-
-   if (oper->type != SLANG_OPER_EQUAL &&
-       oper->type != SLANG_OPER_NOTEQUAL) {
-      /* <, <=, >, >= can only be used with scalars */
-      if ((t0.spec.type != SLANG_SPEC_INT &&
-           t0.spec.type != SLANG_SPEC_FLOAT) ||
-          (t1.spec.type != SLANG_SPEC_INT &&
-           t1.spec.type != SLANG_SPEC_FLOAT)) {
-         slang_info_log_error(A->log, "Incompatible type(s) for inequality operator");
-         return NULL;
-      }
-   }
-
-   n =  new_node2(opcode,
-                  _slang_gen_operation(A, &oper->children[0]),
-                  _slang_gen_operation(A, &oper->children[1]));
-
-   /* result is a bool (size 1) */
-   n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
-
-   return n;
-}
-
-
-#if 0
-static void
-print_vars(slang_variable_scope *s)
-{
-   int i;
-   printf("vars: ");
-   for (i = 0; i < s->num_variables; i++) {
-      printf("%s %d, \n",
-             (char*) s->variables[i]->a_name,
-             s->variables[i]->declared);
-   }
-
-   printf("\n");
-}
-#endif
-
-
-#if 0
-static void
-_slang_undeclare_vars(slang_variable_scope *locals)
-{
-   if (locals->num_variables > 0) {
-      int i;
-      for (i = 0; i < locals->num_variables; i++) {
-         slang_variable *v = locals->variables[i];
-         printf("undeclare %s at %p\n", (char*) v->a_name, v);
-         v->declared = GL_FALSE;
-      }
-   }
-}
-#endif
-
-
-/**
- * Generate IR tree for a slang_operation (AST node)
- */
-static slang_ir_node *
-_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
-{
-   switch (oper->type) {
-   case SLANG_OPER_BLOCK_NEW_SCOPE:
-      {
-         slang_ir_node *n;
-
-         _slang_push_var_table(A->vartable);
-
-         oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE; /* temp change */
-         n = _slang_gen_operation(A, oper);
-         oper->type = SLANG_OPER_BLOCK_NEW_SCOPE; /* restore */
-
-         _slang_pop_var_table(A->vartable);
-
-         /*_slang_undeclare_vars(oper->locals);*/
-         /*print_vars(oper->locals);*/
-
-         if (n)
-            n = new_node1(IR_SCOPE, n);
-         return n;
-      }
-      break;
-
-   case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
-      /* list of operations */
-      if (oper->num_children > 0)
-      {
-         slang_ir_node *n, *tree = NULL;
-         GLuint i;
-
-         for (i = 0; i < oper->num_children; i++) {
-            n = _slang_gen_operation(A, &oper->children[i]);
-            if (!n) {
-               _slang_free_ir_tree(tree);
-               return NULL; /* error must have occured */
-            }
-            tree = new_seq(tree, n);
-         }
-
-         return tree;
-      }
-      else {
-         return new_node0(IR_NOP);
-      }
-
-   case SLANG_OPER_EXPRESSION:
-      return _slang_gen_operation(A, &oper->children[0]);
-
-   case SLANG_OPER_FOR:
-      return _slang_gen_for(A, oper);
-   case SLANG_OPER_DO:
-      return _slang_gen_do(A, oper);
-   case SLANG_OPER_WHILE:
-      return _slang_gen_while(A, oper);
-   case SLANG_OPER_BREAK:
-      if (!current_loop_oper(A)) {
-         slang_info_log_error(A->log, "'break' not in loop");
-         return NULL;
-      }
-      return new_break(current_loop_ir(A));
-   case SLANG_OPER_CONTINUE:
-      if (!current_loop_oper(A)) {
-         slang_info_log_error(A->log, "'continue' not in loop");
-         return NULL;
-      }
-      return _slang_gen_continue(A, oper);
-   case SLANG_OPER_DISCARD:
-      return new_node0(IR_KILL);
-
-   case SLANG_OPER_EQUAL:
-      return _slang_gen_compare(A, oper, IR_EQUAL);
-   case SLANG_OPER_NOTEQUAL:
-      return _slang_gen_compare(A, oper, IR_NOTEQUAL);
-   case SLANG_OPER_GREATER:
-      return _slang_gen_compare(A, oper, IR_SGT);
-   case SLANG_OPER_LESS:
-      return _slang_gen_compare(A, oper, IR_SLT);
-   case SLANG_OPER_GREATEREQUAL:
-      return _slang_gen_compare(A, oper, IR_SGE);
-   case SLANG_OPER_LESSEQUAL:
-      return _slang_gen_compare(A, oper, IR_SLE);
-   case SLANG_OPER_ADD:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_function_call_name(A, "+", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_SUBTRACT:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_function_call_name(A, "-", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_MULTIPLY:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-         n = _slang_gen_function_call_name(A, "*", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_DIVIDE:
-      {
-         slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_function_call_name(A, "/", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_MINUS:
-      {
-         slang_ir_node *n;
-         assert(oper->num_children == 1);
-        n = _slang_gen_function_call_name(A, "-", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_PLUS:
-      /* +expr   --> do nothing */
-      return _slang_gen_operation(A, &oper->children[0]);
-   case SLANG_OPER_VARIABLE_DECL:
-      return _slang_gen_declaration(A, oper);
-   case SLANG_OPER_ASSIGN:
-      return _slang_gen_assignment(A, oper);
-   case SLANG_OPER_ADDASSIGN:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_function_call_name(A, "+=", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_SUBASSIGN:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_function_call_name(A, "-=", oper, NULL);
-        return n;
-      }
-      break;
-   case SLANG_OPER_MULASSIGN:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_function_call_name(A, "*=", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_DIVASSIGN:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_function_call_name(A, "/=", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_LOGICALAND:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_logical_and(A, oper);
-        return n;
-      }
-   case SLANG_OPER_LOGICALOR:
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 2);
-        n = _slang_gen_logical_or(A, oper);
-        return n;
-      }
-   case SLANG_OPER_LOGICALXOR:
-      return _slang_gen_xor(A, oper);
-   case SLANG_OPER_NOT:
-      return _slang_gen_not(A, oper);
-   case SLANG_OPER_SELECT:  /* b ? x : y */
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 3);
-        n = _slang_gen_select(A, oper);
-        return n;
-      }
-
-   case SLANG_OPER_ASM:
-      return _slang_gen_asm(A, oper, NULL);
-   case SLANG_OPER_CALL:
-      return _slang_gen_function_call_name(A, (const char *) oper->a_id,
-                                           oper, NULL);
-   case SLANG_OPER_METHOD:
-      return _slang_gen_method_call(A, oper);
-   case SLANG_OPER_RETURN:
-      return _slang_gen_return(A, oper);
-   case SLANG_OPER_RETURN_INLINED:
-      return _slang_gen_return(A, oper);
-   case SLANG_OPER_LABEL:
-      return new_label(oper->label);
-   case SLANG_OPER_IDENTIFIER:
-      return _slang_gen_variable(A, oper);
-   case SLANG_OPER_IF:
-      return _slang_gen_if(A, oper);
-   case SLANG_OPER_FIELD:
-      return _slang_gen_struct_field(A, oper);
-   case SLANG_OPER_SUBSCRIPT:
-      return _slang_gen_array_element(A, oper);
-   case SLANG_OPER_LITERAL_FLOAT:
-      /* fall-through */
-   case SLANG_OPER_LITERAL_INT:
-      /* fall-through */
-   case SLANG_OPER_LITERAL_BOOL:
-      return new_float_literal(oper->literal, oper->literal_size);
-
-   case SLANG_OPER_POSTINCREMENT:   /* var++ */
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 1);
-        n = _slang_gen_function_call_name(A, "__postIncr", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_POSTDECREMENT:   /* var-- */
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 1);
-        n = _slang_gen_function_call_name(A, "__postDecr", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_PREINCREMENT:   /* ++var */
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 1);
-        n = _slang_gen_function_call_name(A, "++", oper, NULL);
-        return n;
-      }
-   case SLANG_OPER_PREDECREMENT:   /* --var */
-      {
-        slang_ir_node *n;
-         assert(oper->num_children == 1);
-        n = _slang_gen_function_call_name(A, "--", oper, NULL);
-        return n;
-      }
-
-   case SLANG_OPER_NON_INLINED_CALL:
-   case SLANG_OPER_SEQUENCE:
-      {
-         slang_ir_node *tree = NULL;
-         GLuint i;
-         for (i = 0; i < oper->num_children; i++) {
-            slang_ir_node *n = _slang_gen_operation(A, &oper->children[i]);
-            tree = new_seq(tree, n);
-            if (n)
-               tree->Store = n->Store;
-         }
-         if (oper->type == SLANG_OPER_NON_INLINED_CALL) {
-            tree = new_function_call(tree, oper->label);
-         }
-         return tree;
-      }
-
-   case SLANG_OPER_NONE:
-   case SLANG_OPER_VOID:
-      /* returning NULL here would generate an error */
-      return new_node0(IR_NOP);
-
-   default:
-      _mesa_problem(NULL, "bad node type %d in _slang_gen_operation",
-                    oper->type);
-      return new_node0(IR_NOP);
-   }
-
-   return NULL;
-}
-
-
-/**
- * Check if the given type specifier is a rectangular texture sampler.
- */
-static GLboolean
-is_rect_sampler_spec(const slang_type_specifier *spec)
-{
-   while (spec->_array) {
-      spec = spec->_array;
-   }
-   return spec->type == SLANG_SPEC_SAMPLER_RECT ||
-          spec->type == SLANG_SPEC_SAMPLER_RECT_SHADOW;
-}
-
-
-
-/**
- * Called by compiler when a global variable has been parsed/compiled.
- * Here we examine the variable's type to determine what kind of register
- * storage will be used.
- *
- * A uniform such as "gl_Position" will become the register specification
- * (PROGRAM_OUTPUT, VERT_RESULT_HPOS).  Or, uniform "gl_FogFragCoord"
- * will be (PROGRAM_INPUT, FRAG_ATTRIB_FOGC).
- *
- * Samplers are interesting.  For "uniform sampler2D tex;" we'll specify
- * (PROGRAM_SAMPLER, index) where index is resolved at link-time to an
- * actual texture unit (as specified by the user calling glUniform1i()).
- */
-GLboolean
-_slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
-                               slang_unit_type type)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_program *prog = A->program;
-   const char *varName = (char *) var->a_name;
-   GLboolean success = GL_TRUE;
-   slang_ir_storage *store = NULL;
-   int dbg = 0;
-   const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
-   const GLint size = _slang_sizeof_type_specifier(&var->type.specifier);
-   const GLint arrayLen = _slang_array_length(var);
-   const GLint totalSize = _slang_array_size(size, arrayLen);
-   GLint texIndex = sampler_to_texture_index(var->type.specifier.type);
-
-   var->is_global = GL_TRUE;
-
-   /* check for sampler2D arrays */
-   if (texIndex == -1 && var->type.specifier._array)
-      texIndex = sampler_to_texture_index(var->type.specifier._array->type);
-
-   if (texIndex != -1) {
-      /* This is a texture sampler variable...
-       * store->File = PROGRAM_SAMPLER
-       * store->Index = sampler number (0..7, typically)
-       * store->Size = texture type index (1D, 2D, 3D, cube, etc)
-       */
-      if (var->initializer) {
-         slang_info_log_error(A->log, "illegal assignment to '%s'", varName);
-         return GL_FALSE;
-      }
-#if FEATURE_es2_glsl /* XXX should use FEATURE_texture_rect */
-      /* disallow rect samplers */
-      if (ctx->API == API_OPENGLES2 &&
-         is_rect_sampler_spec(&var->type.specifier)) {
-         slang_info_log_error(A->log, "invalid sampler type for '%s'", varName);
-         return GL_FALSE;
-      }
-#else
-      (void) is_rect_sampler_spec; /* silence warning */
-      (void) ctx;
-#endif
-      {
-         GLint sampNum = _mesa_add_sampler(prog->Parameters, varName, datatype);
-         store = _slang_new_ir_storage_sampler(sampNum, texIndex, totalSize);
-
-         /* If we have a sampler array, then we need to allocate the 
-         * additional samplers to ensure we don't allocate them elsewhere.
-         * We can't directly use _mesa_add_sampler() as that checks the
-         * varName and gets a match, so we call _mesa_add_parameter()
-         * directly and use the last sampler number from the call above.
-         */
-        if (arrayLen > 0) {
-           GLint a = arrayLen - 1;
-           GLint i;
-           for (i = 0; i < a; i++) {
-               GLfloat value = (GLfloat)(i + sampNum + 1);
-               (void) _mesa_add_parameter(prog->Parameters, PROGRAM_SAMPLER,
-                                 varName, 1, datatype, &value, NULL, 0x0);
-           }
-        }
-      }
-      if (dbg) printf("SAMPLER ");
-   }
-   else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
-      /* Uniform variable */
-      const GLuint swizzle = _slang_var_swizzle(totalSize, 0);
-
-      if (prog) {
-         /* user-defined uniform */
-         if (datatype == GL_NONE) {
-           if ((var->type.specifier.type == SLANG_SPEC_ARRAY &&
-                var->type.specifier._array->type == SLANG_SPEC_STRUCT) ||
-                (var->type.specifier.type == SLANG_SPEC_STRUCT)) {
-               /* temporary work-around */
-               GLenum datatype = GL_FLOAT;
-               GLint uniformLoc = _mesa_add_uniform(prog->Parameters, varName,
-                                                    totalSize, datatype, NULL);
-               store = _slang_new_ir_storage_swz(PROGRAM_UNIFORM, uniformLoc,
-                                                 totalSize, swizzle);
-        
-              if (arrayLen > 0) {
-                 GLint a = arrayLen - 1;
-                 GLint i;
-                 for (i = 0; i < a; i++) {
-                     GLfloat value = (GLfloat)(i + uniformLoc + 1);
-                     (void) _mesa_add_parameter(prog->Parameters, PROGRAM_UNIFORM,
-                                 varName, 1, datatype, &value, NULL, 0x0);
-                  }
-              }
-
-               /* XXX what we need to do is unroll the struct into its
-                * basic types, creating a uniform variable for each.
-                * For example:
-                * struct foo {
-                *   vec3 a;
-                *   vec4 b;
-                * };
-                * uniform foo f;
-                *
-                * Should produce uniforms:
-                * "f.a"  (GL_FLOAT_VEC3)
-                * "f.b"  (GL_FLOAT_VEC4)
-                */
-
-               if (var->initializer) {
-                  slang_info_log_error(A->log,
-                     "unsupported initializer for uniform '%s'", varName);
-                  return GL_FALSE;
-               }
-            }
-            else {
-               slang_info_log_error(A->log,
-                                    "invalid datatype for uniform variable %s",
-                                    varName);
-               return GL_FALSE;
-            }
-         }
-         else {
-            /* non-struct uniform */
-            if (!_slang_gen_var_decl(A, var, var->initializer))
-               return GL_FALSE;
-            store = var->store;
-         }
-      }
-      else {
-         /* pre-defined uniform, like gl_ModelviewMatrix */
-         /* We know it's a uniform, but don't allocate storage unless
-          * it's really used.
-          */
-         store = _slang_new_ir_storage_swz(PROGRAM_STATE_VAR, -1,
-                                           totalSize, swizzle);
-      }
-      if (dbg) printf("UNIFORM (sz %d) ", totalSize);
-   }
-   else if (var->type.qualifier == SLANG_QUAL_VARYING) {
-      /* varyings must be float, vec or mat */
-      if (!_slang_type_is_float_vec_mat(var->type.specifier.type) &&
-          var->type.specifier.type != SLANG_SPEC_ARRAY) {
-         slang_info_log_error(A->log,
-                              "varying '%s' must be float/vector/matrix",
-                              varName);
-         return GL_FALSE;
-      }
-
-      if (var->initializer) {
-         slang_info_log_error(A->log, "illegal initializer for varying '%s'",
-                              varName);
-         return GL_FALSE;
-      }
-
-      if (prog) {
-         /* user-defined varying */
-         GLbitfield flags;
-         GLint varyingLoc;
-         GLuint swizzle;
-
-         flags = 0x0;
-         if (var->type.centroid == SLANG_CENTROID)
-            flags |= PROG_PARAM_BIT_CENTROID;
-         if (var->type.variant == SLANG_INVARIANT)
-            flags |= PROG_PARAM_BIT_INVARIANT;
-
-         varyingLoc = _mesa_add_varying(prog->Varying, varName,
-                                        totalSize, GL_NONE, flags);
-         swizzle = _slang_var_swizzle(size, 0);
-         store = _slang_new_ir_storage_swz(PROGRAM_VARYING, varyingLoc,
-                                           totalSize, swizzle);
-      }
-      else {
-         /* pre-defined varying, like gl_Color or gl_TexCoord */
-         if (type == SLANG_UNIT_FRAGMENT_BUILTIN) {
-            /* fragment program input */
-            GLuint swizzle;
-            GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
-                                             &swizzle, NULL);
-            assert(index >= 0);
-            assert(index < FRAG_ATTRIB_MAX);
-            store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index,
-                                              size, swizzle);
-         } else if (type == SLANG_UNIT_VERTEX_BUILTIN) {
-            /* vertex program output */
-            GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
-            GLuint swizzle = _slang_var_swizzle(size, 0);
-            assert(index >= 0);
-            assert(index < VERT_RESULT_MAX);
-            assert(type == SLANG_UNIT_VERTEX_BUILTIN);
-            store = _slang_new_ir_storage_swz(PROGRAM_OUTPUT, index,
-                                              size, swizzle);
-         } else {
-            /* geometry program input */
-            GLboolean is_array = GL_FALSE;
-            GLuint swizzle;
-            GLint index = _slang_input_index(varName, MESA_GEOMETRY_PROGRAM,
-                                             &swizzle, &is_array);
-            if (index < 0) {
-               /* geometry program output */
-               index = _slang_output_index(varName, MESA_GEOMETRY_PROGRAM);
-               swizzle = _slang_var_swizzle(size, 0);
-
-               assert(index >= 0);
-               assert(index < GEOM_RESULT_MAX);
-
-               store = _slang_new_ir_storage_swz(PROGRAM_OUTPUT, index,
-                                                 size, swizzle);
-            } else {
-               assert(index >= 0);
-               /* assert(index < GEOM_ATTRIB_MAX); */
-               if (is_array)
-                  store = _slang_new_ir_storage_2d(PROGRAM_INPUT, 0, index,
-                                                   size, swizzle);
-               else
-                  store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index,
-                                                    size, swizzle);
-            }
-         }
-         if (dbg) printf("V/F ");
-      }
-      if (dbg) printf("VARYING ");
-   }
-   else if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE) {
-      GLuint swizzle;
-      GLint index;
-      /* attributes must be float, vec or mat */
-      if (!_slang_type_is_float_vec_mat(var->type.specifier.type)) {
-         slang_info_log_error(A->log,
-                              "attribute '%s' must be float/vector/matrix",
-                              varName);
-         return GL_FALSE;
-      }
-
-      if (prog) {
-         /* user-defined vertex attribute */
-         const GLint attr = -1; /* unknown */
-         swizzle = _slang_var_swizzle(size, 0);
-         index = _mesa_add_attribute(prog->Attributes, varName,
-                                     size, datatype, attr);
-         assert(index >= 0);
-         index = VERT_ATTRIB_GENERIC0 + index;
-      }
-      else {
-         /* pre-defined vertex attrib */
-         index = _slang_input_index(varName, GL_VERTEX_PROGRAM_ARB, &swizzle, NULL);
-         assert(index >= 0);
-      }
-      store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
-      if (dbg) printf("ATTRIB ");
-   }
-   else if (var->type.qualifier == SLANG_QUAL_FIXEDINPUT) {
-      GLuint swizzle = SWIZZLE_XYZW; /* silence compiler warning */
-      if (type == SLANG_UNIT_FRAGMENT_BUILTIN) {
-         GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
-                                          &swizzle, NULL);
-         store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
-      } else if (type == SLANG_UNIT_GEOMETRY_BUILTIN) {
-         GLboolean is_array;
-         GLint index = _slang_input_index(varName, MESA_GEOMETRY_PROGRAM,
-                                          &swizzle, &is_array);
-         if (is_array)
-            store = _slang_new_ir_storage_2d(PROGRAM_INPUT, 0, index, size, swizzle);
-         else
-            store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
-      }
-      if (dbg) printf("INPUT ");
-   }
-   else if (var->type.qualifier == SLANG_QUAL_FIXEDOUTPUT) {
-      if (type == SLANG_UNIT_VERTEX_BUILTIN) {
-         GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
-         store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size);
-      } else if (type == SLANG_UNIT_FRAGMENT_BUILTIN) {
-         GLint index = _slang_output_index(varName, GL_FRAGMENT_PROGRAM_ARB);
-         GLint specialSize = 4; /* treat all fragment outputs as float[4] */
-         assert(type == SLANG_UNIT_FRAGMENT_BUILTIN);
-         store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, specialSize);
-      } else {
-         GLint index = _slang_output_index(varName, MESA_GEOMETRY_PROGRAM);
-         GLint specialSize = 4; /* treat all fragment outputs as float[4] */
-         assert(type == SLANG_UNIT_GEOMETRY_BUILTIN);
-         store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, specialSize);
-      }
-      if (dbg) printf("OUTPUT ");
-   }
-   else if (var->type.qualifier == SLANG_QUAL_CONST && !prog) {
-      /* pre-defined global constant, like gl_MaxLights */
-      store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size);
-      if (dbg) printf("CONST ");
-   }
-   else {
-      /* ordinary variable (may be const) */
-      slang_ir_node *n;
-
-      /* IR node to declare the variable */
-      n = _slang_gen_var_decl(A, var, var->initializer);
-
-      /* emit GPU instructions */
-      success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_FALSE, A->log);
-
-      _slang_free_ir_tree(n);
-   }
-
-   if (dbg) printf("GLOBAL VAR %s  idx %d\n", (char*) var->a_name,
-                   store ? store->Index : -2);
-
-   if (store)
-      var->store = store;  /* save var's storage info */
-
-   var->declared = GL_TRUE;
-
-   return success;
-}
-
-
-/**
- * Produce an IR tree from a function AST (fun->body).
- * Then call the code emitter to convert the IR tree into gl_program
- * instructions.
- */
-GLboolean
-_slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
-{
-   slang_ir_node *n;
-   GLboolean success = GL_TRUE;
-
-   if (strcmp((char *) fun->header.a_name, "main") != 0) {
-      /* we only really generate code for main, all other functions get
-       * inlined or codegen'd upon an actual call.
-       */
-#if 0
-      /* do some basic error checking though */
-      if (fun->header.type.specifier.type != SLANG_SPEC_VOID) {
-         /* check that non-void functions actually return something */
-         slang_operation *op
-            = _slang_find_node_type(fun->body, SLANG_OPER_RETURN);
-         if (!op) {
-            slang_info_log_error(A->log,
-                                 "function \"%s\" has no return statement",
-                                 (char *) fun->header.a_name);
-            printf(
-                   "function \"%s\" has no return statement\n",
-                   (char *) fun->header.a_name);
-            return GL_FALSE;
-         }
-      }
-#endif
-      return GL_TRUE;  /* not an error */
-   }
-
-#if 0
-   printf("\n*********** codegen_function %s\n", (char *) fun->header.a_name);
-   slang_print_function(fun, 1);
-#endif
-
-   /* should have been allocated earlier: */
-   assert(A->program->Parameters );
-   assert(A->program->Varying);
-   assert(A->vartable);
-
-   A->LoopDepth = 0;
-   A->UseReturnFlag = GL_FALSE;
-   A->CurFunction = fun;
-
-   /* fold constant expressions, etc. */
-   _slang_simplify(fun->body, &A->space, A->atoms);
-
-#if 0
-   printf("\n*********** simplified %s\n", (char *) fun->header.a_name);
-   slang_print_function(fun, 1);
-#endif
-
-   /* Create an end-of-function label */
-   A->curFuncEndLabel = _slang_label_new("__endOfFunc__main");
-
-   /* push new vartable scope */
-   _slang_push_var_table(A->vartable);
-
-   /* Generate IR tree for the function body code */
-   n = _slang_gen_operation(A, fun->body);
-   if (n)
-      n = new_node1(IR_SCOPE, n);
-
-   /* pop vartable, restore previous */
-   _slang_pop_var_table(A->vartable);
-
-   if (!n) {
-      /* XXX record error */
-      return GL_FALSE;
-   }
-
-   /* append an end-of-function-label to IR tree */
-   n = new_seq(n, new_label(A->curFuncEndLabel));
-
-   /*_slang_label_delete(A->curFuncEndLabel);*/
-   A->curFuncEndLabel = NULL;
-
-#if 0
-   printf("************* New AST for %s *****\n", (char*)fun->header.a_name);
-   slang_print_function(fun, 1);
-#endif
-#if 0
-   printf("************* IR for %s *******\n", (char*)fun->header.a_name);
-   _slang_print_ir_tree(n, 0);
-#endif
-#if 0
-   printf("************* End codegen function ************\n\n");
-#endif
-
-   if (A->UnresolvedRefs) {
-      /* Can't codegen at this time.
-       * At link time we'll concatenate all the vertex shaders and/or all
-       * the fragment shaders and try recompiling.
-       */
-      return GL_TRUE;
-   }
-
-   /* Emit program instructions */
-   success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_TRUE, A->log);
-   _slang_free_ir_tree(n);
-
-   /* free codegen context */
-   /*
-   free(A->codegen);
-   */
-
-   return success;
-}
-
diff --git a/src/mesa/slang/slang_codegen.h b/src/mesa/slang/slang_codegen.h
deleted file mode 100644 (file)
index ff0279b..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef SLANG_CODEGEN_H
-#define SLANG_CODEGEN_H
-
-
-#include "main/glheader.h"
-#include "slang_compile.h"
-#include "slang_compile_variable.h"
-#include "slang_typeinfo.h"
-#include "slang_utility.h"
-
-struct slang_function_;
-
-#define MAX_LOOP_DEPTH 30
-
-
-typedef struct slang_assemble_ctx_
-{
-   slang_atom_pool *atoms;
-   slang_name_space space;
-   struct gl_program *program;
-   struct gl_sl_pragmas *pragmas;
-   slang_var_table *vartable;
-   slang_info_log *log;
-   GLboolean allow_uniform_initializers;
-
-   /* current loop stack */
-   const slang_operation *LoopOperStack[MAX_LOOP_DEPTH];
-   struct slang_ir_node_ *LoopIRStack[MAX_LOOP_DEPTH];
-   GLuint LoopDepth;
-
-   /* current function */
-   struct slang_function_ *CurFunction;
-   struct slang_label_ *curFuncEndLabel;
-   GLboolean UseReturnFlag;
-
-   GLboolean UnresolvedRefs;
-   GLboolean EmitContReturn;
-} slang_assemble_ctx;
-
-
-extern GLuint
-_slang_sizeof_type_specifier(const slang_type_specifier *spec);
-
-extern GLboolean
-_slang_codegen_function(slang_assemble_ctx *A , struct slang_function_ *fun);
-
-extern GLboolean
-_slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
-                               slang_unit_type type);
-
-
-#endif /* SLANG_CODEGEN_H */
diff --git a/src/mesa/slang/slang_compile.c b/src/mesa/slang/slang_compile.c
deleted file mode 100644 (file)
index de1bb56..0000000
+++ /dev/null
@@ -1,3103 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
- * Copyright (C) 2008 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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_compile.c
- * slang front-end compiler
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "program/program.h"
-#include "program/programopt.h"
-#include "program/prog_optimize.h"
-#include "program/prog_print.h"
-#include "program/prog_parameter.h"
-#include "../../glsl/pp/sl_pp_public.h"
-#include "../../glsl/pp/sl_pp_purify.h"
-#include "../../glsl/cl/sl_cl_parse.h"
-#include "slang_codegen.h"
-#include "slang_compile.h"
-#include "slang_storage.h"
-#include "slang_log.h"
-#include "slang_mem.h"
-#include "slang_vartable.h"
-#include "slang_simplify.h"
-
-/*
- * This is a straightforward implementation of the slang front-end
- * compiler.  Lots of error-checking functionality is missing but
- * every well-formed shader source should compile successfully and
- * execute as expected. However, some semantically ill-formed shaders
- * may be accepted resulting in undefined behaviour.
- */
-
-
-/** re-defined below, should be the same though */
-#define TYPE_SPECIFIER_COUNT 36
-
-
-/**
- * Check if the given identifier is legal.
- */
-static GLboolean
-legal_identifier(slang_atom name)
-{
-   /* "gl_" is a reserved prefix */
-   if (strncmp((char *) name, "gl_", 3) == 0) {
-      return GL_FALSE;
-   }
-   return GL_TRUE;
-}
-
-
-/*
- * slang_code_unit
- */
-
-GLvoid
-_slang_code_unit_ctr(slang_code_unit * self,
-                     struct slang_code_object_ * object)
-{
-   _slang_variable_scope_ctr(&self->vars);
-   _slang_function_scope_ctr(&self->funs);
-   _slang_struct_scope_ctr(&self->structs);
-   self->object = object;
-}
-
-GLvoid
-_slang_code_unit_dtr(slang_code_unit * self)
-{
-   slang_variable_scope_destruct(&self->vars);
-   slang_function_scope_destruct(&self->funs);
-   slang_struct_scope_destruct(&self->structs);
-}
-
-/*
- * slang_code_object
- */
-
-GLvoid
-_slang_code_object_ctr(slang_code_object * self)
-{
-   GLuint i;
-
-   for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
-      _slang_code_unit_ctr(&self->builtin[i], self);
-   _slang_code_unit_ctr(&self->unit, self);
-   slang_atom_pool_construct(&self->atompool);
-}
-
-GLvoid
-_slang_code_object_dtr(slang_code_object * self)
-{
-   GLuint i;
-
-   for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
-      _slang_code_unit_dtr(&self->builtin[i]);
-   _slang_code_unit_dtr(&self->unit);
-   slang_atom_pool_destruct(&self->atompool);
-}
-
-
-/* slang_parse_ctx */
-
-typedef struct slang_parse_ctx_
-{
-   const unsigned char *I;
-   slang_info_log *L;
-   int parsing_builtin;
-   GLboolean global_scope;   /**< Is object being declared a global? */
-   slang_atom_pool *atoms;
-   slang_unit_type type;     /**< Vertex vs. Fragment */
-   GLuint version;           /**< user-specified (or default) #version */
-} slang_parse_ctx;
-
-/* slang_output_ctx */
-
-typedef struct slang_output_ctx_
-{
-   slang_variable_scope *vars;
-   slang_function_scope *funs;
-   slang_struct_scope *structs;
-   struct gl_program *program;
-   struct gl_sl_pragmas *pragmas;
-   slang_var_table *vartable;
-   GLuint default_precision[TYPE_SPECIFIER_COUNT];
-   GLboolean allow_precision;
-   GLboolean allow_invariant;
-   GLboolean allow_centroid;
-   GLboolean allow_array_types;  /* float[] syntax */
-} slang_output_ctx;
-
-/* _slang_compile() */
-
-
-/* Debugging aid, print file/line where parsing error is detected */
-#define RETURN0 \
-   do { \
-      if (0) \
-         printf("slang error at %s:%d\n", __FILE__, __LINE__); \
-      return 0; \
-   } while (0)
-
-
-static void
-parse_identifier_str(slang_parse_ctx * C, char **id)
-{
-   *id = (char *) C->I;
-   C->I += strlen(*id) + 1;
-}
-
-static slang_atom
-parse_identifier(slang_parse_ctx * C)
-{
-   const char *id;
-
-   id = (const char *) C->I;
-   C->I += strlen(id) + 1;
-   return slang_atom_pool_atom(C->atoms, id);
-}
-
-static int
-is_hex_digit(char c)
-{
-   return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
-}
-
-static int
-parse_general_number(slang_parse_ctx *ctx, float *number)
-{
-   char *flt = NULL;
-
-   if (*ctx->I == '0') {
-      int value = 0;
-      const unsigned char *pi;
-
-      if (ctx->I[1] == 'x' || ctx->I[1] == 'X') {
-         ctx->I += 2;
-         if (!is_hex_digit(*ctx->I)) {
-            return 0;
-         }
-         do {
-            int digit;
-
-            if (*ctx->I >= '0' && *ctx->I <= '9') {
-               digit = (int)(*ctx->I - '0');
-            } else if (*ctx->I >= 'a' && *ctx->I <= 'f') {
-               digit = (int)(*ctx->I - 'a') + 10;
-            } else {
-               digit = (int)(*ctx->I - 'A') + 10;
-            }
-            value = value * 0x10 + digit;
-            ctx->I++;
-         } while (is_hex_digit(*ctx->I));
-         if (*ctx->I != '\0') {
-            return 0;
-         }
-         ctx->I++;
-         *number = (float)value;
-         return 1;
-      }
-
-      pi = ctx->I;
-      pi++;
-      while (*pi >= '0' && *pi <= '7') {
-         int digit;
-
-         digit = (int)(*pi - '0');
-         value = value * 010 + digit;
-         pi++;
-      }
-      if (*pi == '\0') {
-         pi++;
-         ctx->I = pi;
-         *number = (float)value;
-         return 1;
-      }
-   }
-
-   parse_identifier_str(ctx, &flt);
-   flt = _mesa_strdup(flt);
-   if (!flt) {
-      return 0;
-   }
-   if (flt[strlen(flt) - 1] == 'f' || flt[strlen(flt) - 1] == 'F') {
-      flt[strlen(flt) - 1] = '\0';
-   }
-   *number = _mesa_strtof(flt, (char **)NULL);
-   free(flt);
-
-   return 1;
-}
-
-static int
-parse_number(slang_parse_ctx * C, int *number)
-{
-   const int radix = (int) (*C->I++);
-
-   if (radix == 1) {
-      float f = 0.0f;
-
-      parse_general_number(C, &f);
-      *number = (int)f;
-   } else {
-      *number = 0;
-      while (*C->I != '\0') {
-         int digit;
-         if (*C->I >= '0' && *C->I <= '9')
-            digit = (int) (*C->I - '0');
-         else if (*C->I >= 'A' && *C->I <= 'Z')
-            digit = (int) (*C->I - 'A') + 10;
-         else
-            digit = (int) (*C->I - 'a') + 10;
-         *number = *number * radix + digit;
-         C->I++;
-      }
-      C->I++;
-   }
-   if (*number > 65535)
-      slang_info_log_warning(C->L, "%d: literal integer overflow.", *number);
-   return 1;
-}
-
-static int
-parse_float(slang_parse_ctx * C, float *number)
-{
-   if (*C->I == 1) {
-      C->I++;
-      parse_general_number(C, number);
-   } else {
-      char *integral = NULL;
-      char *fractional = NULL;
-      char *exponent = NULL;
-      char *whole = NULL;
-
-      parse_identifier_str(C, &integral);
-      parse_identifier_str(C, &fractional);
-      parse_identifier_str(C, &exponent);
-
-      whole = (char *) _slang_alloc((strlen(integral) +
-                                     strlen(fractional) +
-                                     strlen(exponent) + 3) * sizeof(char));
-      if (whole == NULL) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-
-      slang_string_copy(whole, integral);
-      slang_string_concat(whole, ".");
-      slang_string_concat(whole, fractional);
-      slang_string_concat(whole, "E");
-      slang_string_concat(whole, exponent);
-
-      *number = _mesa_strtof(whole, (char **) NULL);
-
-      _slang_free(whole);
-   }
-
-   return 1;
-}
-
-/* revision number - increment after each change affecting emitted output */
-#define REVISION 5
-
-static int
-check_revision(slang_parse_ctx * C)
-{
-   if (*C->I != REVISION) {
-      slang_info_log_error(C->L, "Internal compiler error.");
-      RETURN0;
-   }
-   C->I++;
-   return 1;
-}
-
-static int parse_statement(slang_parse_ctx *, slang_output_ctx *,
-                           slang_operation *);
-static int parse_expression(slang_parse_ctx *, slang_output_ctx *,
-                            slang_operation *);
-static int parse_type_specifier(slang_parse_ctx *, slang_output_ctx *,
-                                slang_type_specifier *);
-static int
-parse_type_array_size(slang_parse_ctx *C,
-                      slang_output_ctx *O,
-                      GLint *array_len);
-
-static GLboolean
-parse_array_len(slang_parse_ctx * C, slang_output_ctx * O, GLuint * len)
-{
-   slang_operation array_size;
-   slang_name_space space;
-   GLboolean result;
-
-   if (!slang_operation_construct(&array_size))
-      return GL_FALSE;
-   if (!parse_expression(C, O, &array_size)) {
-      slang_operation_destruct(&array_size);
-      return GL_FALSE;
-   }
-
-   space.funcs = O->funs;
-   space.structs = O->structs;
-   space.vars = O->vars;
-
-   /* evaluate compile-time expression which is array size */
-   _slang_simplify(&array_size, &space, C->atoms);
-
-   if (array_size.type == SLANG_OPER_LITERAL_INT) {
-      result = GL_TRUE;
-      *len = (GLint) array_size.literal[0];
-   } else if (array_size.type == SLANG_OPER_IDENTIFIER) {
-      slang_variable *var = _slang_variable_locate(array_size.locals, array_size.a_id, GL_TRUE);
-      if (!var) {
-         slang_info_log_error(C->L, "undefined variable '%s'",
-                              (char *) array_size.a_id);
-         result = GL_FALSE;
-      } else if (var->type.qualifier == SLANG_QUAL_CONST &&
-                 var->type.specifier.type == SLANG_SPEC_INT) {
-         if (var->initializer &&
-             var->initializer->type == SLANG_OPER_LITERAL_INT) {
-            *len = (GLint) var->initializer->literal[0];
-            result = GL_TRUE;
-         } else {
-            slang_info_log_error(C->L, "unable to parse array size declaration");
-            result = GL_FALSE;
-         }
-      } else {
-         slang_info_log_error(C->L, "unable to parse array size declaration");
-         result = GL_FALSE;
-      }
-   } else {
-      result = GL_FALSE;
-   }
-
-   slang_operation_destruct(&array_size);
-   return result;
-}
-
-static GLboolean
-calculate_var_size(slang_parse_ctx * C, slang_output_ctx * O,
-                   slang_variable * var)
-{
-   slang_storage_aggregate agg;
-
-   if (!slang_storage_aggregate_construct(&agg))
-      return GL_FALSE;
-   if (!_slang_aggregate_variable(&agg, &var->type.specifier, var->array_len,
-                                  O->funs, O->structs, O->vars, C->atoms)) {
-      slang_storage_aggregate_destruct(&agg);
-      return GL_FALSE;
-   }
-   var->size = _slang_sizeof_aggregate(&agg);
-   slang_storage_aggregate_destruct(&agg);
-   return GL_TRUE;
-}
-
-static void
-promote_type_to_array(slang_parse_ctx *C,
-                      slang_fully_specified_type *type,
-                      GLint array_len)
-{
-   slang_type_specifier *baseType =
-      slang_type_specifier_new(type->specifier.type, NULL, NULL);
-
-   type->specifier.type = SLANG_SPEC_ARRAY;
-   type->specifier._array = baseType;
-   type->array_len = array_len;
-}
-
-
-static GLboolean
-convert_to_array(slang_parse_ctx * C, slang_variable * var,
-                 const slang_type_specifier * sp)
-{
-   /* sized array - mark it as array, copy the specifier to the array element
-    * and parse the expression */
-   var->type.specifier.type = SLANG_SPEC_ARRAY;
-   var->type.specifier._array = (slang_type_specifier *)
-      _slang_alloc(sizeof(slang_type_specifier));
-   if (var->type.specifier._array == NULL) {
-      slang_info_log_memory(C->L);
-      return GL_FALSE;
-   }
-   slang_type_specifier_ctr(var->type.specifier._array);
-   return slang_type_specifier_copy(var->type.specifier._array, sp);
-}
-
-/* structure field */
-#define FIELD_NONE 0
-#define FIELD_NEXT 1
-#define FIELD_ARRAY 2
-
-static GLboolean
-parse_struct_field_var(slang_parse_ctx * C, slang_output_ctx * O,
-                       slang_variable * var, slang_atom a_name,
-                       const slang_type_specifier * sp,
-                       GLuint array_len)
-{
-   var->a_name = a_name;
-   if (var->a_name == SLANG_ATOM_NULL)
-      return GL_FALSE;
-
-   switch (*C->I++) {
-   case FIELD_NONE:
-      if (array_len != -1) {
-         if (!convert_to_array(C, var, sp))
-            return GL_FALSE;
-         var->array_len = array_len;
-      }
-      else {
-         if (!slang_type_specifier_copy(&var->type.specifier, sp))
-            return GL_FALSE;
-      }
-      break;
-   case FIELD_ARRAY:
-      if (array_len != -1)
-         return GL_FALSE;
-      if (!convert_to_array(C, var, sp))
-         return GL_FALSE;
-      if (!parse_array_len(C, O, &var->array_len))
-         return GL_FALSE;
-      break;
-   default:
-      return GL_FALSE;
-   }
-
-   return calculate_var_size(C, O, var);
-}
-
-static int
-parse_struct_field(slang_parse_ctx * C, slang_output_ctx * O,
-                   slang_struct * st, slang_type_specifier * sp)
-{
-   slang_output_ctx o = *O;
-   GLint array_len;
-
-   o.structs = st->structs;
-   if (!parse_type_specifier(C, &o, sp))
-      RETURN0;
-   if (!parse_type_array_size(C, &o, &array_len))
-      RETURN0;
-
-   do {
-      slang_atom a_name;
-      slang_variable *var = slang_variable_scope_grow(st->fields);
-      if (!var) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      a_name = parse_identifier(C);
-      if (_slang_variable_locate(st->fields, a_name, GL_FALSE)) {
-         slang_info_log_error(C->L, "duplicate field '%s'", (char *) a_name);
-         RETURN0;
-      }
-
-      if (!parse_struct_field_var(C, &o, var, a_name, sp, array_len))
-         RETURN0;
-   }
-   while (*C->I++ != FIELD_NONE);
-
-   return 1;
-}
-
-static int
-parse_struct(slang_parse_ctx * C, slang_output_ctx * O, slang_struct ** st)
-{
-   slang_atom a_name;
-   const char *name;
-
-   /* parse struct name (if any) and make sure it is unique in current scope */
-   a_name = parse_identifier(C);
-   if (a_name == SLANG_ATOM_NULL)
-      RETURN0;
-
-   name = slang_atom_pool_id(C->atoms, a_name);
-   if (name[0] != '\0'
-       && slang_struct_scope_find(O->structs, a_name, 0) != NULL) {
-      slang_info_log_error(C->L, "%s: duplicate type name.", name);
-      RETURN0;
-   }
-
-   /* set-up a new struct */
-   *st = (slang_struct *) _slang_alloc(sizeof(slang_struct));
-   if (*st == NULL) {
-      slang_info_log_memory(C->L);
-      RETURN0;
-   }
-   if (!slang_struct_construct(*st)) {
-      _slang_free(*st);
-      *st = NULL;
-      slang_info_log_memory(C->L);
-      RETURN0;
-   }
-   (**st).a_name = a_name;
-   (**st).structs->outer_scope = O->structs;
-
-   /* parse individual struct fields */
-   do {
-      slang_type_specifier sp;
-
-      slang_type_specifier_ctr(&sp);
-      if (!parse_struct_field(C, O, *st, &sp)) {
-         slang_type_specifier_dtr(&sp);
-         RETURN0;
-      }
-      slang_type_specifier_dtr(&sp);
-   }
-   while (*C->I++ != FIELD_NONE);
-
-   /* if named struct, copy it to current scope */
-   if (name[0] != '\0') {
-      slang_struct *s;
-
-      O->structs->structs =
-         (slang_struct *) _slang_realloc(O->structs->structs,
-                                         O->structs->num_structs
-                                         * sizeof(slang_struct),
-                                         (O->structs->num_structs + 1)
-                                         * sizeof(slang_struct));
-      if (O->structs->structs == NULL) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      s = &O->structs->structs[O->structs->num_structs];
-      if (!slang_struct_construct(s))
-         RETURN0;
-      O->structs->num_structs++;
-      if (!slang_struct_copy(s, *st))
-         RETURN0;
-   }
-
-   return 1;
-}
-
-
-/* invariant qualifer */
-#define TYPE_VARIANT    90
-#define TYPE_INVARIANT  91
-
-static int
-parse_type_variant(slang_parse_ctx * C, slang_type_variant *variant)
-{
-   GLuint invariant = *C->I++;
-   switch (invariant) {
-   case TYPE_VARIANT:
-      *variant = SLANG_VARIANT;
-      return 1;
-   case TYPE_INVARIANT:
-      *variant = SLANG_INVARIANT;
-      return 1;
-   default:
-      RETURN0;
-   }
-}
-
-
-/* centroid qualifer */
-#define TYPE_CENTER    95
-#define TYPE_CENTROID  96
-
-static int
-parse_type_centroid(slang_parse_ctx * C, slang_type_centroid *centroid)
-{
-   GLuint c = *C->I++;
-   switch (c) {
-   case TYPE_CENTER:
-      *centroid = SLANG_CENTER;
-      return 1;
-   case TYPE_CENTROID:
-      *centroid = SLANG_CENTROID;
-      return 1;
-   default:
-      RETURN0;
-   }
-}
-
-
-/* Layout qualifiers */
-#define LAYOUT_QUALIFIER_NONE                      0
-#define LAYOUT_QUALIFIER_UPPER_LEFT                1
-#define LAYOUT_QUALIFIER_PIXEL_CENTER_INTEGER      2
-
-static int
-parse_layout_qualifiers(slang_parse_ctx * C, slang_layout_qualifier *layout)
-{
-   *layout = 0x0;
-
-   /* the layout qualifiers come as a list of LAYOUT_QUALIFER_x tokens,
-    * terminated by LAYOUT_QUALIFIER_NONE.
-    */
-   while (1) {
-      GLuint c = *C->I++;
-      switch (c) {
-      case LAYOUT_QUALIFIER_NONE:
-         /* end of list of qualifiers */
-         return 1;
-      case LAYOUT_QUALIFIER_UPPER_LEFT:
-         *layout |= SLANG_LAYOUT_UPPER_LEFT_BIT;
-         break;
-      case LAYOUT_QUALIFIER_PIXEL_CENTER_INTEGER:
-         *layout |= SLANG_LAYOUT_PIXEL_CENTER_INTEGER_BIT;
-         break;
-      default:
-         assert(0 && "Bad layout qualifier");
-      }
-   }
-}
-
-
-/* type qualifier */
-#define TYPE_QUALIFIER_NONE 0
-#define TYPE_QUALIFIER_CONST 1
-#define TYPE_QUALIFIER_ATTRIBUTE 2
-#define TYPE_QUALIFIER_VARYING 3
-#define TYPE_QUALIFIER_UNIFORM 4
-#define TYPE_QUALIFIER_FIXEDOUTPUT 5
-#define TYPE_QUALIFIER_FIXEDINPUT 6
-
-static int
-parse_type_qualifier(slang_parse_ctx * C, slang_type_qualifier * qual)
-{
-   GLuint qualifier = *C->I++;
-   switch (qualifier) {
-   case TYPE_QUALIFIER_NONE:
-      *qual = SLANG_QUAL_NONE;
-      break;
-   case TYPE_QUALIFIER_CONST:
-      *qual = SLANG_QUAL_CONST;
-      break;
-   case TYPE_QUALIFIER_ATTRIBUTE:
-      *qual = SLANG_QUAL_ATTRIBUTE;
-      break;
-   case TYPE_QUALIFIER_VARYING:
-      *qual = SLANG_QUAL_VARYING;
-      break;
-   case TYPE_QUALIFIER_UNIFORM:
-      *qual = SLANG_QUAL_UNIFORM;
-      break;
-   case TYPE_QUALIFIER_FIXEDOUTPUT:
-      *qual = SLANG_QUAL_FIXEDOUTPUT;
-      break;
-   case TYPE_QUALIFIER_FIXEDINPUT:
-      *qual = SLANG_QUAL_FIXEDINPUT;
-      break;
-   default:
-      RETURN0;
-   }
-   return 1;
-}
-
-/* type specifier */
-#define TYPE_SPECIFIER_VOID 0
-#define TYPE_SPECIFIER_BOOL 1
-#define TYPE_SPECIFIER_BVEC2 2
-#define TYPE_SPECIFIER_BVEC3 3
-#define TYPE_SPECIFIER_BVEC4 4
-#define TYPE_SPECIFIER_INT 5
-#define TYPE_SPECIFIER_IVEC2 6
-#define TYPE_SPECIFIER_IVEC3 7
-#define TYPE_SPECIFIER_IVEC4 8
-#define TYPE_SPECIFIER_FLOAT 9
-#define TYPE_SPECIFIER_VEC2 10
-#define TYPE_SPECIFIER_VEC3 11
-#define TYPE_SPECIFIER_VEC4 12
-#define TYPE_SPECIFIER_MAT2 13
-#define TYPE_SPECIFIER_MAT3 14
-#define TYPE_SPECIFIER_MAT4 15
-#define TYPE_SPECIFIER_SAMPLER1D 16
-#define TYPE_SPECIFIER_SAMPLER2D 17
-#define TYPE_SPECIFIER_SAMPLER3D 18
-#define TYPE_SPECIFIER_SAMPLERCUBE 19
-#define TYPE_SPECIFIER_SAMPLER1DSHADOW 20
-#define TYPE_SPECIFIER_SAMPLER2DSHADOW 21
-#define TYPE_SPECIFIER_SAMPLER2DRECT 22
-#define TYPE_SPECIFIER_SAMPLER2DRECTSHADOW 23
-#define TYPE_SPECIFIER_STRUCT 24
-#define TYPE_SPECIFIER_TYPENAME 25
-#define TYPE_SPECIFIER_MAT23 26
-#define TYPE_SPECIFIER_MAT32 27
-#define TYPE_SPECIFIER_MAT24 28
-#define TYPE_SPECIFIER_MAT42 29
-#define TYPE_SPECIFIER_MAT34 30
-#define TYPE_SPECIFIER_MAT43 31
-#define TYPE_SPECIFIER_SAMPLER_1D_ARRAY 32
-#define TYPE_SPECIFIER_SAMPLER_2D_ARRAY 33
-#define TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW 34
-#define TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW 35
-#define TYPE_SPECIFIER_COUNT 36
-
-static int
-parse_type_specifier(slang_parse_ctx * C, slang_output_ctx * O,
-                     slang_type_specifier * spec)
-{
-   int type = *C->I++;
-   switch (type) {
-   case TYPE_SPECIFIER_VOID:
-      spec->type = SLANG_SPEC_VOID;
-      break;
-   case TYPE_SPECIFIER_BOOL:
-      spec->type = SLANG_SPEC_BOOL;
-      break;
-   case TYPE_SPECIFIER_BVEC2:
-      spec->type = SLANG_SPEC_BVEC2;
-      break;
-   case TYPE_SPECIFIER_BVEC3:
-      spec->type = SLANG_SPEC_BVEC3;
-      break;
-   case TYPE_SPECIFIER_BVEC4:
-      spec->type = SLANG_SPEC_BVEC4;
-      break;
-   case TYPE_SPECIFIER_INT:
-      spec->type = SLANG_SPEC_INT;
-      break;
-   case TYPE_SPECIFIER_IVEC2:
-      spec->type = SLANG_SPEC_IVEC2;
-      break;
-   case TYPE_SPECIFIER_IVEC3:
-      spec->type = SLANG_SPEC_IVEC3;
-      break;
-   case TYPE_SPECIFIER_IVEC4:
-      spec->type = SLANG_SPEC_IVEC4;
-      break;
-   case TYPE_SPECIFIER_FLOAT:
-      spec->type = SLANG_SPEC_FLOAT;
-      break;
-   case TYPE_SPECIFIER_VEC2:
-      spec->type = SLANG_SPEC_VEC2;
-      break;
-   case TYPE_SPECIFIER_VEC3:
-      spec->type = SLANG_SPEC_VEC3;
-      break;
-   case TYPE_SPECIFIER_VEC4:
-      spec->type = SLANG_SPEC_VEC4;
-      break;
-   case TYPE_SPECIFIER_MAT2:
-      spec->type = SLANG_SPEC_MAT2;
-      break;
-   case TYPE_SPECIFIER_MAT3:
-      spec->type = SLANG_SPEC_MAT3;
-      break;
-   case TYPE_SPECIFIER_MAT4:
-      spec->type = SLANG_SPEC_MAT4;
-      break;
-   case TYPE_SPECIFIER_MAT23:
-      spec->type = SLANG_SPEC_MAT23;
-      break;
-   case TYPE_SPECIFIER_MAT32:
-      spec->type = SLANG_SPEC_MAT32;
-      break;
-   case TYPE_SPECIFIER_MAT24:
-      spec->type = SLANG_SPEC_MAT24;
-      break;
-   case TYPE_SPECIFIER_MAT42:
-      spec->type = SLANG_SPEC_MAT42;
-      break;
-   case TYPE_SPECIFIER_MAT34:
-      spec->type = SLANG_SPEC_MAT34;
-      break;
-   case TYPE_SPECIFIER_MAT43:
-      spec->type = SLANG_SPEC_MAT43;
-      break;
-   case TYPE_SPECIFIER_SAMPLER1D:
-      spec->type = SLANG_SPEC_SAMPLER_1D;
-      break;
-   case TYPE_SPECIFIER_SAMPLER2D:
-      spec->type = SLANG_SPEC_SAMPLER_2D;
-      break;
-   case TYPE_SPECIFIER_SAMPLER3D:
-      spec->type = SLANG_SPEC_SAMPLER_3D;
-      break;
-   case TYPE_SPECIFIER_SAMPLERCUBE:
-      spec->type = SLANG_SPEC_SAMPLER_CUBE;
-      break;
-   case TYPE_SPECIFIER_SAMPLER2DRECT:
-      spec->type = SLANG_SPEC_SAMPLER_RECT;
-      break;
-   case TYPE_SPECIFIER_SAMPLER1DSHADOW:
-      spec->type = SLANG_SPEC_SAMPLER_1D_SHADOW;
-      break;
-   case TYPE_SPECIFIER_SAMPLER2DSHADOW:
-      spec->type = SLANG_SPEC_SAMPLER_2D_SHADOW;
-      break;
-   case TYPE_SPECIFIER_SAMPLER2DRECTSHADOW:
-      spec->type = SLANG_SPEC_SAMPLER_RECT_SHADOW;
-      break;
-   case TYPE_SPECIFIER_SAMPLER_1D_ARRAY:
-      spec->type = SLANG_SPEC_SAMPLER_1D_ARRAY;
-      break;
-   case TYPE_SPECIFIER_SAMPLER_2D_ARRAY:
-      spec->type = SLANG_SPEC_SAMPLER_2D_ARRAY;
-      break;
-   case TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW:
-      spec->type = SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW;
-      break;
-   case TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW:
-      spec->type = SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW;
-      break;
-   case TYPE_SPECIFIER_STRUCT:
-      spec->type = SLANG_SPEC_STRUCT;
-      if (!parse_struct(C, O, &spec->_struct))
-         RETURN0;
-      break;
-   case TYPE_SPECIFIER_TYPENAME:
-      spec->type = SLANG_SPEC_STRUCT;
-      {
-         slang_atom a_name;
-         slang_struct *stru;
-
-         a_name = parse_identifier(C);
-         if (a_name == NULL)
-            RETURN0;
-
-         stru = slang_struct_scope_find(O->structs, a_name, 1);
-         if (stru == NULL) {
-            slang_info_log_error(C->L, "undeclared type name '%s'",
-                                 slang_atom_pool_id(C->atoms, a_name));
-            RETURN0;
-         }
-
-         spec->_struct = (slang_struct *) _slang_alloc(sizeof(slang_struct));
-         if (spec->_struct == NULL) {
-            slang_info_log_memory(C->L);
-            RETURN0;
-         }
-         if (!slang_struct_construct(spec->_struct)) {
-            _slang_free(spec->_struct);
-            spec->_struct = NULL;
-            RETURN0;
-         }
-         if (!slang_struct_copy(spec->_struct, stru))
-            RETURN0;
-      }
-      break;
-   default:
-      RETURN0;
-   }
-   return 1;
-}
-
-#define TYPE_SPECIFIER_NONARRAY 0
-#define TYPE_SPECIFIER_ARRAY    1
-
-static int
-parse_type_array_size(slang_parse_ctx *C,
-                      slang_output_ctx *O,
-                      GLint *array_len)
-{
-   GLuint size;
-
-   switch (*C->I++) {
-   case TYPE_SPECIFIER_NONARRAY:
-      *array_len = -1; /* -1 = not an array */
-      break;
-   case TYPE_SPECIFIER_ARRAY:
-      if (!parse_array_len(C, O, &size))
-         RETURN0;
-      *array_len = (GLint) size;
-      break;
-   default:
-      assert(0);
-      RETURN0;
-   }
-   return 1;
-}
-
-#define PRECISION_DEFAULT 0
-#define PRECISION_LOW     1
-#define PRECISION_MEDIUM  2
-#define PRECISION_HIGH    3
-
-static int
-parse_type_precision(slang_parse_ctx *C,
-                     slang_type_precision *precision)
-{
-   GLint prec = *C->I++;
-   switch (prec) {
-   case PRECISION_DEFAULT:
-      *precision = SLANG_PREC_DEFAULT;
-      return 1;
-   case PRECISION_LOW:
-      *precision = SLANG_PREC_LOW;
-      return 1;
-   case PRECISION_MEDIUM:
-      *precision = SLANG_PREC_MEDIUM;
-      return 1;
-   case PRECISION_HIGH:
-      *precision = SLANG_PREC_HIGH;
-      return 1;
-   default:
-      RETURN0;
-   }
-}
-
-
-/* parameter qualifier */
-#define PARAM_QUALIFIER_IN 0
-#define PARAM_QUALIFIER_OUT 1
-#define PARAM_QUALIFIER_INOUT 2
-#define PARAM_QUALIFIER_NONE 3
-static int
-parse_varying_qualifier(slang_parse_ctx * C, slang_fully_specified_type *type)
-{
-   int param_qual = *C->I++;
-
-   if (type->qualifier != SLANG_QUAL_VARYING &&
-       param_qual != PARAM_QUALIFIER_NONE) {
-      slang_info_log_error(C->L, "Invalid type qualifier.");
-      RETURN0;
-   }
-   switch (param_qual) {
-   case PARAM_QUALIFIER_IN:
-   case PARAM_QUALIFIER_NONE:
-      type->varying_kind = SLANG_VARYING_IN;
-      break;
-   case PARAM_QUALIFIER_OUT:
-      type->varying_kind = SLANG_VARYING_OUT;
-      break;
-   case PARAM_QUALIFIER_INOUT:
-      slang_info_log_error(C->L, "Invalid type qualifier.");
-      RETURN0;
-      break;
-   default:
-      RETURN0;
-   }
-   return 1;
-}
-
-static int
-parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O,
-                           slang_fully_specified_type * type)
-{
-   if (!parse_layout_qualifiers(C, &type->layout))
-      RETURN0;
-
-   if (!parse_type_variant(C, &type->variant))
-      RETURN0;
-
-   if (!parse_type_centroid(C, &type->centroid))
-      RETURN0;
-
-   if (!parse_type_qualifier(C, &type->qualifier))
-      RETURN0;
-
-   if (!parse_varying_qualifier(C, type))
-      RETURN0;
-
-   if (!parse_type_precision(C, &type->precision))
-      RETURN0;
-
-   if (!parse_type_specifier(C, O, &type->specifier))
-      RETURN0;
-
-   if (!parse_type_array_size(C, O, &type->array_len))
-      RETURN0;
-
-   if (!O->allow_invariant && type->variant == SLANG_INVARIANT) {
-      slang_info_log_error(C->L,
-         "'invariant' keyword not allowed (perhaps set #version 120)");
-      RETURN0;
-   }
-
-   if (!O->allow_centroid && type->centroid == SLANG_CENTROID) {
-      slang_info_log_error(C->L,
-         "'centroid' keyword not allowed (perhaps set #version 120)");
-      RETURN0;
-   }
-   else if (type->centroid == SLANG_CENTROID &&
-            type->qualifier != SLANG_QUAL_VARYING) {
-      slang_info_log_error(C->L,
-         "'centroid' keyword only allowed for varying vars");
-      RETURN0;
-   }
-
-
-   /* need this?
-   if (type->qualifier != SLANG_QUAL_VARYING &&
-       type->variant == SLANG_INVARIANT) {
-      slang_info_log_error(C->L,
-                           "invariant qualifer only allowed for varying vars");
-      RETURN0;
-   }
-   */
-
-   if (O->allow_precision) {
-      if (type->precision == SLANG_PREC_DEFAULT) {
-         assert(type->specifier.type < TYPE_SPECIFIER_COUNT);
-         /* use the default precision for this datatype */
-         type->precision = O->default_precision[type->specifier.type];
-      }
-   }
-   else {
-      /* only default is allowed */
-      if (type->precision != SLANG_PREC_DEFAULT) {
-         slang_info_log_error(C->L, "precision qualifiers not allowed");
-         RETURN0;
-      }
-   }
-
-   if (!O->allow_array_types && type->array_len >= 0) {
-      slang_info_log_error(C->L, "first-class array types not allowed");
-      RETURN0;
-   }
-
-   if (type->array_len >= 0) {
-      /* convert type to array type (ex: convert "int" to "array of int" */
-      promote_type_to_array(C, type, type->array_len);
-   }
-
-   return 1;
-}
-
-/* operation */
-#define OP_END 0
-#define OP_BLOCK_BEGIN_NO_NEW_SCOPE 1
-#define OP_BLOCK_BEGIN_NEW_SCOPE 2
-#define OP_DECLARE 3
-#define OP_ASM 4
-#define OP_BREAK 5
-#define OP_CONTINUE 6
-#define OP_DISCARD 7
-#define OP_RETURN 8
-#define OP_EXPRESSION 9
-#define OP_IF 10
-#define OP_WHILE 11
-#define OP_DO 12
-#define OP_FOR 13
-#define OP_PUSH_VOID 14
-#define OP_PUSH_BOOL 15
-#define OP_PUSH_INT 16
-#define OP_PUSH_FLOAT 17
-#define OP_PUSH_IDENTIFIER 18
-#define OP_SEQUENCE 19
-#define OP_ASSIGN 20
-#define OP_ADDASSIGN 21
-#define OP_SUBASSIGN 22
-#define OP_MULASSIGN 23
-#define OP_DIVASSIGN 24
-/*#define OP_MODASSIGN 25*/
-/*#define OP_LSHASSIGN 26*/
-/*#define OP_RSHASSIGN 27*/
-/*#define OP_ORASSIGN 28*/
-/*#define OP_XORASSIGN 29*/
-/*#define OP_ANDASSIGN 30*/
-#define OP_SELECT 31
-#define OP_LOGICALOR 32
-#define OP_LOGICALXOR 33
-#define OP_LOGICALAND 34
-/*#define OP_BITOR 35*/
-/*#define OP_BITXOR 36*/
-/*#define OP_BITAND 37*/
-#define OP_EQUAL 38
-#define OP_NOTEQUAL 39
-#define OP_LESS 40
-#define OP_GREATER 41
-#define OP_LESSEQUAL 42
-#define OP_GREATEREQUAL 43
-/*#define OP_LSHIFT 44*/
-/*#define OP_RSHIFT 45*/
-#define OP_ADD 46
-#define OP_SUBTRACT 47
-#define OP_MULTIPLY 48
-#define OP_DIVIDE 49
-/*#define OP_MODULUS 50*/
-#define OP_PREINCREMENT 51
-#define OP_PREDECREMENT 52
-#define OP_PLUS 53
-#define OP_MINUS 54
-/*#define OP_COMPLEMENT 55*/
-#define OP_NOT 56
-#define OP_SUBSCRIPT 57
-#define OP_CALL 58
-#define OP_FIELD 59
-#define OP_POSTINCREMENT 60
-#define OP_POSTDECREMENT 61
-#define OP_PRECISION 62
-#define OP_METHOD 63
-
-
-/**
- * When parsing a compound production, this function is used to parse the
- * children.
- * For example, a while-loop compound will have two children, the
- * while condition expression and the loop body.  So, this function will
- * be called twice to parse those two sub-expressions.
- * \param C  the parsing context
- * \param O  the output context
- * \param oper  the operation we're parsing
- * \param statement  indicates whether parsing a statement, or expression
- * \return 1 if success, 0 if error
- */
-static int
-parse_child_operation(slang_parse_ctx * C, slang_output_ctx * O,
-                      slang_operation * oper, GLboolean statement)
-{
-   slang_operation *ch;
-
-   /* grow child array */
-   ch = slang_operation_grow(&oper->num_children, &oper->children);
-   if (statement)
-      return parse_statement(C, O, ch);
-   return parse_expression(C, O, ch);
-}
-
-static int parse_declaration(slang_parse_ctx * C, slang_output_ctx * O);
-
-static int
-parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
-                slang_operation * oper)
-{
-   int op;
-
-   oper->locals->outer_scope = O->vars;
-
-   op = *C->I++;
-   switch (op) {
-   case OP_BLOCK_BEGIN_NO_NEW_SCOPE:
-      /* parse child statements, do not create new variable scope */
-      oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
-      while (*C->I != OP_END)
-         if (!parse_child_operation(C, O, oper, GL_TRUE))
-            RETURN0;
-      C->I++;
-      break;
-   case OP_BLOCK_BEGIN_NEW_SCOPE:
-      /* parse child statements, create new variable scope */
-      {
-         slang_output_ctx o = *O;
-
-         oper->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-         o.vars = oper->locals;
-         while (*C->I != OP_END)
-            if (!parse_child_operation(C, &o, oper, GL_TRUE))
-               RETURN0;
-         C->I++;
-      }
-      break;
-   case OP_DECLARE:
-      /* local variable declaration, individual declarators are stored as
-       * children identifiers
-       */
-      oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
-      {
-         const unsigned int first_var = O->vars->num_variables;
-
-         /* parse the declaration, note that there can be zero or more
-          * than one declarators
-          */
-         if (!parse_declaration(C, O))
-            RETURN0;
-         if (first_var < O->vars->num_variables) {
-            const unsigned int num_vars = O->vars->num_variables - first_var;
-            unsigned int i;
-            assert(oper->num_children == 0);
-            oper->num_children = num_vars;
-            oper->children = slang_operation_new(num_vars);
-            if (oper->children == NULL) {
-               slang_info_log_memory(C->L);
-               RETURN0;
-            }
-            for (i = first_var; i < O->vars->num_variables; i++) {
-               slang_operation *o = &oper->children[i - first_var];
-               slang_variable *var = O->vars->variables[i];
-               o->type = SLANG_OPER_VARIABLE_DECL;
-               o->locals->outer_scope = O->vars;
-               o->a_id = var->a_name;
-
-               /* new/someday...
-               calculate_var_size(C, O, var);
-               */
-
-               if (!legal_identifier(o->a_id)) {
-                  slang_info_log_error(C->L, "illegal variable name '%s'",
-                                       (char *) o->a_id);
-                  RETURN0;
-               }
-            }
-         }
-      }
-      break;
-   case OP_ASM:
-      /* the __asm statement, parse the mnemonic and all its arguments
-       * as expressions
-       */
-      oper->type = SLANG_OPER_ASM;
-      oper->a_id = parse_identifier(C);
-      if (oper->a_id == SLANG_ATOM_NULL)
-         RETURN0;
-      while (*C->I != OP_END) {
-         if (!parse_child_operation(C, O, oper, GL_FALSE))
-            RETURN0;
-      }
-      C->I++;
-      break;
-   case OP_BREAK:
-      oper->type = SLANG_OPER_BREAK;
-      break;
-   case OP_CONTINUE:
-      oper->type = SLANG_OPER_CONTINUE;
-      break;
-   case OP_DISCARD:
-      oper->type = SLANG_OPER_DISCARD;
-      break;
-   case OP_RETURN:
-      oper->type = SLANG_OPER_RETURN;
-      if (!parse_child_operation(C, O, oper, GL_FALSE))
-         RETURN0;
-      break;
-   case OP_EXPRESSION:
-      oper->type = SLANG_OPER_EXPRESSION;
-      if (!parse_child_operation(C, O, oper, GL_FALSE))
-         RETURN0;
-      break;
-   case OP_IF:
-      oper->type = SLANG_OPER_IF;
-      if (!parse_child_operation(C, O, oper, GL_FALSE))
-         RETURN0;
-      if (!parse_child_operation(C, O, oper, GL_TRUE))
-         RETURN0;
-      if (!parse_child_operation(C, O, oper, GL_TRUE))
-         RETURN0;
-      break;
-   case OP_WHILE:
-      {
-         slang_output_ctx o = *O;
-
-         oper->type = SLANG_OPER_WHILE;
-         o.vars = oper->locals;
-         if (!parse_child_operation(C, &o, oper, GL_TRUE))
-            RETURN0;
-         if (!parse_child_operation(C, &o, oper, GL_TRUE))
-            RETURN0;
-      }
-      break;
-   case OP_DO:
-      oper->type = SLANG_OPER_DO;
-      if (!parse_child_operation(C, O, oper, GL_TRUE))
-         RETURN0;
-      if (!parse_child_operation(C, O, oper, GL_FALSE))
-         RETURN0;
-      break;
-   case OP_FOR:
-      {
-         slang_output_ctx o = *O;
-
-         oper->type = SLANG_OPER_FOR;
-         o.vars = oper->locals;
-         if (!parse_child_operation(C, &o, oper, GL_TRUE))
-            RETURN0;
-         if (!parse_child_operation(C, &o, oper, GL_TRUE))
-            RETURN0;
-         if (!parse_child_operation(C, &o, oper, GL_FALSE))
-            RETURN0;
-         if (!parse_child_operation(C, &o, oper, GL_TRUE))
-            RETURN0;
-      }
-      break;
-   case OP_PRECISION:
-      {
-         /* set default precision for a type in this scope */
-         /* ignored at this time */
-         int prec_qual = *C->I++;
-         int datatype = *C->I++;
-         (void) prec_qual;
-         (void) datatype;
-      }
-      break;
-   default:
-      /*printf("Unexpected operation %d\n", op);*/
-      RETURN0;
-   }
-   return 1;
-}
-
-static int
-handle_nary_expression(slang_parse_ctx * C, slang_operation * op,
-                       slang_operation ** ops, unsigned int *total_ops,
-                       unsigned int n)
-{
-   unsigned int i;
-
-   op->children = slang_operation_new(n);
-   if (op->children == NULL) {
-      slang_info_log_memory(C->L);
-      RETURN0;
-   }
-   op->num_children = n;
-
-   for (i = 0; i < n; i++) {
-      slang_operation_destruct(&op->children[i]);
-      op->children[i] = (*ops)[*total_ops - (n + 1 - i)];
-   }
-
-   (*ops)[*total_ops - (n + 1)] = (*ops)[*total_ops - 1];
-   *total_ops -= n;
-
-   *ops = (slang_operation *)
-      _slang_realloc(*ops,
-                     (*total_ops + n) * sizeof(slang_operation),
-                     *total_ops * sizeof(slang_operation));
-   if (*ops == NULL) {
-      slang_info_log_memory(C->L);
-      RETURN0;
-   }
-   return 1;
-}
-
-static int
-is_constructor_name(const char *name, slang_atom a_name,
-                    slang_struct_scope * structs)
-{
-   if (slang_type_specifier_type_from_string(name) != SLANG_SPEC_VOID)
-      return 1;
-   return slang_struct_scope_find(structs, a_name, 1) != NULL;
-}
-
-#define FUNCTION_CALL_NONARRAY 0
-#define FUNCTION_CALL_ARRAY    1
-
-static int
-parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
-                 slang_operation * oper)
-{
-   slang_operation *ops = NULL;
-   unsigned int num_ops = 0;
-   int number;
-
-   while (*C->I != OP_END) {
-      slang_operation *op;
-      const unsigned int op_code = *C->I++;
-
-      /* allocate default operation, becomes a no-op if not used  */
-      ops = (slang_operation *)
-         _slang_realloc(ops,
-                        num_ops * sizeof(slang_operation),
-                        (num_ops + 1) * sizeof(slang_operation));
-      if (ops == NULL) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      op = &ops[num_ops];
-      if (!slang_operation_construct(op)) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      num_ops++;
-      op->locals->outer_scope = O->vars;
-
-      switch (op_code) {
-      case OP_PUSH_VOID:
-         op->type = SLANG_OPER_VOID;
-         break;
-      case OP_PUSH_BOOL:
-         op->type = SLANG_OPER_LITERAL_BOOL;
-         if (!parse_number(C, &number))
-            RETURN0;
-         op->literal[0] =
-         op->literal[1] =
-         op->literal[2] =
-         op->literal[3] = (GLfloat) number;
-         op->literal_size = 1;
-         break;
-      case OP_PUSH_INT:
-         op->type = SLANG_OPER_LITERAL_INT;
-         if (!parse_number(C, &number))
-            RETURN0;
-         op->literal[0] =
-         op->literal[1] =
-         op->literal[2] =
-         op->literal[3] = (GLfloat) number;
-         op->literal_size = 1;
-         break;
-      case OP_PUSH_FLOAT:
-         op->type = SLANG_OPER_LITERAL_FLOAT;
-         if (!parse_float(C, &op->literal[0]))
-            RETURN0;
-         op->literal[1] =
-         op->literal[2] =
-         op->literal[3] = op->literal[0];
-         op->literal_size = 1;
-         break;
-      case OP_PUSH_IDENTIFIER:
-         op->type = SLANG_OPER_IDENTIFIER;
-         op->a_id = parse_identifier(C);
-         if (op->a_id == SLANG_ATOM_NULL)
-            RETURN0;
-         break;
-      case OP_SEQUENCE:
-         op->type = SLANG_OPER_SEQUENCE;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_ASSIGN:
-         op->type = SLANG_OPER_ASSIGN;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_ADDASSIGN:
-         op->type = SLANG_OPER_ADDASSIGN;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_SUBASSIGN:
-         op->type = SLANG_OPER_SUBASSIGN;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_MULASSIGN:
-         op->type = SLANG_OPER_MULASSIGN;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_DIVASSIGN:
-         op->type = SLANG_OPER_DIVASSIGN;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-         /*case OP_MODASSIGN: */
-         /*case OP_LSHASSIGN: */
-         /*case OP_RSHASSIGN: */
-         /*case OP_ORASSIGN: */
-         /*case OP_XORASSIGN: */
-         /*case OP_ANDASSIGN: */
-      case OP_SELECT:
-         op->type = SLANG_OPER_SELECT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 3))
-            RETURN0;
-         break;
-      case OP_LOGICALOR:
-         op->type = SLANG_OPER_LOGICALOR;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_LOGICALXOR:
-         op->type = SLANG_OPER_LOGICALXOR;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_LOGICALAND:
-         op->type = SLANG_OPER_LOGICALAND;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-         /*case OP_BITOR: */
-         /*case OP_BITXOR: */
-         /*case OP_BITAND: */
-      case OP_EQUAL:
-         op->type = SLANG_OPER_EQUAL;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_NOTEQUAL:
-         op->type = SLANG_OPER_NOTEQUAL;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_LESS:
-         op->type = SLANG_OPER_LESS;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_GREATER:
-         op->type = SLANG_OPER_GREATER;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_LESSEQUAL:
-         op->type = SLANG_OPER_LESSEQUAL;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_GREATEREQUAL:
-         op->type = SLANG_OPER_GREATEREQUAL;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-         /*case OP_LSHIFT: */
-         /*case OP_RSHIFT: */
-      case OP_ADD:
-         op->type = SLANG_OPER_ADD;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_SUBTRACT:
-         op->type = SLANG_OPER_SUBTRACT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_MULTIPLY:
-         op->type = SLANG_OPER_MULTIPLY;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_DIVIDE:
-         op->type = SLANG_OPER_DIVIDE;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-         /*case OP_MODULUS: */
-      case OP_PREINCREMENT:
-         op->type = SLANG_OPER_PREINCREMENT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-      case OP_PREDECREMENT:
-         op->type = SLANG_OPER_PREDECREMENT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-      case OP_PLUS:
-         op->type = SLANG_OPER_PLUS;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-      case OP_MINUS:
-         op->type = SLANG_OPER_MINUS;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-      case OP_NOT:
-         op->type = SLANG_OPER_NOT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-         /*case OP_COMPLEMENT: */
-      case OP_SUBSCRIPT:
-         op->type = SLANG_OPER_SUBSCRIPT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
-            RETURN0;
-         break;
-      case OP_METHOD:
-         op->type = SLANG_OPER_METHOD;
-         op->a_obj = parse_identifier(C);
-         if (op->a_obj == SLANG_ATOM_NULL)
-            RETURN0;
-
-         op->a_id = parse_identifier(C);
-         if (op->a_id == SLANG_ATOM_NULL)
-            RETURN0;
-
-         assert(*C->I == OP_END);
-         C->I++;
-
-         while (*C->I != OP_END)
-            if (!parse_child_operation(C, O, op, GL_FALSE))
-               RETURN0;
-         C->I++;
-#if 0
-         /* don't lookup the method (not yet anyway) */
-         if (!C->parsing_builtin
-             && !slang_function_scope_find_by_name(O->funs, op->a_id, 1)) {
-            const char *id;
-
-            id = slang_atom_pool_id(C->atoms, op->a_id);
-            if (!is_constructor_name(id, op->a_id, O->structs)) {
-               slang_info_log_error(C->L, "%s: undeclared function name.", id);
-               RETURN0;
-            }
-         }
-#endif
-         break;
-      case OP_CALL:
-         {
-            GLboolean array_constructor = GL_FALSE;
-            GLint array_constructor_size = 0;
-
-            op->type = SLANG_OPER_CALL;
-            op->a_id = parse_identifier(C);
-            if (op->a_id == SLANG_ATOM_NULL)
-               RETURN0;
-            switch (*C->I++) {
-            case FUNCTION_CALL_NONARRAY:
-               /* Nothing to do. */
-               break;
-            case FUNCTION_CALL_ARRAY:
-               /* Calling an array constructor. For example:
-                *   float[3](1.1, 2.2, 3.3);
-                */
-               if (!O->allow_array_types) {
-                  slang_info_log_error(C->L,
-                                       "array constructors not allowed "
-                                       "in this GLSL version");
-                  RETURN0;
-               }
-               else {
-                  /* parse the array constructor size */
-                  slang_operation array_size;
-                  array_constructor = GL_TRUE;
-                  slang_operation_construct(&array_size);
-                  if (!parse_expression(C, O, &array_size)) {
-                     slang_operation_destruct(&array_size);
-                     return GL_FALSE;
-                  }
-                  if (array_size.type != SLANG_OPER_LITERAL_INT) {
-                     slang_info_log_error(C->L,
-                        "constructor array size is not an integer");
-                     slang_operation_destruct(&array_size);
-                     RETURN0;
-                  }
-                  array_constructor_size = (int) array_size.literal[0];
-                  op->array_constructor = GL_TRUE;
-                  slang_operation_destruct(&array_size);
-               }
-               break;
-            default:
-               assert(0);
-               RETURN0;
-            }
-            while (*C->I != OP_END)
-               if (!parse_child_operation(C, O, op, GL_FALSE))
-                  RETURN0;
-            C->I++;
-
-            if (array_constructor &&
-                array_constructor_size != op->num_children) {
-               slang_info_log_error(C->L, "number of parameters to array"
-                                    " constructor does not match array size");
-               RETURN0;
-            }
-
-            if (!C->parsing_builtin
-                && !slang_function_scope_find_by_name(O->funs, op->a_id, 1)) {
-               const char *id;
-
-               id = slang_atom_pool_id(C->atoms, op->a_id);
-               if (!is_constructor_name(id, op->a_id, O->structs)) {
-                  slang_info_log_error(C->L, "%s: undeclared function name.", id);
-                  RETURN0;
-               }
-            }
-         }
-         break;
-      case OP_FIELD:
-         op->type = SLANG_OPER_FIELD;
-         op->a_id = parse_identifier(C);
-         if (op->a_id == SLANG_ATOM_NULL)
-            RETURN0;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-      case OP_POSTINCREMENT:
-         op->type = SLANG_OPER_POSTINCREMENT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-      case OP_POSTDECREMENT:
-         op->type = SLANG_OPER_POSTDECREMENT;
-         if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
-            RETURN0;
-         break;
-      default:
-         RETURN0;
-      }
-   }
-   C->I++;
-
-   slang_operation_destruct(oper);
-   *oper = *ops; /* struct copy */
-   _slang_free(ops);
-
-   return 1;
-}
-
-/* function parameter array presence */
-#define PARAMETER_ARRAY_NOT_PRESENT 0
-#define PARAMETER_ARRAY_PRESENT 1
-
-static int
-parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O,
-                            slang_variable * param)
-{
-   int param_qual, precision_qual;
-
-   /* parse and validate the parameter's type qualifiers (there can be
-    * two at most) because not all combinations are valid
-    */
-   if (!parse_type_qualifier(C, &param->type.qualifier))
-      RETURN0;
-
-   param_qual = *C->I++;
-   switch (param_qual) {
-   case PARAM_QUALIFIER_IN:
-      if (param->type.qualifier != SLANG_QUAL_CONST
-          && param->type.qualifier != SLANG_QUAL_NONE) {
-         slang_info_log_error(C->L, "Invalid type qualifier.");
-         RETURN0;
-      }
-      break;
-   case PARAM_QUALIFIER_OUT:
-      if (param->type.qualifier == SLANG_QUAL_NONE)
-         param->type.qualifier = SLANG_QUAL_OUT;
-      else {
-         slang_info_log_error(C->L, "Invalid type qualifier.");
-         RETURN0;
-      }
-      break;
-   case PARAM_QUALIFIER_INOUT:
-      if (param->type.qualifier == SLANG_QUAL_NONE)
-         param->type.qualifier = SLANG_QUAL_INOUT;
-      else {
-         slang_info_log_error(C->L, "Invalid type qualifier.");
-         RETURN0;
-      }
-      break;
-   case PARAM_QUALIFIER_NONE:
-      /* like IN but doesn't throw error */
-      break;
-   default:
-      RETURN0;
-   }
-
-   /* parse precision qualifier (lowp, mediump, highp */
-   precision_qual = *C->I++;
-   /* ignored at this time */
-   (void) precision_qual;
-
-   /* parse parameter's type specifier and name */
-   if (!parse_type_specifier(C, O, &param->type.specifier))
-      RETURN0;
-   if (!parse_type_array_size(C, O, &param->type.array_len))
-      RETURN0;
-   param->a_name = parse_identifier(C);
-   if (param->a_name == SLANG_ATOM_NULL)
-      RETURN0;
-
-   /* first-class array
-    */
-   if (param->type.array_len >= 0) {
-      slang_type_specifier p;
-
-      slang_type_specifier_ctr(&p);
-      if (!slang_type_specifier_copy(&p, &param->type.specifier)) {
-         slang_type_specifier_dtr(&p);
-         RETURN0;
-      }
-      if (!convert_to_array(C, param, &p)) {
-         slang_type_specifier_dtr(&p);
-         RETURN0;
-      }
-      slang_type_specifier_dtr(&p);
-      param->array_len = param->type.array_len;
-   }
-
-   /* if the parameter is an array, parse its size (the size must be
-    * explicitly defined
-    */
-   if (*C->I++ == PARAMETER_ARRAY_PRESENT) {
-      slang_type_specifier p;
-
-      if (param->type.array_len >= 0) {
-         slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
-         RETURN0;
-      }
-      slang_type_specifier_ctr(&p);
-      if (!slang_type_specifier_copy(&p, &param->type.specifier)) {
-         slang_type_specifier_dtr(&p);
-         RETURN0;
-      }
-      if (!convert_to_array(C, param, &p)) {
-         slang_type_specifier_dtr(&p);
-         RETURN0;
-      }
-      slang_type_specifier_dtr(&p);
-      if (!parse_array_len(C, O, &param->array_len))
-         RETURN0;
-   }
-
-#if 0
-   /* calculate the parameter size */
-   if (!calculate_var_size(C, O, param))
-      RETURN0;
-#endif
-   /* TODO: allocate the local address here? */
-   return 1;
-}
-
-/* function type */
-#define FUNCTION_ORDINARY 0
-#define FUNCTION_CONSTRUCTOR 1
-#define FUNCTION_OPERATOR 2
-
-/* function parameter */
-#define PARAMETER_NONE 0
-#define PARAMETER_NEXT 1
-
-/* operator type */
-#define OPERATOR_ADDASSIGN 1
-#define OPERATOR_SUBASSIGN 2
-#define OPERATOR_MULASSIGN 3
-#define OPERATOR_DIVASSIGN 4
-/*#define OPERATOR_MODASSIGN 5*/
-/*#define OPERATOR_LSHASSIGN 6*/
-/*#define OPERATOR_RSHASSIGN 7*/
-/*#define OPERATOR_ANDASSIGN 8*/
-/*#define OPERATOR_XORASSIGN 9*/
-/*#define OPERATOR_ORASSIGN 10*/
-#define OPERATOR_LOGICALXOR 11
-/*#define OPERATOR_BITOR 12*/
-/*#define OPERATOR_BITXOR 13*/
-/*#define OPERATOR_BITAND 14*/
-#define OPERATOR_LESS 15
-#define OPERATOR_GREATER 16
-#define OPERATOR_LESSEQUAL 17
-#define OPERATOR_GREATEREQUAL 18
-/*#define OPERATOR_LSHIFT 19*/
-/*#define OPERATOR_RSHIFT 20*/
-#define OPERATOR_MULTIPLY 21
-#define OPERATOR_DIVIDE 22
-/*#define OPERATOR_MODULUS 23*/
-#define OPERATOR_INCREMENT 24
-#define OPERATOR_DECREMENT 25
-#define OPERATOR_PLUS 26
-#define OPERATOR_MINUS 27
-/*#define OPERATOR_COMPLEMENT 28*/
-#define OPERATOR_NOT 29
-
-static const struct
-{
-   unsigned int o_code;
-   const char *o_name;
-} operator_names[] = {
-   {OPERATOR_INCREMENT, "++"},
-   {OPERATOR_ADDASSIGN, "+="},
-   {OPERATOR_PLUS, "+"},
-   {OPERATOR_DECREMENT, "--"},
-   {OPERATOR_SUBASSIGN, "-="},
-   {OPERATOR_MINUS, "-"},
-   {OPERATOR_NOT, "!"},
-   {OPERATOR_MULASSIGN, "*="},
-   {OPERATOR_MULTIPLY, "*"},
-   {OPERATOR_DIVASSIGN, "/="},
-   {OPERATOR_DIVIDE, "/"},
-   {OPERATOR_LESSEQUAL, "<="},
-   /*{ OPERATOR_LSHASSIGN, "<<=" }, */
-   /*{ OPERATOR_LSHIFT, "<<" }, */
-   {OPERATOR_LESS, "<"},
-   {OPERATOR_GREATEREQUAL, ">="},
-   /*{ OPERATOR_RSHASSIGN, ">>=" }, */
-   /*{ OPERATOR_RSHIFT, ">>" }, */
-   {OPERATOR_GREATER, ">"},
-   /*{ OPERATOR_MODASSIGN, "%=" }, */
-   /*{ OPERATOR_MODULUS, "%" }, */
-   /*{ OPERATOR_ANDASSIGN, "&=" }, */
-   /*{ OPERATOR_BITAND, "&" }, */
-   /*{ OPERATOR_ORASSIGN, "|=" }, */
-   /*{ OPERATOR_BITOR, "|" }, */
-   /*{ OPERATOR_COMPLEMENT, "~" }, */
-   /*{ OPERATOR_XORASSIGN, "^=" }, */
-   {OPERATOR_LOGICALXOR, "^^"},
-   /*{ OPERATOR_BITXOR, "^" } */
-};
-
-static slang_atom
-parse_operator_name(slang_parse_ctx * C)
-{
-   unsigned int i;
-
-   for (i = 0; i < sizeof(operator_names) / sizeof(*operator_names); i++) {
-      if (operator_names[i].o_code == (unsigned int) (*C->I)) {
-         slang_atom atom =
-            slang_atom_pool_atom(C->atoms, operator_names[i].o_name);
-         if (atom == SLANG_ATOM_NULL) {
-            slang_info_log_memory(C->L);
-            RETURN0;
-         }
-         C->I++;
-         return atom;
-      }
-   }
-   RETURN0;
-}
-
-
-static int
-parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O,
-                         slang_function * func)
-{
-   GLuint functype;
-   /* parse function type and name */
-   if (!parse_fully_specified_type(C, O, &func->header.type))
-      RETURN0;
-
-   functype = *C->I++;
-   switch (functype) {
-   case FUNCTION_ORDINARY:
-      func->kind = SLANG_FUNC_ORDINARY;
-      func->header.a_name = parse_identifier(C);
-      if (func->header.a_name == SLANG_ATOM_NULL)
-         RETURN0;
-      break;
-   case FUNCTION_CONSTRUCTOR:
-      func->kind = SLANG_FUNC_CONSTRUCTOR;
-      if (func->header.type.specifier.type == SLANG_SPEC_STRUCT)
-         RETURN0;
-      func->header.a_name =
-         slang_atom_pool_atom(C->atoms,
-                              slang_type_specifier_type_to_string
-                              (func->header.type.specifier.type));
-      if (func->header.a_name == SLANG_ATOM_NULL) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      break;
-   case FUNCTION_OPERATOR:
-      func->kind = SLANG_FUNC_OPERATOR;
-      func->header.a_name = parse_operator_name(C);
-      if (func->header.a_name == SLANG_ATOM_NULL)
-         RETURN0;
-      break;
-   default:
-      RETURN0;
-   }
-
-   if (!legal_identifier(func->header.a_name)) {
-      slang_info_log_error(C->L, "illegal function name '%s'",
-                           (char *) func->header.a_name);
-      RETURN0;
-   }
-
-   /* parse function parameters */
-   while (*C->I++ == PARAMETER_NEXT) {
-      slang_variable *p = slang_variable_scope_grow(func->parameters);
-      if (!p) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      if (!parse_parameter_declaration(C, O, p))
-         RETURN0;
-   }
-
-   /* if the function returns a value, append a hidden __retVal 'out'
-    * parameter that corresponds to the return value.
-    */
-   if (_slang_function_has_return_value(func)) {
-      slang_variable *p = slang_variable_scope_grow(func->parameters);
-      slang_atom a_retVal = slang_atom_pool_atom(C->atoms, "__retVal");
-      assert(a_retVal);
-      p->a_name = a_retVal;
-      p->type = func->header.type;
-      p->type.qualifier = SLANG_QUAL_OUT;
-   }
-
-   /* function formal parameters and local variables share the same
-    * scope, so save the information about param count in a seperate
-    * place also link the scope to the global variable scope so when a
-    * given identifier is not found here, the search process continues
-    * in the global space
-    */
-   func->param_count = func->parameters->num_variables;
-   func->parameters->outer_scope = O->vars;
-
-   return 1;
-}
-
-static int
-parse_function_definition(slang_parse_ctx * C, slang_output_ctx * O,
-                          slang_function * func)
-{
-   slang_output_ctx o = *O;
-
-   if (!parse_function_prototype(C, O, func))
-      RETURN0;
-
-   /* create function's body operation */
-   func->body = (slang_operation *) _slang_alloc(sizeof(slang_operation));
-   if (func->body == NULL) {
-      slang_info_log_memory(C->L);
-      RETURN0;
-   }
-   if (!slang_operation_construct(func->body)) {
-      _slang_free(func->body);
-      func->body = NULL;
-      slang_info_log_memory(C->L);
-      RETURN0;
-   }
-
-   /* to parse the body the parse context is modified in order to
-    * capture parsed variables into function's local variable scope
-    */
-   C->global_scope = GL_FALSE;
-   o.vars = func->parameters;
-   if (!parse_statement(C, &o, func->body))
-      RETURN0;
-
-   C->global_scope = GL_TRUE;
-   return 1;
-}
-
-static GLboolean
-initialize_global(slang_assemble_ctx * A, slang_variable * var)
-{
-   slang_operation op_id, op_assign;
-   GLboolean result;
-
-   /* construct the left side of assignment */
-   if (!slang_operation_construct(&op_id))
-      return GL_FALSE;
-   op_id.type = SLANG_OPER_IDENTIFIER;
-   op_id.a_id = var->a_name;
-
-   /* put the variable into operation's scope */
-   op_id.locals->variables =
-      (slang_variable **) _slang_alloc(sizeof(slang_variable *));
-   if (op_id.locals->variables == NULL) {
-      slang_operation_destruct(&op_id);
-      return GL_FALSE;
-   }
-   op_id.locals->num_variables = 1;
-   op_id.locals->variables[0] = var;
-
-   /* construct the assignment expression */
-   if (!slang_operation_construct(&op_assign)) {
-      op_id.locals->num_variables = 0;
-      slang_operation_destruct(&op_id);
-      return GL_FALSE;
-   }
-   op_assign.type = SLANG_OPER_ASSIGN;
-   op_assign.children =
-      (slang_operation *) _slang_alloc(2 * sizeof(slang_operation));
-   if (op_assign.children == NULL) {
-      slang_operation_destruct(&op_assign);
-      op_id.locals->num_variables = 0;
-      slang_operation_destruct(&op_id);
-      return GL_FALSE;
-   }
-   op_assign.num_children = 2;
-   op_assign.children[0] = op_id;
-   op_assign.children[1] = *var->initializer;
-
-   result = 1;
-
-   /* carefully destroy the operations */
-   op_assign.num_children = 0;
-   _slang_free(op_assign.children);
-   op_assign.children = NULL;
-   slang_operation_destruct(&op_assign);
-   op_id.locals->num_variables = 0;
-   slang_operation_destruct(&op_id);
-
-   if (!result)
-      return GL_FALSE;
-
-   return GL_TRUE;
-}
-
-/* init declarator list */
-#define DECLARATOR_NONE 0
-#define DECLARATOR_NEXT 1
-
-/* variable declaration */
-#define VARIABLE_NONE 0
-#define VARIABLE_IDENTIFIER 1
-#define VARIABLE_INITIALIZER 2
-#define VARIABLE_ARRAY_EXPLICIT 3
-#define VARIABLE_ARRAY_UNKNOWN 4
-
-
-/**
- * Check if it's OK to re-declare a variable with the given new type.
- * This happens when applying layout qualifiers to gl_FragCoord or
- * (re)setting an array size.
- * If redeclaration is OK, return a pointer to the incoming variable
- * updated with new type info.  Else return NULL;
- */
-static slang_variable *
-redeclare_variable(slang_variable *var, 
-                   const slang_fully_specified_type *type)
-{
-   if (slang_fully_specified_types_compatible(&var->type, type)) {
-      /* replace orig var layout with new layout */
-      var->type.layout = type->layout;
-
-      /* XXX there may be other type updates in the future here */
-
-      return var;
-   }
-   else
-      return NULL;
-}
-
-
-/**
- * Parse the initializer for a variable declaration.
- */
-static int
-parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
-                      const slang_fully_specified_type * type)
-{
-   GET_CURRENT_CONTEXT(ctx); /* a hack */
-   slang_variable *var = NULL, *prevDecl;
-   slang_atom a_name;
-
-   /* empty init declatator (without name, e.g. "float ;") */
-   if (*C->I++ == VARIABLE_NONE)
-      return 1;
-
-   a_name = parse_identifier(C);
-
-   /* check if name is already in this scope */
-   prevDecl = _slang_variable_locate(O->vars, a_name, C->global_scope);
-   if (prevDecl) {
-      /* A var with this name has already been declared.
-       * Check if redeclaring the var with a different type/layout is legal.
-       */
-      if (C->global_scope) {
-         var = redeclare_variable(prevDecl, type);
-      }
-      if (!var) {
-         slang_info_log_error(C->L,
-                   "declaration of '%s' conflicts with previous declaration",
-                   (char *) a_name);
-         RETURN0;
-      }
-   }
-
-   if (!var) {
-      /* make room for a new variable and initialize it */
-      var = slang_variable_scope_grow(O->vars);
-      if (!var) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-
-      /* copy the declarator type qualifier/etc info, parse the identifier */
-      var->type.qualifier = type->qualifier;
-      var->type.centroid = type->centroid;
-      var->type.precision = type->precision;
-      var->type.specifier = type->specifier;/*new*/
-      var->type.variant = type->variant;
-      var->type.layout = type->layout;
-      var->type.array_len = type->array_len;
-      var->type.varying_kind = type->varying_kind;
-      var->a_name = a_name;
-      if (var->a_name == SLANG_ATOM_NULL)
-         RETURN0;
-   }
-
-   switch (*C->I++) {
-   case VARIABLE_NONE:
-      /* simple variable declarator - just copy the specifier */
-      if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier))
-         RETURN0;
-      break;
-   case VARIABLE_INITIALIZER:
-      /* initialized variable - copy the specifier and parse the expression */
-      if (0 && type->array_len >= 0) {
-         /* The type was something like "float[4]" */
-         convert_to_array(C, var, &type->specifier);
-         var->array_len = type->array_len;
-      }
-      else {
-         if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier))
-            RETURN0;
-      }
-      var->initializer =
-         (slang_operation *) _slang_alloc(sizeof(slang_operation));
-      if (var->initializer == NULL) {
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      if (!slang_operation_construct(var->initializer)) {
-         _slang_free(var->initializer);
-         var->initializer = NULL;
-         slang_info_log_memory(C->L);
-         RETURN0;
-      }
-      if (!parse_expression(C, O, var->initializer))
-         RETURN0;
-      break;
-   case VARIABLE_ARRAY_UNKNOWN:
-      /* unsized array - mark it as array and copy the specifier to
-       * the array element
-       */
-      if (type->array_len >= 0) {
-         slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
-         RETURN0;
-      }
-      if (!convert_to_array(C, var, &type->specifier))
-         return GL_FALSE;
-      break;
-   case VARIABLE_ARRAY_EXPLICIT:
-      if (type->array_len >= 0) {
-         /* the user is trying to do something like: float[2] x[3]; */
-         slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
-         RETURN0;
-      }
-      if (!convert_to_array(C, var, &type->specifier))
-         return GL_FALSE;
-      if (!parse_array_len(C, O, &var->array_len))
-         return GL_FALSE;
-      break;
-   default:
-      RETURN0;
-   }
-
-   /* allocate global address space for a variable with a known size */
-   if (C->global_scope
-       && !(var->type.specifier.type == SLANG_SPEC_ARRAY
-            && var->array_len == 0)) {
-      if (!calculate_var_size(C, O, var))
-         return GL_FALSE;
-   }
-
-   /* emit code for global var decl */
-   if (C->global_scope) {
-      slang_assemble_ctx A;
-      memset(&A, 0, sizeof(slang_assemble_ctx));
-      A.allow_uniform_initializers = C->version > 110;
-      A.atoms = C->atoms;
-      A.space.funcs = O->funs;
-      A.space.structs = O->structs;
-      A.space.vars = O->vars;
-      A.program = O->program;
-      A.pragmas = O->pragmas;
-      A.vartable = O->vartable;
-      A.log = C->L;
-      A.curFuncEndLabel = NULL;
-      A.EmitContReturn = ctx->Shader.EmitContReturn;
-      if (!_slang_codegen_global_variable(&A, var, C->type))
-         RETURN0;
-   }
-
-   /* initialize global variable */
-   if (C->global_scope) {
-      if (var->initializer != NULL) {
-         slang_assemble_ctx A;
-         memset(&A, 0, sizeof(slang_assemble_ctx));
-         A.allow_uniform_initializers = C->version > 110;
-         A.atoms = C->atoms;
-         A.space.funcs = O->funs;
-         A.space.structs = O->structs;
-         A.space.vars = O->vars;
-         if (!initialize_global(&A, var))
-            RETURN0;
-      }
-   }
-
-   if (var->type.qualifier == SLANG_QUAL_FIXEDINPUT &&
-       var->a_name == slang_atom_pool_atom(C->atoms, "gl_FragCoord")) {
-      /* set the program's PixelCenterInteger, OriginUpperLeft fields */
-      struct gl_fragment_program *fragProg =
-         (struct gl_fragment_program *) O->program;
-
-      if (var->type.layout & SLANG_LAYOUT_UPPER_LEFT_BIT) {
-         fragProg->OriginUpperLeft = GL_TRUE;
-      }
-      if (var->type.layout & SLANG_LAYOUT_PIXEL_CENTER_INTEGER_BIT) {
-         fragProg->PixelCenterInteger = GL_TRUE;
-      }
-   }
-
-   return 1;
-}
-
-/**
- * Parse a list of variable declarations.  Each variable may have an
- * initializer.
- */
-static int
-parse_init_declarator_list(slang_parse_ctx * C, slang_output_ctx * O)
-{
-   slang_fully_specified_type type;
-
-   /* parse the fully specified type, common to all declarators */
-   if (!slang_fully_specified_type_construct(&type))
-      RETURN0;
-   if (!parse_fully_specified_type(C, O, &type)) {
-      slang_fully_specified_type_destruct(&type);
-      RETURN0;
-   }
-
-   /* parse declarators, pass-in the parsed type */
-   do {
-      if (!parse_init_declarator(C, O, &type)) {
-         slang_fully_specified_type_destruct(&type);
-         RETURN0;
-      }
-   }
-   while (*C->I++ == DECLARATOR_NEXT);
-
-   slang_fully_specified_type_destruct(&type);
-   return 1;
-}
-
-
-/**
- * Parse a function definition or declaration.
- * \param C  parsing context
- * \param O  output context
- * \param definition if non-zero expect a definition, else a declaration
- * \param parsed_func_ret  returns the parsed function
- * \return GL_TRUE if success, GL_FALSE if failure
- */
-static GLboolean
-parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
-               slang_function ** parsed_func_ret)
-{
-   slang_function parsed_func, *found_func;
-
-   /* parse function definition/declaration */
-   if (!slang_function_construct(&parsed_func))
-      return GL_FALSE;
-   if (definition) {
-      if (!parse_function_definition(C, O, &parsed_func)) {
-         slang_function_destruct(&parsed_func);
-         return GL_FALSE;
-      }
-   }
-   else {
-      if (!parse_function_prototype(C, O, &parsed_func)) {
-         slang_function_destruct(&parsed_func);
-         return GL_FALSE;
-      }
-   }
-
-   /* find a function with a prototype matching the parsed one - only
-    * the current scope is being searched to allow built-in function
-    * overriding
-    */
-   found_func = slang_function_scope_find(O->funs, &parsed_func, 0);
-   if (found_func == NULL) {
-      /* New function, add it to the function list */
-      O->funs->functions =
-         (slang_function *) _slang_realloc(O->funs->functions,
-                                           O->funs->num_functions
-                                           * sizeof(slang_function),
-                                           (O->funs->num_functions + 1)
-                                           * sizeof(slang_function));
-      if (O->funs->functions == NULL) {
-         /* Make sure that there are no functions marked, as the
-          * allocation is currently NULL, in order to avoid
-          * a potental segfault as we clean up later.
-          */
-         O->funs->num_functions = 0;
-
-         slang_info_log_memory(C->L);
-         slang_function_destruct(&parsed_func);
-         return GL_FALSE;
-      }
-      O->funs->functions[O->funs->num_functions] = parsed_func;
-      O->funs->num_functions++;
-
-      /* return the newly parsed function */
-      *parsed_func_ret = &O->funs->functions[O->funs->num_functions - 1];
-   }
-   else {
-      /* previously defined or declared */
-      /* TODO: check function return type qualifiers and specifiers */
-      if (definition) {
-         if (found_func->body != NULL) {
-            slang_info_log_error(C->L, "%s: function already has a body.",
-                                 slang_atom_pool_id(C->atoms,
-                                                    parsed_func.header.
-                                                    a_name));
-            slang_function_destruct(&parsed_func);
-            return GL_FALSE;
-         }
-
-         /* destroy the existing function declaration and replace it
-          * with the new one
-          */
-         slang_function_destruct(found_func);
-         *found_func = parsed_func;
-      }
-      else {
-         /* another declaration of the same function prototype - ignore it */
-         slang_function_destruct(&parsed_func);
-      }
-
-      /* return the found function */
-      *parsed_func_ret = found_func;
-   }
-
-   return GL_TRUE;
-}
-
-/* declaration */
-#define DECLARATION_FUNCTION_PROTOTYPE 1
-#define DECLARATION_INIT_DECLARATOR_LIST 2
-
-static int
-parse_declaration(slang_parse_ctx * C, slang_output_ctx * O)
-{
-   switch (*C->I++) {
-   case DECLARATION_INIT_DECLARATOR_LIST:
-      if (!parse_init_declarator_list(C, O))
-         RETURN0;
-      break;
-   case DECLARATION_FUNCTION_PROTOTYPE:
-      {
-         slang_function *dummy_func;
-
-         if (!parse_function(C, O, 0, &dummy_func))
-            RETURN0;
-      }
-      break;
-   default:
-      RETURN0;
-   }
-   return 1;
-}
-
-static int
-parse_default_precision(slang_parse_ctx * C, slang_output_ctx * O)
-{
-   int precision, type;
-
-   if (!O->allow_precision) {
-      slang_info_log_error(C->L, "syntax error at \"precision\"");
-      RETURN0;
-   }
-
-   precision = *C->I++;
-   switch (precision) {
-   case PRECISION_LOW:
-   case PRECISION_MEDIUM:
-   case PRECISION_HIGH:
-      /* OK */
-      break;
-   default:
-      _mesa_problem(NULL, "unexpected precision %d at %s:%d\n",
-                    precision, __FILE__, __LINE__);
-      RETURN0;
-   }
-
-   type = *C->I++;
-   switch (type) {
-   case TYPE_SPECIFIER_FLOAT:
-   case TYPE_SPECIFIER_INT:
-   case TYPE_SPECIFIER_SAMPLER1D:
-   case TYPE_SPECIFIER_SAMPLER2D:
-   case TYPE_SPECIFIER_SAMPLER3D:
-   case TYPE_SPECIFIER_SAMPLERCUBE:
-   case TYPE_SPECIFIER_SAMPLER1DSHADOW:
-   case TYPE_SPECIFIER_SAMPLER2DSHADOW:
-   case TYPE_SPECIFIER_SAMPLER2DRECT:
-   case TYPE_SPECIFIER_SAMPLER2DRECTSHADOW:
-   case TYPE_SPECIFIER_SAMPLER_1D_ARRAY:
-   case TYPE_SPECIFIER_SAMPLER_2D_ARRAY:
-   case TYPE_SPECIFIER_SAMPLER_1D_ARRAY_SHADOW:
-   case TYPE_SPECIFIER_SAMPLER_2D_ARRAY_SHADOW:
-      /* OK */
-      break;
-   default:
-      _mesa_problem(NULL, "unexpected type %d at %s:%d\n",
-                    type, __FILE__, __LINE__);
-      RETURN0;
-   }
-
-   assert(type < TYPE_SPECIFIER_COUNT);
-   O->default_precision[type] = precision;
-
-   return 1;
-}
-
-
-/**
- * Initialize the default precision for all types.
- * XXX this info isn't used yet.
- */
-static void
-init_default_precision(slang_output_ctx *O, slang_unit_type type)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   GLuint i;
-   for (i = 0; i < TYPE_SPECIFIER_COUNT; i++) {
-#if FEATURE_es2_glsl
-      if (ctx->API == API_OPENGLES2)
-        O->default_precision[i] = PRECISION_LOW;
-      else
-        O->default_precision[i] = PRECISION_HIGH;
-#else
-      (void) ctx;
-      O->default_precision[i] = PRECISION_HIGH;
-#endif
-   }
-
-   if (type == SLANG_UNIT_VERTEX_SHADER || type == SLANG_UNIT_GEOMETRY_SHADER) {
-      O->default_precision[TYPE_SPECIFIER_FLOAT] = PRECISION_HIGH;
-      O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_HIGH;
-   }
-   else {
-      O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_MEDIUM;
-   }
-}
-
-
-static int
-parse_invariant(slang_parse_ctx * C, slang_output_ctx * O)
-{
-   if (O->allow_invariant) {
-      slang_atom *a = parse_identifier(C);
-      /* XXX not doing anything with this var yet */
-      /*printf("ID: %s\n", (char*) a);*/
-      return a ? 1 : 0;
-   }
-   else {
-      slang_info_log_error(C->L, "syntax error at \"invariant\"");
-      RETURN0;
-   }
-}
-      
-
-/* external declaration or default precision specifier */
-#define EXTERNAL_NULL 0
-#define EXTERNAL_FUNCTION_DEFINITION 1
-#define EXTERNAL_DECLARATION 2
-#define DEFAULT_PRECISION 3
-#define INVARIANT_STMT 4
-
-
-static GLboolean
-parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
-                struct gl_shader *shader)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   slang_output_ctx o;
-   GLboolean success;
-   GLuint maxRegs;
-   slang_function *mainFunc = NULL;
-
-   if (unit->type == SLANG_UNIT_FRAGMENT_BUILTIN ||
-       unit->type == SLANG_UNIT_FRAGMENT_SHADER) {
-      maxRegs = ctx->Const.FragmentProgram.MaxTemps;
-   }
-   else if (unit->type == SLANG_UNIT_VERTEX_BUILTIN ||
-            unit->type == SLANG_UNIT_VERTEX_SHADER) {
-      maxRegs = ctx->Const.VertexProgram.MaxTemps;
-   } else {
-      assert(unit->type == SLANG_UNIT_GEOMETRY_BUILTIN ||
-             unit->type == SLANG_UNIT_GEOMETRY_SHADER);
-      maxRegs = ctx->Const.GeometryProgram.MaxTemps;
-   }
-
-   /* setup output context */
-   o.funs = &unit->funs;
-   o.structs = &unit->structs;
-   o.vars = &unit->vars;
-   o.program = shader ? shader->Program : NULL;
-   o.pragmas = shader ? &shader->Pragmas : NULL;
-   o.vartable = _slang_new_var_table(maxRegs);
-   _slang_push_var_table(o.vartable);
-
-   /* allow 'invariant' keyword? */
-#if FEATURE_es2_glsl
-   o.allow_invariant =
-      (ctx->API == API_OPENGLES2 || C->version >= 120) ? GL_TRUE : GL_FALSE;
-#else
-   o.allow_invariant = (C->version >= 120) ? GL_TRUE : GL_FALSE;
-#endif
-
-   /* allow 'centroid' keyword? */
-   o.allow_centroid = (C->version >= 120) ? GL_TRUE : GL_FALSE;
-
-   /* allow 'lowp/mediump/highp' keywords? */
-#if FEATURE_es2_glsl
-   o.allow_precision =
-      (ctx->API == API_OPENGLES2 || C->version >= 120) ? GL_TRUE : GL_FALSE;
-#else
-   o.allow_precision = (C->version >= 120) ? GL_TRUE : GL_FALSE;
-#endif
-   init_default_precision(&o, unit->type);
-
-   /* allow 'float[]' keyword? */
-   o.allow_array_types = (C->version >= 120) ? GL_TRUE : GL_FALSE;
-
-   /* parse individual functions and declarations */
-   while (*C->I != EXTERNAL_NULL) {
-      switch (*C->I++) {
-      case EXTERNAL_FUNCTION_DEFINITION:
-         {
-            slang_function *func;
-            success = parse_function(C, &o, 1, &func);
-            if (success && strcmp((char *) func->header.a_name, "main") == 0) {
-               /* found main() */
-               mainFunc = func;
-            }
-         }
-         break;
-      case EXTERNAL_DECLARATION:
-         success = parse_declaration(C, &o);
-         break;
-      case DEFAULT_PRECISION:
-         success = parse_default_precision(C, &o);
-         break;
-      case INVARIANT_STMT:
-         success = parse_invariant(C, &o);
-         break;
-      default:
-         success = GL_FALSE;
-      }
-
-      if (!success) {
-         /* xxx free codegen */
-         _slang_pop_var_table(o.vartable);
-         return GL_FALSE;
-      }
-   }
-   C->I++;
-
-   if (mainFunc) {
-      /* assemble (generate code) for main() */
-      slang_assemble_ctx A;
-      memset(&A, 0, sizeof(slang_assemble_ctx));
-      A.atoms = C->atoms;
-      A.space.funcs = o.funs;
-      A.space.structs = o.structs;
-      A.space.vars = o.vars;
-      A.program = o.program;
-      A.pragmas = &shader->Pragmas;
-      A.vartable = o.vartable;
-      A.EmitContReturn = ctx->Shader.EmitContReturn;
-      A.log = C->L;
-      A.allow_uniform_initializers = C->version > 110;
-
-      /* main() takes no parameters */
-      if (mainFunc->param_count > 0) {
-         slang_info_log_error(A.log, "main() takes no arguments");
-         return GL_FALSE;
-      }
-
-      _slang_codegen_function(&A, mainFunc);
-
-      shader->Main = GL_TRUE; /* this shader defines main() */
-
-      shader->UnresolvedRefs = A.UnresolvedRefs;
-   }
-
-   _slang_pop_var_table(o.vartable);
-   _slang_delete_var_table(o.vartable);
-
-   return GL_TRUE;
-}
-
-static GLboolean
-compile_binary(const unsigned char * prod, slang_code_unit * unit,
-               GLuint version,
-               slang_unit_type type, slang_info_log * infolog,
-               slang_code_unit * builtin, slang_code_unit * downlink,
-               struct gl_shader *shader)
-{
-   slang_parse_ctx C;
-
-   unit->type = type;
-
-   /* setup parse context */
-   C.I = prod;
-   C.L = infolog;
-   C.parsing_builtin = (builtin == NULL);
-   C.global_scope = GL_TRUE;
-   C.atoms = &unit->object->atompool;
-   C.type = type;
-   C.version = version;
-
-   if (!check_revision(&C))
-      return GL_FALSE;
-
-   if (downlink != NULL) {
-      unit->vars.outer_scope = &downlink->vars;
-      unit->funs.outer_scope = &downlink->funs;
-      unit->structs.outer_scope = &downlink->structs;
-   }
-
-   /* parse translation unit */
-   return parse_code_unit(&C, unit, shader);
-}
-
-static GLboolean
-compile_with_grammar(const char *source,
-                     slang_code_unit *unit,
-                     slang_unit_type type,
-                     slang_info_log *infolog,
-                     slang_code_unit *builtin,
-                     struct gl_shader *shader,
-                     struct gl_sl_pragmas *pragmas,
-                     unsigned int shader_type,
-                     unsigned int parsing_builtin)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct sl_pp_purify_options options;
-   struct sl_pp_context *context;
-   unsigned char *prod;
-   GLuint size;
-   unsigned int version;
-   unsigned int maxVersion;
-   int result;
-   char errmsg[200] = "";
-
-   assert(shader_type == 1 || shader_type == 2);
-
-   memset(&options, 0, sizeof(options));
-
-   context = sl_pp_context_create(source, &options);
-   if (!context) {
-      slang_info_log_error(infolog, "out of memory");
-      return GL_FALSE;
-   }
-
-   if (sl_pp_version(context, &version)) {
-      slang_info_log_error(infolog, "%s", sl_pp_context_error_message(context));
-      sl_pp_context_destroy(context);
-      return GL_FALSE;
-   }
-
-   if (sl_pp_context_add_extension(context, "GL_ARB_draw_buffers") ||
-       sl_pp_context_add_extension(context, "GL_ARB_texture_rectangle")) {
-      slang_info_log_error(infolog, "%s", sl_pp_context_error_message(context));
-      sl_pp_context_destroy(context);
-      return GL_FALSE;
-   }
-
-   if (type == SLANG_UNIT_FRAGMENT_SHADER) {
-      sl_pp_context_add_extension(context, "GL_ARB_fragment_coord_conventions");
-   }
-
-
-#if FEATURE_es2_glsl
-   if (ctx->API == API_OPENGLES2) {
-      if (sl_pp_context_add_predefined(context, "GL_ES", "1") ||
-         sl_pp_context_add_predefined(context, "GL_FRAGMENT_PRECISION_HIGH", "1")) {
-        slang_info_log_error(infolog, "%s", sl_pp_context_error_message(context));
-        sl_pp_context_destroy(context);
-        return GL_FALSE;
-      }
-   }
-#else
-   (void) ctx;
-#endif
-
-#if FEATURE_ARB_shading_language_120
-   maxVersion = 120;
-#elif FEATURE_es2_glsl
-   maxVersion = 100;
-#else
-   maxVersion = 110;
-#endif
-
-   if (version > maxVersion ||
-       (version != 100 && version != 110 && version != 120)) {
-      slang_info_log_error(infolog,
-                           "language version %.2f is not supported.",
-                           version * 0.01);
-      sl_pp_context_destroy(context);
-      return GL_FALSE;
-   }
-
-   /* Finally check the syntax and generate its binary representation. */
-   result = sl_cl_compile(context,
-                          shader_type,
-                          parsing_builtin,
-                          &prod,
-                          &size,
-                          errmsg,
-                          sizeof(errmsg));
-
-   sl_pp_context_destroy(context);
-
-   if (result) {
-      /*GLint pos;*/
-
-      slang_info_log_error(infolog, errmsg);
-      /* syntax error (possibly in library code) */
-#if 0
-      {
-         int line, col;
-         char *s;
-         s = (char *) _mesa_find_line_column((const GLubyte *) source,
-                                             (const GLubyte *) source + pos,
-                                             &line, &col);
-         printf("Error on line %d, col %d: %s\n", line, col, s);
-      }
-#endif
-      return GL_FALSE;
-   }
-
-   /* Syntax is okay - translate it to internal representation. */
-   if (!compile_binary(prod, unit, version, type, infolog, builtin,
-                       &builtin[SLANG_BUILTIN_TOTAL - 1],
-                       shader)) {
-      free(prod);
-      return GL_FALSE;
-   }
-   free(prod);
-   return GL_TRUE;
-}
-
-static const unsigned char slang_core_gc[] = {
-#include "library/slang_core_gc.h"
-};
-
-static const unsigned char slang_120_core_gc[] = {
-#include "library/slang_120_core_gc.h"
-};
-
-static const unsigned char slang_120_fragment_gc[] = {
-#include "library/slang_builtin_120_fragment_gc.h"
-};
-
-static const unsigned char slang_common_builtin_gc[] = {
-#include "library/slang_common_builtin_gc.h"
-};
-
-static const unsigned char slang_fragment_builtin_gc[] = {
-#include "library/slang_fragment_builtin_gc.h"
-};
-
-static const unsigned char slang_vertex_builtin_gc[] = {
-#include "library/slang_vertex_builtin_gc.h"
-};
-
-static const unsigned char slang_geometry_builtin_gc[] = {
-#include "library/slang_geometry_builtin_gc.h"
-};
-
-static GLboolean
-compile_object(const char *source,
-               slang_code_object *object,
-               slang_unit_type type,
-               slang_info_log *infolog,
-               struct gl_shader *shader,
-               struct gl_sl_pragmas *pragmas)
-{
-   slang_code_unit *builtins = NULL;
-   GLuint base_version = 110;
-   unsigned int shader_type;
-   unsigned int parsing_builtin;
-
-   /* set shader type - the syntax is slightly different for different shaders */
-   if (type == SLANG_UNIT_FRAGMENT_SHADER || type == SLANG_UNIT_FRAGMENT_BUILTIN) {
-      shader_type = 1;
-   } else {
-      shader_type = 2;
-   }
-
-   /* enable language extensions */
-   parsing_builtin = 1;
-
-   /* if parsing user-specified shader, load built-in library */
-   if (type == SLANG_UNIT_FRAGMENT_SHADER || type == SLANG_UNIT_VERTEX_SHADER ||
-       type == SLANG_UNIT_GEOMETRY_SHADER) {
-      /* compile core functionality first */
-      if (!compile_binary(slang_core_gc,
-                          &object->builtin[SLANG_BUILTIN_CORE],
-                          base_version,
-                          SLANG_UNIT_FRAGMENT_BUILTIN, infolog,
-                          NULL, NULL, NULL))
-         return GL_FALSE;
-
-#if FEATURE_ARB_shading_language_120
-      if (!compile_binary(slang_120_core_gc,
-                          &object->builtin[SLANG_BUILTIN_120_CORE],
-                          120,
-                          SLANG_UNIT_FRAGMENT_BUILTIN, infolog,
-                          NULL, &object->builtin[SLANG_BUILTIN_CORE], NULL))
-         return GL_FALSE;
-#endif
-
-      /* compile common functions and variables, link to core */
-      if (!compile_binary(slang_common_builtin_gc,
-                          &object->builtin[SLANG_BUILTIN_COMMON],
-#if FEATURE_ARB_shading_language_120
-                          120,
-#else
-                          base_version,
-#endif
-                          SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
-#if FEATURE_ARB_shading_language_120
-                          &object->builtin[SLANG_BUILTIN_120_CORE],
-#else
-                          &object->builtin[SLANG_BUILTIN_CORE],
-#endif
-                          NULL))
-         return GL_FALSE;
-
-      /* compile target-specific functions and variables, link to common */
-      if (type == SLANG_UNIT_FRAGMENT_SHADER) {
-         if (!compile_binary(slang_fragment_builtin_gc,
-                             &object->builtin[SLANG_BUILTIN_TARGET],
-                             base_version,
-                             SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
-                             &object->builtin[SLANG_BUILTIN_COMMON], NULL))
-            return GL_FALSE;
-#if FEATURE_ARB_shading_language_120
-         if (!compile_binary(slang_120_fragment_gc,
-                             &object->builtin[SLANG_BUILTIN_TARGET],
-                             120,
-                             SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
-                             &object->builtin[SLANG_BUILTIN_COMMON], NULL))
-            return GL_FALSE;
-#endif
-      }
-      else if (type == SLANG_UNIT_VERTEX_SHADER) {
-         if (!compile_binary(slang_vertex_builtin_gc,
-                             &object->builtin[SLANG_BUILTIN_TARGET],
-                             base_version,
-                             SLANG_UNIT_VERTEX_BUILTIN, infolog, NULL,
-                             &object->builtin[SLANG_BUILTIN_COMMON], NULL))
-            return GL_FALSE;
-      }
-#if FEATURE_ARB_geometry_shader4
-      else if (type == SLANG_UNIT_GEOMETRY_SHADER) {
-         if (!compile_binary(slang_geometry_builtin_gc,
-                             &object->builtin[SLANG_BUILTIN_TARGET],
-                             base_version,
-                             SLANG_UNIT_GEOMETRY_BUILTIN, infolog, NULL,
-                             &object->builtin[SLANG_BUILTIN_COMMON], NULL))
-            return GL_FALSE;
-      }
-#endif
-
-      /* disable language extensions */
-      parsing_builtin = 0;
-
-      builtins = object->builtin;
-   }
-
-   /* compile the actual shader - pass-in built-in library for external shader */
-   return compile_with_grammar(source,
-                               &object->unit,
-                               type,
-                               infolog,
-                               builtins,
-                               shader,
-                               pragmas,
-                               shader_type,
-                               parsing_builtin);
-}
-
-
-GLboolean
-_slang_compile(GLcontext *ctx, struct gl_shader *shader)
-{
-   GLboolean success;
-   slang_info_log info_log;
-   slang_code_object obj;
-   slang_unit_type type;
-   GLenum progTarget;
-
-   if (shader->Type == GL_VERTEX_SHADER) {
-      type = SLANG_UNIT_VERTEX_SHADER;
-   }
-   else if (shader->Type == GL_FRAGMENT_SHADER) {
-      type = SLANG_UNIT_FRAGMENT_SHADER;
-   } else {
-      assert(shader->Type == GL_GEOMETRY_SHADER_ARB);
-      type = SLANG_UNIT_GEOMETRY_SHADER;
-   }
-
-   if (!shader->Source)
-      return GL_FALSE;
-
-   ctx->Shader.MemPool = _slang_new_mempool(1024*1024);
-
-   shader->Main = GL_FALSE;
-
-   /* free the shader's old instructions, etc */
-   _mesa_reference_program(ctx, &shader->Program, NULL);
-
-   /* allocate new GPU program, parameter lists, etc. */
-   if (shader->Type == GL_VERTEX_SHADER)
-      progTarget = GL_VERTEX_PROGRAM_ARB;
-   else if (shader->Type == GL_FRAGMENT_SHADER)
-      progTarget = GL_FRAGMENT_PROGRAM_ARB;
-   else
-      progTarget = MESA_GEOMETRY_PROGRAM;
-   shader->Program = ctx->Driver.NewProgram(ctx, progTarget, 1);
-   shader->Program->Parameters = _mesa_new_parameter_list();
-   shader->Program->Varying = _mesa_new_parameter_list();
-   shader->Program->Attributes = _mesa_new_parameter_list();
-
-   slang_info_log_construct(&info_log);
-   _slang_code_object_ctr(&obj);
-
-   success = compile_object(shader->Source,
-                            &obj,
-                            type,
-                            &info_log,
-                            shader,
-                            &shader->Pragmas);
-
-   /* free shader's prev info log */
-   if (shader->InfoLog) {
-      free(shader->InfoLog);
-      shader->InfoLog = NULL;
-   }
-
-   if (info_log.text) {
-      /* copy info-log string to shader object */
-      shader->InfoLog = _mesa_strdup(info_log.text);
-   }
-
-   if (info_log.error_flag) {
-      success = GL_FALSE;
-   }
-
-   slang_info_log_destruct(&info_log);
-   _slang_code_object_dtr(&obj);
-
-   _slang_delete_mempool((slang_mempool *) ctx->Shader.MemPool);
-   ctx->Shader.MemPool = NULL;
-
-   /* remove any reads of output registers */
-#if 0
-   printf("Pre-remove output reads:\n");
-   _mesa_print_program(shader->Program);
-#endif
-   _mesa_remove_output_reads(shader->Program, PROGRAM_OUTPUT);
-   if (shader->Type == GL_VERTEX_SHADER) {
-      /* and remove writes to varying vars in vertex programs */
-      _mesa_remove_output_reads(shader->Program, PROGRAM_VARYING);
-   }
-#if 0
-   printf("Post-remove output reads:\n");
-   _mesa_print_program(shader->Program);
-#endif
-
-   shader->CompileStatus = success;
-
-   if (success) {
-      if (shader->Pragmas.Optimize &&
-          (ctx->Shader.Flags & GLSL_NO_OPT) == 0) {
-         _mesa_optimize_program(ctx, shader->Program);
-      }
-      if ((ctx->Shader.Flags & GLSL_NOP_VERT) &&
-          shader->Program->Target == GL_VERTEX_PROGRAM_ARB) {
-         _mesa_nop_vertex_program(ctx,
-                                  (struct gl_vertex_program *) shader->Program);
-      }
-      if ((ctx->Shader.Flags & GLSL_NOP_FRAG) &&
-          shader->Program->Target == GL_FRAGMENT_PROGRAM_ARB) {
-         _mesa_nop_fragment_program(ctx,
-                                (struct gl_fragment_program *) shader->Program);
-      }
-   }
-
-   if (ctx->Shader.Flags & GLSL_LOG) {
-      _mesa_write_shader_to_file(shader);
-   }
-
-   return success;
-}
-
diff --git a/src/mesa/slang/slang_compile.h b/src/mesa/slang/slang_compile.h
deleted file mode 100644 (file)
index 6061f87..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2005-2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#if !defined SLANG_COMPILE_H
-#define SLANG_COMPILE_H
-
-#include "main/glheader.h"
-#include "main/mtypes.h"
-#include "slang_compile_function.h"
-#include "slang_compile_struct.h"
-#include "slang_compile_variable.h"
-#include "slang_utility.h"
-
-struct slang_code_object_;
-
-#if defined __cplusplus
-extern "C" {
-#endif
-
-typedef struct slang_name_space_
-{
-   struct slang_function_scope_ *funcs;
-   struct slang_struct_scope_ *structs;
-   struct slang_variable_scope_ *vars;
-} slang_name_space;
-
-typedef enum slang_unit_type_
-{
-   SLANG_UNIT_FRAGMENT_SHADER,
-   SLANG_UNIT_VERTEX_SHADER,
-   SLANG_UNIT_GEOMETRY_SHADER,
-   SLANG_UNIT_FRAGMENT_BUILTIN,
-   SLANG_UNIT_VERTEX_BUILTIN,
-   SLANG_UNIT_GEOMETRY_BUILTIN
-} slang_unit_type;
-
-
-typedef struct slang_code_unit_
-{
-   slang_variable_scope vars;
-   slang_function_scope funs;
-   slang_struct_scope structs;
-   slang_unit_type type;
-   struct slang_code_object_ *object;
-} slang_code_unit;
-
-
-extern GLvoid
-_slang_code_unit_ctr (slang_code_unit *, struct slang_code_object_ *);
-
-extern GLvoid
-_slang_code_unit_dtr (slang_code_unit *);
-
-#define SLANG_BUILTIN_CORE   0
-#define SLANG_BUILTIN_120_CORE   1
-#define SLANG_BUILTIN_COMMON 2
-#define SLANG_BUILTIN_TARGET 3
-
-#define SLANG_BUILTIN_TOTAL  4
-
-typedef struct slang_code_object_
-{
-   slang_code_unit builtin[SLANG_BUILTIN_TOTAL];
-   slang_code_unit unit;
-   slang_atom_pool atompool;
-} slang_code_object;
-
-extern GLvoid
-_slang_code_object_ctr (slang_code_object *);
-
-extern GLvoid
-_slang_code_object_dtr (slang_code_object *);
-
-extern GLboolean
-_slang_compile (GLcontext *ctx, struct gl_shader *shader);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff --git a/src/mesa/slang/slang_compile_function.c b/src/mesa/slang/slang_compile_function.c
deleted file mode 100644 (file)
index 4dd8851..0000000
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2005-2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_compile_function.c
- * slang front-end compiler
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_compile.h"
-#include "slang_mem.h"
-
-
-int
-slang_function_construct(slang_function * func)
-{
-   func->kind = SLANG_FUNC_ORDINARY;
-   if (!slang_variable_construct(&func->header))
-      return 0;
-
-   func->parameters = (slang_variable_scope *)
-      _slang_alloc(sizeof(slang_variable_scope));
-   if (func->parameters == NULL) {
-      slang_variable_destruct(&func->header);
-      return 0;
-   }
-
-   _slang_variable_scope_ctr(func->parameters);
-   func->param_count = 0;
-   func->body = NULL;
-   return 1;
-}
-
-void
-slang_function_destruct(slang_function * func)
-{
-   slang_variable_destruct(&func->header);
-   slang_variable_scope_destruct(func->parameters);
-   _slang_free(func->parameters);
-   if (func->body != NULL) {
-      slang_operation_destruct(func->body);
-      _slang_free(func->body);
-   }
-}
-
-
-slang_function *
-slang_function_new(slang_function_kind kind)
-{
-   slang_function *fun = (slang_function *)
-      _slang_alloc(sizeof(slang_function));
-   if (fun) {
-      slang_function_construct(fun);
-      fun->kind = kind;
-   }
-   return fun;
-}
-
-
-/*
- * slang_function_scope
- */
-
-GLvoid
-_slang_function_scope_ctr(slang_function_scope * self)
-{
-   self->functions = NULL;
-   self->num_functions = 0;
-   self->outer_scope = NULL;
-}
-
-void
-slang_function_scope_destruct(slang_function_scope * scope)
-{
-   unsigned int i;
-
-   for (i = 0; i < scope->num_functions; i++)
-      slang_function_destruct(scope->functions + i);
-   _slang_free(scope->functions);
-}
-
-
-/**
- * Does this function have a non-void return value?
- */
-GLboolean
-_slang_function_has_return_value(const slang_function *fun)
-{
-   return fun->header.type.specifier.type != SLANG_SPEC_VOID;
-}
-
-
-/**
- * Search a list of functions for a particular function by name.
- * \param funcs  the list of functions to search
- * \param a_name  the name to search for
- * \param all_scopes  if non-zero, search containing scopes too.
- * \return pointer to found function, or NULL.
- */
-int
-slang_function_scope_find_by_name(slang_function_scope * funcs,
-                                  slang_atom a_name, int all_scopes)
-{
-   unsigned int i;
-
-   for (i = 0; i < funcs->num_functions; i++)
-      if (a_name == funcs->functions[i].header.a_name)
-         return 1;
-   if (all_scopes && funcs->outer_scope != NULL)
-      return slang_function_scope_find_by_name(funcs->outer_scope, a_name, 1);
-   return 0;
-}
-
-
-/**
- * Search a list of functions for a particular function (for implementing
- * function calls.  Matching is done by first comparing the function's name,
- * then the function's parameter list.
- *
- * \param funcs  the list of functions to search
- * \param fun  the function to search for
- * \param all_scopes  if non-zero, search containing scopes too.
- * \return pointer to found function, or NULL.
- */
-slang_function *
-slang_function_scope_find(slang_function_scope * funcs, slang_function * fun,
-                          int all_scopes)
-{
-   unsigned int i;
-
-   for (i = 0; i < funcs->num_functions; i++) {
-      slang_function *f = &funcs->functions[i];
-      const GLuint haveRetValue = 0;
-#if 0
-         = (f->header.type.specifier.type != SLANG_SPEC_VOID);
-#endif
-      unsigned int j;
-
-      /*
-      printf("Compare name %s to %s  (ret %u, %d, %d)\n",
-             (char *) fun->header.a_name, (char *) f->header.a_name,
-             haveRetValue,
-             fun->param_count, f->param_count);
-      */
-
-      if (fun->header.a_name != f->header.a_name)
-         continue;
-      if (fun->param_count != f->param_count)
-         continue;
-      for (j = haveRetValue; j < fun->param_count; j++) {
-         if (!slang_type_specifier_equal
-             (&fun->parameters->variables[j]->type.specifier,
-              &f->parameters->variables[j]->type.specifier))
-            break;
-      }
-      if (j == fun->param_count) {
-         /*
-         printf("Found match\n");
-         */
-         return f;
-      }
-   }
-   /*
-   printf("Not found\n");
-   */
-   if (all_scopes && funcs->outer_scope != NULL)
-      return slang_function_scope_find(funcs->outer_scope, fun, 1);
-   return NULL;
-}
-
-
-/**
- * Lookup a function according to name and parameter count/types.
- */
-slang_function *
-_slang_function_locate(const slang_function_scope * funcs, slang_atom a_name,
-                       slang_operation * args, GLuint num_args,
-                       const slang_name_space * space, slang_atom_pool * atoms,
-                       slang_info_log *log, GLboolean *error)
-{
-   slang_typeinfo arg_ti[100];
-   GLuint i;
-
-   *error = GL_FALSE;
-
-   /* determine type of each argument */
-   assert(num_args < 100);
-   for (i = 0; i < num_args; i++) {
-      if (!slang_typeinfo_construct(&arg_ti[i]))
-         return NULL;
-      if (!_slang_typeof_operation(&args[i], space, &arg_ti[i], atoms, log)) {
-         return NULL;
-      }
-   }
-
-   /* loop over function scopes */
-   while (funcs) {
-
-      /* look for function with matching name and argument/param types */
-      for (i = 0; i < funcs->num_functions; i++) {
-         slang_function *f = &funcs->functions[i];
-         const GLuint haveRetValue = _slang_function_has_return_value(f);
-         GLuint j;
-
-         if (a_name != f->header.a_name)
-            continue;
-         if (f->param_count - haveRetValue != num_args)
-            continue;
-
-         /* compare parameter / argument types */
-         for (j = 0; j < num_args; j++) {
-            if (!slang_type_specifier_compatible(&arg_ti[j].spec,
-                              &f->parameters->variables[j]->type.specifier)) {
-               /* param/arg types don't match */
-               break;
-            }
-
-            /* "out" and "inout" formal parameter requires the actual
-             * argument to be an l-value.
-             */
-            if (!arg_ti[j].can_be_referenced &&
-                (f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT ||
-                 f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT)) {
-               /* param is not an lvalue! */
-               *error = GL_TRUE;
-               return NULL;
-            }
-         }
-
-         if (j == num_args) {
-            /* name and args match! */
-            return f;
-         }
-      }
-
-      funcs = funcs->outer_scope;
-   }
-
-   return NULL;
-}
diff --git a/src/mesa/slang/slang_compile_function.h b/src/mesa/slang/slang_compile_function.h
deleted file mode 100644 (file)
index 0eced3c..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.2
- *
- * Copyright (C) 2005-2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_COMPILE_FUNCTION_H
-#define SLANG_COMPILE_FUNCTION_H
-
-#include "main/glheader.h"
-#include "slang_compile_operation.h"
-#include "slang_compile_variable.h"
-#include "slang_log.h"
-#include "slang_utility.h"
-
-struct slang_name_space_;
-struct slang_operation_;
-
-/**
- * Types of functions.
- */
-typedef enum slang_function_kind_
-{
-   SLANG_FUNC_ORDINARY,
-   SLANG_FUNC_CONSTRUCTOR,
-   SLANG_FUNC_OPERATOR
-} slang_function_kind;
-
-
-/**
- * Description of a compiled shader function.
- */
-typedef struct slang_function_
-{
-   slang_function_kind kind;
-   slang_variable header;      /**< The function's name and return type */
-   slang_variable_scope *parameters; /**< formal parameters AND local vars */
-   unsigned int param_count;   /**< number of formal params (no locals) */
-   slang_operation *body;      /**< The instruction tree */
-} slang_function;
-
-extern int slang_function_construct(slang_function *);
-extern void slang_function_destruct(slang_function *);
-extern slang_function *slang_function_new(slang_function_kind kind);
-
-extern GLboolean
-_slang_function_has_return_value(const slang_function *fun);
-
-
-/**
- * Basically, a list of compiled functions.
- */
-typedef struct slang_function_scope_
-{
-   slang_function *functions;
-   GLuint num_functions;
-   struct slang_function_scope_ *outer_scope;
-} slang_function_scope;
-
-
-extern GLvoid
-_slang_function_scope_ctr(slang_function_scope *);
-
-extern void
-slang_function_scope_destruct(slang_function_scope *);
-
-extern int
-slang_function_scope_find_by_name(slang_function_scope *, slang_atom, int);
-
-extern slang_function *
-slang_function_scope_find(slang_function_scope *, slang_function *, int);
-
-extern struct slang_function_ *
-_slang_function_locate(const struct slang_function_scope_ *funcs,
-                       slang_atom name, struct slang_operation_ *params,
-                       GLuint num_params,
-                       const struct slang_name_space_ *space,
-                       slang_atom_pool *atoms, slang_info_log *log,
-                       GLboolean *error);
-
-
-#endif /* SLANG_COMPILE_FUNCTION_H */
diff --git a/src/mesa/slang/slang_compile_operation.c b/src/mesa/slang/slang_compile_operation.c
deleted file mode 100644 (file)
index 5441d60..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.2
- *
- * Copyright (C) 2005-2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_compile_operation.c
- * slang front-end compiler
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_compile.h"
-#include "slang_mem.h"
-
-
-/**
- * Init a slang_operation object
- */
-GLboolean
-slang_operation_construct(slang_operation * oper)
-{
-   oper->type = SLANG_OPER_NONE;
-   oper->children = NULL;
-   oper->num_children = 0;
-   oper->literal[0] = 0.0;
-   oper->literal_size = 1;
-   oper->array_constructor = GL_FALSE;
-   oper->a_id = SLANG_ATOM_NULL;
-   oper->a_obj = SLANG_ATOM_NULL;
-   oper->locals = _slang_variable_scope_new(NULL);
-   if (oper->locals == NULL)
-      return GL_FALSE;
-   _slang_variable_scope_ctr(oper->locals);
-   oper->fun = NULL;
-   oper->var = NULL;
-   oper->label = NULL;
-   return GL_TRUE;
-}
-
-void
-slang_operation_destruct(slang_operation * oper)
-{
-   GLuint i;
-
-   for (i = 0; i < oper->num_children; i++)
-      slang_operation_destruct(oper->children + i);
-   _slang_free(oper->children);
-   slang_variable_scope_destruct(oper->locals);
-   _slang_free(oper->locals);
-   oper->children = NULL;
-   oper->num_children = 0;
-   oper->locals = NULL;
-}
-
-
-/**
- * Recursively traverse 'oper', replacing occurances of 'oldScope' with
- * 'newScope' in the oper->locals->outer_scope field.
- */
-void
-slang_replace_scope(slang_operation *oper,
-                    slang_variable_scope *oldScope,
-                    slang_variable_scope *newScope)
-{
-   GLuint i;
-
-   if (oper->locals != newScope &&
-       oper->locals->outer_scope == oldScope) {
-      /* found.  replace old w/ new */
-      oper->locals->outer_scope = newScope;
-   }
-
-   if (oper->type == SLANG_OPER_VARIABLE_DECL) {
-      /* search/replace in the initializer */
-      slang_variable *var;
-      var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
-      if (var && var->initializer) {
-         slang_replace_scope(var->initializer, oldScope, newScope);
-      }
-   }
-
-   /* search/replace in children */
-   for (i = 0; i < oper->num_children; i++) {
-      slang_replace_scope(&oper->children[i], oldScope, newScope);
-   }
-}
-
-
-/**
- * Recursively copy a slang_operation node.
- * \param x  copy target
- * \param y  copy source
- * \return GL_TRUE for success, GL_FALSE if failure
- */
-GLboolean
-slang_operation_copy(slang_operation * x, const slang_operation * y)
-{
-   slang_operation z;
-   GLuint i;
-
-   if (!slang_operation_construct(&z))
-      return GL_FALSE;
-   z.type = y->type;
-   if (y->num_children > 0) {
-      z.children = (slang_operation *)
-         _slang_alloc(y->num_children * sizeof(slang_operation));
-      if (z.children == NULL) {
-         slang_operation_destruct(&z);
-         return GL_FALSE;
-      }
-   }
-   for (z.num_children = 0; z.num_children < y->num_children;
-        z.num_children++) {
-      if (!slang_operation_construct(&z.children[z.num_children])) {
-         slang_operation_destruct(&z);
-         return GL_FALSE;
-      }
-   }
-   for (i = 0; i < z.num_children; i++) {
-      if (!slang_operation_copy(&z.children[i], &y->children[i])) {
-         slang_operation_destruct(&z);
-         return GL_FALSE;
-      }
-   }
-   z.literal[0] = y->literal[0];
-   z.literal[1] = y->literal[1];
-   z.literal[2] = y->literal[2];
-   z.literal[3] = y->literal[3];
-   z.literal_size = y->literal_size;
-   assert(y->literal_size >= 1);
-   assert(y->literal_size <= 4);
-   z.a_id = y->a_id;
-   if (y->locals) {
-      if (!slang_variable_scope_copy(z.locals, y->locals)) {
-         slang_operation_destruct(&z);
-         return GL_FALSE;
-      }
-   }
-
-   /* update scoping for children */
-   for (i = 0; i < y->num_children; i++) {
-      if (y->children[i].locals &&
-          y->children[i].locals->outer_scope == y->locals) {
-         z.children[i].locals->outer_scope = z.locals;
-      }
-   }
-
-#if 0
-   z.var = y->var;
-   z.fun = y->fun;
-#endif
-   slang_operation_destruct(x);
-   *x = z;
-
-   /* If this operation declares a new scope, we need to make sure
-    * all children point to it, not the original operation's scope!
-    */
-   if (x->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
-       x->type == SLANG_OPER_WHILE ||
-       x->type == SLANG_OPER_FOR) {
-      slang_replace_scope(x, y->locals, x->locals);
-   }
-
-   return GL_TRUE;
-}
-
-
-slang_operation *
-slang_operation_new(GLuint count)
-{
-   slang_operation *ops
-       = (slang_operation *) _slang_alloc(count * sizeof(slang_operation));
-   assert(count > 0);
-   if (ops) {
-      GLuint i;
-      for (i = 0; i < count; i++)
-         slang_operation_construct(ops + i);
-   }
-   return ops;
-}
-
-
-/**
- * Delete operation and all children
- */
-void
-slang_operation_delete(slang_operation *oper)
-{
-   slang_operation_destruct(oper);
-   _slang_free(oper);
-}
-
-
-void
-slang_operation_free_children(slang_operation *oper)
-{
-   GLuint i;
-   for (i = 0; i < slang_oper_num_children(oper); i++) {
-      slang_operation *child = slang_oper_child(oper, i);
-      slang_operation_destruct(child);
-   }
-   _slang_free(oper->children);
-   oper->children = NULL;
-   oper->num_children = 0;
-}
-
-
-slang_operation *
-slang_operation_grow(GLuint *numChildren, slang_operation **children)
-{
-   slang_operation *ops;
-
-   ops = (slang_operation *)
-      _slang_realloc(*children,
-                     *numChildren * sizeof(slang_operation),
-                     (*numChildren + 1) * sizeof(slang_operation));
-   if (ops) {
-      slang_operation *newOp = ops + *numChildren;
-      if (!slang_operation_construct(newOp)) {
-         _slang_free(ops);
-         *children = NULL;
-         return NULL;
-      }
-      *children = ops;
-      (*numChildren)++;
-      return newOp;
-   }
-   return NULL;
-}
-
-/**
- * Insert a new slang_operation into an array.
- * \param numElements  pointer to current array size (in/out)
- * \param array  address of the array (in/out)
- * \param pos  position to insert new element
- * \return  pointer to the new operation/element
- */
-slang_operation *
-slang_operation_insert(GLuint *numElements, slang_operation **array,
-                       GLuint pos)
-{
-   slang_operation *ops;
-
-   assert(pos <= *numElements);
-
-   ops = (slang_operation *)
-      _slang_alloc((*numElements + 1) * sizeof(slang_operation));
-   if (ops) {
-      slang_operation *newOp;
-      newOp = ops + pos;
-      if (pos > 0)
-         memcpy(ops, *array, pos * sizeof(slang_operation));
-      if (pos < *numElements)
-         memcpy(newOp + 1, (*array) + pos,
-                (*numElements - pos) * sizeof(slang_operation));
-
-      if (!slang_operation_construct(newOp)) {
-         _slang_free(ops);
-         *numElements = 0;
-         *array = NULL;
-         return NULL;
-      }
-      if (*array)
-         _slang_free(*array);
-      *array = ops;
-      (*numElements)++;
-      return newOp;
-   }
-   return NULL;
-}
-
-
-/**
- * Add/insert new child into given node at given position.
- * \return pointer to the new child node
- */
-slang_operation *
-slang_operation_insert_child(slang_operation *oper, GLuint pos)
-{
-   slang_operation *newOp;
-
-   newOp = slang_operation_insert(&oper->num_children,
-                                  &oper->children,
-                                  pos);
-   if (newOp) {
-      newOp->locals->outer_scope = oper->locals;
-   }
-
-   return newOp;
-}
-
-
-void
-_slang_operation_swap(slang_operation *oper0, slang_operation *oper1)
-{
-   slang_operation tmp = *oper0;
-   *oper0 = *oper1;
-   *oper1 = tmp;
-}
-
-
-void
-slang_operation_add_children(slang_operation *oper, GLuint num_children)
-{
-   GLuint i;
-   assert(oper->num_children == 0);
-   assert(oper->children == NULL);
-   oper->num_children = num_children;
-   oper->children = slang_operation_new(num_children);
-   for (i = 0; i < num_children; i++) {
-      oper->children[i].locals = _slang_variable_scope_new(oper->locals);
-   }
-}
-
diff --git a/src/mesa/slang/slang_compile_operation.h b/src/mesa/slang/slang_compile_operation.h
deleted file mode 100644 (file)
index b8c5f21..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.2
- *
- * Copyright (C) 2005-2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_COMPILE_OPERATION_H
-#define SLANG_COMPILE_OPERATION_H
-
-
-#include "main/glheader.h"
-#include "slang_compile_variable.h"
-#include "slang_utility.h"
-
-/**
- * Types of slang operations.
- * These are the types of the AST (abstract syntax tree) nodes.
- * [foo] indicates a sub-tree or reference to another type of node
- */
-typedef enum slang_operation_type_
-{
-   SLANG_OPER_NONE,
-   SLANG_OPER_BLOCK_NO_NEW_SCOPE,       /* "{" sequence "}" */
-   SLANG_OPER_BLOCK_NEW_SCOPE,  /* "{" sequence "}" */
-   SLANG_OPER_VARIABLE_DECL,    /* [type] [var] or [var] = [expr] */
-   SLANG_OPER_ASM,
-   SLANG_OPER_BREAK,            /* "break" statement */
-   SLANG_OPER_CONTINUE,         /* "continue" statement */
-   SLANG_OPER_DISCARD,          /* "discard" (kill fragment) statement */
-   SLANG_OPER_RETURN,           /* "return" [expr]  */
-   SLANG_OPER_RETURN_INLINED,   /* "return" [expr] from inlined function  */
-   SLANG_OPER_LABEL,            /* a jump target */
-   SLANG_OPER_EXPRESSION,       /* [expr] */
-   SLANG_OPER_IF,               /* "if" [0] then [1] else [2] */
-   SLANG_OPER_WHILE,            /* "while" [cond] [body] */
-   SLANG_OPER_DO,               /* "do" [body] "while" [cond] */
-   SLANG_OPER_FOR,              /* "for" [init] [while] [incr] [body] */
-   SLANG_OPER_VOID,             /* nop */
-   SLANG_OPER_LITERAL_BOOL,     /* "true" or "false" */
-   SLANG_OPER_LITERAL_INT,      /* integer literal */
-   SLANG_OPER_LITERAL_FLOAT,    /* float literal */
-   SLANG_OPER_IDENTIFIER,       /* var name, func name, etc */
-   SLANG_OPER_SEQUENCE,         /* [expr] "," [expr] "," etc */
-   SLANG_OPER_ASSIGN,           /* [var] "=" [expr] */
-   SLANG_OPER_ADDASSIGN,        /* [var] "+=" [expr] */
-   SLANG_OPER_SUBASSIGN,        /* [var] "-=" [expr] */
-   SLANG_OPER_MULASSIGN,        /* [var] "*=" [expr] */
-   SLANG_OPER_DIVASSIGN,        /* [var] "/=" [expr] */
-   /*SLANG_OPER_MODASSIGN, */
-   /*SLANG_OPER_LSHASSIGN, */
-   /*SLANG_OPER_RSHASSIGN, */
-   /*SLANG_OPER_ORASSIGN, */
-   /*SLANG_OPER_XORASSIGN, */
-   /*SLANG_OPER_ANDASSIGN, */
-   SLANG_OPER_SELECT,           /* [expr] "?" [expr] ":" [expr] */
-   SLANG_OPER_LOGICALOR,        /* [expr] "||" [expr] */
-   SLANG_OPER_LOGICALXOR,       /* [expr] "^^" [expr] */
-   SLANG_OPER_LOGICALAND,       /* [expr] "&&" [expr] */
-   /*SLANG_OPER_BITOR, */
-   /*SLANG_OPER_BITXOR, */
-   /*SLANG_OPER_BITAND, */
-   SLANG_OPER_EQUAL,            /* [expr] "==" [expr] */
-   SLANG_OPER_NOTEQUAL,         /* [expr] "!=" [expr] */
-   SLANG_OPER_LESS,             /* [expr] "<" [expr] */
-   SLANG_OPER_GREATER,          /* [expr] ">" [expr] */
-   SLANG_OPER_LESSEQUAL,        /* [expr] "<=" [expr] */
-   SLANG_OPER_GREATEREQUAL,     /* [expr] ">=" [expr] */
-   /*SLANG_OPER_LSHIFT, */
-   /*SLANG_OPER_RSHIFT, */
-   SLANG_OPER_ADD,              /* [expr] "+" [expr] */
-   SLANG_OPER_SUBTRACT,         /* [expr] "-" [expr] */
-   SLANG_OPER_MULTIPLY,         /* [expr] "*" [expr] */
-   SLANG_OPER_DIVIDE,           /* [expr] "/" [expr] */
-   /*SLANG_OPER_MODULUS, */
-   SLANG_OPER_PREINCREMENT,     /* "++" [var] */
-   SLANG_OPER_PREDECREMENT,     /* "--" [var] */
-   SLANG_OPER_PLUS,             /* "-" [expr] */
-   SLANG_OPER_MINUS,            /* "+" [expr] */
-   /*SLANG_OPER_COMPLEMENT, */
-   SLANG_OPER_NOT,              /* "!" [expr] */
-   SLANG_OPER_SUBSCRIPT,        /* [expr] "[" [expr] "]" */
-   SLANG_OPER_CALL,             /* [func name] [param] [param] [...] */
-   SLANG_OPER_NON_INLINED_CALL, /* a real function call */
-   SLANG_OPER_METHOD,           /* method call, such as  v.length() */
-   SLANG_OPER_FIELD,            /* i.e.: ".next" or ".xzy" or ".xxx" etc */
-   SLANG_OPER_POSTINCREMENT,    /* [var] "++" */
-   SLANG_OPER_POSTDECREMENT     /* [var] "--" */
-} slang_operation_type;
-
-
-/**
- * A slang_operation is basically a compiled instruction (such as assignment,
- * a while-loop, a conditional, a multiply, a function call, etc).
- * The AST (abstract syntax tree) is built from these nodes.
- * NOTE: This structure could have been implemented as a union of simpler
- * structs which would correspond to the operation types above.
- */
-typedef struct slang_operation_
-{
-   slang_operation_type type;
-   struct slang_operation_ *children;
-   GLuint num_children;
-   GLfloat literal[4];           /**< Used for float, int and bool values */
-   GLuint literal_size;          /**< 1, 2, 3, or 4 */
-   slang_atom a_id;              /**< type: asm, identifier, call, field */
-   slang_atom a_obj;             /**< object in a method call */
-   slang_variable_scope *locals; /**< local vars for scope */
-   struct slang_function_ *fun;  /**< If type == SLANG_OPER_CALL */
-   struct slang_variable_ *var;  /**< If type == slang_oper_identier */
-   struct slang_label_ *label;   /**< If type == SLANG_OPER_LABEL */
-   /** If type==SLANG_OPER_CALL and we're calling an array constructor,
-    * for which there's no real function, we need to have a flag to
-    * indicate such.  num_children indicates number of elements.
-    */
-   GLboolean array_constructor;
-} slang_operation;
-
-
-extern GLboolean
-slang_operation_construct(slang_operation *);
-
-extern void
-slang_operation_destruct(slang_operation *);
-
-extern void
-slang_replace_scope(slang_operation *oper,
-                    slang_variable_scope *oldScope,
-                    slang_variable_scope *newScope);
-
-extern GLboolean
-slang_operation_copy(slang_operation *, const slang_operation *);
-
-extern slang_operation *
-slang_operation_new(GLuint count);
-
-extern void
-slang_operation_delete(slang_operation *oper);
-
-extern void
-slang_operation_free_children(slang_operation *oper);
-
-extern slang_operation *
-slang_operation_grow(GLuint *numChildren, slang_operation **children);
-
-extern slang_operation *
-slang_operation_insert(GLuint *numChildren, slang_operation **children,
-                       GLuint pos);
-
-extern slang_operation *
-slang_operation_insert_child(slang_operation *oper, GLuint pos);
-
-extern void
-_slang_operation_swap(slang_operation *oper0, slang_operation *oper1);
-
-
-extern void
-slang_operation_add_children(slang_operation *oper, GLuint num_children);
-
-
-/** Return number of children of given node */
-static INLINE GLuint
-slang_oper_num_children(const slang_operation *oper)
-{
-   return oper->num_children;
-}
-
-/** Return child of given operation node */
-static INLINE slang_operation *
-slang_oper_child(slang_operation *oper, GLuint child)
-{
-   assert(child < oper->num_children);
-   return &oper->children[child];
-}
-
-
-/** Return child of given operation node, const version */
-static INLINE const slang_operation *
-slang_oper_child_const(const slang_operation *oper, GLuint child)
-{
-   assert(child < oper->num_children);
-   return &oper->children[child];
-}
-
-
-/** Init oper to a boolean literal. */
-static INLINE void
-slang_operation_literal_bool(slang_operation *oper, GLboolean value)
-{
-   oper->type = SLANG_OPER_LITERAL_BOOL;
-   oper->literal[0] =
-   oper->literal[1] =
-   oper->literal[2] =
-   oper->literal[3] = (float) value;
-   oper->literal_size = 1;
-}
-
-
-/** Init oper to an int literal. */
-static INLINE void
-slang_operation_literal_int(slang_operation *oper, GLint value)
-{
-   oper->type = SLANG_OPER_LITERAL_INT;
-   oper->literal[0] =
-   oper->literal[1] =
-   oper->literal[2] =
-   oper->literal[3] = (float) value;
-   oper->literal_size = 1;
-}
-
-
-#endif /* SLANG_COMPILE_OPERATION_H */
diff --git a/src/mesa/slang/slang_compile_struct.c b/src/mesa/slang/slang_compile_struct.c
deleted file mode 100644 (file)
index e6c3873..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_compile_struct.c
- * slang front-end compiler
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_mem.h"
-#include "slang_compile.h"
-
-
-GLvoid
-_slang_struct_scope_ctr(slang_struct_scope * self)
-{
-   self->structs = NULL;
-   self->num_structs = 0;
-   self->outer_scope = NULL;
-}
-
-void
-slang_struct_scope_destruct(slang_struct_scope * scope)
-{
-   GLuint i;
-
-   for (i = 0; i < scope->num_structs; i++)
-      slang_struct_destruct(scope->structs + i);
-   _slang_free(scope->structs);
-   /* do not free scope->outer_scope */
-}
-
-int
-slang_struct_scope_copy(slang_struct_scope * x, const slang_struct_scope * y)
-{
-   slang_struct_scope z;
-   GLuint i;
-
-   _slang_struct_scope_ctr(&z);
-   z.structs = (slang_struct *)
-      _slang_alloc(y->num_structs * sizeof(slang_struct));
-   if (z.structs == NULL) {
-      slang_struct_scope_destruct(&z);
-      return 0;
-   }
-   for (z.num_structs = 0; z.num_structs < y->num_structs; z.num_structs++)
-      if (!slang_struct_construct(&z.structs[z.num_structs])) {
-         slang_struct_scope_destruct(&z);
-         return 0;
-      }
-   for (i = 0; i < z.num_structs; i++)
-      if (!slang_struct_copy(&z.structs[i], &y->structs[i])) {
-         slang_struct_scope_destruct(&z);
-         return 0;
-      }
-   z.outer_scope = y->outer_scope;
-   slang_struct_scope_destruct(x);
-   *x = z;
-   return 1;
-}
-
-slang_struct *
-slang_struct_scope_find(slang_struct_scope * stru, slang_atom a_name,
-                        int all_scopes)
-{
-   GLuint i;
-
-   for (i = 0; i < stru->num_structs; i++)
-      if (a_name == stru->structs[i].a_name)
-         return &stru->structs[i];
-   if (all_scopes && stru->outer_scope != NULL)
-      return slang_struct_scope_find(stru->outer_scope, a_name, 1);
-   return NULL;
-}
-
-/* slang_struct */
-
-int
-slang_struct_construct(slang_struct * stru)
-{
-   stru->a_name = SLANG_ATOM_NULL;
-   stru->fields = (slang_variable_scope *)
-      _slang_alloc(sizeof(slang_variable_scope));
-   if (stru->fields == NULL)
-      return 0;
-   _slang_variable_scope_ctr(stru->fields);
-
-   stru->structs =
-      (slang_struct_scope *) _slang_alloc(sizeof(slang_struct_scope));
-   if (stru->structs == NULL) {
-      slang_variable_scope_destruct(stru->fields);
-      _slang_free(stru->fields);
-      return 0;
-   }
-   _slang_struct_scope_ctr(stru->structs);
-   stru->constructor = NULL;
-   return 1;
-}
-
-void
-slang_struct_destruct(slang_struct * stru)
-{
-   slang_variable_scope_destruct(stru->fields);
-   _slang_free(stru->fields);
-   slang_struct_scope_destruct(stru->structs);
-   _slang_free(stru->structs);
-}
-
-int
-slang_struct_copy(slang_struct * x, const slang_struct * y)
-{
-   slang_struct z;
-
-   if (!slang_struct_construct(&z))
-      return 0;
-   z.a_name = y->a_name;
-   if (!slang_variable_scope_copy(z.fields, y->fields)) {
-      slang_struct_destruct(&z);
-      return 0;
-   }
-   if (!slang_struct_scope_copy(z.structs, y->structs)) {
-      slang_struct_destruct(&z);
-      return 0;
-   }
-   slang_struct_destruct(x);
-   *x = z;
-   return 1;
-}
-
-int
-slang_struct_equal(const slang_struct * x, const slang_struct * y)
-{
-   GLuint i;
-
-   if (x->fields->num_variables != y->fields->num_variables)
-      return 0;
-
-   for (i = 0; i < x->fields->num_variables; i++) {
-      const slang_variable *varx = x->fields->variables[i];
-      const slang_variable *vary = y->fields->variables[i];
-
-      if (varx->a_name != vary->a_name)
-         return 0;
-      if (!slang_type_specifier_equal(&varx->type.specifier,
-                                      &vary->type.specifier))
-         return 0;
-      if (varx->type.specifier.type == SLANG_SPEC_ARRAY)
-         if (varx->array_len != vary->array_len)
-            return GL_FALSE;
-   }
-   return 1;
-}
diff --git a/src/mesa/slang/slang_compile_struct.h b/src/mesa/slang/slang_compile_struct.h
deleted file mode 100644 (file)
index 7be6f20..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2005-2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#if !defined SLANG_COMPILE_STRUCT_H
-#define SLANG_COMPILE_STRUCT_H
-
-#if defined __cplusplus
-extern "C" {
-#endif
-
-#include "main/glheader.h"
-#include "slang_utility.h"
-
-struct slang_function_;
-
-typedef struct slang_struct_scope_
-{
-   struct slang_struct_ *structs;
-   GLuint num_structs;
-   struct slang_struct_scope_ *outer_scope;
-} slang_struct_scope;
-
-extern GLvoid
-_slang_struct_scope_ctr (slang_struct_scope *);
-
-void slang_struct_scope_destruct (slang_struct_scope *);
-int slang_struct_scope_copy (slang_struct_scope *, const slang_struct_scope *);
-struct slang_struct_ *slang_struct_scope_find (slang_struct_scope *, slang_atom, int);
-
-typedef struct slang_struct_
-{
-   slang_atom a_name;
-   struct slang_variable_scope_ *fields;
-   slang_struct_scope *structs;
-   struct slang_function_ *constructor;
-} slang_struct;
-
-int slang_struct_construct (slang_struct *);
-void slang_struct_destruct (slang_struct *);
-int slang_struct_copy (slang_struct *, const slang_struct *);
-int slang_struct_equal (const slang_struct *, const slang_struct *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff --git a/src/mesa/slang/slang_compile_variable.c b/src/mesa/slang/slang_compile_variable.c
deleted file mode 100644 (file)
index 23c08a9..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_compile_variable.c
- * slang front-end compiler
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_compile.h"
-#include "slang_mem.h"
-
-
-static slang_variable *
-slang_variable_new(void)
-{
-   slang_variable *v = (slang_variable *) _slang_alloc(sizeof(slang_variable));
-   if (v) {
-      if (!slang_variable_construct(v)) {
-         _slang_free(v);
-         v = NULL;
-      }
-   }
-   return v;
-}
-
-
-static void
-slang_variable_delete(slang_variable * var)
-{
-   slang_variable_destruct(var);
-   _slang_free(var);
-}
-
-
-/*
- * slang_variable_scope
- */
-
-slang_variable_scope *
-_slang_variable_scope_new(slang_variable_scope *parent)
-{
-   slang_variable_scope *s;
-   s = (slang_variable_scope *) _slang_alloc(sizeof(slang_variable_scope));
-   if (s)
-      s->outer_scope = parent;
-   return s;
-}
-
-
-GLvoid
-_slang_variable_scope_ctr(slang_variable_scope * self)
-{
-   self->variables = NULL;
-   self->num_variables = 0;
-   self->outer_scope = NULL;
-}
-
-void
-slang_variable_scope_destruct(slang_variable_scope * scope)
-{
-   unsigned int i;
-
-   if (!scope)
-      return;
-   for (i = 0; i < scope->num_variables; i++) {
-      if (scope->variables[i])
-         slang_variable_delete(scope->variables[i]);
-   }
-   _slang_free(scope->variables);
-   /* do not free scope->outer_scope */
-}
-
-int
-slang_variable_scope_copy(slang_variable_scope * x,
-                          const slang_variable_scope * y)
-{
-   slang_variable_scope z;
-   unsigned int i;
-
-   _slang_variable_scope_ctr(&z);
-   z.variables = (slang_variable **)
-      _slang_alloc(y->num_variables * sizeof(slang_variable *));
-   if (z.variables == NULL) {
-      slang_variable_scope_destruct(&z);
-      return 0;
-   }
-   for (z.num_variables = 0; z.num_variables < y->num_variables;
-        z.num_variables++) {
-      z.variables[z.num_variables] = slang_variable_new();
-      if (!z.variables[z.num_variables]) {
-         slang_variable_scope_destruct(&z);
-         return 0;
-      }
-   }
-   for (i = 0; i < z.num_variables; i++) {
-      if (!slang_variable_copy(z.variables[i], y->variables[i])) {
-         slang_variable_scope_destruct(&z);
-         return 0;
-      }
-   }
-   z.outer_scope = y->outer_scope;
-   slang_variable_scope_destruct(x);
-   *x = z;
-   return 1;
-}
-
-
-/**
- * Grow the variable list by one.
- * \return  pointer to space for the new variable (will be initialized)
- */
-slang_variable *
-slang_variable_scope_grow(slang_variable_scope *scope)
-{
-   const int n = scope->num_variables;
-   scope->variables = (slang_variable **)
-         _slang_realloc(scope->variables,
-                        n * sizeof(slang_variable *),
-                        (n + 1) * sizeof(slang_variable *));
-   if (!scope->variables)
-      return NULL;
-
-   scope->num_variables++;
-
-   scope->variables[n] = slang_variable_new();
-   if (!scope->variables[n])
-      return NULL;
-
-   return scope->variables[n];
-}
-
-
-
-/* slang_variable */
-
-int
-slang_variable_construct(slang_variable * var)
-{
-   if (!slang_fully_specified_type_construct(&var->type))
-      return 0;
-   var->a_name = SLANG_ATOM_NULL;
-   var->array_len = 0;
-   var->initializer = NULL;
-   var->size = 0;
-   var->isTemp = GL_FALSE;
-   var->store = NULL;
-   var->declared = 0;
-   return 1;
-}
-
-
-void
-slang_variable_destruct(slang_variable * var)
-{
-   slang_fully_specified_type_destruct(&var->type);
-   if (var->initializer != NULL) {
-      slang_operation_destruct(var->initializer);
-      _slang_free(var->initializer);
-   }
-#if 0
-   if (var->aux) {
-      free(var->aux);
-   }
-#endif
-}
-
-
-int
-slang_variable_copy(slang_variable * x, const slang_variable * y)
-{
-   slang_variable z;
-
-   if (!slang_variable_construct(&z))
-      return 0;
-   if (!slang_fully_specified_type_copy(&z.type, &y->type)) {
-      slang_variable_destruct(&z);
-      return 0;
-   }
-   z.a_name = y->a_name;
-   z.array_len = y->array_len;
-   if (y->initializer != NULL) {
-      z.initializer
-         = (slang_operation *) _slang_alloc(sizeof(slang_operation));
-      if (z.initializer == NULL) {
-         slang_variable_destruct(&z);
-         return 0;
-      }
-      if (!slang_operation_construct(z.initializer)) {
-         _slang_free(z.initializer);
-         slang_variable_destruct(&z);
-         return 0;
-      }
-      if (!slang_operation_copy(z.initializer, y->initializer)) {
-         slang_variable_destruct(&z);
-         return 0;
-      }
-   }
-   z.size = y->size;
-   slang_variable_destruct(x);
-   *x = z;
-   return 1;
-}
-
-
-/**
- * Search for named variable in given scope.
- * \param all  if true, search parent scopes too.
- */
-slang_variable *
-_slang_variable_locate(const slang_variable_scope * scope,
-                       const slang_atom a_name, GLboolean all)
-{
-   while (scope) {
-      GLuint i;
-      for (i = 0; i < scope->num_variables; i++)
-         if (a_name == scope->variables[i]->a_name)
-            return scope->variables[i];
-      if (all)
-         scope = scope->outer_scope;
-      else
-         scope = NULL;
-   }
-   return NULL;
-}
diff --git a/src/mesa/slang/slang_compile_variable.h b/src/mesa/slang/slang_compile_variable.h
deleted file mode 100644 (file)
index 48dc6ef..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.2
- *
- * Copyright (C) 2005-2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_COMPILE_VARIABLE_H
-#define SLANG_COMPILE_VARIABLE_H
-
-
-#include "main/glheader.h"
-#include "slang_typeinfo.h"
-#include "slang_utility.h"
-
-
-/**
- * A shading language program variable.
- */
-typedef struct slang_variable_
-{
-   slang_fully_specified_type type; /**< Variable's data type */
-   slang_atom a_name;               /**< The variable's name (char *) */
-   GLuint array_len;                /**< only if type == SLANG_SPEC_ARRAy */
-   struct slang_operation_ *initializer; /**< Optional initializer code */
-   GLuint size;                     /**< Variable's size in bytes */
-   GLboolean is_global;
-   GLboolean isTemp;                /**< a named temporary (__resultTmp) */
-   GLboolean declared;              /**< has the var been declared? */
-   struct slang_ir_storage_ *store; /**< Storage for this var */
-} slang_variable;
-
-
-/**
- * Basically a list of variables, with a pointer to the parent scope.
- */
-typedef struct slang_variable_scope_
-{
-   slang_variable **variables;  /**< Array [num_variables] of ptrs to vars */
-   GLuint num_variables;
-   struct slang_variable_scope_ *outer_scope;
-} slang_variable_scope;
-
-
-extern slang_variable_scope *
-_slang_variable_scope_new(slang_variable_scope *parent);
-
-extern GLvoid
-_slang_variable_scope_ctr(slang_variable_scope *);
-
-extern void
-slang_variable_scope_destruct(slang_variable_scope *);
-
-extern int
-slang_variable_scope_copy(slang_variable_scope *,
-                          const slang_variable_scope *);
-
-extern slang_variable *
-slang_variable_scope_grow(slang_variable_scope *);
-
-extern int
-slang_variable_construct(slang_variable *);
-
-extern void
-slang_variable_destruct(slang_variable *);
-
-extern int
-slang_variable_copy(slang_variable *, const slang_variable *);
-
-extern slang_variable *
-_slang_variable_locate(const slang_variable_scope *, const slang_atom a_name,
-                       GLboolean all);
-
-
-#endif /* SLANG_COMPILE_VARIABLE_H */
diff --git a/src/mesa/slang/slang_emit.c b/src/mesa/slang/slang_emit.c
deleted file mode 100644 (file)
index a9aa6fe..0000000
+++ /dev/null
@@ -1,2686 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
- * Copyright (C) 2008 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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_emit.c
- * Emit program instructions (PI code) from IR trees.
- * \author Brian Paul
- */
-
-/***
- *** NOTES
- ***
- *** To emit GPU instructions, we basically just do an in-order traversal
- *** of the IR tree.
- ***/
-
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "program/program.h"
-#include "program/prog_instruction.h"
-#include "program/prog_parameter.h"
-#include "program/prog_print.h"
-#include "slang_builtin.h"
-#include "slang_emit.h"
-#include "slang_mem.h"
-
-
-#define PEEPHOLE_OPTIMIZATIONS 1
-#define ANNOTATE 0
-
-
-typedef struct
-{
-   slang_info_log *log;
-   slang_var_table *vt;
-   struct gl_program *prog;
-   struct gl_program **Subroutines;
-   GLuint NumSubroutines;
-
-   GLuint MaxInstructions;  /**< size of prog->Instructions[] buffer */
-
-   GLboolean UnresolvedFunctions;
-
-   /* code-gen options */
-   GLboolean EmitHighLevelInstructions;
-   GLboolean EmitCondCodes;
-   GLboolean EmitComments;
-   GLboolean EmitBeginEndSub; /* XXX TEMPORARY */
-} slang_emit_info;
-
-
-
-static struct gl_program *
-new_subroutine(slang_emit_info *emitInfo, GLuint *id)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   const GLuint n = emitInfo->NumSubroutines;
-
-   emitInfo->Subroutines = (struct gl_program **)
-      _mesa_realloc(emitInfo->Subroutines,
-                    n * sizeof(struct gl_program *),
-                    (n + 1) * sizeof(struct gl_program *));
-   emitInfo->Subroutines[n] = ctx->Driver.NewProgram(ctx, emitInfo->prog->Target, 0);
-   emitInfo->Subroutines[n]->Parameters = emitInfo->prog->Parameters;
-   emitInfo->NumSubroutines++;
-   *id = n;
-   return emitInfo->Subroutines[n];
-}
-
-
-/**
- * Convert a writemask to a swizzle.  Used for testing cond codes because
- * we only want to test the cond code component(s) that was set by the
- * previous instruction.
- */
-static GLuint
-writemask_to_swizzle(GLuint writemask)
-{
-   if (writemask == WRITEMASK_X)
-      return SWIZZLE_XXXX;
-   if (writemask == WRITEMASK_Y)
-      return SWIZZLE_YYYY;
-   if (writemask == WRITEMASK_Z)
-      return SWIZZLE_ZZZZ;
-   if (writemask == WRITEMASK_W)
-      return SWIZZLE_WWWW;
-   return SWIZZLE_XYZW;  /* shouldn't be hit */
-}
-
-
-/**
- * Convert a swizzle mask to a writemask.
- * Note that the slang_ir_storage->Swizzle field can represent either a
- * swizzle mask or a writemask, depending on how it's used.  For example,
- * when we parse "direction.yz" alone, we don't know whether .yz is a
- * writemask or a swizzle.  In this case, we encode ".yz" in store->Swizzle
- * as a swizzle mask (.yz?? actually).  Later, if direction.yz is used as
- * an R-value, we use store->Swizzle as-is.  Otherwise, if direction.yz is
- * used as an L-value, we convert it to a writemask.
- */
-static GLuint
-swizzle_to_writemask(GLuint swizzle)
-{
-   GLuint i, writemask = 0x0;
-   for (i = 0; i < 4; i++) {
-      GLuint swz = GET_SWZ(swizzle, i);
-      if (swz <= SWIZZLE_W) {
-         writemask |= (1 << swz);
-      }
-   }
-   return writemask;
-}
-
-
-/**
- * Swizzle a swizzle (function composition).
- * That is, return swz2(swz1), or said another way: swz1.szw2
- * Example: swizzle_swizzle(".zwxx", ".xxyw") yields ".zzwx"
- */
-GLuint
-_slang_swizzle_swizzle(GLuint swz1, GLuint swz2)
-{
-   GLuint i, swz, s[4];
-   for (i = 0; i < 4; i++) {
-      GLuint c = GET_SWZ(swz2, i);
-      if (c <= SWIZZLE_W)
-         s[i] = GET_SWZ(swz1, c);
-      else
-         s[i] = c;
-   }
-   swz = MAKE_SWIZZLE4(s[0], s[1], s[2], s[3]);
-   return swz;
-}
-
-
-/**
- * Return the default swizzle mask for accessing a variable of the
- * given size (in floats).  If size = 1, comp is used to identify
- * which component [0..3] of the register holds the variable.
- */
-GLuint
-_slang_var_swizzle(GLint size, GLint comp)
-{
-   switch (size) {
-   case 1:
-      return MAKE_SWIZZLE4(comp, SWIZZLE_NIL, SWIZZLE_NIL, SWIZZLE_NIL);
-   case 2:
-      return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_NIL, SWIZZLE_NIL);
-   case 3:
-      return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_NIL);
-   default:
-      return SWIZZLE_XYZW;
-   }
-}
-
-
-
-/**
- * Allocate storage for the given node (if it hasn't already been allocated).
- *
- * Typically this is temporary storage for an intermediate result (such as
- * for a multiply or add, etc).
- *
- * If n->Store does not exist it will be created and will be of the size
- * specified by defaultSize.
- */
-static GLboolean
-alloc_node_storage(slang_emit_info *emitInfo, slang_ir_node *n,
-                   GLint defaultSize)
-{
-   assert(!n->Var);
-   if (!n->Store) {
-      assert(defaultSize > 0);
-      n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, defaultSize);
-      if (!n->Store) {
-         return GL_FALSE;
-      }
-   }
-
-   /* now allocate actual register(s).  I.e. set n->Store->Index >= 0 */
-   if (n->Store->Index < 0) {
-      if (!_slang_alloc_temp(emitInfo->vt, n->Store)) {
-         slang_info_log_error(emitInfo->log,
-                              "Ran out of registers, too many temporaries");
-         _slang_free(n->Store);
-         n->Store = NULL;
-         return GL_FALSE;
-      }
-   }
-   return GL_TRUE;
-}
-
-
-/**
- * Free temporary storage, if n->Store is, in fact, temp storage.
- * Otherwise, no-op.
- */
-static void
-free_node_storage(slang_var_table *vt, slang_ir_node *n)
-{
-   if (n->Store->File == PROGRAM_TEMPORARY &&
-       n->Store->Index >= 0 &&
-       n->Opcode != IR_SWIZZLE) {
-      if (_slang_is_temp(vt, n->Store)) {
-         _slang_free_temp(vt, n->Store);
-         n->Store->Index = -1;
-         n->Store = NULL; /* XXX this may not be needed */
-      }
-   }
-}
-
-
-/**
- * Helper function to allocate a short-term temporary.
- * Free it with _slang_free_temp().
- */
-static GLboolean
-alloc_local_temp(slang_emit_info *emitInfo, slang_ir_storage *temp, GLint size)
-{
-   assert(size >= 1);
-   assert(size <= 4);
-   memset(temp, 0, sizeof(*temp));
-   temp->Size = size;
-   temp->File = PROGRAM_TEMPORARY;
-   temp->Index = -1;
-   return _slang_alloc_temp(emitInfo->vt, temp);
-}
-
-
-/**
- * Remove any SWIZZLE_NIL terms from given swizzle mask.
- * For a swizzle like .z??? generate .zzzz (replicate single component).
- * Else, for .wx?? generate .wxzw (insert default component for the position).
- */
-static GLuint
-fix_swizzle(GLuint swizzle)
-{
-   GLuint c0 = GET_SWZ(swizzle, 0),
-      c1 = GET_SWZ(swizzle, 1),
-      c2 = GET_SWZ(swizzle, 2),
-      c3 = GET_SWZ(swizzle, 3);
-   if (c1 == SWIZZLE_NIL && c2 == SWIZZLE_NIL && c3 == SWIZZLE_NIL) {
-      /* smear first component across all positions */
-      c1 = c2 = c3 = c0;
-   }
-   else {
-      /* insert default swizzle components */
-      if (c0 == SWIZZLE_NIL)
-         c0 = SWIZZLE_X;
-      if (c1 == SWIZZLE_NIL)
-         c1 = SWIZZLE_Y;
-      if (c2 == SWIZZLE_NIL)
-         c2 = SWIZZLE_Z;
-      if (c3 == SWIZZLE_NIL)
-         c3 = SWIZZLE_W;
-   }
-   return MAKE_SWIZZLE4(c0, c1, c2, c3);
-}
-
-
-
-/**
- * Convert IR storage to an instruction dst register.
- */
-static void
-storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st)
-{
-   const GLboolean relAddr = st->RelAddr;
-   const GLint size = st->Size;
-   GLint index = st->Index;
-   GLuint swizzle = st->Swizzle;
-
-   assert(index >= 0);
-   /* if this is storage relative to some parent storage, walk up the tree */
-   while (st->Parent) {
-      st = st->Parent;
-      assert(st->Index >= 0);
-      index += st->Index;
-      swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
-   }
-
-   assert(st->File != PROGRAM_UNDEFINED);
-   dst->File = st->File;
-
-   assert(index >= 0);
-   dst->Index = index;
-
-   assert(size >= 1);
-   assert(size <= 4);
-
-   if (swizzle != SWIZZLE_XYZW) {
-      dst->WriteMask = swizzle_to_writemask(swizzle);
-   }
-   else {
-      switch (size) {
-      case 1:
-         dst->WriteMask = WRITEMASK_X << GET_SWZ(st->Swizzle, 0);
-         break;
-      case 2:
-         dst->WriteMask = WRITEMASK_XY;
-         break;
-      case 3:
-         dst->WriteMask = WRITEMASK_XYZ;
-         break;
-      case 4:
-         dst->WriteMask = WRITEMASK_XYZW;
-         break;
-      default:
-         ; /* error would have been caught above */
-      }
-   }
-
-   dst->RelAddr = relAddr;
-}
-
-
-/**
- * Convert IR storage to an instruction src register.
- */
-static void
-storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
-{
-   const GLboolean relAddr = st->RelAddr;
-   GLint index = st->Index;
-   GLuint swizzle = st->Swizzle;
-
-   /* if this is storage relative to some parent storage, walk up the tree */
-   assert(index >= 0);
-   while (st->Parent) {
-      st = st->Parent;
-      if (st->Index < 0) {
-         /* an error should have been reported already */
-         return;
-      }
-      assert(st->Index >= 0);
-      index += st->Index;
-      swizzle = _slang_swizzle_swizzle(fix_swizzle(st->Swizzle), swizzle);
-   }
-
-   assert(st->File >= 0);
-#if 1 /* XXX temporary */
-   if (st->File == PROGRAM_UNDEFINED) {
-      slang_ir_storage *st0 = (slang_ir_storage *) st;
-      st0->File = PROGRAM_TEMPORARY;
-   }
-#endif
-   assert(st->File < PROGRAM_FILE_MAX);
-   src->File = st->File;
-
-   assert(index >= 0);
-   src->Index = index;
-
-   swizzle = fix_swizzle(swizzle);
-   assert(GET_SWZ(swizzle, 0) <= SWIZZLE_W);
-   assert(GET_SWZ(swizzle, 1) <= SWIZZLE_W);
-   assert(GET_SWZ(swizzle, 2) <= SWIZZLE_W);
-   assert(GET_SWZ(swizzle, 3) <= SWIZZLE_W);
-   src->Swizzle = swizzle;
-
-   src->HasIndex2 = st->Is2D;
-   src->Index2 = st->Index2;
-
-   src->RelAddr = relAddr;
-}
-
-
-/*
- * Setup storage pointing to a scalar constant/literal.
- */
-static void
-constant_to_storage(slang_emit_info *emitInfo,
-                    GLfloat val,
-                    slang_ir_storage *store)
-{
-   GLuint swizzle;
-   GLint reg;
-   GLfloat value[4];
-
-   value[0] = val;
-   reg = _mesa_add_unnamed_constant(emitInfo->prog->Parameters,
-                                        value, 1, &swizzle);
-
-   memset(store, 0, sizeof(*store));
-   store->File = PROGRAM_CONSTANT;
-   store->Index = reg;
-   store->Swizzle = swizzle;
-}
-
-
-/**
- * Add new instruction at end of given program.
- * \param prog  the program to append instruction onto
- * \param opcode  opcode for the new instruction
- * \return pointer to the new instruction
- */
-static struct prog_instruction *
-new_instruction(slang_emit_info *emitInfo, gl_inst_opcode opcode)
-{
-   struct gl_program *prog = emitInfo->prog;
-   struct prog_instruction *inst;
-
-#if 0
-   /* print prev inst */
-   if (prog->NumInstructions > 0) {
-      _mesa_print_instruction(prog->Instructions + prog->NumInstructions - 1);
-   }
-#endif
-   assert(prog->NumInstructions <= emitInfo->MaxInstructions);
-
-   if (prog->NumInstructions == emitInfo->MaxInstructions) {
-      /* grow the instruction buffer */
-      emitInfo->MaxInstructions += 20;
-      prog->Instructions =
-         _mesa_realloc_instructions(prog->Instructions,
-                                    prog->NumInstructions,
-                                    emitInfo->MaxInstructions);
-      if (!prog->Instructions) {
-         return NULL;
-      }
-   }
-
-   inst = prog->Instructions + prog->NumInstructions;
-   prog->NumInstructions++;
-   _mesa_init_instructions(inst, 1);
-   inst->Opcode = opcode;
-   inst->BranchTarget = -1; /* invalid */
-   /*
-   printf("New inst %d: %p %s\n", prog->NumInstructions-1,(void*)inst,
-          _mesa_opcode_string(inst->Opcode));
-   */
-   return inst;
-}
-
-
-static struct prog_instruction *
-emit_arl_load(slang_emit_info *emitInfo,
-              gl_register_file file, GLint index, GLuint swizzle)
-{
-   struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ARL);
-   if (inst) {
-      inst->SrcReg[0].File = file;
-      inst->SrcReg[0].Index = index;
-      inst->SrcReg[0].Swizzle = fix_swizzle(swizzle);
-      inst->DstReg.File = PROGRAM_ADDRESS;
-      inst->DstReg.Index = 0;
-      inst->DstReg.WriteMask = WRITEMASK_X;
-   }
-   return inst;
-}
-
-
-/**
- * Emit a new instruction with given opcode, operands.
- * At this point the instruction may have multiple indirect register
- * loads/stores.  We convert those into ARL loads and address-relative
- * operands.  See comments inside.
- * At some point in the future we could directly emit indirectly addressed
- * registers in Mesa GPU instructions.
- */
-static struct prog_instruction *
-emit_instruction(slang_emit_info *emitInfo,
-                 gl_inst_opcode opcode,
-                 const slang_ir_storage *dst,
-                 const slang_ir_storage *src0,
-                 const slang_ir_storage *src1,
-                 const slang_ir_storage *src2)
-{
-   struct prog_instruction *inst;
-   GLuint numIndirect = 0;
-   const slang_ir_storage *src[3];
-   slang_ir_storage newSrc[3], newDst;
-   GLuint i;
-   GLboolean isTemp[3];
-
-   isTemp[0] = isTemp[1] = isTemp[2] = GL_FALSE;
-
-   src[0] = src0;
-   src[1] = src1;
-   src[2] = src2;
-
-   /* count up how many operands are indirect loads */
-   for (i = 0; i < 3; i++) {
-      if (src[i] && src[i]->IsIndirect)
-         numIndirect++;
-   }
-   if (dst && dst->IsIndirect)
-      numIndirect++;
-
-   /* Take special steps for indirect register loads.
-    * If we had multiple address registers this would be simpler.
-    * For example, this GLSL code:
-    *    x[i] = y[j] + z[k];
-    * would translate into something like:
-    *    ARL ADDR.x, i;
-    *    ARL ADDR.y, j;
-    *    ARL ADDR.z, k;
-    *    ADD TEMP[ADDR.x+5], TEMP[ADDR.y+9], TEMP[ADDR.z+4];
-    * But since we currently only have one address register we have to do this:
-    *    ARL ADDR.x, i;
-    *    MOV t1, TEMP[ADDR.x+9];
-    *    ARL ADDR.x, j;
-    *    MOV t2, TEMP[ADDR.x+4];
-    *    ARL ADDR.x, k;
-    *    ADD TEMP[ADDR.x+5], t1, t2;
-    * The code here figures this out...
-    */
-   if (numIndirect > 0) {
-      for (i = 0; i < 3; i++) {
-         if (src[i] && src[i]->IsIndirect) {
-            /* load the ARL register with the indirect register */
-            emit_arl_load(emitInfo,
-                          src[i]->IndirectFile,
-                          src[i]->IndirectIndex,
-                          src[i]->IndirectSwizzle);
-
-            if (numIndirect > 1) {
-               /* Need to load src[i] into a temporary register */
-               slang_ir_storage srcRelAddr;
-               alloc_local_temp(emitInfo, &newSrc[i], src[i]->Size);
-               isTemp[i] = GL_TRUE;
-
-               /* set RelAddr flag on src register */
-               srcRelAddr = *src[i];
-               srcRelAddr.RelAddr = GL_TRUE;
-               srcRelAddr.IsIndirect = GL_FALSE; /* not really needed */
-
-               /* MOV newSrc, srcRelAddr; */
-               inst = emit_instruction(emitInfo,
-                                       OPCODE_MOV,
-                                       &newSrc[i],
-                                       &srcRelAddr,
-                                       NULL,
-                                       NULL);
-               if (!inst) {
-                  return NULL;
-               }
-
-               src[i] = &newSrc[i];
-            }
-            else {
-               /* just rewrite the src[i] storage to be ARL-relative */
-               newSrc[i] = *src[i];
-               newSrc[i].RelAddr = GL_TRUE;
-               newSrc[i].IsIndirect = GL_FALSE; /* not really needed */
-               src[i] = &newSrc[i];
-            }
-         }
-      }
-   }
-
-   /* Take special steps for indirect dest register write */
-   if (dst && dst->IsIndirect) {
-      /* load the ARL register with the indirect register */
-      emit_arl_load(emitInfo,
-                    dst->IndirectFile,
-                    dst->IndirectIndex,
-                    dst->IndirectSwizzle);
-      newDst = *dst;
-      newDst.RelAddr = GL_TRUE;
-      newDst.IsIndirect = GL_FALSE;
-      dst = &newDst;
-   }
-
-   /* OK, emit the instruction and its dst, src regs */
-   inst = new_instruction(emitInfo, opcode);
-   if (!inst)
-      return NULL;
-
-   if (dst)
-      storage_to_dst_reg(&inst->DstReg, dst);
-
-   for (i = 0; i < 3; i++) {
-      if (src[i])
-         storage_to_src_reg(&inst->SrcReg[i], src[i]);
-   }
-
-   /* Free any temp registers that we allocated above */
-   for (i = 0; i < 3; i++) {
-      if (isTemp[i])
-         _slang_free_temp(emitInfo->vt, &newSrc[i]);
-   }
-
-   return inst;
-}
-
-
-
-/**
- * Put a comment on the given instruction.
- */
-static void
-inst_comment(struct prog_instruction *inst, const char *comment)
-{
-   if (inst)
-      inst->Comment = _mesa_strdup(comment);
-}
-
-
-
-/**
- * Return pointer to last instruction in program.
- */
-static struct prog_instruction *
-prev_instruction(slang_emit_info *emitInfo)
-{
-   struct gl_program *prog = emitInfo->prog;
-   if (prog->NumInstructions == 0)
-      return NULL;
-   else
-      return prog->Instructions + prog->NumInstructions - 1;
-}
-
-
-static struct prog_instruction *
-emit(slang_emit_info *emitInfo, slang_ir_node *n);
-
-
-/**
- * Return an annotation string for given node's storage.
- */
-static char *
-storage_annotation(const slang_ir_node *n, const struct gl_program *prog)
-{
-#if ANNOTATE
-   const slang_ir_storage *st = n->Store;
-   static char s[100] = "";
-
-   if (!st)
-      return _mesa_strdup("");
-
-   switch (st->File) {
-   case PROGRAM_CONSTANT:
-      if (st->Index >= 0) {
-         const GLfloat *val = prog->Parameters->ParameterValues[st->Index];
-         if (st->Swizzle == SWIZZLE_NOOP)
-            _mesa_snprintf(s, sizeof(s), "{%g, %g, %g, %g}", val[0], val[1], val[2], val[3]);
-         else {
-            _mesa_snprintf(s, sizeof(s), "%g", val[GET_SWZ(st->Swizzle, 0)]);
-         }
-      }
-      break;
-   case PROGRAM_TEMPORARY:
-      if (n->Var)
-         _mesa_snprintf(s, sizeof(s), "%s", (char *) n->Var->a_name);
-      else
-         _mesa_snprintf(s, sizeof(s), "t[%d]", st->Index);
-      break;
-   case PROGRAM_STATE_VAR:
-   case PROGRAM_UNIFORM:
-      _mesa_snprintf(s, sizeof(s), "%s", prog->Parameters->Parameters[st->Index].Name);
-      break;
-   case PROGRAM_VARYING:
-      _mesa_snprintf(s, sizeof(s), "%s", prog->Varying->Parameters[st->Index].Name);
-      break;
-   case PROGRAM_INPUT:
-      _mesa_snprintf(s, sizeof(s), "input[%d]", st->Index);
-      break;
-   case PROGRAM_OUTPUT:
-      _mesa_snprintf(s, sizeof(s), "output[%d]", st->Index);
-      break;
-   default:
-      s[0] = 0;
-   }
-   return _mesa_strdup(s);
-#else
-   return NULL;
-#endif
-}
-
-
-/**
- * Return an annotation string for an instruction.
- */
-static char *
-instruction_annotation(gl_inst_opcode opcode, char *dstAnnot,
-                       char *srcAnnot0, char *srcAnnot1, char *srcAnnot2)
-{
-#if ANNOTATE
-   const char *operator;
-   char *s;
-   int len = 50;
-
-   if (dstAnnot)
-      len += strlen(dstAnnot);
-   else
-      dstAnnot = _mesa_strdup("");
-
-   if (srcAnnot0)
-      len += strlen(srcAnnot0);
-   else
-      srcAnnot0 = _mesa_strdup("");
-
-   if (srcAnnot1)
-      len += strlen(srcAnnot1);
-   else
-      srcAnnot1 = _mesa_strdup("");
-
-   if (srcAnnot2)
-      len += strlen(srcAnnot2);
-   else
-      srcAnnot2 = _mesa_strdup("");
-
-   switch (opcode) {
-   case OPCODE_ADD:
-      operator = "+";
-      break;
-   case OPCODE_SUB:
-      operator = "-";
-      break;
-   case OPCODE_MUL:
-      operator = "*";
-      break;
-   case OPCODE_DP2:
-      operator = "DP2";
-      break;
-   case OPCODE_DP3:
-      operator = "DP3";
-      break;
-   case OPCODE_DP4:
-      operator = "DP4";
-      break;
-   case OPCODE_XPD:
-      operator = "XPD";
-      break;
-   case OPCODE_RSQ:
-      operator = "RSQ";
-      break;
-   case OPCODE_SGT:
-      operator = ">";
-      break;
-   default:
-      operator = ",";
-   }
-
-   s = (char *) malloc(len);
-   _mesa_snprintf(s, len, "%s = %s %s %s %s", dstAnnot,
-                  srcAnnot0, operator, srcAnnot1, srcAnnot2);
-
-   free(dstAnnot);
-   free(srcAnnot0);
-   free(srcAnnot1);
-   free(srcAnnot2);
-
-   return s;
-#else
-   return NULL;
-#endif
-}
-
-
-/**
- * Emit an instruction that's just a comment.
- */
-static struct prog_instruction *
-emit_comment(slang_emit_info *emitInfo, const char *comment)
-{
-   struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_NOP);
-   if (inst) {
-      inst_comment(inst, comment);
-   }
-   return inst;
-}
-
-
-/**
- * Generate code for a simple arithmetic instruction.
- * Either 1, 2 or 3 operands.
- */
-static struct prog_instruction *
-emit_arith(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   const slang_ir_info *info = _slang_ir_info(n->Opcode);
-   struct prog_instruction *inst;
-   GLuint i;
-
-   assert(info);
-   assert(info->InstOpcode != OPCODE_NOP);
-
-#if PEEPHOLE_OPTIMIZATIONS
-   /* Look for MAD opportunity */
-   if (info->NumParams == 2 &&
-       n->Opcode == IR_ADD && n->Children[0]->Opcode == IR_MUL) {
-      /* found pattern IR_ADD(IR_MUL(A, B), C) */
-      emit(emitInfo, n->Children[0]->Children[0]);  /* A */
-      emit(emitInfo, n->Children[0]->Children[1]);  /* B */
-      emit(emitInfo, n->Children[1]);  /* C */
-      if (!alloc_node_storage(emitInfo, n, -1)) {  /* dest */
-         return NULL;
-      }
-
-      inst = emit_instruction(emitInfo,
-                              OPCODE_MAD,
-                              n->Store,
-                              n->Children[0]->Children[0]->Store,
-                              n->Children[0]->Children[1]->Store,
-                              n->Children[1]->Store);
-
-      free_node_storage(emitInfo->vt, n->Children[0]->Children[0]);
-      free_node_storage(emitInfo->vt, n->Children[0]->Children[1]);
-      free_node_storage(emitInfo->vt, n->Children[1]);
-      return inst;
-   }
-
-   if (info->NumParams == 2 &&
-       n->Opcode == IR_ADD && n->Children[1]->Opcode == IR_MUL) {
-      /* found pattern IR_ADD(A, IR_MUL(B, C)) */
-      emit(emitInfo, n->Children[0]);  /* A */
-      emit(emitInfo, n->Children[1]->Children[0]);  /* B */
-      emit(emitInfo, n->Children[1]->Children[1]);  /* C */
-      if (!alloc_node_storage(emitInfo, n, -1)) {  /* dest */
-         return NULL;
-      }
-
-      inst = emit_instruction(emitInfo,
-                              OPCODE_MAD,
-                              n->Store,
-                              n->Children[1]->Children[0]->Store,
-                              n->Children[1]->Children[1]->Store,
-                              n->Children[0]->Store);
-
-      free_node_storage(emitInfo->vt, n->Children[1]->Children[0]);
-      free_node_storage(emitInfo->vt, n->Children[1]->Children[1]);
-      free_node_storage(emitInfo->vt, n->Children[0]);
-      return inst;
-   }
-#endif
-
-   /* gen code for children, may involve temp allocation */
-   for (i = 0; i < info->NumParams; i++) {
-      emit(emitInfo, n->Children[i]);
-      if (!n->Children[i] || !n->Children[i]->Store) {
-         /* error recovery */
-         return NULL;
-      }
-   }
-
-   /* result storage */
-   if (!alloc_node_storage(emitInfo, n, -1)) {
-      return NULL;
-   }
-
-   inst = emit_instruction(emitInfo,
-                           info->InstOpcode,
-                           n->Store,  /* dest */
-                           (info->NumParams > 0 ? n->Children[0]->Store : NULL),
-                           (info->NumParams > 1 ? n->Children[1]->Store : NULL),
-                           (info->NumParams > 2 ? n->Children[2]->Store : NULL)
-                           );
-
-   /* free temps */
-   for (i = 0; i < info->NumParams; i++)
-      free_node_storage(emitInfo->vt, n->Children[i]);
-
-   return inst;
-}
-
-
-/**
- * Emit code for == and != operators.  These could normally be handled
- * by emit_arith() except we need to be able to handle structure comparisons.
- */
-static struct prog_instruction *
-emit_compare(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst = NULL;
-   GLint size;
-
-   assert(n->Opcode == IR_EQUAL || n->Opcode == IR_NOTEQUAL);
-
-   /* gen code for children */
-   emit(emitInfo, n->Children[0]);
-   emit(emitInfo, n->Children[1]);
-
-   if (n->Children[0]->Store->Size != n->Children[1]->Store->Size) {
-      /* XXX this error should have been caught in slang_codegen.c */
-      slang_info_log_error(emitInfo->log, "invalid operands to == or !=");
-      n->Store = NULL;
-      return NULL;
-   }
-
-   /* final result is 1 bool */
-   if (!alloc_node_storage(emitInfo, n, 1))
-      return NULL;
-
-   size = n->Children[0]->Store->Size;
-
-   if (size == 1) {
-      gl_inst_opcode opcode = n->Opcode == IR_EQUAL ? OPCODE_SEQ : OPCODE_SNE;
-      inst =  emit_instruction(emitInfo,
-                               opcode,
-                               n->Store, /* dest */
-                               n->Children[0]->Store,
-                               n->Children[1]->Store,
-                               NULL);
-   }
-   else if (size <= 4) {
-      /* compare two vectors.
-       * Unfortunately, there's no instruction to compare vectors and
-       * return a scalar result.  Do it with some compare and dot product
-       * instructions...
-       */
-      GLuint swizzle;
-      gl_inst_opcode dotOp;
-      slang_ir_storage tempStore;
-
-      if (!alloc_local_temp(emitInfo, &tempStore, 4)) {
-         n->Store = NULL;
-         return NULL;
-         /* out of temps */
-      }
-
-      if (size == 4) {
-         dotOp = OPCODE_DP4;
-         swizzle = SWIZZLE_XYZW;
-      }
-      else if (size == 3) {
-         dotOp = OPCODE_DP3;
-         swizzle = SWIZZLE_XYZW;
-      }
-      else {
-         assert(size == 2);
-         dotOp = OPCODE_DP3; /* XXX use OPCODE_DP2 eventually */
-         swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y);
-      }
-
-      /* Compute inequality (temp = (A != B)) */
-      inst = emit_instruction(emitInfo,
-                              OPCODE_SNE,
-                              &tempStore,
-                              n->Children[0]->Store,
-                              n->Children[1]->Store,
-                              NULL);
-      if (!inst) {
-         return NULL;
-      }
-      inst_comment(inst, "Compare values");
-
-      /* Compute val = DOT(temp, temp)  (reduction) */
-      inst = emit_instruction(emitInfo,
-                              dotOp,
-                              n->Store,
-                              &tempStore,
-                              &tempStore,
-                              NULL);
-      if (!inst) {
-         return NULL;
-      }
-      inst->SrcReg[0].Swizzle = inst->SrcReg[1].Swizzle = swizzle; /*override*/
-      inst_comment(inst, "Reduce vec to bool");
-
-      _slang_free_temp(emitInfo->vt, &tempStore); /* free temp */
-
-      if (n->Opcode == IR_EQUAL) {
-         /* compute val = !val.x  with SEQ val, val, 0; */
-         slang_ir_storage zero;
-         constant_to_storage(emitInfo, 0.0, &zero);
-         inst = emit_instruction(emitInfo,
-                                 OPCODE_SEQ,
-                                 n->Store, /* dest */
-                                 n->Store,
-                                 &zero,
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-         inst_comment(inst, "Invert true/false");
-      }
-   }
-   else {
-      /* size > 4, struct or array compare.
-       * XXX this won't work reliably for structs with padding!!
-       */
-      GLint i, num = (n->Children[0]->Store->Size + 3) / 4;
-      slang_ir_storage accTemp, sneTemp;
-
-      if (!alloc_local_temp(emitInfo, &accTemp, 4))
-         return NULL;
-
-      if (!alloc_local_temp(emitInfo, &sneTemp, 4))
-         return NULL;
-
-      for (i = 0; i < num; i++) {
-         slang_ir_storage srcStore0 = *n->Children[0]->Store;
-         slang_ir_storage srcStore1 = *n->Children[1]->Store;
-         srcStore0.Index += i;
-         srcStore1.Index += i;
-
-         if (i == 0) {
-            /* SNE accTemp, left[i], right[i] */
-            inst = emit_instruction(emitInfo, OPCODE_SNE,
-                                    &accTemp, /* dest */
-                                    &srcStore0,
-                                    &srcStore1,
-                                    NULL);
-            if (!inst) {
-               return NULL;
-            }
-            inst_comment(inst, "Begin struct/array comparison");
-         }
-         else {
-            /* SNE sneTemp, left[i], right[i] */
-            inst = emit_instruction(emitInfo, OPCODE_SNE,
-                                    &sneTemp, /* dest */
-                                    &srcStore0,
-                                    &srcStore1,
-                                    NULL);
-            if (!inst) {
-               return NULL;
-            }
-            /* ADD accTemp, accTemp, sneTemp; # like logical-OR */
-            inst = emit_instruction(emitInfo, OPCODE_ADD,
-                                    &accTemp, /* dest */
-                                    &accTemp,
-                                    &sneTemp,
-                                    NULL);
-            if (!inst) {
-               return NULL;
-            }
-         }
-      }
-
-      /* compute accTemp.x || accTemp.y || accTemp.z || accTemp.w with DOT4 */
-      inst = emit_instruction(emitInfo, OPCODE_DP4,
-                              n->Store,
-                              &accTemp,
-                              &accTemp,
-                              NULL);
-      if (!inst) {
-         return NULL;
-      }
-      inst_comment(inst, "End struct/array comparison");
-
-      if (n->Opcode == IR_EQUAL) {
-         /* compute tmp.x = !tmp.x  via tmp.x = (tmp.x == 0) */
-         slang_ir_storage zero;
-         constant_to_storage(emitInfo, 0.0, &zero);
-         inst = emit_instruction(emitInfo, OPCODE_SEQ,
-                                 n->Store, /* dest */
-                                 n->Store,
-                                 &zero,
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-         inst_comment(inst, "Invert true/false");
-      }
-
-      _slang_free_temp(emitInfo->vt, &accTemp);
-      _slang_free_temp(emitInfo->vt, &sneTemp);
-   }
-
-   /* free temps */
-   free_node_storage(emitInfo->vt, n->Children[0]);
-   free_node_storage(emitInfo->vt, n->Children[1]);
-
-   return inst;
-}
-
-
-
-/**
- * Generate code for an IR_CLAMP instruction.
- */
-static struct prog_instruction *
-emit_clamp(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-   slang_ir_node tmpNode;
-
-   assert(n->Opcode == IR_CLAMP);
-   /* ch[0] = value
-    * ch[1] = min limit
-    * ch[2] = max limit
-    */
-
-   inst = emit(emitInfo, n->Children[0]);
-
-   /* If lower limit == 0.0 and upper limit == 1.0,
-    *    set prev instruction's SaturateMode field to SATURATE_ZERO_ONE.
-    * Else,
-    *    emit OPCODE_MIN, OPCODE_MAX sequence.
-    */
-#if 0
-   /* XXX this isn't quite finished yet */
-   if (n->Children[1]->Opcode == IR_FLOAT &&
-       n->Children[1]->Value[0] == 0.0 &&
-       n->Children[1]->Value[1] == 0.0 &&
-       n->Children[1]->Value[2] == 0.0 &&
-       n->Children[1]->Value[3] == 0.0 &&
-       n->Children[2]->Opcode == IR_FLOAT &&
-       n->Children[2]->Value[0] == 1.0 &&
-       n->Children[2]->Value[1] == 1.0 &&
-       n->Children[2]->Value[2] == 1.0 &&
-       n->Children[2]->Value[3] == 1.0) {
-      if (!inst) {
-         inst = prev_instruction(prog);
-      }
-      if (inst && inst->Opcode != OPCODE_NOP) {
-         /* and prev instruction's DstReg matches n->Children[0]->Store */
-         inst->SaturateMode = SATURATE_ZERO_ONE;
-         n->Store = n->Children[0]->Store;
-         return inst;
-      }
-   }
-#else
-   (void) inst;
-#endif
-
-   if (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))
-      return NULL;
-
-   emit(emitInfo, n->Children[1]);
-   emit(emitInfo, n->Children[2]);
-
-   /* Some GPUs don't allow reading from output registers.  So if the
-    * dest for this clamp() is an output reg, we can't use that reg for
-    * the intermediate result.  Use a temp register instead.
-    */
-   memset(&tmpNode, 0, sizeof(tmpNode));
-   if (!alloc_node_storage(emitInfo, &tmpNode, n->Store->Size)) {
-      return NULL;
-   }
-
-   /* tmp = max(ch[0], ch[1]) */
-   inst = emit_instruction(emitInfo, OPCODE_MAX,
-                           tmpNode.Store, /* dest */
-                           n->Children[0]->Store,
-                           n->Children[1]->Store,
-                           NULL);
-   if (!inst) {
-      return NULL;
-   }
-
-   /* n->dest = min(tmp, ch[2]) */
-   inst = emit_instruction(emitInfo, OPCODE_MIN,
-                           n->Store, /* dest */
-                           tmpNode.Store,
-                           n->Children[2]->Store,
-                           NULL);
-
-   free_node_storage(emitInfo->vt, &tmpNode);
-
-   return inst;
-}
-
-
-static struct prog_instruction *
-emit_negation(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   /* Implement as MOV dst, -src; */
-   /* XXX we could look at the previous instruction and in some circumstances
-    * modify it to accomplish the negation.
-    */
-   struct prog_instruction *inst;
-
-   emit(emitInfo, n->Children[0]);
-
-   if (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))
-      return NULL;
-
-   inst = emit_instruction(emitInfo,
-                           OPCODE_MOV,
-                           n->Store, /* dest */
-                           n->Children[0]->Store,
-                           NULL,
-                           NULL);
-   if (inst) {
-      inst->SrcReg[0].Negate = NEGATE_XYZW;
-   }
-   return inst;
-}
-
-
-static struct prog_instruction *
-emit_label(slang_emit_info *emitInfo, const slang_ir_node *n)
-{
-   assert(n->Label);
-#if 0
-   /* XXX this fails in loop tail code - investigate someday */
-   assert(_slang_label_get_location(n->Label) < 0);
-   _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
-                             emitInfo->prog);
-#else
-   if (_slang_label_get_location(n->Label) < 0)
-      _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
-                                emitInfo->prog);
-#endif
-   return NULL;
-}
-
-
-/**
- * Emit code for a function call.
- * Note that for each time a function is called, we emit the function's
- * body code again because the set of available registers may be different.
- */
-static struct prog_instruction *
-emit_fcall(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct gl_program *progSave;
-   struct prog_instruction *inst;
-   GLuint subroutineId;
-   GLuint maxInstSave;
-
-   assert(n->Opcode == IR_CALL);
-   assert(n->Label);
-
-   /* save/push cur program */
-   maxInstSave = emitInfo->MaxInstructions;
-   progSave = emitInfo->prog;
-
-   emitInfo->prog = new_subroutine(emitInfo, &subroutineId);
-   emitInfo->MaxInstructions = emitInfo->prog->NumInstructions;
-
-   _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
-                             emitInfo->prog);
-
-   if (emitInfo->EmitBeginEndSub) {
-      /* BGNSUB isn't a real instruction.
-       * We require a label (i.e. "foobar:") though, if we're going to
-       * print the program in the NV format.  The BNGSUB instruction is
-       * really just a NOP to attach the label to.
-       */
-      inst = new_instruction(emitInfo, OPCODE_BGNSUB);
-      if (!inst) {
-         return NULL;
-      }
-      inst_comment(inst, n->Label->Name);
-   }
-
-   /* body of function: */
-   emit(emitInfo, n->Children[0]);
-   n->Store = n->Children[0]->Store;
-
-   /* add RET instruction now, if needed */
-   inst = prev_instruction(emitInfo);
-   if (inst && inst->Opcode != OPCODE_RET) {
-      inst = new_instruction(emitInfo, OPCODE_RET);
-      if (!inst) {
-         return NULL;
-      }
-   }
-
-   if (emitInfo->EmitBeginEndSub) {
-      inst = new_instruction(emitInfo, OPCODE_ENDSUB);
-      if (!inst) {
-         return NULL;
-      }
-      inst_comment(inst, n->Label->Name);
-   }
-
-   /* pop/restore cur program */
-   emitInfo->prog = progSave;
-   emitInfo->MaxInstructions = maxInstSave;
-
-   /* emit the function call */
-   inst = new_instruction(emitInfo, OPCODE_CAL);
-   if (!inst) {
-      return NULL;
-   }
-   /* The branch target is just the subroutine number (changed later) */
-   inst->BranchTarget = subroutineId;
-   inst_comment(inst, n->Label->Name);
-   assert(inst->BranchTarget >= 0);
-
-   return inst;
-}
-
-
-/**
- * Emit code for a 'return' statement.
- */
-static struct prog_instruction *
-emit_return(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-   assert(n);
-   assert(n->Opcode == IR_RETURN);
-   assert(n->Label);
-   inst = new_instruction(emitInfo, OPCODE_RET);
-   if (inst) {
-      inst->DstReg.CondMask = COND_TR;  /* always return */
-   }
-   return inst;
-}
-
-
-static struct prog_instruction *
-emit_kill(slang_emit_info *emitInfo)
-{
-   struct gl_fragment_program *fp;
-   struct prog_instruction *inst;
-   /* NV-KILL - discard fragment depending on condition code.
-    * Note that ARB-KILL depends on sign of vector operand.
-    */
-   inst = new_instruction(emitInfo, OPCODE_KIL_NV);
-   if (!inst) {
-      return NULL;
-   }
-   inst->DstReg.CondMask = COND_TR;  /* always kill */
-
-   assert(emitInfo->prog->Target == GL_FRAGMENT_PROGRAM_ARB);
-   fp = (struct gl_fragment_program *) emitInfo->prog;
-   fp->UsesKill = GL_TRUE;
-
-   return inst;
-}
-
-
-static struct prog_instruction *
-emit_tex(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-   gl_inst_opcode opcode;
-   GLboolean shadow = GL_FALSE;
-
-   switch (n->Opcode) {
-   case IR_TEX:
-      opcode = OPCODE_TEX;
-      break;
-   case IR_TEX_SH:
-      opcode = OPCODE_TEX;
-      shadow = GL_TRUE;
-      break;
-   case IR_TEXB:
-      opcode = OPCODE_TXB;
-      break;
-   case IR_TEXB_SH:
-      opcode = OPCODE_TXB;
-      shadow = GL_TRUE;
-      break;
-   case IR_TEXP:
-      opcode = OPCODE_TXP;
-      break;
-   case IR_TEXP_SH:
-      opcode = OPCODE_TXP;
-      shadow = GL_TRUE;
-      break;
-   default:
-      _mesa_problem(NULL, "Bad IR TEX code");
-      return NULL;
-   }
-
-   if (n->Children[0]->Opcode == IR_ELEMENT) {
-      /* array is the sampler (a uniform which'll indicate the texture unit) */
-      assert(n->Children[0]->Children[0]->Store);
-      assert(n->Children[0]->Children[0]->Store->File == PROGRAM_SAMPLER);
-
-      emit(emitInfo, n->Children[0]);
-
-      n->Children[0]->Var = n->Children[0]->Children[0]->Var;
-   } else {
-      /* this is the sampler (a uniform which'll indicate the texture unit) */
-      assert(n->Children[0]->Store);
-      assert(n->Children[0]->Store->File == PROGRAM_SAMPLER);
-   }
-
-   /* emit code for the texcoord operand */
-   (void) emit(emitInfo, n->Children[1]);
-
-   /* alloc storage for result of texture fetch */
-   if (!alloc_node_storage(emitInfo, n, 4))
-      return NULL;
-
-   /* emit TEX instruction;  Child[1] is the texcoord */
-   inst = emit_instruction(emitInfo,
-                           opcode,
-                           n->Store,
-                           n->Children[1]->Store,
-                           NULL,
-                           NULL);
-   if (!inst) {
-      return NULL;
-   }
-
-   inst->TexShadow = shadow;
-
-   /* Store->Index is the uniform/sampler index */
-   assert(n->Children[0]->Store->Index >= 0);
-   inst->TexSrcUnit = n->Children[0]->Store->Index;
-   inst->TexSrcTarget = n->Children[0]->Store->TexTarget;
-
-   /* mark the sampler as being used */
-   _mesa_use_uniform(emitInfo->prog->Parameters,
-                     (char *) n->Children[0]->Var->a_name);
-
-   return inst;
-}
-
-
-/**
- * Assignment/copy
- */
-static struct prog_instruction *
-emit_copy(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-
-   assert(n->Opcode == IR_COPY);
-
-   /* lhs */
-   emit(emitInfo, n->Children[0]);
-   if (!n->Children[0]->Store || n->Children[0]->Store->Index < 0) {
-      /* an error should have been already recorded */
-      return NULL;
-   }
-
-   /* rhs */
-   assert(n->Children[1]);
-   inst = emit(emitInfo, n->Children[1]);
-
-   if (!n->Children[1]->Store || n->Children[1]->Store->Index < 0) {
-      if (!emitInfo->log->text && !emitInfo->UnresolvedFunctions) {
-         /* XXX this error should have been caught in slang_codegen.c */
-         slang_info_log_error(emitInfo->log, "invalid assignment");
-      }
-      return NULL;
-   }
-
-   assert(n->Children[1]->Store->Index >= 0);
-
-   /*assert(n->Children[0]->Store->Size == n->Children[1]->Store->Size);*/
-
-   n->Store = n->Children[0]->Store;
-
-   if (n->Store->File == PROGRAM_SAMPLER) {
-      /* no code generated for sampler assignments,
-       * just copy the sampler index/target at compile time.
-       */
-      n->Store->Index = n->Children[1]->Store->Index;
-      n->Store->TexTarget = n->Children[1]->Store->TexTarget;
-      return NULL;
-   }
-
-#if PEEPHOLE_OPTIMIZATIONS
-   if (inst &&
-       (n->Children[1]->Opcode != IR_SWIZZLE) &&
-       _slang_is_temp(emitInfo->vt, n->Children[1]->Store) &&
-       (inst->DstReg.File == n->Children[1]->Store->File) &&
-       (inst->DstReg.Index == n->Children[1]->Store->Index) &&
-       !n->Children[0]->Store->IsIndirect &&
-       n->Children[0]->Store->Size <= 4) {
-      /* Peephole optimization:
-       * The Right-Hand-Side has its results in a temporary place.
-       * Modify the RHS (and the prev instruction) to store its results
-       * in the destination specified by n->Children[0].
-       * Then, this MOVE is a no-op.
-       * Ex:
-       *   MUL tmp, x, y;
-       *   MOV a, tmp;
-       * becomes:
-       *   MUL a, x, y;
-       */
-
-      /* fixup the previous instruction (which stored the RHS result) */
-      assert(n->Children[0]->Store->Index >= 0);
-      storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store);
-      return inst;
-   }
-   else
-#endif
-   {
-      if (n->Children[0]->Store->Size > 4) {
-         /* move matrix/struct etc (block of registers) */
-         slang_ir_storage dstStore = *n->Children[0]->Store;
-         slang_ir_storage srcStore = *n->Children[1]->Store;
-         GLint size = srcStore.Size;
-         ASSERT(n->Children[1]->Store->Swizzle == SWIZZLE_NOOP);
-         dstStore.Size = 4;
-         srcStore.Size = 4;
-         while (size >= 4) {
-            inst = emit_instruction(emitInfo, OPCODE_MOV,
-                                    &dstStore,
-                                    &srcStore,
-                                    NULL,
-                                    NULL);
-            if (!inst) {
-               return NULL;
-            }
-            inst_comment(inst, "IR_COPY block");
-            srcStore.Index++;
-            dstStore.Index++;
-            size -= 4;
-         }
-      }
-      else {
-         /* single register move */
-         char *srcAnnot, *dstAnnot;
-         assert(n->Children[0]->Store->Index >= 0);
-         inst = emit_instruction(emitInfo, OPCODE_MOV,
-                                 n->Children[0]->Store, /* dest */
-                                 n->Children[1]->Store,
-                                 NULL,
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-         dstAnnot = storage_annotation(n->Children[0], emitInfo->prog);
-         srcAnnot = storage_annotation(n->Children[1], emitInfo->prog);
-         inst->Comment = instruction_annotation(inst->Opcode, dstAnnot,
-                                                srcAnnot, NULL, NULL);
-      }
-      free_node_storage(emitInfo->vt, n->Children[1]);
-      return inst;
-   }
-}
-
-
-/**
- * An IR_COND node wraps a boolean expression which is used by an
- * IF or WHILE test.  This is where we'll set condition codes, if needed.
- */
-static struct prog_instruction *
-emit_cond(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-
-   assert(n->Opcode == IR_COND);
-
-   if (!n->Children[0])
-      return NULL;
-
-   /* emit code for the expression */
-   inst = emit(emitInfo, n->Children[0]);
-
-   if (!n->Children[0]->Store) {
-      /* error recovery */
-      return NULL;
-   }
-
-   assert(n->Children[0]->Store);
-   /*assert(n->Children[0]->Store->Size == 1);*/
-
-   if (emitInfo->EmitCondCodes) {
-      if (inst &&
-          n->Children[0]->Store &&
-          inst->DstReg.File == n->Children[0]->Store->File &&
-          inst->DstReg.Index == n->Children[0]->Store->Index) {
-         /* The previous instruction wrote to the register who's value
-          * we're testing.  Just fix that instruction so that the
-          * condition codes are computed.
-          */
-         inst->CondUpdate = GL_TRUE;
-         n->Store = n->Children[0]->Store;
-         return inst;
-      }
-      else {
-         /* This'll happen for things like "if (i) ..." where no code
-          * is normally generated for the expression "i".
-          * Generate a move instruction just to set condition codes.
-          */
-         if (!alloc_node_storage(emitInfo, n, 1))
-            return NULL;
-         inst = emit_instruction(emitInfo, OPCODE_MOV,
-                                 n->Store, /* dest */
-                                 n->Children[0]->Store,
-                                 NULL,
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-         inst->CondUpdate = GL_TRUE;
-         inst_comment(inst, "COND expr");
-         _slang_free_temp(emitInfo->vt, n->Store);
-         return inst;
-      }
-   }
-   else {
-      /* No-op: the boolean result of the expression is in a regular reg */
-      n->Store = n->Children[0]->Store;
-      return inst;
-   }
-}
-
-
-/**
- * Logical-NOT
- */
-static struct prog_instruction *
-emit_not(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   static const struct {
-      gl_inst_opcode op, opNot;
-   } operators[] = {
-      { OPCODE_SLT, OPCODE_SGE },
-      { OPCODE_SLE, OPCODE_SGT },
-      { OPCODE_SGT, OPCODE_SLE },
-      { OPCODE_SGE, OPCODE_SLT },
-      { OPCODE_SEQ, OPCODE_SNE },
-      { OPCODE_SNE, OPCODE_SEQ },
-      { 0, 0 }
-   };
-   struct prog_instruction *inst;
-   slang_ir_storage zero;
-   GLuint i;
-
-   /* child expr */
-   inst = emit(emitInfo, n->Children[0]);
-
-#if PEEPHOLE_OPTIMIZATIONS
-   if (inst) {
-      /* if the prev instruction was a comparison instruction, invert it */
-      for (i = 0; operators[i].op; i++) {
-         if (inst->Opcode == operators[i].op) {
-            inst->Opcode = operators[i].opNot;
-            n->Store = n->Children[0]->Store;
-            return inst;
-         }
-      }
-   }
-#endif
-
-   /* else, invert using SEQ (v = v == 0) */
-   if (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))
-      return NULL;
-
-   constant_to_storage(emitInfo, 0.0, &zero);
-   inst = emit_instruction(emitInfo,
-                           OPCODE_SEQ,
-                           n->Store,
-                           n->Children[0]->Store,
-                           &zero,
-                           NULL);
-   if (!inst) {
-      return NULL;
-   }
-   inst_comment(inst, "NOT");
-
-   free_node_storage(emitInfo->vt, n->Children[0]);
-
-   return inst;
-}
-
-
-static struct prog_instruction *
-emit_if(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct gl_program *prog = emitInfo->prog;
-   GLuint ifInstLoc, elseInstLoc = 0;
-   GLuint condWritemask = 0;
-
-   /* emit condition expression code */
-   {
-      struct prog_instruction *inst;
-      inst = emit(emitInfo, n->Children[0]);
-      if (emitInfo->EmitCondCodes) {
-         if (!inst) {
-            /* error recovery */
-            return NULL;
-         }
-         condWritemask = inst->DstReg.WriteMask;
-      }
-   }
-
-   if (!n->Children[0]->Store)
-      return NULL;
-
-#if 0
-   assert(n->Children[0]->Store->Size == 1); /* a bool! */
-#endif
-
-   ifInstLoc = prog->NumInstructions;
-   if (emitInfo->EmitHighLevelInstructions) {
-      if (emitInfo->EmitCondCodes) {
-         /* IF condcode THEN ... */
-         struct prog_instruction *ifInst = new_instruction(emitInfo, OPCODE_IF);
-         if (!ifInst) {
-            return NULL;
-         }
-         ifInst->DstReg.CondMask = COND_NE;  /* if cond is non-zero */
-         /* only test the cond code (1 of 4) that was updated by the
-          * previous instruction.
-          */
-         ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
-      }
-      else {
-         struct prog_instruction *inst;
-
-         /* IF src[0] THEN ... */
-         inst = emit_instruction(emitInfo, OPCODE_IF,
-                                 NULL, /* dst */
-                                 n->Children[0]->Store, /* op0 */
-                                 NULL,
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-      }
-   }
-   else {
-      /* conditional jump to else, or endif */
-      struct prog_instruction *ifInst = new_instruction(emitInfo, OPCODE_BRA);
-      if (!ifInst) {
-         return NULL;
-      }
-      ifInst->DstReg.CondMask = COND_EQ;  /* BRA if cond is zero */
-      inst_comment(ifInst, "if zero");
-      ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
-   }
-
-   /* if body */
-   emit(emitInfo, n->Children[1]);
-
-   if (n->Children[2]) {
-      /* have else body */
-      elseInstLoc = prog->NumInstructions;
-      if (emitInfo->EmitHighLevelInstructions) {
-         struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ELSE);
-         if (!inst) {
-            return NULL;
-         }
-         prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions - 1;
-      }
-      else {
-         /* jump to endif instruction */
-         struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_BRA);
-         if (!inst) {
-            return NULL;
-         }
-         inst_comment(inst, "else");
-         inst->DstReg.CondMask = COND_TR;  /* always branch */
-         prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions;
-      }
-      emit(emitInfo, n->Children[2]);
-   }
-   else {
-      /* no else body */
-      prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions;
-   }
-
-   if (emitInfo->EmitHighLevelInstructions) {
-      struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ENDIF);
-      if (!inst) {
-         return NULL;
-      }
-   }
-
-   if (elseInstLoc) {
-      /* point ELSE instruction BranchTarget at ENDIF */
-      if (emitInfo->EmitHighLevelInstructions) {
-         prog->Instructions[elseInstLoc].BranchTarget = prog->NumInstructions - 1;
-      }
-      else {
-         prog->Instructions[elseInstLoc].BranchTarget = prog->NumInstructions;
-      }
-   }
-   return NULL;
-}
-
-
-static struct prog_instruction *
-emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct gl_program *prog = emitInfo->prog;
-   struct prog_instruction *endInst;
-   GLuint beginInstLoc, tailInstLoc, endInstLoc;
-   slang_ir_node *ir;
-
-   /* emit OPCODE_BGNLOOP */
-   beginInstLoc = prog->NumInstructions;
-   if (emitInfo->EmitHighLevelInstructions) {
-      struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_BGNLOOP);
-      if (!inst) {
-         return NULL;
-      }
-   }
-
-   /* body */
-   emit(emitInfo, n->Children[0]);
-
-   /* tail */
-   tailInstLoc = prog->NumInstructions;
-   if (n->Children[1]) {
-      if (emitInfo->EmitComments)
-         emit_comment(emitInfo, "Loop tail code:");
-      emit(emitInfo, n->Children[1]);
-   }
-
-   endInstLoc = prog->NumInstructions;
-   if (emitInfo->EmitHighLevelInstructions) {
-      /* emit OPCODE_ENDLOOP */
-      endInst = new_instruction(emitInfo, OPCODE_ENDLOOP);
-      if (!endInst) {
-         return NULL;
-      }
-   }
-   else {
-      /* emit unconditional BRA-nch */
-      endInst = new_instruction(emitInfo, OPCODE_BRA);
-      if (!endInst) {
-         return NULL;
-      }
-      endInst->DstReg.CondMask = COND_TR;  /* always true */
-   }
-   /* ENDLOOP's BranchTarget points to the BGNLOOP inst */
-   endInst->BranchTarget = beginInstLoc;
-
-   if (emitInfo->EmitHighLevelInstructions) {
-      /* BGNLOOP's BranchTarget points to the ENDLOOP inst */
-      prog->Instructions[beginInstLoc].BranchTarget = prog->NumInstructions -1;
-   }
-
-   /* Done emitting loop code.  Now walk over the loop's linked list of
-    * BREAK and CONT nodes, filling in their BranchTarget fields (which
-    * will point to the corresponding ENDLOOP instruction.
-    */
-   for (ir = n->List; ir; ir = ir->List) {
-      struct prog_instruction *inst = prog->Instructions + ir->InstLocation;
-      assert(inst->BranchTarget < 0);
-      if (ir->Opcode == IR_BREAK ||
-          ir->Opcode == IR_BREAK_IF_TRUE) {
-         assert(inst->Opcode == OPCODE_BRK ||
-                inst->Opcode == OPCODE_BRA);
-         /* go to instruction at end of loop */
-         if (emitInfo->EmitHighLevelInstructions) {
-            inst->BranchTarget = endInstLoc;
-         }
-         else {
-            inst->BranchTarget = endInstLoc + 1;
-         }
-      }
-      else {
-         assert(ir->Opcode == IR_CONT ||
-                ir->Opcode == IR_CONT_IF_TRUE);
-         assert(inst->Opcode == OPCODE_CONT ||
-                inst->Opcode == OPCODE_BRA);
-         /* go to instruction at tail of loop */
-         inst->BranchTarget = endInstLoc;
-      }
-   }
-   return NULL;
-}
-
-
-/**
- * Unconditional "continue" or "break" statement.
- * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted.
- */
-static struct prog_instruction *
-emit_cont_break(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   gl_inst_opcode opcode;
-   struct prog_instruction *inst;
-
-   if (n->Opcode == IR_CONT) {
-      /* we need to execute the loop's tail code before doing CONT */
-      assert(n->Parent);
-      assert(n->Parent->Opcode == IR_LOOP);
-      if (n->Parent->Children[1]) {
-         /* emit tail code */
-         if (emitInfo->EmitComments) {
-            emit_comment(emitInfo, "continue - tail code:");
-         }
-         emit(emitInfo, n->Parent->Children[1]);
-      }
-   }
-
-   /* opcode selection */
-   if (emitInfo->EmitHighLevelInstructions) {
-      opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
-   }
-   else {
-      opcode = OPCODE_BRA;
-   }
-   n->InstLocation = emitInfo->prog->NumInstructions;
-   inst = new_instruction(emitInfo, opcode);
-   if (inst) {
-      inst->DstReg.CondMask = COND_TR;  /* always true */
-   }
-   return inst;
-}
-
-
-/**
- * Conditional "continue" or "break" statement.
- * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted.
- */
-static struct prog_instruction *
-emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-
-   assert(n->Opcode == IR_CONT_IF_TRUE ||
-          n->Opcode == IR_BREAK_IF_TRUE);
-
-   /* evaluate condition expr, setting cond codes */
-   inst = emit(emitInfo, n->Children[0]);
-   if (emitInfo->EmitCondCodes) {
-      assert(inst);
-      inst->CondUpdate = GL_TRUE;
-   }
-
-   n->InstLocation = emitInfo->prog->NumInstructions;
-
-   /* opcode selection */
-   if (emitInfo->EmitHighLevelInstructions) {
-      const gl_inst_opcode opcode
-         = (n->Opcode == IR_CONT_IF_TRUE) ? OPCODE_CONT : OPCODE_BRK;
-      if (emitInfo->EmitCondCodes) {
-         /* Get the writemask from the previous instruction which set
-          * the condcodes.  Use that writemask as the CondSwizzle.
-          */
-         const GLuint condWritemask = inst->DstReg.WriteMask;
-         inst = new_instruction(emitInfo, opcode);
-         if (inst) {
-            inst->DstReg.CondMask = COND_NE;
-            inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
-         }
-         return inst;
-      }
-      else {
-         /* IF reg
-          *    BRK/CONT;
-          * ENDIF
-          */
-         GLint ifInstLoc;
-         ifInstLoc = emitInfo->prog->NumInstructions;
-         inst = emit_instruction(emitInfo, OPCODE_IF,
-                                 NULL, /* dest */
-                                 n->Children[0]->Store,
-                                 NULL,
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-         n->InstLocation = emitInfo->prog->NumInstructions;
-
-         inst = new_instruction(emitInfo, opcode);
-         if (!inst) {
-            return NULL;
-         }
-         inst = new_instruction(emitInfo, OPCODE_ENDIF);
-         if (!inst) {
-            return NULL;
-         }
-
-         emitInfo->prog->Instructions[ifInstLoc].BranchTarget
-            = emitInfo->prog->NumInstructions - 1;
-         return inst;
-      }
-   }
-   else {
-      const GLuint condWritemask = inst->DstReg.WriteMask;
-      assert(emitInfo->EmitCondCodes);
-      inst = new_instruction(emitInfo, OPCODE_BRA);
-      if (inst) {
-         inst->DstReg.CondMask = COND_NE;
-         inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
-      }
-      return inst;
-   }
-}
-
-
-/**
- * Return the size of a swizzle mask given that some swizzle components
- * may be NIL/undefined.  For example:
- *  swizzle_size(".zzxx") = 4
- *  swizzle_size(".xy??") = 2
- *  swizzle_size(".w???") = 1
- */
-static GLuint
-swizzle_size(GLuint swizzle)
-{
-   GLuint i;
-   for (i = 0; i < 4; i++) {
-      if (GET_SWZ(swizzle, i) == SWIZZLE_NIL)
-         return i;
-   }
-   return 4;
-}
-
-
-static struct prog_instruction *
-emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-
-   inst = emit(emitInfo, n->Children[0]);
-
-   if (!n->Store->Parent) {
-      /* this covers a case such as "(b ? p : q).x" */
-      n->Store->Parent = n->Children[0]->Store;
-      assert(n->Store->Parent);
-   }
-
-   {
-      const GLuint swizzle = n->Store->Swizzle;
-      /* new storage is parent storage with updated Swizzle + Size fields */
-      _slang_copy_ir_storage(n->Store, n->Store->Parent);
-      /* Apply this node's swizzle to parent's storage */
-      n->Store->Swizzle = _slang_swizzle_swizzle(n->Store->Swizzle, swizzle);
-      /* Update size */
-      n->Store->Size = swizzle_size(n->Store->Swizzle);
-   }
-
-   assert(!n->Store->Parent);
-   assert(n->Store->Index >= 0);
-
-   return inst;
-}
-
-
-/**
- * Dereference array element:  element == array[index]
- * This basically involves emitting code for computing the array index
- * and updating the node/element's storage info.
- */
-static struct prog_instruction *
-emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   slang_ir_storage *arrayStore, *indexStore;
-   const int elemSize = n->Store->Size;           /* number of floats */
-   const GLint elemSizeVec = (elemSize + 3) / 4;  /* number of vec4 */
-   struct prog_instruction *inst;
-
-   assert(n->Opcode == IR_ELEMENT);
-   assert(elemSize > 0);
-
-   /* special case for built-in state variables, like light state */
-   {
-      slang_ir_storage *root = n->Store;
-      assert(!root->Parent);
-      while (root->Parent)
-         root = root->Parent;
-
-      if (root->File == PROGRAM_STATE_VAR) {
-         GLboolean direct;
-         GLint index =
-            _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct);
-         if (index < 0) {
-            /* error */
-            return NULL;
-         }
-         if (direct) {
-            n->Store->Index = index;
-            return NULL; /* all done */
-         }
-      }
-   }
-
-   /* do codegen for array itself */
-   emit(emitInfo, n->Children[0]);
-   arrayStore = n->Children[0]->Store;
-
-   /* The initial array element storage is the array's storage,
-    * then modified below.
-    */
-   _slang_copy_ir_storage(n->Store, arrayStore);
-
-
-   if (n->Children[1]->Opcode == IR_FLOAT) {
-      /* Constant array index */
-      const GLint element = (GLint) n->Children[1]->Value[0];
-
-      /* this element's storage is the array's storage, plus constant offset */
-      n->Store->Index += elemSizeVec * element;
-   }
-   else {
-      /* Variable array index */
-
-      /* do codegen for array index expression */
-      emit(emitInfo, n->Children[1]);
-      indexStore = n->Children[1]->Store;
-
-      if (indexStore->IsIndirect) {
-         /* need to put the array index into a temporary since we can't
-          * directly support a[b[i]] constructs.
-          */
-
-
-         /*indexStore = tempstore();*/
-      }
-
-
-      if (elemSize > 4) {
-         /* need to multiply array index by array element size */
-         struct prog_instruction *inst;
-         slang_ir_storage *indexTemp;
-         slang_ir_storage elemSizeStore;
-
-         /* allocate 1 float indexTemp */
-         indexTemp = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
-         _slang_alloc_temp(emitInfo->vt, indexTemp);
-
-         /* allocate a constant containing the element size */
-         constant_to_storage(emitInfo, (float) elemSizeVec, &elemSizeStore);
-
-         /* multiply array index by element size */
-         inst = emit_instruction(emitInfo,
-                                 OPCODE_MUL,
-                                 indexTemp, /* dest */
-                                 indexStore, /* the index */
-                                 &elemSizeStore,
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-
-         indexStore = indexTemp;
-      }
-
-      if (arrayStore->IsIndirect) {
-         /* ex: in a[i][j], a[i] (the arrayStore) is indirect */
-         /* Need to add indexStore to arrayStore->Indirect store */
-         slang_ir_storage indirectArray;
-         slang_ir_storage *indexTemp;
-
-         _slang_init_ir_storage(&indirectArray,
-                                arrayStore->IndirectFile,
-                                arrayStore->IndirectIndex,
-                                1,
-                                arrayStore->IndirectSwizzle);
-
-         /* allocate 1 float indexTemp */
-         indexTemp = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
-         _slang_alloc_temp(emitInfo->vt, indexTemp);
-
-         inst = emit_instruction(emitInfo,
-                                 OPCODE_ADD,
-                                 indexTemp,      /* dest */
-                                 indexStore,     /* the index */
-                                 &indirectArray, /* indirect array base */
-                                 NULL);
-         if (!inst) {
-            return NULL;
-         }
-
-         indexStore = indexTemp;
-      }
-
-      /* update the array element storage info */
-      n->Store->IsIndirect = GL_TRUE;
-      n->Store->IndirectFile = indexStore->File;
-      n->Store->IndirectIndex = indexStore->Index;
-      n->Store->IndirectSwizzle = indexStore->Swizzle;
-   }
-
-   n->Store->Size = elemSize;
-   n->Store->Swizzle = _slang_var_swizzle(elemSize, 0);
-
-   return NULL; /* no instruction */
-}
-
-
-/**
- * Resolve storage for accessing a structure field.
- */
-static struct prog_instruction *
-emit_struct_field(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   slang_ir_storage *root = n->Store;
-   GLint fieldOffset, fieldSize;
-
-   assert(n->Opcode == IR_FIELD);
-
-   assert(!root->Parent);
-   while (root->Parent)
-      root = root->Parent;
-
-   /* If this is the field of a state var, allocate constant/uniform
-    * storage for it now if we haven't already.
-    * Note that we allocate storage (uniform/constant slots) for state
-    * variables here rather than at declaration time so we only allocate
-    * space for the ones that we actually use!
-    */
-   if (root->File == PROGRAM_STATE_VAR) {
-      GLboolean direct;
-      GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct);
-      if (index < 0) {
-         slang_info_log_error(emitInfo->log, "Error parsing state variable");
-         return NULL;
-      }
-      if (direct) {
-         root->Index = index;
-         return NULL; /* all done */
-      }
-   }
-
-   /* do codegen for struct */
-   emit(emitInfo, n->Children[0]);
-   assert(n->Children[0]->Store->Index >= 0);
-
-
-   fieldOffset = n->Store->Index;
-   fieldSize = n->Store->Size;
-
-   _slang_copy_ir_storage(n->Store, n->Children[0]->Store);
-
-   n->Store->Index = n->Children[0]->Store->Index + fieldOffset / 4;
-   n->Store->Size = fieldSize;
-
-   switch (fieldSize) {
-   case 1:
-      {
-         GLint swz = fieldOffset % 4;
-         n->Store->Swizzle = MAKE_SWIZZLE4(swz, swz, swz, swz);
-      }
-      break;
-   case 2:
-      n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
-                                        SWIZZLE_NIL, SWIZZLE_NIL);
-      break;
-   case 3:
-      n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
-                                        SWIZZLE_Z, SWIZZLE_NIL);
-      break;
-   default:
-      n->Store->Swizzle = SWIZZLE_XYZW;
-   }
-
-   assert(n->Store->Index >= 0);
-
-   return NULL; /* no instruction */
-}
-
-
-/**
- * Emit code for a variable declaration.
- * This usually doesn't result in any code generation, but just
- * memory allocation.
- */
-static struct prog_instruction *
-emit_var_decl(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   assert(n->Store);
-   assert(n->Store->File != PROGRAM_UNDEFINED);
-   assert(n->Store->Size > 0);
-   /*assert(n->Store->Index < 0);*/
-
-   if (!n->Var || n->Var->isTemp) {
-      /* a nameless/temporary variable, will be freed after first use */
-      /*NEW*/
-      if (n->Store->Index < 0 && !_slang_alloc_temp(emitInfo->vt, n->Store)) {
-         slang_info_log_error(emitInfo->log,
-                              "Ran out of registers, too many temporaries");
-         return NULL;
-      }
-   }
-   else {
-      /* a regular variable */
-      _slang_add_variable(emitInfo->vt, n->Var);
-      if (!_slang_alloc_var(emitInfo->vt, n->Store)) {
-         slang_info_log_error(emitInfo->log,
-                              "Ran out of registers, too many variables");
-         return NULL;
-      }
-      /*
-        printf("IR_VAR_DECL %s %d store %p\n",
-        (char*) n->Var->a_name, n->Store->Index, (void*) n->Store);
-      */
-      assert(n->Var->store == n->Store);
-   }
-   if (emitInfo->EmitComments) {
-      /* emit NOP with comment describing the variable's storage location */
-      char s[1000];
-      _mesa_snprintf(s, sizeof(s), "TEMP[%d]%s = variable %s (size %d)",
-                     n->Store->Index,
-                     _mesa_swizzle_string(n->Store->Swizzle, 0, GL_FALSE), 
-                     (n->Var ? (char *) n->Var->a_name : "anonymous"),
-                     n->Store->Size);
-      emit_comment(emitInfo, s);
-   }
-   return NULL;
-}
-
-
-/**
- * Emit code for a reference to a variable.
- * Actually, no code is generated but we may do some memory allocation.
- * In particular, state vars (uniforms) are allocated on an as-needed basis.
- */
-static struct prog_instruction *
-emit_var_ref(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   assert(n->Store);
-   assert(n->Store->File != PROGRAM_UNDEFINED);
-
-   if (n->Store->File == PROGRAM_STATE_VAR && n->Store->Index < 0) {
-      GLboolean direct;
-      GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct);
-      if (index < 0) {
-         /* error */
-         char s[100];
-         /* XXX isn't this really an out of memory/resources error? */
-         _mesa_snprintf(s, sizeof(s), "Undefined variable '%s'",
-                 (char *) n->Var->a_name);
-         slang_info_log_error(emitInfo->log, s);
-         return NULL;
-      }
-
-      n->Store->Index = index;
-   }
-   else if (n->Store->File == PROGRAM_UNIFORM ||
-            n->Store->File == PROGRAM_SAMPLER) {
-      /* mark var as used */
-      _mesa_use_uniform(emitInfo->prog->Parameters, (char *) n->Var->a_name);
-   }
-   else if (n->Store->File == PROGRAM_INPUT) {
-      assert(n->Store->Index >= 0);
-      /* geometry shaders have the input index in the second
-       * index */
-      if (emitInfo->prog->Target == MESA_GEOMETRY_PROGRAM &&
-          n->Store->Is2D) {
-         emitInfo->prog->InputsRead |= (1 << n->Store->Index2);
-      } else
-         emitInfo->prog->InputsRead |= (1 << n->Store->Index);
-   }
-
-   if (n->Store->Index < 0) {
-      /* probably ran out of registers */
-      return NULL;
-   }
-   assert(n->Store->Size > 0);
-
-   return NULL;
-}
-
-
-static struct prog_instruction *
-emit(slang_emit_info *emitInfo, slang_ir_node *n)
-{
-   struct prog_instruction *inst;
-   if (!n)
-      return NULL;
-
-   if (emitInfo->log->error_flag) {
-      return NULL;
-   }
-
-   if (n->Comment) {
-      inst = new_instruction(emitInfo, OPCODE_NOP);
-      if (inst) {
-         inst->Comment = _mesa_strdup(n->Comment);
-      }
-      inst = NULL;
-   }
-
-   switch (n->Opcode) {
-   case IR_SEQ:
-      /* sequence of two sub-trees */
-      assert(n->Children[0]);
-      assert(n->Children[1]);
-      emit(emitInfo, n->Children[0]);
-      if (emitInfo->log->error_flag)
-         return NULL;
-      inst = emit(emitInfo, n->Children[1]);
-#if 0
-      assert(!n->Store);
-#endif
-      if (n->Children[1]->Store)
-         n->Store = n->Children[1]->Store;
-      else
-         n->Store = n->Children[0]->Store;
-      return inst;
-
-   case IR_SCOPE:
-      /* new variable scope */
-      _slang_push_var_table(emitInfo->vt);
-      inst = emit(emitInfo, n->Children[0]);
-      _slang_pop_var_table(emitInfo->vt);
-      n->Store = n->Children[0]->Store;
-      return inst;
-
-   case IR_VAR_DECL:
-      /* Variable declaration - allocate a register for it */
-      inst = emit_var_decl(emitInfo, n);
-      return inst;
-
-   case IR_VAR:
-      /* Reference to a variable
-       * Storage should have already been resolved/allocated.
-       */
-      return emit_var_ref(emitInfo, n);
-
-   case IR_ELEMENT:
-      return emit_array_element(emitInfo, n);
-   case IR_FIELD:
-      return emit_struct_field(emitInfo, n);
-   case IR_SWIZZLE:
-      return emit_swizzle(emitInfo, n);
-
-   /* Simple arithmetic */
-   /* unary */
-   case IR_MOVE:
-   case IR_RSQ:
-   case IR_RCP:
-   case IR_FLOOR:
-   case IR_FRAC:
-   case IR_F_TO_I:
-   case IR_I_TO_F:
-   case IR_ABS:
-   case IR_SIN:
-   case IR_COS:
-   case IR_DDX:
-   case IR_DDY:
-   case IR_EXP:
-   case IR_EXP2:
-   case IR_LOG2:
-   case IR_NOISE1:
-   case IR_NOISE2:
-   case IR_NOISE3:
-   case IR_NOISE4:
-   case IR_NRM4:
-   case IR_NRM3:
-   /* binary */
-   case IR_ADD:
-   case IR_SUB:
-   case IR_MUL:
-   case IR_DOT4:
-   case IR_DOT3:
-   case IR_DOT2:
-   case IR_CROSS:
-   case IR_MIN:
-   case IR_MAX:
-   case IR_SEQUAL:
-   case IR_SNEQUAL:
-   case IR_SGE:
-   case IR_SGT:
-   case IR_SLE:
-   case IR_SLT:
-   case IR_POW:
-   /* trinary operators */
-   case IR_LRP:
-   case IR_CMP:
-      return emit_arith(emitInfo, n);
-
-   case IR_EQUAL:
-   case IR_NOTEQUAL:
-      return emit_compare(emitInfo, n);
-
-   case IR_CLAMP:
-      return emit_clamp(emitInfo, n);
-   case IR_TEX:
-   case IR_TEXB:
-   case IR_TEXP:
-   case IR_TEX_SH:
-   case IR_TEXB_SH:
-   case IR_TEXP_SH:
-      return emit_tex(emitInfo, n);
-   case IR_NEG:
-      return emit_negation(emitInfo, n);
-   case IR_FLOAT:
-      /* find storage location for this float constant */
-      n->Store->Index = _mesa_add_unnamed_constant(emitInfo->prog->Parameters,
-                                                   n->Value,
-                                                   n->Store->Size,
-                                                   &n->Store->Swizzle);
-      if (n->Store->Index < 0) {
-         slang_info_log_error(emitInfo->log, "Ran out of space for constants");
-         return NULL;
-      }
-      return NULL;
-
-   case IR_COPY:
-      return emit_copy(emitInfo, n);
-
-   case IR_COND:
-      return emit_cond(emitInfo, n);
-
-   case IR_NOT:
-      return emit_not(emitInfo, n);
-
-   case IR_LABEL:
-      return emit_label(emitInfo, n);
-
-   case IR_KILL:
-      return emit_kill(emitInfo);
-
-   case IR_CALL:
-      /* new variable scope for subroutines/function calls */
-      _slang_push_var_table(emitInfo->vt);
-      inst = emit_fcall(emitInfo, n);
-      _slang_pop_var_table(emitInfo->vt);
-      return inst;
-
-   case IR_IF:
-      return emit_if(emitInfo, n);
-
-   case IR_LOOP:
-      return emit_loop(emitInfo, n);
-   case IR_BREAK_IF_TRUE:
-   case IR_CONT_IF_TRUE:
-      return emit_cont_break_if_true(emitInfo, n);
-   case IR_BREAK:
-      /* fall-through */
-   case IR_CONT:
-      return emit_cont_break(emitInfo, n);
-
-   case IR_BEGIN_SUB:
-      return new_instruction(emitInfo, OPCODE_BGNSUB);
-   case IR_END_SUB:
-      return new_instruction(emitInfo, OPCODE_ENDSUB);
-   case IR_RETURN:
-      return emit_return(emitInfo, n);
-
-   case IR_NOP:
-      return NULL;
-
-   case IR_EMIT_VERTEX:
-      return new_instruction(emitInfo, OPCODE_EMIT_VERTEX);
-   case IR_END_PRIMITIVE:
-      return new_instruction(emitInfo, OPCODE_END_PRIMITIVE);
-
-   default:
-      _mesa_problem(NULL, "Unexpected IR opcode in emit()\n");
-   }
-   return NULL;
-}
-
-
-/**
- * After code generation, any subroutines will be in separate program
- * objects.  This function appends all the subroutines onto the main
- * program and resolves the linking of all the branch/call instructions.
- * XXX this logic should really be part of the linking process...
- */
-static void
-_slang_resolve_subroutines(slang_emit_info *emitInfo)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_program *mainP = emitInfo->prog;
-   GLuint *subroutineLoc, i, total;
-
-   subroutineLoc
-      = (GLuint *) malloc(emitInfo->NumSubroutines * sizeof(GLuint));
-
-   /* total number of instructions */
-   total = mainP->NumInstructions;
-   for (i = 0; i < emitInfo->NumSubroutines; i++) {
-      subroutineLoc[i] = total;
-      total += emitInfo->Subroutines[i]->NumInstructions;
-   }
-
-   /* adjust BranchTargets within the functions */
-   for (i = 0; i < emitInfo->NumSubroutines; i++) {
-      struct gl_program *sub = emitInfo->Subroutines[i];
-      GLuint j;
-      for (j = 0; j < sub->NumInstructions; j++) {
-         struct prog_instruction *inst = sub->Instructions + j;
-         if (inst->Opcode != OPCODE_CAL && inst->BranchTarget >= 0) {
-            inst->BranchTarget += subroutineLoc[i];
-         }
-      }
-   }
-
-   /* append subroutines' instructions after main's instructions */
-   mainP->Instructions = _mesa_realloc_instructions(mainP->Instructions,
-                                                    mainP->NumInstructions,
-                                                    total);
-   mainP->NumInstructions = total;
-   for (i = 0; i < emitInfo->NumSubroutines; i++) {
-      struct gl_program *sub = emitInfo->Subroutines[i];
-      _mesa_copy_instructions(mainP->Instructions + subroutineLoc[i],
-                              sub->Instructions,
-                              sub->NumInstructions);
-      /* delete subroutine code */
-      sub->Parameters = NULL; /* prevent double-free */
-      _mesa_reference_program(ctx, &emitInfo->Subroutines[i], NULL);
-   }
-
-   /* free subroutine list */
-   if (emitInfo->Subroutines) {
-      free(emitInfo->Subroutines);
-      emitInfo->Subroutines = NULL;
-   }
-   emitInfo->NumSubroutines = 0;
-
-   /* Examine CAL instructions.
-    * At this point, the BranchTarget field of the CAL instruction is
-    * the number/id of the subroutine to call (an index into the
-    * emitInfo->Subroutines list).
-    * Translate that into an actual instruction location now.
-    */
-   for (i = 0; i < mainP->NumInstructions; i++) {
-      struct prog_instruction *inst = mainP->Instructions + i;
-      if (inst->Opcode == OPCODE_CAL) {
-         const GLuint f = inst->BranchTarget;
-         inst->BranchTarget = subroutineLoc[f];
-      }
-   }
-
-   free(subroutineLoc);
-}
-
-
-
-/**
- * Convert the IR tree into GPU instructions.
- * \param n  root of IR tree
- * \param vt  variable table
- * \param prog  program to put GPU instructions into
- * \param pragmas  controls codegen options
- * \param withEnd  if true, emit END opcode at end
- * \param log  log for emitting errors/warnings/info
- */
-GLboolean
-_slang_emit_code(slang_ir_node *n, slang_var_table *vt,
-                 struct gl_program *prog,
-                 const struct gl_sl_pragmas *pragmas,
-                 GLboolean withEnd,
-                 slang_info_log *log)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   GLboolean success;
-   slang_emit_info emitInfo;
-   GLuint maxUniforms;
-
-   emitInfo.log = log;
-   emitInfo.vt = vt;
-   emitInfo.prog = prog;
-   emitInfo.Subroutines = NULL;
-   emitInfo.NumSubroutines = 0;
-   emitInfo.MaxInstructions = prog->NumInstructions;
-
-   emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;
-   emitInfo.EmitCondCodes = ctx->Shader.EmitCondCodes;
-   emitInfo.EmitComments = ctx->Shader.EmitComments || pragmas->Debug;
-   emitInfo.EmitBeginEndSub = GL_TRUE;
-
-   if (!emitInfo.EmitCondCodes) {
-      emitInfo.EmitHighLevelInstructions = GL_TRUE;
-   }      
-
-   /* Check uniform/constant limits */
-   if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
-      maxUniforms = ctx->Const.FragmentProgram.MaxUniformComponents / 4;
-   }
-   else if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
-      maxUniforms = ctx->Const.VertexProgram.MaxUniformComponents / 4;
-   } else {
-      assert(prog->Target == MESA_GEOMETRY_PROGRAM);
-      maxUniforms = ctx->Const.GeometryProgram.MaxUniformComponents / 4;
-   }
-   if (prog->Parameters->NumParameters > maxUniforms) {
-      slang_info_log_error(log, "Constant/uniform register limit exceeded "
-                           "(max=%u vec4)", maxUniforms);
-
-      return GL_FALSE;
-   }
-
-   (void) emit(&emitInfo, n);
-
-   /* finish up by adding the END opcode to program */
-   if (withEnd) {
-      struct prog_instruction *inst;
-      inst = new_instruction(&emitInfo, OPCODE_END);
-      if (!inst) {
-         return GL_FALSE;
-      }
-   }
-
-   _slang_resolve_subroutines(&emitInfo);
-
-   success = GL_TRUE;
-
-#if 0
-   printf("*********** End emit code (%u inst):\n", prog->NumInstructions);
-   _mesa_print_program(prog);
-   _mesa_print_program_parameters(ctx,prog);
-#endif
-
-   return success;
-}
diff --git a/src/mesa/slang/slang_emit.h b/src/mesa/slang/slang_emit.h
deleted file mode 100644 (file)
index f93d6b0..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.1
- *
- * Copyright (C) 2005-2008  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_EMIT_H
-#define SLANG_EMIT_H
-
-#include "main/glheader.h"
-#include "slang_ir.h"
-#include "slang_vartable.h"
-
-
-extern GLuint
-_slang_swizzle_swizzle(GLuint swz1, GLuint swz2);
-
-
-extern GLuint
-_slang_var_swizzle(GLint size, GLint comp);
-
-
-extern GLboolean
-_slang_emit_code(slang_ir_node *n, slang_var_table *vartable,
-                 struct gl_program *prog,
-                 const struct gl_sl_pragmas *pragmas,
-                 GLboolean withEnd,
-                 slang_info_log *log);
-
-
-#endif /* SLANG_EMIT_H */
diff --git a/src/mesa/slang/slang_ir.c b/src/mesa/slang/slang_ir.c
deleted file mode 100644 (file)
index 078c936..0000000
+++ /dev/null
@@ -1,534 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
- * Copyright (C) 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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "slang_ir.h"
-#include "slang_mem.h"
-#include "program/prog_instruction.h"
-#include "program/prog_print.h"
-
-
-static const slang_ir_info IrInfo[] = {
-   /* binary ops */
-   { IR_ADD, "IR_ADD", OPCODE_ADD, 4, 2 },
-   { IR_SUB, "IR_SUB", OPCODE_SUB, 4, 2 },
-   { IR_MUL, "IR_MUL", OPCODE_MUL, 4, 2 },
-   { IR_DIV, "IR_DIV", OPCODE_NOP, 0, 2 }, /* XXX broke */
-   { IR_DOT4, "IR_DOT4", OPCODE_DP4, 1, 2 },
-   { IR_DOT3, "IR_DOT3", OPCODE_DP3, 1, 2 },
-   { IR_DOT2, "IR_DOT2", OPCODE_DP2, 1, 2 },
-   { IR_NRM4, "IR_NRM4", OPCODE_NRM4, 1, 1 },
-   { IR_NRM3, "IR_NRM3", OPCODE_NRM3, 1, 1 },
-   { IR_CROSS, "IR_CROSS", OPCODE_XPD, 3, 2 },
-   { IR_LRP, "IR_LRP", OPCODE_LRP, 4, 3 },
-   { IR_MIN, "IR_MIN", OPCODE_MIN, 4, 2 },
-   { IR_MAX, "IR_MAX", OPCODE_MAX, 4, 2 },
-   { IR_CLAMP, "IR_CLAMP", OPCODE_NOP, 4, 3 }, /* special case: emit_clamp() */
-   { IR_SEQUAL, "IR_SEQUAL", OPCODE_SEQ, 4, 2 },
-   { IR_SNEQUAL, "IR_SNEQUAL", OPCODE_SNE, 4, 2 },
-   { IR_SGE, "IR_SGE", OPCODE_SGE, 4, 2 },
-   { IR_SGT, "IR_SGT", OPCODE_SGT, 4, 2 },
-   { IR_SLE, "IR_SLE", OPCODE_SLE, 4, 2 },
-   { IR_SLT, "IR_SLT", OPCODE_SLT, 4, 2 },
-   { IR_POW, "IR_POW", OPCODE_POW, 1, 2 },
-   { IR_EQUAL, "IR_EQUAL", OPCODE_NOP, 1, 2 },
-   { IR_NOTEQUAL, "IR_NOTEQUAL", OPCODE_NOP, 1, 2 },
-
-   /* unary ops */
-   { IR_MOVE, "IR_MOVE", OPCODE_MOV, 4, 1 },
-   { IR_I_TO_F, "IR_I_TO_F", OPCODE_MOV, 4, 1 },  /* int[4] to float[4] */
-   { IR_F_TO_I, "IR_F_TO_I", OPCODE_TRUNC, 4, 1 },
-   { IR_EXP, "IR_EXP", OPCODE_EXP, 1, 1 },
-   { IR_EXP2, "IR_EXP2", OPCODE_EX2, 1, 1 },
-   { IR_LOG2, "IR_LOG2", OPCODE_LG2, 1, 1 },
-   { IR_RSQ, "IR_RSQ", OPCODE_RSQ, 1, 1 },
-   { IR_RCP, "IR_RCP", OPCODE_RCP, 1, 1 },
-   { IR_FLOOR, "IR_FLOOR", OPCODE_FLR, 4, 1 },
-   { IR_FRAC, "IR_FRAC", OPCODE_FRC, 4, 1 },
-   { IR_ABS, "IR_ABS", OPCODE_ABS, 4, 1 },
-   { IR_NEG, "IR_NEG", OPCODE_NOP, 4, 1 }, /* special case: emit_negation() */
-   { IR_DDX, "IR_DDX", OPCODE_DDX, 4, 1 },
-   { IR_DDY, "IR_DDY", OPCODE_DDY, 4, 1 },
-   { IR_SIN, "IR_SIN", OPCODE_SIN, 1, 1 },
-   { IR_COS, "IR_COS", OPCODE_COS, 1, 1 },
-   { IR_NOISE1, "IR_NOISE1", OPCODE_NOISE1, 1, 1 },
-   { IR_NOISE2, "IR_NOISE2", OPCODE_NOISE2, 1, 1 },
-   { IR_NOISE3, "IR_NOISE3", OPCODE_NOISE3, 1, 1 },
-   { IR_NOISE4, "IR_NOISE4", OPCODE_NOISE4, 1, 1 },
-
-   /* other */
-   { IR_CMP, "IR_CMP", OPCODE_CMP, 4, 3 },  /* compare/select */
-   { IR_SEQ, "IR_SEQ", OPCODE_NOP, 0, 0 },
-   { IR_SCOPE, "IR_SCOPE", OPCODE_NOP, 0, 0 },
-   { IR_LABEL, "IR_LABEL", OPCODE_NOP, 0, 0 },
-   { IR_IF, "IR_IF", OPCODE_NOP, 0, 0 },
-   { IR_KILL, "IR_KILL", OPCODE_NOP, 0, 0 },
-   { IR_COND, "IR_COND", OPCODE_NOP, 0, 0 },
-   { IR_CALL, "IR_CALL", OPCODE_NOP, 0, 0 },
-   { IR_COPY, "IR_COPY", OPCODE_NOP, 0, 1 },
-   { IR_NOT, "IR_NOT", OPCODE_NOP, 1, 1 },
-   { IR_VAR, "IR_VAR", OPCODE_NOP, 0, 0 },
-   { IR_VAR_DECL, "IR_VAR_DECL", OPCODE_NOP, 0, 0 },
-   { IR_TEX, "IR_TEX", OPCODE_TEX, 4, 1 },
-   { IR_TEXB, "IR_TEXB", OPCODE_TXB, 4, 1 },
-   { IR_TEXP, "IR_TEXP", OPCODE_TXP, 4, 1 },
-   { IR_TEX_SH, "IR_TEX_SH", OPCODE_TEX, 4, 1 },
-   { IR_TEXB_SH, "IR_TEXB_SH", OPCODE_TXB, 4, 1 },
-   { IR_TEXP_SH, "IR_TEXP_SH", OPCODE_TXP, 4, 1 },
-   { IR_FLOAT, "IR_FLOAT", OPCODE_NOP, 0, 0 }, /* float literal */
-   { IR_FIELD, "IR_FIELD", OPCODE_NOP, 0, 0 },
-   { IR_ELEMENT, "IR_ELEMENT", OPCODE_NOP, 0, 0 },
-   { IR_SWIZZLE, "IR_SWIZZLE", OPCODE_NOP, 0, 0 },
-   { IR_NOP, "IR_NOP", OPCODE_NOP, 0, 0 },
-   { IR_EMIT_VERTEX, "IR_EMIT_VERTEX", OPCODE_EMIT_VERTEX, 0, 0 },
-   { IR_END_PRIMITIVE, "IR_END_PRIMITIVE", OPCODE_END_PRIMITIVE, 0, 0 },
-   { 0, NULL, 0, 0, 0 }
-};
-
-
-const slang_ir_info *
-_slang_ir_info(slang_ir_opcode opcode)
-{
-   GLuint i;
-   for (i = 0; IrInfo[i].IrName; i++) {
-      if (IrInfo[i].IrOpcode == opcode) {
-        return IrInfo + i;
-      }
-   }
-   return NULL;
-}
-
-
-void
-_slang_init_ir_storage(slang_ir_storage *st,
-                       gl_register_file file, GLint index, GLint size,
-                       GLuint swizzle)
-{
-   st->File = file;
-   st->Index = index;
-   st->Size = size;
-   st->Swizzle = swizzle;
-   st->Parent = NULL;
-   st->IsIndirect = GL_FALSE;
-   st->Is2D = GL_FALSE;
-   st->Index2 = 0;
-}
-
-
-/**
- * Return a new slang_ir_storage object.
- */
-slang_ir_storage *
-_slang_new_ir_storage(gl_register_file file, GLint index, GLint size)
-{
-   slang_ir_storage *st;
-   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
-   if (st) {
-      st->File = file;
-      st->Index = index;
-      st->Size = size;
-      st->Swizzle = SWIZZLE_NOOP;
-      st->Parent = NULL;
-      st->IsIndirect = GL_FALSE;
-      st->Is2D = GL_FALSE;
-      st->Index2 = 0;
-   }
-   return st;
-}
-
-
-/**
- * Return a new slang_ir_storage object.
- */
-slang_ir_storage *
-_slang_new_ir_storage_swz(gl_register_file file, GLint index, GLint size,
-                          GLuint swizzle)
-{
-   slang_ir_storage *st;
-   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
-   if (st) {
-      st->File = file;
-      st->Index = index;
-      st->Size = size;
-      st->Swizzle = swizzle;
-      st->Parent = NULL;
-      st->IsIndirect = GL_FALSE;
-      st->Is2D = GL_FALSE;
-      st->Index2 = 0;
-   }
-   return st;
-}
-
-/**
- * Return a new slang_ir_storage object.
- */
-slang_ir_storage *
-_slang_new_ir_storage_2d(gl_register_file file,
-                         GLint index, GLint index2,
-                         GLint size, GLuint swizzle)
-{
-   slang_ir_storage *st;
-   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
-   if (st) {
-      st->File = file;
-      st->Index = index;
-      st->Size = size;
-      st->Swizzle = swizzle;
-      st->Parent = NULL;
-      st->IsIndirect = GL_FALSE;
-      st->Is2D = GL_TRUE;
-      st->Index2 = index2;
-   }
-   return st;
-}
-
-
-
-/**
- * Return a new slang_ir_storage object.
- */
-slang_ir_storage *
-_slang_new_ir_storage_relative(GLint index, GLint size,
-                               slang_ir_storage *parent)
-{
-   slang_ir_storage *st;
-   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
-   if (st) {
-      st->File = PROGRAM_UNDEFINED;
-      st->Index = index;
-      st->Size = size;
-      st->Swizzle = SWIZZLE_NOOP;
-      st->Parent = parent;
-      st->IsIndirect = GL_FALSE;
-      st->Is2D = GL_FALSE;
-      st->Index2 = 0;
-   }
-   return st;
-}
-
-
-slang_ir_storage *
-_slang_new_ir_storage_indirect(gl_register_file file,
-                               GLint index,
-                               GLint size,
-                               gl_register_file indirectFile,
-                               GLint indirectIndex,
-                               GLuint indirectSwizzle)
-{
-   slang_ir_storage *st;
-   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
-   if (st) {
-      st->File = file;
-      st->Index = index;
-      st->Size = size;
-      st->Swizzle = SWIZZLE_NOOP;
-      st->IsIndirect = GL_TRUE;
-      st->IndirectFile = indirectFile;
-      st->IndirectIndex = indirectIndex;
-      st->IndirectSwizzle = indirectSwizzle;
-      st->Is2D = GL_FALSE;
-      st->Index2 = 0;
-   }
-   return st;
-}
-
-
-/**
- * Allocate IR storage for a texture sampler.
- * \param sampNum  the sampler number/index
- * \param texTarget  one of TEXTURE_x_INDEX values
- * \param size  number of samplers (in case of sampler array)
- */
-slang_ir_storage *
-_slang_new_ir_storage_sampler(GLint sampNum, GLuint texTarget, GLint size)
-{
-   slang_ir_storage *st;
-   assert(texTarget < NUM_TEXTURE_TARGETS);
-   st = _slang_new_ir_storage(PROGRAM_SAMPLER, sampNum, size);
-   if (st) {
-      st->TexTarget = texTarget;
-   }
-   return st;
-}
-
-
-
-/* XXX temporary function */
-void
-_slang_copy_ir_storage(slang_ir_storage *dst, const slang_ir_storage *src)
-{
-   *dst = *src;
-   dst->Parent = NULL;
-}
-
-
-
-static const char *
-_slang_ir_name(slang_ir_opcode opcode)
-{
-   return _slang_ir_info(opcode)->IrName;
-}
-
-
-
-#if 0 /* no longer needed with mempool */
-/**
- * Since many IR nodes might point to the same IR storage info, we need
- * to be careful when deleting things.
- * Before deleting an IR tree, traverse it and do refcounting on the
- * IR storage nodes.  Use the refcount info during delete to free things
- * properly.
- */
-static void
-_slang_refcount_storage(slang_ir_node *n)
-{
-   GLuint i;
-   if (!n)
-      return;
-   if (n->Store)
-      n->Store->RefCount++;
-   for (i = 0; i < 3; i++)
-      _slang_refcount_storage(n->Children[i]);
-}
-#endif
-
-
-static void
-_slang_free_ir(slang_ir_node *n)
-{
-   GLuint i;
-   if (!n)
-      return;
-
-#if 0
-   if (n->Store) {
-      n->Store->RefCount--;
-      if (n->Store->RefCount == 0) {
-         _slang_free(n->Store);
-         n->Store = NULL;
-      }
-   }
-#endif
-
-   for (i = 0; i < 3; i++)
-      _slang_free_ir(n->Children[i]);
-   /* Do not free n->List since it's a child elsewhere */
-   _slang_free(n);
-}
-
-
-/**
- * Recursively free an IR tree.
- */
-void
-_slang_free_ir_tree(slang_ir_node *n)
-{
-#if 0
-   _slang_refcount_storage(n);
-#endif
-   _slang_free_ir(n);
-}
-
-
-static const char *
-storage_string(const slang_ir_storage *st)
-{
-   static const char *files[] = {
-      "TEMP",
-      "LOCAL_PARAM",
-      "ENV_PARAM",
-      "STATE",
-      "INPUT",
-      "OUTPUT",
-      "NAMED_PARAM",
-      "CONSTANT",
-      "UNIFORM",
-      "VARYING",
-      "WRITE_ONLY",
-      "ADDRESS",
-      "SAMPLER",
-      "UNDEFINED"
-   };
-   static char s[100];
-   assert(Elements(files) == PROGRAM_FILE_MAX);
-#if 0
-   if (st->Size == 1)
-      _mesa_snprintf(s, "%s[%d]", files[st->File], st->Index);
-   else
-      _mesa_snprintf(s, "%s[%d..%d]", files[st->File], st->Index,
-                     st->Index + st->Size - 1);
-#endif
-   assert(st->File < (GLint) (sizeof(files) / sizeof(files[0])));
-   _mesa_snprintf(s, sizeof(s), "%s[%d]", files[st->File], st->Index);
-   return s;
-}
-
-
-static void
-spaces(int n)
-{
-   while (n-- > 0) {
-      printf(" ");
-   }
-}
-
-
-void
-_slang_print_ir_tree(const slang_ir_node *n, int indent)
-{
-#define IND 0
-
-   if (!n)
-      return;
-#if !IND
-   if (n->Opcode != IR_SEQ)
-#else
-      printf("%3d:", indent);
-#endif
-      spaces(indent);
-
-   switch (n->Opcode) {
-   case IR_SEQ:
-#if IND
-      printf("SEQ  at %p\n", (void*) n);
-#endif
-      assert(n->Children[0]);
-      assert(n->Children[1]);
-      _slang_print_ir_tree(n->Children[0], indent + IND);
-      _slang_print_ir_tree(n->Children[1], indent + IND);
-      break;
-   case IR_SCOPE:
-      printf("NEW SCOPE\n");
-      assert(!n->Children[1]);
-      _slang_print_ir_tree(n->Children[0], indent + 3);
-      break;
-   case IR_COPY:
-      printf("COPY\n");
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      _slang_print_ir_tree(n->Children[1], indent+3);
-      break;
-   case IR_LABEL:
-      printf("LABEL: %s\n", n->Label->Name);
-      break;
-   case IR_COND:
-      printf("COND\n");
-      _slang_print_ir_tree(n->Children[0], indent + 3);
-      break;
-
-   case IR_IF:
-      printf("IF \n");
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      spaces(indent);
-      printf("THEN\n");
-      _slang_print_ir_tree(n->Children[1], indent+3);
-      if (n->Children[2]) {
-         spaces(indent);
-         printf("ELSE\n");
-         _slang_print_ir_tree(n->Children[2], indent+3);
-      }
-      spaces(indent);
-      printf("ENDIF\n");
-      break;
-
-   case IR_BEGIN_SUB:
-      printf("BEGIN_SUB\n");
-      break;
-   case IR_END_SUB:
-      printf("END_SUB\n");
-      break;
-   case IR_RETURN:
-      printf("RETURN\n");
-      break;
-   case IR_CALL:
-      printf("CALL %s\n", n->Label->Name);
-      break;
-
-   case IR_LOOP:
-      printf("LOOP\n");
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      if (n->Children[1]) {
-         spaces(indent);
-         printf("TAIL:\n");
-         _slang_print_ir_tree(n->Children[1], indent+3);
-      }
-      spaces(indent);
-      printf("ENDLOOP\n");
-      break;
-   case IR_CONT:
-      printf("CONT\n");
-      break;
-   case IR_BREAK:
-      printf("BREAK\n");
-      break;
-   case IR_BREAK_IF_TRUE:
-      printf("BREAK_IF_TRUE\n");
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      break;
-   case IR_CONT_IF_TRUE:
-      printf("CONT_IF_TRUE\n");
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      break;
-
-   case IR_VAR:
-      printf("VAR %s%s at %s  store %p\n",
-             (n->Var ? (char *) n->Var->a_name : "TEMP"),
-             _mesa_swizzle_string(n->Store->Swizzle, 0, 0),
-             storage_string(n->Store), (void*) n->Store);
-      break;
-   case IR_VAR_DECL:
-      printf("VAR_DECL %s (%p) at %s  store %p\n",
-             (n->Var ? (char *) n->Var->a_name : "TEMP"),
-             (void*) n->Var, storage_string(n->Store),
-             (void*) n->Store);
-      break;
-   case IR_FIELD:
-      printf("FIELD %s of\n", n->Field);
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      break;
-   case IR_FLOAT:
-      printf("FLOAT %g %g %g %g\n",
-             n->Value[0], n->Value[1], n->Value[2], n->Value[3]);
-      break;
-   case IR_I_TO_F:
-      printf("INT_TO_FLOAT\n");
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      break;
-   case IR_F_TO_I:
-      printf("FLOAT_TO_INT\n");
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      break;
-   case IR_SWIZZLE:
-      printf("SWIZZLE %s of  (store %p) \n",
-             _mesa_swizzle_string(n->Store->Swizzle, 0, 0), (void*) n->Store);
-      _slang_print_ir_tree(n->Children[0], indent + 3);
-      break;
-   default:
-      printf("%s (%p, %p)  (store %p)\n", _slang_ir_name(n->Opcode),
-             (void*) n->Children[0], (void*) n->Children[1], (void*) n->Store);
-      _slang_print_ir_tree(n->Children[0], indent+3);
-      _slang_print_ir_tree(n->Children[1], indent+3);
-   }
-}
diff --git a/src/mesa/slang/slang_ir.h b/src/mesa/slang/slang_ir.h
deleted file mode 100644 (file)
index ce9a6c5..0000000
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 2005-2008  Brian Paul   All Rights Reserved.
- * Copyright (C) 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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_ir.h
- * Mesa GLSL Intermediate Representation tree types and constants.
- * \author Brian Paul
- */
-
-
-#ifndef SLANG_IR_H
-#define SLANG_IR_H
-
-
-#include "main/imports.h"
-#include "slang_compile.h"
-#include "slang_label.h"
-#include "main/mtypes.h"
-#include "program/prog_instruction.h"
-
-
-/**
- * Intermediate Representation opcodes
- */
-typedef enum
-{
-   IR_NOP = 0,
-   IR_SEQ,     /* sequence (eval left, then right) */
-   IR_SCOPE,   /* new variable scope (one child) */
-
-   IR_LABEL,   /* target of a jump or cjump */
-
-   IR_COND,    /* conditional expression/predicate */
-
-   IR_IF,      /* high-level IF/then/else */
-               /* Children[0] = conditional expression */
-               /* Children[1] = if-true part */
-               /* Children[2] = if-else part, or NULL */
-
-   IR_BEGIN_SUB, /* begin subroutine */
-   IR_END_SUB,   /* end subroutine */
-   IR_RETURN,    /* return from subroutine */
-   IR_CALL,      /* call subroutine */
-
-   IR_LOOP,      /* high-level loop-begin / loop-end */
-                 /* Children[0] = loop body */
-                 /* Children[1] = loop tail code, or NULL */
-
-   IR_CONT,      /* continue loop */
-                 /* n->Parent = ptr to parent IR_LOOP Node */
-   IR_BREAK,     /* break loop */
-
-   IR_BREAK_IF_TRUE, /**< Children[0] = the condition expression */
-   IR_CONT_IF_TRUE,
-
-   IR_COPY,       /**< assignment/copy */
-   IR_MOVE,       /**< assembly MOV instruction */
-
-   /* vector ops: */
-   IR_ADD,        /**< assembly ADD instruction */
-   IR_SUB,
-   IR_MUL,
-   IR_DIV,
-   IR_DOT4,
-   IR_DOT3,
-   IR_DOT2,
-   IR_NRM4,
-   IR_NRM3,
-   IR_CROSS,   /* vec3 cross product */
-   IR_LRP,
-   IR_CLAMP,
-   IR_MIN,
-   IR_MAX,
-   IR_CMP,     /* = (op0 < 0) ? op1 : op2 */
-   IR_SEQUAL,  /* Set if args are equal (vector) */
-   IR_SNEQUAL, /* Set if args are not equal (vector) */
-   IR_SGE,     /* Set if greater or equal (vector) */
-   IR_SGT,     /* Set if greater than (vector) */
-   IR_SLE,     /* Set if less or equal (vector) */
-   IR_SLT,     /* Set if less than (vector) */
-   IR_POW,     /* x^y */
-   IR_EXP,     /* e^x */
-   IR_EXP2,    /* 2^x */
-   IR_LOG2,    /* log base 2 */
-   IR_RSQ,     /* 1/sqrt() */
-   IR_RCP,     /* reciprocol */
-   IR_FLOOR,
-   IR_FRAC,
-   IR_ABS,     /* absolute value */
-   IR_NEG,     /* negate */
-   IR_DDX,     /* derivative w.r.t. X */
-   IR_DDY,     /* derivative w.r.t. Y */
-   IR_SIN,     /* sine */
-   IR_COS,     /* cosine */
-   IR_NOISE1,  /* noise(x) */
-   IR_NOISE2,  /* noise(x, y) */
-   IR_NOISE3,  /* noise(x, y, z) */
-   IR_NOISE4,  /* noise(x, y, z, w) */
-
-   IR_EQUAL,   /* boolean equality */
-   IR_NOTEQUAL,/* boolean inequality */
-   IR_NOT,     /* boolean not */
-
-   IR_VAR,     /* variable reference */
-   IR_VAR_DECL,/* var declaration */
-
-   IR_ELEMENT, /* array element */
-   IR_FIELD,   /* struct field */
-   IR_SWIZZLE, /* swizzled storage access */
-
-   IR_TEX,     /* texture lookup */
-   IR_TEXB,    /* texture lookup with LOD bias */
-   IR_TEXP,    /* texture lookup with projection */
-
-   IR_TEX_SH,     /* texture lookup, shadow compare */
-   IR_TEXB_SH,    /* texture lookup with LOD bias, shadow compare */
-   IR_TEXP_SH,    /* texture lookup with projection, shadow compare */
-
-   IR_FLOAT,
-   IR_I_TO_F,  /* int[4] to float[4] conversion */
-   IR_F_TO_I,  /* float[4] to int[4] conversion */
-
-   IR_KILL,     /* fragment kill/discard */
-
-   IR_EMIT_VERTEX,  /* geometry shader: emit vertex */
-   IR_END_PRIMITIVE /* geometry shader: end primitive */
-} slang_ir_opcode;
-
-
-/**
- * Describes where data/variables are stored in the various register files.
- *
- * In the simple case, the File, Index and Size fields indicate where
- * a variable is stored.  For example, a vec3 variable may be stored
- * as (File=PROGRAM_TEMPORARY, Index=6, Size=3).  Or, File[Index].
- * Or, a program input like color may be stored as
- * (File=PROGRAM_INPUT,Index=3,Size=4);
- *
- * For single-float values, the Swizzle field indicates which component
- * of the vector contains the float.
- *
- * If IsIndirect is set, the storage is accessed through an indirect
- * register lookup.  The value in question will be located at:
- *   File[Index + IndirectFile[IndirectIndex]]
- *
- * This is primary used for indexing arrays.  For example, consider this
- * GLSL code:
- *   uniform int i;
- *   float a[10];
- *   float x = a[i];
- *
- * here, storage for a[i] would be described by (File=PROGRAM_TEMPORAY,
- * Index=aPos, IndirectFile=PROGRAM_UNIFORM, IndirectIndex=iPos), which
- * would mean TEMP[aPos + UNIFORM[iPos]]
- */
-struct slang_ir_storage_
-{
-   gl_register_file File;  /**< PROGRAM_TEMPORARY, PROGRAM_INPUT, etc */
-   GLint Index;    /**< -1 means unallocated */
-   GLint Size;     /**< number of floats or ints */
-   GLuint Swizzle; /**< Swizzle AND writemask info */
-   GLint RefCount; /**< Used during IR tree delete */
-
-   GLboolean RelAddr; /* we'll remove this eventually */
-
-   GLboolean IsIndirect;
-   gl_register_file IndirectFile;
-   GLint IndirectIndex;
-   GLuint IndirectSwizzle;
-   GLuint TexTarget;  /**< If File==PROGRAM_SAMPLER, one of TEXTURE_x_INDEX */
-
-   /* Is the register two-dimensional and
-    * if so what's the second index */
-   GLboolean Is2D;
-   GLint Index2;
-
-   /** If Parent is non-null, Index is relative to parent.
-    * The other fields are ignored.
-    */
-   struct slang_ir_storage_ *Parent;
-};
-
-typedef struct slang_ir_storage_ slang_ir_storage;
-
-
-/**
- * Intermediate Representation (IR) tree node
- * Basically a binary tree, but IR_LRP and IR_CLAMP have three children.
- */
-typedef struct slang_ir_node_
-{
-   slang_ir_opcode Opcode;
-   struct slang_ir_node_ *Children[3];
-   slang_ir_storage *Store;  /**< location of result of this operation */
-   GLint InstLocation;  /**< Location of instruction emitted for this node */
-
-   /** special fields depending on Opcode: */
-   const char *Field;  /**< If Opcode == IR_FIELD */
-   GLfloat Value[4];    /**< If Opcode == IR_FLOAT */
-   slang_variable *Var;  /**< If Opcode == IR_VAR or IR_VAR_DECL */
-   struct slang_ir_node_ *List;  /**< For various linked lists */
-   struct slang_ir_node_ *Parent;  /**< Pointer to logical parent (ie. loop) */
-   slang_label *Label;  /**< Used for branches */
-   const char *Comment; /**< If Opcode == IR_COMMENT */
-} slang_ir_node;
-
-
-
-/**
- * Assembly and IR info
- */
-typedef struct
-{
-   slang_ir_opcode IrOpcode;
-   const char *IrName;
-   gl_inst_opcode InstOpcode;
-   GLuint ResultSize, NumParams;
-} slang_ir_info;
-
-
-
-extern const slang_ir_info *
-_slang_ir_info(slang_ir_opcode opcode);
-
-
-extern void
-_slang_init_ir_storage(slang_ir_storage *st,
-                       gl_register_file file, GLint index, GLint size,
-                       GLuint swizzle);
-
-extern slang_ir_storage *
-_slang_new_ir_storage(gl_register_file file, GLint index, GLint size);
-
-
-extern slang_ir_storage *
-_slang_new_ir_storage_swz(gl_register_file file, GLint index, GLint size,
-                          GLuint swizzle);
-
-extern slang_ir_storage *
-_slang_new_ir_storage_2d(gl_register_file file, GLint index, GLint index2d,
-                         GLint size, GLuint swizzle);
-
-extern slang_ir_storage *
-_slang_new_ir_storage_relative(GLint index, GLint size,
-                               slang_ir_storage *parent);
-
-
-extern slang_ir_storage *
-_slang_new_ir_storage_indirect(gl_register_file file,
-                               GLint index,
-                               GLint size,
-                               gl_register_file indirectFile,
-                               GLint indirectIndex,
-                               GLuint indirectSwizzle);
-
-extern slang_ir_storage *
-_slang_new_ir_storage_sampler(GLint sampNum, GLuint texTarget, GLint size);
-
-
-extern void
-_slang_copy_ir_storage(slang_ir_storage *dst, const slang_ir_storage *src);
-
-
-extern void
-_slang_free_ir_tree(slang_ir_node *n);
-
-
-extern void
-_slang_print_ir_tree(const slang_ir_node *n, int indent);
-
-
-#endif /* SLANG_IR_H */
diff --git a/src/mesa/slang/slang_label.c b/src/mesa/slang/slang_label.c
deleted file mode 100644 (file)
index 24881d5..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-
-
-/**
- * Functions for managing instruction labels.
- * Basically, this is used to manage the problem of forward branches where
- * we have a branch instruciton but don't know the target address yet.
- */
-
-
-#include "main/mtypes.h"
-#include "program/prog_instruction.h"
-#include "slang_label.h"
-#include "slang_mem.h"
-
-
-
-slang_label *
-_slang_label_new(const char *name)
-{
-   slang_label *l = (slang_label *) _slang_alloc(sizeof(slang_label));
-   if (l) {
-      l->Name = _slang_strdup(name);
-      l->Location = -1;
-   }
-   return l;
-}
-
-/**
- * As above, but suffix the name with a unique number.
- */
-slang_label *
-_slang_label_new_unique(const char *name)
-{
-   static int id = 1;
-   slang_label *l = (slang_label *) _slang_alloc(sizeof(slang_label));
-   if (l) {
-      l->Name = (char *) _slang_alloc(strlen(name) + 10);
-      if (!l->Name) {
-         free(l);
-         return NULL;
-      }
-      _mesa_snprintf(l->Name, strlen(name) + 10, "%s_%d", name, id);
-      id++;
-      l->Location = -1;
-   }
-   return l;
-}
-
-void
-_slang_label_delete(slang_label *l)
-{
-   if (l->Name) {
-      _slang_free(l->Name);
-      l->Name = NULL;
-   }
-   if (l->References) {
-      _slang_free(l->References);
-      l->References = NULL;
-   }
-   _slang_free(l);
-}
-
-
-void
-_slang_label_add_reference(slang_label *l, GLuint inst)
-{
-   const GLuint oldSize = l->NumReferences * sizeof(GLuint);
-   assert(l->Location < 0);
-   l->References = _slang_realloc(l->References,
-                                  oldSize, oldSize + sizeof(GLuint));
-   if (l->References) {
-      l->References[l->NumReferences] = inst;
-      l->NumReferences++;
-   }
-}
-
-
-GLint
-_slang_label_get_location(const slang_label *l)
-{
-   return l->Location;
-}
-
-
-void
-_slang_label_set_location(slang_label *l, GLint location,
-                          struct gl_program *prog)
-{
-   GLuint i;
-
-   assert(l->Location < 0);
-   assert(location >= 0);
-
-   l->Location = location;
-
-   /* for the instructions that were waiting to learn the label's location: */
-   for (i = 0; i < l->NumReferences; i++) {
-      const GLuint j = l->References[i];
-      prog->Instructions[j].BranchTarget = location;
-   }
-
-   if (l->References) {
-      _slang_free(l->References);
-      l->References = NULL;
-   }
-}
diff --git a/src/mesa/slang/slang_label.h b/src/mesa/slang/slang_label.h
deleted file mode 100644 (file)
index b0cff3a..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef SLANG_LABEL_H
-#define SLANG_LABEL_H 1
-
-#include "main/glheader.h"
-
-struct gl_program;
-
-struct slang_label_
-{
-   char *Name;
-   GLint Location;
-   /**
-    * List of instruction references (numbered starting at zero) which need
-    * their BranchTarget field filled in with the location eventually
-    * assigned to the label.
-    */
-   GLuint NumReferences;
-   GLuint *References;   /** Array [NumReferences] */
-};
-
-typedef struct slang_label_ slang_label;
-
-
-extern slang_label *
-_slang_label_new(const char *name);
-
-extern slang_label *
-_slang_label_new_unique(const char *name);
-
-extern void
-_slang_label_delete(slang_label *l);
-
-extern void
-_slang_label_add_reference(slang_label *l, GLuint inst);
-
-extern GLint
-_slang_label_get_location(const slang_label *l);
-
-extern void
-_slang_label_set_location(slang_label *l, GLint location,
-                          struct gl_program *prog);
-
-
-#endif /* SLANG_LABEL_H */
diff --git a/src/mesa/slang/slang_link.c b/src/mesa/slang/slang_link.c
deleted file mode 100644 (file)
index c21f672..0000000
+++ /dev/null
@@ -1,1287 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.3
- *
- * Copyright (C) 2008  Brian Paul   All Rights Reserved.
- * Copyright (C) 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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_link.c
- * GLSL linker
- * \author Brian Paul
- */
-
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/macros.h"
-#include "main/shaderapi.h"
-#include "main/shaderobj.h"
-#include "main/uniforms.h"
-#include "program/program.h"
-#include "program/prog_instruction.h"
-#include "program/prog_parameter.h"
-#include "program/prog_print.h"
-#include "program/prog_statevars.h"
-#include "program/prog_uniform.h"
-#include "slang_builtin.h"
-#include "slang_link.h"
-
-
-/** cast wrapper */
-static struct gl_vertex_program *
-vertex_program(struct gl_program *prog)
-{
-   assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
-   return (struct gl_vertex_program *) prog;
-}
-
-
-/** cast wrapper */
-static struct gl_fragment_program *
-fragment_program(struct gl_program *prog)
-{
-   assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
-   return (struct gl_fragment_program *) prog;
-}
-
-static struct gl_geometry_program *
-geometry_program(struct gl_program *prog)
-{
-   assert(prog->Target == MESA_GEOMETRY_PROGRAM);
-   return (struct gl_geometry_program *)prog;
-}
-
-/**
- * Record a linking error.
- */
-static void
-link_error(struct gl_shader_program *shProg, const char *msg)
-{
-   if (shProg->InfoLog) {
-      free(shProg->InfoLog);
-   }
-   shProg->InfoLog = _mesa_strdup(msg);
-   shProg->LinkStatus = GL_FALSE;
-}
-
-
-
-/**
- * Check if the given bit is either set or clear in both bitfields.
- */
-static GLboolean
-bits_agree(GLbitfield flags1, GLbitfield flags2, GLbitfield bit)
-{
-   return (flags1 & bit) == (flags2 & bit);
-}
-
-
-/**
- * Examine the outputs/varyings written by the vertex shader and
- * append the names of those outputs onto the Varyings list.
- * This will only capture the pre-defined/built-in varyings like
- * gl_Position, not user-defined varyings.
- */
-static void
-update_varying_var_list(GLcontext *ctx, struct gl_shader_program *shProg)
-{
-   if (shProg->VertexProgram) {
-      GLbitfield64 written = shProg->VertexProgram->Base.OutputsWritten;
-      GLuint i;
-      for (i = 0; written && i < VERT_RESULT_MAX; i++) {
-         if (written & BITFIELD64_BIT(i)) {
-            const char *name = _slang_vertex_output_name(i);            
-            if (name)
-               _mesa_add_varying(shProg->Varying, name, 1, GL_FLOAT_VEC4, 0x0);
-            written &= ~BITFIELD64_BIT(i);
-         }
-      }
-   }
-   if (shProg->GeometryProgram) {
-      GLbitfield64 written = shProg->GeometryProgram->Base.OutputsWritten;
-      GLuint i;
-      for (i = 0; written && i < GEOM_RESULT_MAX; i++) {
-         if (written & BITFIELD64_BIT(i)) {
-            const char *name = _slang_geometry_output_name(i);
-            if (name)
-               _mesa_add_varying(shProg->Varying, name, 1, GL_FLOAT_VEC4, 0x0);
-            written &= ~BITFIELD64_BIT(i);
-         }
-      }
-   }
-}
-
-
-/**
- * Do link error checking related to transform feedback.
- */
-static GLboolean
-link_transform_feedback(GLcontext *ctx, struct gl_shader_program *shProg)
-{
-   GLbitfield varyingMask;
-   GLuint totalComps, maxComps, i;
-
-   if (shProg->TransformFeedback.NumVarying == 0) {
-      /* nothing to do */
-      return GL_TRUE;
-   }
-
-   /* Check that there's a vertex shader */
-   if (shProg->TransformFeedback.NumVarying > 0 &&
-       !shProg->VertexProgram) {
-      link_error(shProg, "Transform feedback without vertex shader");
-      return GL_FALSE;
-   }
-
-   /* Check that all named variables exist, and that none are duplicated.
-    * Also, build a count of the number of varying components to feedback.
-    */
-   totalComps = 0;
-   varyingMask = 0x0;
-   for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
-      const GLchar *name = shProg->TransformFeedback.VaryingNames[i];
-      GLint v = _mesa_lookup_parameter_index(shProg->Varying, -1, name);
-      struct gl_program_parameter *p;
-
-      if (v < 0) {
-         char msg[100];
-         _mesa_snprintf(msg, sizeof(msg),
-                        "vertex shader does not emit %s", name);
-         link_error(shProg, msg);
-         return GL_FALSE;
-      }
-
-      assert(v < MAX_VARYING);
-
-      /* already seen this varying name? */
-      if (varyingMask & (1 << v)) {
-         char msg[100];
-         _mesa_snprintf(msg, sizeof(msg),
-                        "duplicated transform feedback varying name: %s",
-                        name);
-         link_error(shProg, msg);
-         return GL_FALSE;
-      }
-
-      varyingMask |= (1 << v);
-
-      p = &shProg->Varying->Parameters[v];
-      
-      totalComps += _mesa_sizeof_glsl_type(p->DataType);
-   }
-
-   if (shProg->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS)
-      maxComps = ctx->Const.MaxTransformFeedbackInterleavedComponents;
-   else
-      maxComps = ctx->Const.MaxTransformFeedbackSeparateComponents;
-
-   /* check max varying components against the limit */
-   if (totalComps > maxComps) {
-      char msg[100];
-      _mesa_snprintf(msg, sizeof(msg),
-                     "Too many feedback components: %u, max is %u",
-                     totalComps, maxComps);
-      link_error(shProg, msg);
-      return GL_FALSE;
-   }
-
-   return GL_TRUE;
-}
-
-
-/**
- * Linking varying vars involves rearranging varying vars so that the
- * vertex program's output varyings matches the order of the fragment
- * program's input varyings.
- * We'll then rewrite instructions to replace PROGRAM_VARYING with either
- * PROGRAM_INPUT or PROGRAM_OUTPUT depending on whether it's a vertex or
- * fragment shader.
- * This is also where we set program Input/OutputFlags to indicate
- * which inputs are centroid-sampled, invariant, etc.
- */
-static GLboolean
-link_varying_vars(GLcontext *ctx,
-                  struct gl_shader_program *shProg, struct gl_program *prog)
-{
-   GLuint *map, i, firstSrcVarying, firstDstVarying, newSrcFile, newDstFile;
-   GLbitfield *inOutFlags = NULL;
-
-   map = (GLuint *) malloc(prog->Varying->NumParameters * sizeof(GLuint));
-   if (!map)
-      return GL_FALSE;
-
-   /* Varying variables are treated like other vertex program outputs
-    * (and like other fragment program inputs).  The position of the
-    * first varying differs for vertex/fragment programs...
-    * Also, replace File=PROGRAM_VARYING with File=PROGRAM_INPUT/OUTPUT.
-    */
-   if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
-      firstSrcVarying = firstDstVarying = VERT_RESULT_VAR0;
-      newSrcFile = newDstFile = PROGRAM_OUTPUT;
-      inOutFlags = prog->OutputFlags;
-   }
-   else if (prog->Target == MESA_GEOMETRY_PROGRAM) {
-      firstSrcVarying = GEOM_ATTRIB_VAR0;
-      newSrcFile = PROGRAM_INPUT;
-      firstDstVarying = GEOM_RESULT_VAR0;
-      newDstFile = PROGRAM_OUTPUT;
-   }
-   else {
-      assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
-      firstSrcVarying = firstDstVarying = FRAG_ATTRIB_VAR0;
-      newSrcFile = newDstFile = PROGRAM_INPUT;
-      inOutFlags = prog->InputFlags;
-   }
-
-   for (i = 0; i < prog->Varying->NumParameters; i++) {
-      /* see if this varying is in the linked varying list */
-      const struct gl_program_parameter *var = prog->Varying->Parameters + i;
-      GLint j = _mesa_lookup_parameter_index(shProg->Varying, -1, var->Name);
-      if (j >= 0) {
-         /* varying is already in list, do some error checking */
-         const struct gl_program_parameter *v =
-            &shProg->Varying->Parameters[j];
-         if (var->Size != v->Size) {
-            link_error(shProg, "mismatched varying variable types");
-            free(map);
-            return GL_FALSE;
-         }
-         if (!bits_agree(var->Flags, v->Flags, PROG_PARAM_BIT_CENTROID)) {
-            char msg[100];
-            _mesa_snprintf(msg, sizeof(msg),
-                    "centroid modifier mismatch for '%s'", var->Name);
-            link_error(shProg, msg);
-            free(map);
-            return GL_FALSE;
-         }
-         if (!bits_agree(var->Flags, v->Flags, PROG_PARAM_BIT_INVARIANT)) {
-            char msg[100];
-            _mesa_snprintf(msg, sizeof(msg),
-                    "invariant modifier mismatch for '%s'", var->Name);
-            link_error(shProg, msg);
-            free(map);
-            return GL_FALSE;
-         }
-      }
-      else {
-         /* not already in linked list */
-         j = _mesa_add_varying(shProg->Varying, var->Name, var->Size,
-                               var->DataType, var->Flags);
-      }
-
-      if (shProg->Varying->NumParameters > ctx->Const.MaxVarying) {
-         link_error(shProg, "Too many varying variables");
-         free(map);
-         return GL_FALSE;
-      }
-
-      /* Map varying[i] to varying[j].
-       * Note: the loop here takes care of arrays or large (sz>4) vars.
-       */
-      {
-         GLint sz = var->Size;
-         while (sz > 0) {
-            inOutFlags[firstDstVarying + j] = var->Flags;
-            /*printf("Link varying from %d to %d\n", i, j);*/
-            map[i++] = j++;
-            sz -= 4;
-         }
-         i--; /* go back one */
-      }
-   }
-
-
-   /* OK, now scan the program/shader instructions looking for varying vars,
-    * replacing the old index with the new index.
-    */
-   for (i = 0; i < prog->NumInstructions; i++) {
-      struct prog_instruction *inst = prog->Instructions + i;
-      GLuint j;
-
-      if (inst->DstReg.File == PROGRAM_VARYING) {
-         inst->DstReg.File = newDstFile;
-         inst->DstReg.Index = map[ inst->DstReg.Index ] + firstDstVarying;
-      }
-
-      for (j = 0; j < 3; j++) {
-         if (inst->SrcReg[j].File == PROGRAM_VARYING) {
-            inst->SrcReg[j].File = newSrcFile;
-            inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ] + firstSrcVarying;
-         }
-      }
-   }
-
-   free(map);
-
-   /* these will get recomputed before linking is completed */
-   prog->InputsRead = 0x0;
-   prog->OutputsWritten = 0x0;
-
-   return GL_TRUE;
-}
-
-
-/**
- * Build the shProg->Uniforms list.
- * This is basically a list/index of all uniforms found in either/both of
- * the vertex and fragment shaders.
- *
- * About uniforms:
- * Each uniform has two indexes, one that points into the vertex
- * program's parameter array and another that points into the fragment
- * program's parameter array.  When the user changes a uniform's value
- * we have to change the value in the vertex and/or fragment program's
- * parameter array.
- *
- * This function will be called twice to set up the two uniform->parameter
- * mappings.
- *
- * If a uniform is only present in the vertex program OR fragment program
- * then the fragment/vertex parameter index, respectively, will be -1.
- */
-static GLboolean
-link_uniform_vars(GLcontext *ctx,
-                  struct gl_shader_program *shProg,
-                  struct gl_program *prog,
-                  GLuint *numSamplers)
-{
-   GLuint samplerMap[200]; /* max number of samplers declared, not used */
-   GLuint i;
-
-   for (i = 0; i < prog->Parameters->NumParameters; i++) {
-      const struct gl_program_parameter *p = prog->Parameters->Parameters + i;
-
-      /*
-       * XXX FIX NEEDED HERE
-       * We should also be adding a uniform if p->Type == PROGRAM_STATE_VAR.
-       * For example, modelview matrix, light pos, etc.
-       * Also, we need to update the state-var name-generator code to
-       * generate GLSL-style names, like "gl_LightSource[0].position".
-       * Furthermore, we'll need to fix the state-var's size/datatype info.
-       */
-
-      if ((p->Type == PROGRAM_UNIFORM || p->Type == PROGRAM_SAMPLER)
-          && p->Used) {
-         /* add this uniform, indexing into the target's Parameters list */
-         struct gl_uniform *uniform =
-            _mesa_append_uniform(shProg->Uniforms, p->Name, prog->Target, i);
-         if (uniform)
-            uniform->Initialized = p->Initialized;
-      }
-
-      /* The samplerMap[] table we build here is used to remap/re-index
-       * sampler references by TEX instructions.
-       */
-      if (p->Type == PROGRAM_SAMPLER && p->Used) {
-         /* Allocate a new sampler index */
-         GLuint oldSampNum = (GLuint) prog->Parameters->ParameterValues[i][0];
-         GLuint newSampNum = *numSamplers;
-         if (newSampNum >= ctx->Const.MaxTextureImageUnits) {
-            char s[100];
-            _mesa_snprintf(s, sizeof(s),
-                           "Too many texture samplers (%u, max is %u)",
-                           newSampNum, ctx->Const.MaxTextureImageUnits);
-            link_error(shProg, s);
-            return GL_FALSE;
-         }
-         /* save old->new mapping in the table */
-         if (oldSampNum < Elements(samplerMap))
-            samplerMap[oldSampNum] = newSampNum;
-         /* update parameter's sampler index */
-         prog->Parameters->ParameterValues[i][0] = (GLfloat) newSampNum;
-         (*numSamplers)++;
-      }
-   }
-
-   /* OK, now scan the program/shader instructions looking for texture
-    * instructions using sampler vars.  Replace old sampler indexes with
-    * new ones.
-    */
-   prog->SamplersUsed = 0x0;
-   for (i = 0; i < prog->NumInstructions; i++) {
-      struct prog_instruction *inst = prog->Instructions + i;
-      if (_mesa_is_tex_instruction(inst->Opcode)) {
-         /* here, inst->TexSrcUnit is really the sampler unit */
-         const GLint oldSampNum = inst->TexSrcUnit;
-
-#if 0
-         printf("====== remap sampler from %d to %d\n",
-                inst->TexSrcUnit, samplerMap[ inst->TexSrcUnit ]);
-#endif
-
-         if (oldSampNum < Elements(samplerMap)) {
-            const GLuint newSampNum = samplerMap[oldSampNum];
-            inst->TexSrcUnit = newSampNum;
-            prog->SamplerTargets[newSampNum] = inst->TexSrcTarget;
-            prog->SamplersUsed |= (1 << newSampNum);
-            if (inst->TexShadow) {
-               prog->ShadowSamplers |= (1 << newSampNum);
-            }
-         }
-      }
-   }
-
-   return GL_TRUE;
-}
-
-
-/**
- * Resolve binding of generic vertex attributes.
- * For example, if the vertex shader declared "attribute vec4 foobar" we'll
- * allocate a generic vertex attribute for "foobar" and plug that value into
- * the vertex program instructions.
- * But if the user called glBindAttributeLocation(), those bindings will
- * have priority.
- */
-static GLboolean
-_slang_resolve_attributes(struct gl_shader_program *shProg,
-                          const struct gl_program *origProg,
-                          struct gl_program *linkedProg)
-{
-   GLint attribMap[MAX_VERTEX_GENERIC_ATTRIBS];
-   GLuint i, j;
-   GLbitfield usedAttributes; /* generics only, not legacy attributes */
-   GLbitfield inputsRead = 0x0;
-
-   assert(origProg != linkedProg);
-   assert(origProg->Target == GL_VERTEX_PROGRAM_ARB);
-   assert(linkedProg->Target == GL_VERTEX_PROGRAM_ARB);
-
-   if (!shProg->Attributes)
-      shProg->Attributes = _mesa_new_parameter_list();
-
-   if (linkedProg->Attributes) {
-      _mesa_free_parameter_list(linkedProg->Attributes);
-   }
-   linkedProg->Attributes = _mesa_new_parameter_list();
-
-
-   /* Build a bitmask indicating which attribute indexes have been
-    * explicitly bound by the user with glBindAttributeLocation().
-    */
-   usedAttributes = 0x0;
-   for (i = 0; i < shProg->Attributes->NumParameters; i++) {
-      GLint attr = shProg->Attributes->Parameters[i].StateIndexes[0];
-      usedAttributes |= (1 << attr);
-   }
-
-   /* If gl_Vertex is used, that actually counts against the limit
-    * on generic vertex attributes.  This avoids the ambiguity of
-    * whether glVertexAttrib4fv(0, v) sets legacy attribute 0 (vert pos)
-    * or generic attribute[0].  If gl_Vertex is used, we want the former.
-    */
-   if (origProg->InputsRead & VERT_BIT_POS) {
-      usedAttributes |= 0x1;
-   }
-
-   /* initialize the generic attribute map entries to -1 */
-   for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
-      attribMap[i] = -1;
-   }
-
-   /*
-    * Scan program for generic attribute references
-    */
-   for (i = 0; i < linkedProg->NumInstructions; i++) {
-      struct prog_instruction *inst = linkedProg->Instructions + i;
-      for (j = 0; j < 3; j++) {
-         if (inst->SrcReg[j].File == PROGRAM_INPUT) {
-            inputsRead |= (1 << inst->SrcReg[j].Index);
-         }
-
-         if (inst->SrcReg[j].File == PROGRAM_INPUT &&
-             inst->SrcReg[j].Index >= VERT_ATTRIB_GENERIC0) {
-            /*
-             * OK, we've found a generic vertex attribute reference.
-             */
-            const GLint k = inst->SrcReg[j].Index - VERT_ATTRIB_GENERIC0;
-
-            GLint attr = attribMap[k];
-
-            if (attr < 0) {
-               /* Need to figure out attribute mapping now.
-                */
-               const char *name = origProg->Attributes->Parameters[k].Name;
-               const GLint size = origProg->Attributes->Parameters[k].Size;
-               const GLenum type =origProg->Attributes->Parameters[k].DataType;
-               GLint index;
-
-               /* See if there's a user-defined attribute binding for
-                * this name.
-                */
-               index = _mesa_lookup_parameter_index(shProg->Attributes,
-                                                    -1, name);
-               if (index >= 0) {
-                  /* Found a user-defined binding */
-                  attr = shProg->Attributes->Parameters[index].StateIndexes[0];
-               }
-               else {
-                  /* No user-defined binding, choose our own attribute number.
-                   * Start at 1 since generic attribute 0 always aliases
-                   * glVertex/position.
-                   */
-                  for (attr = 0; attr < MAX_VERTEX_GENERIC_ATTRIBS; attr++) {
-                     if (((1 << attr) & usedAttributes) == 0)
-                        break;
-                  }
-                  if (attr == MAX_VERTEX_GENERIC_ATTRIBS) {
-                     link_error(shProg, "Too many vertex attributes");
-                     return GL_FALSE;
-                  }
-
-                  /* mark this attribute as used */
-                  usedAttributes |= (1 << attr);
-               }
-
-               attribMap[k] = attr;
-
-               /* Save the final name->attrib binding so it can be queried
-                * with glGetAttributeLocation().
-                */
-               _mesa_add_attribute(linkedProg->Attributes, name,
-                                   size, type, attr);
-            }
-
-            assert(attr >= 0);
-
-            /* update the instruction's src reg */
-            inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + attr;
-         }
-      }
-   }
-
-   /* Handle pre-defined attributes here (gl_Vertex, gl_Normal, etc).
-    * When the user queries the active attributes we need to include both
-    * the user-defined attributes and the built-in ones.
-    */
-   for (i = VERT_ATTRIB_POS; i < VERT_ATTRIB_GENERIC0; i++) {
-      if (inputsRead & (1 << i)) {
-         _mesa_add_attribute(linkedProg->Attributes,
-                             _slang_vert_attrib_name(i),
-                             4, /* size in floats */
-                             _slang_vert_attrib_type(i),
-                             -1 /* attrib/input */);
-      }
-   }
-
-   return GL_TRUE;
-}
-
-
-/**
- * Scan program instructions to update the program's NumTemporaries field.
- * Note: this implemenation relies on the code generator allocating
- * temps in increasing order (0, 1, 2, ... ).
- */
-static void
-_slang_count_temporaries(struct gl_program *prog)
-{
-   GLuint i, j;
-   GLint maxIndex = -1;
-
-   for (i = 0; i < prog->NumInstructions; i++) {
-      const struct prog_instruction *inst = prog->Instructions + i;
-      const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
-      for (j = 0; j < numSrc; j++) {
-         if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
-            if (maxIndex < inst->SrcReg[j].Index)
-               maxIndex = inst->SrcReg[j].Index;
-         }
-         if (inst->DstReg.File == PROGRAM_TEMPORARY) {
-            if (maxIndex < (GLint) inst->DstReg.Index)
-               maxIndex = inst->DstReg.Index;
-         }
-      }
-   }
-
-   prog->NumTemporaries = (GLuint) (maxIndex + 1);
-}
-
-
-/**
- * If an input attribute is indexed with relative addressing we have
- * to compute a gl_program::InputsRead bitmask which reflects the fact
- * that any input may be referenced by array element.  Ex: gl_TexCoord[i].
- * This function computes the bitmask of potentially read inputs.
- */
-static GLbitfield
-get_inputs_read_mask(GLenum target, GLuint index, GLboolean relAddr)
-{
-   GLbitfield mask;
-
-   mask = 1 << index;
-
-   if (relAddr) {
-      if (target == GL_VERTEX_PROGRAM_ARB) {
-         switch (index) {
-         case VERT_ATTRIB_TEX0:
-            mask = ((1U << (VERT_ATTRIB_TEX7 + 1)) - 1)
-                 - ((1U << VERT_ATTRIB_TEX0) - 1);
-            break;
-         case VERT_ATTRIB_GENERIC0:
-            /* different code to avoid uint overflow */
-            mask = ~0x0U - ((1U << VERT_ATTRIB_GENERIC0) - 1);
-            break;
-         default:
-            ; /* a non-array input attribute */
-         }
-      }
-      else if (target == GL_FRAGMENT_PROGRAM_ARB) {
-         switch (index) {
-         case FRAG_ATTRIB_TEX0:
-            mask = ((1U << (FRAG_ATTRIB_TEX7 + 1)) - 1)
-                 - ((1U << FRAG_ATTRIB_TEX0) - 1);
-            break;
-         case FRAG_ATTRIB_VAR0:
-            mask = ((1U << (FRAG_ATTRIB_VAR0 + MAX_VARYING)) - 1)
-                 - ((1U << FRAG_ATTRIB_VAR0) - 1);
-            break;
-         default:
-            ; /* a non-array input attribute */
-         }
-      }
-      else if (target == MESA_GEOMETRY_PROGRAM) {
-         switch (index) {
-         case GEOM_ATTRIB_VAR0:
-            mask = ((1ULL << (GEOM_ATTRIB_VAR0 + MAX_VARYING)) - 1)
-                   - ((1ULL << GEOM_ATTRIB_VAR0) - 1);
-            break;
-         default:
-            ; /* a non-array input attribute */
-         }
-      }
-      else {
-         assert(0 && "bad program target");
-      }
-   }
-   else {
-   }
-
-   return mask;
-}
-
-
-/**
- * If an output attribute is indexed with relative addressing we have
- * to compute a gl_program::OutputsWritten bitmask which reflects the fact
- * that any output may be referenced by array element.  Ex: gl_TexCoord[i].
- * This function computes the bitmask of potentially written outputs.
- */
-static GLbitfield64
-get_outputs_written_mask(GLenum target, GLuint index, GLboolean relAddr)
-{
-   GLbitfield64 mask;
-
-   mask = BITFIELD64_BIT(index);
-
-   if (relAddr) {
-      if (target == GL_VERTEX_PROGRAM_ARB) {
-         switch (index) {
-         case VERT_RESULT_TEX0:
-            mask = BITFIELD64_RANGE(VERT_RESULT_TEX0,
-                                    (VERT_RESULT_TEX0
-                                     + MAX_TEXTURE_COORD_UNITS - 1));
-            break;
-         case VERT_RESULT_VAR0:
-            mask = BITFIELD64_RANGE(VERT_RESULT_VAR0,
-                                    (VERT_RESULT_VAR0 + MAX_VARYING - 1));
-            break;
-         default:
-            ; /* a non-array output attribute */
-         }
-      }
-      else if (target == GL_FRAGMENT_PROGRAM_ARB) {
-         switch (index) {
-         case FRAG_RESULT_DATA0:
-            mask = BITFIELD64_RANGE(FRAG_RESULT_DATA0,
-                                    (FRAG_RESULT_DATA0
-                                     + MAX_DRAW_BUFFERS - 1));
-            break;
-         default:
-            ; /* a non-array output attribute */
-         }
-      }
-      else if (target == MESA_GEOMETRY_PROGRAM) {
-         switch (index) {
-         case GEOM_RESULT_TEX0:
-            mask = BITFIELD64_RANGE(GEOM_RESULT_TEX0,
-                                    (GEOM_RESULT_TEX0
-                                     + MAX_TEXTURE_COORD_UNITS - 1));
-            break;
-         case GEOM_RESULT_VAR0:
-            mask = BITFIELD64_RANGE(GEOM_RESULT_VAR0,
-                                    (GEOM_RESULT_VAR0 + MAX_VARYING - 1));
-            break;
-         default:
-            ; /* a non-array output attribute */
-         }
-      }
-      else {
-         assert(0 && "bad program target");
-      }
-   }
-
-   return mask;
-}
-
-
-/**
- * Scan program instructions to update the program's InputsRead and
- * OutputsWritten fields.
- */
-static void
-_slang_update_inputs_outputs(struct gl_program *prog)
-{
-   GLuint i, j;
-   GLuint maxAddrReg = 0;
-
-   prog->InputsRead = 0x0;
-   prog->OutputsWritten = 0x0;
-
-   prog->IndirectRegisterFiles = 0x0;
-
-   for (i = 0; i < prog->NumInstructions; i++) {
-      const struct prog_instruction *inst = prog->Instructions + i;
-      const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
-      for (j = 0; j < numSrc; j++) {
-         if (inst->SrcReg[j].File == PROGRAM_INPUT) {
-            if (prog->Target == MESA_GEOMETRY_PROGRAM &&
-                inst->SrcReg[j].HasIndex2)
-               prog->InputsRead |= get_inputs_read_mask(prog->Target,
-                                                        inst->SrcReg[j].Index2,
-                                                        inst->SrcReg[j].RelAddr2);
-            else
-               prog->InputsRead |= get_inputs_read_mask(prog->Target,
-                                                        inst->SrcReg[j].Index,
-                                                        inst->SrcReg[j].RelAddr);
-         }
-         else if (inst->SrcReg[j].File == PROGRAM_ADDRESS) {
-            maxAddrReg = MAX2(maxAddrReg, (GLuint) (inst->SrcReg[j].Index + 1));
-         }
-
-         if (inst->SrcReg[j].RelAddr)
-            prog->IndirectRegisterFiles |= (1 << inst->SrcReg[j].File);
-      }
-
-      if (inst->DstReg.File == PROGRAM_OUTPUT) {
-         prog->OutputsWritten |= get_outputs_written_mask(prog->Target,
-                                                          inst->DstReg.Index,
-                                                          inst->DstReg.RelAddr);
-      }
-      else if (inst->DstReg.File == PROGRAM_ADDRESS) {
-         maxAddrReg = MAX2(maxAddrReg, inst->DstReg.Index + 1);
-      }
-      if (inst->DstReg.RelAddr)
-         prog->IndirectRegisterFiles |= (1 << inst->DstReg.File);
-   }
-   prog->NumAddressRegs = maxAddrReg;
-}
-
-
-
-/**
- * Remove extra #version directives from the concatenated source string.
- * Disable the extra ones by converting first two chars to //, a comment.
- * This is a bit of hack to work around a preprocessor bug that only
- * allows one #version directive per source.
- */
-static void
-remove_extra_version_directives(GLchar *source)
-{
-   GLuint verCount = 0;
-   while (1) {
-      char *ver = strstr(source, "#version");
-      if (ver) {
-         verCount++;
-         if (verCount > 1) {
-            ver[0] = '/';
-            ver[1] = '/';
-         }
-         source += 8;
-      }
-      else {
-         break;
-      }
-   }
-}
-
-/* Returns the number of vertices per geometry shader
- * input primitive.
- * XXX: duplicated in Gallium in u_vertices_per_prim
- * method. Once Mesa core will start using Gallium
- * this should be removed
- */
-static int
-vertices_per_prim(int prim)
-{
-   switch (prim) {
-   case GL_POINTS:
-      return 1;
-   case GL_LINES:
-      return 2;
-   case GL_TRIANGLES:
-      return 3;
-   case GL_LINES_ADJACENCY_ARB:
-      return 4;
-   case GL_TRIANGLES_ADJACENCY_ARB:
-      return 6;
-   default:
-      ASSERT(!"Bad primitive");
-      return 3;
-   }
-}
-
-/**
- * Return a new shader whose source code is the concatenation of
- * all the shader sources of the given type.
- */
-static struct gl_shader *
-concat_shaders(struct gl_shader_program *shProg, GLenum shaderType)
-{
-   struct gl_shader *newShader;
-   const struct gl_shader *firstShader = NULL;
-   GLuint *shaderLengths;
-   GLchar *source;
-   GLuint totalLen = 0, len = 0;
-   GLuint i;
-
-   shaderLengths = (GLuint *)malloc(shProg->NumShaders * sizeof(GLuint));
-   if (!shaderLengths) {
-      return NULL;
-   }
-
-   /* compute total size of new shader source code */
-   for (i = 0; i < shProg->NumShaders; i++) {
-      const struct gl_shader *shader = shProg->Shaders[i];
-      if (shader->Type == shaderType) {
-         shaderLengths[i] = strlen(shader->Source);
-         totalLen += shaderLengths[i];
-         if (!firstShader)
-            firstShader = shader;
-      }
-   }
-
-   if (totalLen == 0) {
-      free(shaderLengths);
-      return NULL;
-   }
-
-   /* Geometry shader will inject definition of
-    * const int gl_VerticesIn */
-   if (shaderType == GL_GEOMETRY_SHADER_ARB) {
-      totalLen += 32;
-   }
-
-   source = (GLchar *) malloc(totalLen + 1);
-   if (!source) {
-      free(shaderLengths);
-      return NULL;
-   }
-
-   /* concatenate shaders */
-   for (i = 0; i < shProg->NumShaders; i++) {
-      const struct gl_shader *shader = shProg->Shaders[i];
-      if (shader->Type == shaderType) {
-         memcpy(source + len, shader->Source, shaderLengths[i]);
-         len += shaderLengths[i];
-      }
-   }
-   /* if it's geometry shader we need to inject definition
-    * of "const int gl_VerticesIn = X;" where X is the number
-    * of vertices per input primitive
-    */
-   if (shaderType == GL_GEOMETRY_SHADER_ARB) {
-      GLchar gs_pre[32];
-      GLuint num_verts = vertices_per_prim(shProg->Geom.InputType);
-      _mesa_snprintf(gs_pre, 31,
-                     "const int gl_VerticesIn = %d;\n", num_verts);
-      memcpy(source + len, gs_pre, strlen(gs_pre));
-      len += strlen(gs_pre);
-   }
-   source[len] = '\0';
-   /*
-   printf("---NEW CONCATENATED SHADER---:\n%s\n------------\n", source);
-   */
-
-   free(shaderLengths);
-
-   remove_extra_version_directives(source);
-
-   newShader = CALLOC_STRUCT(gl_shader);
-   if (!newShader) {
-      free(source);
-      return NULL;
-   }
-
-   newShader->Type = shaderType;
-   newShader->Source = source;
-   newShader->Pragmas = firstShader->Pragmas;
-
-   return newShader;
-}
-
-/**
- * Search the shader program's list of shaders to find the one that
- * defines main().
- * This will involve shader concatenation and recompilation if needed.
- */
-static struct gl_shader *
-get_main_shader(GLcontext *ctx,
-                struct gl_shader_program *shProg, GLenum type)
-{
-   struct gl_shader *shader = NULL;
-   GLuint i;
-
-   /*
-    * Look for a shader that defines main() and has no unresolved references.
-    */
-   for (i = 0; i < shProg->NumShaders; i++) {
-      shader = shProg->Shaders[i];
-      if (shader->Type == type &&
-          shader->Main &&
-          !shader->UnresolvedRefs) {
-         /* All set! */
-         return shader;
-      }
-   }
-
-   /*
-    * There must have been unresolved references during the original
-    * compilation.  Try concatenating all the shaders of the given type
-    * and recompile that.
-    */
-   shader = concat_shaders(shProg, type);
-
-   if (shader) {
-      _slang_compile(ctx, shader);
-
-      /* Finally, check if recompiling failed */
-      if (!shader->CompileStatus ||
-          !shader->Main ||
-          shader->UnresolvedRefs) {
-         link_error(shProg, "Unresolved symbols");
-         ctx->Driver.DeleteShader(ctx, shader);
-         return NULL;
-      }
-   }
-
-   return shader;
-}
-
-
-/**
- * Shader linker.  Currently:
- *
- * 1. The last attached vertex shader and fragment shader are linked.
- * 2. Varying vars in the two shaders are combined so their locations
- *    agree between the vertex and fragment stages.  They're treated as
- *    vertex program output attribs and as fragment program input attribs.
- * 3. The vertex and fragment programs are cloned and modified to update
- *    src/dst register references so they use the new, linked varying
- *    storage locations.
- */
-void
-_slang_link(GLcontext *ctx,
-            GLhandleARB programObj,
-            struct gl_shader_program *shProg)
-{
-   const struct gl_vertex_program *vertProg = NULL;
-   const struct gl_fragment_program *fragProg = NULL;
-   const struct gl_geometry_program *geomProg = NULL;
-   GLboolean vertNotify = GL_TRUE, fragNotify = GL_TRUE, geomNotify = GL_TRUE;
-   GLuint numSamplers = 0;
-   GLuint i;
-
-   _mesa_clear_shader_program_data(ctx, shProg);
-
-   /* Initialize LinkStatus to "success".  Will be cleared if error. */
-   shProg->LinkStatus = GL_TRUE;
-
-   /* check that all programs compiled successfully */
-   for (i = 0; i < shProg->NumShaders; i++) {
-      if (!shProg->Shaders[i]->CompileStatus) {
-         link_error(shProg, "linking with uncompiled shader\n");
-         return;
-      }
-   }
-
-   shProg->Uniforms = _mesa_new_uniform_list();
-   shProg->Varying = _mesa_new_parameter_list();
-
-   /*
-    * Find the vertex and fragment shaders which define main()
-    */
-   {
-      struct gl_shader *vertShader, *fragShader, *geomShader;
-      vertShader = get_main_shader(ctx, shProg, GL_VERTEX_SHADER);
-      geomShader = get_main_shader(ctx, shProg, GL_GEOMETRY_SHADER_ARB);
-      fragShader = get_main_shader(ctx, shProg, GL_FRAGMENT_SHADER);
-
-      if (vertShader)
-         vertProg = vertex_program(vertShader->Program);
-      if (geomShader)
-         geomProg = geometry_program(geomShader->Program);
-      if (fragShader)
-         fragProg = fragment_program(fragShader->Program);
-      if (!shProg->LinkStatus)
-         return;
-   }
-
-#if FEATURE_es2_glsl
-   /* must have both a vertex and fragment program for ES2 */
-   if (ctx->API == API_OPENGLES2) {
-      if (!vertProg) {
-        link_error(shProg, "missing vertex shader\n");
-        return;
-      }
-      if (!fragProg) {
-        link_error(shProg, "missing fragment shader\n");
-        return;
-      }
-   }
-#endif
-
-   /*
-    * Make copies of the vertex/fragment programs now since we'll be
-    * changing src/dst registers after merging the uniforms and varying vars.
-    */
-   _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
-   if (vertProg) {
-      struct gl_vertex_program *linked_vprog =
-         _mesa_clone_vertex_program(ctx, vertProg);
-      shProg->VertexProgram = linked_vprog; /* refcount OK */
-      /* vertex program ID not significant; just set Id for debugging purposes */
-      shProg->VertexProgram->Base.Id = shProg->Name;
-      ASSERT(shProg->VertexProgram->Base.RefCount == 1);
-   }
-   _mesa_reference_geomprog(ctx, &shProg->GeometryProgram, NULL);
-   if (geomProg) {
-      struct gl_geometry_program *linked_gprog =
-         _mesa_clone_geometry_program(ctx, geomProg);
-      shProg->GeometryProgram = linked_gprog; /* refcount OK */
-      shProg->GeometryProgram->Base.Id = shProg->Name;
-      ASSERT(shProg->GeometryProgram->Base.RefCount == 1);
-   }
-   _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
-   if (fragProg) {
-      struct gl_fragment_program *linked_fprog = 
-         _mesa_clone_fragment_program(ctx, fragProg);
-      shProg->FragmentProgram = linked_fprog; /* refcount OK */
-      /* vertex program ID not significant; just set Id for debugging purposes */
-      shProg->FragmentProgram->Base.Id = shProg->Name;
-      ASSERT(shProg->FragmentProgram->Base.RefCount == 1);
-   }
-
-   /* link varying vars */
-   if (shProg->VertexProgram) {
-      if (!link_varying_vars(ctx, shProg, &shProg->VertexProgram->Base))
-         return;
-   }
-   if (shProg->GeometryProgram) {
-      if (!link_varying_vars(ctx, shProg, &shProg->GeometryProgram->Base))
-         return;
-   }
-   if (shProg->FragmentProgram) {
-      if (!link_varying_vars(ctx, shProg, &shProg->FragmentProgram->Base))
-         return;
-   }
-
-   /* link uniform vars */
-   if (shProg->VertexProgram) {
-      if (!link_uniform_vars(ctx, shProg, &shProg->VertexProgram->Base,
-                             &numSamplers)) {
-         return;
-      }
-   }
-   if (shProg->GeometryProgram) {
-      if (!link_uniform_vars(ctx, shProg, &shProg->GeometryProgram->Base,
-                             &numSamplers)) {
-         return;
-      }
-   }
-   if (shProg->FragmentProgram) {
-      if (!link_uniform_vars(ctx, shProg, &shProg->FragmentProgram->Base,
-                             &numSamplers)) {
-         return;
-      }
-   }
-
-   /*_mesa_print_uniforms(shProg->Uniforms);*/
-
-   if (shProg->VertexProgram) {
-      if (!_slang_resolve_attributes(shProg, &vertProg->Base,
-                                     &shProg->VertexProgram->Base)) {
-         return;
-      }
-   }
-
-   if (shProg->VertexProgram) {
-      _slang_update_inputs_outputs(&shProg->VertexProgram->Base);
-      _slang_count_temporaries(&shProg->VertexProgram->Base);
-      if (!(shProg->VertexProgram->Base.OutputsWritten
-           & BITFIELD64_BIT(VERT_RESULT_HPOS))) {
-         /* the vertex program did not compute a vertex position */
-         link_error(shProg,
-                    "gl_Position was not written by vertex shader\n");
-         return;
-      }
-   }
-   if (shProg->GeometryProgram) {
-      if (!shProg->VertexProgram) {
-         link_error(shProg,
-                    "Geometry shader without a vertex shader is illegal!\n");
-         return;
-      }
-      if (shProg->Geom.VerticesOut == 0) {
-         link_error(shProg,
-                    "GEOMETRY_VERTICES_OUT is zero\n");
-         return;
-      }
-
-      _slang_count_temporaries(&shProg->GeometryProgram->Base);
-      _slang_update_inputs_outputs(&shProg->GeometryProgram->Base);
-   }
-   if (shProg->FragmentProgram) {
-      _slang_count_temporaries(&shProg->FragmentProgram->Base);
-      _slang_update_inputs_outputs(&shProg->FragmentProgram->Base);
-   }
-
-   /* Check that all the varying vars needed by the fragment shader are
-    * actually produced by the vertex shader.
-    */
-   if (shProg->FragmentProgram) {
-      const GLbitfield varyingRead
-         = shProg->FragmentProgram->Base.InputsRead >> FRAG_ATTRIB_VAR0;
-      const GLbitfield64 varyingWritten = shProg->VertexProgram ?
-         shProg->VertexProgram->Base.OutputsWritten >> VERT_RESULT_VAR0 : 0x0;
-      if ((varyingRead & varyingWritten) != varyingRead) {
-         link_error(shProg,
-          "Fragment program using varying vars not written by vertex shader\n");
-         return;
-      }         
-   }
-
-   /* check that gl_FragColor and gl_FragData are not both written to */
-   if (shProg->FragmentProgram) {
-      const GLbitfield64 outputsWritten =
-        shProg->FragmentProgram->Base.OutputsWritten;
-      if ((outputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) &&
-          (outputsWritten >= BITFIELD64_BIT(FRAG_RESULT_DATA0))) {
-         link_error(shProg, "Fragment program cannot write both gl_FragColor"
-                    " and gl_FragData[].\n");
-         return;
-      }         
-   }
-
-   update_varying_var_list(ctx, shProg);
-
-   /* checks related to transform feedback */
-   if (!link_transform_feedback(ctx, shProg)) {
-      return;
-   }
-
-   if (fragProg && shProg->FragmentProgram) {
-      /* Compute initial program's TexturesUsed info */
-      _mesa_update_shader_textures_used(&shProg->FragmentProgram->Base);
-
-      /* notify driver that a new fragment program has been compiled/linked */
-      vertNotify = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
-                                                 &shProg->FragmentProgram->Base);
-      if (ctx->Shader.Flags & GLSL_DUMP) {
-         fprintf(stderr, "Mesa pre-link fragment program:\n");
-         _mesa_print_program(&fragProg->Base);
-         _mesa_print_program_parameters(ctx, &fragProg->Base);
-
-         fprintf(stderr, "Mesa post-link fragment program:\n");
-         _mesa_print_program(&shProg->FragmentProgram->Base);
-         _mesa_print_program_parameters(ctx, &shProg->FragmentProgram->Base);
-      }
-   }
-
-   if (geomProg && shProg->GeometryProgram) {
-      /* Compute initial program's TexturesUsed info */
-      _mesa_update_shader_textures_used(&shProg->GeometryProgram->Base);
-
-      /* Copy some per-shader-program fields to per-shader object */
-      shProg->GeometryProgram->VerticesOut = shProg->Geom.VerticesOut;
-      shProg->GeometryProgram->InputType = shProg->Geom.InputType;
-      shProg->GeometryProgram->OutputType = shProg->Geom.OutputType;
-
-      /* notify driver that a new fragment program has been compiled/linked */
-      geomNotify = ctx->Driver.ProgramStringNotify(ctx, MESA_GEOMETRY_PROGRAM,
-                                                   &shProg->GeometryProgram->Base);
-      if (ctx->Shader.Flags & GLSL_DUMP) {
-         fprintf(stderr, "Mesa pre-link geometry program:\n");
-         _mesa_print_program(&geomProg->Base);
-         _mesa_print_program_parameters(ctx, &geomProg->Base);
-
-         fprintf(stderr, "Mesa post-link geometry program:\n");
-         _mesa_print_program(&shProg->GeometryProgram->Base);
-         _mesa_print_program_parameters(ctx, &shProg->GeometryProgram->Base);
-      }
-   }
-
-   if (vertProg && shProg->VertexProgram) {
-      /* Compute initial program's TexturesUsed info */
-      _mesa_update_shader_textures_used(&shProg->VertexProgram->Base);
-
-      /* notify driver that a new vertex program has been compiled/linked */
-      fragNotify = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
-                                                   &shProg->VertexProgram->Base);
-      if (ctx->Shader.Flags & GLSL_DUMP) {
-         fprintf(stderr, "Mesa pre-link vertex program:\n");
-         _mesa_print_program(&vertProg->Base);
-         _mesa_print_program_parameters(ctx, &vertProg->Base);
-
-         fprintf(stderr, "Mesa post-link vertex program:\n");
-         _mesa_print_program(&shProg->VertexProgram->Base);
-         _mesa_print_program_parameters(ctx, &shProg->VertexProgram->Base);
-      }
-   }
-
-   /* Debug: */
-   if (0) {
-      if (shProg->VertexProgram)
-         _mesa_postprocess_program(ctx, &shProg->VertexProgram->Base);
-      if (shProg->FragmentProgram)
-         _mesa_postprocess_program(ctx, &shProg->FragmentProgram->Base);
-   }
-
-   if (ctx->Shader.Flags & GLSL_DUMP) {
-      fprintf(stderr, "Varying vars:\n");
-      _mesa_print_parameter_list(shProg->Varying);
-      if (shProg->InfoLog) {
-         fprintf(stderr, "Info Log: %s\n", shProg->InfoLog);
-      }
-   }
-
-   if (!vertNotify || !fragNotify || !geomNotify) {
-      /* driver rejected one/both of the vertex/fragment programs */
-      if (!shProg->InfoLog) {
-        link_error(shProg,
-                   "Vertex, geometry and/or fragment program rejected by driver\n");
-      }
-   }
-   else {
-      shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram);
-   }
-}
-
diff --git a/src/mesa/slang/slang_link.h b/src/mesa/slang/slang_link.h
deleted file mode 100644 (file)
index 3e9fa2d..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.2
- *
- * Copyright (C) 2008  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_LINK_H
-#define SLANG_LINK_H 1
-
-#include "main/mtypes.h"
-
-
-extern void
-_slang_link(GLcontext *ctx, GLhandleARB h,
-            struct gl_shader_program *shProg);
-
-
-#endif
-
diff --git a/src/mesa/slang/slang_log.c b/src/mesa/slang/slang_log.c
deleted file mode 100644 (file)
index 9ff2141..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.3
- *
- * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
- * Copyright (C) 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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "main/imports.h"
-#include "slang_log.h"
-#include "slang_utility.h"
-
-
-
-static char *out_of_memory = "Error: Out of memory.\n";
-
-void
-slang_info_log_construct(slang_info_log * log)
-{
-   log->text = NULL;
-   log->dont_free_text = GL_FALSE;
-   log->error_flag = GL_FALSE;
-}
-
-void
-slang_info_log_destruct(slang_info_log * log)
-{
-   if (!log->dont_free_text)
-      free(log->text);
-}
-
-static int
-slang_info_log_message(slang_info_log * log, const char *prefix,
-                       const char *msg)
-{
-   GLuint size;
-
-   if (log->dont_free_text)
-      return 0;
-   size = slang_string_length(msg) + 2;
-   if (prefix != NULL)
-      size += slang_string_length(prefix) + 2;
-   if (log->text != NULL) {
-      GLuint old_len = slang_string_length(log->text);
-      log->text = (char *)
-        _mesa_realloc(log->text, old_len + 1, old_len + size);
-   }
-   else {
-      log->text = (char *) (malloc(size));
-      if (log->text != NULL)
-         log->text[0] = '\0';
-   }
-   if (log->text == NULL)
-      return 0;
-   if (prefix != NULL) {
-      slang_string_concat(log->text, prefix);
-      slang_string_concat(log->text, ": ");
-   }
-   slang_string_concat(log->text, msg);
-   slang_string_concat(log->text, "\n");
-
-   return 1;
-}
-
-int
-slang_info_log_print(slang_info_log * log, const char *msg, ...)
-{
-   va_list va;
-   char buf[1024];
-
-   va_start(va, msg);
-   vsprintf(buf, msg, va);
-   va_end(va);
-   return slang_info_log_message(log, NULL, buf);
-}
-
-int
-slang_info_log_error(slang_info_log * log, const char *msg, ...)
-{
-   va_list va;
-   char buf[1024];
-
-   va_start(va, msg);
-   vsprintf(buf, msg, va);
-   va_end(va);
-   log->error_flag = GL_TRUE;
-   if (slang_info_log_message(log, "Error", buf))
-      return 1;
-   slang_info_log_memory(log);
-   return 0;
-}
-
-int
-slang_info_log_warning(slang_info_log * log, const char *msg, ...)
-{
-   va_list va;
-   char buf[1024];
-
-   va_start(va, msg);
-   vsprintf(buf, msg, va);
-   va_end(va);
-   if (slang_info_log_message(log, "Warning", buf))
-      return 1;
-   slang_info_log_memory(log);
-   return 0;
-}
-
-void
-slang_info_log_memory(slang_info_log * log)
-{
-   if (!slang_info_log_message(log, "Error", "Out of memory.")) {
-      log->dont_free_text = GL_TRUE;
-      log->error_flag = GL_TRUE;
-      log->text = out_of_memory;
-   }
-}
diff --git a/src/mesa/slang/slang_log.h b/src/mesa/slang/slang_log.h
deleted file mode 100644 (file)
index 544a266..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef SLANG_LOG_H
-#define SLANG_LOG_H
-
-
-#include "main/glheader.h"
-
-typedef struct slang_info_log_
-{
-   char *text;
-   GLboolean dont_free_text;
-   GLboolean error_flag;
-} slang_info_log;
-
-
-extern void
-slang_info_log_construct(slang_info_log *);
-
-extern void
-slang_info_log_destruct(slang_info_log *);
-
-extern int
-slang_info_log_print(slang_info_log *, const char *, ...);
-
-extern int
-slang_info_log_error(slang_info_log *, const char *, ...);
-
-extern int
-slang_info_log_warning(slang_info_log *, const char *, ...);
-
-extern void
-slang_info_log_memory(slang_info_log *);
-
-
-#endif /* SLANG_LOG_H */
diff --git a/src/mesa/slang/slang_mem.c b/src/mesa/slang/slang_mem.c
deleted file mode 100644 (file)
index 5eaa7c4..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_mem.c
- *
- * Memory manager for GLSL compiler.  The general idea is to do all
- * allocations out of a large pool then just free the pool when done
- * compiling to avoid intricate malloc/free tracking and memory leaks.
- *
- * \author Brian Paul
- */
-
-#include "main/context.h"
-#include "main/macros.h"
-#include "slang_mem.h"
-
-
-#define GRANULARITY 8
-#define ROUND_UP(B)  ( ((B) + (GRANULARITY - 1)) & ~(GRANULARITY - 1) )
-
-
-/** If 1, use conventional malloc/free.  Helpful for debugging */
-#define USE_MALLOC_FREE 0
-
-
-struct slang_mempool_
-{
-   GLuint Size, Used, Count, Largest;
-   char *Data;
-   struct slang_mempool_ *Next;
-};
-
-
-slang_mempool *
-_slang_new_mempool(GLuint initialSize)
-{
-   slang_mempool *pool = (slang_mempool *) calloc(1, sizeof(slang_mempool));
-   if (pool) {
-      pool->Data = (char *) calloc(1, initialSize);
-      /*printf("ALLOC MEMPOOL %d at %p\n", initialSize, pool->Data);*/
-      if (!pool->Data) {
-         free(pool);
-         return NULL;
-      }
-      pool->Size = initialSize;
-      pool->Used = 0;
-   }
-   return pool;
-}
-
-
-void
-_slang_delete_mempool(slang_mempool *pool)
-{
-   GLuint total = 0;
-   while (pool) {
-      slang_mempool *next = pool->Next;
-      /*
-      printf("DELETE MEMPOOL %u / %u  count=%u largest=%u\n",
-             pool->Used, pool->Size, pool->Count, pool->Largest);
-      */
-      total += pool->Used;
-      free(pool->Data);
-      free(pool);
-      pool = next;
-   }
-   /*printf("TOTAL ALLOCATED: %u\n", total);*/
-}
-
-
-#ifdef DEBUG
-static void
-check_zero(const char *addr, GLuint n)
-{
-   GLuint i;
-   for (i = 0; i < n; i++) {
-      assert(addr[i]==0);
-   }
-}
-#endif
-
-
-#ifdef DEBUG
-static GLboolean
-is_valid_address(const slang_mempool *pool, void *addr)
-{
-   while (pool) {
-      if ((char *) addr >= pool->Data &&
-          (char *) addr < pool->Data + pool->Used)
-         return GL_TRUE;
-
-      pool = pool->Next;
-   }
-   return GL_FALSE;
-}
-#endif
-
-
-/**
- * Alloc 'bytes' from shader mempool.
- */
-void *
-_slang_alloc(GLuint bytes)
-{
-#if USE_MALLOC_FREE
-   return calloc(1, bytes);
-#else
-   slang_mempool *pool;
-   GET_CURRENT_CONTEXT(ctx);
-   pool = (slang_mempool *) ctx->Shader.MemPool;
-
-   if (bytes == 0)
-      bytes = 1;
-
-   while (pool) {
-      if (pool->Used + bytes <= pool->Size) {
-         /* found room */
-         void *addr = (void *) (pool->Data + pool->Used);
-#ifdef DEBUG
-         check_zero((char*) addr, bytes);
-#endif
-         pool->Used += ROUND_UP(bytes);
-         pool->Largest = MAX2(pool->Largest, bytes);
-         pool->Count++;
-         /*printf("alloc %u  Used %u\n", bytes, pool->Used);*/
-         return addr;
-      }
-      else if (pool->Next) {
-         /* try next block */
-         pool = pool->Next;
-      }
-      else {
-         /* alloc new pool */
-         const GLuint sz = MAX2(bytes, pool->Size);
-         pool->Next = _slang_new_mempool(sz);
-         if (!pool->Next) {
-            /* we're _really_ out of memory */
-            return NULL;
-         }
-         else {
-            pool = pool->Next;
-            pool->Largest = bytes;
-            pool->Count++;
-            pool->Used = ROUND_UP(bytes);
-#ifdef DEBUG
-            check_zero((char*) pool->Data, bytes);
-#endif
-            return (void *) pool->Data;
-         }
-      }
-   }
-   return NULL;
-#endif
-}
-
-
-void *
-_slang_realloc(void *oldBuffer, GLuint oldSize, GLuint newSize)
-{
-#if USE_MALLOC_FREE
-   return _mesa_realloc(oldBuffer, oldSize, newSize);
-#else
-   GET_CURRENT_CONTEXT(ctx);
-   slang_mempool *pool = (slang_mempool *) ctx->Shader.MemPool;
-   (void) pool;
-
-   if (newSize < oldSize) {
-      return oldBuffer;
-   }
-   else {
-      const GLuint copySize = (oldSize < newSize) ? oldSize : newSize;
-      void *newBuffer = _slang_alloc(newSize);
-
-      if (oldBuffer)
-         ASSERT(is_valid_address(pool, oldBuffer));
-
-      if (newBuffer && oldBuffer && copySize > 0)
-         memcpy(newBuffer, oldBuffer, copySize);
-
-      return newBuffer;
-   }
-#endif
-}
-
-
-/**
- * Clone string, storing in current mempool.
- */
-char *
-_slang_strdup(const char *s)
-{
-   if (s) {
-      size_t l = strlen(s);
-      char *s2 = (char *) _slang_alloc(l + 1);
-      if (s2)
-         strcpy(s2, s);
-      return s2;
-   }
-   else {
-      return NULL;
-   }
-}
-
-
-/**
- * Don't actually free memory, but mark it (for debugging).
- */
-void
-_slang_free(void *addr)
-{
-#if USE_MALLOC_FREE
-   free(addr);
-#else
-   if (addr) {
-      GET_CURRENT_CONTEXT(ctx);
-      slang_mempool *pool = (slang_mempool *) ctx->Shader.MemPool;
-      (void) pool;
-      ASSERT(is_valid_address(pool, addr));
-   }
-#endif
-}
diff --git a/src/mesa/slang/slang_mem.h b/src/mesa/slang/slang_mem.h
deleted file mode 100644 (file)
index b5bfae2..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef SLANG_MEM_H
-#define SLANG_MEM_H
-
-
-#include "main/imports.h"
-
-
-typedef struct slang_mempool_ slang_mempool;
-
-
-extern slang_mempool *
-_slang_new_mempool(GLuint initialSize);
-
-extern void
-_slang_delete_mempool(slang_mempool *pool);
-
-extern void *
-_slang_alloc(GLuint bytes);
-
-extern void *
-_slang_realloc(void *oldBuffer, GLuint oldSize, GLuint newSize);
-
-extern char *
-_slang_strdup(const char *s);
-
-extern void
-_slang_free(void *addr);
-
-
-#endif
diff --git a/src/mesa/slang/slang_print.c b/src/mesa/slang/slang_print.c
deleted file mode 100644 (file)
index 6b34f39..0000000
+++ /dev/null
@@ -1,883 +0,0 @@
-
-/**
- * Dump/print a slang_operation tree
- */
-
-
-#include "main/imports.h"
-#include "slang_compile.h"
-#include "slang_print.h"
-
-
-static void
-spaces(int n)
-{
-   while (n--)
-      printf(" ");
-}
-
-
-static void
-print_type(const slang_fully_specified_type *t)
-{
-   switch (t->qualifier) {
-   case SLANG_QUAL_NONE:
-      /*printf("");*/
-      break;
-   case SLANG_QUAL_CONST:
-      printf("const ");
-      break;
-   case SLANG_QUAL_ATTRIBUTE:
-      printf("attrib ");
-      break;
-   case SLANG_QUAL_VARYING:
-      printf("varying ");
-      break;
-   case SLANG_QUAL_UNIFORM:
-      printf("uniform ");
-      break;
-   case SLANG_QUAL_OUT:
-      printf("output ");
-      break;
-   case SLANG_QUAL_INOUT:
-      printf("inout ");
-      break;
-   case SLANG_QUAL_FIXEDOUTPUT:
-      printf("fixedoutput");
-      break;
-   case SLANG_QUAL_FIXEDINPUT:
-      printf("fixedinput");
-      break;
-   default:
-      printf("unknown qualifer!");
-   }
-
-   switch (t->specifier.type) {
-   case SLANG_SPEC_VOID:
-      printf("void");
-      break;
-   case SLANG_SPEC_BOOL:
-      printf("bool");
-      break;
-   case SLANG_SPEC_BVEC2:
-      printf("bvec2");
-      break;
-   case SLANG_SPEC_BVEC3:
-      printf("bvec3");
-      break;
-   case SLANG_SPEC_BVEC4:
-      printf("bvec4");
-      break;
-   case SLANG_SPEC_INT:
-      printf("int");
-      break;
-   case SLANG_SPEC_IVEC2:
-      printf("ivec2");
-      break;
-   case SLANG_SPEC_IVEC3:
-      printf("ivec3");
-      break;
-   case SLANG_SPEC_IVEC4:
-      printf("ivec4");
-      break;
-   case SLANG_SPEC_FLOAT:
-      printf("float");
-      break;
-   case SLANG_SPEC_VEC2:
-      printf("vec2");
-      break;
-   case SLANG_SPEC_VEC3:
-      printf("vec3");
-      break;
-   case SLANG_SPEC_VEC4:
-      printf("vec4");
-      break;
-   case SLANG_SPEC_MAT2:
-      printf("mat2");
-      break;
-   case SLANG_SPEC_MAT3:
-      printf("mat3");
-      break;
-   case SLANG_SPEC_MAT4:
-      printf("mat4");
-      break;
-   case SLANG_SPEC_MAT23:
-      printf("mat2x3");
-      break;
-   case SLANG_SPEC_MAT32:
-      printf("mat3x2");
-      break;
-   case SLANG_SPEC_MAT24:
-      printf("mat2x4");
-      break;
-   case SLANG_SPEC_MAT42:
-      printf("mat4x2");
-      break;
-   case SLANG_SPEC_MAT34:
-      printf("mat3x4");
-      break;
-   case SLANG_SPEC_MAT43:
-      printf("mat4x3");
-      break;
-   case SLANG_SPEC_SAMPLER_1D:
-      printf("sampler1D");
-      break;
-   case SLANG_SPEC_SAMPLER_2D:
-      printf("sampler2D");
-      break;
-   case SLANG_SPEC_SAMPLER_3D:
-      printf("sampler3D");
-      break;
-   case SLANG_SPEC_SAMPLER_CUBE:
-      printf("samplerCube");
-      break;
-   case SLANG_SPEC_SAMPLER_1D_SHADOW:
-      printf("sampler1DShadow");
-      break;
-   case SLANG_SPEC_SAMPLER_2D_SHADOW:
-      printf("sampler2DShadow");
-      break;
-   case SLANG_SPEC_STRUCT:
-      printf("struct");
-      break;
-   case SLANG_SPEC_ARRAY:
-      printf("array");
-      break;
-   default:
-      printf("unknown type");
-   }
-   /*printf("\n");*/
-}
-
-
-static void
-print_variable(const slang_variable *v, int indent)
-{
-   spaces(indent);
-   printf("VAR ");
-   print_type(&v->type);
-   printf(" %s (at %p)", (char *) v->a_name, (void *) v);
-   if (v->initializer) {
-      printf(" :=\n");
-      slang_print_tree(v->initializer, indent + 3);
-   }
-   else {
-      printf(";\n");
-   }
-}
-
-
-static void
-print_binary(const slang_operation *op, const char *oper, int indent)
-{
-   assert(op->num_children == 2);
-#if 0
-   printf("binary at %p locals=%p outer=%p\n",
-          (void *) op,
-          (void *) op->locals,
-          (void *) op->locals->outer_scope);
-#endif
-   slang_print_tree(&op->children[0], indent + 3);
-   spaces(indent);
-   printf("%s at %p locals=%p outer=%p\n",
-          oper, (void *) op, (void *) op->locals,
-          (void *) op->locals->outer_scope);
-   slang_print_tree(&op->children[1], indent + 3);
-}
-
-
-static void
-print_generic2(const slang_operation *op, const char *oper,
-               const char *s, int indent)
-{
-   GLuint i;
-   if (oper) {
-      spaces(indent);
-      printf("%s %s at %p locals=%p outer=%p\n",
-             oper, s, (void *) op, (void *) op->locals, 
-             (void *) op->locals->outer_scope);
-   }
-   for (i = 0; i < op->num_children; i++) {
-      spaces(indent);
-      printf("//child %u of %u:\n", i, op->num_children);
-      slang_print_tree(&op->children[i], indent);
-   }
-}
-
-static void
-print_generic(const slang_operation *op, const char *oper, int indent)
-{
-   print_generic2(op, oper, "", indent);
-}
-
-
-static const slang_variable_scope *
-find_scope(const slang_variable_scope *s, slang_atom name)
-{
-   GLuint i;
-   for (i = 0; i < s->num_variables; i++) {
-      if (s->variables[i]->a_name == name)
-         return s;
-   }
-   if (s->outer_scope)
-      return find_scope(s->outer_scope, name);
-   else
-      return NULL;
-}
-
-static const slang_variable *
-find_var(const slang_variable_scope *s, slang_atom name)
-{
-   GLuint i;
-   for (i = 0; i < s->num_variables; i++) {
-      if (s->variables[i]->a_name == name)
-         return s->variables[i];
-   }
-   if (s->outer_scope)
-      return find_var(s->outer_scope, name);
-   else
-      return NULL;
-}
-
-
-void
-slang_print_tree(const slang_operation *op, int indent)
-{
-   GLuint i;
-
-   switch (op->type) {
-
-   case SLANG_OPER_NONE:
-      spaces(indent);
-      printf("SLANG_OPER_NONE\n");
-      break;
-
-   case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
-      spaces(indent);
-      printf("{ locals=%p  outer=%p\n", (void*)op->locals, (void*)op->locals->outer_scope);
-      print_generic(op, NULL, indent+3);
-      spaces(indent);
-      printf("}\n");
-      break;
-
-   case SLANG_OPER_BLOCK_NEW_SCOPE:
-   case SLANG_OPER_NON_INLINED_CALL:
-      spaces(indent);
-      printf("{{ // new scope  locals=%p outer=%p: ",
-             (void *) op->locals,
-             (void *) op->locals->outer_scope);
-      for (i = 0; i < op->locals->num_variables; i++) {
-         printf("%s ", (char *) op->locals->variables[i]->a_name);
-      }
-      printf("\n");
-      print_generic(op, NULL, indent+3);
-      spaces(indent);
-      printf("}}\n");
-      break;
-
-   case SLANG_OPER_VARIABLE_DECL:
-      assert(op->num_children == 0 || op->num_children == 1);
-      {
-         slang_variable *v;
-         v = _slang_variable_locate(op->locals, op->a_id, GL_TRUE);
-         if (v) {
-            const slang_variable_scope *scope;
-            spaces(indent);
-            printf("DECL (locals=%p outer=%p) ", (void*)op->locals, (void*) op->locals->outer_scope);
-            print_type(&v->type);
-            printf(" %s (%p)", (char *) op->a_id,
-                   (void *) find_var(op->locals, op->a_id));
-
-            scope = find_scope(op->locals, op->a_id);
-            printf(" (in scope %p) ", (void *) scope);
-            assert(scope);
-            if (op->num_children == 1) {
-               printf(" :=\n");
-               slang_print_tree(&op->children[0], indent + 3);
-            }
-            else if (v->initializer) {
-               printf(" := INITIALIZER\n");
-               slang_print_tree(v->initializer, indent + 3);
-            }
-            else {
-               printf(";\n");
-            }
-            /*
-            spaces(indent);
-            printf("TYPE: ");
-            print_type(&v->type);
-            spaces(indent);
-            printf("ADDR: %d  size: %d\n", v->address, v->size);
-            */
-         }
-         else {
-            spaces(indent);
-            printf("DECL %s (anonymous variable!!!!)\n", (char *) op->a_id);
-         }
-      }
-      break;
-
-   case SLANG_OPER_ASM:
-      spaces(indent);
-      printf("ASM: %s at %p locals=%p outer=%p\n",
-             (char *) op->a_id,
-             (void *) op,
-             (void *) op->locals,
-             (void *) op->locals->outer_scope);
-      print_generic(op, "ASM", indent+3);
-      break;
-
-   case SLANG_OPER_BREAK:
-      spaces(indent);
-      printf("BREAK\n");
-      break;
-
-   case SLANG_OPER_CONTINUE:
-      spaces(indent);
-      printf("CONTINUE\n");
-      break;
-
-   case SLANG_OPER_DISCARD:
-      spaces(indent);
-      printf("DISCARD\n");
-      break;
-
-   case SLANG_OPER_RETURN:
-      spaces(indent);
-      printf("RETURN\n");
-      if (op->num_children > 0)
-         slang_print_tree(&op->children[0], indent + 3);
-      break;
-
-   case SLANG_OPER_RETURN_INLINED:
-      spaces(indent);
-      printf("RETURN_INLINED\n");
-      if (op->num_children > 0)
-         slang_print_tree(&op->children[0], indent + 3);
-      break;
-
-   case SLANG_OPER_LABEL:
-      spaces(indent);
-      printf("LABEL %s\n", (char *) op->a_id);
-      break;
-
-   case SLANG_OPER_EXPRESSION:
-      spaces(indent);
-      printf("EXPR:  locals=%p outer=%p\n",
-             (void *) op->locals,
-             (void *) op->locals->outer_scope);
-      /*print_generic(op, "SLANG_OPER_EXPRESSION", indent);*/
-      slang_print_tree(&op->children[0], indent + 3);
-      break;
-
-   case SLANG_OPER_IF:
-      spaces(indent);
-      printf("IF\n");
-      slang_print_tree(&op->children[0], indent + 3);
-      spaces(indent);
-      printf("THEN\n");
-      slang_print_tree(&op->children[1], indent + 3);
-      spaces(indent);
-      printf("ELSE\n");
-      slang_print_tree(&op->children[2], indent + 3);
-      spaces(indent);
-      printf("ENDIF\n");
-      break;
-
-   case SLANG_OPER_WHILE:
-      assert(op->num_children == 2);
-      spaces(indent);
-      printf("WHILE LOOP: locals = %p\n", (void *) op->locals);
-      indent += 3;
-      spaces(indent);
-      printf("WHILE cond:\n");
-      slang_print_tree(&op->children[0], indent + 3);
-      spaces(indent);
-      printf("WHILE body:\n");
-      slang_print_tree(&op->children[1], indent + 3);
-      indent -= 3;
-      spaces(indent);
-      printf("END WHILE LOOP\n");
-      break;
-
-   case SLANG_OPER_DO:
-      spaces(indent);
-      printf("DO LOOP: locals = %p\n", (void *) op->locals);
-      indent += 3;
-      spaces(indent);
-      printf("DO body:\n");
-      slang_print_tree(&op->children[0], indent + 3);
-      spaces(indent);
-      printf("DO cond:\n");
-      slang_print_tree(&op->children[1], indent + 3);
-      indent -= 3;
-      spaces(indent);
-      printf("END DO LOOP\n");
-      break;
-
-   case SLANG_OPER_FOR:
-      spaces(indent);
-      printf("FOR LOOP: locals = %p\n", (void *) op->locals);
-      indent += 3;
-      spaces(indent);
-      printf("FOR init:\n");
-      slang_print_tree(&op->children[0], indent + 3);
-      spaces(indent);
-      printf("FOR condition:\n");
-      slang_print_tree(&op->children[1], indent + 3);
-      spaces(indent);
-      printf("FOR step:\n");
-      slang_print_tree(&op->children[2], indent + 3);
-      spaces(indent);
-      printf("FOR body:\n");
-      slang_print_tree(&op->children[3], indent + 3);
-      indent -= 3;
-      spaces(indent);
-      printf("ENDFOR\n");
-      /*
-      print_generic(op, "FOR", indent + 3);
-      */
-      break;
-
-   case SLANG_OPER_VOID:
-      spaces(indent);
-      printf("(oper-void)\n");
-      break;
-
-   case SLANG_OPER_LITERAL_BOOL:
-      spaces(indent);
-      printf("LITERAL (");
-      for (i = 0; i < op->literal_size; i++)
-         printf("%s ", op->literal[0] ? "TRUE" : "FALSE");
-      printf(")\n");
-
-      break;
-
-   case SLANG_OPER_LITERAL_INT:
-      spaces(indent);
-      printf("LITERAL (");
-      for (i = 0; i < op->literal_size; i++)
-         printf("%d ", (int) op->literal[i]);
-      printf(")\n");
-      break;
-
-   case SLANG_OPER_LITERAL_FLOAT:
-      spaces(indent);
-      printf("LITERAL (");
-      for (i = 0; i < op->literal_size; i++)
-         printf("%f ", op->literal[i]);
-      printf(")\n");
-      break;
-
-   case SLANG_OPER_IDENTIFIER:
-      {
-         const slang_variable_scope *scope;
-         spaces(indent);
-         if (op->var && op->var->a_name) {
-            scope = find_scope(op->locals, op->var->a_name);
-            printf("VAR %s  (in scope %p)\n", (char *) op->var->a_name,
-                   (void *) scope);
-            assert(scope);
-         }
-         else {
-            scope = find_scope(op->locals, op->a_id);
-            printf("VAR' %s  (in scope %p) locals=%p outer=%p\n",
-                   (char *) op->a_id,
-                   (void *) scope,
-                   (void *) op->locals,
-                   (void *) op->locals->outer_scope);
-            /*assert(scope);*/
-         }
-      }
-      break;
-
-   case SLANG_OPER_SEQUENCE:
-      print_generic(op, "COMMA-SEQ", indent+3);
-      break;
-
-   case SLANG_OPER_ASSIGN:
-      spaces(indent);
-      printf("ASSIGNMENT  locals=%p outer=%p\n",
-             (void *) op->locals,
-             (void *) op->locals->outer_scope);
-      print_binary(op, ":=", indent);
-      break;
-
-   case SLANG_OPER_ADDASSIGN:
-      spaces(indent);
-      printf("ASSIGN\n");
-      print_binary(op, "+=", indent);
-      break;
-
-   case SLANG_OPER_SUBASSIGN:
-      spaces(indent);
-      printf("ASSIGN\n");
-      print_binary(op, "-=", indent);
-      break;
-
-   case SLANG_OPER_MULASSIGN:
-      spaces(indent);
-      printf("ASSIGN\n");
-      print_binary(op, "*=", indent);
-      break;
-
-   case SLANG_OPER_DIVASSIGN:
-      spaces(indent);
-      printf("ASSIGN\n");
-      print_binary(op, "/=", indent);
-      break;
-
-       /*SLANG_OPER_MODASSIGN,*/
-       /*SLANG_OPER_LSHASSIGN,*/
-       /*SLANG_OPER_RSHASSIGN,*/
-       /*SLANG_OPER_ORASSIGN,*/
-       /*SLANG_OPER_XORASSIGN,*/
-       /*SLANG_OPER_ANDASSIGN,*/
-   case SLANG_OPER_SELECT:
-      spaces(indent);
-      printf("SLANG_OPER_SELECT n=%d\n", op->num_children);
-      assert(op->num_children == 3);
-      slang_print_tree(&op->children[0], indent+3);
-      spaces(indent);
-      printf("?\n");
-      slang_print_tree(&op->children[1], indent+3);
-      spaces(indent);
-      printf(":\n");
-      slang_print_tree(&op->children[2], indent+3);
-      break;
-
-   case SLANG_OPER_LOGICALOR:
-      print_binary(op, "||", indent);
-      break;
-
-   case SLANG_OPER_LOGICALXOR:
-      print_binary(op, "^^", indent);
-      break;
-
-   case SLANG_OPER_LOGICALAND:
-      print_binary(op, "&&", indent);
-      break;
-
-   /*SLANG_OPER_BITOR*/
-   /*SLANG_OPER_BITXOR*/
-   /*SLANG_OPER_BITAND*/
-   case SLANG_OPER_EQUAL:
-      print_binary(op, "==", indent);
-      break;
-
-   case SLANG_OPER_NOTEQUAL:
-      print_binary(op, "!=", indent);
-      break;
-
-   case SLANG_OPER_LESS:
-      print_binary(op, "<", indent);
-      break;
-
-   case SLANG_OPER_GREATER:
-      print_binary(op, ">", indent);
-      break;
-
-   case SLANG_OPER_LESSEQUAL:
-      print_binary(op, "<=", indent);
-      break;
-
-   case SLANG_OPER_GREATEREQUAL:
-      print_binary(op, ">=", indent);
-      break;
-
-   /*SLANG_OPER_LSHIFT*/
-   /*SLANG_OPER_RSHIFT*/
-   case SLANG_OPER_ADD:
-      print_binary(op, "+", indent);
-      break;
-
-   case SLANG_OPER_SUBTRACT:
-      print_binary(op, "-", indent);
-      break;
-
-   case SLANG_OPER_MULTIPLY:
-      print_binary(op, "*", indent);
-      break;
-
-   case SLANG_OPER_DIVIDE:
-      print_binary(op, "/", indent);
-      break;
-
-   /*SLANG_OPER_MODULUS*/
-   case SLANG_OPER_PREINCREMENT:
-      spaces(indent);
-      printf("PRE++\n");
-      slang_print_tree(&op->children[0], indent+3);
-      break;
-
-   case SLANG_OPER_PREDECREMENT:
-      spaces(indent);
-      printf("PRE--\n");
-      slang_print_tree(&op->children[0], indent+3);
-      break;
-
-   case SLANG_OPER_PLUS:
-      spaces(indent);
-      printf("SLANG_OPER_PLUS\n");
-      break;
-
-   case SLANG_OPER_MINUS:
-      spaces(indent);
-      printf("SLANG_OPER_MINUS\n");
-      break;
-
-   /*SLANG_OPER_COMPLEMENT*/
-   case SLANG_OPER_NOT:
-      spaces(indent);
-      printf("NOT\n");
-      slang_print_tree(&op->children[0], indent+3);
-      break;
-
-   case SLANG_OPER_SUBSCRIPT:
-      spaces(indent);
-      printf("SLANG_OPER_SUBSCRIPT locals=%p outer=%p\n",
-             (void *) op->locals,
-             (void *) op->locals->outer_scope);
-      print_generic(op, NULL, indent+3);
-      break;
-
-   case SLANG_OPER_CALL:
-#if 0
-         slang_function *fun
-            = _slang_function_locate(A->space.funcs, oper->a_id,
-                                     oper->children,
-                                     oper->num_children, &A->space, A->atoms);
-#endif
-      spaces(indent);
-      printf("CALL %s(\n", (char *) op->a_id);
-      for (i = 0; i < op->num_children; i++) {
-         slang_print_tree(&op->children[i], indent+3);
-         if (i + 1 < op->num_children) {
-            spaces(indent + 3);
-            printf(",\n");
-         }
-      }
-      spaces(indent);
-      printf(")\n");
-      break;
-
-   case SLANG_OPER_METHOD:
-      spaces(indent);
-      printf("METHOD CALL %s.%s\n", (char *) op->a_obj, (char *) op->a_id);
-      break;
-
-   case SLANG_OPER_FIELD:
-      spaces(indent);
-      printf("FIELD %s of\n", (char*) op->a_id);
-      slang_print_tree(&op->children[0], indent+3);
-      break;
-
-   case SLANG_OPER_POSTINCREMENT:
-      spaces(indent);
-      printf("POST++\n");
-      slang_print_tree(&op->children[0], indent+3);
-      break;
-
-   case SLANG_OPER_POSTDECREMENT:
-      spaces(indent);
-      printf("POST--\n");
-      slang_print_tree(&op->children[0], indent+3);
-      break;
-
-   default:
-      printf("unknown op->type %d\n", (int) op->type);
-   }
-
-}
-
-
-
-void
-slang_print_function(const slang_function *f, GLboolean body)
-{
-   GLuint i;
-
-#if 0
-   if (strcmp((char *) f->header.a_name, "main") != 0)
-     return;
-#endif
-
-   printf("FUNCTION %s ( scope=%p\n",
-          (char *) f->header.a_name, (void *) f->parameters);
-
-   for (i = 0; i < f->param_count; i++) {
-      print_variable(f->parameters->variables[i], 3);
-   }
-
-   printf(") param scope = %p\n", (void *) f->parameters);
-
-   if (body && f->body)
-      slang_print_tree(f->body, 0);
-}
-
-
-
-
-
-const char *
-slang_type_qual_string(slang_type_qualifier q)
-{
-   switch (q) {
-   case SLANG_QUAL_NONE:
-      return "none";
-   case SLANG_QUAL_CONST:
-      return "const";
-   case SLANG_QUAL_ATTRIBUTE:
-      return "attribute";
-   case SLANG_QUAL_VARYING:
-      return "varying";
-   case SLANG_QUAL_UNIFORM:
-      return "uniform";
-   case SLANG_QUAL_OUT:
-      return "out";
-   case SLANG_QUAL_INOUT:
-      return "inout";
-   case SLANG_QUAL_FIXEDOUTPUT:
-      return "fixedoutput";
-   case SLANG_QUAL_FIXEDINPUT:
-      return "fixedinputk";
-   default:
-      return "qual?";
-   }
-}
-
-
-static const char *
-slang_type_string(slang_type_specifier_type t)
-{
-   switch (t) {
-   case SLANG_SPEC_VOID:
-      return "void";
-   case SLANG_SPEC_BOOL:
-      return "bool";
-   case SLANG_SPEC_BVEC2:
-      return "bvec2";
-   case SLANG_SPEC_BVEC3:
-      return "bvec3";
-   case SLANG_SPEC_BVEC4:
-      return "bvec4";
-   case SLANG_SPEC_INT:
-      return "int";
-   case SLANG_SPEC_IVEC2:
-      return "ivec2";
-   case SLANG_SPEC_IVEC3:
-      return "ivec3";
-   case SLANG_SPEC_IVEC4:
-      return "ivec4";
-   case SLANG_SPEC_FLOAT:
-      return "float";
-   case SLANG_SPEC_VEC2:
-      return "vec2";
-   case SLANG_SPEC_VEC3:
-      return "vec3";
-   case SLANG_SPEC_VEC4:
-      return "vec4";
-   case SLANG_SPEC_MAT2:
-      return "mat2";
-   case SLANG_SPEC_MAT3:
-      return "mat3";
-   case SLANG_SPEC_MAT4:
-      return "mat4";
-   case SLANG_SPEC_SAMPLER_1D:
-      return "sampler1D";
-   case SLANG_SPEC_SAMPLER_2D:
-      return "sampler2D";
-   case SLANG_SPEC_SAMPLER_3D:
-      return "sampler3D";
-   case SLANG_SPEC_SAMPLER_CUBE:
-      return "samplerCube";
-   case SLANG_SPEC_SAMPLER_1D_SHADOW:
-      return "sampler1DShadow";
-   case SLANG_SPEC_SAMPLER_2D_SHADOW:
-      return "sampler2DShadow";
-   case SLANG_SPEC_SAMPLER_RECT:
-      return "sampler2DRect";
-   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
-      return "sampler2DRectShadow";
-   case SLANG_SPEC_STRUCT:
-      return "struct";
-   case SLANG_SPEC_ARRAY:
-      return "array";
-   default:
-      return "type?";
-   }
-}
-
-
-static const char *
-slang_fq_type_string(const slang_fully_specified_type *t)
-{
-   static char str[1000];
-   _mesa_snprintf(str, sizeof(str), "%s %s", slang_type_qual_string(t->qualifier),
-      slang_type_string(t->specifier.type));
-   return str;
-}
-
-
-void
-slang_print_type(const slang_fully_specified_type *t)
-{
-   printf("%s %s", slang_type_qual_string(t->qualifier),
-      slang_type_string(t->specifier.type));
-}
-
-
-#if 0
-static char *
-slang_var_string(const slang_variable *v)
-{
-   static char str[1000];
-   _mesa_snprintf(str, sizeof(str), "%s : %s",
-                  (char *) v->a_name,
-                  slang_fq_type_string(&v->type));
-   return str;
-}
-#endif
-
-
-void
-slang_print_variable(const slang_variable *v)
-{
-   printf("Name: %s\n", (char *) v->a_name);
-   printf("Type: %s\n", slang_fq_type_string(&v->type));
-}
-
-
-void
-_slang_print_var_scope(const slang_variable_scope *vars, int indent)
-{
-   GLuint i;
-
-   spaces(indent);
-   printf("Var scope %p  %d vars:\n", (void *) vars, vars->num_variables);
-   for (i = 0; i < vars->num_variables; i++) {
-      spaces(indent + 3);
-      printf("%s (at %p)\n", (char *) vars->variables[i]->a_name, (void*) (vars->variables + i));
-   }
-   spaces(indent + 3);
-   printf("outer_scope = %p\n", (void*) vars->outer_scope);
-
-   if (vars->outer_scope) {
-      /*spaces(indent + 3);*/
-      _slang_print_var_scope(vars->outer_scope, indent + 3);
-   }
-}
-
-
-
-int
-slang_checksum_tree(const slang_operation *op)
-{
-   int s = op->num_children;
-   GLuint i;
-
-   for (i = 0; i < op->num_children; i++) {
-      s += slang_checksum_tree(&op->children[i]);
-   }
-   return s;
-}
diff --git a/src/mesa/slang/slang_print.h b/src/mesa/slang/slang_print.h
deleted file mode 100644 (file)
index 99da304..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-#ifndef SLANG_PRINT
-#define SLANG_PRINT
-
-#include "main/glheader.h"
-#include "slang_compile_function.h"
-#include "slang_compile_operation.h"
-#include "slang_compile_variable.h"
-#include "slang_typeinfo.h"
-
-extern void
-slang_print_function(const slang_function *f, GLboolean body);
-
-extern void
-slang_print_tree(const slang_operation *op, int indent);
-
-extern const char *
-slang_type_qual_string(slang_type_qualifier q);
-
-extern void
-slang_print_type(const slang_fully_specified_type *t);
-
-extern void
-slang_print_variable(const slang_variable *v);
-
-extern void
-_slang_print_var_scope(const slang_variable_scope *s, int indent);
-
-
-extern int
-slang_checksum_tree(const slang_operation *op);
-
-#endif /* SLANG_PRINT */
-
diff --git a/src/mesa/slang/slang_simplify.c b/src/mesa/slang/slang_simplify.c
deleted file mode 100644 (file)
index 13b9ca3..0000000
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.1
- *
- * Copyright (C) 2005-2008  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * Functions for constant folding, built-in constant lookup, and function
- * call casting.
- */
-
-
-#include "main/imports.h"
-#include "main/macros.h"
-#include "main/get.h"
-#include "slang_compile.h"
-#include "slang_codegen.h"
-#include "slang_simplify.h"
-#include "slang_print.h"
-
-
-#ifndef GL_MAX_FRAGMENT_UNIFORM_VECTORS
-#define GL_MAX_FRAGMENT_UNIFORM_VECTORS     0x8DFD
-#endif
-#ifndef GL_MAX_VERTEX_UNIFORM_VECTORS
-#define GL_MAX_VERTEX_UNIFORM_VECTORS       0x8DFB
-#endif
-#ifndef GL_MAX_VARYING_VECTORS
-#define GL_MAX_VARYING_VECTORS              0x8DFC
-#endif
-
-
-/**
- * Lookup the value of named constant, such as gl_MaxLights.
- * \return value of constant, or -1 if unknown
- */
-GLint
-_slang_lookup_constant(const char *name)
-{
-   struct constant_info {
-      const char *Name;
-      const GLenum Token;
-   };
-   static const struct constant_info info[] = {
-      { "gl_MaxClipPlanes", GL_MAX_CLIP_PLANES },
-      { "gl_MaxCombinedTextureImageUnits", GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS },
-      { "gl_MaxDrawBuffers", GL_MAX_DRAW_BUFFERS },
-      { "gl_MaxFragmentUniformComponents", GL_MAX_FRAGMENT_UNIFORM_COMPONENTS },
-      { "gl_MaxLights", GL_MAX_LIGHTS },
-      { "gl_MaxTextureUnits", GL_MAX_TEXTURE_UNITS },
-      { "gl_MaxTextureCoords", GL_MAX_TEXTURE_COORDS },
-      { "gl_MaxVertexAttribs", GL_MAX_VERTEX_ATTRIBS },
-      { "gl_MaxVertexUniformComponents", GL_MAX_VERTEX_UNIFORM_COMPONENTS },
-      { "gl_MaxVaryingFloats", GL_MAX_VARYING_FLOATS },
-      { "gl_MaxVertexTextureImageUnits", GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS },
-      { "gl_MaxTextureImageUnits", GL_MAX_TEXTURE_IMAGE_UNITS },
-#if FEATURE_es2_glsl
-      { "gl_MaxVertexUniformVectors", GL_MAX_VERTEX_UNIFORM_VECTORS },
-      { "gl_MaxVaryingVectors", GL_MAX_VARYING_VECTORS },
-      { "gl_MaxFragmentUniformVectors", GL_MAX_FRAGMENT_UNIFORM_VECTORS },
-#endif
-      { NULL, 0 }
-   };
-   GLuint i;
-
-   for (i = 0; info[i].Name; i++) {
-      if (strcmp(info[i].Name, name) == 0) {
-         /* found */
-         GLint values[16];
-         values[0] = -1;
-         _mesa_GetIntegerv(info[i].Token, values);
-         ASSERT(values[0] >= 0);  /* sanity check that glGetFloatv worked */
-         return values[0];
-      }
-   }
-   return -1;
-}
-
-
-static slang_operation_type
-literal_type(slang_operation_type t1, slang_operation_type t2)
-{
-   if (t1 == SLANG_OPER_LITERAL_FLOAT || t2 == SLANG_OPER_LITERAL_FLOAT)
-      return SLANG_OPER_LITERAL_FLOAT;
-   else
-      return SLANG_OPER_LITERAL_INT;
-}
-
-
-/**
- * Recursively traverse an AST tree, applying simplifications wherever
- * possible.
- * At the least, we do constant folding.  We need to do that much so that
- * compile-time expressions can be evaluated for things like array
- * declarations.  I.e.:  float foo[3 + 5];
- */
-void
-_slang_simplify(slang_operation *oper,
-                const slang_name_space * space,
-                slang_atom_pool * atoms)
-{
-   GLboolean isFloat[4];
-   GLboolean isBool[4];
-   GLuint i, n;
-
-   if (oper->type == SLANG_OPER_IDENTIFIER) {
-      /* see if it's a named constant */
-      GLint value = _slang_lookup_constant((char *) oper->a_id);
-      /*printf("value[%s] = %d\n", (char*) oper->a_id, value);*/
-      if (value >= 0) {
-         oper->literal[0] =
-         oper->literal[1] =
-         oper->literal[2] =
-         oper->literal[3] = (GLfloat) value;
-         oper->type = SLANG_OPER_LITERAL_INT;
-         return;
-      }
-      /* look for user-defined constant */
-      {
-         slang_variable *var;
-         var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
-         if (var) {
-            if (var->type.qualifier == SLANG_QUAL_CONST &&
-                var->initializer &&
-                (var->initializer->type == SLANG_OPER_LITERAL_INT ||
-                 var->initializer->type == SLANG_OPER_LITERAL_FLOAT)) {
-               oper->literal[0] = var->initializer->literal[0];
-               oper->literal[1] = var->initializer->literal[1];
-               oper->literal[2] = var->initializer->literal[2];
-               oper->literal[3] = var->initializer->literal[3];
-               oper->literal_size = var->initializer->literal_size;
-               oper->type = var->initializer->type;
-               /*
-               printf("value[%s] = %f\n",
-                      (char*) oper->a_id, oper->literal[0]);
-               */
-               return;
-            }
-         }
-      }
-   }
-
-   /* first, simplify children */
-   for (i = 0; i < oper->num_children; i++) {
-      _slang_simplify(&oper->children[i], space, atoms);
-   }
-
-   /* examine children */
-   n = MIN2(oper->num_children, 4);
-   for (i = 0; i < n; i++) {
-      isFloat[i] = (oper->children[i].type == SLANG_OPER_LITERAL_FLOAT ||
-                   oper->children[i].type == SLANG_OPER_LITERAL_INT);
-      isBool[i] = (oper->children[i].type == SLANG_OPER_LITERAL_BOOL);
-   }
-                              
-   if (oper->num_children == 2 && isFloat[0] && isFloat[1]) {
-      /* probably simple arithmetic */
-      switch (oper->type) {
-      case SLANG_OPER_ADD:
-         for (i = 0; i < 4; i++) {
-            oper->literal[i]
-               = oper->children[0].literal[i] + oper->children[1].literal[i];
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         oper->type = literal_type(oper->children[0].type, 
-                                   oper->children[1].type);
-         slang_operation_destruct(oper);  /* frees unused children */
-         return;
-      case SLANG_OPER_SUBTRACT:
-         for (i = 0; i < 4; i++) {
-            oper->literal[i]
-               = oper->children[0].literal[i] - oper->children[1].literal[i];
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         oper->type = literal_type(oper->children[0].type, 
-                                   oper->children[1].type);
-         slang_operation_destruct(oper);
-         return;
-      case SLANG_OPER_MULTIPLY:
-         for (i = 0; i < 4; i++) {
-            oper->literal[i]
-               = oper->children[0].literal[i] * oper->children[1].literal[i];
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         oper->type = literal_type(oper->children[0].type, 
-                                   oper->children[1].type);
-         slang_operation_destruct(oper);
-         return;
-      case SLANG_OPER_DIVIDE:
-         for (i = 0; i < 4; i++) {
-            oper->literal[i]
-               = oper->children[0].literal[i] / oper->children[1].literal[i];
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         oper->type = literal_type(oper->children[0].type, 
-                                   oper->children[1].type);
-         slang_operation_destruct(oper);
-         return;
-      default:
-         ; /* nothing */
-      }
-   }
-
-   if (oper->num_children == 1 && isFloat[0]) {
-      switch (oper->type) {
-      case SLANG_OPER_MINUS:
-         for (i = 0; i < 4; i++) {
-            oper->literal[i] = -oper->children[0].literal[i];
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         slang_operation_destruct(oper);
-         oper->type = SLANG_OPER_LITERAL_FLOAT;
-         return;
-      case SLANG_OPER_PLUS:
-         COPY_4V(oper->literal, oper->children[0].literal);
-         oper->literal_size = oper->children[0].literal_size;
-         slang_operation_destruct(oper);
-         oper->type = SLANG_OPER_LITERAL_FLOAT;
-         return;
-      default:
-         ; /* nothing */
-      }
-   }
-
-   if (oper->num_children == 2 && isBool[0] && isBool[1]) {
-      /* simple boolean expression */
-      switch (oper->type) {
-      case SLANG_OPER_LOGICALAND:
-         for (i = 0; i < 4; i++) {
-            const GLint a = oper->children[0].literal[i] ? 1 : 0;
-            const GLint b = oper->children[1].literal[i] ? 1 : 0;
-            oper->literal[i] = (GLfloat) (a && b);
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         slang_operation_destruct(oper);
-         oper->type = SLANG_OPER_LITERAL_BOOL;
-         return;
-      case SLANG_OPER_LOGICALOR:
-         for (i = 0; i < 4; i++) {
-            const GLint a = oper->children[0].literal[i] ? 1 : 0;
-            const GLint b = oper->children[1].literal[i] ? 1 : 0;
-            oper->literal[i] = (GLfloat) (a || b);
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         slang_operation_destruct(oper);
-         oper->type = SLANG_OPER_LITERAL_BOOL;
-         return;
-      case SLANG_OPER_LOGICALXOR:
-         for (i = 0; i < 4; i++) {
-            const GLint a = oper->children[0].literal[i] ? 1 : 0;
-            const GLint b = oper->children[1].literal[i] ? 1 : 0;
-            oper->literal[i] = (GLfloat) (a ^ b);
-         }
-         oper->literal_size = oper->children[0].literal_size;
-         slang_operation_destruct(oper);
-         oper->type = SLANG_OPER_LITERAL_BOOL;
-         return;
-      default:
-         ; /* nothing */
-      }
-   }
-
-   if (oper->num_children == 4
-       && isFloat[0] && isFloat[1] && isFloat[2] && isFloat[3]) {
-      /* vec4(flt, flt, flt, flt) constructor */
-      if (oper->type == SLANG_OPER_CALL) {
-         if (strcmp((char *) oper->a_id, "vec4") == 0) {
-            oper->literal[0] = oper->children[0].literal[0];
-            oper->literal[1] = oper->children[1].literal[0];
-            oper->literal[2] = oper->children[2].literal[0];
-            oper->literal[3] = oper->children[3].literal[0];
-            oper->literal_size = 4;
-            slang_operation_destruct(oper);
-            oper->type = SLANG_OPER_LITERAL_FLOAT;
-            return;
-         }
-      }
-   }
-
-   if (oper->num_children == 3 && isFloat[0] && isFloat[1] && isFloat[2]) {
-      /* vec3(flt, flt, flt) constructor */
-      if (oper->type == SLANG_OPER_CALL) {
-         if (strcmp((char *) oper->a_id, "vec3") == 0) {
-            oper->literal[0] = oper->children[0].literal[0];
-            oper->literal[1] = oper->children[1].literal[0];
-            oper->literal[2] = oper->children[2].literal[0];
-            oper->literal[3] = oper->literal[2];
-            oper->literal_size = 3;
-            slang_operation_destruct(oper);
-            oper->type = SLANG_OPER_LITERAL_FLOAT;
-            return;
-         }
-      }
-   }
-
-   if (oper->num_children == 2 && isFloat[0] && isFloat[1]) {
-      /* vec2(flt, flt) constructor */
-      if (oper->type == SLANG_OPER_CALL) {
-         if (strcmp((char *) oper->a_id, "vec2") == 0) {
-            oper->literal[0] = oper->children[0].literal[0];
-            oper->literal[1] = oper->children[1].literal[0];
-            oper->literal[2] = oper->literal[1];
-            oper->literal[3] = oper->literal[1];
-            oper->literal_size = 2;
-            slang_operation_destruct(oper); /* XXX oper->locals goes NULL! */
-            oper->type = SLANG_OPER_LITERAL_FLOAT;
-            assert(oper->num_children == 0);
-            return;
-         }
-      }
-   }
-
-   if (oper->num_children == 1 && isFloat[0]) {
-      /* vec2/3/4(flt, flt) constructor */
-      if (oper->type == SLANG_OPER_CALL) {
-         const char *func = (const char *) oper->a_id;
-         if (strncmp(func, "vec", 3) == 0 && func[3] >= '2' && func[3] <= '4') {
-            oper->literal[0] =
-            oper->literal[1] =
-            oper->literal[2] =
-            oper->literal[3] = oper->children[0].literal[0];
-            oper->literal_size = func[3] - '0';
-            assert(oper->literal_size >= 2);
-            assert(oper->literal_size <= 4);
-            slang_operation_destruct(oper); /* XXX oper->locals goes NULL! */
-            oper->type = SLANG_OPER_LITERAL_FLOAT;
-            assert(oper->num_children == 0);
-            return;
-         }
-      }
-   }
-}
-
-
-
-/**
- * Insert casts to try to adapt actual parameters to formal parameters for a
- * function call when an exact match for the parameter types is not found.
- * Example:
- *   void foo(int i, bool b) {}
- *   x = foo(3.15, 9);
- * Gets translated into:
- *   x = foo(int(3.15), bool(9))
- */
-GLboolean
-_slang_cast_func_params(slang_operation *callOper, const slang_function *fun,
-                        const slang_name_space * space,
-                        slang_atom_pool * atoms, slang_info_log *log)
-{
-   const GLboolean haveRetValue = _slang_function_has_return_value(fun);
-   const int numParams = fun->param_count - haveRetValue;
-   int i;
-   int dbg = 0;
-
-   if (dbg)
-      printf("Adapt call of %d args to func %s (%d params)\n",
-             callOper->num_children, (char*) fun->header.a_name, numParams);
-
-   for (i = 0; i < numParams; i++) {
-      slang_typeinfo argType;
-      slang_variable *paramVar = fun->parameters->variables[i];
-
-      /* Get type of arg[i] */
-      if (!slang_typeinfo_construct(&argType))
-         return GL_FALSE;
-      if (!_slang_typeof_operation(&callOper->children[i], space,
-                                    &argType, atoms, log)) {
-         slang_typeinfo_destruct(&argType);
-         return GL_FALSE;
-      }
-
-      /* see if arg type matches parameter type */
-      if (!slang_type_specifier_equal(&argType.spec,
-                                      &paramVar->type.specifier)) {
-         /* need to adapt arg type to match param type */
-         const char *constructorName =
-            slang_type_specifier_type_to_string(paramVar->type.specifier.type);
-         slang_operation *child = slang_operation_new(1);
-
-         if (dbg)
-            printf("Need to adapt types of arg %d\n", i);
-
-         slang_operation_copy(child, &callOper->children[i]);
-         child->locals->outer_scope = callOper->children[i].locals;
-
-#if 0
-         if (_slang_sizeof_type_specifier(&argType.spec) >
-             _slang_sizeof_type_specifier(&paramVar->type.specifier)) {
-         }
-#endif
-
-         callOper->children[i].type = SLANG_OPER_CALL;
-         callOper->children[i].a_id = slang_atom_pool_atom(atoms, constructorName);
-         callOper->children[i].num_children = 1;
-         callOper->children[i].children = child;
-      }
-
-      slang_typeinfo_destruct(&argType);
-   }
-
-   if (dbg) {
-      printf("===== New call to %s with cast arguments ===============\n",
-             (char*) fun->header.a_name);
-      slang_print_tree(callOper, 5);
-   }
-
-   return GL_TRUE;
-}
-
-
-/**
- * Adapt the arguments for a function call to match the parameters of
- * the given function.
- * This is for:
- * 1. converting/casting argument types to match parameters
- * 2. breaking up vector/matrix types into individual components to
- *    satisfy constructors.
- */
-GLboolean
-_slang_adapt_call(slang_operation *callOper, const slang_function *fun,
-                  const slang_name_space * space,
-                  slang_atom_pool * atoms, slang_info_log *log)
-{
-   const GLboolean haveRetValue = _slang_function_has_return_value(fun);
-   const int numParams = fun->param_count - haveRetValue;
-   int i;
-   int dbg = 0;
-
-   if (dbg)
-      printf("Adapt %d args to %d parameters for %s\n",
-             callOper->num_children, numParams, (char *) fun->header.a_name);
-
-   /* Only try adapting for constructors */
-   if (fun->kind != SLANG_FUNC_CONSTRUCTOR)
-      return GL_FALSE;
-
-   if (callOper->num_children != numParams) {
-      /* number of arguments doesn't match number of parameters */
-
-      /* For constructor calls, we can try to unroll vector/matrix args
-       * into individual floats/ints and try to match the function params.
-       */
-      for (i = 0; i < numParams; i++) {
-         slang_typeinfo argType;
-         GLint argSz, j;
-
-         /* Get type of arg[i] */
-         if (!slang_typeinfo_construct(&argType))
-            return GL_FALSE;
-         if (!_slang_typeof_operation(&callOper->children[i], space,
-                                       &argType, atoms, log)) {
-            slang_typeinfo_destruct(&argType);
-            return GL_FALSE;
-         }
-
-         /*
-           paramSz = _slang_sizeof_type_specifier(&paramVar->type.specifier);
-           assert(paramSz == 1);
-         */
-         argSz = _slang_sizeof_type_specifier(&argType.spec);
-         if (argSz > 1) {
-            slang_operation origArg;
-            /* break up arg[i] into components */
-            if (dbg)
-               printf("Break up arg %d from 1 to %d elements\n", i, argSz);
-
-            slang_operation_construct(&origArg);
-            slang_operation_copy(&origArg, &callOper->children[i]);
-
-            /* insert argSz-1 new children/args */
-            for (j = 0; j < argSz - 1; j++) {
-               (void) slang_operation_insert(&callOper->num_children,
-                                             &callOper->children, i);
-            }
-
-            /* replace arg[i+j] with subscript/index oper */
-            for (j = 0; j < argSz; j++) {
-               callOper->children[i + j].type = SLANG_OPER_SUBSCRIPT;
-               callOper->children[i + j].locals = _slang_variable_scope_new(callOper->locals);
-               callOper->children[i + j].num_children = 2;
-               callOper->children[i + j].children = slang_operation_new(2);
-               slang_operation_copy(&callOper->children[i + j].children[0],
-                                    &origArg);
-               callOper->children[i + j].children[1].type
-                  = SLANG_OPER_LITERAL_INT;
-               callOper->children[i + j].children[1].literal[0] = (GLfloat) j;
-            }
-         }
-      }
-   }
-
-   if (callOper->num_children < (GLuint) numParams) {
-      /* still not enough args for all params */
-      return GL_FALSE;
-   }
-   else if (callOper->num_children > (GLuint) numParams) {
-      /* now too many arguments */
-      /* just truncate */
-      callOper->num_children = (GLuint) numParams;
-   }
-
-   if (dbg) {
-      printf("===== New call to %s with adapted arguments ===============\n",
-             (char*) fun->header.a_name);
-      slang_print_tree(callOper, 5);
-   }
-
-   return GL_TRUE;
-}
diff --git a/src/mesa/slang/slang_simplify.h b/src/mesa/slang/slang_simplify.h
deleted file mode 100644 (file)
index 37fb938..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  7.1
- *
- * Copyright (C) 2005-2008  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_SIMPLIFY_H
-#define SLANG_SIMPLIFY_H
-
-
-#include "main/glheader.h"
-#include "slang_compile.h"
-#include "slang_compile_function.h"
-#include "slang_compile_operation.h"
-#include "slang_log.h"
-#include "slang_utility.h"
-
-extern GLint
-_slang_lookup_constant(const char *name);
-
-
-extern void
-_slang_simplify(slang_operation *oper,
-                const slang_name_space * space,
-                slang_atom_pool * atoms);
-
-
-extern GLboolean
-_slang_cast_func_params(slang_operation *callOper, const slang_function *fun,
-                        const slang_name_space * space,
-                        slang_atom_pool * atoms, slang_info_log *log);
-
-extern GLboolean
-_slang_adapt_call(slang_operation *callOper, const slang_function *fun,
-                  const slang_name_space * space,
-                  slang_atom_pool * atoms, slang_info_log *log);
-
-
-#endif /* SLANG_SIMPLIFY_H */
diff --git a/src/mesa/slang/slang_storage.c b/src/mesa/slang/slang_storage.c
deleted file mode 100644 (file)
index 656e156..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2005-2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_storage.c
- * slang variable storage
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_storage.h"
-#include "slang_mem.h"
-
-/* slang_storage_array */
-
-GLboolean
-slang_storage_array_construct(slang_storage_array * arr)
-{
-   arr->type = SLANG_STORE_AGGREGATE;
-   arr->aggregate = NULL;
-   arr->length = 0;
-   return GL_TRUE;
-}
-
-GLvoid
-slang_storage_array_destruct(slang_storage_array * arr)
-{
-   if (arr->aggregate != NULL) {
-      slang_storage_aggregate_destruct(arr->aggregate);
-      _slang_free(arr->aggregate);
-   }
-}
-
-/* slang_storage_aggregate */
-
-GLboolean
-slang_storage_aggregate_construct(slang_storage_aggregate * agg)
-{
-   agg->arrays = NULL;
-   agg->count = 0;
-   return GL_TRUE;
-}
-
-GLvoid
-slang_storage_aggregate_destruct(slang_storage_aggregate * agg)
-{
-   GLuint i;
-
-   for (i = 0; i < agg->count; i++)
-      slang_storage_array_destruct(agg->arrays + i);
-   _slang_free(agg->arrays);
-}
-
-static slang_storage_array *
-slang_storage_aggregate_push_new(slang_storage_aggregate * agg)
-{
-   slang_storage_array *arr = NULL;
-
-   agg->arrays = (slang_storage_array *)
-      _slang_realloc(agg->arrays,
-                     agg->count * sizeof(slang_storage_array),
-                     (agg->count + 1) * sizeof(slang_storage_array));
-   if (agg->arrays != NULL) {
-      arr = agg->arrays + agg->count;
-      if (!slang_storage_array_construct(arr))
-         return NULL;
-      agg->count++;
-   }
-   return arr;
-}
-
-/* _slang_aggregate_variable() */
-
-static GLboolean
-aggregate_vector(slang_storage_aggregate * agg, slang_storage_type basic_type,
-                 GLuint row_count)
-{
-   slang_storage_array *arr = slang_storage_aggregate_push_new(agg);
-   if (arr == NULL)
-      return GL_FALSE;
-   arr->type = basic_type;
-   arr->length = row_count;
-   return GL_TRUE;
-}
-
-static GLboolean
-aggregate_matrix(slang_storage_aggregate * agg, slang_storage_type basic_type,
-                 GLuint columns, GLuint rows)
-{
-   slang_storage_array *arr = slang_storage_aggregate_push_new(agg);
-   if (arr == NULL)
-      return GL_FALSE;
-   arr->type = SLANG_STORE_AGGREGATE;
-   arr->length = columns;
-   arr->aggregate = (slang_storage_aggregate *)
-      _slang_alloc(sizeof(slang_storage_aggregate));
-   if (arr->aggregate == NULL)
-      return GL_FALSE;
-   if (!slang_storage_aggregate_construct(arr->aggregate)) {
-      _slang_free(arr->aggregate);
-      arr->aggregate = NULL;
-      return GL_FALSE;
-   }
-   if (!aggregate_vector(arr->aggregate, basic_type, rows))
-      return GL_FALSE;
-   return GL_TRUE;
-}
-
-
-static GLboolean
-aggregate_variables(slang_storage_aggregate * agg,
-                    slang_variable_scope * vars, slang_function_scope * funcs,
-                    slang_struct_scope * structs,
-                    slang_variable_scope * globals,
-                    slang_atom_pool * atoms)
-{
-   GLuint i;
-
-   for (i = 0; i < vars->num_variables; i++)
-      if (!_slang_aggregate_variable(agg, &vars->variables[i]->type.specifier,
-                                     vars->variables[i]->array_len, funcs,
-                                     structs, globals, atoms))
-         return GL_FALSE;
-   return GL_TRUE;
-}
-
-
-GLboolean
-_slang_aggregate_variable(slang_storage_aggregate * agg,
-                          slang_type_specifier * spec, GLuint array_len,
-                          slang_function_scope * funcs,
-                          slang_struct_scope * structs,
-                          slang_variable_scope * vars,
-                          slang_atom_pool * atoms)
-{
-   switch (spec->type) {
-   case SLANG_SPEC_BOOL:
-      return aggregate_vector(agg, SLANG_STORE_BOOL, 1);
-   case SLANG_SPEC_BVEC2:
-      return aggregate_vector(agg, SLANG_STORE_BOOL, 2);
-   case SLANG_SPEC_BVEC3:
-      return aggregate_vector(agg, SLANG_STORE_BOOL, 3);
-   case SLANG_SPEC_BVEC4:
-      return aggregate_vector(agg, SLANG_STORE_BOOL, 4);
-   case SLANG_SPEC_INT:
-      return aggregate_vector(agg, SLANG_STORE_INT, 1);
-   case SLANG_SPEC_IVEC2:
-      return aggregate_vector(agg, SLANG_STORE_INT, 2);
-   case SLANG_SPEC_IVEC3:
-      return aggregate_vector(agg, SLANG_STORE_INT, 3);
-   case SLANG_SPEC_IVEC4:
-      return aggregate_vector(agg, SLANG_STORE_INT, 4);
-   case SLANG_SPEC_FLOAT:
-      return aggregate_vector(agg, SLANG_STORE_FLOAT, 1);
-   case SLANG_SPEC_VEC2:
-      return aggregate_vector(agg, SLANG_STORE_FLOAT, 2);
-   case SLANG_SPEC_VEC3:
-      return aggregate_vector(agg, SLANG_STORE_FLOAT, 3);
-   case SLANG_SPEC_VEC4:
-      return aggregate_vector(agg, SLANG_STORE_FLOAT, 4);
-   case SLANG_SPEC_MAT2:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 2, 2);
-   case SLANG_SPEC_MAT3:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 3, 3);
-   case SLANG_SPEC_MAT4:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 4, 4);
-
-   case SLANG_SPEC_MAT23:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 2, 3);
-   case SLANG_SPEC_MAT32:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 3, 2);
-   case SLANG_SPEC_MAT24:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 2, 4);
-   case SLANG_SPEC_MAT42:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 4, 2);
-   case SLANG_SPEC_MAT34:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 3, 4);
-   case SLANG_SPEC_MAT43:
-      return aggregate_matrix(agg, SLANG_STORE_FLOAT, 4, 3);
-
-   case SLANG_SPEC_SAMPLER_1D:
-   case SLANG_SPEC_SAMPLER_2D:
-   case SLANG_SPEC_SAMPLER_3D:
-   case SLANG_SPEC_SAMPLER_CUBE:
-   case SLANG_SPEC_SAMPLER_1D_SHADOW:
-   case SLANG_SPEC_SAMPLER_2D_SHADOW:
-   case SLANG_SPEC_SAMPLER_RECT:
-   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
-   case SLANG_SPEC_SAMPLER_1D_ARRAY:
-   case SLANG_SPEC_SAMPLER_2D_ARRAY:
-   case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
-   case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
-
-      return aggregate_vector(agg, SLANG_STORE_INT, 1);
-   case SLANG_SPEC_STRUCT:
-      return aggregate_variables(agg, spec->_struct->fields, funcs, structs,
-                                 vars, atoms);
-   case SLANG_SPEC_ARRAY:
-      {
-         slang_storage_array *arr;
-
-         arr = slang_storage_aggregate_push_new(agg);
-         if (arr == NULL)
-            return GL_FALSE;
-         arr->type = SLANG_STORE_AGGREGATE;
-         arr->aggregate = (slang_storage_aggregate *)
-            _slang_alloc(sizeof(slang_storage_aggregate));
-         if (arr->aggregate == NULL)
-            return GL_FALSE;
-         if (!slang_storage_aggregate_construct(arr->aggregate)) {
-            _slang_free(arr->aggregate);
-            arr->aggregate = NULL;
-            return GL_FALSE;
-         }
-         if (!_slang_aggregate_variable(arr->aggregate, spec->_array, 0,
-                                        funcs, structs, vars, atoms))
-            return GL_FALSE;
-         arr->length = array_len;
-         /* TODO: check if 0 < arr->length <= 65535 */
-      }
-      return GL_TRUE;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-GLuint
-_slang_sizeof_type(slang_storage_type type)
-{
-   if (type == SLANG_STORE_AGGREGATE)
-      return 0;
-   if (type == SLANG_STORE_VEC4)
-      return 4 * sizeof(GLfloat);
-   return sizeof(GLfloat);
-}
-
-
-GLuint
-_slang_sizeof_aggregate(const slang_storage_aggregate * agg)
-{
-   GLuint i, size = 0;
-
-   for (i = 0; i < agg->count; i++) {
-      slang_storage_array *arr = &agg->arrays[i];
-      GLuint element_size;
-
-      if (arr->type == SLANG_STORE_AGGREGATE)
-         element_size = _slang_sizeof_aggregate(arr->aggregate);
-      else
-         element_size = _slang_sizeof_type(arr->type);
-      size += element_size * arr->length;
-   }
-   return size;
-}
-
-
-#if 0
-GLboolean
-_slang_flatten_aggregate(slang_storage_aggregate * flat,
-                         const slang_storage_aggregate * agg)
-{
-   GLuint i;
-
-   for (i = 0; i < agg->count; i++) {
-      GLuint j;
-
-      for (j = 0; j < agg->arrays[i].length; j++) {
-         if (agg->arrays[i].type == SLANG_STORE_AGGREGATE) {
-            if (!_slang_flatten_aggregate(flat, agg->arrays[i].aggregate))
-               return GL_FALSE;
-         }
-         else {
-            GLuint k, count;
-            slang_storage_type type;
-
-            if (agg->arrays[i].type == SLANG_STORE_VEC4) {
-               count = 4;
-               type = SLANG_STORE_FLOAT;
-            }
-            else {
-               count = 1;
-               type = agg->arrays[i].type;
-            }
-
-            for (k = 0; k < count; k++) {
-               slang_storage_array *arr;
-
-               arr = slang_storage_aggregate_push_new(flat);
-               if (arr == NULL)
-                  return GL_FALSE;
-               arr->type = type;
-               arr->length = 1;
-            }
-         }
-      }
-   }
-   return GL_TRUE;
-}
-#endif
diff --git a/src/mesa/slang/slang_storage.h b/src/mesa/slang/slang_storage.h
deleted file mode 100644 (file)
index 1876a36..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2005-2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_STORAGE_H
-#define SLANG_STORAGE_H
-
-#include "slang_compile.h"
-
-
-/*
- * Program variable data storage is kept completely transparent to the
- * front-end compiler. It is up to the back-end how the data is
- * actually allocated. The slang_storage_type enum provides the basic
- * information about how the memory is interpreted. This abstract
- * piece of memory is called a data slot. A data slot of a particular
- * type has a fixed size.
- *
- * For now, only the three basic types are supported, that is bool,
- * int and float. Other built-in types like vector or matrix can
- * easily be decomposed into a series of basic types.
- *
- * If the vec4 module is enabled, 4-component vectors of floats are
- * used when possible. 4x4 matrices are constructed of 4 vec4 slots.
- */
-typedef enum slang_storage_type_
-{
-   /* core */
-   SLANG_STORE_AGGREGATE,
-   SLANG_STORE_BOOL,
-   SLANG_STORE_INT,
-   SLANG_STORE_FLOAT,
-   /* vec4 */
-   SLANG_STORE_VEC4
-} slang_storage_type;
-
-
-/**
- * The slang_storage_array structure groups data slots of the same
- * type into an array. This array has a fixed length. Arrays are
- * required to have a size equal to the sum of sizes of its
- * elements. They are also required to support indirect
- * addressing. That is, if B references first data slot in the array,
- * S is the size of the data slot and I is the integral index that is
- * not known at compile time, B+I*S references I-th data slot.
- *
- * This structure is also used to break down built-in data types that
- * are not supported directly.  Vectors, like vec3, are constructed
- * from arrays of their basic types. Matrices are formed of an array
- * of column vectors, which are in turn processed as other vectors.
- */
-typedef struct slang_storage_array_
-{
-   slang_storage_type type;
-   struct slang_storage_aggregate_ *aggregate;
-   GLuint length;
-} slang_storage_array;
-
-GLboolean slang_storage_array_construct (slang_storage_array *);
-GLvoid slang_storage_array_destruct (slang_storage_array *);
-
-
-/**
- * The slang_storage_aggregate structure relaxes the indirect
- * addressing requirement for slang_storage_array
- * structure. Aggregates are always accessed statically - its member
- * addresses are well-known at compile time. For example, user-defined
- * types are implemented as aggregates. Aggregates can collect data of
- * a different type.
- */
-typedef struct slang_storage_aggregate_
-{
-   slang_storage_array *arrays;
-   GLuint count;
-} slang_storage_aggregate;
-
-GLboolean slang_storage_aggregate_construct (slang_storage_aggregate *);
-GLvoid slang_storage_aggregate_destruct (slang_storage_aggregate *);
-
-
-extern GLboolean
-_slang_aggregate_variable(slang_storage_aggregate *agg,
-                          slang_type_specifier *spec,
-                          GLuint array_len,
-                          slang_function_scope *funcs,
-                          slang_struct_scope *structs,
-                          slang_variable_scope *vars,
-                          slang_atom_pool *atoms);
-
-/*
- * Returns the size (in machine units) of the given storage type.
- * It is an error to pass-in SLANG_STORE_AGGREGATE.
- * Returns 0 on error.
- */
-extern GLuint
-_slang_sizeof_type (slang_storage_type);
-
-
-/**
- * Returns total size (in machine units) of the given aggregate.
- * Returns 0 on error.
- */
-extern GLuint
-_slang_sizeof_aggregate (const slang_storage_aggregate *);
-
-
-#if 0
-/**
- * Converts structured aggregate to a flat one, with arrays of generic
- * type being one-element long.  Returns GL_TRUE on success.  Returns
- * GL_FALSE otherwise.
- */
-extern GLboolean
-_slang_flatten_aggregate (slang_storage_aggregate *,
-                          const slang_storage_aggregate *);
-
-#endif
-
-#endif /* SLANG_STORAGE_H */
diff --git a/src/mesa/slang/slang_typeinfo.c b/src/mesa/slang/slang_typeinfo.c
deleted file mode 100644 (file)
index d039a12..0000000
+++ /dev/null
@@ -1,1177 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2005-2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_typeinfo.c
- * slang type info
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "program/prog_instruction.h"
-#include "slang_typeinfo.h"
-#include "slang_compile.h"
-#include "slang_log.h"
-#include "slang_mem.h"
-
-
-/**
- * Checks if a field selector is a general swizzle (an r-value swizzle
- * with replicated components or an l-value swizzle mask) for a
- * vector.  Returns GL_TRUE if this is the case, <swz> is filled with
- * swizzle information.  Returns GL_FALSE otherwise.
- */
-GLboolean
-_slang_is_swizzle(const char *field, GLuint rows, slang_swizzle * swz)
-{
-   GLuint i;
-   GLboolean xyzw = GL_FALSE, rgba = GL_FALSE, stpq = GL_FALSE;
-
-   /* init to undefined.
-    * We rely on undefined/nil values to distinguish between
-    * regular swizzles and writemasks.
-    * For example, the swizzle ".xNNN" is the writemask ".x".
-    * That's different than the swizzle ".xxxx".
-    */
-   for (i = 0; i < 4; i++)
-      swz->swizzle[i] = SWIZZLE_NIL;
-
-   /* the swizzle can be at most 4-component long */
-   swz->num_components = slang_string_length(field);
-   if (swz->num_components > 4)
-      return GL_FALSE;
-
-   for (i = 0; i < swz->num_components; i++) {
-      /* mark which swizzle group is used */
-      switch (field[i]) {
-      case 'x':
-      case 'y':
-      case 'z':
-      case 'w':
-         xyzw = GL_TRUE;
-         break;
-      case 'r':
-      case 'g':
-      case 'b':
-      case 'a':
-         rgba = GL_TRUE;
-         break;
-      case 's':
-      case 't':
-      case 'p':
-      case 'q':
-         stpq = GL_TRUE;
-         break;
-      default:
-         return GL_FALSE;
-      }
-
-      /* collect swizzle component */
-      switch (field[i]) {
-      case 'x':
-      case 'r':
-      case 's':
-         swz->swizzle[i] = 0;
-         break;
-      case 'y':
-      case 'g':
-      case 't':
-         swz->swizzle[i] = 1;
-         break;
-      case 'z':
-      case 'b':
-      case 'p':
-         swz->swizzle[i] = 2;
-         break;
-      case 'w':
-      case 'a':
-      case 'q':
-         swz->swizzle[i] = 3;
-         break;
-      }
-
-      /* check if the component is valid for given vector's row count */
-      if (rows <= swz->swizzle[i])
-         return GL_FALSE;
-   }
-
-   /* only one swizzle group can be used */
-   if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq))
-      return GL_FALSE;
-
-   return GL_TRUE;
-}
-
-
-
-/**
- * Checks if a general swizzle is an l-value swizzle - these swizzles
- * do not have duplicated fields.  Returns GL_TRUE if this is a
- * swizzle mask.  Returns GL_FALSE otherwise
- */
-static GLboolean
-_slang_is_swizzle_mask(const slang_swizzle * swz, GLuint rows)
-{
-   GLuint i, c = 0;
-
-   /* the swizzle may not be longer than the vector dim */
-   if (swz->num_components > rows)
-      return GL_FALSE;
-
-   /* the swizzle components cannot be duplicated */
-   for (i = 0; i < swz->num_components; i++) {
-      if ((c & (1 << swz->swizzle[i])) != 0)
-         return GL_FALSE;
-      c |= 1 << swz->swizzle[i];
-   }
-
-   return GL_TRUE;
-}
-
-
-/**
- * Combines (multiplies) two swizzles to form single swizzle.
- * Example: "vec.wzyx.yx" --> "vec.zw".
- */
-static void
-_slang_multiply_swizzles(slang_swizzle * dst, const slang_swizzle * left,
-                         const slang_swizzle * right)
-{
-   GLuint i;
-
-   dst->num_components = right->num_components;
-   for (i = 0; i < right->num_components; i++)
-      dst->swizzle[i] = left->swizzle[right->swizzle[i]];
-}
-
-
-typedef struct
-{
-   const char *name;
-   slang_type_specifier_type type;
-} type_specifier_type_name;
-
-static const type_specifier_type_name type_specifier_type_names[] = {
-   {"void", SLANG_SPEC_VOID},
-   {"bool", SLANG_SPEC_BOOL},
-   {"bvec2", SLANG_SPEC_BVEC2},
-   {"bvec3", SLANG_SPEC_BVEC3},
-   {"bvec4", SLANG_SPEC_BVEC4},
-   {"int", SLANG_SPEC_INT},
-   {"ivec2", SLANG_SPEC_IVEC2},
-   {"ivec3", SLANG_SPEC_IVEC3},
-   {"ivec4", SLANG_SPEC_IVEC4},
-   {"float", SLANG_SPEC_FLOAT},
-   {"vec2", SLANG_SPEC_VEC2},
-   {"vec3", SLANG_SPEC_VEC3},
-   {"vec4", SLANG_SPEC_VEC4},
-   {"mat2", SLANG_SPEC_MAT2},
-   {"mat3", SLANG_SPEC_MAT3},
-   {"mat4", SLANG_SPEC_MAT4},
-   {"mat2x3", SLANG_SPEC_MAT23},
-   {"mat3x2", SLANG_SPEC_MAT32},
-   {"mat2x4", SLANG_SPEC_MAT24},
-   {"mat4x2", SLANG_SPEC_MAT42},
-   {"mat3x4", SLANG_SPEC_MAT34},
-   {"mat4x3", SLANG_SPEC_MAT43},
-   {"sampler1D", SLANG_SPEC_SAMPLER_1D},
-   {"sampler2D", SLANG_SPEC_SAMPLER_2D},
-   {"sampler3D", SLANG_SPEC_SAMPLER_3D},
-   {"samplerCube", SLANG_SPEC_SAMPLER_CUBE},
-   {"sampler1DShadow", SLANG_SPEC_SAMPLER_1D_SHADOW},
-   {"sampler2DShadow", SLANG_SPEC_SAMPLER_2D_SHADOW},
-   {"sampler2DRect", SLANG_SPEC_SAMPLER_RECT},
-   {"sampler2DRectShadow", SLANG_SPEC_SAMPLER_RECT_SHADOW},
-   {"sampler1DArray", SLANG_SPEC_SAMPLER_1D_ARRAY},
-   {"sampler2DArray", SLANG_SPEC_SAMPLER_2D_ARRAY},
-   {"sampler1DArrayShadow", SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW},
-   {"sampler2DArrayShadow", SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW},
-   {NULL, SLANG_SPEC_VOID}
-};
-
-slang_type_specifier_type
-slang_type_specifier_type_from_string(const char *name)
-{
-   const type_specifier_type_name *p = type_specifier_type_names;
-   while (p->name != NULL) {
-      if (slang_string_compare(p->name, name) == 0)
-         break;
-      p++;
-   }
-   return p->type;
-}
-
-const char *
-slang_type_specifier_type_to_string(slang_type_specifier_type type)
-{
-   const type_specifier_type_name *p = type_specifier_type_names;
-   while (p->name != NULL) {
-      if (p->type == type)
-         break;
-      p++;
-   }
-   return p->name;
-}
-
-/* slang_fully_specified_type */
-
-int
-slang_fully_specified_type_construct(slang_fully_specified_type * type)
-{
-   type->qualifier = SLANG_QUAL_NONE;
-   slang_type_specifier_ctr(&type->specifier);
-   return 1;
-}
-
-void
-slang_fully_specified_type_destruct(slang_fully_specified_type * type)
-{
-   slang_type_specifier_dtr(&type->specifier);
-}
-
-int
-slang_fully_specified_type_copy(slang_fully_specified_type * x,
-                                const slang_fully_specified_type * y)
-{
-   slang_fully_specified_type z;
-
-   if (!slang_fully_specified_type_construct(&z))
-      return 0;
-   z.qualifier = y->qualifier;
-   z.precision = y->precision;
-   z.variant = y->variant;
-   z.centroid = y->centroid;
-   z.layout = y->layout;
-   z.array_len = y->array_len;
-   if (!slang_type_specifier_copy(&z.specifier, &y->specifier)) {
-      slang_fully_specified_type_destruct(&z);
-      return 0;
-   }
-   slang_fully_specified_type_destruct(x);
-   *x = z;
-   return 1;
-}
-
-
-/**
- * Test if two fully specified types are compatible.  This is a bit
- * looser than testing for equality.  We don't check the precision,
- * variant, centroid, etc. information.
- * XXX this may need some tweaking.
- */
-GLboolean
-slang_fully_specified_types_compatible(const slang_fully_specified_type * x,
-                                       const slang_fully_specified_type * y)
-{
-   if (!slang_type_specifier_equal(&x->specifier, &y->specifier))
-      return GL_FALSE;
-
-   if (x->qualifier == SLANG_QUAL_FIXEDINPUT &&
-       y->qualifier == SLANG_QUAL_VARYING)
-      ; /* ok */
-   else if (x->qualifier != y->qualifier)
-      return GL_FALSE;
-
-   /* Note: don't compare precision, variant, centroid */
-
-   /* XXX array length? */
-
-   return GL_TRUE;
-}
-
-
-GLvoid
-slang_type_specifier_ctr(slang_type_specifier * self)
-{
-   self->type = SLANG_SPEC_VOID;
-   self->_struct = NULL;
-   self->_array = NULL;
-}
-
-GLvoid
-slang_type_specifier_dtr(slang_type_specifier * self)
-{
-   if (self->_struct != NULL) {
-      slang_struct_destruct(self->_struct);
-      _slang_free(self->_struct);
-   }
-   if (self->_array != NULL) {
-      slang_type_specifier_dtr(self->_array);
-      _slang_free(self->_array);
-   }
-}
-
-slang_type_specifier *
-slang_type_specifier_new(slang_type_specifier_type type,
-                         struct slang_struct_ *_struct,
-                         struct slang_type_specifier_ *_array)
-{
-   slang_type_specifier *spec =
-      (slang_type_specifier *) _slang_alloc(sizeof(slang_type_specifier));
-   if (spec) {
-      spec->type = type;
-      spec->_struct = _struct;
-      spec->_array = _array;
-   }
-   return spec;
-}
-
-GLboolean
-slang_type_specifier_copy(slang_type_specifier * x,
-                          const slang_type_specifier * y)
-{
-   slang_type_specifier z;
-
-   slang_type_specifier_ctr(&z);
-   z.type = y->type;
-   if (z.type == SLANG_SPEC_STRUCT) {
-      z._struct = (slang_struct *) _slang_alloc(sizeof(slang_struct));
-      if (z._struct == NULL) {
-         slang_type_specifier_dtr(&z);
-         return GL_FALSE;
-      }
-      if (!slang_struct_construct(z._struct)) {
-         _slang_free(z._struct);
-         slang_type_specifier_dtr(&z);
-         return GL_FALSE;
-      }
-      if (!slang_struct_copy(z._struct, y->_struct)) {
-         slang_type_specifier_dtr(&z);
-         return GL_FALSE;
-      }
-   }
-   else if (z.type == SLANG_SPEC_ARRAY) {
-      z._array = (slang_type_specifier *)
-         _slang_alloc(sizeof(slang_type_specifier));
-      if (z._array == NULL) {
-         slang_type_specifier_dtr(&z);
-         return GL_FALSE;
-      }
-      slang_type_specifier_ctr(z._array);
-      if (!slang_type_specifier_copy(z._array, y->_array)) {
-         slang_type_specifier_dtr(&z);
-         return GL_FALSE;
-      }
-   }
-   slang_type_specifier_dtr(x);
-   *x = z;
-   return GL_TRUE;
-}
-
-
-/**
- * Test if two types are equal.
- */
-GLboolean
-slang_type_specifier_equal(const slang_type_specifier * x,
-                           const slang_type_specifier * y)
-{
-   if (x->type != y->type)
-      return GL_FALSE;
-   if (x->type == SLANG_SPEC_STRUCT)
-      return slang_struct_equal(x->_struct, y->_struct);
-   if (x->type == SLANG_SPEC_ARRAY)
-      return slang_type_specifier_equal(x->_array, y->_array);
-   return GL_TRUE;
-}
-
-
-/**
- * As above, but allow float/int casting.
- */
-GLboolean
-slang_type_specifier_compatible(const slang_type_specifier * x,
-                                const slang_type_specifier * y)
-{
-   /* special case: float == int */
-   if (x->type == SLANG_SPEC_INT && y->type == SLANG_SPEC_FLOAT) {
-      return GL_TRUE;
-   }
-   /* XXX may need to add bool/int compatibility, etc */
-
-   if (x->type != y->type)
-      return GL_FALSE;
-   if (x->type == SLANG_SPEC_STRUCT)
-      return slang_struct_equal(x->_struct, y->_struct);
-   if (x->type == SLANG_SPEC_ARRAY)
-      return slang_type_specifier_compatible(x->_array, y->_array);
-   return GL_TRUE;
-}
-
-
-GLboolean
-slang_typeinfo_construct(slang_typeinfo * ti)
-{
-   memset(ti, 0, sizeof(*ti));
-   slang_type_specifier_ctr(&ti->spec);
-   ti->array_len = 0;
-   return GL_TRUE;
-}
-
-GLvoid
-slang_typeinfo_destruct(slang_typeinfo * ti)
-{
-   slang_type_specifier_dtr(&ti->spec);
-}
-
-
-
-/**
- * Determine the return type of a function.
- * \param a_name  the function name
- * \param param  function parameters (overloading)
- * \param num_params  number of parameters to function
- * \param space  namespace to search
- * \param spec  returns the type
- * \param funFound  returns pointer to the function, or NULL if not found.
- * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
- */
-static GLboolean
-_slang_typeof_function(slang_atom a_name,
-                       slang_operation * params, GLuint num_params,
-                       const slang_name_space * space,
-                       slang_type_specifier * spec,
-                       slang_function **funFound,
-                       slang_atom_pool *atoms, slang_info_log *log)
-{
-   GLboolean error;
-
-   *funFound = _slang_function_locate(space->funcs, a_name, params,
-                                      num_params, space, atoms, log, &error);
-   if (error)
-      return GL_FALSE;
-
-   if (!*funFound)
-      return GL_TRUE;  /* yes, not false */
-
-   return slang_type_specifier_copy(spec, &(*funFound)->header.type.specifier);
-}
-
-
-/**
- * Determine the type of a math function.
- * \param name  name of the operator, one of +,-,*,/ or unary -
- * \param params  array of function parameters
- * \param num_params  number of parameters
- * \param space  namespace to use
- * \param spec  returns the function's type
- * \param atoms  atom pool
- * \return GL_TRUE for success, GL_FALSE if failure
- */
-static GLboolean
-typeof_math_call(const char *name, slang_operation *call,
-                 const slang_name_space * space,
-                 slang_type_specifier * spec,
-                 slang_atom_pool * atoms,
-                 slang_info_log *log)
-{
-   if (call->fun) {
-      /* we've previously resolved this function call */
-      slang_type_specifier_copy(spec, &call->fun->header.type.specifier);
-      return GL_TRUE;
-   }
-   else {
-      slang_atom atom;
-      slang_function *fun;
-
-      /* number of params: */
-      assert(call->num_children == 1 || call->num_children == 2);
-
-      atom = slang_atom_pool_atom(atoms, name);
-      if (!_slang_typeof_function(atom, call->children, call->num_children,
-                                  space, spec, &fun, atoms, log))
-         return GL_FALSE;
-
-      if (fun) {
-         /* Save pointer to save time in future */
-         call->fun = fun;
-         return GL_TRUE;
-      }
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Determine the return type of an operation.
- * \param op  the operation node
- * \param space  the namespace to use
- * \param ti  the returned type
- * \param atoms  atom pool
- * \return GL_TRUE for success, GL_FALSE if failure
- */
-GLboolean
-_slang_typeof_operation(slang_operation * op,
-                         const slang_name_space * space,
-                         slang_typeinfo * ti,
-                         slang_atom_pool * atoms,
-                         slang_info_log *log)
-{
-   ti->can_be_referenced = GL_FALSE;
-   ti->is_swizzled = GL_FALSE;
-
-   switch (op->type) {
-   case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
-   case SLANG_OPER_BLOCK_NEW_SCOPE:
-   case SLANG_OPER_ASM:
-   case SLANG_OPER_BREAK:
-   case SLANG_OPER_CONTINUE:
-   case SLANG_OPER_DISCARD:
-   case SLANG_OPER_RETURN:
-   case SLANG_OPER_IF:
-   case SLANG_OPER_WHILE:
-   case SLANG_OPER_DO:
-   case SLANG_OPER_FOR:
-   case SLANG_OPER_VOID:
-      ti->spec.type = SLANG_SPEC_VOID;
-      break;
-   case SLANG_OPER_EXPRESSION:
-   case SLANG_OPER_ASSIGN:
-   case SLANG_OPER_ADDASSIGN:
-   case SLANG_OPER_SUBASSIGN:
-   case SLANG_OPER_MULASSIGN:
-   case SLANG_OPER_DIVASSIGN:
-   case SLANG_OPER_PREINCREMENT:
-   case SLANG_OPER_PREDECREMENT:
-      if (!_slang_typeof_operation(op->children, space, ti, atoms, log))
-         return GL_FALSE;
-      break;
-   case SLANG_OPER_LITERAL_BOOL:
-      if (op->literal_size == 1)
-         ti->spec.type = SLANG_SPEC_BOOL;
-      else if (op->literal_size == 2)
-         ti->spec.type = SLANG_SPEC_BVEC2;
-      else if (op->literal_size == 3)
-         ti->spec.type = SLANG_SPEC_BVEC3;
-      else if (op->literal_size == 4)
-         ti->spec.type = SLANG_SPEC_BVEC4;
-      else {
-         _mesa_problem(NULL,
-               "Unexpected bool literal_size %d in _slang_typeof_operation()",
-               op->literal_size);
-         ti->spec.type = SLANG_SPEC_BOOL;
-      }
-      break;
-   case SLANG_OPER_LOGICALOR:
-   case SLANG_OPER_LOGICALXOR:
-   case SLANG_OPER_LOGICALAND:
-   case SLANG_OPER_EQUAL:
-   case SLANG_OPER_NOTEQUAL:
-   case SLANG_OPER_LESS:
-   case SLANG_OPER_GREATER:
-   case SLANG_OPER_LESSEQUAL:
-   case SLANG_OPER_GREATEREQUAL:
-   case SLANG_OPER_NOT:
-      ti->spec.type = SLANG_SPEC_BOOL;
-      break;
-   case SLANG_OPER_LITERAL_INT:
-      if (op->literal_size == 1)
-         ti->spec.type = SLANG_SPEC_INT;
-      else if (op->literal_size == 2)
-         ti->spec.type = SLANG_SPEC_IVEC2;
-      else if (op->literal_size == 3)
-         ti->spec.type = SLANG_SPEC_IVEC3;
-      else if (op->literal_size == 4)
-         ti->spec.type = SLANG_SPEC_IVEC4;
-      else {
-         _mesa_problem(NULL,
-               "Unexpected int literal_size %d in _slang_typeof_operation()",
-               op->literal_size);
-         ti->spec.type = SLANG_SPEC_INT;
-      }
-      break;
-   case SLANG_OPER_LITERAL_FLOAT:
-      if (op->literal_size == 1)
-         ti->spec.type = SLANG_SPEC_FLOAT;
-      else if (op->literal_size == 2)
-         ti->spec.type = SLANG_SPEC_VEC2;
-      else if (op->literal_size == 3)
-         ti->spec.type = SLANG_SPEC_VEC3;
-      else if (op->literal_size == 4)
-         ti->spec.type = SLANG_SPEC_VEC4;
-      else {
-         _mesa_problem(NULL,
-               "Unexpected float literal_size %d in _slang_typeof_operation()",
-               op->literal_size);
-         ti->spec.type = SLANG_SPEC_FLOAT;
-      }
-      break;
-   case SLANG_OPER_IDENTIFIER:
-   case SLANG_OPER_VARIABLE_DECL:
-      {
-         slang_variable *var;
-         var = _slang_variable_locate(op->locals, op->a_id, GL_TRUE);
-         if (!var) {
-            slang_info_log_error(log, "undefined variable '%s'",
-                                 (char *) op->a_id);
-            return GL_FALSE;
-         }
-         if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier)) {
-            slang_info_log_memory(log);
-            return GL_FALSE;
-         }
-         ti->can_be_referenced = GL_TRUE;
-         if (var->type.specifier.type == SLANG_SPEC_ARRAY &&
-             var->type.array_len >= 1) {
-            /* the datatype is an array, ex: float[3] x; */
-            ti->array_len = var->type.array_len;
-         }
-         else {
-            /* the variable is an array, ex: float x[3]; */
-            ti->array_len = var->array_len;
-         }
-      }
-      break;
-   case SLANG_OPER_SEQUENCE:
-      /* TODO: check [0] and [1] if they match */
-      if (!_slang_typeof_operation(&op->children[1], space, ti, atoms, log)) {
-         return GL_FALSE;
-      }
-      ti->can_be_referenced = GL_FALSE;
-      ti->is_swizzled = GL_FALSE;
-      break;
-      /*case SLANG_OPER_MODASSIGN: */
-      /*case SLANG_OPER_LSHASSIGN: */
-      /*case SLANG_OPER_RSHASSIGN: */
-      /*case SLANG_OPER_ORASSIGN: */
-      /*case SLANG_OPER_XORASSIGN: */
-      /*case SLANG_OPER_ANDASSIGN: */
-   case SLANG_OPER_SELECT:
-      /* TODO: check [1] and [2] if they match */
-      if (!_slang_typeof_operation(&op->children[1], space, ti, atoms, log)) {
-         return GL_FALSE;
-      }
-      ti->can_be_referenced = GL_FALSE;
-      ti->is_swizzled = GL_FALSE;
-      break;
-      /*case SLANG_OPER_BITOR: */
-      /*case SLANG_OPER_BITXOR: */
-      /*case SLANG_OPER_BITAND: */
-      /*case SLANG_OPER_LSHIFT: */
-      /*case SLANG_OPER_RSHIFT: */
-   case SLANG_OPER_ADD:
-      assert(op->num_children == 2);
-      if (!typeof_math_call("+", op, space, &ti->spec, atoms, log))
-         return GL_FALSE;
-      break;
-   case SLANG_OPER_SUBTRACT:
-      assert(op->num_children == 2);
-      if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
-         return GL_FALSE;
-      break;
-   case SLANG_OPER_MULTIPLY:
-      assert(op->num_children == 2);
-      if (!typeof_math_call("*", op, space, &ti->spec, atoms, log))
-         return GL_FALSE;
-      break;
-   case SLANG_OPER_DIVIDE:
-      assert(op->num_children == 2);
-      if (!typeof_math_call("/", op, space, &ti->spec, atoms, log))
-         return GL_FALSE;
-      break;
-   /*case SLANG_OPER_MODULUS: */
-   case SLANG_OPER_PLUS:
-      if (!_slang_typeof_operation(op->children, space, ti, atoms, log))
-         return GL_FALSE;
-      ti->can_be_referenced = GL_FALSE;
-      ti->is_swizzled = GL_FALSE;
-      break;
-   case SLANG_OPER_MINUS:
-      assert(op->num_children == 1);
-      if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
-         return GL_FALSE;
-      break;
-      /*case SLANG_OPER_COMPLEMENT: */
-   case SLANG_OPER_SUBSCRIPT:
-      {
-         slang_typeinfo _ti;
-
-         if (!slang_typeinfo_construct(&_ti))
-            return GL_FALSE;
-         if (!_slang_typeof_operation(op->children, space, &_ti, atoms, log)) {
-            slang_typeinfo_destruct(&_ti);
-            return GL_FALSE;
-         }
-         ti->can_be_referenced = _ti.can_be_referenced;
-         if (_ti.spec.type == SLANG_SPEC_ARRAY) {
-            if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) {
-               slang_typeinfo_destruct(&_ti);
-               return GL_FALSE;
-            }
-         }
-         else {
-            if (!_slang_type_is_vector(_ti.spec.type)
-                && !_slang_type_is_matrix(_ti.spec.type)) {
-               slang_typeinfo_destruct(&_ti);
-               slang_info_log_error(log, "cannot index a non-array type");
-               return GL_FALSE;
-            }
-            ti->spec.type = _slang_type_base(_ti.spec.type);
-         }
-         slang_typeinfo_destruct(&_ti);
-      }
-      break;
-   case SLANG_OPER_CALL:
-      if (op->array_constructor) {
-         /* build array typeinfo */
-         ti->spec.type = SLANG_SPEC_ARRAY;
-         ti->spec._array = (slang_type_specifier *)
-            _slang_alloc(sizeof(slang_type_specifier));
-         slang_type_specifier_ctr(ti->spec._array);
-
-         ti->spec._array->type =
-            slang_type_specifier_type_from_string((char *) op->a_id);
-         ti->array_len = op->num_children;
-      }
-      else if (op->fun) {
-         /* we've resolved this call before */
-         slang_type_specifier_copy(&ti->spec, &op->fun->header.type.specifier);
-      }
-      else {
-         slang_function *fun;
-         if (!_slang_typeof_function(op->a_id, op->children, op->num_children,
-                                     space, &ti->spec, &fun, atoms, log))
-            return GL_FALSE;
-         if (fun) {
-            /* save result for future use */
-            op->fun = fun;
-         }
-         else {
-            slang_struct *s =
-               slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
-            if (s) {
-               /* struct initializer */
-               ti->spec.type = SLANG_SPEC_STRUCT;
-               ti->spec._struct =
-                  (slang_struct *) _slang_alloc(sizeof(slang_struct));
-               if (ti->spec._struct == NULL)
-                  return GL_FALSE;
-               if (!slang_struct_construct(ti->spec._struct)) {
-                  _slang_free(ti->spec._struct);
-                  ti->spec._struct = NULL;
-                  return GL_FALSE;
-               }
-               if (!slang_struct_copy(ti->spec._struct, s))
-                  return GL_FALSE;
-            }
-            else {
-               /* float, int, vec4, mat3, etc. constructor? */
-               const char *name;
-               slang_type_specifier_type type;
-
-               name = slang_atom_pool_id(atoms, op->a_id);
-               type = slang_type_specifier_type_from_string(name);
-               if (type == SLANG_SPEC_VOID) {
-                  slang_info_log_error(log, "undefined function '%s'", name);
-                  return GL_FALSE;
-               }
-               ti->spec.type = type;
-            }
-         }
-      }
-      break;
-   case SLANG_OPER_METHOD:
-      /* at this time, GLSL 1.20 only has one method: array.length()
-       * which returns an integer.
-       */
-      ti->spec.type = SLANG_SPEC_INT;
-      break;
-   case SLANG_OPER_FIELD:
-      {
-         slang_typeinfo _ti;
-
-         if (!slang_typeinfo_construct(&_ti))
-            return GL_FALSE;
-         if (!_slang_typeof_operation(op->children, space, &_ti, atoms, log)) {
-            slang_typeinfo_destruct(&_ti);
-            return GL_FALSE;
-         }
-         if (_ti.spec.type == SLANG_SPEC_STRUCT) {
-            slang_variable *field;
-
-            field = _slang_variable_locate(_ti.spec._struct->fields, op->a_id,
-                                           GL_FALSE);
-            if (field == NULL) {
-               slang_typeinfo_destruct(&_ti);
-               return GL_FALSE;
-            }
-            if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
-               slang_typeinfo_destruct(&_ti);
-               return GL_FALSE;
-            }
-            ti->can_be_referenced = _ti.can_be_referenced;
-            ti->array_len = field->array_len;
-         }
-         else {
-            GLuint rows;
-            const char *swizzle;
-            slang_type_specifier_type base;
-
-            /* determine the swizzle of the field expression */
-            if (!_slang_type_is_vector(_ti.spec.type)) {
-               slang_typeinfo_destruct(&_ti);
-               slang_info_log_error(log, "Can't swizzle scalar expression");
-               return GL_FALSE;
-            }
-            rows = _slang_type_dim(_ti.spec.type);
-            swizzle = slang_atom_pool_id(atoms, op->a_id);
-            if (!_slang_is_swizzle(swizzle, rows, &ti->swz)) {
-               slang_typeinfo_destruct(&_ti);
-               slang_info_log_error(log, "bad swizzle '%s'", swizzle);
-               return GL_FALSE;
-            }
-            ti->is_swizzled = GL_TRUE;
-            ti->can_be_referenced = _ti.can_be_referenced
-               && _slang_is_swizzle_mask(&ti->swz, rows);
-            if (_ti.is_swizzled) {
-               slang_swizzle swz;
-
-               /* swizzle the swizzle */
-               _slang_multiply_swizzles(&swz, &_ti.swz, &ti->swz);
-               ti->swz = swz;
-            }
-            base = _slang_type_base(_ti.spec.type);
-            switch (ti->swz.num_components) {
-            case 1:
-               ti->spec.type = base;
-               break;
-            case 2:
-               switch (base) {
-               case SLANG_SPEC_FLOAT:
-                  ti->spec.type = SLANG_SPEC_VEC2;
-                  break;
-               case SLANG_SPEC_INT:
-                  ti->spec.type = SLANG_SPEC_IVEC2;
-                  break;
-               case SLANG_SPEC_BOOL:
-                  ti->spec.type = SLANG_SPEC_BVEC2;
-                  break;
-               default:
-                  break;
-               }
-               break;
-            case 3:
-               switch (base) {
-               case SLANG_SPEC_FLOAT:
-                  ti->spec.type = SLANG_SPEC_VEC3;
-                  break;
-               case SLANG_SPEC_INT:
-                  ti->spec.type = SLANG_SPEC_IVEC3;
-                  break;
-               case SLANG_SPEC_BOOL:
-                  ti->spec.type = SLANG_SPEC_BVEC3;
-                  break;
-               default:
-                  break;
-               }
-               break;
-            case 4:
-               switch (base) {
-               case SLANG_SPEC_FLOAT:
-                  ti->spec.type = SLANG_SPEC_VEC4;
-                  break;
-               case SLANG_SPEC_INT:
-                  ti->spec.type = SLANG_SPEC_IVEC4;
-                  break;
-               case SLANG_SPEC_BOOL:
-                  ti->spec.type = SLANG_SPEC_BVEC4;
-                  break;
-               default:
-                  break;
-               }
-               break;
-            default:
-               break;
-            }
-         }
-         slang_typeinfo_destruct(&_ti);
-      }
-      break;
-   case SLANG_OPER_POSTINCREMENT:
-   case SLANG_OPER_POSTDECREMENT:
-      if (!_slang_typeof_operation(op->children, space, ti, atoms, log))
-         return GL_FALSE;
-      ti->can_be_referenced = GL_FALSE;
-      ti->is_swizzled = GL_FALSE;
-      break;
-   default:
-      return GL_FALSE;
-   }
-
-   return GL_TRUE;
-}
-
-
-/**
- * Determine if a type is a matrix.
- * \return GL_TRUE if is a matrix, GL_FALSE otherwise.
- */
-GLboolean
-_slang_type_is_matrix(slang_type_specifier_type ty)
-{
-   switch (ty) {
-   case SLANG_SPEC_MAT2:
-   case SLANG_SPEC_MAT3:
-   case SLANG_SPEC_MAT4:
-   case SLANG_SPEC_MAT23:
-   case SLANG_SPEC_MAT32:
-   case SLANG_SPEC_MAT24:
-   case SLANG_SPEC_MAT42:
-   case SLANG_SPEC_MAT34:
-   case SLANG_SPEC_MAT43:
-      return GL_TRUE;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Determine if a type is a vector.
- * \return GL_TRUE if is a vector, GL_FALSE otherwise.
- */
-GLboolean
-_slang_type_is_vector(slang_type_specifier_type ty)
-{
-   switch (ty) {
-   case SLANG_SPEC_VEC2:
-   case SLANG_SPEC_VEC3:
-   case SLANG_SPEC_VEC4:
-   case SLANG_SPEC_IVEC2:
-   case SLANG_SPEC_IVEC3:
-   case SLANG_SPEC_IVEC4:
-   case SLANG_SPEC_BVEC2:
-   case SLANG_SPEC_BVEC3:
-   case SLANG_SPEC_BVEC4:
-      return GL_TRUE;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Determine if a type is a float, float vector or float matrix.
- * \return GL_TRUE if so, GL_FALSE otherwise
- */
-GLboolean
-_slang_type_is_float_vec_mat(slang_type_specifier_type ty)
-{
-   switch (ty) {
-   case SLANG_SPEC_FLOAT:
-   case SLANG_SPEC_VEC2:
-   case SLANG_SPEC_VEC3:
-   case SLANG_SPEC_VEC4:
-   case SLANG_SPEC_MAT2:
-   case SLANG_SPEC_MAT3:
-   case SLANG_SPEC_MAT4:
-   case SLANG_SPEC_MAT23:
-   case SLANG_SPEC_MAT32:
-   case SLANG_SPEC_MAT24:
-   case SLANG_SPEC_MAT42:
-   case SLANG_SPEC_MAT34:
-   case SLANG_SPEC_MAT43:
-      return GL_TRUE;
-   default:
-      return GL_FALSE;
-   }
-}
-
-
-/**
- * Given a vector type, return the type of the vector's elements.
- * For a matrix, return the type of the columns.
- */
-slang_type_specifier_type
-_slang_type_base(slang_type_specifier_type ty)
-{
-   switch (ty) {
-   case SLANG_SPEC_FLOAT:
-   case SLANG_SPEC_VEC2:
-   case SLANG_SPEC_VEC3:
-   case SLANG_SPEC_VEC4:
-      return SLANG_SPEC_FLOAT;
-   case SLANG_SPEC_INT:
-   case SLANG_SPEC_IVEC2:
-   case SLANG_SPEC_IVEC3:
-   case SLANG_SPEC_IVEC4:
-      return SLANG_SPEC_INT;
-   case SLANG_SPEC_BOOL:
-   case SLANG_SPEC_BVEC2:
-   case SLANG_SPEC_BVEC3:
-   case SLANG_SPEC_BVEC4:
-      return SLANG_SPEC_BOOL;
-   case SLANG_SPEC_MAT2:
-      return SLANG_SPEC_VEC2;
-   case SLANG_SPEC_MAT3:
-      return SLANG_SPEC_VEC3;
-   case SLANG_SPEC_MAT4:
-      return SLANG_SPEC_VEC4;
-   case SLANG_SPEC_MAT23:
-      return SLANG_SPEC_VEC3;
-   case SLANG_SPEC_MAT32:
-      return SLANG_SPEC_VEC2;
-   case SLANG_SPEC_MAT24:
-      return SLANG_SPEC_VEC4;
-   case SLANG_SPEC_MAT42:
-      return SLANG_SPEC_VEC2;
-   case SLANG_SPEC_MAT34:
-      return SLANG_SPEC_VEC4;
-   case SLANG_SPEC_MAT43:
-      return SLANG_SPEC_VEC3;
-   default:
-      return SLANG_SPEC_VOID;
-   }
-}
-
-
-/**
- * Return the dimensionality of a vector, or for a matrix, return number
- * of columns.
- */
-GLuint
-_slang_type_dim(slang_type_specifier_type ty)
-{
-   switch (ty) {
-   case SLANG_SPEC_FLOAT:
-   case SLANG_SPEC_INT:
-   case SLANG_SPEC_BOOL:
-      return 1;
-   case SLANG_SPEC_VEC2:
-   case SLANG_SPEC_IVEC2:
-   case SLANG_SPEC_BVEC2:
-   case SLANG_SPEC_MAT2:
-      return 2;
-   case SLANG_SPEC_VEC3:
-   case SLANG_SPEC_IVEC3:
-   case SLANG_SPEC_BVEC3:
-   case SLANG_SPEC_MAT3:
-      return 3;
-   case SLANG_SPEC_VEC4:
-   case SLANG_SPEC_IVEC4:
-   case SLANG_SPEC_BVEC4:
-   case SLANG_SPEC_MAT4:
-      return 4;
-
-   case SLANG_SPEC_MAT23:
-      return 2;
-   case SLANG_SPEC_MAT32:
-      return 3;
-   case SLANG_SPEC_MAT24:
-      return 2;
-   case SLANG_SPEC_MAT42:
-      return 4;
-   case SLANG_SPEC_MAT34:
-      return 3;
-   case SLANG_SPEC_MAT43:
-      return 4;
-
-   default:
-      return 0;
-   }
-}
-
-
-/**
- * Return the GL_* type that corresponds to a SLANG_SPEC_* type.
- */
-GLenum
-_slang_gltype_from_specifier(const slang_type_specifier *type)
-{
-   switch (type->type) {
-   case SLANG_SPEC_BOOL:
-      return GL_BOOL;
-   case SLANG_SPEC_BVEC2:
-      return GL_BOOL_VEC2;
-   case SLANG_SPEC_BVEC3:
-      return GL_BOOL_VEC3;
-   case SLANG_SPEC_BVEC4:
-      return GL_BOOL_VEC4;
-   case SLANG_SPEC_INT:
-      return GL_INT;
-   case SLANG_SPEC_IVEC2:
-      return GL_INT_VEC2;
-   case SLANG_SPEC_IVEC3:
-      return GL_INT_VEC3;
-   case SLANG_SPEC_IVEC4:
-      return GL_INT_VEC4;
-   case SLANG_SPEC_FLOAT:
-      return GL_FLOAT;
-   case SLANG_SPEC_VEC2:
-      return GL_FLOAT_VEC2;
-   case SLANG_SPEC_VEC3:
-      return GL_FLOAT_VEC3;
-   case SLANG_SPEC_VEC4:
-      return GL_FLOAT_VEC4;
-   case SLANG_SPEC_MAT2:
-      return GL_FLOAT_MAT2;
-   case SLANG_SPEC_MAT3:
-      return GL_FLOAT_MAT3;
-   case SLANG_SPEC_MAT4:
-      return GL_FLOAT_MAT4;
-   case SLANG_SPEC_MAT23:
-      return GL_FLOAT_MAT2x3;
-   case SLANG_SPEC_MAT32:
-      return GL_FLOAT_MAT3x2;
-   case SLANG_SPEC_MAT24:
-      return GL_FLOAT_MAT2x4;
-   case SLANG_SPEC_MAT42:
-      return GL_FLOAT_MAT4x2;
-   case SLANG_SPEC_MAT34:
-      return GL_FLOAT_MAT3x4;
-   case SLANG_SPEC_MAT43:
-      return GL_FLOAT_MAT4x3;
-   case SLANG_SPEC_SAMPLER_1D:
-      return GL_SAMPLER_1D;
-   case SLANG_SPEC_SAMPLER_2D:
-      return GL_SAMPLER_2D;
-   case SLANG_SPEC_SAMPLER_3D:
-      return GL_SAMPLER_3D;
-   case SLANG_SPEC_SAMPLER_CUBE:
-      return GL_SAMPLER_CUBE;
-   case SLANG_SPEC_SAMPLER_1D_SHADOW:
-      return GL_SAMPLER_1D_SHADOW;
-   case SLANG_SPEC_SAMPLER_2D_SHADOW:
-      return GL_SAMPLER_2D_SHADOW;
-   case SLANG_SPEC_SAMPLER_RECT:
-      return GL_SAMPLER_2D_RECT_ARB;
-   case SLANG_SPEC_SAMPLER_RECT_SHADOW:
-      return GL_SAMPLER_2D_RECT_SHADOW_ARB;
-   case SLANG_SPEC_SAMPLER_1D_ARRAY:
-      return GL_SAMPLER_1D_ARRAY_EXT;
-   case SLANG_SPEC_SAMPLER_2D_ARRAY:
-      return GL_SAMPLER_2D_ARRAY_EXT;
-   case SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW:
-      return GL_SAMPLER_1D_ARRAY_SHADOW_EXT;
-   case SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW:
-      return GL_SAMPLER_2D_ARRAY_SHADOW_EXT;
-   case SLANG_SPEC_ARRAY:
-      return _slang_gltype_from_specifier(type->_array);
-   case SLANG_SPEC_STRUCT:
-      /* fall-through */
-   default:
-      return GL_NONE;
-   }
-}
-
diff --git a/src/mesa/slang/slang_typeinfo.h b/src/mesa/slang/slang_typeinfo.h
deleted file mode 100644 (file)
index 2251b06..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5
- *
- * Copyright (C) 2005-2006  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_TYPEINFO_H
-#define SLANG_TYPEINFO_H 1
-
-#include "main/imports.h"
-#include "main/mtypes.h"
-#include "slang_log.h"
-#include "slang_utility.h"
-#include "slang_vartable.h"
-
-
-struct slang_operation_;
-
-struct slang_name_space_;
-
-
-
-/**
- * Holds complete information about vector swizzle - the <swizzle>
- * array contains vector component source indices, where 0 is "x", 1
- * is "y", 2 is "z" and 3 is "w".
- * Example: "xwz" --> { 3, { 0, 3, 2, not used } }.
- */
-typedef struct slang_swizzle_
-{
-   GLuint num_components;
-   GLuint swizzle[4];
-} slang_swizzle;
-
-extern GLboolean
-_slang_is_swizzle(const char *field, GLuint rows, slang_swizzle *swz);
-
-
-typedef enum slang_type_variant_
-{
-   SLANG_VARIANT,    /* the default */
-   SLANG_INVARIANT   /* indicates the "invariant" keyword */
-} slang_type_variant;
-
-
-typedef enum slang_type_centroid_
-{
-   SLANG_CENTER,    /* the default */
-   SLANG_CENTROID   /* indicates the "centroid" keyword */
-} slang_type_centroid;
-
-
-/**
- * These only apply to gl_FragCoord, but other layout qualifiers may
- * appear in the future.
- */
-typedef enum slang_layout_qualifier_
-{
-   SLANG_LAYOUT_NONE                      = 0x0,
-   SLANG_LAYOUT_UPPER_LEFT_BIT            = 0x1,
-   SLANG_LAYOUT_PIXEL_CENTER_INTEGER_BIT  = 0x2
-} slang_layout_qualifier;
-
-
-typedef enum slang_type_qualifier_
-{
-   SLANG_QUAL_NONE,
-   SLANG_QUAL_CONST,
-   SLANG_QUAL_ATTRIBUTE,
-   SLANG_QUAL_VARYING,
-   SLANG_QUAL_UNIFORM,
-   SLANG_QUAL_OUT,
-   SLANG_QUAL_INOUT,
-   SLANG_QUAL_FIXEDOUTPUT,      /* internal */
-   SLANG_QUAL_FIXEDINPUT        /* internal */
-} slang_type_qualifier;
-
-typedef enum slang_varying_kind_
-{
-   SLANG_VARYING_IN,
-   SLANG_VARYING_OUT,
-} slang_varying_kind;
-
-typedef enum slang_type_precision_
-{
-   SLANG_PREC_DEFAULT,
-   SLANG_PREC_LOW,
-   SLANG_PREC_MEDIUM,
-   SLANG_PREC_HIGH
-} slang_type_precision;
-
-
-/**
- * The basic shading language types (float, vec4, mat3, etc)
- */
-typedef enum slang_type_specifier_type_
-{
-   SLANG_SPEC_VOID,
-   SLANG_SPEC_BOOL,
-   SLANG_SPEC_BVEC2,
-   SLANG_SPEC_BVEC3,
-   SLANG_SPEC_BVEC4,
-   SLANG_SPEC_INT,
-   SLANG_SPEC_IVEC2,
-   SLANG_SPEC_IVEC3,
-   SLANG_SPEC_IVEC4,
-   SLANG_SPEC_FLOAT,
-   SLANG_SPEC_VEC2,
-   SLANG_SPEC_VEC3,
-   SLANG_SPEC_VEC4,
-   SLANG_SPEC_MAT2,
-   SLANG_SPEC_MAT3,
-   SLANG_SPEC_MAT4,
-   SLANG_SPEC_MAT23,
-   SLANG_SPEC_MAT32,
-   SLANG_SPEC_MAT24,
-   SLANG_SPEC_MAT42,
-   SLANG_SPEC_MAT34,
-   SLANG_SPEC_MAT43,
-   SLANG_SPEC_SAMPLER_1D,
-   SLANG_SPEC_SAMPLER_2D,
-   SLANG_SPEC_SAMPLER_3D,
-   SLANG_SPEC_SAMPLER_CUBE,
-   SLANG_SPEC_SAMPLER_RECT,
-   SLANG_SPEC_SAMPLER_1D_SHADOW,
-   SLANG_SPEC_SAMPLER_2D_SHADOW,
-   SLANG_SPEC_SAMPLER_RECT_SHADOW,
-   SLANG_SPEC_SAMPLER_1D_ARRAY,
-   SLANG_SPEC_SAMPLER_2D_ARRAY,
-   SLANG_SPEC_SAMPLER_1D_ARRAY_SHADOW,
-   SLANG_SPEC_SAMPLER_2D_ARRAY_SHADOW,
-   SLANG_SPEC_STRUCT,
-   SLANG_SPEC_ARRAY
-} slang_type_specifier_type;
-
-
-extern slang_type_specifier_type
-slang_type_specifier_type_from_string(const char *);
-
-extern const char *
-slang_type_specifier_type_to_string(slang_type_specifier_type);
-
-
-/**
- * Describes more sophisticated types, like structs and arrays.
- */
-typedef struct slang_type_specifier_
-{
-   slang_type_specifier_type type;
-   struct slang_struct_ *_struct;         /**< if type == SLANG_SPEC_STRUCT */
-   struct slang_type_specifier_ *_array;  /**< if type == SLANG_SPEC_ARRAY */
-} slang_type_specifier;
-
-
-extern GLvoid
-slang_type_specifier_ctr(slang_type_specifier *);
-
-extern GLvoid
-slang_type_specifier_dtr(slang_type_specifier *);
-
-extern slang_type_specifier *
-slang_type_specifier_new(slang_type_specifier_type type,
-                         struct slang_struct_ *_struct,
-                         struct slang_type_specifier_ *_array);
-
-
-extern GLboolean
-slang_type_specifier_copy(slang_type_specifier *, const slang_type_specifier *);
-
-extern GLboolean
-slang_type_specifier_equal(const slang_type_specifier *,
-                           const slang_type_specifier *);
-
-
-extern GLboolean
-slang_type_specifier_compatible(const slang_type_specifier *x,
-                                const slang_type_specifier *y);
-
-
-typedef struct slang_fully_specified_type_
-{
-   slang_type_qualifier qualifier;
-   slang_type_specifier specifier;
-   slang_type_precision precision;
-   slang_type_variant variant;
-   slang_type_centroid centroid;
-   slang_layout_qualifier layout;
-   GLint array_len;           /**< -1 if not an array type */
-   slang_varying_kind varying_kind;
-} slang_fully_specified_type;
-
-extern int
-slang_fully_specified_type_construct(slang_fully_specified_type *);
-
-extern void
-slang_fully_specified_type_destruct(slang_fully_specified_type *);
-
-extern int
-slang_fully_specified_type_copy(slang_fully_specified_type *,
-                               const slang_fully_specified_type *);
-
-GLboolean
-slang_fully_specified_types_compatible(const slang_fully_specified_type * x,
-                                       const slang_fully_specified_type * y);
-
-
-typedef struct slang_typeinfo_
-{
-   GLboolean can_be_referenced;
-   GLboolean is_swizzled;
-   slang_swizzle swz;
-   slang_type_specifier spec;
-   GLuint array_len;
-} slang_typeinfo;
-
-extern GLboolean
-slang_typeinfo_construct(slang_typeinfo *);
-
-extern GLvoid
-slang_typeinfo_destruct(slang_typeinfo *);
-
-
-extern GLboolean
-_slang_typeof_operation(struct slang_operation_ *,
-                         const struct slang_name_space_ *,
-                         slang_typeinfo *, slang_atom_pool *,
-                         slang_info_log *log);
-
-extern GLboolean
-_slang_type_is_matrix(slang_type_specifier_type);
-
-extern GLboolean
-_slang_type_is_vector(slang_type_specifier_type);
-
-extern GLboolean
-_slang_type_is_float_vec_mat(slang_type_specifier_type);
-
-extern slang_type_specifier_type
-_slang_type_base(slang_type_specifier_type);
-
-extern GLuint
-_slang_type_dim(slang_type_specifier_type);
-
-extern GLenum
-_slang_gltype_from_specifier(const slang_type_specifier *type);
-
-#endif
diff --git a/src/mesa/slang/slang_utility.c b/src/mesa/slang/slang_utility.c
deleted file mode 100644 (file)
index c1d5740..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file slang_utility.c
- * slang utilities
- * \author Michal Krol
- */
-
-#include "main/imports.h"
-#include "slang_utility.h"
-#include "slang_mem.h"
-
-char *
-slang_string_concat (char *dst, const char *src)
-{
-   return strcpy (dst + strlen (dst), src);
-}
-
-
-/* slang_string */
-
-GLvoid
-slang_string_init (slang_string *self)
-{
-   self->data = NULL;
-   self->capacity = 0;
-   self->length = 0;
-   self->fail = GL_FALSE;
-}
-
-GLvoid
-slang_string_free (slang_string *self)
-{
-   if (self->data != NULL)
-      free(self->data);
-}
-
-GLvoid
-slang_string_reset (slang_string *self)
-{
-   self->length = 0;
-   self->fail = GL_FALSE;
-}
-
-static GLboolean
-grow (slang_string *self, GLuint size)
-{
-   if (self->fail)
-      return GL_FALSE;
-   if (size > self->capacity) {
-      /* do not overflow 32-bit range */
-      assert (size < 0x80000000);
-
-      self->data = (char *) (_mesa_realloc (self->data, self->capacity, size * 2));
-      self->capacity = size * 2;
-      if (self->data == NULL) {
-         self->capacity = 0;
-         self->fail = GL_TRUE;
-         return GL_FALSE;
-      }
-   }
-   return GL_TRUE;
-}
-
-GLvoid
-slang_string_push (slang_string *self, const slang_string *str)
-{
-   if (str->fail) {
-      self->fail = GL_TRUE;
-      return;
-   }
-   if (grow (self, self->length + str->length)) {
-      memcpy (&self->data[self->length], str->data, str->length);
-      self->length += str->length;
-   }
-}
-
-GLvoid
-slang_string_pushc (slang_string *self, const char c)
-{
-   if (grow (self, self->length + 1)) {
-      self->data[self->length] = c;
-      self->length++;
-   }
-}
-
-GLvoid
-slang_string_pushs (slang_string *self, const char *cstr, GLuint len)
-{
-   if (grow (self, self->length + len)) {
-      memcpy (&self->data[self->length], cstr, len);
-      self->length += len;
-   }
-}
-
-GLvoid
-slang_string_pushi (slang_string *self, GLint i)
-{
-   char buffer[12];
-
-   _mesa_snprintf (buffer, sizeof(buffer), "%d", i);
-   slang_string_pushs (self, buffer, strlen (buffer));
-}
-
-const char *
-slang_string_cstr (slang_string *self)
-{
-   if (grow (self, self->length + 1))
-      self->data[self->length] = '\0';
-   return self->data;
-}
-
-/* slang_atom_pool */
-
-void
-slang_atom_pool_construct(slang_atom_pool * pool)
-{
-   GLuint i;
-
-   for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++)
-      pool->entries[i] = NULL;
-}
-
-void
-slang_atom_pool_destruct (slang_atom_pool * pool)
-{
-   GLuint i;
-
-   for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++) {
-      slang_atom_entry * entry;
-               
-      entry = pool->entries[i];
-      while (entry != NULL) {
-         slang_atom_entry *next = entry->next;
-         _slang_free(entry->id);
-         _slang_free(entry);
-         entry = next;
-      }
-   }
-}
-
-/*
- * Search the atom pool for an atom with a given name.
- * If atom is not found, create and add it to the pool.
- * Returns ATOM_NULL if the atom was not found and the function failed
- * to create a new atom.
- */
-slang_atom
-slang_atom_pool_atom(slang_atom_pool * pool, const char * id)
-{
-   GLuint hash;
-   const char * p = id;
-   slang_atom_entry ** entry;
-
-   /* Hash a given string to a number in the range [0, ATOM_POOL_SIZE). */
-   hash = 0;
-   while (*p != '\0') {
-      GLuint g;
-
-      hash = (hash << 4) + (GLuint) (*p++);
-      g = hash & 0xf0000000;
-      if (g != 0)
-         hash ^= g >> 24;
-      hash &= ~g;
-   }
-   hash %= SLANG_ATOM_POOL_SIZE;
-
-   /* Now the hash points to a linked list of atoms with names that
-    * have the same hash value.  Search the linked list for a given
-    * name.
-    */
-   entry = &pool->entries[hash];
-   while (*entry != NULL) {
-      /* If the same, return the associated atom. */
-      if (slang_string_compare((**entry).id, id) == 0)
-         return (slang_atom) (**entry).id;
-      /* Grab the next atom in the linked list. */
-      entry = &(**entry).next;
-   }
-
-   /* Okay, we have not found an atom. Create a new entry for it.
-    * Note that the <entry> points to the last entry's <next> field.
-    */
-   *entry = (slang_atom_entry *) _slang_alloc(sizeof(slang_atom_entry));
-   if (*entry == NULL)
-      return SLANG_ATOM_NULL;
-
-   /* Initialize a new entry. Because we'll need the actual name of
-    * the atom, we use the pointer to this string as an actual atom's
-    * value.
-    */
-   (**entry).next = NULL;
-   (**entry).id = _slang_strdup(id);
-   if ((**entry).id == NULL)
-      return SLANG_ATOM_NULL;
-   return (slang_atom) (**entry).id;
-}
-
-/**
- * Return the name of a given atom.
- */
-const char *
-slang_atom_pool_id(slang_atom_pool * pool, slang_atom atom)
-{
-   return (const char *) (atom);
-}
diff --git a/src/mesa/slang/slang_utility.h b/src/mesa/slang/slang_utility.h
deleted file mode 100644 (file)
index cb9b6d2..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.5.3
- *
- * Copyright (C) 2005-2007  Brian Paul   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, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef SLANG_UTILITY_H
-#define SLANG_UTILITY_H
-
-
-#include "main/glheader.h"
-
-/* Compile-time assertions.  If the expression is zero, try to declare an
- * array of size [-1] to cause compilation error.
- */
-#define static_assert(expr) do { int _array[(expr) ? 1 : -1]; (void) _array[0]; } while (0)
-
-
-#define slang_string_compare(str1, str2) strcmp (str1, str2)
-#define slang_string_copy(dst, src) strcpy (dst, src)
-#define slang_string_length(str) strlen (str)
-
-char *slang_string_concat (char *, const char *);
-
-/* slang_string */
-
-typedef struct
-{
-   char *data;
-   GLuint length;
-   GLuint capacity;
-   GLboolean fail;
-} slang_string;
-
-GLvoid
-slang_string_init (slang_string *);
-
-GLvoid
-slang_string_free (slang_string *);
-
-GLvoid
-slang_string_reset (slang_string *);
-
-GLvoid
-slang_string_push (slang_string *, const slang_string *);
-
-GLvoid
-slang_string_pushc (slang_string *, const char);
-
-GLvoid
-slang_string_pushs (slang_string *, const char *, GLuint);
-
-GLvoid
-slang_string_pushi (slang_string *, GLint);
-
-const char *
-slang_string_cstr (slang_string *);
-
-/* slang_atom */
-
-typedef GLvoid *slang_atom;
-
-#define SLANG_ATOM_NULL ((slang_atom) 0)
-
-typedef struct slang_atom_entry_
-{
-       char *id;
-       struct slang_atom_entry_ *next;
-} slang_atom_entry;
-
-#define SLANG_ATOM_POOL_SIZE 1023
-
-typedef struct slang_atom_pool_
-{
-       slang_atom_entry *entries[SLANG_ATOM_POOL_SIZE];
-} slang_atom_pool;
-
-GLvoid slang_atom_pool_construct (slang_atom_pool *);
-GLvoid slang_atom_pool_destruct (slang_atom_pool *);
-slang_atom slang_atom_pool_atom (slang_atom_pool *, const char *);
-const char *slang_atom_pool_id (slang_atom_pool *, slang_atom);
-
-
-#endif
diff --git a/src/mesa/slang/slang_vartable.c b/src/mesa/slang/slang_vartable.c
deleted file mode 100644 (file)
index 8371631..0000000
+++ /dev/null
@@ -1,362 +0,0 @@
-
-#include "main/imports.h"
-#include "program/program.h"
-#include "program/prog_print.h"
-#include "slang_compile.h"
-#include "slang_compile_variable.h"
-#include "slang_emit.h"
-#include "slang_mem.h"
-#include "slang_vartable.h"
-#include "slang_ir.h"
-
-
-static int dbg = 0;
-
-
-typedef enum {
-   FREE,
-   VAR,
-   TEMP
-} TempState;
-
-
-/**
- * Variable/register info for one variable scope.
- */
-struct table
-{
-   int Level;
-   int NumVars;
-   slang_variable **Vars;  /* array [NumVars] */
-
-   TempState Temps[MAX_PROGRAM_TEMPS * 4];  /* per-component state */
-   int ValSize[MAX_PROGRAM_TEMPS * 4];     /**< For debug only */
-
-   struct table *Parent;  /** Parent scope table */
-};
-
-
-/**
- * A variable table is a stack of tables, one per scope.
- */
-struct slang_var_table_
-{
-   GLint CurLevel;
-   GLuint MaxRegisters;
-   struct table *Top;  /**< Table at top of stack */
-};
-
-
-
-slang_var_table *
-_slang_new_var_table(GLuint maxRegisters)
-{
-   slang_var_table *vt
-      = (slang_var_table *) _slang_alloc(sizeof(slang_var_table));
-   if (vt) {
-      vt->MaxRegisters = maxRegisters;
-   }
-   return vt;
-}
-
-
-void
-_slang_delete_var_table(slang_var_table *vt)
-{
-   if (vt->Top) {
-      _mesa_problem(NULL, "non-empty var table in _slang_delete_var_table()");
-      return;
-   }
-   _slang_free(vt);
-}
-
-
-
-/**
- * Create new table on top of vartable stack.
- * Used when we enter a {} block.
- */
-void
-_slang_push_var_table(slang_var_table *vt)
-{
-   struct table *t = (struct table *) _slang_alloc(sizeof(struct table));
-   if (t) {
-      t->Level = vt->CurLevel++;
-      t->Parent = vt->Top;
-      if (t->Parent) {
-         /* copy the info indicating which temp regs are in use */
-         memcpy(t->Temps, t->Parent->Temps, sizeof(t->Temps));
-         memcpy(t->ValSize, t->Parent->ValSize, sizeof(t->ValSize));
-      }
-      vt->Top = t;
-      if (dbg) printf("Pushing level %d\n", t->Level);
-   }
-}
-
-
-/**
- * Pop top entry from variable table.
- * Used when we leave a {} block.
- */
-void
-_slang_pop_var_table(slang_var_table *vt)
-{
-   struct table *t = vt->Top;
-   int i;
-
-   if (dbg) printf("Popping level %d\n", t->Level);
-
-   /* free the storage allocated for each variable */
-   for (i = 0; i < t->NumVars; i++) {
-      slang_ir_storage *store = t->Vars[i]->store;
-      GLint j;
-      GLuint comp;
-      if (dbg) printf("  Free var %s, size %d at %d.%s\n",
-                      (char*) t->Vars[i]->a_name, store->Size,
-                      store->Index,
-                      _mesa_swizzle_string(store->Swizzle, 0, 0));
-
-      if (store->File == PROGRAM_SAMPLER) {
-         /* samplers have no storage */
-         continue;
-      }
-
-      if (store->Size == 1)
-         comp = GET_SWZ(store->Swizzle, 0);
-      else
-         comp = 0;
-
-      /* store->Index may be -1 if we run out of registers */
-      if (store->Index >= 0) {
-         for (j = 0; j < store->Size; j++) {
-            assert(t->Temps[store->Index * 4 + j + comp] == VAR);
-            t->Temps[store->Index * 4 + j + comp] = FREE;
-         }
-      }
-      store->Index = -1;
-   }
-   if (t->Parent) {
-      /* just verify that any remaining allocations in this scope 
-       * were for temps
-       */
-      for (i = 0; i < (int) vt->MaxRegisters * 4; i++) {
-         if (t->Temps[i] != FREE && t->Parent->Temps[i] == FREE) {
-            if (dbg) printf("  Free reg %d\n", i/4);
-            assert(t->Temps[i] == TEMP);
-         }
-      }
-   }
-
-   if (t->Vars) {
-      _slang_free(t->Vars);
-      t->Vars = NULL;
-   }
-
-   vt->Top = t->Parent;
-   _slang_free(t);
-   vt->CurLevel--;
-}
-
-
-/**
- * Add a new variable to the given var/symbol table.
- */
-void
-_slang_add_variable(slang_var_table *vt, slang_variable *v)
-{
-   struct table *t;
-   assert(vt);
-   t = vt->Top;
-   assert(t);
-   if (dbg) printf("Adding var %s, store %p\n", (char *) v->a_name, (void *) v->store);
-   t->Vars = (slang_variable **)
-      _slang_realloc(t->Vars,
-                     t->NumVars * sizeof(slang_variable *),
-                     (t->NumVars + 1) * sizeof(slang_variable *));
-   t->Vars[t->NumVars] = v;
-   t->NumVars++;
-}
-
-
-/**
- * Look for variable by name in given table.
- * If not found, Parent table will be searched.
- */
-slang_variable *
-_slang_find_variable(const slang_var_table *vt, slang_atom name)
-{
-   struct table *t = vt->Top;
-   while (1) {
-      int i;
-      for (i = 0; i < t->NumVars; i++) {
-         if (t->Vars[i]->a_name == name)
-            return t->Vars[i];
-      }
-      if (t->Parent)
-         t = t->Parent;
-      else
-         return NULL;
-   }
-}
-
-
-/**
- * Allocation helper.
- * \param size  var size in floats
- * \return  position for var, measured in floats
- */
-static GLint
-alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp)
-{
-   struct table *t = vt->Top;
-   /* if size == 1, allocate anywhere, else, pos must be multiple of 4 */
-   const GLuint step = (size == 1) ? 1 : 4;
-   GLuint i, j;
-   assert(size > 0); /* number of floats */
-
-   for (i = 0; i <= vt->MaxRegisters * 4 - size; i += step) {
-      GLuint found = 0;
-      for (j = 0; j < (GLuint) size; j++) {
-         assert(i + j < 4 * MAX_PROGRAM_TEMPS);
-         if (i + j < vt->MaxRegisters * 4 && t->Temps[i + j] == FREE) {
-            found++;
-         }
-         else {
-            break;
-         }
-      }
-      if (found == size) {
-         /* found block of size free regs */
-         if (size > 1)
-            assert(i % 4 == 0);
-         for (j = 0; j < (GLuint) size; j++) {
-            assert(i + j < 4 * MAX_PROGRAM_TEMPS);
-            t->Temps[i + j] = isTemp ? TEMP : VAR;
-         }
-         assert(i < MAX_PROGRAM_TEMPS * 4);
-         t->ValSize[i] = size;
-         return i;
-      }
-   }
-
-   /* if we get here, we ran out of registers */
-   return -1;
-}
-
-
-/**
- * Allocate temp register(s) for storing a variable.
- * \param size  size needed, in floats
- * \param swizzle  returns swizzle mask for accessing var in register
- * \return  register allocated, or -1
- */
-GLboolean
-_slang_alloc_var(slang_var_table *vt, slang_ir_storage *store)
-{
-   struct table *t = vt->Top;
-   int i;
-
-   if (store->File == PROGRAM_SAMPLER) {
-      /* don't really allocate storage */
-      store->Index = 0;
-      return GL_TRUE;
-   }
-
-   i = alloc_reg(vt, store->Size, GL_FALSE);
-   if (i < 0)
-      return GL_FALSE;
-
-   store->Index = i / 4;
-   store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
-
-   if (dbg)
-      printf("Alloc var storage sz %d at %d.%s (level %d) store %p\n",
-             store->Size, store->Index,
-             _mesa_swizzle_string(store->Swizzle, 0, 0),
-             t->Level,
-             (void*) store);
-
-   return GL_TRUE;
-}
-
-
-
-/**
- * Allocate temp register(s) for storing an unnamed intermediate value.
- */
-GLboolean
-_slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store)
-{
-   struct table *t = vt->Top;
-   const int i = alloc_reg(vt, store->Size, GL_TRUE);
-   if (i < 0)
-      return GL_FALSE;
-
-   assert(store->Index < 0);
-
-   store->Index = i / 4;
-   store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
-
-   if (dbg) printf("Alloc temp sz %d at %d.%s (level %d) store %p\n",
-                   store->Size, store->Index,
-                   _mesa_swizzle_string(store->Swizzle, 0, 0), t->Level,
-                   (void *) store);
-
-   return GL_TRUE;
-}
-
-
-void
-_slang_free_temp(slang_var_table *vt, slang_ir_storage *store)
-{
-   struct table *t = vt->Top;
-   GLuint i;
-   GLint r = store->Index;
-   assert(store->Size > 0);
-   assert(r >= 0);
-   assert((GLuint)r + store->Size <= vt->MaxRegisters * 4);
-   if (dbg) printf("Free temp sz %d at %d.%s (level %d) store %p\n",
-                   store->Size, r,
-                   _mesa_swizzle_string(store->Swizzle, 0, 0),
-                   t->Level, (void *) store);
-   if (store->Size == 1) {
-      const GLuint comp = GET_SWZ(store->Swizzle, 0);
-      /* we can actually fail some of these assertions because of the
-       * troublesome IR_SWIZZLE handling.
-       */
-#if 0
-      assert(store->Swizzle == MAKE_SWIZZLE4(comp, comp, comp, comp));
-      assert(comp < 4);
-      assert(t->ValSize[r * 4 + comp] == 1);
-#endif
-      assert(t->Temps[r * 4 + comp] == TEMP);
-      t->Temps[r * 4 + comp] = FREE;
-   }
-   else {
-      /*assert(store->Swizzle == SWIZZLE_NOOP);*/
-      assert(t->ValSize[r*4] == store->Size);
-      for (i = 0; i < (GLuint) store->Size; i++) {
-         assert(t->Temps[r * 4 + i] == TEMP);
-         t->Temps[r * 4 + i] = FREE;
-      }
-   }
-}
-
-
-GLboolean
-_slang_is_temp(const slang_var_table *vt, const slang_ir_storage *store)
-{
-   struct table *t = vt->Top;
-   GLuint comp;
-   assert(store->Index >= 0);
-   assert(store->Index < (int) vt->MaxRegisters);
-   if (store->Swizzle == SWIZZLE_NOOP)
-      comp = 0;
-   else
-      comp = GET_SWZ(store->Swizzle, 0);
-
-   if (t->Temps[store->Index * 4 + comp] == TEMP)
-      return GL_TRUE;
-   else
-      return GL_FALSE;
-}
diff --git a/src/mesa/slang/slang_vartable.h b/src/mesa/slang/slang_vartable.h
deleted file mode 100644 (file)
index 97945b8..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-
-#ifndef SLANG_VARTABLE_H
-#define SLANG_VARTABLE_H
-
-#include "main/glheader.h"
-#include "slang_utility.h"
-
-struct slang_ir_storage_;
-
-typedef struct slang_var_table_ slang_var_table;
-
-struct slang_variable_;
-
-extern slang_var_table *
-_slang_new_var_table(GLuint maxRegisters);
-
-extern void
-_slang_delete_var_table(slang_var_table *vt);
-
-extern void
-_slang_push_var_table(slang_var_table *parent);
-
-extern void
-_slang_pop_var_table(slang_var_table *t);
-
-extern void
-_slang_add_variable(slang_var_table *t, struct slang_variable_ *v);
-
-extern struct slang_variable_ *
-_slang_find_variable(const slang_var_table *t, slang_atom name);
-
-extern GLboolean
-_slang_alloc_var(slang_var_table *t, struct slang_ir_storage_ *store);
-
-extern GLboolean
-_slang_alloc_temp(slang_var_table *t, struct slang_ir_storage_ *store);
-
-extern void
-_slang_free_temp(slang_var_table *t, struct slang_ir_storage_ *store);
-
-extern GLboolean
-_slang_is_temp(const slang_var_table *t, const struct slang_ir_storage_ *store);
-
-
-#endif /* SLANG_VARTABLE_H */
index f01b60c4fc89d4a6960a58bf33ed45333f4aacbc..9156024d4718b70501bb4e5298502ad0a29b9ed1 100644 (file)
@@ -250,26 +250,8 @@ PROGRAM_SOURCES = \
        program/programopt.c \
        program/symbol_table.c
 
-SLANG_SOURCES =        \
-       slang/slang_builtin.c   \
-       slang/slang_codegen.c   \
-       slang/slang_compile.c   \
-       slang/slang_compile_function.c  \
-       slang/slang_compile_operation.c \
-       slang/slang_compile_struct.c    \
-       slang/slang_compile_variable.c  \
-       slang/slang_emit.c      \
-       slang/slang_ir.c        \
-       slang/slang_label.c     \
-       slang/slang_link.c      \
-       slang/slang_log.c       \
-       slang/slang_mem.c       \
-       slang/slang_print.c     \
-       slang/slang_simplify.c  \
-       slang/slang_storage.c   \
-       slang/slang_typeinfo.c  \
-       slang/slang_vartable.c  \
-       slang/slang_utility.c
+SHADER_CXX_SOURCES = \
+       program/ir_to_mesa.cpp
 
 ASM_C_SOURCES =        \
        x86/common_x86.c \
@@ -324,8 +306,10 @@ MESA_SOURCES = \
        $(SWRAST_SOURCES)       \
        $(SWRAST_SETUP_SOURCES) \
        $(COMMON_DRIVER_SOURCES)\
-       $(ASM_C_SOURCES)        \
-       $(SLANG_SOURCES)
+       $(ASM_C_SOURCES)
+
+MESA_CXX_SOURCES = \
+        $(SHADER_CXX_SOURCES)
 
 # Sources for building Gallium drivers
 MESA_GALLIUM_SOURCES = \
@@ -335,12 +319,15 @@ MESA_GALLIUM_SOURCES = \
        $(STATETRACKER_SOURCES) \
        $(PROGRAM_SOURCES)      \
        ppc/common_ppc.c        \
-       x86/common_x86.c        \
-       $(SLANG_SOURCES)
+       x86/common_x86.c
+
+MESA_GALLIUM_CXX_SOURCES = \
+        $(SHADER_CXX_SOURCES)
 
 # All the core C sources, for dependency checking
 ALL_SOURCES = \
        $(MESA_SOURCES)         \
+       $(MESA_CXX_SOURCES)     \
        $(MESA_ASM_SOURCES)     \
        $(STATETRACKER_SOURCES)
 
@@ -349,10 +336,12 @@ ALL_SOURCES = \
 
 MESA_OBJECTS = \
        $(MESA_SOURCES:.c=.o) \
+       $(MESA_CXX_SOURCES:.cpp=.o) \
        $(MESA_ASM_SOURCES:.S=.o)
 
 MESA_GALLIUM_OBJECTS = \
        $(MESA_GALLIUM_SOURCES:.c=.o) \
+       $(MESA_GALLIUM_CXX_SOURCES:.cpp=.o) \
        $(MESA_ASM_SOURCES:.S=.o)
 
 
@@ -362,8 +351,7 @@ COMMON_DRIVER_OBJECTS = $(COMMON_DRIVER_SOURCES:.c=.o)
 ### Other archives/libraries
 
 GLSL_LIBS = \
-       $(TOP)/src/glsl/pp/libglslpp.a \
-       $(TOP)/src/glsl/cl/libglslcl.a
+       $(TOP)/src/glsl/libglsl.a
 
 
 ### Include directories
index 7d52481c82e7cf268eaf87d2ef828fae6e4c2ff0..06425dc8a35922f3412b4512a9447b683bdad40f 100644 (file)
@@ -41,6 +41,8 @@ extern void st_init_accum_functions(struct dd_function_table *functions);
 
 #else
 
+#include "main/compiler.h"
+
 static INLINE void
 st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
 {
index 0b8ecd27cb99da8a03c1c8f6760ce4afb4a330b3..8da5cbb5e6840f7096e99d966d13dbf68a92e7b0 100644 (file)
@@ -275,7 +275,7 @@ make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
    /**
     * Create texture to hold bitmap pattern.
     */
-   pt = st_texture_create(st, PIPE_TEXTURE_2D, st->bitmap.tex_format,
+   pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format,
                           0, width, height, 1,
                           PIPE_BIND_SAMPLER_VIEW);
    if (!pt) {
@@ -304,7 +304,7 @@ make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
 }
 
 static GLuint
-setup_bitmap_vertex_data(struct st_context *st,
+setup_bitmap_vertex_data(struct st_context *st, bool normalized,
                          int x, int y, int width, int height,
                          float z, const float color[4])
 {
@@ -316,12 +316,20 @@ setup_bitmap_vertex_data(struct st_context *st,
    const GLfloat x1 = (GLfloat)(x + width);
    const GLfloat y0 = (GLfloat)y;
    const GLfloat y1 = (GLfloat)(y + height);
-   const GLfloat sLeft = (GLfloat)0.0, sRight = (GLfloat)1.0;
-   const GLfloat tTop = (GLfloat)0.0, tBot = (GLfloat)1.0 - tTop;
+   GLfloat sLeft = (GLfloat)0.0, sRight = (GLfloat)1.0;
+   GLfloat tTop = (GLfloat)0.0, tBot = (GLfloat)1.0 - tTop;
    const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
    const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
    const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
    const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
+   const GLuint max_slots = 1; /* 4096 / sizeof(st->bitmap.vertices); */
+   GLuint i;
+
+   if(!normalized)
+   {
+      sRight = width;
+      tBot = height;
+   }
 
    /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as
     * no_flush) updates to buffers where we know there is no conflict
@@ -333,9 +341,6 @@ setup_bitmap_vertex_data(struct st_context *st,
     * price of allocating a new buffer for each bitmap cache-flush to
     * avoid synchronous rendering.
     */
-   const GLuint max_slots = 1; /* 4096 / sizeof(st->bitmap.vertices); */
-   GLuint i;
-
    if (st->bitmap.vbuf_slot >= max_slots) {
       pipe_resource_reference(&st->bitmap.vbuf, NULL);
       st->bitmap.vbuf_slot = 0;
@@ -462,7 +467,7 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
       for (i = 0; i < st->state.num_samplers; i++) {
          samplers[i] = &st->state.samplers[i];
       }
-      samplers[stfp->bitmap_sampler] = &st->bitmap.sampler;
+      samplers[stfp->bitmap_sampler] = &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT];
       cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers);
    }
 
@@ -499,7 +504,7 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
    z = z * 2.0 - 1.0;
 
    /* draw textured quad */
-   offset = setup_bitmap_vertex_data(st, x, y, width, height, z, color);
+   offset = setup_bitmap_vertex_data(st, sv->texture->target != PIPE_TEXTURE_RECT, x, y, width, height, z, color);
 
    util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset,
                            PIPE_PRIM_TRIANGLE_FAN,
@@ -761,7 +766,7 @@ st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
    if (pt) {
       struct pipe_sampler_view *sv = st_create_texture_sampler_view(st->pipe, pt);
 
-      assert(pt->target == PIPE_TEXTURE_2D);
+      assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT);
 
       if (sv) {
          draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
@@ -789,7 +794,7 @@ st_init_bitmap_functions(struct dd_function_table *functions)
 void
 st_init_bitmap(struct st_context *st)
 {
-   struct pipe_sampler_state *sampler = &st->bitmap.sampler;
+   struct pipe_sampler_state *sampler = &st->bitmap.samplers[0];
    struct pipe_context *pipe = st->pipe;
    struct pipe_screen *screen = pipe->screen;
 
@@ -801,7 +806,8 @@ st_init_bitmap(struct st_context *st)
    sampler->min_img_filter = PIPE_TEX_FILTER_NEAREST;
    sampler->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
    sampler->mag_img_filter = PIPE_TEX_FILTER_NEAREST;
-   sampler->normalized_coords = 1;
+   st->bitmap.samplers[1] = *sampler;
+   st->bitmap.samplers[1].normalized_coords = 1;
 
    /* init baseline rasterizer state once */
    memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer));
index 1f73f503f6f004880c94dca32a5d540997840e85..536748402f40075477a1d560fd490d43ed1d3f8e 100644 (file)
@@ -40,6 +40,7 @@
 #include "st_cb_fbo.h"
 
 #include "util/u_blit.h"
+#include "util/u_inlines.h"
 
 
 void
@@ -152,38 +153,33 @@ st_BlitFramebuffer(GLcontext *ctx,
       /* depth and/or stencil blit */
 
       /* get src/dst depth surfaces */
-      struct st_renderbuffer *srcDepthRb = 
+      struct gl_renderbuffer_attachment *srcDepth =
+         &readFB->Attachment[BUFFER_DEPTH];
+      struct gl_renderbuffer_attachment *dstDepth =
+         &drawFB->Attachment[BUFFER_DEPTH];
+      struct gl_renderbuffer_attachment *srcStencil =
+         &readFB->Attachment[BUFFER_STENCIL];
+      struct gl_renderbuffer_attachment *dstStencil =
+         &drawFB->Attachment[BUFFER_STENCIL];
+
+      struct st_renderbuffer *srcDepthRb =
          st_renderbuffer(readFB->Attachment[BUFFER_DEPTH].Renderbuffer);
       struct st_renderbuffer *dstDepthRb = 
          st_renderbuffer(drawFB->Attachment[BUFFER_DEPTH].Renderbuffer);
-      struct pipe_surface *srcDepthSurf =
-         srcDepthRb ? srcDepthRb->surface : NULL;
       struct pipe_surface *dstDepthSurf =
          dstDepthRb ? dstDepthRb->surface : NULL;
 
-      /* get src/dst stencil surfaces */
-      struct st_renderbuffer *srcStencilRb = 
-         st_renderbuffer(readFB->Attachment[BUFFER_STENCIL].Renderbuffer);
-      struct st_renderbuffer *dstStencilRb = 
-         st_renderbuffer(drawFB->Attachment[BUFFER_STENCIL].Renderbuffer);
-      struct pipe_surface *srcStencilSurf =
-         srcStencilRb ? srcStencilRb->surface : NULL;
-      struct pipe_surface *dstStencilSurf =
-         dstStencilRb ? dstStencilRb->surface : NULL;
-
       if ((mask & depthStencil) == depthStencil &&
-          srcDepthSurf == srcStencilSurf &&
-          dstDepthSurf == dstStencilSurf) {
-         struct pipe_subresource srcSub;
-
-         srcSub.face = srcDepthRb->surface->face;
-         srcSub.level = srcDepthRb->surface->level;
+          st_is_depth_stencil_combined(srcDepth, srcStencil) &&
+          st_is_depth_stencil_combined(dstDepth, dstStencil)) {
 
          /* Blitting depth and stencil values between combined
           * depth/stencil buffers.  This is the ideal case for such buffers.
           */
-         util_blit_pixels(st->blit,
-                          srcDepthRb->texture, srcSub, srcX0, srcY0, srcX1, srcY1,
+         util_blit_pixels(st->blit, srcDepthRb->texture,
+                          u_subresource(srcDepthRb->surface->face,
+                                        srcDepthRb->surface->level),
+                          srcX0, srcY0, srcX1, srcY1,
                           srcDepthRb->surface->zslice,
                           dstDepthSurf, dstX0, dstY0, dstX1, dstY1,
                           0.0, pFilter);
@@ -192,8 +188,13 @@ st_BlitFramebuffer(GLcontext *ctx,
          /* blitting depth and stencil separately */
 
          if (mask & GL_DEPTH_BUFFER_BIT) {
-            /* blit Z only */
-            _mesa_problem(ctx, "st_BlitFramebuffer(DEPTH) not completed");
+            util_blit_pixels(st->blit, srcDepthRb->texture,
+                             u_subresource(srcDepthRb->surface->face,
+                                           srcDepthRb->surface->level),
+                             srcX0, srcY0, srcX1, srcY1,
+                             srcDepthRb->surface->zslice,
+                             dstDepthSurf, dstX0, dstY0, dstX1, dstY1,
+                             0.0, pFilter);
          }
 
          if (mask & GL_STENCIL_BUFFER_BIT) {
index 69a3dd45e80a49558e869f2c7f2ae9035211e9e5..1147b1950e25bd51ffaa3627c43cb44e7adea163 100644 (file)
@@ -301,37 +301,10 @@ static struct pipe_resource *
 alloc_texture(struct st_context *st, GLsizei width, GLsizei height,
               enum pipe_format texFormat)
 {
-   struct pipe_context *pipe = st->pipe;
-   struct pipe_screen *screen = pipe->screen;
    struct pipe_resource *pt;
-   int ptw, pth;
-
-   ptw = width;
-   pth = height;
-
-   /* Need to use POT texture? */
-   if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) {
-      int l2pt, maxSize;
-
-      l2pt = util_logbase2(width);
-      if (1 << l2pt != width) {
-         ptw = 1 << (l2pt + 1);
-      }
-
-      l2pt = util_logbase2(height);
-      if (1 << l2pt != height) {
-         pth = 1 << (l2pt + 1);
-      }
-
-      /* Check against maximum texture size */
-      maxSize = 1 << (pipe->screen->get_param(pipe->screen,
-                               PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
-      assert(ptw <= maxSize);
-      assert(pth <= maxSize);
-   }
 
-   pt = st_texture_create(st, PIPE_TEXTURE_2D, texFormat, 0,
-                          ptw, pth, 1, PIPE_BIND_SAMPLER_VIEW);
+   pt = st_texture_create(st, st->internal_target, texFormat, 0,
+                          width, height, 1, PIPE_BIND_SAMPLER_VIEW);
 
    return pt;
 }
@@ -536,6 +509,7 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
    struct cso_context *cso = st->cso_context;
    GLfloat x0, y0, x1, y1;
    GLsizei maxSize;
+   boolean normalized = sv->texture->target != PIPE_TEXTURE_RECT;
 
    /* limit checks */
    /* XXX if DrawPixels image is larger than max texture size, break
@@ -579,7 +553,7 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
       sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
       sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
       sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
-      sampler.normalized_coords = 1;
+      sampler.normalized_coords = normalized;
 
       cso_single_sampler(cso, 0, &sampler);
       if (st->pixel_xfer.pixelmap_enabled) {
@@ -635,8 +609,8 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
    z = z * 2.0 - 1.0;
 
    draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex,
-             (GLfloat) width / sv->texture->width0,
-             (GLfloat) height / sv->texture->height0);
+             normalized ? ((GLfloat) width / sv->texture->width0) : (GLfloat)width,
+             normalized ? ((GLfloat) height / sv->texture->height0) : (GLfloat)height);
 
    /* restore state */
    cso_restore_rasterizer(cso);
@@ -1002,7 +976,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
 
    srcFormat = rbRead->texture->format;
 
-   if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE_2D, sample_count,
+   if (screen->is_format_supported(screen, srcFormat, st->internal_target, sample_count,
                                    PIPE_BIND_SAMPLER_VIEW, 0)) {
       texFormat = srcFormat;
    }
@@ -1010,13 +984,13 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
       /* srcFormat can't be used as a texture format */
       if (type == GL_DEPTH) {
          texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT,
-                                      PIPE_TEXTURE_2D, sample_count,
+                                      st->internal_target, sample_count,
                                       PIPE_BIND_DEPTH_STENCIL);
          assert(texFormat != PIPE_FORMAT_NONE);
       }
       else {
          /* default color format */
-         texFormat = st_choose_format(screen, GL_RGBA, PIPE_TEXTURE_2D, 
+         texFormat = st_choose_format(screen, GL_RGBA, st->internal_target,
                                       sample_count, PIPE_BIND_SAMPLER_VIEW);
          assert(texFormat != PIPE_FORMAT_NONE);
       }
index 037e576fabe229366d728195067df780e24bd51c..3145416383baad5dba19547cbeab7e85d7b7e945 100644 (file)
@@ -128,7 +128,8 @@ st_bind_surface(GLcontext *ctx, GLenum target,
    _mesa_set_fetch_functions(texImage, 2);
 
    /* FIXME create a non-default sampler view from the pipe_surface? */
-   pipe_resource_reference(&stImage->pt, ps->texture);
+   pipe_resource_reference(&stObj->pt, ps->texture);
+   pipe_resource_reference(&stImage->pt, stObj->pt);
 
    stObj->width0 = ps->width;
    stObj->height0 = ps->height;
index 13119ce2037fb6510fca0debec4507589809c830..71bd4729e03dc5862109cccddc4f79a95997b559 100644 (file)
@@ -108,7 +108,7 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
       /* Setup new texture template.
        */
       memset(&template, 0, sizeof(template));
-      template.target = PIPE_TEXTURE_2D;
+      template.target = st->internal_target;
       template.format = format;
       template.width0 = width;
       template.height0 = height;
@@ -447,6 +447,30 @@ st_validate_attachment(struct pipe_screen *screen,
 }
 
 
+/**
+ * Check if two renderbuffer attachments name a combined depth/stencil
+ * renderbuffer.
+ */
+GLboolean
+st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth,
+                             const struct gl_renderbuffer_attachment *stencil)
+{
+   assert(depth && stencil);
+
+   if (depth->Type == stencil->Type) {
+      if (depth->Type == GL_RENDERBUFFER_EXT &&
+          depth->Renderbuffer == stencil->Renderbuffer)
+         return GL_TRUE;
+
+      if (depth->Type == GL_TEXTURE &&
+          depth->Texture == stencil->Texture)
+         return GL_TRUE;
+   }
+
+   return GL_FALSE;
+}
+
 /**
  * Check that the framebuffer configuration is valid in terms of what
  * the driver can support.
@@ -543,6 +567,7 @@ st_ReadBuffer(GLcontext *ctx, GLenum buffer)
 
 void st_init_fbo_functions(struct dd_function_table *functions)
 {
+#if FEATURE_EXT_framebuffer_object
    functions->NewFramebuffer = st_new_framebuffer;
    functions->NewRenderbuffer = st_new_renderbuffer;
    functions->BindFramebuffer = st_bind_framebuffer;
@@ -550,6 +575,7 @@ void st_init_fbo_functions(struct dd_function_table *functions)
    functions->RenderTexture = st_render_texture;
    functions->FinishRenderTexture = st_finish_render_texture;
    functions->ValidateFramebuffer = st_validate_framebuffer;
+#endif
    /* no longer needed by core Mesa, drivers handle resizes...
    functions->ResizeBuffers = st_resize_buffers;
    */
index 62a9bbcb25f087e893490903b773e3715f3ebb70..3e9815c1b13cfee4216075caf318438bbfc8401a 100644 (file)
@@ -88,4 +88,9 @@ st_get_renderbuffer_sampler_view(struct st_renderbuffer *rb,
                                  struct pipe_context *pipe);
 
 
+extern GLboolean
+st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth,
+                             const struct gl_renderbuffer_attachment *stencil);
+
+
 #endif /* ST_CB_FBO_H */
index b8493dab93f0ad02fcc0b7c635fb59c08a9586c3..6ab03ec9391d6e916047323e3bcec2f4f86aeee2 100644 (file)
@@ -68,16 +68,20 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
    ubyte *stmap;
    GLint j;
 
+   if (strb->Base.Wrapped) {
+      strb = st_renderbuffer(strb->Base.Wrapped);
+   }
+
    if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
       y = ctx->DrawBuffer->Height - y - height;
    }
 
    /* Create a read transfer from the renderbuffer's texture */
 
-   pt = pipe_get_transfer(st_context(ctx)->pipe, strb->texture,
-                                      0, 0, 0,
-                                      PIPE_TRANSFER_READ, x, y,
-                                      width, height);
+   pt = pipe_get_transfer(pipe, strb->texture,
+                          0, 0, 0,  /* face, level, zslice */
+                          PIPE_TRANSFER_READ,
+                          x, y, width, height);
 
    /* map the stencil buffer */
    stmap = pipe_transfer_map(pipe, pt);
@@ -230,10 +234,10 @@ st_fast_readpixels(GLcontext *ctx, struct st_renderbuffer *strb,
          y = strb->texture->height0 - y - height;
       }
 
-      trans = pipe_get_transfer(st_context(ctx)->pipe, strb->texture,
-                                            0, 0, 0,
-                                            PIPE_TRANSFER_READ, x, y,
-                                            width, height);
+      trans = pipe_get_transfer(pipe, strb->texture,
+                                0, 0, 0,  /* face, level, zslice */
+                                PIPE_TRANSFER_READ,
+                                x, y, width, height);
       if (!trans) {
          return GL_FALSE;
       }
@@ -359,6 +363,9 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
    }
    else if (format == GL_DEPTH_COMPONENT) {
       strb = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
+      if (strb->Base.Wrapped) {
+         strb = st_renderbuffer(strb->Base.Wrapped);
+      }
    }
    else {
       /* Read color buffer */
@@ -394,10 +401,10 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
    }
 
    /* Create a read transfer from the renderbuffer's texture */
-   trans = pipe_get_transfer(st_context(ctx)->pipe, strb->texture,
-                                         0, 0, 0,
-                                         PIPE_TRANSFER_READ, x, y,
-                                         width, height);
+   trans = pipe_get_transfer(pipe, strb->texture,
+                             0, 0, 0,  /* face, level, zslice */
+                             PIPE_TRANSFER_READ,
+                             x, y, width, height);
 
    /* determine bottom-to-top vs. top-to-bottom order */
    if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
index 4c3e3688dd89720e80373c0db6212c03f5dfc137..9eb14033eeb57765cab10a19e1eebd6ee8e2b7dd 100644 (file)
@@ -74,9 +74,11 @@ gl_target_to_pipe(GLenum target)
       return PIPE_TEXTURE_1D;
 
    case GL_TEXTURE_2D:
-   case GL_TEXTURE_RECTANGLE_NV:
       return PIPE_TEXTURE_2D;
 
+   case GL_TEXTURE_RECTANGLE_NV:
+      return PIPE_TEXTURE_RECT;
+
    case GL_TEXTURE_3D:
       return PIPE_TEXTURE_3D;
 
@@ -449,7 +451,7 @@ compress_with_blit(GLcontext * ctx,
    /* Create the temporary source texture
     */
    memset(&templ, 0, sizeof(templ));
-   templ.target = PIPE_TEXTURE_2D;
+   templ.target = st->internal_target;
    templ.format = st_mesa_format_to_pipe_format(mesa_format);
    templ.width0 = width;
    templ.height0 = height;
@@ -546,6 +548,14 @@ st_TexImage(GLcontext * ctx,
    /* switch to "normal" */
    if (stObj->surface_based) {
       _mesa_clear_texture_object(ctx, texObj);
+      pipe_resource_reference(&stObj->pt, NULL);
+
+      /* oops, need to init this image again */
+      _mesa_init_teximage_fields(ctx, target, texImage,
+            width, height, depth, border, internalFormat);
+      _mesa_choose_texture_format(ctx, texObj, texImage, target, level,
+            internalFormat, format, type);
+
       stObj->surface_based = GL_FALSE;
    }
 
index 2ce5f08753684fa0f8d6828fa3c5a3dff7b61dd0..3b046962efe9e06944862641356c408ea3ce4b3a 100644 (file)
@@ -125,6 +125,11 @@ st_create_context_priv( GLcontext *ctx, struct pipe_context *pipe )
    st_init_generate_mipmap(st);
    st_init_blit(st);
 
+   if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES))
+      st->internal_target = PIPE_TEXTURE_2D;
+   else
+      st->internal_target = PIPE_TEXTURE_RECT;
+
    for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
       st->state.sampler_list[i] = &st->state.samplers[i];
 
index 60c25fb8f00225a7c14057f59ed079630864b1c5..991feee3001b60dc911ef2b5c7dd081241d0ca81 100644 (file)
@@ -149,7 +149,7 @@ struct st_context
    /** for glBitmap */
    struct {
       struct pipe_rasterizer_state rasterizer;
-      struct pipe_sampler_state sampler;
+      struct pipe_sampler_state samplers[2];
       enum pipe_format tex_format;
       void *vs;
       float vertices[4][3][4];  /**< vertex pos + color + texcoord */
@@ -182,6 +182,7 @@ struct st_context
 
    void *passthrough_fs;  /**< simple pass-through frag shader */
 
+   enum pipe_texture_target internal_target;
    struct gen_mipmap_state *gen_mipmap;
    struct blit_state *blit;
 
index 5b0548927023633384bf81e886bc67026f972c97..318e08886c7e6cb73af2a37b771f7a5bd67b75b6 100644 (file)
@@ -691,9 +691,6 @@ st_draw_vbo(GLcontext *ctx,
    pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer);
    cso_set_vertex_elements(st->cso_context, num_velements, velements);
 
-   if (num_vbuffers == 0 || num_velements == 0)
-      return;
-
    setup_index_buffer(ctx, ib, &ibuffer);
    pipe->set_index_buffer(pipe, &ibuffer);
 
index 5cf2666334129234baa0627d6696df5404685f24..df05c7f70dfafa7e48463eeff9ad718f469788a5 100644 (file)
@@ -104,14 +104,15 @@ st_feedback_draw_vbo(GLcontext *ctx,
    struct draw_context *draw = st->draw;
    const struct st_vertex_program *vp;
    const struct pipe_shader_state *vs;
-   struct pipe_resource *index_buffer_handle = 0;
    struct pipe_vertex_buffer vbuffers[PIPE_MAX_SHADER_INPUTS];
    struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
+   struct pipe_index_buffer ibuffer;
    struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
    struct pipe_transfer *ib_transfer = NULL;
    struct pipe_transfer *cb_transfer;
    GLuint attr, i;
    ubyte *mapped_constants;
+   const void *mapped_indices = NULL;
 
    assert(draw);
 
@@ -204,17 +205,19 @@ st_feedback_draw_vbo(GLcontext *ctx,
    draw_set_vertex_buffers(draw, vp->num_inputs, vbuffers);
    draw_set_vertex_elements(draw, vp->num_inputs, velements);
 
+   memset(&ibuffer, 0, sizeof(ibuffer));
    if (ib) {
       struct gl_buffer_object *bufobj = ib->obj;
-      unsigned indexSize;
-      void *map;
 
       switch (ib->type) {
       case GL_UNSIGNED_INT:
-         indexSize = 4;
+         ibuffer.index_size = 4;
          break;
       case GL_UNSIGNED_SHORT:
-         indexSize = 2;
+         ibuffer.index_size = 2;
+         break;
+      case GL_UNSIGNED_BYTE:
+         ibuffer.index_size = 1;
          break;
       default:
          assert(0);
@@ -224,23 +227,20 @@ st_feedback_draw_vbo(GLcontext *ctx,
       if (bufobj && bufobj->Name) {
          struct st_buffer_object *stobj = st_buffer_object(bufobj);
 
-         index_buffer_handle = stobj->buffer;
-
-         map = pipe_buffer_map(pipe, index_buffer_handle,
-                               PIPE_TRANSFER_READ, &ib_transfer);
+         pipe_resource_reference(&ibuffer.buffer, stobj->buffer);
+         ibuffer.offset = pointer_to_offset(ib->ptr);
 
-         draw_set_mapped_element_buffer(draw, indexSize, 0, map);
+         mapped_indices = pipe_buffer_map(pipe, stobj->buffer,
+                                          PIPE_TRANSFER_READ, &ib_transfer);
       }
       else {
-         draw_set_mapped_element_buffer(draw, indexSize, 0, (void *) ib->ptr);
-        ib_transfer = NULL;
+         /* skip setting ibuffer.buffer as the draw module does not use it */
+         mapped_indices = ib->ptr;
       }
-   }
-   else {
-      /* no index/element buffer */
-      draw_set_mapped_element_buffer(draw, 0, 0, NULL);
-   }
 
+      draw_set_index_buffer(draw, &ibuffer);
+      draw_set_mapped_index_buffer(draw, mapped_indices);
+   }
 
    /* map constant buffers */
    mapped_constants = pipe_buffer_map(pipe,
@@ -273,9 +273,14 @@ st_feedback_draw_vbo(GLcontext *ctx,
          draw_set_mapped_vertex_buffer(draw, i, NULL);
       }
    }
-   if (index_buffer_handle) {
-      pipe_buffer_unmap(pipe, index_buffer_handle, ib_transfer);
-      draw_set_mapped_element_buffer(draw, 0, 0, NULL);
+
+   if (ib) {
+      draw_set_mapped_index_buffer(draw, NULL);
+      draw_set_index_buffer(draw, NULL);
+
+      if (ib_transfer)
+         pipe_buffer_unmap(pipe, ibuffer.buffer, ib_transfer);
+      pipe_resource_reference(&ibuffer.buffer, NULL);
    }
 }
 
index 90e78679e472c20101d6df14014cceab1f46db77..6cd74db897b34ad1c82804a2d9429ee2ecfd1a19 100644 (file)
@@ -161,6 +161,13 @@ void st_init_limits(struct st_context *st)
    pc->MaxNativeTemps           = screen->get_param(screen, PIPE_CAP_MAX_VS_TEMPS);
    pc->MaxNativeAddressRegs     = screen->get_param(screen, PIPE_CAP_MAX_VS_ADDRS);
    pc->MaxNativeParameters      = screen->get_param(screen, PIPE_CAP_MAX_VS_CONSTS);
+
+   /* PIPE_CAP_MAX_FS_INPUTS specifies the number of COLORn + GENERICn inputs
+    * and is set in MaxNativeAttribs. It's always 2 colors + N generic
+    * attributes. The GLSL compiler never uses COLORn for varyings, so we
+    * subtract the 2 colors to get the maximum number of varyings (generic
+    * attributes) supported by a driver. */
+   c->MaxVarying = screen->get_param(screen, PIPE_CAP_MAX_FS_INPUTS) - 2;
 }
 
 
index c9fa7a62e19131ce820c1bf8db840f20b047ea84..1ed79524b2cc688c8de8a1d8f851d66782916b4a 100644 (file)
@@ -35,7 +35,6 @@
 #include "main/imports.h"
 #include "main/context.h"
 #include "main/texstore.h"
-#include "main/enums.h"
 #include "main/image.h"
 #include "main/macros.h"
 
@@ -78,7 +77,9 @@ st_format_datatype(enum pipe_format format)
          return GL_UNSIGNED_SHORT;
       }
       else if (format == PIPE_FORMAT_Z24_UNORM_S8_USCALED ||
-               format == PIPE_FORMAT_S8_USCALED_Z24_UNORM) {
+               format == PIPE_FORMAT_S8_USCALED_Z24_UNORM ||
+               format == PIPE_FORMAT_Z24X8_UNORM ||
+               format == PIPE_FORMAT_X8Z24_UNORM) {
          return GL_UNSIGNED_INT_24_8;
       }
       else {
index 2afc682e0b142167a2a505ba84f9826345a40e69..ccce574c36460da69e94aaa7804efee5424bf609 100644 (file)
@@ -42,6 +42,7 @@
 #include "main/texstate.h"
 #include "main/texfetch.h"
 #include "main/framebuffer.h"
+#include "main/fbobject.h"
 #include "main/renderbuffer.h"
 #include "st_texture.h"
 
@@ -247,6 +248,9 @@ st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb,
    int samples;
    boolean sw;
 
+   if (!stfb->iface)
+      return FALSE;
+
    /* do not distinguish depth/stencil buffers */
    if (idx == BUFFER_STENCIL)
       idx = BUFFER_DEPTH;
@@ -299,6 +303,10 @@ st_visual_to_context_mode(const struct st_visual *visual,
 {
    memset(mode, 0, sizeof(*mode));
 
+   /* FBO-only context */
+   if (!visual)
+      return;
+
    if (st_visual_have_buffers(visual, ST_ATTACHMENT_BACK_LEFT_MASK))
       mode->doubleBufferMode = GL_TRUE;
    if (st_visual_have_buffers(visual,
@@ -422,6 +430,15 @@ st_framebuffer_create(struct st_framebuffer_iface *stfbi)
    if (!stfb)
       return NULL;
 
+   /* for FBO-only context */
+   if (!stfbi) {
+      GLframebuffer *base = _mesa_get_incomplete_framebuffer();
+
+      stfb->Base = *base;
+
+      return stfb;
+   }
+
    st_visual_to_context_mode(stfbi->visual, &mode);
    _mesa_initialize_window_framebuffer(&stfb->Base, &mode);
 
@@ -693,10 +710,14 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
             st_framebuffer_validate(stread, st);
 
          /* modify the draw/read buffers of the context */
-         st_visual_to_default_buffer(stdraw->iface->visual,
-               &st->ctx->Color.DrawBuffer[0], NULL);
-         st_visual_to_default_buffer(stread->iface->visual,
-               &st->ctx->Pixel.ReadBuffer, NULL);
+         if (stdraw->iface) {
+            st_visual_to_default_buffer(stdraw->iface->visual,
+                  &st->ctx->Color.DrawBuffer[0], NULL);
+         }
+         if (stread->iface) {
+            st_visual_to_default_buffer(stread->iface->visual,
+                  &st->ctx->Pixel.ReadBuffer, NULL);
+         }
 
          ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base);
       }
@@ -748,6 +769,8 @@ st_manager_flush_frontbuffer(struct st_context *st)
    if (!strb)
       return;
 
+   /* never a dummy fb */
+   assert(stfb->iface);
    stfb->iface->flush_front(stfb->iface, ST_ATTACHMENT_FRONT_LEFT);
 }
 
index a19dcc92534a0be9932fcfd58764a1e8c09a3f8d..0ed822b8c27a46c0195a3b4124642c2110915895 100644 (file)
  */
 
 #include "pipe/p_compiler.h"
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
 #include "pipe/p_shader_tokens.h"
 #include "pipe/p_state.h"
-#include "pipe/p_context.h"
 #include "tgsi/tgsi_ureg.h"
 #include "st_mesa_to_tgsi.h"
 #include "st_context.h"
index 91528c227b23974ac850b76eaee1c4b058bbcbb8..8c2d8b6154bbef7f5f68f9e0ce2e1a57933fa141 100644 (file)
@@ -207,6 +207,9 @@ st_translate_vertex_program(struct st_context *st,
    enum pipe_error error;
    unsigned num_outputs;
 
+   _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT);
+   _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_VARYING);
+
    ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
    if (ureg == NULL) {
       FREE(vpv);
@@ -298,6 +301,8 @@ st_translate_fragment_program(struct st_context *st,
    ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
    uint fs_num_outputs = 0;
 
+   _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT);
+
    /*
     * Convert Mesa program inputs to TGSI input register semantics.
     */
@@ -485,6 +490,9 @@ st_translate_geometry_program(struct st_context *st,
    GLuint maxSlot = 0;
    struct ureg_program *ureg;
 
+   _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT);
+   _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING);
+
    ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY );
    if (ureg == NULL) {
       return;
index add6e949dfb68facd7e3c90f8fd1c8ffd9c5d1eb..c6cf2ba061b4cceb11d159b1834e033e3e7fa457 100644 (file)
@@ -64,7 +64,7 @@ st_texture_create(struct st_context *st,
    struct pipe_resource pt, *newtex;
    struct pipe_screen *screen = st->pipe->screen;
 
-   assert(target <= PIPE_TEXTURE_CUBE);
+   assert(target < PIPE_MAX_TEXTURE_TYPES);
    assert(width0 > 0);
    assert(height0 > 0);
    assert(depth0 > 0);
index d8d8a80b7d7b59668c8cb7b9f88aaf53c5af9cec..f76a2b68ecdf33b0a361b22617b9d467326e7034 100644 (file)
@@ -950,7 +950,7 @@ _swrast_print_vertex( GLcontext *ctx, const SWvertex *v )
                   v->attrib[FRAG_ATTRIB_COL1][2],
                   v->attrib[FRAG_ATTRIB_COL1][3]);
       _mesa_debug(ctx, "fog %f\n", v->attrib[FRAG_ATTRIB_FOGC][0]);
-      _mesa_debug(ctx, "index %d\n", v->attrib[FRAG_ATTRIB_CI][0]);
+      _mesa_debug(ctx, "index %f\n", v->attrib[FRAG_ATTRIB_CI][0]);
       _mesa_debug(ctx, "pointsize %f\n", v->pointSize);
       _mesa_debug(ctx, "\n");
    }
index c32a5044438f902cbbd325e555227375385abbb8..1759e578870de0921cbc87f550f8d8f73647d340 100644 (file)
@@ -785,7 +785,7 @@ vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
                        start, end, count, type, indices,
                        ctx->Array.ArrayObj->_MaxElement - 1,
                        ctx->Array.ElementArrayBufferObj->Name,
-                       ctx->Array.ElementArrayBufferObj->Size);
+                       (int) ctx->Array.ElementArrayBufferObj->Size);
       }
 
       if (0)
@@ -811,7 +811,7 @@ vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
                              start, end, count, type, indices, max,
                              ctx->Array.ArrayObj->_MaxElement - 1,
                              ctx->Array.ElementArrayBufferObj->Name,
-                             ctx->Array.ElementArrayBufferObj->Size);
+                             (int) ctx->Array.ElementArrayBufferObj->Size);
             }
          }
          /* XXX we could also find the min index and compare to 'start'
index df9f2638d76d684f31c61c009515ed4f9d1bb795..1c1fedcd4f3006c45cfc802bafb5d4187930b338 100644 (file)
@@ -31,8 +31,6 @@
 #ifndef __3DNOW_H__
 #define __3DNOW_H__
 
-#include "math/m_xform.h"
-
 void _mesa_init_3dnow_transform_asm( void );
 
 #endif
index 5efdb4f24a6a82064444d66b04d6c71c88296df2..f763a3aa8a4bc3c2ea7fb3fcdcb7d56de1c2989c 100644 (file)
@@ -55,7 +55,7 @@
 /** Bitmask of X86_FEATURE_x bits */
 int _mesa_x86_cpu_features = 0x0;
 
-
+static int detection_debug = GL_FALSE;
 
 /* No reason for this to be public.
  */
@@ -190,7 +190,8 @@ void _mesa_check_os_sse_support( void )
 #else
    /* Do nothing on other platforms for now.
     */
-   _mesa_debug(NULL, "Not testing OS support for SSE, leaving enabled.\n");
+   if (detection_debug)
+      _mesa_debug(NULL, "Not testing OS support for SSE, leaving enabled.\n");
 #endif /* __FreeBSD__ */
 }
 
@@ -232,7 +233,8 @@ _mesa_get_x86_features(void)
        _mesa_x86_cpuid(0, &result, (GLuint *)(cpu_vendor + 0), (GLuint *)(cpu_vendor + 8), (GLuint *)(cpu_vendor + 4));
        cpu_vendor[12] = '\0';
 
-       _mesa_debug(NULL, "CPU vendor: %s\n", cpu_vendor);
+       if (detection_debug)
+         _mesa_debug(NULL, "CPU vendor: %s\n", cpu_vendor);
 
        /* get cpu features */
        cpu_features = _mesa_x86_cpuid_edx(1);
@@ -284,10 +286,49 @@ _mesa_get_x86_features(void)
                   _mesa_x86_cpuid(0x80000002+ofs, (GLuint *)(cpu_name + (16*ofs)+0), (GLuint *)(cpu_name + (16*ofs)+4), (GLuint *)(cpu_name + (16*ofs)+8), (GLuint *)(cpu_name + (16*ofs)+12));
               cpu_name[48] = '\0'; /* the name should be NULL terminated, but just to be sure */
 
-              _mesa_debug(NULL, "CPU name: %s\n", cpu_name);
+              if (detection_debug)
+                 _mesa_debug(NULL, "CPU name: %s\n", cpu_name);
           }
        }
 
    }
+
+#ifdef USE_MMX_ASM
+   if ( cpu_has_mmx ) {
+      if ( _mesa_getenv( "MESA_NO_MMX" ) == 0 ) {
+        if (detection_debug)
+           _mesa_debug(NULL, "MMX cpu detected.\n");
+      } else {
+         _mesa_x86_cpu_features &= ~(X86_FEATURE_MMX);
+      }
+   }
+#endif
+
+#ifdef USE_3DNOW_ASM
+   if ( cpu_has_3dnow ) {
+      if ( _mesa_getenv( "MESA_NO_3DNOW" ) == 0 ) {
+        if (detection_debug)
+           _mesa_debug(NULL, "3DNow! cpu detected.\n");
+      } else {
+         _mesa_x86_cpu_features &= ~(X86_FEATURE_3DNOW);
+      }
+   }
+#endif
+
+#ifdef USE_SSE_ASM
+   if ( cpu_has_xmm ) {
+      if ( _mesa_getenv( "MESA_NO_SSE" ) == 0 ) {
+        if (detection_debug)
+           _mesa_debug(NULL, "SSE cpu detected.\n");
+         if ( _mesa_getenv( "MESA_FORCE_SSE" ) == 0 ) {
+            _mesa_check_os_sse_support();
+         }
+      } else {
+         _mesa_debug(NULL, "SSE cpu detected, but switched off by user.\n");
+         _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
+      }
+   }
+#endif
+
 #endif /* USE_X86_ASM */
 }
index 5641936bdb049ca3f6591bba0d41acd8ba745c79..47a0d4b54dd633fa2bcd18f900e8190ee5b9f536 100644 (file)
@@ -26,6 +26,9 @@
 #ifndef ASM_MMX_H
 #define ASM_MMX_H
 
+#include "main/compiler.h"
+#include "main/mtypes.h"
+
 extern void _ASMAPI
 _mesa_mmx_blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
                               GLvoid *rgba, const GLvoid *dest,
index 521f91e41179b1c2bb6a3436039b65d30bbda854..e92ddc1394103bf2334d5bc9453f46fe6f8880d6 100644 (file)
@@ -31,8 +31,6 @@
 #ifndef __SSE_H__
 #define __SSE_H__
 
-#include "math/m_xform.h"
-
 void _mesa_init_sse_transform_asm( void );
 
 #endif
index c834e2b468b8b26b4e7c86b5e00978f8de01cdea..3dcc55e16b6898f173f7fd5af32630687f70a0a0 100644 (file)
@@ -114,42 +114,13 @@ void _mesa_init_all_x86_transform_asm( void )
       _mesa_init_x86_transform_asm();
    }
 
-#ifdef USE_MMX_ASM
-   if ( cpu_has_mmx ) {
-      if ( _mesa_getenv( "MESA_NO_MMX" ) == 0 ) {
-         _mesa_debug(NULL, "MMX cpu detected.\n");
-      } else {
-         _mesa_x86_cpu_features &= ~(X86_FEATURE_MMX);
-      }
+   if (cpu_has_3dnow) {
+      _mesa_init_3dnow_transform_asm();
    }
-#endif
-
-#ifdef USE_3DNOW_ASM
-   if ( cpu_has_3dnow ) {
-      if ( _mesa_getenv( "MESA_NO_3DNOW" ) == 0 ) {
-         _mesa_debug(NULL, "3DNow! cpu detected.\n");
-         _mesa_init_3dnow_transform_asm();
-      } else {
-         _mesa_x86_cpu_features &= ~(X86_FEATURE_3DNOW);
-      }
-   }
-#endif
 
-#ifdef USE_SSE_ASM
    if ( cpu_has_xmm ) {
-      if ( _mesa_getenv( "MESA_NO_SSE" ) == 0 ) {
-         _mesa_debug(NULL, "SSE cpu detected.\n");
-         if ( _mesa_getenv( "MESA_FORCE_SSE" ) == 0 ) {
-            _mesa_check_os_sse_support();
-         }
-         if ( cpu_has_xmm ) {
-            _mesa_init_sse_transform_asm();
-         }
-      } else {
-         _mesa_debug(NULL, "SSE cpu detected, but switched off by user.\n");
-         _mesa_x86_cpu_features &= ~(X86_FEATURE_XMM);
-      }
+      _mesa_init_sse_transform_asm();
    }
-#endif
+
 #endif
 }
diff --git a/src/talloc/SConscript b/src/talloc/SConscript
new file mode 100644 (file)
index 0000000..3bf7029
--- /dev/null
@@ -0,0 +1,20 @@
+Import('*')
+
+if env['platform'] != 'windows':
+    Return()
+
+env = env.Clone()
+
+talloc = env.SharedLibrary(
+    target = 'talloc',
+    source = ['talloc.c', 'talloc.def'],
+)
+
+env.InstallSharedLibrary(talloc)
+
+if env['platform'] == 'windows':
+    talloc = env.FindIxes(talloc, 'LIBPREFIX', 'LIBSUFFIX')
+else:
+    talloc = env.FindIxes(talloc, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+
+Export('talloc')
diff --git a/src/talloc/gpl-3.0.txt b/src/talloc/gpl-3.0.txt
new file mode 100644 (file)
index 0000000..94a9ed0
--- /dev/null
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/src/talloc/lgpl-3.0.txt b/src/talloc/lgpl-3.0.txt
new file mode 100644 (file)
index 0000000..65c5ca8
--- /dev/null
@@ -0,0 +1,165 @@
+                   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/src/talloc/talloc.c b/src/talloc/talloc.c
new file mode 100644 (file)
index 0000000..cc01346
--- /dev/null
@@ -0,0 +1,2034 @@
+/* 
+   Samba Unix SMB/CIFS implementation.
+
+   Samba trivial allocation library - new interface
+
+   NOTE: Please read talloc_guide.txt for full documentation
+
+   Copyright (C) Andrew Tridgell 2004
+   Copyright (C) Stefan Metzmacher 2006
+   
+     ** NOTE! The following LGPL license applies to the talloc
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 3 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+  inspired by http://swapped.cc/halloc/
+*/
+
+#include "talloc.h"
+#include <string.h>
+
+#define TALLOC_MIN(a,b) ((a)<(b)?(a):(b))
+
+/* Visual C++ 2008 compatibility */
+#if defined(_MSC_VER) && !defined(_cplusplus)
+typedef size_t ssize_t;
+#define inline __inline
+#endif
+
+/* Xcode/gcc4.0 compatibility */
+#if defined(__APPLE__) || defined(__MINGW32__)
+static size_t strnlen (const char* s, size_t n)
+{
+       size_t i;
+       for (i = 0; i < n; ++i)
+       {
+               if (s[i] == '\0')
+                       break;
+       }
+       return i;
+}
+#endif
+
+/* Visual C++ 2008 & Xcode/gcc4.0 compatibility */
+#if !defined(_cplusplus) && (defined(WIN32) || defined(__APPLE__))
+typedef int bool;
+#define false 0
+#define true 1
+#endif
+
+
+#ifdef TALLOC_BUILD_VERSION_MAJOR
+#if (TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR)
+#error "TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR"
+#endif
+#endif
+
+#ifdef TALLOC_BUILD_VERSION_MINOR
+#if (TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR)
+#error "TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR"
+#endif
+#endif
+
+/* use this to force every realloc to change the pointer, to stress test
+   code that might not cope */
+#define ALWAYS_REALLOC 0
+
+
+#define MAX_TALLOC_SIZE 0x10000000
+#define TALLOC_MAGIC_BASE 0xe814ec70
+#define TALLOC_MAGIC ( \
+       TALLOC_MAGIC_BASE + \
+       (TALLOC_VERSION_MAJOR << 12) + \
+       (TALLOC_VERSION_MINOR << 4) \
+)
+
+#define TALLOC_FLAG_FREE 0x01
+#define TALLOC_FLAG_LOOP 0x02
+#define TALLOC_FLAG_POOL 0x04          /* This is a talloc pool */
+#define TALLOC_FLAG_POOLMEM 0x08       /* This is allocated in a pool */
+#define TALLOC_MAGIC_REFERENCE ((const char *)1)
+
+/* by default we abort when given a bad pointer (such as when talloc_free() is called 
+   on a pointer that came from malloc() */
+#ifndef TALLOC_ABORT
+#define TALLOC_ABORT(reason) abort()
+#endif
+
+#ifndef discard_const_p
+#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
+# define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
+#else
+# define discard_const_p(type, ptr) ((type *)(ptr))
+#endif
+#endif
+
+/* these macros gain us a few percent of speed on gcc */
+#if (__GNUC__ >= 3)
+/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
+   as its first argument */
+#ifndef likely
+#define likely(x)   __builtin_expect(!!(x), 1)
+#endif
+#ifndef unlikely
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#endif
+#else
+#ifndef likely
+#define likely(x) (x)
+#endif
+#ifndef unlikely
+#define unlikely(x) (x)
+#endif
+#endif
+
+/* this null_context is only used if talloc_enable_leak_report() or
+   talloc_enable_leak_report_full() is called, otherwise it remains
+   NULL
+*/
+static void *null_context;
+static void *autofree_context;
+
+struct talloc_reference_handle {
+       struct talloc_reference_handle *next, *prev;
+       void *ptr;
+       const char *location;
+};
+
+typedef int (*talloc_destructor_t)(void *);
+
+struct talloc_chunk {
+       struct talloc_chunk *next, *prev;
+       struct talloc_chunk *parent, *child;
+       struct talloc_reference_handle *refs;
+       talloc_destructor_t destructor;
+       const char *name;
+       size_t size;
+       unsigned flags;
+
+       /*
+        * "pool" has dual use:
+        *
+        * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
+        * marks the end of the currently allocated area.
+        *
+        * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
+        * is a pointer to the struct talloc_chunk of the pool that it was
+        * allocated from. This way children can quickly find the pool to chew
+        * from.
+        */
+       void *pool;
+};
+
+/* 16 byte alignment seems to keep everyone happy */
+#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
+#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
+
+int talloc_version_major(void)
+{
+       return TALLOC_VERSION_MAJOR;
+}
+
+int talloc_version_minor(void)
+{
+       return TALLOC_VERSION_MINOR;
+}
+
+static void (*talloc_log_fn)(const char *message);
+
+void talloc_set_log_fn(void (*log_fn)(const char *message))
+{
+       talloc_log_fn = log_fn;
+}
+
+static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
+static void talloc_log(const char *fmt, ...)
+{
+       va_list ap;
+       char *message;
+
+       if (!talloc_log_fn) {
+               return;
+       }
+
+       va_start(ap, fmt);
+       message = talloc_vasprintf(NULL, fmt, ap);
+       va_end(ap);
+
+       talloc_log_fn(message);
+       talloc_free(message);
+}
+
+static void talloc_log_stderr(const char *message)
+{
+       fprintf(stderr, "%s", message);
+}
+
+void talloc_set_log_stderr(void)
+{
+       talloc_set_log_fn(talloc_log_stderr);
+}
+
+static void (*talloc_abort_fn)(const char *reason);
+
+void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
+{
+       talloc_abort_fn = abort_fn;
+}
+
+static void talloc_abort(const char *reason)
+{
+       talloc_log("%s\n", reason);
+
+       if (!talloc_abort_fn) {
+               TALLOC_ABORT(reason);
+       }
+
+       talloc_abort_fn(reason);
+}
+
+static void talloc_abort_magic(unsigned magic)
+{
+       unsigned striped = magic - TALLOC_MAGIC_BASE;
+       unsigned major = (striped & 0xFFFFF000) >> 12;
+       unsigned minor = (striped & 0x00000FF0) >> 4;
+       talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n",
+                  magic, major, minor,
+                  TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR);
+       talloc_abort("Bad talloc magic value - wrong talloc version used/mixed");
+}
+
+static void talloc_abort_double_free(void)
+{
+       talloc_abort("Bad talloc magic value - double free");
+}
+
+static void talloc_abort_unknown_value(void)
+{
+       talloc_abort("Bad talloc magic value - unknown value");
+}
+
+/* panic if we get a bad magic value */
+static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
+{
+       const char *pp = (const char *)ptr;
+       struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
+       if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) { 
+               if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) {
+                       talloc_abort_magic(tc->flags & (~0xF));
+                       return NULL;
+               }
+
+               if (tc->flags & TALLOC_FLAG_FREE) {
+                       talloc_log("talloc: double free error - first free may be at %s\n", tc->name);
+                       talloc_abort_double_free();
+                       return NULL;
+               } else {
+                       talloc_abort_unknown_value();
+                       return NULL;
+               }
+       }
+       return tc;
+}
+
+/* hook into the front of the list */
+#define _TLIST_ADD(list, p) \
+do { \
+        if (!(list)) { \
+               (list) = (p); \
+               (p)->next = (p)->prev = NULL; \
+       } else { \
+               (list)->prev = (p); \
+               (p)->next = (list); \
+               (p)->prev = NULL; \
+               (list) = (p); \
+       }\
+} while (0)
+
+/* remove an element from a list - element doesn't have to be in list. */
+#define _TLIST_REMOVE(list, p) \
+do { \
+       if ((p) == (list)) { \
+               (list) = (p)->next; \
+               if (list) (list)->prev = NULL; \
+       } else { \
+               if ((p)->prev) (p)->prev->next = (p)->next; \
+               if ((p)->next) (p)->next->prev = (p)->prev; \
+       } \
+       if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
+} while (0)
+
+
+/*
+  return the parent chunk of a pointer
+*/
+static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
+{
+       struct talloc_chunk *tc;
+
+       if (unlikely(ptr == NULL)) {
+               return NULL;
+       }
+
+       tc = talloc_chunk_from_ptr(ptr);
+       while (tc->prev) tc=tc->prev;
+
+       return tc->parent;
+}
+
+void *talloc_parent(const void *ptr)
+{
+       struct talloc_chunk *tc = talloc_parent_chunk(ptr);
+       return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
+}
+
+/*
+  find parents name
+*/
+const char *talloc_parent_name(const void *ptr)
+{
+       struct talloc_chunk *tc = talloc_parent_chunk(ptr);
+       return tc? tc->name : NULL;
+}
+
+/*
+  A pool carries an in-pool object count count in the first 16 bytes.
+  bytes. This is done to support talloc_steal() to a parent outside of the
+  pool. The count includes the pool itself, so a talloc_free() on a pool will
+  only destroy the pool if the count has dropped to zero. A talloc_free() of a
+  pool member will reduce the count, and eventually also call free(3) on the
+  pool memory.
+
+  The object count is not put into "struct talloc_chunk" because it is only
+  relevant for talloc pools and the alignment to 16 bytes would increase the
+  memory footprint of each talloc chunk by those 16 bytes.
+*/
+
+#define TALLOC_POOL_HDR_SIZE 16
+
+static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc)
+{
+       return (unsigned int *)((char *)tc + sizeof(struct talloc_chunk));
+}
+
+/*
+  Allocate from a pool
+*/
+
+static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
+                                             size_t size)
+{
+       struct talloc_chunk *pool_ctx = NULL;
+       size_t space_left;
+       struct talloc_chunk *result;
+       size_t chunk_size;
+
+       if (parent == NULL) {
+               return NULL;
+       }
+
+       if (parent->flags & TALLOC_FLAG_POOL) {
+               pool_ctx = parent;
+       }
+       else if (parent->flags & TALLOC_FLAG_POOLMEM) {
+               pool_ctx = (struct talloc_chunk *)parent->pool;
+       }
+
+       if (pool_ctx == NULL) {
+               return NULL;
+       }
+
+       space_left = ((char *)pool_ctx + TC_HDR_SIZE + pool_ctx->size)
+               - ((char *)pool_ctx->pool);
+
+       /*
+        * Align size to 16 bytes
+        */
+       chunk_size = ((size + 15) & ~15);
+
+       if (space_left < chunk_size) {
+               return NULL;
+       }
+
+       result = (struct talloc_chunk *)pool_ctx->pool;
+
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
+       VALGRIND_MAKE_MEM_UNDEFINED(result, size);
+#endif
+
+       pool_ctx->pool = (void *)((char *)result + chunk_size);
+
+       result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
+       result->pool = pool_ctx;
+
+       *talloc_pool_objectcount(pool_ctx) += 1;
+
+       return result;
+}
+
+/* 
+   Allocate a bit of memory as a child of an existing pointer
+*/
+static inline void *__talloc(const void *context, size_t size)
+{
+       struct talloc_chunk *tc = NULL;
+
+       if (unlikely(context == NULL)) {
+               context = null_context;
+       }
+
+       if (unlikely(size >= MAX_TALLOC_SIZE)) {
+               return NULL;
+       }
+
+       if (context != NULL) {
+               tc = talloc_alloc_pool(talloc_chunk_from_ptr(context),
+                                      TC_HDR_SIZE+size);
+       }
+
+       if (tc == NULL) {
+               tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
+               if (unlikely(tc == NULL)) return NULL;
+               tc->flags = TALLOC_MAGIC;
+               tc->pool  = NULL;
+       }
+
+       tc->size = size;
+       tc->destructor = NULL;
+       tc->child = NULL;
+       tc->name = NULL;
+       tc->refs = NULL;
+
+       if (likely(context)) {
+               struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
+
+               if (parent->child) {
+                       parent->child->parent = NULL;
+                       tc->next = parent->child;
+                       tc->next->prev = tc;
+               } else {
+                       tc->next = NULL;
+               }
+               tc->parent = parent;
+               tc->prev = NULL;
+               parent->child = tc;
+       } else {
+               tc->next = tc->prev = tc->parent = NULL;
+       }
+
+       return TC_PTR_FROM_CHUNK(tc);
+}
+
+/*
+ * Create a talloc pool
+ */
+
+void *talloc_pool(const void *context, size_t size)
+{
+       void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE);
+       struct talloc_chunk *tc;
+
+       if (unlikely(result == NULL)) {
+               return NULL;
+       }
+
+       tc = talloc_chunk_from_ptr(result);
+
+       tc->flags |= TALLOC_FLAG_POOL;
+       tc->pool = (char *)result + TALLOC_POOL_HDR_SIZE;
+
+       *talloc_pool_objectcount(tc) = 1;
+
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
+       VALGRIND_MAKE_MEM_NOACCESS(tc->pool, size);
+#endif
+
+       return result;
+}
+
+/*
+  setup a destructor to be called on free of a pointer
+  the destructor should return 0 on success, or -1 on failure.
+  if the destructor fails then the free is failed, and the memory can
+  be continued to be used
+*/
+void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
+{
+       struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+       tc->destructor = destructor;
+}
+
+/*
+  increase the reference count on a piece of memory. 
+*/
+int talloc_increase_ref_count(const void *ptr)
+{
+       if (unlikely(!talloc_reference(null_context, ptr))) {
+               return -1;
+       }
+       return 0;
+}
+
+/*
+  helper for talloc_reference()
+
+  this is referenced by a function pointer and should not be inline
+*/
+static int talloc_reference_destructor(struct talloc_reference_handle *handle)
+{
+       struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
+       _TLIST_REMOVE(ptr_tc->refs, handle);
+       return 0;
+}
+
+/*
+   more efficient way to add a name to a pointer - the name must point to a 
+   true string constant
+*/
+static inline void _talloc_set_name_const(const void *ptr, const char *name)
+{
+       struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+       tc->name = name;
+}
+
+/*
+  internal talloc_named_const()
+*/
+static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
+{
+       void *ptr;
+
+       ptr = __talloc(context, size);
+       if (unlikely(ptr == NULL)) {
+               return NULL;
+       }
+
+       _talloc_set_name_const(ptr, name);
+
+       return ptr;
+}
+
+/*
+  make a secondary reference to a pointer, hanging off the given context.
+  the pointer remains valid until both the original caller and this given
+  context are freed.
+  
+  the major use for this is when two different structures need to reference the 
+  same underlying data, and you want to be able to free the two instances separately,
+  and in either order
+*/
+void *_talloc_reference_loc(const void *context, const void *ptr, const char *location)
+{
+       struct talloc_chunk *tc;
+       struct talloc_reference_handle *handle;
+       if (unlikely(ptr == NULL)) return NULL;
+
+       tc = talloc_chunk_from_ptr(ptr);
+       handle = (struct talloc_reference_handle *)_talloc_named_const(context,
+                                                  sizeof(struct talloc_reference_handle),
+                                                  TALLOC_MAGIC_REFERENCE);
+       if (unlikely(handle == NULL)) return NULL;
+
+       /* note that we hang the destructor off the handle, not the
+          main context as that allows the caller to still setup their
+          own destructor on the context if they want to */
+       talloc_set_destructor(handle, talloc_reference_destructor);
+       handle->ptr = discard_const_p(void, ptr);
+       handle->location = location;
+       _TLIST_ADD(tc->refs, handle);
+       return handle->ptr;
+}
+
+static void *_talloc_steal_internal(const void *new_ctx, const void *ptr);
+
+/* 
+   internal talloc_free call
+*/
+static inline int _talloc_free_internal(void *ptr, const char *location)
+{
+       struct talloc_chunk *tc;
+
+       if (unlikely(ptr == NULL)) {
+               return -1;
+       }
+
+       tc = talloc_chunk_from_ptr(ptr);
+
+       if (unlikely(tc->refs)) {
+               int is_child;
+               /* check this is a reference from a child or grantchild
+                * back to it's parent or grantparent
+                *
+                * in that case we need to remove the reference and
+                * call another instance of talloc_free() on the current
+                * pointer.
+                */
+               is_child = talloc_is_parent(tc->refs, ptr);
+               _talloc_free_internal(tc->refs, location);
+               if (is_child) {
+                       return _talloc_free_internal(ptr, location);
+               }
+               return -1;
+       }
+
+       if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
+               /* we have a free loop - stop looping */
+               return 0;
+       }
+
+       if (unlikely(tc->destructor)) {
+               talloc_destructor_t d = tc->destructor;
+               if (d == (talloc_destructor_t)-1) {
+                       return -1;
+               }
+               tc->destructor = (talloc_destructor_t)-1;
+               if (d(ptr) == -1) {
+                       tc->destructor = d;
+                       return -1;
+               }
+               tc->destructor = NULL;
+       }
+
+       if (tc->parent) {
+               _TLIST_REMOVE(tc->parent->child, tc);
+               if (tc->parent->child) {
+                       tc->parent->child->parent = tc->parent;
+               }
+       } else {
+               if (tc->prev) tc->prev->next = tc->next;
+               if (tc->next) tc->next->prev = tc->prev;
+       }
+
+       tc->flags |= TALLOC_FLAG_LOOP;
+
+       while (tc->child) {
+               /* we need to work out who will own an abandoned child
+                  if it cannot be freed. In priority order, the first
+                  choice is owner of any remaining reference to this
+                  pointer, the second choice is our parent, and the
+                  final choice is the null context. */
+               void *child = TC_PTR_FROM_CHUNK(tc->child);
+               const void *new_parent = null_context;
+               if (unlikely(tc->child->refs)) {
+                       struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
+                       if (p) new_parent = TC_PTR_FROM_CHUNK(p);
+               }
+               if (unlikely(_talloc_free_internal(child, location) == -1)) {
+                       if (new_parent == null_context) {
+                               struct talloc_chunk *p = talloc_parent_chunk(ptr);
+                               if (p) new_parent = TC_PTR_FROM_CHUNK(p);
+                       }
+                       _talloc_steal_internal(new_parent, child);
+               }
+       }
+
+       tc->flags |= TALLOC_FLAG_FREE;
+
+       /* we mark the freed memory with where we called the free
+        * from. This means on a double free error we can report where
+        * the first free came from 
+        */      
+       tc->name = location;
+
+       if (tc->flags & (TALLOC_FLAG_POOL|TALLOC_FLAG_POOLMEM)) {
+               struct talloc_chunk *pool;
+               unsigned int *pool_object_count;
+
+               pool = (tc->flags & TALLOC_FLAG_POOL)
+                       ? tc : (struct talloc_chunk *)tc->pool;
+
+               pool_object_count = talloc_pool_objectcount(pool);
+
+               if (*pool_object_count == 0) {
+                       talloc_abort("Pool object count zero!");
+                       return 0;
+               }
+
+               *pool_object_count -= 1;
+
+               if (*pool_object_count == 0) {
+                       free(pool);
+               }
+       }
+       else {
+               free(tc);
+       }
+       return 0;
+}
+
+/* 
+   move a lump of memory from one talloc context to another return the
+   ptr on success, or NULL if it could not be transferred.
+   passing NULL as ptr will always return NULL with no side effects.
+*/
+static void *_talloc_steal_internal(const void *new_ctx, const void *ptr)
+{
+       struct talloc_chunk *tc, *new_tc;
+
+       if (unlikely(!ptr)) {
+               return NULL;
+       }
+
+       if (unlikely(new_ctx == NULL)) {
+               new_ctx = null_context;
+       }
+
+       tc = talloc_chunk_from_ptr(ptr);
+
+       if (unlikely(new_ctx == NULL)) {
+               if (tc->parent) {
+                       _TLIST_REMOVE(tc->parent->child, tc);
+                       if (tc->parent->child) {
+                               tc->parent->child->parent = tc->parent;
+                       }
+               } else {
+                       if (tc->prev) tc->prev->next = tc->next;
+                       if (tc->next) tc->next->prev = tc->prev;
+               }
+               
+               tc->parent = tc->next = tc->prev = NULL;
+               return discard_const_p(void, ptr);
+       }
+
+       new_tc = talloc_chunk_from_ptr(new_ctx);
+
+       if (unlikely(tc == new_tc || tc->parent == new_tc)) {
+               return discard_const_p(void, ptr);
+       }
+
+       if (tc->parent) {
+               _TLIST_REMOVE(tc->parent->child, tc);
+               if (tc->parent->child) {
+                       tc->parent->child->parent = tc->parent;
+               }
+       } else {
+               if (tc->prev) tc->prev->next = tc->next;
+               if (tc->next) tc->next->prev = tc->prev;
+       }
+
+       tc->parent = new_tc;
+       if (new_tc->child) new_tc->child->parent = NULL;
+       _TLIST_ADD(new_tc->child, tc);
+
+       return discard_const_p(void, ptr);
+}
+
+/* 
+   move a lump of memory from one talloc context to another return the
+   ptr on success, or NULL if it could not be transferred.
+   passing NULL as ptr will always return NULL with no side effects.
+*/
+void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location)
+{
+       struct talloc_chunk *tc;
+
+       if (unlikely(ptr == NULL)) {
+               return NULL;
+       }
+       
+       tc = talloc_chunk_from_ptr(ptr);
+       
+       if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) {
+               struct talloc_reference_handle *h;
+
+               talloc_log("WARNING: talloc_steal with references at %s\n",
+                          location);
+
+               for (h=tc->refs; h; h=h->next) {
+                       talloc_log("\treference at %s\n",
+                                  h->location);
+               }
+       }
+       
+       return _talloc_steal_internal(new_ctx, ptr);
+}
+
+/* 
+   this is like a talloc_steal(), but you must supply the old
+   parent. This resolves the ambiguity in a talloc_steal() which is
+   called on a context that has more than one parent (via references)
+
+   The old parent can be either a reference or a parent
+*/
+void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr)
+{
+       struct talloc_chunk *tc;
+       struct talloc_reference_handle *h;
+
+       if (unlikely(ptr == NULL)) {
+               return NULL;
+       }
+
+       if (old_parent == talloc_parent(ptr)) {
+               return _talloc_steal_internal(new_parent, ptr);
+       }
+
+       tc = talloc_chunk_from_ptr(ptr);
+       for (h=tc->refs;h;h=h->next) {
+               if (talloc_parent(h) == old_parent) {
+                       if (_talloc_steal_internal(new_parent, h) != h) {
+                               return NULL;
+                       }
+                       return discard_const_p(void, ptr);
+               }
+       }       
+
+       /* it wasn't a parent */
+       return NULL;
+}
+
+/*
+  remove a secondary reference to a pointer. This undo's what
+  talloc_reference() has done. The context and pointer arguments
+  must match those given to a talloc_reference()
+*/
+static inline int talloc_unreference(const void *context, const void *ptr)
+{
+       struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+       struct talloc_reference_handle *h;
+
+       if (unlikely(context == NULL)) {
+               context = null_context;
+       }
+
+       for (h=tc->refs;h;h=h->next) {
+               struct talloc_chunk *p = talloc_parent_chunk(h);
+               if (p == NULL) {
+                       if (context == NULL) break;
+               } else if (TC_PTR_FROM_CHUNK(p) == context) {
+                       break;
+               }
+       }
+       if (h == NULL) {
+               return -1;
+       }
+
+       return _talloc_free_internal(h, __location__);
+}
+
+/*
+  remove a specific parent context from a pointer. This is a more
+  controlled varient of talloc_free()
+*/
+int talloc_unlink(const void *context, void *ptr)
+{
+       struct talloc_chunk *tc_p, *new_p;
+       void *new_parent;
+
+       if (ptr == NULL) {
+               return -1;
+       }
+
+       if (context == NULL) {
+               context = null_context;
+       }
+
+       if (talloc_unreference(context, ptr) == 0) {
+               return 0;
+       }
+
+       if (context == NULL) {
+               if (talloc_parent_chunk(ptr) != NULL) {
+                       return -1;
+               }
+       } else {
+               if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
+                       return -1;
+               }
+       }
+       
+       tc_p = talloc_chunk_from_ptr(ptr);
+
+       if (tc_p->refs == NULL) {
+               return _talloc_free_internal(ptr, __location__);
+       }
+
+       new_p = talloc_parent_chunk(tc_p->refs);
+       if (new_p) {
+               new_parent = TC_PTR_FROM_CHUNK(new_p);
+       } else {
+               new_parent = NULL;
+       }
+
+       if (talloc_unreference(new_parent, ptr) != 0) {
+               return -1;
+       }
+
+       _talloc_steal_internal(new_parent, ptr);
+
+       return 0;
+}
+
+/*
+  add a name to an existing pointer - va_list version
+*/
+static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+
+static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
+{
+       struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+       tc->name = talloc_vasprintf(ptr, fmt, ap);
+       if (likely(tc->name)) {
+               _talloc_set_name_const(tc->name, ".name");
+       }
+       return tc->name;
+}
+
+/*
+  add a name to an existing pointer
+*/
+const char *talloc_set_name(const void *ptr, const char *fmt, ...)
+{
+       const char *name;
+       va_list ap;
+       va_start(ap, fmt);
+       name = talloc_set_name_v(ptr, fmt, ap);
+       va_end(ap);
+       return name;
+}
+
+
+/*
+  create a named talloc pointer. Any talloc pointer can be named, and
+  talloc_named() operates just like talloc() except that it allows you
+  to name the pointer.
+*/
+void *talloc_named(const void *context, size_t size, const char *fmt, ...)
+{
+       va_list ap;
+       void *ptr;
+       const char *name;
+
+       ptr = __talloc(context, size);
+       if (unlikely(ptr == NULL)) return NULL;
+
+       va_start(ap, fmt);
+       name = talloc_set_name_v(ptr, fmt, ap);
+       va_end(ap);
+
+       if (unlikely(name == NULL)) {
+               _talloc_free_internal(ptr, __location__);
+               return NULL;
+       }
+
+       return ptr;
+}
+
+/*
+  return the name of a talloc ptr, or "UNNAMED"
+*/
+const char *talloc_get_name(const void *ptr)
+{
+       struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+       if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
+               return ".reference";
+       }
+       if (likely(tc->name)) {
+               return tc->name;
+       }
+       return "UNNAMED";
+}
+
+
+/*
+  check if a pointer has the given name. If it does, return the pointer,
+  otherwise return NULL
+*/
+void *talloc_check_name(const void *ptr, const char *name)
+{
+       const char *pname;
+       if (unlikely(ptr == NULL)) return NULL;
+       pname = talloc_get_name(ptr);
+       if (likely(pname == name || strcmp(pname, name) == 0)) {
+               return discard_const_p(void, ptr);
+       }
+       return NULL;
+}
+
+static void talloc_abort_type_missmatch(const char *location,
+                                       const char *name,
+                                       const char *expected)
+{
+       const char *reason;
+
+       reason = talloc_asprintf(NULL,
+                                "%s: Type mismatch: name[%s] expected[%s]",
+                                location,
+                                name?name:"NULL",
+                                expected);
+       if (!reason) {
+               reason = "Type mismatch";
+       }
+
+       talloc_abort(reason);
+}
+
+void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
+{
+       const char *pname;
+
+       if (unlikely(ptr == NULL)) {
+               talloc_abort_type_missmatch(location, NULL, name);
+               return NULL;
+       }
+
+       pname = talloc_get_name(ptr);
+       if (likely(pname == name || strcmp(pname, name) == 0)) {
+               return discard_const_p(void, ptr);
+       }
+
+       talloc_abort_type_missmatch(location, pname, name);
+       return NULL;
+}
+
+/*
+  this is for compatibility with older versions of talloc
+*/
+void *talloc_init(const char *fmt, ...)
+{
+       va_list ap;
+       void *ptr;
+       const char *name;
+
+       /*
+        * samba3 expects talloc_report_depth_cb(NULL, ...)
+        * reports all talloc'ed memory, so we need to enable
+        * null_tracking
+        */
+       talloc_enable_null_tracking();
+
+       ptr = __talloc(NULL, 0);
+       if (unlikely(ptr == NULL)) return NULL;
+
+       va_start(ap, fmt);
+       name = talloc_set_name_v(ptr, fmt, ap);
+       va_end(ap);
+
+       if (unlikely(name == NULL)) {
+               _talloc_free_internal(ptr, __location__);
+               return NULL;
+       }
+
+       return ptr;
+}
+
+/*
+  this is a replacement for the Samba3 talloc_destroy_pool functionality. It
+  should probably not be used in new code. It's in here to keep the talloc
+  code consistent across Samba 3 and 4.
+*/
+void talloc_free_children(void *ptr)
+{
+       struct talloc_chunk *tc;
+
+       if (unlikely(ptr == NULL)) {
+               return;
+       }
+
+       tc = talloc_chunk_from_ptr(ptr);
+
+       while (tc->child) {
+               /* we need to work out who will own an abandoned child
+                  if it cannot be freed. In priority order, the first
+                  choice is owner of any remaining reference to this
+                  pointer, the second choice is our parent, and the
+                  final choice is the null context. */
+               void *child = TC_PTR_FROM_CHUNK(tc->child);
+               const void *new_parent = null_context;
+               if (unlikely(tc->child->refs)) {
+                       struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
+                       if (p) new_parent = TC_PTR_FROM_CHUNK(p);
+               }
+               if (unlikely(talloc_free(child) == -1)) {
+                       if (new_parent == null_context) {
+                               struct talloc_chunk *p = talloc_parent_chunk(ptr);
+                               if (p) new_parent = TC_PTR_FROM_CHUNK(p);
+                       }
+                       _talloc_steal_internal(new_parent, child);
+               }
+       }
+
+       if ((tc->flags & TALLOC_FLAG_POOL)
+           && (*talloc_pool_objectcount(tc) == 1)) {
+               tc->pool = ((char *)tc + TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE);
+#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
+               VALGRIND_MAKE_MEM_NOACCESS(
+                       tc->pool, tc->size - TALLOC_POOL_HDR_SIZE);
+#endif
+       }
+}
+
+/* 
+   Allocate a bit of memory as a child of an existing pointer
+*/
+void *_talloc(const void *context, size_t size)
+{
+       return __talloc(context, size);
+}
+
+/*
+  externally callable talloc_set_name_const()
+*/
+void talloc_set_name_const(const void *ptr, const char *name)
+{
+       _talloc_set_name_const(ptr, name);
+}
+
+/*
+  create a named talloc pointer. Any talloc pointer can be named, and
+  talloc_named() operates just like talloc() except that it allows you
+  to name the pointer.
+*/
+void *talloc_named_const(const void *context, size_t size, const char *name)
+{
+       return _talloc_named_const(context, size, name);
+}
+
+/* 
+   free a talloc pointer. This also frees all child pointers of this 
+   pointer recursively
+
+   return 0 if the memory is actually freed, otherwise -1. The memory
+   will not be freed if the ref_count is > 1 or the destructor (if
+   any) returns non-zero
+*/
+int _talloc_free(void *ptr, const char *location)
+{
+       struct talloc_chunk *tc;
+
+       if (unlikely(ptr == NULL)) {
+               return -1;
+       }
+       
+       tc = talloc_chunk_from_ptr(ptr);
+       
+       if (unlikely(tc->refs != NULL)) {
+               struct talloc_reference_handle *h;
+
+               talloc_log("ERROR: talloc_free with references at %s\n",
+                          location);
+
+               for (h=tc->refs; h; h=h->next) {
+                       talloc_log("\treference at %s\n",
+                                  h->location);
+               }
+               return -1;
+       }
+       
+       return _talloc_free_internal(ptr, location);
+}
+
+
+
+/*
+  A talloc version of realloc. The context argument is only used if
+  ptr is NULL
+*/
+void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
+{
+       struct talloc_chunk *tc;
+       void *new_ptr;
+       bool malloced = false;
+
+       /* size zero is equivalent to free() */
+       if (unlikely(size == 0)) {
+               talloc_unlink(context, ptr);
+               return NULL;
+       }
+
+       if (unlikely(size >= MAX_TALLOC_SIZE)) {
+               return NULL;
+       }
+
+       /* realloc(NULL) is equivalent to malloc() */
+       if (ptr == NULL) {
+               return _talloc_named_const(context, size, name);
+       }
+
+       tc = talloc_chunk_from_ptr(ptr);
+
+       /* don't allow realloc on referenced pointers */
+       if (unlikely(tc->refs)) {
+               return NULL;
+       }
+
+       /* don't let anybody try to realloc a talloc_pool */
+       if (unlikely(tc->flags & TALLOC_FLAG_POOL)) {
+               return NULL;
+       }
+
+       /* don't shrink if we have less than 1k to gain */
+       if ((size < tc->size) && ((tc->size - size) < 1024)) {
+               tc->size = size;
+               return ptr;
+       }
+
+       /* by resetting magic we catch users of the old memory */
+       tc->flags |= TALLOC_FLAG_FREE;
+
+#if ALWAYS_REALLOC
+       new_ptr = malloc(size + TC_HDR_SIZE);
+       if (new_ptr) {
+               memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
+               free(tc);
+       }
+#else
+       if (tc->flags & TALLOC_FLAG_POOLMEM) {
+
+               new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
+               *talloc_pool_objectcount((struct talloc_chunk *)
+                                        (tc->pool)) -= 1;
+
+               if (new_ptr == NULL) {
+                       new_ptr = malloc(TC_HDR_SIZE+size);
+                       malloced = true;
+               }
+
+               if (new_ptr) {
+                       memcpy(new_ptr, tc, TALLOC_MIN(tc->size,size) + TC_HDR_SIZE);
+               }
+       }
+       else {
+               new_ptr = realloc(tc, size + TC_HDR_SIZE);
+       }
+#endif
+       if (unlikely(!new_ptr)) {       
+               tc->flags &= ~TALLOC_FLAG_FREE; 
+               return NULL; 
+       }
+
+       tc = (struct talloc_chunk *)new_ptr;
+       tc->flags &= ~TALLOC_FLAG_FREE;
+       if (malloced) {
+               tc->flags &= ~TALLOC_FLAG_POOLMEM;
+       }
+       if (tc->parent) {
+               tc->parent->child = tc;
+       }
+       if (tc->child) {
+               tc->child->parent = tc;
+       }
+
+       if (tc->prev) {
+               tc->prev->next = tc;
+       }
+       if (tc->next) {
+               tc->next->prev = tc;
+       }
+
+       tc->size = size;
+       _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
+
+       return TC_PTR_FROM_CHUNK(tc);
+}
+
+/*
+  a wrapper around talloc_steal() for situations where you are moving a pointer
+  between two structures, and want the old pointer to be set to NULL
+*/
+void *_talloc_move(const void *new_ctx, const void *_pptr)
+{
+       const void **pptr = discard_const_p(const void *,_pptr);
+       void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr));
+       (*pptr) = NULL;
+       return ret;
+}
+
+/*
+  return the total size of a talloc pool (subtree)
+*/
+size_t talloc_total_size(const void *ptr)
+{
+       size_t total = 0;
+       struct talloc_chunk *c, *tc;
+
+       if (ptr == NULL) {
+               ptr = null_context;
+       }
+       if (ptr == NULL) {
+               return 0;
+       }
+
+       tc = talloc_chunk_from_ptr(ptr);
+
+       if (tc->flags & TALLOC_FLAG_LOOP) {
+               return 0;
+       }
+
+       tc->flags |= TALLOC_FLAG_LOOP;
+
+       if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
+               total = tc->size;
+       }
+       for (c=tc->child;c;c=c->next) {
+               total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
+       }
+
+       tc->flags &= ~TALLOC_FLAG_LOOP;
+
+       return total;
+}
+
+/*
+  return the total number of blocks in a talloc pool (subtree)
+*/
+size_t talloc_total_blocks(const void *ptr)
+{
+       size_t total = 0;
+       struct talloc_chunk *c, *tc;
+
+       if (ptr == NULL) {
+               ptr = null_context;
+       }
+       if (ptr == NULL) {
+               return 0;
+       }
+
+       tc = talloc_chunk_from_ptr(ptr);
+
+       if (tc->flags & TALLOC_FLAG_LOOP) {
+               return 0;
+       }
+
+       tc->flags |= TALLOC_FLAG_LOOP;
+
+       total++;
+       for (c=tc->child;c;c=c->next) {
+               total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
+       }
+
+       tc->flags &= ~TALLOC_FLAG_LOOP;
+
+       return total;
+}
+
+/*
+  return the number of external references to a pointer
+*/
+size_t talloc_reference_count(const void *ptr)
+{
+       struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+       struct talloc_reference_handle *h;
+       size_t ret = 0;
+
+       for (h=tc->refs;h;h=h->next) {
+               ret++;
+       }
+       return ret;
+}
+
+/*
+  report on memory usage by all children of a pointer, giving a full tree view
+*/
+void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
+                           void (*callback)(const void *ptr,
+                                            int depth, int max_depth,
+                                            int is_ref,
+                                            void *private_data),
+                           void *private_data)
+{
+       struct talloc_chunk *c, *tc;
+
+       if (ptr == NULL) {
+               ptr = null_context;
+       }
+       if (ptr == NULL) return;
+
+       tc = talloc_chunk_from_ptr(ptr);
+
+       if (tc->flags & TALLOC_FLAG_LOOP) {
+               return;
+       }
+
+       callback(ptr, depth, max_depth, 0, private_data);
+
+       if (max_depth >= 0 && depth >= max_depth) {
+               return;
+       }
+
+       tc->flags |= TALLOC_FLAG_LOOP;
+       for (c=tc->child;c;c=c->next) {
+               if (c->name == TALLOC_MAGIC_REFERENCE) {
+                       struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
+                       callback(h->ptr, depth + 1, max_depth, 1, private_data);
+               } else {
+                       talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
+               }
+       }
+       tc->flags &= ~TALLOC_FLAG_LOOP;
+}
+
+static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
+{
+       const char *name = talloc_get_name(ptr);
+       FILE *f = (FILE *)_f;
+
+       if (is_ref) {
+               fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
+               return;
+       }
+
+       if (depth == 0) {
+               fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", 
+                       (max_depth < 0 ? "full " :""), name,
+                       (unsigned long)talloc_total_size(ptr),
+                       (unsigned long)talloc_total_blocks(ptr));
+               return;
+       }
+
+       fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n", 
+               depth*4, "",
+               name,
+               (unsigned long)talloc_total_size(ptr),
+               (unsigned long)talloc_total_blocks(ptr),
+               (int)talloc_reference_count(ptr), ptr);
+
+#if 0
+       fprintf(f, "content: ");
+       if (talloc_total_size(ptr)) {
+               int tot = talloc_total_size(ptr);
+               int i;
+
+               for (i = 0; i < tot; i++) {
+                       if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
+                               fprintf(f, "%c", ((char *)ptr)[i]);
+                       } else {
+                               fprintf(f, "~%02x", ((char *)ptr)[i]);
+                       }
+               }
+       }
+       fprintf(f, "\n");
+#endif
+}
+
+/*
+  report on memory usage by all children of a pointer, giving a full tree view
+*/
+void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
+{
+       if (f) {
+               talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
+               fflush(f);
+       }
+}
+
+/*
+  report on memory usage by all children of a pointer, giving a full tree view
+*/
+void talloc_report_full(const void *ptr, FILE *f)
+{
+       talloc_report_depth_file(ptr, 0, -1, f);
+}
+
+/*
+  report on memory usage by all children of a pointer
+*/
+void talloc_report(const void *ptr, FILE *f)
+{
+       talloc_report_depth_file(ptr, 0, 1, f);
+}
+
+/*
+  report on any memory hanging off the null context
+*/
+static void talloc_report_null(void)
+{
+       if (talloc_total_size(null_context) != 0) {
+               talloc_report(null_context, stderr);
+       }
+}
+
+/*
+  report on any memory hanging off the null context
+*/
+static void talloc_report_null_full(void)
+{
+       if (talloc_total_size(null_context) != 0) {
+               talloc_report_full(null_context, stderr);
+       }
+}
+
+/*
+  enable tracking of the NULL context
+*/
+void talloc_enable_null_tracking(void)
+{
+       if (null_context == NULL) {
+               null_context = _talloc_named_const(NULL, 0, "null_context");
+               if (autofree_context != NULL) {
+                       talloc_reparent(NULL, null_context, autofree_context);
+               }
+       }
+}
+
+/*
+  enable tracking of the NULL context, not moving the autofree context
+  into the NULL context. This is needed for the talloc testsuite
+*/
+void talloc_enable_null_tracking_no_autofree(void)
+{
+       if (null_context == NULL) {
+               null_context = _talloc_named_const(NULL, 0, "null_context");
+       }
+}
+
+/*
+  disable tracking of the NULL context
+*/
+void talloc_disable_null_tracking(void)
+{
+       if (null_context != NULL) {
+               /* we have to move any children onto the real NULL
+                  context */
+               struct talloc_chunk *tc, *tc2;
+               tc = talloc_chunk_from_ptr(null_context);
+               for (tc2 = tc->child; tc2; tc2=tc2->next) {
+                       if (tc2->parent == tc) tc2->parent = NULL;
+                       if (tc2->prev == tc) tc2->prev = NULL;
+               }
+               for (tc2 = tc->next; tc2; tc2=tc2->next) {
+                       if (tc2->parent == tc) tc2->parent = NULL;
+                       if (tc2->prev == tc) tc2->prev = NULL;
+               }
+               tc->child = NULL;
+               tc->next = NULL;
+       }
+       talloc_free(null_context);
+       null_context = NULL;
+}
+
+/*
+  enable leak reporting on exit
+*/
+void talloc_enable_leak_report(void)
+{
+       talloc_enable_null_tracking();
+       atexit(talloc_report_null);
+}
+
+/*
+  enable full leak reporting on exit
+*/
+void talloc_enable_leak_report_full(void)
+{
+       talloc_enable_null_tracking();
+       atexit(talloc_report_null_full);
+}
+
+/* 
+   talloc and zero memory. 
+*/
+void *_talloc_zero(const void *ctx, size_t size, const char *name)
+{
+       void *p = _talloc_named_const(ctx, size, name);
+
+       if (p) {
+               memset(p, '\0', size);
+       }
+
+       return p;
+}
+
+/*
+  memdup with a talloc. 
+*/
+void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
+{
+       void *newp = _talloc_named_const(t, size, name);
+
+       if (likely(newp)) {
+               memcpy(newp, p, size);
+       }
+
+       return newp;
+}
+
+static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
+{
+       char *ret;
+
+       ret = (char *)__talloc(t, len + 1);
+       if (unlikely(!ret)) return NULL;
+
+       memcpy(ret, p, len);
+       ret[len] = 0;
+
+       _talloc_set_name_const(ret, ret);
+       return ret;
+}
+
+/*
+  strdup with a talloc
+*/
+char *talloc_strdup(const void *t, const char *p)
+{
+       if (unlikely(!p)) return NULL;
+       return __talloc_strlendup(t, p, strlen(p));
+}
+
+/*
+  strndup with a talloc
+*/
+char *talloc_strndup(const void *t, const char *p, size_t n)
+{
+       if (unlikely(!p)) return NULL;
+       return __talloc_strlendup(t, p, strnlen(p, n));
+}
+
+static inline char *__talloc_strlendup_append(char *s, size_t slen,
+                                             const char *a, size_t alen)
+{
+       char *ret;
+
+       ret = talloc_realloc(NULL, s, char, slen + alen + 1);
+       if (unlikely(!ret)) return NULL;
+
+       /* append the string and the trailing \0 */
+       memcpy(&ret[slen], a, alen);
+       ret[slen+alen] = 0;
+
+       _talloc_set_name_const(ret, ret);
+       return ret;
+}
+
+/*
+ * Appends at the end of the string.
+ */
+char *talloc_strdup_append(char *s, const char *a)
+{
+       if (unlikely(!s)) {
+               return talloc_strdup(NULL, a);
+       }
+
+       if (unlikely(!a)) {
+               return s;
+       }
+
+       return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
+}
+
+/*
+ * Appends at the end of the talloc'ed buffer,
+ * not the end of the string.
+ */
+char *talloc_strdup_append_buffer(char *s, const char *a)
+{
+       size_t slen;
+
+       if (unlikely(!s)) {
+               return talloc_strdup(NULL, a);
+       }
+
+       if (unlikely(!a)) {
+               return s;
+       }
+
+       slen = talloc_get_size(s);
+       if (likely(slen > 0)) {
+               slen--;
+       }
+
+       return __talloc_strlendup_append(s, slen, a, strlen(a));
+}
+
+/*
+ * Appends at the end of the string.
+ */
+char *talloc_strndup_append(char *s, const char *a, size_t n)
+{
+       if (unlikely(!s)) {
+               return talloc_strdup(NULL, a);
+       }
+
+       if (unlikely(!a)) {
+               return s;
+       }
+
+       return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
+}
+
+/*
+ * Appends at the end of the talloc'ed buffer,
+ * not the end of the string.
+ */
+char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
+{
+       size_t slen;
+
+       if (unlikely(!s)) {
+               return talloc_strdup(NULL, a);
+       }
+
+       if (unlikely(!a)) {
+               return s;
+       }
+
+       slen = talloc_get_size(s);
+       if (likely(slen > 0)) {
+               slen--;
+       }
+
+       return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
+}
+
+#ifndef va_copy
+#ifdef HAVE___VA_COPY
+#define va_copy(dest, src) __va_copy(dest, src)
+#else
+#define va_copy(dest, src) (dest) = (src)
+#endif
+#endif
+
+char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
+{
+       int len;
+       char *ret;
+       va_list ap2;
+       char c;
+
+       /* this call looks strange, but it makes it work on older solaris boxes */
+       va_copy(ap2, ap);
+       #ifdef _MSC_VER
+       /* MSVC runtime needs to use _vcsprintf to return buffer size; vsnprintf would return -1 */
+       len = _vscprintf(fmt, ap2);
+       #else
+       len = vsnprintf(&c, 1, fmt, ap2);
+       #endif
+       va_end(ap2);
+       if (unlikely(len < 0)) {
+               return NULL;
+       }
+
+       ret = (char *)__talloc(t, len+1);
+       if (unlikely(!ret)) return NULL;
+
+       va_copy(ap2, ap);
+       vsnprintf(ret, len+1, fmt, ap2);
+       va_end(ap2);
+
+       _talloc_set_name_const(ret, ret);
+       return ret;
+}
+
+
+/*
+  Perform string formatting, and return a pointer to newly allocated
+  memory holding the result, inside a memory pool.
+ */
+char *talloc_asprintf(const void *t, const char *fmt, ...)
+{
+       va_list ap;
+       char *ret;
+
+       va_start(ap, fmt);
+       ret = talloc_vasprintf(t, fmt, ap);
+       va_end(ap);
+       return ret;
+}
+
+static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
+                                                const char *fmt, va_list ap)
+                                                PRINTF_ATTRIBUTE(3,0);
+
+static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
+                                                const char *fmt, va_list ap)
+{
+       ssize_t alen;
+       va_list ap2;
+       char c;
+
+       va_copy(ap2, ap);
+       #ifdef _MSC_VER
+       /* MSVC runtime needs to use _vcsprintf to return buffer size; vsnprintf would return -1 */
+       alen = _vscprintf(fmt, ap2);
+       #else
+       alen = vsnprintf(&c, 1, fmt, ap2);
+       #endif
+       va_end(ap2);
+
+       if (alen <= 0) {
+               /* Either the vsnprintf failed or the format resulted in
+                * no characters being formatted. In the former case, we
+                * ought to return NULL, in the latter we ought to return
+                * the original string. Most current callers of this
+                * function expect it to never return NULL.
+                */
+               return s;
+       }
+
+       s = talloc_realloc(NULL, s, char, slen + alen + 1);
+       if (!s) return NULL;
+
+       va_copy(ap2, ap);
+       vsnprintf(s + slen, alen + 1, fmt, ap2);
+       va_end(ap2);
+
+       _talloc_set_name_const(s, s);
+       return s;
+}
+
+/**
+ * Realloc @p s to append the formatted result of @p fmt and @p ap,
+ * and return @p s, which may have moved.  Good for gradually
+ * accumulating output into a string buffer. Appends at the end
+ * of the string.
+ **/
+char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
+{
+       if (unlikely(!s)) {
+               return talloc_vasprintf(NULL, fmt, ap);
+       }
+
+       return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
+}
+
+/**
+ * Realloc @p s to append the formatted result of @p fmt and @p ap,
+ * and return @p s, which may have moved. Always appends at the
+ * end of the talloc'ed buffer, not the end of the string.
+ **/
+char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
+{
+       size_t slen;
+
+       if (unlikely(!s)) {
+               return talloc_vasprintf(NULL, fmt, ap);
+       }
+
+       slen = talloc_get_size(s);
+       if (likely(slen > 0)) {
+               slen--;
+       }
+
+       return __talloc_vaslenprintf_append(s, slen, fmt, ap);
+}
+
+/*
+  Realloc @p s to append the formatted result of @p fmt and return @p
+  s, which may have moved.  Good for gradually accumulating output
+  into a string buffer.
+ */
+char *talloc_asprintf_append(char *s, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       s = talloc_vasprintf_append(s, fmt, ap);
+       va_end(ap);
+       return s;
+}
+
+/*
+  Realloc @p s to append the formatted result of @p fmt and return @p
+  s, which may have moved.  Good for gradually accumulating output
+  into a buffer.
+ */
+char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       s = talloc_vasprintf_append_buffer(s, fmt, ap);
+       va_end(ap);
+       return s;
+}
+
+/*
+  alloc an array, checking for integer overflow in the array size
+*/
+void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
+{
+       if (count >= MAX_TALLOC_SIZE/el_size) {
+               return NULL;
+       }
+       return _talloc_named_const(ctx, el_size * count, name);
+}
+
+/*
+  alloc an zero array, checking for integer overflow in the array size
+*/
+void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
+{
+       if (count >= MAX_TALLOC_SIZE/el_size) {
+               return NULL;
+       }
+       return _talloc_zero(ctx, el_size * count, name);
+}
+
+/*
+  realloc an array, checking for integer overflow in the array size
+*/
+void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
+{
+       if (count >= MAX_TALLOC_SIZE/el_size) {
+               return NULL;
+       }
+       return _talloc_realloc(ctx, ptr, el_size * count, name);
+}
+
+/*
+  a function version of talloc_realloc(), so it can be passed as a function pointer
+  to libraries that want a realloc function (a realloc function encapsulates
+  all the basic capabilities of an allocation library, which is why this is useful)
+*/
+void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
+{
+       return _talloc_realloc(context, ptr, size, NULL);
+}
+
+
+static int talloc_autofree_destructor(void *ptr)
+{
+       autofree_context = NULL;
+       return 0;
+}
+
+static void talloc_autofree(void)
+{
+       talloc_free(autofree_context);
+}
+
+/*
+  return a context which will be auto-freed on exit
+  this is useful for reducing the noise in leak reports
+*/
+void *talloc_autofree_context(void)
+{
+       if (autofree_context == NULL) {
+               autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
+               talloc_set_destructor(autofree_context, talloc_autofree_destructor);
+               atexit(talloc_autofree);
+       }
+       return autofree_context;
+}
+
+size_t talloc_get_size(const void *context)
+{
+       struct talloc_chunk *tc;
+
+       if (context == NULL) {
+               context = null_context;
+       }
+       if (context == NULL) {
+               return 0;
+       }
+
+       tc = talloc_chunk_from_ptr(context);
+
+       return tc->size;
+}
+
+/*
+  find a parent of this context that has the given name, if any
+*/
+void *talloc_find_parent_byname(const void *context, const char *name)
+{
+       struct talloc_chunk *tc;
+
+       if (context == NULL) {
+               return NULL;
+       }
+
+       tc = talloc_chunk_from_ptr(context);
+       while (tc) {
+               if (tc->name && strcmp(tc->name, name) == 0) {
+                       return TC_PTR_FROM_CHUNK(tc);
+               }
+               while (tc && tc->prev) tc = tc->prev;
+               if (tc) {
+                       tc = tc->parent;
+               }
+       }
+       return NULL;
+}
+
+/*
+  show the parentage of a context
+*/
+void talloc_show_parents(const void *context, FILE *file)
+{
+       struct talloc_chunk *tc;
+
+       if (context == NULL) {
+               fprintf(file, "talloc no parents for NULL\n");
+               return;
+       }
+
+       tc = talloc_chunk_from_ptr(context);
+       fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
+       while (tc) {
+               fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
+               while (tc && tc->prev) tc = tc->prev;
+               if (tc) {
+                       tc = tc->parent;
+               }
+       }
+       fflush(file);
+}
+
+/*
+  return 1 if ptr is a parent of context
+*/
+int talloc_is_parent(const void *context, const void *ptr)
+{
+       struct talloc_chunk *tc;
+
+       if (context == NULL) {
+               return 0;
+       }
+
+       tc = talloc_chunk_from_ptr(context);
+       while (tc) {
+               if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
+               while (tc && tc->prev) tc = tc->prev;
+               if (tc) {
+                       tc = tc->parent;
+               }
+       }
+       return 0;
+}
diff --git a/src/talloc/talloc.def b/src/talloc/talloc.def
new file mode 100644 (file)
index 0000000..13d7a15
--- /dev/null
@@ -0,0 +1,63 @@
+EXPORTS
+       _talloc
+       _talloc_array
+       _talloc_free
+       _talloc_get_type_abort
+       _talloc_memdup
+       _talloc_move
+       _talloc_realloc
+       _talloc_realloc_array
+       _talloc_reference_loc
+       _talloc_set_destructor
+       _talloc_steal_loc
+       _talloc_zero
+       _talloc_zero_array
+       talloc_asprintf
+       talloc_asprintf_append
+       talloc_asprintf_append_buffer
+       talloc_autofree_context
+       talloc_check_name
+       talloc_disable_null_tracking
+       talloc_enable_leak_report
+       talloc_enable_leak_report_full
+       talloc_enable_null_tracking
+       talloc_enable_null_tracking_no_autofree
+       talloc_find_parent_byname
+       talloc_free_children
+       talloc_get_name
+       talloc_get_size
+       talloc_increase_ref_count
+       talloc_init
+       talloc_is_parent
+       talloc_named
+       talloc_named_const
+       talloc_parent
+       talloc_parent_name
+       talloc_pool
+       talloc_realloc_fn
+       talloc_reference_count
+       talloc_reparent
+       talloc_report
+       talloc_report_depth_cb
+       talloc_report_depth_file
+       talloc_report_full
+       talloc_set_abort_fn
+       talloc_set_log_fn
+       talloc_set_log_stderr
+       talloc_set_name
+       talloc_set_name_const
+       talloc_show_parents
+       talloc_strdup
+       talloc_strdup_append
+       talloc_strdup_append_buffer
+       talloc_strndup
+       talloc_strndup_append
+       talloc_strndup_append_buffer
+       talloc_total_blocks
+       talloc_total_size
+       talloc_unlink
+       talloc_vasprintf
+       talloc_vasprintf_append
+       talloc_vasprintf_append_buffer
+       talloc_version_major
+       talloc_version_minor
diff --git a/src/talloc/talloc.h b/src/talloc/talloc.h
new file mode 100644 (file)
index 0000000..f549a17
--- /dev/null
@@ -0,0 +1,202 @@
+#ifndef _TALLOC_H_
+#define _TALLOC_H_
+/* 
+   Unix SMB/CIFS implementation.
+   Samba temporary memory allocation functions
+
+   Copyright (C) Andrew Tridgell 2004-2005
+   Copyright (C) Stefan Metzmacher 2006
+   
+     ** NOTE! The following LGPL license applies to the talloc
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 3 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#define TALLOC_VERSION_MAJOR 2
+#define TALLOC_VERSION_MINOR 0
+
+int talloc_version_major(void);
+int talloc_version_minor(void);
+
+/* this is only needed for compatibility with the old talloc */
+typedef void TALLOC_CTX;
+
+/*
+  this uses a little trick to allow __LINE__ to be stringified
+*/
+#ifndef __location__
+#define __TALLOC_STRING_LINE1__(s)    #s
+#define __TALLOC_STRING_LINE2__(s)   __TALLOC_STRING_LINE1__(s)
+#define __TALLOC_STRING_LINE3__  __TALLOC_STRING_LINE2__(__LINE__)
+#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__
+#endif
+
+#ifndef TALLOC_DEPRECATED
+#define TALLOC_DEPRECATED 0
+#endif
+
+#ifndef PRINTF_ATTRIBUTE
+#if (__GNUC__ >= 3)
+/** Use gcc attribute to check printf fns.  a1 is the 1-based index of
+ * the parameter containing the format, and a2 the index of the first
+ * argument. Note that some gcc 2.x versions don't handle this
+ * properly **/
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#else
+#define PRINTF_ATTRIBUTE(a1, a2)
+#endif
+#endif
+
+/* try to make talloc_set_destructor() and talloc_steal() type safe,
+   if we have a recent gcc */
+#if (__GNUC__ >= 3)
+#define _TALLOC_TYPEOF(ptr) __typeof__(ptr)
+#define talloc_set_destructor(ptr, function)                                 \
+       do {                                                                  \
+               int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function);       \
+               _talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \
+       } while(0)
+/* this extremely strange macro is to avoid some braindamaged warning
+   stupidity in gcc 4.1.x */
+#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__); __talloc_steal_ret; })
+#else
+#define talloc_set_destructor(ptr, function) \
+       _talloc_set_destructor((ptr), (int (*)(void *))(function))
+#define _TALLOC_TYPEOF(ptr) void *
+#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__)
+#endif
+
+#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference_loc((ctx),(ptr), __location__)
+#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr))
+
+/* useful macros for creating type checked pointers */
+#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type)
+#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__)
+#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr)))
+
+#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__)
+
+#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type)
+#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__)
+
+#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type)
+#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type)
+#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__)
+#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count)
+#define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx))
+
+#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type)
+#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__)
+
+#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__)
+
+#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type)
+#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type)
+#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__)
+
+#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type)
+#define talloc_free(ctx) _talloc_free(ctx, __location__)
+
+
+#if TALLOC_DEPRECATED
+#define talloc_zero_p(ctx, type) talloc_zero(ctx, type)
+#define talloc_p(ctx, type) talloc(ctx, type)
+#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count)
+#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count)
+#define talloc_destroy(ctx) talloc_free(ctx)
+#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a))
+#endif
+
+#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
+
+/* The following definitions come from talloc.c  */
+void *_talloc(const void *context, size_t size);
+void *talloc_pool(const void *context, size_t size);
+void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *));
+int talloc_increase_ref_count(const void *ptr);
+size_t talloc_reference_count(const void *ptr);
+void *_talloc_reference_loc(const void *context, const void *ptr, const char *location);
+int talloc_unlink(const void *context, void *ptr);
+const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+void talloc_set_name_const(const void *ptr, const char *name);
+void *talloc_named(const void *context, size_t size, 
+                  const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
+void *talloc_named_const(const void *context, size_t size, const char *name);
+const char *talloc_get_name(const void *ptr);
+void *talloc_check_name(const void *ptr, const char *name);
+void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location);
+void *talloc_parent(const void *ptr);
+const char *talloc_parent_name(const void *ptr);
+void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
+int _talloc_free(void *ptr, const char *location);
+void talloc_free_children(void *ptr);
+void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name);
+void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location);
+void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr);
+void *_talloc_move(const void *new_ctx, const void *pptr);
+size_t talloc_total_size(const void *ptr);
+size_t talloc_total_blocks(const void *ptr);
+void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
+                           void (*callback)(const void *ptr,
+                                            int depth, int max_depth,
+                                            int is_ref,
+                                            void *private_data),
+                           void *private_data);
+void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f);
+void talloc_report_full(const void *ptr, FILE *f);
+void talloc_report(const void *ptr, FILE *f);
+void talloc_enable_null_tracking(void);
+void talloc_enable_null_tracking_no_autofree(void);
+void talloc_disable_null_tracking(void);
+void talloc_enable_leak_report(void);
+void talloc_enable_leak_report_full(void);
+void *_talloc_zero(const void *ctx, size_t size, const char *name);
+void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name);
+void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name);
+void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name);
+void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name);
+void *talloc_realloc_fn(const void *context, void *ptr, size_t size);
+void *talloc_autofree_context(void);
+size_t talloc_get_size(const void *ctx);
+void *talloc_find_parent_byname(const void *ctx, const char *name);
+void talloc_show_parents(const void *context, FILE *file);
+int talloc_is_parent(const void *context, const void *ptr);
+
+char *talloc_strdup(const void *t, const char *p);
+char *talloc_strdup_append(char *s, const char *a);
+char *talloc_strdup_append_buffer(char *s, const char *a);
+
+char *talloc_strndup(const void *t, const char *p, size_t n);
+char *talloc_strndup_append(char *s, const char *a, size_t n);
+char *talloc_strndup_append_buffer(char *s, const char *a, size_t n);
+
+char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+
+char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+
+void talloc_set_abort_fn(void (*abort_fn)(const char *reason));
+void talloc_set_log_fn(void (*log_fn)(const char *message));
+void talloc_set_log_stderr(void);
+
+#endif
diff --git a/src/talloc/talloc_guide.txt b/src/talloc/talloc_guide.txt
new file mode 100644 (file)
index 0000000..01de806
--- /dev/null
@@ -0,0 +1,757 @@
+Using talloc in Samba4
+======================
+
+.. contents::
+
+Andrew Tridgell
+August 2009
+
+The most current version of this document is available at
+   http://samba.org/ftp/unpacked/talloc/talloc_guide.txt
+
+If you are used to the "old" talloc from Samba3 before 3.0.20 then please read
+this carefully, as talloc has changed a lot. With 3.0.20 (or 3.0.14?) the
+Samba4 talloc has been ported back to Samba3, so this guide applies to both.
+
+The new talloc is a hierarchical, reference counted memory pool system
+with destructors. Quite a mouthful really, but not too bad once you
+get used to it.
+
+Perhaps the biggest change from Samba3 is that there is no distinction
+between a "talloc context" and a "talloc pointer". Any pointer
+returned from talloc() is itself a valid talloc context. This means
+you can do this::
+
+  struct foo *X = talloc(mem_ctx, struct foo);
+  X->name = talloc_strdup(X, "foo");
+
+and the pointer X->name would be a "child" of the talloc context "X"
+which is itself a child of mem_ctx. So if you do talloc_free(mem_ctx)
+then it is all destroyed, whereas if you do talloc_free(X) then just X
+and X->name are destroyed, and if you do talloc_free(X->name) then
+just the name element of X is destroyed.
+
+If you think about this, then what this effectively gives you is an
+n-ary tree, where you can free any part of the tree with
+talloc_free().
+
+If you find this confusing, then I suggest you run the testsuite to
+watch talloc in action. You may also like to add your own tests to
+testsuite.c to clarify how some particular situation is handled.
+
+
+Performance
+-----------
+
+All the additional features of talloc() over malloc() do come at a
+price. We have a simple performance test in Samba4 that measures
+talloc() versus malloc() performance, and it seems that talloc() is
+about 4% slower than malloc() on my x86 Debian Linux box. For Samba,
+the great reduction in code complexity that we get by using talloc
+makes this worthwhile, especially as the total overhead of
+talloc/malloc in Samba is already quite small.
+
+
+talloc API
+----------
+
+The following is a complete guide to the talloc API. Read it all at
+least twice.
+
+Multi-threading
+---------------
+
+talloc itself does not deal with threads. It is thread-safe (assuming  
+the underlying "malloc" is), as long as each thread uses different  
+memory contexts.
+If two threads uses the same context then they need to synchronize in  
+order to be safe. In particular:
+- when using talloc_enable_leak_report(), giving directly NULL as a  
+parent context implicitly refers to a hidden "null context" global  
+variable, so this should not be used in a multi-threaded environment  
+without proper synchronization ;
+- the context returned by talloc_autofree_context() is also global so  
+shouldn't be used by several threads simultaneously without  
+synchronization.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc(const void *context, type);
+
+The talloc() macro is the core of the talloc library. It takes a
+memory context and a type, and returns a pointer to a new area of
+memory of the given type.
+
+The returned pointer is itself a talloc context, so you can use it as
+the context argument to more calls to talloc if you wish.
+
+The returned pointer is a "child" of the supplied context. This means
+that if you talloc_free() the context then the new child disappears as
+well. Alternatively you can free just the child.
+
+The context argument to talloc() can be NULL, in which case a new top
+level context is created. 
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_size(const void *context, size_t size);
+
+The function talloc_size() should be used when you don't have a
+convenient type to pass to talloc(). Unlike talloc(), it is not type
+safe (as it returns a void *), so you are on your own for type checking.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(typeof(ptr)) talloc_ptrtype(const void *ctx, ptr);
+
+The talloc_ptrtype() macro should be used when you have a pointer and
+want to allocate memory to point at with this pointer. When compiling
+with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_size()
+and talloc_get_name() will return the current location in the source file.
+and not the type.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int talloc_free(void *ptr);
+
+The talloc_free() function frees a piece of talloc memory, and all its
+children. You can call talloc_free() on any pointer returned by
+talloc().
+
+The return value of talloc_free() indicates success or failure, with 0
+returned for success and -1 for failure. The only possible failure
+condition is if the pointer had a destructor attached to it and the
+destructor returned -1. See talloc_set_destructor() for details on
+destructors.
+
+If this pointer has an additional parent when talloc_free() is called
+then the memory is not actually released, but instead the most
+recently established parent is destroyed. See talloc_reference() for
+details on establishing additional parents.
+
+For more control on which parent is removed, see talloc_unlink()
+
+talloc_free() operates recursively on its children.
+
+From the 2.0 version of talloc, as a special case, talloc_free() is
+refused on pointers that have more than one parent, as talloc would
+have no way of knowing which parent should be removed. To free a
+pointer that has more than one parent please use talloc_unlink().
+
+To help you find problems in your code caused by this behaviour, if
+you do try and free a pointer with more than one parent then the
+talloc logging function will be called to give output like this:
+
+  ERROR: talloc_free with references at some_dir/source/foo.c:123
+       reference at some_dir/source/other.c:325
+       reference at some_dir/source/third.c:121
+
+Please see the documentation for talloc_set_log_fn() and
+talloc_set_log_stderr() for more information on talloc logging
+functions.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int talloc_free_children(void *ptr);
+
+The talloc_free_children() walks along the list of all children of a
+talloc context and talloc_free()s only the children, not the context
+itself.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_reference(const void *context, const void *ptr);
+
+The talloc_reference() function makes "context" an additional parent
+of "ptr".
+
+The return value of talloc_reference() is always the original pointer
+"ptr", unless talloc ran out of memory in creating the reference in
+which case it will return NULL (each additional reference consumes
+around 48 bytes of memory on intel x86 platforms).
+
+If "ptr" is NULL, then the function is a no-op, and simply returns NULL.
+
+After creating a reference you can free it in one of the following
+ways:
+
+  - you can talloc_free() any parent of the original pointer. That
+    will reduce the number of parents of this pointer by 1, and will
+    cause this pointer to be freed if it runs out of parents.
+
+  - you can talloc_free() the pointer itself. That will destroy the
+    most recently established parent to the pointer and leave the
+    pointer as a child of its current parent.
+
+For more control on which parent to remove, see talloc_unlink()
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int talloc_unlink(const void *context, const void *ptr);
+
+The talloc_unlink() function removes a specific parent from ptr. The
+context passed must either be a context used in talloc_reference()
+with this pointer, or must be a direct parent of ptr. 
+
+Note that if the parent has already been removed using talloc_free()
+then this function will fail and will return -1.  Likewise, if "ptr"
+is NULL, then the function will make no modifications and return -1.
+
+Usually you can just use talloc_free() instead of talloc_unlink(), but
+sometimes it is useful to have the additional control on which parent
+is removed.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_destructor(const void *ptr, int (*destructor)(void *));
+
+The function talloc_set_destructor() sets the "destructor" for the
+pointer "ptr". A destructor is a function that is called when the
+memory used by a pointer is about to be released. The destructor
+receives the pointer as an argument, and should return 0 for success
+and -1 for failure.
+
+The destructor can do anything it wants to, including freeing other
+pieces of memory. A common use for destructors is to clean up
+operating system resources (such as open file descriptors) contained
+in the structure the destructor is placed on.
+
+You can only place one destructor on a pointer. If you need more than
+one destructor then you can create a zero-length child of the pointer
+and place an additional destructor on that.
+
+To remove a destructor call talloc_set_destructor() with NULL for the
+destructor.
+
+If your destructor attempts to talloc_free() the pointer that it is
+the destructor for then talloc_free() will return -1 and the free will
+be ignored. This would be a pointless operation anyway, as the
+destructor is only called when the memory is just about to go away.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+int talloc_increase_ref_count(const void *ptr);
+
+The talloc_increase_ref_count(ptr) function is exactly equivalent to:
+
+  talloc_reference(NULL, ptr);
+
+You can use either syntax, depending on which you think is clearer in
+your code.
+
+It returns 0 on success and -1 on failure.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+size_t talloc_reference_count(const void *ptr);
+
+Return the number of references to the pointer.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_name(const void *ptr, const char *fmt, ...);
+
+Each talloc pointer has a "name". The name is used principally for
+debugging purposes, although it is also possible to set and get the
+name on a pointer in as a way of "marking" pointers in your code.
+
+The main use for names on pointer is for "talloc reports". See
+talloc_report() and talloc_report_full() for details. Also see
+talloc_enable_leak_report() and talloc_enable_leak_report_full().
+
+The talloc_set_name() function allocates memory as a child of the
+pointer. It is logically equivalent to:
+  talloc_set_name_const(ptr, talloc_asprintf(ptr, fmt, ...));
+
+Note that multiple calls to talloc_set_name() will allocate more
+memory without releasing the name. All of the memory is released when
+the ptr is freed using talloc_free().
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_name_const(const void *ptr, const char *name);
+
+The function talloc_set_name_const() is just like talloc_set_name(),
+but it takes a string constant, and is much faster. It is extensively
+used by the "auto naming" macros, such as talloc_p().
+
+This function does not allocate any memory. It just copies the
+supplied pointer into the internal representation of the talloc
+ptr. This means you must not pass a name pointer to memory that will
+disappear before the ptr is freed with talloc_free().
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_named(const void *context, size_t size, const char *fmt, ...);
+
+The talloc_named() function creates a named talloc pointer. It is
+equivalent to:
+
+   ptr = talloc_size(context, size);
+   talloc_set_name(ptr, fmt, ....);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_named_const(const void *context, size_t size, const char *name);
+
+This is equivalent to::
+
+   ptr = talloc_size(context, size);
+   talloc_set_name_const(ptr, name);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+const char *talloc_get_name(const void *ptr);
+
+This returns the current name for the given talloc pointer. See
+talloc_set_name() for details.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_init(const char *fmt, ...);
+
+This function creates a zero length named talloc context as a top
+level context. It is equivalent to::
+
+  talloc_named(NULL, 0, fmt, ...);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_new(void *ctx);
+
+This is a utility macro that creates a new memory context hanging
+off an exiting context, automatically naming it "talloc_new: __location__"
+where __location__ is the source line it is called from. It is
+particularly useful for creating a new temporary working context.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_realloc(const void *context, void *ptr, type, count);
+
+The talloc_realloc() macro changes the size of a talloc
+pointer. The "count" argument is the number of elements of type "type"
+that you want the resulting pointer to hold. 
+
+talloc_realloc() has the following equivalences::
+
+  talloc_realloc(context, NULL, type, 1) ==> talloc(context, type);
+  talloc_realloc(context, NULL, type, N) ==> talloc_array(context, type, N);
+  talloc_realloc(context, ptr, type, 0)  ==> talloc_free(ptr);
+
+The "context" argument is only used if "ptr" is NULL, otherwise it is
+ignored.
+
+talloc_realloc() returns the new pointer, or NULL on failure. The call
+will fail either due to a lack of memory, or because the pointer has
+more than one parent (see talloc_reference()).
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_realloc_size(const void *context, void *ptr, size_t size);
+
+the talloc_realloc_size() function is useful when the type is not 
+known so the typesafe talloc_realloc() cannot be used.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_steal(const void *new_ctx, const void *ptr);
+
+The talloc_steal() function changes the parent context of a talloc
+pointer. It is typically used when the context that the pointer is
+currently a child of is going to be freed and you wish to keep the
+memory for a longer time. 
+
+The talloc_steal() function returns the pointer that you pass it. It
+does not have any failure modes.
+
+NOTE: It is possible to produce loops in the parent/child relationship
+if you are not careful with talloc_steal(). No guarantees are provided
+as to your sanity or the safety of your data if you do this.
+
+talloc_steal (new_ctx, NULL) will return NULL with no sideeffects.
+
+Note that if you try and call talloc_steal() on a pointer that has
+more than one parent then the result is ambiguous. Talloc will choose
+to remove the parent that is currently indicated by talloc_parent()
+and replace it with the chosen parent. You will also get a message
+like this via the talloc logging functions:
+
+  WARNING: talloc_steal with references at some_dir/source/foo.c:123
+       reference at some_dir/source/other.c:325
+       reference at some_dir/source/third.c:121
+
+To unambiguously change the parent of a pointer please see the
+function talloc_reparent(). See the talloc_set_log_fn() documentation
+for more information on talloc logging.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr);
+
+The talloc_reparent() function changes the parent context of a talloc
+pointer. It is typically used when the context that the pointer is
+currently a child of is going to be freed and you wish to keep the
+memory for a longer time.
+
+The talloc_reparent() function returns the pointer that you pass it. It
+does not have any failure modes.
+
+The difference between talloc_reparent() and talloc_steal() is that
+talloc_reparent() can specify which parent you wish to change. This is
+useful when a pointer has multiple parents via references.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_parent(const void *ptr);
+
+The talloc_parent() function returns the current talloc parent. This
+is usually the pointer under which this memory was originally created,
+but it may have changed due to a talloc_steal() or talloc_reparent()
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+size_t talloc_total_size(const void *ptr);
+
+The talloc_total_size() function returns the total size in bytes used
+by this pointer and all child pointers. Mostly useful for debugging.
+
+Passing NULL is allowed, but it will only give a meaningful result if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+size_t talloc_total_blocks(const void *ptr);
+
+The talloc_total_blocks() function returns the total memory block
+count used by this pointer and all child pointers. Mostly useful for
+debugging.
+
+Passing NULL is allowed, but it will only give a meaningful result if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
+                           void (*callback)(const void *ptr,
+                                            int depth, int max_depth,
+                                            int is_ref,
+                                            void *priv),
+                           void *priv);
+
+This provides a more flexible reports than talloc_report(). It
+will recursively call the callback for the entire tree of memory
+referenced by the pointer. References in the tree are passed with
+is_ref = 1 and the pointer that is referenced.
+
+You can pass NULL for the pointer, in which case a report is
+printed for the top level memory context, but only if
+talloc_enable_leak_report() or talloc_enable_leak_report_full()
+has been called.
+
+The recursion is stopped when depth >= max_depth.
+max_depth = -1 means only stop at leaf nodes.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f);
+
+This provides a more flexible reports than talloc_report(). It
+will let you specify the depth and max_depth.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report(const void *ptr, FILE *f);
+
+The talloc_report() function prints a summary report of all memory
+used by ptr. One line of report is printed for each immediate child of
+ptr, showing the total memory and number of blocks used by that child.
+
+You can pass NULL for the pointer, in which case a report is printed
+for the top level memory context, but only if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_report_full(const void *ptr, FILE *f);
+
+This provides a more detailed report than talloc_report(). It will
+recursively print the ensire tree of memory referenced by the
+pointer. References in the tree are shown by giving the name of the
+pointer that is referenced.
+
+You can pass NULL for the pointer, in which case a report is printed
+for the top level memory context, but only if
+talloc_enable_leak_report() or talloc_enable_leak_report_full() has
+been called.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_enable_leak_report(void);
+
+This enables calling of talloc_report(NULL, stderr) when the program
+exits. In Samba4 this is enabled by using the --leak-report command
+line option.
+
+For it to be useful, this function must be called before any other
+talloc function as it establishes a "null context" that acts as the
+top of the tree. If you don't call this function first then passing
+NULL to talloc_report() or talloc_report_full() won't give you the
+full tree printout.
+
+Here is a typical talloc report:
+
+talloc report on 'null_context' (total 267 bytes in 15 blocks)
+        libcli/auth/spnego_parse.c:55  contains     31 bytes in   2 blocks
+        libcli/auth/spnego_parse.c:55  contains     31 bytes in   2 blocks
+        iconv(UTF8,CP850)              contains     42 bytes in   2 blocks
+        libcli/auth/spnego_parse.c:55  contains     31 bytes in   2 blocks
+        iconv(CP850,UTF8)              contains     42 bytes in   2 blocks
+        iconv(UTF8,UTF-16LE)           contains     45 bytes in   2 blocks
+        iconv(UTF-16LE,UTF8)           contains     45 bytes in   2 blocks
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_enable_leak_report_full(void);
+
+This enables calling of talloc_report_full(NULL, stderr) when the
+program exits. In Samba4 this is enabled by using the
+--leak-report-full command line option.
+
+For it to be useful, this function must be called before any other
+talloc function as it establishes a "null context" that acts as the
+top of the tree. If you don't call this function first then passing
+NULL to talloc_report() or talloc_report_full() won't give you the
+full tree printout.
+
+Here is a typical full report:
+
+full talloc report on 'root' (total 18 bytes in 8 blocks)
+    p1                             contains     18 bytes in   7 blocks (ref 0)
+        r1                             contains     13 bytes in   2 blocks (ref 0)
+            reference to: p2
+        p2                             contains      1 bytes in   1 blocks (ref 1)
+        x3                             contains      1 bytes in   1 blocks (ref 0)
+        x2                             contains      1 bytes in   1 blocks (ref 0)
+        x1                             contains      1 bytes in   1 blocks (ref 0)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_enable_null_tracking(void);
+
+This enables tracking of the NULL memory context without enabling leak
+reporting on exit. Useful for when you want to do your own leak
+reporting call via talloc_report_null_full();
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_disable_null_tracking(void);
+
+This disables tracking of the NULL memory context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_zero(const void *ctx, type);
+
+The talloc_zero() macro is equivalent to::
+
+  ptr = talloc(ctx, type);
+  if (ptr) memset(ptr, 0, sizeof(type));
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_zero_size(const void *ctx, size_t size)
+
+The talloc_zero_size() function is useful when you don't have a known type
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_memdup(const void *ctx, const void *p, size_t size);
+
+The talloc_memdup() function is equivalent to::
+
+  ptr = talloc_size(ctx, size);
+  if (ptr) memcpy(ptr, p, size);
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_strdup(const void *ctx, const char *p);
+
+The talloc_strdup() function is equivalent to::
+
+  ptr = talloc_size(ctx, strlen(p)+1);
+  if (ptr) memcpy(ptr, p, strlen(p)+1);
+
+This functions sets the name of the new pointer to the passed
+string. This is equivalent to::
+
+   talloc_set_name_const(ptr, ptr)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_strndup(const void *t, const char *p, size_t n);
+
+The talloc_strndup() function is the talloc equivalent of the C
+library function strndup()
+
+This functions sets the name of the new pointer to the passed
+string. This is equivalent to:
+   talloc_set_name_const(ptr, ptr)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_append_string(const void *t, char *orig, const char *append);
+
+The talloc_append_string() function appends the given formatted
+string to the given string.
+
+This function sets the name of the new pointer to the new
+string. This is equivalent to::
+
+   talloc_set_name_const(ptr, ptr)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_vasprintf(const void *t, const char *fmt, va_list ap);
+
+The talloc_vasprintf() function is the talloc equivalent of the C
+library function vasprintf()
+
+This functions sets the name of the new pointer to the new
+string. This is equivalent to::
+
+   talloc_set_name_const(ptr, ptr)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_asprintf(const void *t, const char *fmt, ...);
+
+The talloc_asprintf() function is the talloc equivalent of the C
+library function asprintf()
+
+This functions sets the name of the new pointer to the new
+string. This is equivalent to::
+
+   talloc_set_name_const(ptr, ptr)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_asprintf_append(char *s, const char *fmt, ...);
+
+The talloc_asprintf_append() function appends the given formatted
+string to the given string.
+Use this varient when the string in the current talloc buffer may
+have been truncated in length.
+
+This functions sets the name of the new pointer to the new
+string. This is equivalent to::
+
+   talloc_set_name_const(ptr, ptr)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...);
+
+The talloc_asprintf_append() function appends the given formatted 
+string to the end of the currently allocated talloc buffer.
+Use this varient when the string in the current talloc buffer has
+not been changed.
+
+This functions sets the name of the new pointer to the new
+string. This is equivalent to::
+
+   talloc_set_name_const(ptr, ptr)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+((type *)talloc_array(const void *ctx, type, uint_t count);
+
+The talloc_array() macro is equivalent to::
+
+  (type *)talloc_size(ctx, sizeof(type) * count);
+
+except that it provides integer overflow protection for the multiply,
+returning NULL if the multiply overflows.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_array_size(const void *ctx, size_t size, uint_t count);
+
+The talloc_array_size() function is useful when the type is not
+known. It operates in the same way as talloc_array(), but takes a size
+instead of a type.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(typeof(ptr)) talloc_array_ptrtype(const void *ctx, ptr, uint_t count);
+
+The talloc_ptrtype() macro should be used when you have a pointer to an array
+and want to allocate memory of an array to point at with this pointer. When compiling
+with gcc >= 3 it is typesafe. Note this is a wrapper of talloc_array_size()
+and talloc_get_name() will return the current location in the source file.
+and not the type.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_realloc_fn(const void *ctx, void *ptr, size_t size);
+
+This is a non-macro version of talloc_realloc(), which is useful 
+as libraries sometimes want a ralloc function pointer. A realloc()
+implementation encapsulates the functionality of malloc(), free() and
+realloc() in one call, which is why it is useful to be able to pass
+around a single function pointer.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_autofree_context(void);
+
+This is a handy utility function that returns a talloc context
+which will be automatically freed on program exit. This can be used
+to reduce the noise in memory leak reports.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_check_name(const void *ptr, const char *name);
+
+This function checks if a pointer has the specified name. If it does
+then the pointer is returned. It it doesn't then NULL is returned.
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_get_type(const void *ptr, type);
+
+This macro allows you to do type checking on talloc pointers. It is
+particularly useful for void* private pointers. It is equivalent to
+this::
+
+   (type *)talloc_check_name(ptr, #type)
+
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+talloc_set_type(const void *ptr, type);
+
+This macro allows you to force the name of a pointer to be a
+particular type. This can be used in conjunction with
+talloc_get_type() to do type checking on void* pointers.
+
+It is equivalent to this::
+
+   talloc_set_name_const(ptr, #type)
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+talloc_get_size(const void *ctx);
+
+This function lets you know the amount of memory alloced so far by
+this context. It does NOT account for subcontext memory.
+This can be used to calculate the size of an array.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void *talloc_find_parent_byname(const void *ctx, const char *name);
+
+Find a parent memory context of the current context that has the given
+name. This can be very useful in complex programs where it may be
+difficult to pass all information down to the level you need, but you
+know the structure you want is a parent of another context.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+(type *)talloc_find_parent_bytype(ctx, type);
+
+Like talloc_find_parent_byname() but takes a type, making it typesafe.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_log_fn(void (*log_fn)(const char *message));
+
+This function sets a logging function that talloc will use for
+warnings and errors. By default talloc will not print any warnings or
+errors.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+void talloc_set_log_stderr(void)
+
+This sets the talloc log function to write log messages to stderr