summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>2010-09-02 18:31:49 +0200
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>2010-09-02 18:31:49 +0200
commit222d2f2ac2c7d93cbc0643082c78278ad2c8cfce (patch)
treeb79152c238022b2a901201c22e5809ac520732bf /src
parent443abc80db9e1a288ce770e76cccd43664348098 (diff)
parente73c5501b2fe20290d1b691c85a5d82ac3a0431c (diff)
Merge remote branch 'origin/master' into nv50-compiler
Conflicts: src/gallium/drivers/nv50/nv50_program.c
Diffstat (limited to 'src')
-rw-r--r--src/SConscript3
-rw-r--r--src/egl/docs/EGL_MESA_screen_surface2
-rw-r--r--src/egl/drivers/dri2/egl_dri2.c223
-rw-r--r--src/egl/main/Makefile6
-rw-r--r--src/egl/main/SConscript4
-rw-r--r--src/egl/main/egl.def35
-rw-r--r--src/egl/main/eglapi.c189
-rw-r--r--src/egl/main/eglapi.h28
-rw-r--r--src/egl/main/eglconfig.c7
-rw-r--r--src/egl/main/eglcontext.c20
-rw-r--r--src/egl/main/egldisplay.h8
-rw-r--r--src/egl/main/egldriver.c9
-rw-r--r--src/egl/main/eglmisc.c4
-rw-r--r--src/egl/main/eglsync.c128
-rw-r--r--src/egl/main/eglsync.h120
-rw-r--r--src/egl/main/egltypedefs.h2
-rw-r--r--src/gallium/auxiliary/Makefile36
-rw-r--r--src/gallium/auxiliary/SConscript37
-rw-r--r--src/gallium/auxiliary/draw/draw_cliptest_tmp.h114
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c113
-rw-r--r--src/gallium/auxiliary/draw/draw_context.h23
-rw-r--r--src/gallium/auxiliary/draw/draw_decompose_tmp.h26
-rw-r--r--src/gallium/auxiliary/draw/draw_gs.c3
-rw-r--r--src/gallium/auxiliary/draw/draw_gs_tmp.h6
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.c74
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.h54
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe.c32
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_validate.c2
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_vbuf.c3
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h44
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c139
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.h51
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_elts.c89
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_emit.c11
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_emit.c29
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c29
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c27
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c35
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_post_vs.c288
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_so_emit.c2
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_util.c7
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_varray.c200
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_varray_tmp.h238
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h103
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vcache.c610
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h19
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vsplit.c208
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h309
-rw-r--r--src/gallium/auxiliary/draw/draw_so_emit_tmp.h6
-rw-r--r--src/gallium/auxiliary/draw/draw_split_tmp.h176
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_llvm.c6
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_arit.c48
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_debug.c2
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_format_aos.c4
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_misc.cpp14
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_pack.h2
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample.c103
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample.h11
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c307
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c8
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_type.h8
-rw-r--r--src/gallium/auxiliary/os/os_stream.c58
-rw-r--r--src/gallium/auxiliary/os/os_stream.h25
-rw-r--r--src/gallium/auxiliary/os/os_stream_log.c3
-rw-r--r--src/gallium/auxiliary/os/os_stream_null.c8
-rw-r--r--src/gallium/auxiliary/os/os_stream_stdc.c9
-rw-r--r--src/gallium/auxiliary/os/os_stream_str.c1
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr.h3
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_cpu.c6
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_x86sse.c499
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_x86sse.h100
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_dump.h1
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.c5
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_info.h1
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_parse.c27
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_parse.h12
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sse2.h5
-rw-r--r--src/gallium/auxiliary/translate/translate.c2
-rw-r--r--src/gallium/auxiliary/translate/translate.h12
-rw-r--r--src/gallium/auxiliary/translate/translate_generic.c213
-rw-r--r--src/gallium/auxiliary/translate/translate_sse.c1378
-rw-r--r--src/gallium/auxiliary/util/u_bitmask.h3
-rw-r--r--src/gallium/auxiliary/util/u_blit.c130
-rw-r--r--src/gallium/auxiliary/util/u_blit.h12
-rw-r--r--src/gallium/auxiliary/util/u_blitter.c54
-rw-r--r--src/gallium/auxiliary/util/u_blitter.h36
-rw-r--r--src/gallium/auxiliary/util/u_cpu_detect.c177
-rw-r--r--src/gallium/auxiliary/util/u_debug_describe.c81
-rw-r--r--src/gallium/auxiliary/util/u_debug_describe.h49
-rw-r--r--src/gallium/auxiliary/util/u_debug_refcnt.c181
-rw-r--r--src/gallium/auxiliary/util/u_debug_refcnt.h63
-rw-r--r--src/gallium/auxiliary/util/u_debug_symbol.c97
-rw-r--r--src/gallium/auxiliary/util/u_debug_symbol.h7
-rw-r--r--src/gallium/auxiliary/util/u_dirty_surfaces.h30
-rw-r--r--src/gallium/auxiliary/util/u_draw.h1
-rw-r--r--src/gallium/auxiliary/util/u_dynarray.h3
-rw-r--r--src/gallium/auxiliary/util/u_gen_mipmap.c1
-rw-r--r--src/gallium/auxiliary/util/u_inlines.h25
-rw-r--r--src/gallium/auxiliary/util/u_linkage.c149
-rw-r--r--src/gallium/auxiliary/util/u_linkage.h66
-rw-r--r--src/gallium/auxiliary/util/u_math.h13
-rw-r--r--src/gallium/auxiliary/util/u_pack_color.h8
-rw-r--r--src/gallium/auxiliary/util/u_rect.c51
-rw-r--r--src/gallium/auxiliary/util/u_rect.h60
-rw-r--r--src/gallium/auxiliary/util/u_simple_shaders.c1
-rw-r--r--src/gallium/auxiliary/util/u_split_prim.h13
-rw-r--r--src/gallium/auxiliary/util/u_staging.c38
-rw-r--r--src/gallium/auxiliary/util/u_staging.h34
-rw-r--r--src/gallium/auxiliary/util/u_surface.c46
-rw-r--r--src/gallium/auxiliary/util/u_surfaces.c26
-rw-r--r--src/gallium/auxiliary/util/u_surfaces.h30
-rw-r--r--src/gallium/auxiliary/util/u_tile.h3
-rw-r--r--src/gallium/auxiliary/util/u_transfer.h1
-rw-r--r--src/gallium/auxiliary/util/u_upload_mgr.h5
-rw-r--r--src/gallium/docs/source/context.rst4
-rw-r--r--src/gallium/docs/source/debugging.rst4
-rw-r--r--src/gallium/docs/source/distro.rst9
-rw-r--r--src/gallium/docs/source/index.rst1
-rw-r--r--src/gallium/docs/source/resources.rst195
-rw-r--r--src/gallium/drivers/cell/ppu/cell_draw_arrays.c15
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_vertex.c2
-rw-r--r--src/gallium/drivers/galahad/glhd_context.c27
-rw-r--r--src/gallium/drivers/galahad/glhd_screen.c30
-rw-r--r--src/gallium/drivers/i915/i915_context.c22
-rw-r--r--src/gallium/drivers/i915/i915_resource_texture.c5
-rw-r--r--src/gallium/drivers/i915/i915_state.c8
-rw-r--r--src/gallium/drivers/i965/brw_batchbuffer.c2
-rw-r--r--src/gallium/drivers/i965/brw_resource_texture.c4
-rw-r--r--src/gallium/drivers/i965/brw_wm_debug.c8
-rw-r--r--src/gallium/drivers/llvmpipe/Makefile2
-rw-r--r--src/gallium/drivers/llvmpipe/SConscript2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.c20
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.h3
-rw-r--r--src/gallium/drivers/llvmpipe/lp_debug.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_draw_arrays.c18
-rw-r--r--src/gallium/drivers/llvmpipe/lp_fence.c93
-rw-r--r--src/gallium/drivers/llvmpipe/lp_fence.h13
-rw-r--r--src/gallium/drivers/llvmpipe/lp_flush.c39
-rw-r--r--src/gallium/drivers/llvmpipe/lp_flush.h13
-rw-r--r--src/gallium/drivers/llvmpipe/lp_perf.c21
-rw-r--r--src/gallium/drivers/llvmpipe/lp_perf.h7
-rw-r--r--src/gallium/drivers/llvmpipe/lp_query.c26
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.c37
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.h8
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast_tri.c223
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h35
-rw-r--r--src/gallium/drivers/llvmpipe/lp_scene.c7
-rw-r--r--src/gallium/drivers/llvmpipe/lp_screen.c61
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.c61
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.h13
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_coef.c258
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_coef.h (renamed from src/glsl/pp/sl_pp_dict.h)74
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_coef_intrin.c207
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_context.h37
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_line.c664
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_point.c292
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_tri.c568
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_derived.c20
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.c41
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.h6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_rasterizer.c8
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_vertex.c2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_surface.c6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_texture.c4
-rw-r--r--src/gallium/drivers/nouveau/nouveau_class.h17
-rw-r--r--src/gallium/drivers/nouveau/nouveau_screen.c3
-rw-r--r--src/gallium/drivers/nouveau/nouveau_util.h91
-rw-r--r--src/gallium/drivers/nv50/nv50_miptree.c3
-rw-r--r--src/gallium/drivers/nv50/nv50_push.c5
-rw-r--r--src/gallium/drivers/nv50/nv50_tex.c3
-rw-r--r--src/gallium/drivers/nvfx/Makefile3
-rw-r--r--src/gallium/drivers/nvfx/SConscript3
-rw-r--r--src/gallium/drivers/nvfx/nv04_2d.c1341
-rw-r--r--src/gallium/drivers/nvfx/nv04_2d.h87
-rw-r--r--src/gallium/drivers/nvfx/nv04_2d_loops.h70
-rw-r--r--src/gallium/drivers/nvfx/nv04_surface_2d.c532
-rw-r--r--src/gallium/drivers/nvfx/nv04_surface_2d.h43
-rw-r--r--src/gallium/drivers/nvfx/nv30_fragtex.c192
-rw-r--r--src/gallium/drivers/nvfx/nv30_vertprog.h9
-rw-r--r--src/gallium/drivers/nvfx/nv40_fragtex.c183
-rw-r--r--src/gallium/drivers/nvfx/nv40_vertprog.h4
-rw-r--r--src/gallium/drivers/nvfx/nvfx_buffer.c171
-rw-r--r--src/gallium/drivers/nvfx/nvfx_context.c35
-rw-r--r--src/gallium/drivers/nvfx/nvfx_context.h166
-rw-r--r--src/gallium/drivers/nvfx/nvfx_draw.c73
-rw-r--r--src/gallium/drivers/nvfx/nvfx_fragprog.c1177
-rw-r--r--src/gallium/drivers/nvfx/nvfx_fragtex.c301
-rw-r--r--src/gallium/drivers/nvfx/nvfx_miptree.c387
-rw-r--r--src/gallium/drivers/nvfx/nvfx_push.c414
-rw-r--r--src/gallium/drivers/nvfx/nvfx_resource.c48
-rw-r--r--src/gallium/drivers/nvfx/nvfx_resource.h194
-rw-r--r--src/gallium/drivers/nvfx/nvfx_screen.c125
-rw-r--r--src/gallium/drivers/nvfx/nvfx_screen.h23
-rw-r--r--src/gallium/drivers/nvfx/nvfx_shader.h194
-rw-r--r--src/gallium/drivers/nvfx/nvfx_state.c290
-rw-r--r--src/gallium/drivers/nvfx/nvfx_state.h45
-rw-r--r--src/gallium/drivers/nvfx/nvfx_state_emit.c231
-rw-r--r--src/gallium/drivers/nvfx/nvfx_state_fb.c256
-rw-r--r--src/gallium/drivers/nvfx/nvfx_state_stipple.c21
-rw-r--r--src/gallium/drivers/nvfx/nvfx_surface.c448
-rw-r--r--src/gallium/drivers/nvfx/nvfx_tex.h90
-rw-r--r--src/gallium/drivers/nvfx/nvfx_transfer.c328
-rw-r--r--src/gallium/drivers/nvfx/nvfx_transfer.h10
-rw-r--r--src/gallium/drivers/nvfx/nvfx_vbo.c1022
-rw-r--r--src/gallium/drivers/nvfx/nvfx_vertprog.c798
-rw-r--r--src/gallium/drivers/r300/r300_context.c97
-rw-r--r--src/gallium/drivers/r300/r300_context.h10
-rw-r--r--src/gallium/drivers/r300/r300_emit.c42
-rw-r--r--src/gallium/drivers/r300/r300_flush.c5
-rw-r--r--src/gallium/drivers/r300/r300_fs.c23
-rw-r--r--src/gallium/drivers/r300/r300_hyperz.c28
-rw-r--r--src/gallium/drivers/r300/r300_hyperz.h2
-rw-r--r--src/gallium/drivers/r300/r300_reg.h1
-rw-r--r--src/gallium/drivers/r300/r300_render.c55
-rw-r--r--src/gallium/drivers/r300/r300_state.c64
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c26
-rw-r--r--src/gallium/drivers/r300/r300_texture.c49
-rw-r--r--src/gallium/drivers/r300/r300_texture.h7
-rw-r--r--src/gallium/drivers/r300/r300_texture_desc.c6
-rw-r--r--src/gallium/drivers/r300/r300_texture_desc.h1
-rw-r--r--src/gallium/drivers/r300/r300_tgsi_to_rc.c4
-rw-r--r--src/gallium/drivers/r300/r300_vs.c17
-rw-r--r--src/gallium/drivers/r300/r300_winsys.h1
-rw-r--r--src/gallium/drivers/r600/r600_asm.c138
-rw-r--r--src/gallium/drivers/r600/r600_asm.h39
-rw-r--r--src/gallium/drivers/r600/r600_blit.c484
-rw-r--r--src/gallium/drivers/r600/r600_context.c182
-rw-r--r--src/gallium/drivers/r600/r600_context.h79
-rw-r--r--src/gallium/drivers/r600/r600_draw.c105
-rw-r--r--src/gallium/drivers/r600/r600_query.c200
-rw-r--r--src/gallium/drivers/r600/r600_resource.h12
-rw-r--r--src/gallium/drivers/r600/r600_screen.c25
-rw-r--r--src/gallium/drivers/r600/r600_screen.h18
-rw-r--r--src/gallium/drivers/r600/r600_shader.c1602
-rw-r--r--src/gallium/drivers/r600/r600_shader.h1
-rw-r--r--src/gallium/drivers/r600/r600_sq.h27
-rw-r--r--src/gallium/drivers/r600/r600_state.c476
-rw-r--r--src/gallium/drivers/r600/r600_state_inlines.h7
-rw-r--r--src/gallium/drivers/r600/r600_texture.c461
-rw-r--r--src/gallium/drivers/r600/r600d.h8
-rw-r--r--src/gallium/drivers/r600/radeon.h198
-rw-r--r--src/gallium/drivers/softpipe/sp_draw_arrays.c26
-rw-r--r--src/gallium/drivers/softpipe/sp_flush.c1
-rw-r--r--src/gallium/drivers/softpipe/sp_screen.c1
-rw-r--r--src/gallium/drivers/softpipe/sp_state_vertex.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_tex_sample.c2
-rw-r--r--src/gallium/drivers/svga/svga_cmd.c2
-rw-r--r--src/gallium/drivers/svga/svga_context.c5
-rw-r--r--src/gallium/drivers/svga/svga_context.h1
-rw-r--r--src/gallium/drivers/svga/svga_pipe_draw.c82
-rw-r--r--src/gallium/drivers/svga/svga_resource_texture.c3
-rw-r--r--src/gallium/drivers/svga/svga_state_framebuffer.c15
-rw-r--r--src/gallium/drivers/svga/svga_state_tss.c27
-rw-r--r--src/gallium/drivers/svga/svga_swtnl.h11
-rw-r--r--src/gallium/drivers/svga/svga_swtnl_draw.c39
-rw-r--r--src/gallium/drivers/svga/svga_tgsi_emit.h1
-rw-r--r--src/gallium/drivers/svga/svga_tgsi_insn.c19
-rw-r--r--src/gallium/drivers/trace/tr_context.c9
-rw-r--r--src/gallium/include/pipe/p_compiler.h8
-rw-r--r--src/gallium/include/pipe/p_context.h30
-rw-r--r--src/gallium/include/pipe/p_defines.h6
-rw-r--r--src/gallium/include/pipe/p_format.h2
-rw-r--r--src/gallium/include/pipe/p_shader_tokens.h2
-rw-r--r--src/gallium/include/pipe/p_state.h1
-rw-r--r--src/gallium/include/state_tracker/graw.h28
-rw-r--r--src/gallium/state_trackers/dri/common/dri_context.h1
-rw-r--r--src/gallium/state_trackers/dri/common/dri_screen.c5
-rw-r--r--src/gallium/state_trackers/dri/common/dri_screen.h1
-rw-r--r--src/gallium/state_trackers/dri/drm/dri2.c4
-rw-r--r--src/gallium/state_trackers/dri/sw/drisw.c2
-rw-r--r--src/gallium/state_trackers/egl/Makefile2
-rw-r--r--src/gallium/state_trackers/egl/SConscript1
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d.c12
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d.h20
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_api.c33
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_image.c245
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_image.h8
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_sync.c284
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_sync.h53
-rw-r--r--src/gallium/state_trackers/egl/kms/native_kms.c79
-rw-r--r--src/gallium/state_trackers/glx/xlib/glx_api.c8
-rw-r--r--src/gallium/state_trackers/glx/xlib/glx_usefont.c3
-rw-r--r--src/gallium/state_trackers/glx/xlib/xm_api.c78
-rw-r--r--src/gallium/state_trackers/glx/xlib/xm_api.h4
-rw-r--r--src/gallium/state_trackers/glx/xlib/xm_st.c24
-rw-r--r--src/gallium/state_trackers/wgl/stw_context.c2
-rw-r--r--src/gallium/state_trackers/wgl/stw_device.c2
-rw-r--r--src/gallium/state_trackers/wgl/stw_pixelformat.c4
-rw-r--r--src/gallium/state_trackers/wgl/stw_pixelformat.h2
-rw-r--r--src/gallium/targets/Makefile.dri13
-rw-r--r--src/gallium/targets/SConscript15
-rw-r--r--src/gallium/targets/dri-r300/Makefile (renamed from src/gallium/targets/dri-radeong/Makefile)2
-rw-r--r--src/gallium/targets/dri-r300/SConscript (renamed from src/gallium/targets/dri-radeong/SConscript)4
-rw-r--r--src/gallium/targets/dri-r300/target.c (renamed from src/gallium/targets/dri-radeong/target.c)2
-rw-r--r--src/gallium/targets/dri-r600/Makefile6
-rw-r--r--src/gallium/targets/egl-gdi/egl-static.c39
-rw-r--r--src/gallium/targets/egl/Makefile33
-rw-r--r--src/gallium/targets/egl/egl.c27
-rw-r--r--src/gallium/targets/egl/pipe_r300.c (renamed from src/gallium/targets/egl/pipe_radeon.c)2
-rw-r--r--src/gallium/targets/egl/pipe_r600.c27
-rw-r--r--src/gallium/targets/graw-xlib/graw_util.c1
-rw-r--r--src/gallium/targets/graw-xlib/graw_xlib.c1
-rw-r--r--src/gallium/targets/libgl-gdi/SConscript1
-rw-r--r--src/gallium/targets/libgl-xlib/Makefile3
-rw-r--r--src/gallium/targets/libgl-xlib/SConscript1
-rw-r--r--src/gallium/targets/libgl-xlib/xlib.c1
-rwxr-xr-xsrc/gallium/tests/python/tests/texture_blit.py2
-rwxr-xr-xsrc/gallium/tools/addr2line.sh26
-rw-r--r--src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c3
-rw-r--r--src/gallium/winsys/r600/drm/r600_state.c182
-rw-r--r--src/gallium/winsys/r600/drm/r600_states.h161
-rw-r--r--src/gallium/winsys/r600/drm/r600d.h3
-rw-r--r--src/gallium/winsys/r600/drm/radeon.c70
-rw-r--r--src/gallium/winsys/r600/drm/radeon_bo.c4
-rw-r--r--src/gallium/winsys/r600/drm/radeon_ctx.c218
-rw-r--r--src/gallium/winsys/r600/drm/radeon_draw.c108
-rw-r--r--src/gallium/winsys/r600/drm/radeon_priv.h37
-rw-r--r--src/gallium/winsys/r600/drm/radeon_state.c145
-rw-r--r--src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c8
-rw-r--r--src/glsl/.dir-locals.el3
-rw-r--r--src/glsl/.gitignore2
-rw-r--r--src/glsl/Makefile179
-rw-r--r--src/glsl/Makefile.am75
-rw-r--r--src/glsl/README191
-rw-r--r--src/glsl/SConscript115
-rw-r--r--src/glsl/TODO50
-rw-r--r--src/glsl/apps/.gitignore5
-rw-r--r--src/glsl/apps/Makefile43
-rw-r--r--src/glsl/apps/compile.c198
-rw-r--r--src/glsl/apps/process.c388
-rw-r--r--src/glsl/apps/purify.c112
-rw-r--r--src/glsl/apps/tokenise.c340
-rw-r--r--src/glsl/apps/version.c121
-rw-r--r--src/glsl/ast.h664
-rw-r--r--src/glsl/ast_expr.cpp96
-rw-r--r--src/glsl/ast_function.cpp1240
-rw-r--r--src/glsl/ast_to_hir.cpp2751
-rw-r--r--src/glsl/ast_type.cpp122
-rwxr-xr-xsrc/glsl/autogen.sh12
-rw-r--r--src/glsl/builtin_function.cpp16935
-rw-r--r--src/glsl/builtin_types.h290
-rw-r--r--src/glsl/builtin_variables.h98
-rw-r--r--src/glsl/builtins/ir/abs21
-rw-r--r--src/glsl/builtins/ir/acos22
-rw-r--r--src/glsl/builtins/ir/all16
-rw-r--r--src/glsl/builtins/ir/any16
-rw-r--r--src/glsl/builtins/ir/asin97
-rw-r--r--src/glsl/builtins/ir/atan150
-rw-r--r--src/glsl/builtins/ir/ceil21
-rw-r--r--src/glsl/builtins/ir/clamp148
-rw-r--r--src/glsl/builtins/ir/cos21
-rw-r--r--src/glsl/builtins/ir/cosh30
-rw-r--r--src/glsl/builtins/ir/cross7
-rw-r--r--src/glsl/builtins/ir/dFdx21
-rw-r--r--src/glsl/builtins/ir/dFdy21
-rw-r--r--src/glsl/builtins/ir/degrees21
-rw-r--r--src/glsl/builtins/ir/distance33
-rw-r--r--src/glsl/builtins/ir/dot25
-rw-r--r--src/glsl/builtins/ir/equal121
-rw-r--r--src/glsl/builtins/ir/exp21
-rw-r--r--src/glsl/builtins/ir/exp221
-rw-r--r--src/glsl/builtins/ir/faceforward37
-rw-r--r--src/glsl/builtins/ir/floor21
-rw-r--r--src/glsl/builtins/ir/fract22
-rw-r--r--src/glsl/builtins/ir/ftransform9
-rw-r--r--src/glsl/builtins/ir/fwidth29
-rw-r--r--src/glsl/builtins/ir/greaterThan91
-rw-r--r--src/glsl/builtins/ir/greaterThanEqual91
-rw-r--r--src/glsl/builtins/ir/inversesqrt21
-rw-r--r--src/glsl/builtins/ir/length21
-rw-r--r--src/glsl/builtins/ir/lessThan91
-rw-r--r--src/glsl/builtins/ir/lessThanEqual91
-rw-r--r--src/glsl/builtins/ir/log21
-rw-r--r--src/glsl/builtins/ir/log221
-rw-r--r--src/glsl/builtins/ir/matrixCompMult91
-rw-r--r--src/glsl/builtins/ir/max127
-rw-r--r--src/glsl/builtins/ir/min127
-rw-r--r--src/glsl/builtins/ir/mix88
-rw-r--r--src/glsl/builtins/ir/mod43
-rw-r--r--src/glsl/builtins/ir/noise118
-rw-r--r--src/glsl/builtins/ir/noise218
-rw-r--r--src/glsl/builtins/ir/noise318
-rw-r--r--src/glsl/builtins/ir/noise418
-rw-r--r--src/glsl/builtins/ir/normalize21
-rw-r--r--src/glsl/builtins/ir/not16
-rw-r--r--src/glsl/builtins/ir/notEqual121
-rw-r--r--src/glsl/builtins/ir/outerProduct92
-rw-r--r--src/glsl/builtins/ir/pow25
-rw-r--r--src/glsl/builtins/ir/radians21
-rw-r--r--src/glsl/builtins/ir/reflect58
-rw-r--r--src/glsl/builtins/ir/refract102
-rw-r--r--src/glsl/builtins/ir/sign42
-rw-r--r--src/glsl/builtins/ir/sin21
-rw-r--r--src/glsl/builtins/ir/sinh30
-rw-r--r--src/glsl/builtins/ir/smoothstep153
-rw-r--r--src/glsl/builtins/ir/sqrt21
-rw-r--r--src/glsl/builtins/ir/step68
-rw-r--r--src/glsl/builtins/ir/tan21
-rw-r--r--src/glsl/builtins/ir/tanh42
-rw-r--r--src/glsl/builtins/ir/transpose139
-rw-r--r--src/glsl/builtins/profiles/110.frag364
-rw-r--r--src/glsl/builtins/profiles/110.vert351
-rw-r--r--src/glsl/builtins/profiles/120.frag396
-rw-r--r--src/glsl/builtins/profiles/120.vert383
-rw-r--r--src/glsl/builtins/profiles/130.frag1031
-rw-r--r--src/glsl/builtins/profiles/130.vert1019
-rw-r--r--src/glsl/builtins/profiles/ARB_texture_rectangle.frag7
-rw-r--r--src/glsl/builtins/profiles/ARB_texture_rectangle.vert7
-rw-r--r--src/glsl/builtins/profiles/EXT_texture_array.frag11
-rw-r--r--src/glsl/builtins/profiles/EXT_texture_array.vert11
-rw-r--r--src/glsl/builtins/tools/builtin_function.cpp39
-rwxr-xr-xsrc/glsl/builtins/tools/generate_builtins.py240
-rwxr-xr-xsrc/glsl/builtins/tools/generate_matrixCompMultGLSL.py28
-rwxr-xr-xsrc/glsl/builtins/tools/generate_outerProductGLSL.py23
-rwxr-xr-xsrc/glsl/builtins/tools/generate_transposeGLSL.py28
-rwxr-xr-xsrc/glsl/builtins/tools/texture_builtins.py349
-rw-r--r--src/glsl/cl/Makefile13
-rw-r--r--src/glsl/cl/sl_cl_parse.c3027
-rw-r--r--src/glsl/cl/sl_cl_parse.h42
-rw-r--r--src/glsl/configure.ac69
-rw-r--r--src/glsl/glcpp/.gitignore8
-rw-r--r--src/glsl/glcpp/Makefile.am44
-rw-r--r--src/glsl/glcpp/README32
-rw-r--r--src/glsl/glcpp/glcpp-lex.c2691
-rw-r--r--src/glsl/glcpp/glcpp-lex.l325
-rw-r--r--src/glsl/glcpp/glcpp-parse.c4168
-rw-r--r--src/glsl/glcpp/glcpp-parse.h101
-rw-r--r--src/glsl/glcpp/glcpp-parse.y1850
-rw-r--r--src/glsl/glcpp/glcpp.c122
-rw-r--r--src/glsl/glcpp/glcpp.h222
-rw-r--r--src/glsl/glcpp/pp.c167
-rw-r--r--src/glsl/glcpp/tests/000-content-with-spaces.c1
-rw-r--r--src/glsl/glcpp/tests/000-content-with-spaces.c.expected2
-rw-r--r--src/glsl/glcpp/tests/001-define.c2
-rw-r--r--src/glsl/glcpp/tests/001-define.c.expected3
-rw-r--r--src/glsl/glcpp/tests/002-define-chain.c3
-rw-r--r--src/glsl/glcpp/tests/002-define-chain.c.expected4
-rw-r--r--src/glsl/glcpp/tests/003-define-chain-reverse.c3
-rw-r--r--src/glsl/glcpp/tests/003-define-chain-reverse.c.expected4
-rw-r--r--src/glsl/glcpp/tests/004-define-recursive.c6
-rw-r--r--src/glsl/glcpp/tests/004-define-recursive.c.expected7
-rw-r--r--src/glsl/glcpp/tests/005-define-composite-chain.c3
-rw-r--r--src/glsl/glcpp/tests/005-define-composite-chain.c.expected4
-rw-r--r--src/glsl/glcpp/tests/006-define-composite-chain-reverse.c3
-rw-r--r--src/glsl/glcpp/tests/006-define-composite-chain-reverse.c.expected4
-rw-r--r--src/glsl/glcpp/tests/007-define-composite-recursive.c6
-rw-r--r--src/glsl/glcpp/tests/007-define-composite-recursive.c.expected7
-rw-r--r--src/glsl/glcpp/tests/008-define-empty.c2
-rw-r--r--src/glsl/glcpp/tests/008-define-empty.c.expected3
-rw-r--r--src/glsl/glcpp/tests/009-undef.c4
-rw-r--r--src/glsl/glcpp/tests/009-undef.c.expected5
-rw-r--r--src/glsl/glcpp/tests/010-undef-re-define.c6
-rw-r--r--src/glsl/glcpp/tests/010-undef-re-define.c.expected7
-rw-r--r--src/glsl/glcpp/tests/011-define-func-empty.c2
-rw-r--r--src/glsl/glcpp/tests/011-define-func-empty.c.expected3
-rw-r--r--src/glsl/glcpp/tests/012-define-func-no-args.c2
-rw-r--r--src/glsl/glcpp/tests/012-define-func-no-args.c.expected3
-rw-r--r--src/glsl/glcpp/tests/013-define-func-1-arg-unused.c2
-rw-r--r--src/glsl/glcpp/tests/013-define-func-1-arg-unused.c.expected3
-rw-r--r--src/glsl/glcpp/tests/014-define-func-2-arg-unused.c2
-rw-r--r--src/glsl/glcpp/tests/014-define-func-2-arg-unused.c.expected3
-rw-r--r--src/glsl/glcpp/tests/015-define-object-with-parens.c4
-rw-r--r--src/glsl/glcpp/tests/015-define-object-with-parens.c.expected5
-rw-r--r--src/glsl/glcpp/tests/016-define-func-1-arg.c2
-rw-r--r--src/glsl/glcpp/tests/016-define-func-1-arg.c.expected3
-rw-r--r--src/glsl/glcpp/tests/017-define-func-2-args.c2
-rw-r--r--src/glsl/glcpp/tests/017-define-func-2-args.c.expected3
-rw-r--r--src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c3
-rw-r--r--src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c.expected4
-rw-r--r--src/glsl/glcpp/tests/019-define-func-1-arg-multi.c2
-rw-r--r--src/glsl/glcpp/tests/019-define-func-1-arg-multi.c.expected3
-rw-r--r--src/glsl/glcpp/tests/020-define-func-2-arg-multi.c2
-rw-r--r--src/glsl/glcpp/tests/020-define-func-2-arg-multi.c.expected3
-rw-r--r--src/glsl/glcpp/tests/021-define-func-compose.c3
-rw-r--r--src/glsl/glcpp/tests/021-define-func-compose.c.expected4
-rw-r--r--src/glsl/glcpp/tests/022-define-func-arg-with-parens.c2
-rw-r--r--src/glsl/glcpp/tests/022-define-func-arg-with-parens.c.expected3
-rw-r--r--src/glsl/glcpp/tests/023-define-extra-whitespace.c8
-rw-r--r--src/glsl/glcpp/tests/023-define-extra-whitespace.c.expected9
-rw-r--r--src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c3
-rw-r--r--src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c.expected4
-rw-r--r--src/glsl/glcpp/tests/025-func-macro-as-non-macro.c2
-rw-r--r--src/glsl/glcpp/tests/025-func-macro-as-non-macro.c.expected3
-rw-r--r--src/glsl/glcpp/tests/026-define-func-extra-newlines.c6
-rw-r--r--src/glsl/glcpp/tests/026-define-func-extra-newlines.c.expected4
-rw-r--r--src/glsl/glcpp/tests/027-define-chain-obj-to-func.c3
-rw-r--r--src/glsl/glcpp/tests/027-define-chain-obj-to-func.c.expected4
-rw-r--r--src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c3
-rw-r--r--src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c.expected4
-rw-r--r--src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c3
-rw-r--r--src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c.expected4
-rw-r--r--src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c4
-rw-r--r--src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c.expected5
-rw-r--r--src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c4
-rw-r--r--src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c.expected5
-rw-r--r--src/glsl/glcpp/tests/032-define-func-self-recurse.c2
-rw-r--r--src/glsl/glcpp/tests/032-define-func-self-recurse.c.expected3
-rw-r--r--src/glsl/glcpp/tests/033-define-func-self-compose.c2
-rw-r--r--src/glsl/glcpp/tests/033-define-func-self-compose.c.expected3
-rw-r--r--src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c2
-rw-r--r--src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c.expected3
-rw-r--r--src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c2
-rw-r--r--src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c.expected3
-rw-r--r--src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c3
-rw-r--r--src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c.expected4
-rw-r--r--src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c3
-rw-r--r--src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c.expected4
-rw-r--r--src/glsl/glcpp/tests/038-func-arg-with-commas.c2
-rw-r--r--src/glsl/glcpp/tests/038-func-arg-with-commas.c.expected3
-rw-r--r--src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c3
-rw-r--r--src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected4
-rw-r--r--src/glsl/glcpp/tests/040-token-pasting.c2
-rw-r--r--src/glsl/glcpp/tests/040-token-pasting.c.expected3
-rw-r--r--src/glsl/glcpp/tests/041-if-0.c5
-rw-r--r--src/glsl/glcpp/tests/041-if-0.c.expected6
-rw-r--r--src/glsl/glcpp/tests/042-if-1.c5
-rw-r--r--src/glsl/glcpp/tests/042-if-1.c.expected6
-rw-r--r--src/glsl/glcpp/tests/043-if-0-else.c7
-rw-r--r--src/glsl/glcpp/tests/043-if-0-else.c.expected8
-rw-r--r--src/glsl/glcpp/tests/044-if-1-else.c7
-rw-r--r--src/glsl/glcpp/tests/044-if-1-else.c.expected8
-rw-r--r--src/glsl/glcpp/tests/045-if-0-elif.c11
-rw-r--r--src/glsl/glcpp/tests/045-if-0-elif.c.expected12
-rw-r--r--src/glsl/glcpp/tests/046-if-1-elsif.c11
-rw-r--r--src/glsl/glcpp/tests/046-if-1-elsif.c.expected12
-rw-r--r--src/glsl/glcpp/tests/047-if-elif-else.c11
-rw-r--r--src/glsl/glcpp/tests/047-if-elif-else.c.expected12
-rw-r--r--src/glsl/glcpp/tests/048-if-nested.c11
-rw-r--r--src/glsl/glcpp/tests/048-if-nested.c.expected12
-rw-r--r--src/glsl/glcpp/tests/049-if-expression-precedence.c5
-rw-r--r--src/glsl/glcpp/tests/049-if-expression-precedence.c.expected6
-rw-r--r--src/glsl/glcpp/tests/050-if-defined.c17
-rw-r--r--src/glsl/glcpp/tests/050-if-defined.c.expected18
-rw-r--r--src/glsl/glcpp/tests/051-if-relational.c35
-rw-r--r--src/glsl/glcpp/tests/051-if-relational.c.expected36
-rw-r--r--src/glsl/glcpp/tests/052-if-bitwise.c20
-rw-r--r--src/glsl/glcpp/tests/052-if-bitwise.c.expected21
-rw-r--r--src/glsl/glcpp/tests/053-if-divide-and-shift.c15
-rw-r--r--src/glsl/glcpp/tests/053-if-divide-and-shift.c.expected16
-rw-r--r--src/glsl/glcpp/tests/054-if-with-macros.c34
-rw-r--r--src/glsl/glcpp/tests/054-if-with-macros.c.expected35
-rw-r--r--src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c3
-rw-r--r--src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c.expected4
-rw-r--r--src/glsl/glcpp/tests/056-macro-argument-with-comma.c4
-rw-r--r--src/glsl/glcpp/tests/056-macro-argument-with-comma.c.expected5
-rw-r--r--src/glsl/glcpp/tests/057-empty-arguments.c6
-rw-r--r--src/glsl/glcpp/tests/057-empty-arguments.c.expected7
-rw-r--r--src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c5
-rw-r--r--src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c.expected6
-rw-r--r--src/glsl/glcpp/tests/059-token-pasting-integer.c4
-rw-r--r--src/glsl/glcpp/tests/059-token-pasting-integer.c.expected5
-rw-r--r--src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c3
-rw-r--r--src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c.expected4
-rw-r--r--src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c5
-rw-r--r--src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c.expected6
-rw-r--r--src/glsl/glcpp/tests/062-if-0-skips-garbage.c5
-rw-r--r--src/glsl/glcpp/tests/062-if-0-skips-garbage.c.expected6
-rw-r--r--src/glsl/glcpp/tests/063-comments.c20
-rw-r--r--src/glsl/glcpp/tests/063-comments.c.expected14
-rw-r--r--src/glsl/glcpp/tests/064-version.c2
-rw-r--r--src/glsl/glcpp/tests/064-version.c.expected3
-rw-r--r--src/glsl/glcpp/tests/065-if-defined-parens.c17
-rw-r--r--src/glsl/glcpp/tests/065-if-defined-parens.c.expected18
-rw-r--r--src/glsl/glcpp/tests/066-if-nospace-expression.c3
-rw-r--r--src/glsl/glcpp/tests/066-if-nospace-expression.c.expected4
-rw-r--r--src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c40
-rw-r--r--src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c.expected41
-rw-r--r--src/glsl/glcpp/tests/068-accidental-pasting.c11
-rw-r--r--src/glsl/glcpp/tests/068-accidental-pasting.c.expected12
-rw-r--r--src/glsl/glcpp/tests/069-repeated-argument.c2
-rw-r--r--src/glsl/glcpp/tests/069-repeated-argument.c.expected3
-rw-r--r--src/glsl/glcpp/tests/070-undefined-macro-in-expression.c2
-rw-r--r--src/glsl/glcpp/tests/070-undefined-macro-in-expression.c.expected2
-rw-r--r--src/glsl/glcpp/tests/071-punctuator.c1
-rw-r--r--src/glsl/glcpp/tests/071-punctuator.c.expected2
-rw-r--r--src/glsl/glcpp/tests/072-token-pasting-same-line.c2
-rw-r--r--src/glsl/glcpp/tests/072-token-pasting-same-line.c.expected3
-rw-r--r--src/glsl/glcpp/tests/073-if-in-ifdef.c4
-rw-r--r--src/glsl/glcpp/tests/073-if-in-ifdef.c.expected5
-rw-r--r--src/glsl/glcpp/tests/074-elif-undef.c3
-rw-r--r--src/glsl/glcpp/tests/074-elif-undef.c.expected4
-rw-r--r--src/glsl/glcpp/tests/075-elif-elif-undef.c4
-rw-r--r--src/glsl/glcpp/tests/075-elif-elif-undef.c.expected5
-rw-r--r--src/glsl/glcpp/tests/076-elif-undef-nested.c5
-rw-r--r--src/glsl/glcpp/tests/076-elif-undef-nested.c.expected6
-rw-r--r--src/glsl/glcpp/tests/077-else-without-if.c1
-rw-r--r--src/glsl/glcpp/tests/077-else-without-if.c.expected4
-rw-r--r--src/glsl/glcpp/tests/078-elif-without-if.c1
-rw-r--r--src/glsl/glcpp/tests/078-elif-without-if.c.expected4
-rw-r--r--src/glsl/glcpp/tests/079-endif-without-if.c1
-rw-r--r--src/glsl/glcpp/tests/079-endif-without-if.c.expected4
-rw-r--r--src/glsl/glcpp/tests/080-if-without-expression.c4
-rw-r--r--src/glsl/glcpp/tests/080-if-without-expression.c.expected6
-rw-r--r--src/glsl/glcpp/tests/081-elif-without-expression.c3
-rw-r--r--src/glsl/glcpp/tests/081-elif-without-expression.c.expected5
-rw-r--r--src/glsl/glcpp/tests/082-invalid-paste.c2
-rw-r--r--src/glsl/glcpp/tests/082-invalid-paste.c.expected5
-rw-r--r--src/glsl/glcpp/tests/083-unterminated-if.c2
-rw-r--r--src/glsl/glcpp/tests/083-unterminated-if.c.expected5
-rw-r--r--src/glsl/glcpp/tests/084-unbalanced-parentheses.c2
-rw-r--r--src/glsl/glcpp/tests/085-incorrect-argument-count.c5
-rw-r--r--src/glsl/glcpp/tests/085-incorrect-argument-count.c.expected12
-rw-r--r--src/glsl/glcpp/tests/086-reserved-macro-names.c2
-rw-r--r--src/glsl/glcpp/tests/086-reserved-macro-names.c.expected7
-rw-r--r--src/glsl/glcpp/tests/087-if-comments.c5
-rw-r--r--src/glsl/glcpp/tests/087-if-comments.c.expected6
-rw-r--r--src/glsl/glcpp/tests/088-redefine-macro-legitimate.c5
-rw-r--r--src/glsl/glcpp/tests/088-redefine-macro-legitimate.c.expected6
-rw-r--r--src/glsl/glcpp/tests/089-redefine-macro-error.c17
-rw-r--r--src/glsl/glcpp/tests/089-redefine-macro-error.c.expected30
-rw-r--r--src/glsl/glcpp/tests/090-hash-error.c1
-rw-r--r--src/glsl/glcpp/tests/090-hash-error.c.expected3
-rw-r--r--src/glsl/glcpp/tests/091-hash-line.c8
-rw-r--r--src/glsl/glcpp/tests/091-hash-line.c.expected13
-rw-r--r--src/glsl/glcpp/tests/099-c99-example.c17
-rw-r--r--src/glsl/glcpp/tests/099-c99-example.c.expected17
-rwxr-xr-xsrc/glsl/glcpp/tests/glcpp-test50
-rw-r--r--src/glsl/glsl_lexer.cpp3492
-rw-r--r--src/glsl/glsl_lexer.lpp389
-rw-r--r--src/glsl/glsl_parser.cpp5268
-rw-r--r--src/glsl/glsl_parser.h294
-rw-r--r--src/glsl/glsl_parser.ypp1520
-rw-r--r--src/glsl/glsl_parser_extras.cpp773
-rw-r--r--src/glsl/glsl_parser_extras.h235
-rw-r--r--src/glsl/glsl_symbol_table.cpp160
-rw-r--r--src/glsl/glsl_symbol_table.h121
-rw-r--r--src/glsl/glsl_types.cpp484
-rw-r--r--src/glsl/glsl_types.h476
-rw-r--r--src/glsl/hir_field_selection.cpp102
-rw-r--r--src/glsl/ir.cpp1175
-rw-r--r--src/glsl/ir.h1399
-rw-r--r--src/glsl/ir_algebraic.cpp472
-rw-r--r--src/glsl/ir_basic_block.cpp149
-rw-r--r--src/glsl/ir_basic_block.h28
-rw-r--r--src/glsl/ir_clone.cpp402
-rw-r--r--src/glsl/ir_constant_expression.cpp1159
-rw-r--r--src/glsl/ir_constant_folding.cpp147
-rw-r--r--src/glsl/ir_constant_propagation.cpp435
-rw-r--r--src/glsl/ir_constant_variable.cpp198
-rw-r--r--src/glsl/ir_copy_propagation.cpp362
-rw-r--r--src/glsl/ir_dead_code.cpp142
-rw-r--r--src/glsl/ir_dead_code_local.cpp229
-rw-r--r--src/glsl/ir_dead_functions.cpp151
-rw-r--r--src/glsl/ir_div_to_mul_rcp.cpp115
-rw-r--r--src/glsl/ir_explog_to_explog2.cpp85
-rw-r--r--src/glsl/ir_expression_flattening.cpp92
-rw-r--r--src/glsl/ir_expression_flattening.h38
-rw-r--r--src/glsl/ir_function.cpp227
-rw-r--r--src/glsl/ir_function_can_inline.cpp71
-rw-r--r--src/glsl/ir_function_inlining.cpp417
-rw-r--r--src/glsl/ir_function_inlining.h30
-rw-r--r--src/glsl/ir_hierarchical_visitor.cpp296
-rw-r--r--src/glsl/ir_hierarchical_visitor.h176
-rw-r--r--src/glsl/ir_hv_accept.cpp369
-rw-r--r--src/glsl/ir_if_return.cpp246
-rw-r--r--src/glsl/ir_if_simplification.cpp84
-rw-r--r--src/glsl/ir_if_to_cond_assign.cpp168
-rw-r--r--src/glsl/ir_import_prototypes.cpp138
-rw-r--r--src/glsl/ir_mat_op_to_vec.cpp491
-rw-r--r--src/glsl/ir_mod_to_fract.cpp90
-rw-r--r--src/glsl/ir_noop_swizzle.cpp80
-rw-r--r--src/glsl/ir_optimization.h57
-rw-r--r--src/glsl/ir_print_visitor.cpp459
-rw-r--r--src/glsl/ir_print_visitor.h83
-rw-r--r--src/glsl/ir_reader.cpp1088
-rw-r--r--src/glsl/ir_reader.h34
-rw-r--r--src/glsl/ir_rvalue_visitor.cpp134
-rw-r--r--src/glsl/ir_rvalue_visitor.h47
-rw-r--r--src/glsl/ir_set_program_inouts.cpp167
-rw-r--r--src/glsl/ir_structure_splitting.cpp361
-rw-r--r--src/glsl/ir_sub_to_add_neg.cpp76
-rw-r--r--src/glsl/ir_swizzle_swizzle.cpp93
-rw-r--r--src/glsl/ir_tree_grafting.cpp367
-rw-r--r--src/glsl/ir_validate.cpp402
-rw-r--r--src/glsl/ir_variable.cpp415
-rw-r--r--src/glsl/ir_variable_refcount.cpp113
-rw-r--r--src/glsl/ir_variable_refcount.h78
-rw-r--r--src/glsl/ir_vec_index_to_cond_assign.cpp258
-rw-r--r--src/glsl/ir_vec_index_to_swizzle.cpp157
-rw-r--r--src/glsl/ir_visitor.h67
-rw-r--r--src/glsl/link_functions.cpp262
-rw-r--r--src/glsl/linker.cpp1501
-rw-r--r--src/glsl/linker.h35
-rw-r--r--src/glsl/list.h465
-rw-r--r--src/glsl/main.cpp287
-rw-r--r--src/glsl/pp/Makefile27
-rw-r--r--src/glsl/pp/sl_pp_context.c183
-rw-r--r--src/glsl/pp/sl_pp_context.h99
-rw-r--r--src/glsl/pp/sl_pp_define.c240
-rw-r--r--src/glsl/pp/sl_pp_dict.c85
-rw-r--r--src/glsl/pp/sl_pp_error.c271
-rw-r--r--src/glsl/pp/sl_pp_expression.c413
-rw-r--r--src/glsl/pp/sl_pp_expression.h40
-rw-r--r--src/glsl/pp/sl_pp_extension.c180
-rw-r--r--src/glsl/pp/sl_pp_if.c343
-rw-r--r--src/glsl/pp/sl_pp_line.c129
-rw-r--r--src/glsl/pp/sl_pp_macro.c415
-rw-r--r--src/glsl/pp/sl_pp_macro.h70
-rw-r--r--src/glsl/pp/sl_pp_pragma.c110
-rw-r--r--src/glsl/pp/sl_pp_process.c331
-rw-r--r--src/glsl/pp/sl_pp_process.h113
-rw-r--r--src/glsl/pp/sl_pp_public.h79
-rw-r--r--src/glsl/pp/sl_pp_purify.c302
-rw-r--r--src/glsl/pp/sl_pp_purify.h63
-rw-r--r--src/glsl/pp/sl_pp_token.c854
-rw-r--r--src/glsl/pp/sl_pp_token.h133
-rw-r--r--src/glsl/pp/sl_pp_token_util.c183
-rw-r--r--src/glsl/pp/sl_pp_token_util.h98
-rw-r--r--src/glsl/pp/sl_pp_version.c162
-rw-r--r--src/glsl/program.h (renamed from src/mesa/slang/library/slang_builtin_120_fragment.gc)15
-rw-r--r--src/glsl/s_expression.cpp140
-rw-r--r--src/glsl/s_expression.h142
-rw-r--r--src/glsl/tests/array-01.glsl3
-rw-r--r--src/glsl/tests/array-02.glsl3
-rw-r--r--src/glsl/tests/array-03.glsl3
-rw-r--r--src/glsl/tests/array-04.glsl2
-rw-r--r--src/glsl/tests/array-05.glsl2
-rw-r--r--src/glsl/tests/array-06.glsl2
-rw-r--r--src/glsl/tests/array-07.glsl2
-rw-r--r--src/glsl/tests/array-08.glsl2
-rw-r--r--src/glsl/tests/array-09.glsl9
-rw-r--r--src/glsl/tests/array-10.glsl11
-rw-r--r--src/glsl/tests/array-11.glsl9
-rw-r--r--src/glsl/tests/array-12.glsl11
-rw-r--r--src/glsl/tests/array-13.glsl11
-rw-r--r--src/glsl/tests/attribute-01.glsl7
-rw-r--r--src/glsl/tests/attribute-02.glsl7
-rw-r--r--src/glsl/tests/attribute-03.glsl7
-rw-r--r--src/glsl/tests/attribute-04.glsl7
-rw-r--r--src/glsl/tests/attribute-05.glsl7
-rw-r--r--src/glsl/tests/attribute-06.glsl7
-rw-r--r--src/glsl/tests/attribute-07.glsl7
-rw-r--r--src/glsl/tests/attribute-08.glsl7
-rw-r--r--src/glsl/tests/attribute-09.glsl7
-rw-r--r--src/glsl/tests/attribute-10.glsl8
-rw-r--r--src/glsl/tests/attribute-11.glsl8
-rw-r--r--src/glsl/tests/condition-01.glsl8
-rw-r--r--src/glsl/tests/condition-02.glsl8
-rw-r--r--src/glsl/tests/condition-03.glsl8
-rw-r--r--src/glsl/tests/condition-04.glsl8
-rw-r--r--src/glsl/tests/condition-05.glsl13
-rw-r--r--src/glsl/tests/constructor-01.glsl6
-rw-r--r--src/glsl/tests/constructor-02.glsl7
-rw-r--r--src/glsl/tests/constructor-03.glsl12
-rw-r--r--src/glsl/tests/constructor-04.glsl14
-rw-r--r--src/glsl/tests/constructor-05.glsl13
-rw-r--r--src/glsl/tests/constructor-06.glsl13
-rw-r--r--src/glsl/tests/constructor-07.glsl13
-rw-r--r--src/glsl/tests/constructor-08.glsl13
-rw-r--r--src/glsl/tests/constructor-09.glsl26
-rw-r--r--src/glsl/tests/function-01.glsl16
-rw-r--r--src/glsl/tests/function-02.glsl16
-rw-r--r--src/glsl/tests/function-03.glsl16
-rw-r--r--src/glsl/tests/function-04.glsl15
-rw-r--r--src/glsl/tests/function-05.glsl26
-rw-r--r--src/glsl/tests/if-01.glsl11
-rw-r--r--src/glsl/tests/if-02.glsl11
-rw-r--r--src/glsl/tests/if-03.glsl11
-rw-r--r--src/glsl/tests/if-04.glsl11
-rw-r--r--src/glsl/tests/matrix-01.glsl6
-rw-r--r--src/glsl/tests/matrix-02.glsl6
-rw-r--r--src/glsl/tests/matrix-03.glsl6
-rw-r--r--src/glsl/tests/matrix-04.glsl6
-rw-r--r--src/glsl/tests/matrix-05.glsl6
-rw-r--r--src/glsl/tests/matrix-06.glsl6
-rw-r--r--src/glsl/tests/matrix-07.glsl27
-rw-r--r--src/glsl/tests/matrix-08.glsl19
-rw-r--r--src/glsl/tests/matrix-09.glsl11
-rw-r--r--src/glsl/tests/matrix-10.glsl12
-rw-r--r--src/glsl/tests/parameters-01.glsl11
-rw-r--r--src/glsl/tests/parameters-02.glsl11
-rw-r--r--src/glsl/tests/parameters-03.glsl9
-rw-r--r--src/glsl/tests/qualifier-01.glsl3
-rw-r--r--src/glsl/tests/qualifier-02.glsl2
-rw-r--r--src/glsl/tests/qualifier-03.glsl2
-rw-r--r--src/glsl/tests/qualifier-04.glsl3
-rw-r--r--src/glsl/tests/qualifier-05.glsl3
-rw-r--r--src/glsl/tests/qualifier-06.glsl7
-rw-r--r--src/glsl/tests/qualifier-07.glsl7
-rw-r--r--src/glsl/tests/swiz-01.glsl11
-rw-r--r--src/glsl/tests/swiz-02.glsl11
-rw-r--r--src/glsl/tests/void-01.glsl2
-rw-r--r--src/glut/glx/glut_init.c2
-rw-r--r--src/glx/Makefile5
-rw-r--r--src/mapi/glapi/gen/glX_proto_send.py6
-rw-r--r--src/mapi/glapi/glapi.h116
-rw-r--r--src/mapi/glapi/glapi_dispatch.c11
-rw-r--r--src/mapi/glapi/glapi_entrypoint.c9
-rw-r--r--src/mapi/glapi/glapi_getproc.c9
-rw-r--r--src/mapi/glapi/glapi_nop.c21
-rw-r--r--src/mapi/glapi/glapi_priv.h25
-rw-r--r--src/mapi/glapi/glthread.c2
-rw-r--r--src/mapi/glapi/glthread.h5
-rw-r--r--src/mapi/mapi/entry_x86-64_tls.h4
-rw-r--r--src/mapi/mapi/entry_x86_tls.h2
-rw-r--r--src/mapi/mapi/entry_x86_tsd.h4
-rw-r--r--src/mapi/mapi/mapi.h22
-rw-r--r--src/mapi/mapi/u_current.c93
-rw-r--r--src/mapi/mapi/u_current.h91
-rw-r--r--src/mapi/vgapi/SConscript1
-rw-r--r--src/mesa/Makefile29
-rw-r--r--src/mesa/SConscript33
-rw-r--r--src/mesa/drivers/dri/Makefile.template9
-rw-r--r--src/mesa/drivers/dri/common/dri_util.c13
-rw-r--r--src/mesa/drivers/dri/common/dri_util.h5
-rw-r--r--src/mesa/drivers/dri/i915/i830_context.c1
-rw-r--r--src/mesa/drivers/dri/i915/i915_context.c2
-rw-r--r--src/mesa/drivers/dri/i915/i915_fragprog.c61
-rw-r--r--src/mesa/drivers/dri/i965/Makefile5
-rw-r--r--src/mesa/drivers/dri/i965/brw_context.c9
-rw-r--r--src/mesa/drivers/dri/i965/brw_context.h26
-rw-r--r--src/mesa/drivers/dri/i965/brw_defines.h3
-rw-r--r--src/mesa/drivers/dri/i965/brw_disasm.c80
-rw-r--r--src/mesa/drivers/dri/i965/brw_draw_upload.c4
-rw-r--r--src/mesa/drivers/dri/i965/brw_eu.c6
-rw-r--r--src/mesa/drivers/dri/i965/brw_eu.h10
-rw-r--r--src/mesa/drivers/dri/i965/brw_eu_emit.c63
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.cpp1924
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp365
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp391
-rw-r--r--src/mesa/drivers/dri/i965/brw_misc_state.c4
-rw-r--r--src/mesa/drivers/dri/i965/brw_optimize.c81
-rw-r--r--src/mesa/drivers/dri/i965/brw_program.c36
-rw-r--r--src/mesa/drivers/dri/i965/brw_state.h1
-rw-r--r--src/mesa/drivers/dri/i965/brw_state_upload.c7
-rw-r--r--src/mesa/drivers/dri/i965/brw_structs.h11
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs.c8
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs_emit.c134
-rw-r--r--src/mesa/drivers/dri/i965/brw_vtbl.c1
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm.c27
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm.h21
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_debug.c8
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_emit.c138
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_fp.c11
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_glsl.c26
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_iz.c2
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_pass0.c2
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_pass1.c6
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_pass2.c4
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_state.c18
-rw-r--r--src/mesa/drivers/dri/i965/gen6_cc.c2
-rw-r--r--src/mesa/drivers/dri/i965/gen6_wm_state.c71
-rw-r--r--src/mesa/drivers/dri/intel/intel_buffer_objects.c6
-rw-r--r--src/mesa/drivers/dri/intel/intel_chipset.h4
-rw-r--r--src/mesa/drivers/dri/intel/intel_context.c5
-rw-r--r--src/mesa/drivers/dri/intel/intel_context.h14
-rw-r--r--src/mesa/drivers/dri/intel/intel_extensions.c4
-rw-r--r--src/mesa/drivers/dri/intel/intel_fbo.c18
-rw-r--r--src/mesa/drivers/dri/intel/intel_mipmap_tree.c3
-rw-r--r--src/mesa/drivers/dri/intel/intel_regions.c67
-rw-r--r--src/mesa/drivers/dri/intel/intel_regions.h7
-rw-r--r--src/mesa/drivers/dri/intel/intel_screen.c73
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex.h2
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_driver.c2
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_fbo.c2
-rw-r--r--src/mesa/drivers/dri/r300/compiler/Makefile1
-rwxr-xr-xsrc/mesa/drivers/dri/r300/compiler/SConscript1
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c18
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c231
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_code.h2
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_compiler.h5
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c31
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c17
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_opcodes.h6
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c30
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c117
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c8
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.c128
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.h36
-rw-r--r--src/mesa/drivers/dri/r300/r300_fragprog_common.c1
-rw-r--r--src/mesa/drivers/dri/r600/Makefile9
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_chip.c1289
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_chip.h516
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_context.c106
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_context.h (renamed from src/mesa/slang/slang_link.h)25
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_diff.h335
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_fragprog.c817
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_fragprog.h77
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_ioctl.c (renamed from src/mesa/slang/slang_log.h)58
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_ioctl.h (renamed from src/mesa/slang/slang_mem.h)45
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_off.h881
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_oglprog.c193
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_oglprog.h (renamed from src/mesa/slang/slang_emit.h)38
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_render.c937
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_sq.h735
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_state.c1878
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_state.h47
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_tex.c1551
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_tex.h38
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_vertprog.c736
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_vertprog.h109
-rw-r--r--src/mesa/drivers/dri/r600/r600_blit.c9
-rw-r--r--src/mesa/drivers/dri/r600/r600_cmdbuf.c9
-rw-r--r--src/mesa/drivers/dri/r600/r600_cmdbuf.h40
-rw-r--r--src/mesa/drivers/dri/r600/r600_context.c89
-rw-r--r--src/mesa/drivers/dri/r600/r600_context.h50
-rw-r--r--src/mesa/drivers/dri/r600/r600_emit.c65
-rw-r--r--src/mesa/drivers/dri/r600/r600_emit.h10
-rw-r--r--src/mesa/drivers/dri/r600/r600_texstate.c26
-rw-r--r--src/mesa/drivers/dri/r600/r700_assembler.c1700
-rw-r--r--src/mesa/drivers/dri/r600/r700_assembler.h31
-rw-r--r--src/mesa/drivers/dri/r600/r700_chip.c135
-rw-r--r--src/mesa/drivers/dri/r600/r700_chip.h7
-rw-r--r--src/mesa/drivers/dri/r600/r700_fragprog.c33
-rw-r--r--src/mesa/drivers/dri/r600/r700_fragprog.h5
-rw-r--r--src/mesa/drivers/dri/r600/r700_oglprog.c21
-rw-r--r--src/mesa/drivers/dri/r600/r700_render.c1
-rw-r--r--src/mesa/drivers/dri/r600/r700_state.c16
-rw-r--r--src/mesa/drivers/dri/r600/r700_vertprog.c55
-rw-r--r--src/mesa/drivers/dri/r600/r700_vertprog.h5
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_chipset.h45
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common_context.c5
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common_context.h2
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_fbo.c4
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c6
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_screen.c57
-rw-r--r--src/mesa/drivers/glslcompiler/Makefile43
-rw-r--r--src/mesa/drivers/glslcompiler/glslcompiler.c436
-rw-r--r--src/mesa/drivers/osmesa/Makefile7
-rw-r--r--src/mesa/drivers/x11/Makefile5
-rw-r--r--src/mesa/main/accum.h2
-rw-r--r--src/mesa/main/attrib.h2
-rw-r--r--src/mesa/main/bufferobj.c22
-rw-r--r--src/mesa/main/colortab.h2
-rw-r--r--src/mesa/main/compiler.h5
-rw-r--r--src/mesa/main/context.c31
-rw-r--r--src/mesa/main/convolve.h2
-rw-r--r--src/mesa/main/core.h66
-rw-r--r--src/mesa/main/dd.h51
-rw-r--r--src/mesa/main/depthstencil.c4
-rw-r--r--src/mesa/main/dlist.c10
-rw-r--r--src/mesa/main/dlist.h2
-rw-r--r--src/mesa/main/es_generator.py10
-rw-r--r--src/mesa/main/extensions.c2
-rw-r--r--src/mesa/main/fbobject.c2
-rw-r--r--src/mesa/main/feedback.h2
-rw-r--r--src/mesa/main/formats.c12
-rw-r--r--src/mesa/main/formats.h3
-rw-r--r--src/mesa/main/framebuffer.c4
-rw-r--r--src/mesa/main/get.c18
-rw-r--r--src/mesa/main/getstring.c4
-rw-r--r--src/mesa/main/imports.h52
-rw-r--r--src/mesa/main/mipmap.c17
-rw-r--r--src/mesa/main/mtypes.h56
-rw-r--r--src/mesa/main/querymatrix.c3
-rw-r--r--src/mesa/main/shaderapi.c12
-rw-r--r--src/mesa/main/shaderobj.c60
-rw-r--r--src/mesa/main/shaderobj.h29
-rw-r--r--src/mesa/main/shared.c4
-rw-r--r--src/mesa/main/texcompress_s3tc.c1
-rw-r--r--src/mesa/main/transformfeedback.c7
-rw-r--r--src/mesa/main/uniforms.c108
-rw-r--r--src/mesa/main/uniforms.h15
-rw-r--r--src/mesa/program/hash_table.c31
-rw-r--r--src/mesa/program/hash_table.h35
-rw-r--r--src/mesa/program/ir_to_mesa.cpp2796
-rw-r--r--src/mesa/program/ir_to_mesa.h38
-rw-r--r--src/mesa/program/prog_execute.c29
-rw-r--r--src/mesa/program/prog_instruction.h2
-rw-r--r--src/mesa/program/prog_optimize.c84
-rw-r--r--src/mesa/program/prog_parameter.c96
-rw-r--r--src/mesa/program/prog_parameter.h16
-rw-r--r--src/mesa/program/prog_print.c38
-rw-r--r--src/mesa/program/prog_print.h7
-rw-r--r--src/mesa/program/prog_uniform.c4
-rw-r--r--src/mesa/program/prog_uniform.h5
-rw-r--r--src/mesa/program/symbol_table.c59
-rw-r--r--src/mesa/program/symbol_table.h3
-rw-r--r--src/mesa/slang/descrip.mms67
-rw-r--r--src/mesa/slang/library/.gitignore1
-rw-r--r--src/mesa/slang/library/Makefile54
-rw-r--r--src/mesa/slang/library/SConscript62
-rw-r--r--src/mesa/slang/library/slang_120_core.gc1978
-rw-r--r--src/mesa/slang/library/slang_builtin_120_common.gc200
-rw-r--r--src/mesa/slang/library/slang_common_builtin.gc1887
-rw-r--r--src/mesa/slang/library/slang_core.gc2619
-rw-r--r--src/mesa/slang/library/slang_fragment_builtin.gc299
-rw-r--r--src/mesa/slang/library/slang_geometry_builtin.gc55
-rw-r--r--src/mesa/slang/library/slang_vertex_builtin.gc210
-rw-r--r--src/mesa/slang/slang_builtin.c1018
-rw-r--r--src/mesa/slang/slang_builtin.h68
-rw-r--r--src/mesa/slang/slang_codegen.c5410
-rw-r--r--src/mesa/slang/slang_codegen.h77
-rw-r--r--src/mesa/slang/slang_compile.c3103
-rw-r--r--src/mesa/slang/slang_compile.h103
-rw-r--r--src/mesa/slang/slang_compile_function.c262
-rw-r--r--src/mesa/slang/slang_compile_function.h100
-rw-r--r--src/mesa/slang/slang_compile_operation.c334
-rw-r--r--src/mesa/slang/slang_compile_operation.h229
-rw-r--r--src/mesa/slang/slang_compile_struct.c174
-rw-r--r--src/mesa/slang/slang_compile_struct.h69
-rw-r--r--src/mesa/slang/slang_compile_variable.c247
-rw-r--r--src/mesa/slang/slang_compile_variable.h92
-rw-r--r--src/mesa/slang/slang_emit.c2686
-rw-r--r--src/mesa/slang/slang_ir.c534
-rw-r--r--src/mesa/slang/slang_ir.h293
-rw-r--r--src/mesa/slang/slang_label.c106
-rw-r--r--src/mesa/slang/slang_label.h44
-rw-r--r--src/mesa/slang/slang_link.c1287
-rw-r--r--src/mesa/slang/slang_log.c133
-rw-r--r--src/mesa/slang/slang_mem.c243
-rw-r--r--src/mesa/slang/slang_print.c883
-rw-r--r--src/mesa/slang/slang_print.h35
-rw-r--r--src/mesa/slang/slang_simplify.c527
-rw-r--r--src/mesa/slang/slang_simplify.h57
-rw-r--r--src/mesa/slang/slang_storage.c321
-rw-r--r--src/mesa/slang/slang_storage.h139
-rw-r--r--src/mesa/slang/slang_typeinfo.c1177
-rw-r--r--src/mesa/slang/slang_typeinfo.h265
-rw-r--r--src/mesa/slang/slang_utility.c228
-rw-r--r--src/mesa/slang/slang_utility.h102
-rw-r--r--src/mesa/slang/slang_vartable.c362
-rw-r--r--src/mesa/slang/slang_vartable.h45
-rw-r--r--src/mesa/sources.mak40
-rw-r--r--src/mesa/state_tracker/st_cb_accum.h2
-rw-r--r--src/mesa/state_tracker/st_cb_bitmap.c30
-rw-r--r--src/mesa/state_tracker/st_cb_blit.c47
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c44
-rw-r--r--src/mesa/state_tracker/st_cb_eglimage.c3
-rw-r--r--src/mesa/state_tracker/st_cb_fbo.c28
-rw-r--r--src/mesa/state_tracker/st_cb_fbo.h5
-rw-r--r--src/mesa/state_tracker/st_cb_readpixels.c31
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c14
-rw-r--r--src/mesa/state_tracker/st_context.c5
-rw-r--r--src/mesa/state_tracker/st_context.h3
-rw-r--r--src/mesa/state_tracker/st_draw.c3
-rw-r--r--src/mesa/state_tracker/st_draw_feedback.c45
-rw-r--r--src/mesa/state_tracker/st_extensions.c7
-rw-r--r--src/mesa/state_tracker/st_format.c5
-rw-r--r--src/mesa/state_tracker/st_manager.c31
-rw-r--r--src/mesa/state_tracker/st_mesa_to_tgsi.c3
-rw-r--r--src/mesa/state_tracker/st_program.c8
-rw-r--r--src/mesa/state_tracker/st_texture.c2
-rw-r--r--src/mesa/swrast/s_context.c2
-rw-r--r--src/mesa/vbo/vbo_exec_array.c4
-rw-r--r--src/mesa/x86/3dnow.h2
-rw-r--r--src/mesa/x86/common_x86.c49
-rw-r--r--src/mesa/x86/mmx.h3
-rw-r--r--src/mesa/x86/sse.h2
-rw-r--r--src/mesa/x86/x86_xform.c37
-rw-r--r--src/talloc/SConscript20
-rw-r--r--src/talloc/gpl-3.0.txt674
-rw-r--r--src/talloc/lgpl-3.0.txt165
-rw-r--r--src/talloc/talloc.c2034
-rw-r--r--src/talloc/talloc.def63
-rw-r--r--src/talloc/talloc.h202
-rw-r--r--src/talloc/talloc_guide.txt757
1047 files changed, 115776 insertions, 47945 deletions
diff --git a/src/SConscript b/src/SConscript
index 2b46186f98..c3e34be6f7 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -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')
diff --git a/src/egl/docs/EGL_MESA_screen_surface b/src/egl/docs/EGL_MESA_screen_surface
index 6beb4ce88e..698a240578 100644
--- a/src/egl/docs/EGL_MESA_screen_surface
+++ b/src/egl/docs/EGL_MESA_screen_surface
@@ -14,7 +14,7 @@ Contact
Status
- Preliminary - totally subject to change.
+ Obsolete.
Version
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index efb93bcf06..2b78bcc763 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -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;
@@ -1621,6 +1623,96 @@ dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
}
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,
EGLClientBuffer buffer, const EGLint *attr_list)
@@ -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;
diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile
index 41d301fc14..d92fbf6d9a 100644
--- a/src/egl/main/Makefile
+++ b/src/egl/main/Makefile
@@ -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)
diff --git a/src/egl/main/SConscript b/src/egl/main/SConscript
index 3d7ae3a8e4..06846475ba 100644
--- a/src/egl/main/SConscript
+++ b/src/egl/main/SConscript
@@ -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
index 0000000000..0cfe920e0e
--- /dev/null
+++ b/src/egl/main/egl.def
@@ -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
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 4dc8707cfb..31c5419bbc 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -68,6 +68,7 @@
#include "eglscreen.h"
#include "eglmode.h"
#include "eglimage.h"
+#include "eglsync.h"
/**
@@ -126,6 +127,8 @@
#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 },
@@ -834,6 +894,10 @@ eglGetProcAddress(const char *procname)
#ifdef EGL_NOK_swap_region
{ "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK },
#endif
+#ifdef EGL_MESA_drm_image
+ { "eglCreateDRMImageMESA", (_EGLProc) eglCreateDRMImageMESA },
+ { "eglExportDRMImageMESA", (_EGLProc) eglExportDRMImageMESA },
+#endif
{ NULL, NULL }
};
EGLint i;
@@ -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
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
index d8c8b49a49..127becc9ac 100644
--- a/src/egl/main/eglapi.h
+++ b/src/egl/main/eglapi.h
@@ -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 */
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
index ea8e47d02b..01e7144d40 100644
--- a/src/egl/main/eglconfig.c
+++ b/src/egl/main/eglconfig.c
@@ -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;
}
}
diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c
index 9fc529613e..e72664c23c 100644
--- a/src/egl/main/eglcontext.c
+++ b/src/egl/main/eglcontext.c
@@ -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");
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index a2cee08bf6..3863cce010 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -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;
diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c
index 8fc9e792b0..67f1d3dbaa 100644
--- a/src/egl/main/egldriver.c
+++ b/src/egl/main/egldriver.c
@@ -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 */
}
diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
index 985d1e0069..eb3dde1fb4 100644
--- a/src/egl/main/eglmisc.c
+++ b/src/egl/main/eglmisc.c
@@ -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
index 0000000000..b6c62d0087
--- /dev/null
+++ b/src/egl/main/eglsync.c
@@ -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
index 0000000000..25c467175e
--- /dev/null
+++ b/src/egl/main/eglsync.h
@@ -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 */
diff --git a/src/egl/main/egltypedefs.h b/src/egl/main/egltypedefs.h
index 0e29e9aa47..b65f3b72ae 100644
--- a/src/egl/main/egltypedefs.h
+++ b/src/egl/main/egltypedefs.h
@@ -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 */
diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile
index 9544e90a96..eb86d83d2a 100644
--- a/src/gallium/auxiliary/Makefile
+++ b/src/gallium/auxiliary/Makefile
@@ -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
diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript
index 3124e20ce8..6210ada990 100644
--- a/src/gallium/auxiliary/SConscript
+++ b/src/gallium/auxiliary/SConscript
@@ -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
index 0000000000..958ed20dc8
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_cliptest_tmp.h
@@ -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
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index 995b675b9a..937b093479 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -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"
@@ -41,6 +42,25 @@
#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);
diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h
index 116716af6f..4c780e4dcb 100644
--- a/src/gallium/auxiliary/draw/draw_context.h
+++ b/src/gallium/auxiliary/draw/draw_context.h
@@ -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 );
diff --git a/src/gallium/auxiliary/draw/draw_decompose_tmp.h b/src/gallium/auxiliary/draw/draw_decompose_tmp.h
index a52d2b5058..a142563af9 100644
--- a/src/gallium/auxiliary/draw/draw_decompose_tmp.h
+++ b/src/gallium/auxiliary/draw/draw_decompose_tmp.h
@@ -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);
diff --git a/src/gallium/auxiliary/draw/draw_gs.c b/src/gallium/auxiliary/draw/draw_gs.c
index 4a1013e79a..50a03ac95a 100644
--- a/src/gallium/auxiliary/draw/draw_gs.c
+++ b/src/gallium/auxiliary/draw/draw_gs.c
@@ -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;
diff --git a/src/gallium/auxiliary/draw/draw_gs_tmp.h b/src/gallium/auxiliary/draw/draw_gs_tmp.h
index 4a17af0dea..de7b02655a 100644
--- a/src/gallium/auxiliary/draw/draw_gs_tmp.h
+++ b/src/gallium/auxiliary/draw/draw_gs_tmp.h
@@ -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) { \
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index 8d53601d19..8759c38cab 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -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
diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h
index 4addb47d2d..6196b2f983 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.h
+++ b/src/gallium/auxiliary/draw/draw_llvm.h
@@ -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,
diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c
index 58995e0724..6206197dae 100644
--- a/src/gallium/auxiliary/draw/draw_pipe.c
+++ b/src/gallium/auxiliary/draw/draw_pipe.c
@@ -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);
diff --git a/src/gallium/auxiliary/draw/draw_pipe_validate.c b/src/gallium/auxiliary/draw/draw_pipe_validate.c
index eafa29276f..8b92543987 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_validate.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_validate.c
@@ -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;
diff --git a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
index 3c93c9014a..58c5858734 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
@@ -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;
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 397d4bf653..362f563ba6 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -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,
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index 248927505d..f44bf2507c 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -39,25 +39,14 @@
#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);
}
}
diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h
index 44356fba4c..5fbb424291 100644
--- a/src/gallium/auxiliary/draw/draw_pt.h
+++ b/src/gallium/auxiliary/draw/draw_pt.h
@@ -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
index 88f4d9f495..0000000000
--- a/src/gallium/auxiliary/draw/draw_pt_elts.c
+++ /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;
- }
-}
diff --git a/src/gallium/auxiliary/draw/draw_pt_emit.c b/src/gallium/auxiliary/draw/draw_pt_emit.c
index 5568fbb9f8..c8dfc16911 100644
--- a/src/gallium/auxiliary/draw/draw_pt_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_emit.c
@@ -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...
*/
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
index 5c8af17c8e..e706b7796f 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
@@ -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 ))
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
index b8270280b6..7c198c6026 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
@@ -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 ))
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
index 5b16c3788e..b72fd61245 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
@@ -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;
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
index 4b99bee86a..77291e304e 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
@@ -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;
diff --git a/src/gallium/auxiliary/draw/draw_pt_post_vs.c b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
index 308f927b77..769409cfd6 100644
--- a/src/gallium/auxiliary/draw/draw_pt_post_vs.c
+++ b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
@@ -26,14 +26,26 @@
**************************************************************************/
#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;
}
}
diff --git a/src/gallium/auxiliary/draw/draw_pt_so_emit.c b/src/gallium/auxiliary/draw/draw_pt_so_emit.c
index f7f4f24d35..c86bdd99a3 100644
--- a/src/gallium/auxiliary/draw/draw_pt_so_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_so_emit.c
@@ -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"
diff --git a/src/gallium/auxiliary/draw/draw_pt_util.c b/src/gallium/auxiliary/draw/draw_pt_util.c
index 182a597cca..513bbbed21 100644
--- a/src/gallium/auxiliary/draw/draw_pt_util.c
+++ b/src/gallium/auxiliary/draw/draw_pt_util.c
@@ -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
index cd7bb7bf25..0000000000
--- a/src/gallium/auxiliary/draw/draw_pt_varray.c
+++ /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
index 7c722457c3..0000000000
--- a/src/gallium/auxiliary/draw/draw_pt_varray_tmp.h
+++ /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
index 55e43b2a71..0000000000
--- a/src/gallium/auxiliary/draw/draw_pt_varray_tmp_linear.h
+++ /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
index a848b54f7d..0000000000
--- a/src/gallium/auxiliary/draw/draw_pt_vcache.c
+++ /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
index 1a3748d5f0..0000000000
--- a/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h
+++ /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
index 0000000000..a687525309
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_vsplit.c
@@ -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
index 0000000000..3f66f962e1
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h
@@ -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
diff --git a/src/gallium/auxiliary/draw/draw_so_emit_tmp.h b/src/gallium/auxiliary/draw/draw_so_emit_tmp.h
index 6d8937a0b4..7fafde9d5e 100644
--- a/src/gallium/auxiliary/draw/draw_so_emit_tmp.h
+++ b/src/gallium/auxiliary/draw/draw_so_emit_tmp.h
@@ -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
index 0000000000..47defc62b9
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_split_tmp.h
@@ -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
diff --git a/src/gallium/auxiliary/draw/draw_vs_llvm.c b/src/gallium/auxiliary/draw/draw_vs_llvm.c
index d13ad24fff..fa9992db78 100644
--- a/src/gallium/auxiliary/draw/draw_vs_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_vs_llvm.c
@@ -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;
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
index 7b35dd4bb4..e0d30be98d 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
@@ -59,14 +59,6 @@
#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);
}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_debug.c b/src/gallium/auxiliary/gallivm/lp_bld_debug.c
index 39dfc51e50..d3a5afff8c 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_debug.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_debug.c
@@ -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;
}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
index 247cb83ce6..92123e09d3 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
@@ -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 &&
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp b/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp
index 6d5410d970..48baf7c425 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp
+++ b/src/gallium/auxiliary/gallivm/lp_bld_misc.cpp
@@ -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;
}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_pack.h b/src/gallium/auxiliary/gallivm/lp_bld_pack.h
index e470082b97..e947b90d16 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_pack.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_pack.h
@@ -37,6 +37,8 @@
#define LP_BLD_PACK_H
+#include "pipe/p_compiler.h"
+
#include "gallivm/lp_bld.h"
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
index 0fd014ab9b..259b1142e3 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
@@ -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;
@@ -124,6 +124,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.
*
* x, y, z, y_stride, z_stride are vectors, and they refer to pixels.
@@ -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;
}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
index 5b8f478094..caafc4eca0 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
@@ -36,6 +36,8 @@
#define LP_BLD_SAMPLE_H
+#include "pipe/p_format.h"
+
#include "gallivm/lp_bld.h"
struct pipe_resource;
@@ -147,6 +149,15 @@ lp_sampler_static_state(struct lp_sampler_static_state *state,
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,
LLVMValueRef x,
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
index 806c7d56a8..1f39d9c98b 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
@@ -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:
@@ -322,59 +323,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.
*/
static LLVMValueRef
@@ -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 &&
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
index 0aa64affac..0e07f7f3f3 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
@@ -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:
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_type.h b/src/gallium/auxiliary/gallivm/lp_bld_type.h
index 3ffe916f8e..fec1d3dfbc 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_type.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_type.h
@@ -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
index 0000000000..3c55fc00d9
--- /dev/null
+++ b/src/gallium/auxiliary/os/os_stream.c
@@ -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;
+}
diff --git a/src/gallium/auxiliary/os/os_stream.h b/src/gallium/auxiliary/os/os_stream.h
index 693a0621e2..6c6050bb02 100644
--- a/src/gallium/auxiliary/os/os_stream.h
+++ b/src/gallium/auxiliary/os/os_stream.h
@@ -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_ */
diff --git a/src/gallium/auxiliary/os/os_stream_log.c b/src/gallium/auxiliary/os/os_stream_log.c
index 7cc2028a22..b01377c346 100644
--- a/src/gallium/auxiliary/os/os_stream_log.c
+++ b/src/gallium/auxiliary/os/os_stream_log.c
@@ -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,
};
diff --git a/src/gallium/auxiliary/os/os_stream_null.c b/src/gallium/auxiliary/os/os_stream_null.c
index 128c4e8f0e..a549a789e6 100644
--- a/src/gallium/auxiliary/os/os_stream_null.c
+++ b/src/gallium/auxiliary/os/os_stream_null.c
@@ -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
};
diff --git a/src/gallium/auxiliary/os/os_stream_stdc.c b/src/gallium/auxiliary/os/os_stream_stdc.c
index 9e7ed71107..37e7d063e2 100644
--- a/src/gallium/auxiliary/os/os_stream_stdc.c
+++ b/src/gallium/auxiliary/os/os_stream_stdc.c
@@ -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)
diff --git a/src/gallium/auxiliary/os/os_stream_str.c b/src/gallium/auxiliary/os/os_stream_str.c
index b5c7270d2a..be9478b2a1 100644
--- a/src/gallium/auxiliary/os/os_stream_str.c
+++ b/src/gallium/auxiliary/os/os_stream_str.c
@@ -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)
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
index cec2524da2..2ef02160f2 100644
--- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
@@ -50,8 +50,7 @@
#define PB_BUFMGR_H_
-#include "pipe/p_compiler.h"
-#include "pipe/p_defines.h"
+#include "pb_buffer.h"
#ifdef __cplusplus
diff --git a/src/gallium/auxiliary/rtasm/rtasm_cpu.c b/src/gallium/auxiliary/rtasm/rtasm_cpu.c
index 2e15751e50..0461c81550 100644
--- a/src/gallium/auxiliary/rtasm/rtasm_cpu.c
+++ b/src/gallium/auxiliary/rtasm/rtasm_cpu.c
@@ -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;
diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c
index 9f70b73698..75b0f6a68e 100644
--- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c
+++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c
@@ -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 )
diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.h b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h
index 6208e8f707..2b9678b176 100644
--- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.h
+++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h
@@ -24,22 +24,31 @@
#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 );
diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.h b/src/gallium/auxiliary/tgsi/tgsi_dump.h
index 4cd27317b3..dd78b36100 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_dump.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_dump.h
@@ -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
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
index 298f3d0a8b..0757f05dfa 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -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);
diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.h b/src/gallium/auxiliary/tgsi/tgsi_info.h
index 50248884fd..1992d11bbe 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_info.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_info.h
@@ -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
diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.c b/src/gallium/auxiliary/tgsi/tgsi_parse.c
index db9a342220..1891203abe 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_parse.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_parse.c
@@ -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");
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.h b/src/gallium/auxiliary/tgsi/tgsi_parse.h
index 36de8807b4..d4df585176 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_parse.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_parse.h
@@ -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);
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.h b/src/gallium/auxiliary/tgsi/tgsi_sse2.h
index d81ee3d00e..00aa8b84fe 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_sse2.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.h
@@ -32,9 +32,12 @@
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(
diff --git a/src/gallium/auxiliary/translate/translate.c b/src/gallium/auxiliary/translate/translate.c
index fe638e211f..73287b667d 100644
--- a/src/gallium/auxiliary/translate/translate.c
+++ b/src/gallium/auxiliary/translate/translate.c
@@ -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;
diff --git a/src/gallium/auxiliary/translate/translate.h b/src/gallium/auxiliary/translate/translate.h
index eb6f2cc486..a75380228b 100644
--- a/src/gallium/auxiliary/translate/translate.h
+++ b/src/gallium/auxiliary/translate/translate.h
@@ -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,
diff --git a/src/gallium/auxiliary/translate/translate_generic.c b/src/gallium/auxiliary/translate/translate_generic.c
index 42cfd763e9..ad809db720 100644
--- a/src/gallium/auxiliary/translate/translate_generic.c
+++ b/src/gallium/auxiliary/translate/translate_generic.c
@@ -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;
diff --git a/src/gallium/auxiliary/translate/translate_sse.c b/src/gallium/auxiliary/translate/translate_sse.c
index ef3aa674a3..f8bf5b4669 100644
--- a/src/gallium/auxiliary/translate/translate_sse.c
+++ b/src/gallium/auxiliary/translate/translate_sse.c
@@ -30,11 +30,12 @@
#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"
@@ -46,21 +47,9 @@
#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;
diff --git a/src/gallium/auxiliary/util/u_bitmask.h b/src/gallium/auxiliary/util/u_bitmask.h
index 87f1110296..98b85ddecd 100644
--- a/src/gallium/auxiliary/util/u_bitmask.h
+++ b/src/gallium/auxiliary/util/u_bitmask.h
@@ -36,6 +36,9 @@
#define U_HANDLE_BITMASK_H_
+#include "pipe/p_compiler.h"
+
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c
index 97fa99ec65..dfb142b9e1 100644
--- a/src/gallium/auxiliary/util/u_blit.c
+++ b/src/gallium/auxiliary/util/u_blit.c
@@ -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);
diff --git a/src/gallium/auxiliary/util/u_blit.h b/src/gallium/auxiliary/util/u_blit.h
index ef95134f32..b8a0dfce13 100644
--- a/src/gallium/auxiliary/util/u_blit.h
+++ b/src/gallium/auxiliary/util/u_blit.h
@@ -30,18 +30,20 @@
#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 *
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index b5b86b7214..f93ef26ae7 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -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,
diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h
index f316587dea..e33d2e283f 100644
--- a/src/gallium/auxiliary/util/u_blitter.h
+++ b/src/gallium/auxiliary/util/u_blitter.h
@@ -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
diff --git a/src/gallium/auxiliary/util/u_cpu_detect.c b/src/gallium/auxiliary/util/u_cpu_detect.c
index 5056351307..32519b148b 100644
--- a/src/gallium/auxiliary/util/u_cpu_detect.c
+++ b/src/gallium/auxiliary/util/u_cpu_detect.c
@@ -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
index 0000000000..1c90ff3106
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_describe.c
@@ -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
index 0000000000..26d1f803bf
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_describe.h
@@ -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
index 0000000000..40a26c9c69
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_refcnt.c
@@ -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
index 0000000000..bea2d1c478
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_debug_refcnt.h
@@ -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_ */
diff --git a/src/gallium/auxiliary/util/u_debug_symbol.c b/src/gallium/auxiliary/util/u_debug_symbol.c
index 6e250575d6..332952af88 100644
--- a/src/gallium/auxiliary/util/u_debug_symbol.c
+++ b/src/gallium/auxiliary/util/u_debug_symbol.c
@@ -33,9 +33,12 @@
*/
#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;
}
diff --git a/src/gallium/auxiliary/util/u_debug_symbol.h b/src/gallium/auxiliary/util/u_debug_symbol.h
index 021586987b..b247706c2a 100644
--- a/src/gallium/auxiliary/util/u_debug_symbol.h
+++ b/src/gallium/auxiliary/util/u_debug_symbol.h
@@ -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
}
diff --git a/src/gallium/auxiliary/util/u_dirty_surfaces.h b/src/gallium/auxiliary/util/u_dirty_surfaces.h
index 99f260bf96..fd1bbe5ffd 100644
--- a/src/gallium/auxiliary/util/u_dirty_surfaces.h
+++ b/src/gallium/auxiliary/util/u_dirty_surfaces.h
@@ -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
diff --git a/src/gallium/auxiliary/util/u_draw.h b/src/gallium/auxiliary/util/u_draw.h
index 2a91ea0f9a..f06d09ef91 100644
--- a/src/gallium/auxiliary/util/u_draw.h
+++ b/src/gallium/auxiliary/util/u_draw.h
@@ -31,6 +31,7 @@
#include "pipe/p_compiler.h"
#include "pipe/p_context.h"
+#include "pipe/p_state.h"
static INLINE void
diff --git a/src/gallium/auxiliary/util/u_dynarray.h b/src/gallium/auxiliary/util/u_dynarray.h
index 9d1c1713a7..980cadf22d 100644
--- a/src/gallium/auxiliary/util/u_dynarray.h
+++ b/src/gallium/auxiliary/util/u_dynarray.h
@@ -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 */
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c
index b7fe2d3003..6a931a9581 100644
--- a/src/gallium/auxiliary/util/u_gen_mipmap.c
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.c
@@ -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;
diff --git a/src/gallium/auxiliary/util/u_inlines.h b/src/gallium/auxiliary/util/u_inlines.h
index 540305c146..78473bf35a 100644
--- a/src/gallium/auxiliary/util/u_inlines.h
+++ b/src/gallium/auxiliary/util/u_inlines.h
@@ -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
index 0000000000..2f6f41ba84
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_linkage.c
@@ -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
index 0000000000..4720e0ee60
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_linkage.h
@@ -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_ */
diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h
index fe19466436..69a7681494 100644
--- a/src/gallium/auxiliary/util/u_math.h
+++ b/src/gallium/auxiliary/util/u_math.h
@@ -361,16 +361,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.
diff --git a/src/gallium/auxiliary/util/u_pack_color.h b/src/gallium/auxiliary/util/u_pack_color.h
index 5f113f742b..aae8b8bdf1 100644
--- a/src/gallium/auxiliary/util/u_pack_color.h
+++ b/src/gallium/auxiliary/util/u_pack_color.h
@@ -42,12 +42,18 @@
#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];
};
/**
diff --git a/src/gallium/auxiliary/util/u_rect.c b/src/gallium/auxiliary/util/u_rect.c
index 9bbcf1c8c4..56fcfac069 100644
--- a/src/gallium/auxiliary/util/u_rect.c
+++ b/src/gallium/auxiliary/util/u_rect.c
@@ -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;
}
}
diff --git a/src/gallium/auxiliary/util/u_rect.h b/src/gallium/auxiliary/util/u_rect.h
index 40d57e662d..4cb90d3c31 100644
--- a/src/gallium/auxiliary/util/u_rect.h
+++ b/src/gallium/auxiliary/util/u_rect.h
@@ -26,17 +26,67 @@
**************************************************************************/
-/**
- * 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 */
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c
index 5b682f496c..58ef68377f 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.c
+++ b/src/gallium/auxiliary/util/u_simple_shaders.c
@@ -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"
diff --git a/src/gallium/auxiliary/util/u_split_prim.h b/src/gallium/auxiliary/util/u_split_prim.h
index 206e1ec311..7f80fc1270 100644
--- a/src/gallium/auxiliary/util/u_split_prim.h
+++ b/src/gallium/auxiliary/util/u_split_prim.h
@@ -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 */
diff --git a/src/gallium/auxiliary/util/u_staging.c b/src/gallium/auxiliary/util/u_staging.c
index 607c31f5ee..c5d68f8df8 100644
--- a/src/gallium/auxiliary/util/u_staging.c
+++ b/src/gallium/auxiliary/util/u_staging.c
@@ -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;
diff --git a/src/gallium/auxiliary/util/u_staging.h b/src/gallium/auxiliary/util/u_staging.h
index 602faa2971..1aab78cc88 100644
--- a/src/gallium/auxiliary/util/u_staging.h
+++ b/src/gallium/auxiliary/util/u_staging.h
@@ -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);
diff --git a/src/gallium/auxiliary/util/u_surface.c b/src/gallium/auxiliary/util/u_surface.c
index cab7691c70..af99163b2e 100644
--- a/src/gallium/auxiliary/util/u_surface.c
+++ b/src/gallium/auxiliary/util/u_surface.c
@@ -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);
diff --git a/src/gallium/auxiliary/util/u_surfaces.c b/src/gallium/auxiliary/util/u_surfaces.c
index 7733ad24d0..404e121995 100644
--- a/src/gallium/auxiliary/util/u_surfaces.c
+++ b/src/gallium/auxiliary/util/u_surfaces.c
@@ -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"
diff --git a/src/gallium/auxiliary/util/u_surfaces.h b/src/gallium/auxiliary/util/u_surfaces.h
index af978c7057..17d8a5d3a5 100644
--- a/src/gallium/auxiliary/util/u_surfaces.h
+++ b/src/gallium/auxiliary/util/u_surfaces.h
@@ -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;
diff --git a/src/gallium/auxiliary/util/u_tile.h b/src/gallium/auxiliary/util/u_tile.h
index 986eee0743..558351d0ce 100644
--- a/src/gallium/auxiliary/util/u_tile.h
+++ b/src/gallium/auxiliary/util/u_tile.h
@@ -29,7 +29,10 @@
#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;
/**
diff --git a/src/gallium/auxiliary/util/u_transfer.h b/src/gallium/auxiliary/util/u_transfer.h
index eb07945d15..e3a38730f2 100644
--- a/src/gallium/auxiliary/util/u_transfer.h
+++ b/src/gallium/auxiliary/util/u_transfer.h
@@ -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,
diff --git a/src/gallium/auxiliary/util/u_upload_mgr.h b/src/gallium/auxiliary/util/u_upload_mgr.h
index a124924fc8..de016df02e 100644
--- a/src/gallium/auxiliary/util/u_upload_mgr.h
+++ b/src/gallium/auxiliary/util/u_upload_mgr.h
@@ -32,11 +32,8 @@
#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,
diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst
index f241411a00..8250c30f2a 100644
--- a/src/gallium/docs/source/context.rst
+++ b/src/gallium/docs/source/context.rst
@@ -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``
diff --git a/src/gallium/docs/source/debugging.rst b/src/gallium/docs/source/debugging.rst
index 42bda5aee9..e081cbf74e 100644
--- a/src/gallium/docs/source/debugging.rst
+++ b/src/gallium/docs/source/debugging.rst
@@ -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.
diff --git a/src/gallium/docs/source/distro.rst b/src/gallium/docs/source/distro.rst
index 70d75b51e6..08c8eab890 100644
--- a/src/gallium/docs/source/distro.rst
+++ b/src/gallium/docs/source/distro.rst
@@ -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
--------------
diff --git a/src/gallium/docs/source/index.rst b/src/gallium/docs/source/index.rst
index 6c19842dac..2a73e3ab59 100644
--- a/src/gallium/docs/source/index.rst
+++ b/src/gallium/docs/source/index.rst
@@ -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
index 0000000000..c8a5766821
--- /dev/null
+++ b/src/gallium/docs/source/resources.rst
@@ -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
diff --git a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c
index 4adef5b8c0..a367fa3fe1 100644
--- a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c
+++ b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c
@@ -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);
}
/*
diff --git a/src/gallium/drivers/cell/ppu/cell_state_vertex.c b/src/gallium/drivers/cell/ppu/cell_state_vertex.c
index 4e3701cd0a..a065d68b5a 100644
--- a/src/gallium/drivers/cell/ppu/cell_state_vertex.c
+++ b/src/gallium/drivers/cell/ppu/cell_state_vertex.c
@@ -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);
}
diff --git a/src/gallium/drivers/galahad/glhd_context.c b/src/gallium/drivers/galahad/glhd_context.c
index fe14a287ef..383c448926 100644
--- a/src/gallium/drivers/galahad/glhd_context.c
+++ b/src/gallium/drivers/galahad/glhd_context.c
@@ -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;
}
diff --git a/src/gallium/drivers/galahad/glhd_screen.c b/src/gallium/drivers/galahad/glhd_screen.c
index 4117485702..75e4c2d82e 100644
--- a/src/gallium/drivers/galahad/glhd_screen.c
+++ b/src/gallium/drivers/galahad/glhd_screen.c
@@ -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;
}
diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c
index 2beb9e3091..847dd6dd47 100644
--- a/src/gallium/drivers/i915/i915_context.c
+++ b/src/gallium/drivers/i915/i915_context.c
@@ -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);
}
diff --git a/src/gallium/drivers/i915/i915_resource_texture.c b/src/gallium/drivers/i915/i915_resource_texture.c
index 752ddaae7b..c5c6179b16 100644
--- a/src/gallium/drivers/i915/i915_resource_texture.c
+++ b/src/gallium/drivers/i915/i915_resource_texture.c
@@ -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;
diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c
index 385c3b2d2d..bbfcff6bc4 100644
--- a/src/gallium/drivers/i915/i915_state.c
+++ b/src/gallium/drivers/i915/i915_state.c
@@ -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
diff --git a/src/gallium/drivers/i965/brw_batchbuffer.c b/src/gallium/drivers/i965/brw_batchbuffer.c
index 8b3f46f2c1..e80067f3b1 100644
--- a/src/gallium/drivers/i965/brw_batchbuffer.c
+++ b/src/gallium/drivers/i965/brw_batchbuffer.c
@@ -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;
}
diff --git a/src/gallium/drivers/i965/brw_resource_texture.c b/src/gallium/drivers/i965/brw_resource_texture.c
index ffd0f38672..3860d18a7a 100644
--- a/src/gallium/drivers/i965/brw_resource_texture.c
+++ b/src/gallium/drivers/i965/brw_resource_texture.c
@@ -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;
diff --git a/src/gallium/drivers/i965/brw_wm_debug.c b/src/gallium/drivers/i965/brw_wm_debug.c
index e2767264e7..1b2aa93bef 100644
--- a/src/gallium/drivers/i965/brw_wm_debug.c
+++ b/src/gallium/drivers/i965/brw_wm_debug.c
@@ -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("?");
}
diff --git a/src/gallium/drivers/llvmpipe/Makefile b/src/gallium/drivers/llvmpipe/Makefile
index 2892b62920..dec874623e 100644
--- a/src/gallium/drivers/llvmpipe/Makefile
+++ b/src/gallium/drivers/llvmpipe/Makefile
@@ -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 \
diff --git a/src/gallium/drivers/llvmpipe/SConscript b/src/gallium/drivers/llvmpipe/SConscript
index 5583fca38e..8d57db72cf 100644
--- a/src/gallium/drivers/llvmpipe/SConscript
+++ b/src/gallium/drivers/llvmpipe/SConscript
@@ -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',
diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c
index 7543bd7b2b..39f2c6085e 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.c
+++ b/src/gallium/drivers/llvmpipe/lp_context.c
@@ -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? */
diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h
index 50f9091c3c..34fa20e204 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_context.h
@@ -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;
diff --git a/src/gallium/drivers/llvmpipe/lp_debug.h b/src/gallium/drivers/llvmpipe/lp_debug.h
index 92fb2b3ee5..a928ee38be 100644
--- a/src/gallium/drivers/llvmpipe/lp_debug.h
+++ b/src/gallium/drivers/llvmpipe/lp_debug.h
@@ -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
diff --git a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
index e73b431cb4..3af5c8d5c5 100644
--- a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
+++ b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
@@ -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);
diff --git a/src/gallium/drivers/llvmpipe/lp_fence.c b/src/gallium/drivers/llvmpipe/lp_fence.c
index f9805e5d68..3a55e76bc3 100644
--- a/src/gallium/drivers/llvmpipe/lp_fence.c
+++ b/src/gallium/drivers/llvmpipe/lp_fence.c
@@ -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,6 +66,9 @@ 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);
@@ -68,82 +76,49 @@ lp_fence_destroy(struct lp_fence *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.
*/
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);
}
+
+
diff --git a/src/gallium/drivers/llvmpipe/lp_fence.h b/src/gallium/drivers/llvmpipe/lp_fence.h
index 13358fb99f..3c59118780 100644
--- a/src/gallium/drivers/llvmpipe/lp_fence.h
+++ b/src/gallium/drivers/llvmpipe/lp_fence.h
@@ -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 */
diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c
index 845292f4ab..e2c723b7a8 100644
--- a/src/gallium/drivers/llvmpipe/lp_flush.c
+++ b/src/gallium/drivers/llvmpipe/lp_flush.c
@@ -31,6 +31,7 @@
#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
#include "util/u_string.h"
#include "draw/draw_context.h"
#include "lp_flush.h"
@@ -45,14 +46,15 @@
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);
}
}
diff --git a/src/gallium/drivers/llvmpipe/lp_flush.h b/src/gallium/drivers/llvmpipe/lp_flush.h
index 7b605681a9..bb538b2bd8 100644
--- a/src/gallium/drivers/llvmpipe/lp_flush.h
+++ b/src/gallium/drivers/llvmpipe/lp_flush.h
@@ -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
diff --git a/src/gallium/drivers/llvmpipe/lp_perf.c b/src/gallium/drivers/llvmpipe/lp_perf.c
index 083e7e30a5..e22532f25c 100644
--- a/src/gallium/drivers/llvmpipe/lp_perf.c
+++ b/src/gallium/drivers/llvmpipe/lp_perf.c
@@ -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);
diff --git a/src/gallium/drivers/llvmpipe/lp_perf.h b/src/gallium/drivers/llvmpipe/lp_perf.h
index 4774f64550..c28652fc30 100644
--- a/src/gallium/drivers/llvmpipe/lp_perf.h
+++ b/src/gallium/drivers/llvmpipe/lp_perf.h
@@ -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
diff --git a/src/gallium/drivers/llvmpipe/lp_query.c b/src/gallium/drivers/llvmpipe/lp_query.c
index 02eeaf6487..67fd797af2 100644
--- a/src/gallium/drivers/llvmpipe/lp_query.c
+++ b/src/gallium/drivers/llvmpipe/lp_query.c
@@ -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);
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 3215d0f652..b1c306bbe9 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -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
/**
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h
index 44319a0ad6..b4564ef33b 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast.h
@@ -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
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_tri.c b/src/gallium/drivers/llvmpipe/lp_rast_tri.c
index 980c18c024..dbaa8e023a 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_tri.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast_tri.c
@@ -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);
+ }
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h b/src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h
index 43f72d8ca8..99a0bae45d 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_tri_tmp.h
@@ -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) {
diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c
index f88a759fe7..15a09b7100 100644
--- a/src/gallium/drivers/llvmpipe/lp_scene.c
+++ b/src/gallium/drivers/llvmpipe/lp_scene.c
@@ -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:
diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c
index 167cb2ee2e..1e65a91fc6 100644
--- a/src/gallium/drivers/llvmpipe/lp_screen.c
+++ b/src/gallium/drivers/llvmpipe/lp_screen.c
@@ -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);
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index 556e571585..3da9097154 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -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);
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h
index 73b1c85325..821ebb1087 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup.h
@@ -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
index 0000000000..95e3e8fffe
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_setup_coef.c
@@ -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/glsl/pp/sl_pp_dict.h b/src/gallium/drivers/llvmpipe/lp_setup_coef.h
index 875217bd30..d68b39c603 100644
--- a/src/glsl/pp/sl_pp_dict.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup_coef.h
@@ -1,8 +1,8 @@
/**************************************************************************
- *
- * Copyright 2009 VMware, Inc.
+ *
+ * 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
@@ -10,68 +10,52 @@
* 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
+ * 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 SL_PP_DICT_H
-#define SL_PP_DICT_H
+/**
+ * The setup code is concerned with point/line/triangle setup and
+ * putting commands/data into the bins.
+ */
-struct sl_pp_context;
-struct sl_pp_dict {
- int all;
+#ifndef LP_SETUP_COEF_H
+#define LP_SETUP_COEF_H
- int require;
- int enable;
- int warn;
- int disable;
- int defined;
+struct lp_tri_info {
- int ___LINE__;
- int ___FILE__;
- int ___VERSION__;
+ float x0_center;
+ float y0_center;
- int optimize;
- int debug;
+ /* turn these into an aligned float[4] */
+ float dy01_ooa;
+ float dy20_ooa;
+ float dx01_ooa;
+ float dx20_ooa;
- int off;
- int on;
+ const float (*v0)[4];
+ const float (*v1)[4];
+ const float (*v2)[4];
- 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;
+ 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);
-int
-sl_pp_dict_init(struct sl_pp_context *context);
-
-#endif /* SL_PP_DICT_H */
+#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
index 0000000000..73fb70599c
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_setup_coef_intrin.c
@@ -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
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h
index a0606f5034..877a492c6d 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h
@@ -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
+
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_line.c b/src/gallium/drivers/llvmpipe/lp_setup_line.c
index be41c44e6f..ce2da55cf4 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_line.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_line.c
@@ -29,19 +29,671 @@
* 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;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_point.c b/src/gallium/drivers/llvmpipe/lp_setup_point.c
index 9f69e6c5ce..6ae318d328 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_point.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_point.c
@@ -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.
@@ -30,17 +30,299 @@
*/
#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;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
index 393533ebee..0180d95090 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
@@ -31,35 +31,15 @@
#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 );
}
diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c
index 77bec4640b..edd723f65f 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_derived.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c
@@ -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);
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index dbca49a2ef..33c1a49efe 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -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);
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.h b/src/gallium/drivers/llvmpipe/lp_state_fs.h
index 37900fc544..33c480010d 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.h
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.h
@@ -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;
diff --git a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c
index afd3e0b21c..0bad7320f3 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c
@@ -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;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_state_vertex.c b/src/gallium/drivers/llvmpipe/lp_state_vertex.c
index d86e66b4fb..fb29423dd3 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_vertex.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_vertex.c
@@ -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
diff --git a/src/gallium/drivers/llvmpipe/lp_surface.c b/src/gallium/drivers/llvmpipe/lp_surface.c
index f761e82850..63ddc669c2 100644
--- a/src/gallium/drivers/llvmpipe/lp_surface.c
+++ b/src/gallium/drivers/llvmpipe/lp_surface.c
@@ -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",
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c
index 25112c10a6..5832ea2744 100644
--- a/src/gallium/drivers/llvmpipe/lp_texture.c
+++ b/src/gallium/drivers/llvmpipe/lp_texture.c
@@ -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.
*/
diff --git a/src/gallium/drivers/nouveau/nouveau_class.h b/src/gallium/drivers/nouveau/nouveau_class.h
index f44979e562..d9f35b4c4b 100644
--- a/src/gallium/drivers/nouveau/nouveau_class.h
+++ b/src/gallium/drivers/nouveau/nouveau_class.h
@@ -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
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c
index 513e5e02bc..ebb21a6e5a 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.c
+++ b/src/gallium/drivers/nouveau/nouveau_screen.c
@@ -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
index b165f7a611..0000000000
--- a/src/gallium/drivers/nouveau/nouveau_util.h
+++ /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
diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c
index 12b5ad106c..dd0e8fd41b 100644
--- a/src/gallium/drivers/nv50/nv50_miptree.c
+++ b/src/gallium/drivers/nv50/nv50_miptree.c
@@ -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;
diff --git a/src/gallium/drivers/nv50/nv50_push.c b/src/gallium/drivers/nv50/nv50_push.c
index 0091927a98..380f69406a 100644
--- a/src/gallium/drivers/nv50/nv50_push.c
+++ b/src/gallium/drivers/nv50/nv50_push.c
@@ -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);
diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c
index 5535818370..658324ec5b 100644
--- a/src/gallium/drivers/nv50/nv50_tex.c
+++ b/src/gallium/drivers/nv50/nv50_tex.c
@@ -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;
diff --git a/src/gallium/drivers/nvfx/Makefile b/src/gallium/drivers/nvfx/Makefile
index c1d57ca396..6cbbad699e 100644
--- a/src/gallium/drivers/nvfx/Makefile
+++ b/src/gallium/drivers/nvfx/Makefile
@@ -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 \
diff --git a/src/gallium/drivers/nvfx/SConscript b/src/gallium/drivers/nvfx/SConscript
index 02d931b10e..80e3ef2257 100644
--- a/src/gallium/drivers/nvfx/SConscript
+++ b/src/gallium/drivers/nvfx/SConscript
@@ -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
index 0000000000..c05312219b
--- /dev/null
+++ b/src/gallium/drivers/nvfx/nv04_2d.c
@@ -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
index 0000000000..e638b8c874
--- /dev/null
+++ b/src/gallium/drivers/nvfx/nv04_2d.h
@@ -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
index 0000000000..3a6787c071
--- /dev/null
+++ b/src/gallium/drivers/nvfx/nv04_2d_loops.h
@@ -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
index 7acbb505df..0000000000
--- a/src/gallium/drivers/nvfx/nv04_surface_2d.c
+++ /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
index 2123c3ed08..0000000000
--- a/src/gallium/drivers/nvfx/nv04_surface_2d.h
+++ /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
diff --git a/src/gallium/drivers/nvfx/nv30_fragtex.c b/src/gallium/drivers/nvfx/nv30_fragtex.c
index dec073ac90..0c3d43fd57 100644
--- a/src/gallium/drivers/nvfx/nv30_fragtex.c
+++ b/src/gallium/drivers/nvfx/nv30_fragtex.c
@@ -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;
diff --git a/src/gallium/drivers/nvfx/nv30_vertprog.h b/src/gallium/drivers/nvfx/nv30_vertprog.h
index ec0444c07f..9a68f5c1fb 100644
--- a/src/gallium/drivers/nvfx/nv30_vertprog.h
+++ b/src/gallium/drivers/nvfx/nv30_vertprog.h
@@ -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)
@@ -111,7 +111,7 @@
#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*/
@@ -125,7 +125,7 @@
#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
@@ -133,7 +133,8 @@
# 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
diff --git a/src/gallium/drivers/nvfx/nv40_fragtex.c b/src/gallium/drivers/nvfx/nv40_fragtex.c
index 0068b1ba54..106ce71a07 100644
--- a/src/gallium/drivers/nvfx/nv40_fragtex.c
+++ b/src/gallium/drivers/nvfx/nv40_fragtex.c
@@ -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);
diff --git a/src/gallium/drivers/nvfx/nv40_vertprog.h b/src/gallium/drivers/nvfx/nv40_vertprog.h
index 7337293bab..3d0a1fe3d1 100644
--- a/src/gallium/drivers/nvfx/nv40_vertprog.h
+++ b/src/gallium/drivers/nvfx/nv40_vertprog.h
@@ -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)
@@ -100,7 +100,7 @@
#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
diff --git a/src/gallium/drivers/nvfx/nvfx_buffer.c b/src/gallium/drivers/nvfx/nvfx_buffer.c
index 05b824b8f7..041099e0e5 100644
--- a/src/gallium/drivers/nvfx/nvfx_buffer.c
+++ b/src/gallium/drivers/nvfx/nvfx_buffer.c
@@ -6,115 +6,39 @@
#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;
+ }
+}
diff --git a/src/gallium/drivers/nvfx/nvfx_context.c b/src/gallium/drivers/nvfx/nvfx_context.c
index 7218abff22..5a2fa14c88 100644
--- a/src/gallium/drivers/nvfx/nvfx_context.c
+++ b/src/gallium/drivers/nvfx/nvfx_context.c
@@ -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;
}
diff --git a/src/gallium/drivers/nvfx/nvfx_context.h b/src/gallium/drivers/nvfx/nvfx_context.h
index 89f94c10bd..4c654bfa8b 100644
--- a/src/gallium/drivers/nvfx/nvfx_context.h
+++ b/src/gallium/drivers/nvfx/nvfx_context.h
@@ -11,8 +11,10 @@
#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"
@@ -42,17 +44,26 @@
#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
diff --git a/src/gallium/drivers/nvfx/nvfx_draw.c b/src/gallium/drivers/nvfx/nvfx_draw.c
index 22cff370b7..2601d5b8e2 100644
--- a/src/gallium/drivers/nvfx/nvfx_draw.c
+++ b/src/gallium/drivers/nvfx/nvfx_draw.c
@@ -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;
diff --git a/src/gallium/drivers/nvfx/nvfx_fragprog.c b/src/gallium/drivers/nvfx/nvfx_fragprog.c
index ee41f03b9b..275672a31f 100644
--- a/src/gallium/drivers/nvfx/nvfx_fragprog.c
+++ b/src/gallium/drivers/nvfx/nvfx_fragprog.c
@@ -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;
+}
diff --git a/src/gallium/drivers/nvfx/nvfx_fragtex.c b/src/gallium/drivers/nvfx/nvfx_fragtex.c
index 0b4a434fec..6503c7afcb 100644
--- a/src/gallium/drivers/nvfx/nvfx_fragtex.c
+++ b/src/gallium/drivers/nvfx/nvfx_fragtex.c
@@ -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)
+};
diff --git a/src/gallium/drivers/nvfx/nvfx_miptree.c b/src/gallium/drivers/nvfx/nvfx_miptree.c
index b5639bb464..0916aaa828 100644
--- a/src/gallium/drivers/nvfx/nvfx_miptree.c
+++ b/src/gallium/drivers/nvfx/nvfx_miptree.c
@@ -2,309 +2,220 @@
#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
index 0000000000..ffe7e98357
--- /dev/null
+++ b/src/gallium/drivers/nvfx/nvfx_push.c
@@ -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);
+ }
+ }
+ }
+}
diff --git a/src/gallium/drivers/nvfx/nvfx_resource.c b/src/gallium/drivers/nvfx/nvfx_resource.c
index 10cdeed2a3..39ae893f1b 100644
--- a/src/gallium/drivers/nvfx/nvfx_resource.c
+++ b/src/gallium/drivers/nvfx/nvfx_resource.c
@@ -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;
}
diff --git a/src/gallium/drivers/nvfx/nvfx_resource.h b/src/gallium/drivers/nvfx/nvfx_resource.h
index a68c14cf3f..583be4de2a 100644
--- a/src/gallium/drivers/nvfx/nvfx_resource.h
+++ b/src/gallium/drivers/nvfx/nvfx_resource.h
@@ -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
diff --git a/src/gallium/drivers/nvfx/nvfx_screen.c b/src/gallium/drivers/nvfx/nvfx_screen.c
index f2525ccb38..65ca265d45 100644
--- a/src/gallium/drivers/nvfx/nvfx_screen.c
+++ b/src/gallium/drivers/nvfx/nvfx_screen.c
@@ -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);
diff --git a/src/gallium/drivers/nvfx/nvfx_screen.h b/src/gallium/drivers/nvfx/nvfx_screen.h
index 5e1c3945ae..1b79235ae0 100644
--- a/src/gallium/drivers/nvfx/nvfx_screen.h
+++ b/src/gallium/drivers/nvfx/nvfx_screen.h
@@ -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
diff --git a/src/gallium/drivers/nvfx/nvfx_shader.h b/src/gallium/drivers/nvfx/nvfx_shader.h
index 50830b3916..35006eec3d 100644
--- a/src/gallium/drivers/nvfx/nvfx_shader.h
+++ b/src/gallium/drivers/nvfx/nvfx_shader.h
@@ -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 */
@@ -71,11 +77,58 @@
/*
* 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
@@ -210,6 +263,7 @@
/* 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
@@ -218,10 +272,11 @@
#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
@@ -254,6 +309,7 @@
#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
@@ -263,13 +319,13 @@
#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
@@ -283,9 +339,9 @@
#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)
@@ -323,6 +379,7 @@
#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
@@ -352,51 +409,88 @@
#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
diff --git a/src/gallium/drivers/nvfx/nvfx_state.c b/src/gallium/drivers/nvfx/nvfx_state.c
index cd58e439d7..5bd7dc07f0 100644
--- a/src/gallium/drivers/nvfx/nvfx_state.c
+++ b/src/gallium/drivers/nvfx/nvfx_state.c
@@ -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"
@@ -81,111 +82,6 @@ nvfx_blend_state_delete(struct pipe_context *pipe, void *hwcso)
}
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;
}
diff --git a/src/gallium/drivers/nvfx/nvfx_state.h b/src/gallium/drivers/nvfx/nvfx_state.h
index 9ceb2577ec..e9c1f2c26d 100644
--- a/src/gallium/drivers/nvfx/nvfx_state.h
+++ b/src/gallium/drivers/nvfx/nvfx_state.h
@@ -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
diff --git a/src/gallium/drivers/nvfx/nvfx_state_emit.c b/src/gallium/drivers/nvfx/nvfx_state_emit.c
index f91ae19ecd..390bca8cdb 100644
--- a/src/gallium/drivers/nvfx/nvfx_state_emit.c
+++ b/src/gallium/drivers/nvfx/nvfx_state_emit.c
@@ -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;
diff --git a/src/gallium/drivers/nvfx/nvfx_state_fb.c b/src/gallium/drivers/nvfx/nvfx_state_fb.c
index 360e569f77..3b869d43a1 100644
--- a/src/gallium/drivers/nvfx/nvfx_state_fb.c
+++ b/src/gallium/drivers/nvfx/nvfx_state_fb.c
@@ -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;
}
diff --git a/src/gallium/drivers/nvfx/nvfx_state_stipple.c b/src/gallium/drivers/nvfx/nvfx_state_stipple.c
index 4da968f093..b76e9dd382 100644
--- a/src/gallium/drivers/nvfx/nvfx_state_stipple.c
+++ b/src/gallium/drivers/nvfx/nvfx_state_stipple.c
@@ -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);
}
diff --git a/src/gallium/drivers/nvfx/nvfx_surface.c b/src/gallium/drivers/nvfx/nvfx_surface.c
index a605d2b754..a5931b6e15 100644
--- a/src/gallium/drivers/nvfx/nvfx_surface.c
+++ b/src/gallium/drivers/nvfx/nvfx_surface.c
@@ -26,33 +26,421 @@
*
**************************************************************************/
+#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;
}
diff --git a/src/gallium/drivers/nvfx/nvfx_tex.h b/src/gallium/drivers/nvfx/nvfx_tex.h
index 69187a79e7..34be936a89 100644
--- a/src/gallium/drivers/nvfx/nvfx_tex.h
+++ b/src/gallium/drivers/nvfx/nvfx_tex.h
@@ -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_ */
diff --git a/src/gallium/drivers/nvfx/nvfx_transfer.c b/src/gallium/drivers/nvfx/nvfx_transfer.c
index 9ff0a93d30..7cb47a20f6 100644
--- a/src/gallium/drivers/nvfx/nvfx_transfer.c
+++ b/src/gallium/drivers/nvfx/nvfx_transfer.c
@@ -4,204 +4,218 @@
#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;
}
diff --git a/src/gallium/drivers/nvfx/nvfx_transfer.h b/src/gallium/drivers/nvfx/nvfx_transfer.h
index 3e3317b2c7..20f20d5b0b 100644
--- a/src/gallium/drivers/nvfx/nvfx_transfer.h
+++ b/src/gallium/drivers/nvfx/nvfx_transfer.h
@@ -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);
diff --git a/src/gallium/drivers/nvfx/nvfx_vbo.c b/src/gallium/drivers/nvfx/nvfx_vbo.c
index 4aa3793842..e6e9a8f2e4 100644
--- a/src/gallium/drivers/nvfx/nvfx_vbo.c
+++ b/src/gallium/drivers/nvfx/nvfx_vbo.c
@@ -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"
@@ -10,646 +11,595 @@
#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;
}
diff --git a/src/gallium/drivers/nvfx/nvfx_vertprog.c b/src/gallium/drivers/nvfx/nvfx_vertprog.c
index 24d9846310..ea7e88c561 100644
--- a/src/gallium/drivers/nvfx/nvfx_vertprog.c
+++ b/src/gallium/drivers/nvfx/nvfx_vertprog.c
@@ -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
@@ -25,26 +29,34 @@
#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;
}
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index e8b6c4f7af..624dadd07d 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -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;
}
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 6fa7f470f9..8f0e86fd37 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -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,
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index d0fd45349e..232259e21d 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -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;
}
diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c
index fe182b6615..2b5d2e42ba 100644
--- a/src/gallium/drivers/r300/r300_flush.c
+++ b/src/gallium/drivers/r300/r300_flush.c
@@ -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);
diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c
index 2a0c30620a..9845e54610 100644
--- a/src/gallium/drivers/r300/r300_fs.c
+++ b/src/gallium/drivers/r300/r300_fs.c
@@ -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;
diff --git a/src/gallium/drivers/r300/r300_hyperz.c b/src/gallium/drivers/r300/r300_hyperz.c
index 811b5646e1..eb5b0c36f8 100644
--- a/src/gallium/drivers/r300/r300_hyperz.c
+++ b/src/gallium/drivers/r300/r300_hyperz.c
@@ -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;
}
diff --git a/src/gallium/drivers/r300/r300_hyperz.h b/src/gallium/drivers/r300/r300_hyperz.h
index 09e1ff6625..30a23ec649 100644
--- a/src/gallium/drivers/r300/r300_hyperz.h
+++ b/src/gallium/drivers/r300/r300_hyperz.h
@@ -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
diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h
index 60d3b600cb..6bea783f69 100644
--- a/src/gallium/drivers/r300/r300_reg.h
+++ b/src/gallium/drivers/r300/r300_reg.h
@@ -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
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index 86b11ca045..20bad2c56f 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -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 *
***************************************************************************/
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index 239edd98e3..8ccb63964e 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -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) {
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index 4a63ed7fc1..960dfdbaf0 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -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);
}
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index da8eadd3b5..66f6d80bd0 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -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;
diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h
index a4524320fd..c4588a0c90 100644
--- a/src/gallium/drivers/r300/r300_texture.h
+++ b/src/gallium/drivers/r300/r300_texture.h
@@ -23,11 +23,14 @@
#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,
diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c
index 5d690e8c33..2fe5d72188 100644
--- a/src/gallium/drivers/r300/r300_texture_desc.c
+++ b/src/gallium/drivers/r300/r300_texture_desc.c
@@ -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);
}
diff --git a/src/gallium/drivers/r300/r300_texture_desc.h b/src/gallium/drivers/r300/r300_texture_desc.h
index 95de66f654..3d7fe1fb47 100644
--- a/src/gallium/drivers/r300/r300_texture_desc.h
+++ b/src/gallium/drivers/r300/r300_texture_desc.h
@@ -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;
diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
index dd697b9c37..a4911b9a2a 100644
--- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c
+++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
@@ -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;
diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c
index 54c8de1241..5f8dbb28d0 100644
--- a/src/gallium/drivers/r300/r300_vs.c
+++ b/src/gallium/drivers/r300/r300_vs.c
@@ -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... */
diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h
index 187780750f..4597332399 100644
--- a/src/gallium/drivers/r300/r300_winsys.h
+++ b/src/gallium/drivers/r300/r300_winsys.h
@@ -33,6 +33,7 @@
#include "r300_defines.h"
+struct winsys_handle;
struct r300_winsys_screen;
struct r300_winsys_buffer;
diff --git a/src/gallium/drivers/r600/r600_asm.c b/src/gallium/drivers/r600/r600_asm.c
index 9ea9d4354d..6483dac703 100644
--- a/src/gallium/drivers/r600/r600_asm.c
+++ b/src/gallium/drivers/r600/r600_asm.c
@@ -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);
diff --git a/src/gallium/drivers/r600/r600_asm.h b/src/gallium/drivers/r600/r600_asm.h
index 10d98afaf0..9e65fcdd4f 100644
--- a/src/gallium/drivers/r600/r600_asm.h
+++ b/src/gallium/drivers/r600/r600_asm.h
@@ -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
diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
index f4eedfe4cb..e6ded342e5 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -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>
@@ -31,9 +32,12 @@
#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;
+}
diff --git a/src/gallium/drivers/r600/r600_context.c b/src/gallium/drivers/r600/r600_context.c
index edde80c660..7a0e5b4049 100644
--- a/src/gallium/drivers/r600/r600_context.c
+++ b/src/gallium/drivers/r600/r600_context.c
@@ -34,10 +34,26 @@
#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;
}
diff --git a/src/gallium/drivers/r600/r600_context.h b/src/gallium/drivers/r600/r600_context.h
index 76d5de8653..cea0813054 100644
--- a/src/gallium/drivers/r600/r600_context.h
+++ b/src/gallium/drivers/r600/r600_context.h
@@ -30,9 +30,32 @@
#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
diff --git a/src/gallium/drivers/r600/r600_draw.c b/src/gallium/drivers/r600/r600_draw.c
index f058455162..fabd337d23 100644
--- a/src/gallium/drivers/r600/r600_draw.c
+++ b/src/gallium/drivers/r600/r600_draw.c
@@ -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);
}
diff --git a/src/gallium/drivers/r600/r600_query.c b/src/gallium/drivers/r600/r600_query.c
index 9b02ae680e..530940ed84 100644
--- a/src/gallium/drivers/r600/r600_query.c
+++ b/src/gallium/drivers/r600/r600_query.c
@@ -24,39 +24,225 @@
* 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;
diff --git a/src/gallium/drivers/r600/r600_resource.h b/src/gallium/drivers/r600/r600_resource.h
index bb90e76fb7..129667ad20 100644
--- a/src/gallium/drivers/r600/r600_resource.h
+++ b/src/gallium/drivers/r600/r600_resource.h
@@ -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);
diff --git a/src/gallium/drivers/r600/r600_screen.c b/src/gallium/drivers/r600/r600_screen.c
index cdaca9ed7d..a047a49a6c 100644
--- a/src/gallium/drivers/r600/r600_screen.c
+++ b/src/gallium/drivers/r600/r600_screen.c
@@ -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;
diff --git a/src/gallium/drivers/r600/r600_screen.h b/src/gallium/drivers/r600/r600_screen.h
index 53b560c617..b9938f117a 100644
--- a/src/gallium/drivers/r600/r600_screen.h
+++ b/src/gallium/drivers/r600/r600_screen.h
@@ -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);
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index 956c7e7930..0ba26a2311 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -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,19 +1171,43 @@ static int tgsi_trans(struct r600_shader_ctx *ctx)
return 0;
}
+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, r;
+
+ 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, 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]);
+ for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
+ r = tgsi_src(ctx, &inst->Src[i], &alu.src[i]);
if (r)
return r;
- alu.src[j].chan = tgsi_chan(&inst->Src[j], 0);
+ alu.src[i].chan = tgsi_chan(&inst->Src[i], 0);
}
alu.dst.sel = ctx->temp_reg;
alu.dst.write = 1;
@@ -900,16 +1215,124 @@ static int tgsi_trans_srcx_replicate(struct r600_shader_ctx *ctx)
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},
diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h
index 2ee7780ead..7c722c07cb 100644
--- a/src/gallium/drivers/r600/r600_shader.h
+++ b/src/gallium/drivers/r600/r600_shader.h
@@ -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
diff --git a/src/gallium/drivers/r600/r600_sq.h b/src/gallium/drivers/r600/r600_sq.h
index 002660c654..fa7a31742a 100644
--- a/src/gallium/drivers/r600/r600_sq.h
+++ b/src/gallium/drivers/r600/r600_sq.h
@@ -206,6 +206,26 @@
#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
@@ -583,4 +603,11 @@
#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
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index 3efd409ae0..66cab7d7a6 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -34,6 +34,17 @@
#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;
diff --git a/src/gallium/drivers/r600/r600_state_inlines.h b/src/gallium/drivers/r600/r600_state_inlines.h
index f93c20da35..84866825aa 100644
--- a/src/gallium/drivers/r600/r600_state_inlines.h
+++ b/src/gallium/drivers/r600/r600_state_inlines.h
@@ -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;
diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c
index 30d79ebdd6..b6698e3885 100644
--- a/src/gallium/drivers/r600/r600_texture.c
+++ b/src/gallium/drivers/r600/r600_texture.c
@@ -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>
@@ -33,10 +34,26 @@
#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;
+}
diff --git a/src/gallium/drivers/r600/r600d.h b/src/gallium/drivers/r600/r600d.h
index 53388f822e..7b9a983d53 100644
--- a/src/gallium/drivers/r600/r600d.h
+++ b/src/gallium/drivers/r600/r600d.h
@@ -199,6 +199,7 @@
#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
@@ -1316,4 +1317,11 @@
#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
diff --git a/src/gallium/drivers/r600/radeon.h b/src/gallium/drivers/r600/radeon.h
index 8f00a4895a..aaac8de528 100644
--- a/src/gallium/drivers/r600/radeon.h
+++ b/src/gallium/drivers/r600/radeon.h
@@ -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
diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c
index 386c8acb8c..01b4ca985d 100644
--- a/src/gallium/drivers/softpipe/sp_draw_arrays.c
+++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c
@@ -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);
}
/*
diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c
index 4a53ef048f..1071011db0 100644
--- a/src/gallium/drivers/softpipe/sp_flush.c
+++ b/src/gallium/drivers/softpipe/sp_flush.c
@@ -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"
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index 93af6ee5b0..73ae2dea56 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -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);
diff --git a/src/gallium/drivers/softpipe/sp_state_vertex.c b/src/gallium/drivers/softpipe/sp_state_vertex.c
index 880a7c7cd2..b650fcaea5 100644
--- a/src/gallium/drivers/softpipe/sp_state_vertex.c
+++ b/src/gallium/drivers/softpipe/sp_state_vertex.c
@@ -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);
}
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c
index cf7ab81405..e654bb77c2 100644
--- a/src/gallium/drivers/softpipe/sp_tex_sample.c
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.c
@@ -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 &&
diff --git a/src/gallium/drivers/svga/svga_cmd.c b/src/gallium/drivers/svga/svga_cmd.c
index 7b2dfe2549..e975f3b02f 100644
--- a/src/gallium/drivers/svga/svga_cmd.c
+++ b/src/gallium/drivers/svga/svga_cmd.c
@@ -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;
}
diff --git a/src/gallium/drivers/svga/svga_context.c b/src/gallium/drivers/svga/svga_context.c
index 3b30b9e341..cd3f6b8982 100644
--- a/src/gallium/drivers/svga/svga_context.c
+++ b/src/gallium/drivers/svga/svga_context.c
@@ -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);
diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h
index 67a7614c8a..1fb5a04887 100644
--- a/src/gallium/drivers/svga/svga_context.h
+++ b/src/gallium/drivers/svga/svga_context.h
@@ -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
diff --git a/src/gallium/drivers/svga/svga_pipe_draw.c b/src/gallium/drivers/svga/svga_pipe_draw.c
index de08bc5e56..001ec3616c 100644
--- a/src/gallium/drivers/svga/svga_pipe_draw.c
+++ b/src/gallium/drivers/svga/svga_pipe_draw.c
@@ -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;
diff --git a/src/gallium/drivers/svga/svga_resource_texture.c b/src/gallium/drivers/svga/svga_resource_texture.c
index ff83c750aa..26eb03a895 100644
--- a/src/gallium/drivers/svga/svga_resource_texture.c
+++ b/src/gallium/drivers/svga/svga_resource_texture.c
@@ -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;
diff --git a/src/gallium/drivers/svga/svga_state_framebuffer.c b/src/gallium/drivers/svga/svga_state_framebuffer.c
index bd92f00343..fcbb35e797 100644
--- a/src/gallium/drivers/svga/svga_state_framebuffer.c
+++ b/src/gallium/drivers/svga/svga_state_framebuffer.c
@@ -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
};
diff --git a/src/gallium/drivers/svga/svga_state_tss.c b/src/gallium/drivers/svga/svga_state_tss.c
index 76a2dae143..4a50b19474 100644
--- a/src/gallium/drivers/svga/svga_state_tss.c
+++ b/src/gallium/drivers/svga/svga_state_tss.c
@@ -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
};
diff --git a/src/gallium/drivers/svga/svga_swtnl.h b/src/gallium/drivers/svga/svga_swtnl.h
index 65c675f99c..fc094e5142 100644
--- a/src/gallium/drivers/svga/svga_swtnl.h
+++ b/src/gallium/drivers/svga/svga_swtnl.h
@@ -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
diff --git a/src/gallium/drivers/svga/svga_swtnl_draw.c b/src/gallium/drivers/svga/svga_swtnl_draw.c
index eb71c23195..814e8edd70 100644
--- a/src/gallium/drivers/svga/svga_swtnl_draw.c
+++ b/src/gallium/drivers/svga/svga_swtnl_draw.c
@@ -36,13 +36,8 @@
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;
diff --git a/src/gallium/drivers/svga/svga_tgsi_emit.h b/src/gallium/drivers/svga/svga_tgsi_emit.h
index 48eced2ece..b4e90a957d 100644
--- a/src/gallium/drivers/svga/svga_tgsi_emit.h
+++ b/src/gallium/drivers/svga/svga_tgsi_emit.h
@@ -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;
diff --git a/src/gallium/drivers/svga/svga_tgsi_insn.c b/src/gallium/drivers/svga/svga_tgsi_insn.c
index 67e1f22a70..72dccdf150 100644
--- a/src/gallium/drivers/svga/svga_tgsi_insn.c
+++ b/src/gallium/drivers/svga/svga_tgsi_insn.c
@@ -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 ||
diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c
index 84e5a6a824..271cd4aff5 100644
--- a/src/gallium/drivers/trace/tr_context.c
+++ b/src/gallium/drivers/trace/tr_context.c
@@ -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);
diff --git a/src/gallium/include/pipe/p_compiler.h b/src/gallium/include/pipe/p_compiler.h
index 1fa3ec8300..0a5be43f6b 100644
--- a/src/gallium/include/pipe/p_compiler.h
+++ b/src/gallium/include/pipe/p_compiler.h
@@ -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
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index 0579962ec6..0e53aef6d2 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -28,19 +28,37 @@
#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:
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
index 00aa2076ed..627b5ae538 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -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
};
diff --git a/src/gallium/include/pipe/p_format.h b/src/gallium/include/pipe/p_format.h
index 436c3f627a..06412f4894 100644
--- a/src/gallium/include/pipe/p_format.h
+++ b/src/gallium/include/pipe/p_format.h
@@ -29,8 +29,6 @@
#ifndef PIPE_FORMAT_H
#define PIPE_FORMAT_H
-#include "p_compiler.h"
-
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h
index 9df20ea858..c4bd17e92b 100644
--- a/src/gallium/include/pipe/p_shader_tokens.h
+++ b/src/gallium/include/pipe/p_shader_tokens.h
@@ -33,8 +33,6 @@
extern "C" {
#endif
-#include "p_compiler.h"
-
struct tgsi_header
{
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index 0f1a44cde4..9a2b31da50 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -43,7 +43,6 @@
#include "p_compiler.h"
#include "p_defines.h"
#include "p_format.h"
-#include "p_screen.h"
#ifdef __cplusplus
diff --git a/src/gallium/include/state_tracker/graw.h b/src/gallium/include/state_tracker/graw.h
index 59b0e337c9..6a99b234aa 100644
--- a/src/gallium/include/state_tracker/graw.h
+++ b/src/gallium/include/state_tracker/graw.h
@@ -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;
diff --git a/src/gallium/state_trackers/dri/common/dri_context.h b/src/gallium/state_trackers/dri/common/dri_context.h
index 692c49d7cd..35b870a8a3 100644
--- a/src/gallium/state_trackers/dri/common/dri_context.h
+++ b/src/gallium/state_trackers/dri/common/dri_context.h
@@ -34,7 +34,6 @@
#include "pipe/p_compiler.h"
#include "dri_wrapper.h"
-#include "main/mtypes.h"
struct pipe_context;
struct pipe_fence;
diff --git a/src/gallium/state_trackers/dri/common/dri_screen.c b/src/gallium/state_trackers/dri/common/dri_screen.c
index 6ad2c7da4d..0ab4dd1893 100644
--- a/src/gallium/state_trackers/dri/common/dri_screen.c
+++ b/src/gallium/state_trackers/dri/common/dri_screen.c
@@ -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);
diff --git a/src/gallium/state_trackers/dri/common/dri_screen.h b/src/gallium/state_trackers/dri/common/dri_screen.h
index 53ccce145b..849f399b2f 100644
--- a/src/gallium/state_trackers/dri/common/dri_screen.h
+++ b/src/gallium/state_trackers/dri/common/dri_screen.h
@@ -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 */
diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c
index 47005c17e2..93f910a26d 100644
--- a/src/gallium/state_trackers/dri/drm/dri2.c
+++ b/src/gallium/state_trackers/dri/drm/dri2.c
@@ -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;
diff --git a/src/gallium/state_trackers/dri/sw/drisw.c b/src/gallium/state_trackers/dri/sw/drisw.c
index 249ccd7fcf..04bba631ae 100644
--- a/src/gallium/state_trackers/dri/sw/drisw.c
+++ b/src/gallium/state_trackers/dri/sw/drisw.c
@@ -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;
diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile
index 9e9e479e7e..4199d7c6ba 100644
--- a/src/gallium/state_trackers/egl/Makefile
+++ b/src/gallium/state_trackers/egl/Makefile
@@ -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)
diff --git a/src/gallium/state_trackers/egl/SConscript b/src/gallium/state_trackers/egl/SConscript
index e71aec35b7..efcce25e31 100644
--- a/src/gallium/state_trackers/egl/SConscript
+++ b/src/gallium/state_trackers/egl/SConscript
@@ -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',
]
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c
index 56d575ffe0..4e653bdf3b 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.c
@@ -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;
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h
index f33dc91cf9..be450bbede 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.h
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.h
@@ -30,12 +30,14 @@
#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 {
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.c b/src/gallium/state_trackers/egl/common/egl_g3d_api.c
index edac72a822..3ec53653f4 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_api.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c
@@ -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;
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
index 1e13cfcf7e..558638e72f 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
@@ -31,12 +31,16 @@
#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;
+}
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.h b/src/gallium/state_trackers/egl/common/egl_g3d_image.h
index adda933371..f051da8283 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_image.h
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.h
@@ -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
index 0000000000..ec74e9eb94
--- /dev/null
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_sync.c
@@ -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
index 0000000000..3179ca04e1
--- /dev/null
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_sync.h
@@ -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_ */
diff --git a/src/gallium/state_trackers/egl/kms/native_kms.c b/src/gallium/state_trackers/egl/kms/native_kms.c
index d4e8fbc913..208f73306c 100644
--- a/src/gallium/state_trackers/egl/kms/native_kms.c
+++ b/src/gallium/state_trackers/egl/kms/native_kms.c
@@ -38,6 +38,10 @@
#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;
}
diff --git a/src/gallium/state_trackers/glx/xlib/glx_api.c b/src/gallium/state_trackers/glx/xlib/glx_api.c
index eb8d6a1933..dcd50e19d7 100644
--- a/src/gallium/state_trackers/glx/xlib/glx_api.c
+++ b/src/gallium/state_trackers/glx/xlib/glx_api.c
@@ -34,10 +34,6 @@
#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);
}
diff --git a/src/gallium/state_trackers/glx/xlib/glx_usefont.c b/src/gallium/state_trackers/glx/xlib/glx_usefont.c
index 8903b0e6cb..0aa37e150b 100644
--- a/src/gallium/state_trackers/glx/xlib/glx_usefont.c
+++ b/src/gallium/state_trackers/glx/xlib/glx_usefont.c
@@ -30,8 +30,7 @@
*/
-#include "main/context.h"
-#include "main/imports.h"
+#include "main/core.h"
#include <GL/glx.h>
diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c
index c0c418306f..eb4ce74266 100644
--- a/src/gallium/state_trackers/glx/xlib/xm_api.c
+++ b/src/gallium/state_trackers/glx/xlib/xm_api.c
@@ -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"
@@ -72,10 +71,35 @@
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 );
}
}
diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.h b/src/gallium/state_trackers/glx/xlib/xm_api.h
index 4f2c8a6e6a..f209b14ea1 100644
--- a/src/gallium/state_trackers/glx/xlib/xm_api.h
+++ b/src/gallium/state_trackers/glx/xlib/xm_api.h
@@ -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
diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c
index c62eb8bfbd..0f74b3f7aa 100644
--- a/src/gallium/state_trackers/glx/xlib/xm_st.c
+++ b/src/gallium/state_trackers/glx/xlib/xm_st.c
@@ -26,18 +26,18 @@
* 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);
}
}
diff --git a/src/gallium/state_trackers/wgl/stw_context.c b/src/gallium/state_trackers/wgl/stw_context.c
index 0fb7cd8306..a0e14b9601 100644
--- a/src/gallium/state_trackers/wgl/stw_context.c
+++ b/src/gallium/state_trackers/wgl/stw_context.c
@@ -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"
diff --git a/src/gallium/state_trackers/wgl/stw_device.c b/src/gallium/state_trackers/wgl/stw_device.c
index a107c71bda..37809d084c 100644
--- a/src/gallium/state_trackers/wgl/stw_device.c
+++ b/src/gallium/state_trackers/wgl/stw_device.c
@@ -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"
diff --git a/src/gallium/state_trackers/wgl/stw_pixelformat.c b/src/gallium/state_trackers/wgl/stw_pixelformat.c
index e606477e97..18ac482369 100644
--- a/src/gallium/state_trackers/wgl/stw_pixelformat.c
+++ b/src/gallium/state_trackers/wgl/stw_pixelformat.c
@@ -25,15 +25,13 @@
*
**************************************************************************/
-#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"
diff --git a/src/gallium/state_trackers/wgl/stw_pixelformat.h b/src/gallium/state_trackers/wgl/stw_pixelformat.h
index d405172773..282c9f643c 100644
--- a/src/gallium/state_trackers/wgl/stw_pixelformat.h
+++ b/src/gallium/state_trackers/wgl/stw_pixelformat.h
@@ -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"
diff --git a/src/gallium/targets/Makefile.dri b/src/gallium/targets/Makefile.dri
index de05f96d23..59961e982a 100644
--- a/src/gallium/targets/Makefile.dri
+++ b/src/gallium/targets/Makefile.dri
@@ -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 $@
diff --git a/src/gallium/targets/SConscript b/src/gallium/targets/SConscript
index f8276b1555..e447d09361 100644
--- a/src/gallium/targets/SConscript
+++ b/src/gallium/targets/SConscript
@@ -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-radeong/Makefile b/src/gallium/targets/dri-r300/Makefile
index 3f9ec36166..9afbb13276 100644
--- a/src/gallium/targets/dri-radeong/Makefile
+++ b/src/gallium/targets/dri-r300/Makefile
@@ -1,7 +1,7 @@
TOP = ../../../..
include $(TOP)/configs/current
-LIBNAME = radeong_dri.so
+LIBNAME = r300_dri.so
PIPE_DRIVERS = \
$(TOP)/src/gallium/state_trackers/dri/drm/libdridrm.a \
diff --git a/src/gallium/targets/dri-radeong/SConscript b/src/gallium/targets/dri-r300/SConscript
index 1402c3bd12..33a458f2e6 100644
--- a/src/gallium/targets/dri-radeong/SConscript
+++ b/src/gallium/targets/dri-r300/SConscript
@@ -1,7 +1,7 @@
Import('*')
if not 'r300' in env['drivers']:
- print 'warning: r300 pipe driver not built skipping radeong_dri.so'
+ print 'warning: r300 pipe driver not built skipping r300_dri.so'
Return()
env = drienv.Clone()
@@ -24,7 +24,7 @@ env.Prepend(LIBS = [
])
env.SharedLibrary(
- target ='radeon_dri.so',
+ target ='r300_dri.so',
source = 'target.c',
SHLIBPREFIX = '',
)
diff --git a/src/gallium/targets/dri-radeong/target.c b/src/gallium/targets/dri-r300/target.c
index 5a0a8dc573..2ecf3457a7 100644
--- a/src/gallium/targets/dri-radeong/target.c
+++ b/src/gallium/targets/dri-r300/target.c
@@ -23,4 +23,4 @@ create_screen(int fd)
return screen;
}
-DRM_DRIVER_DESCRIPTOR("radeon", "radeon", create_screen)
+DRM_DRIVER_DESCRIPTOR("r300", "radeon", create_screen)
diff --git a/src/gallium/targets/dri-r600/Makefile b/src/gallium/targets/dri-r600/Makefile
index 932303d194..661283de6a 100644
--- a/src/gallium/targets/dri-r600/Makefile
+++ b/src/gallium/targets/dri-r600/Makefile
@@ -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/egl-gdi/egl-static.c b/src/gallium/targets/egl-gdi/egl-static.c
index ec2f865c31..4655d79117 100644
--- a/src/gallium/targets/egl-gdi/egl-static.c
+++ b/src/gallium/targets/egl-gdi/egl-static.c
@@ -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;
diff --git a/src/gallium/targets/egl/Makefile b/src/gallium/targets/egl/Makefile
index 1e4bb4d94c..2784fd0d10 100644
--- a/src/gallium/targets/egl/Makefile
+++ b/src/gallium/targets/egl/Makefile
@@ -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)
diff --git a/src/gallium/targets/egl/egl.c b/src/gallium/targets/egl/egl.c
index d9d89485c3..a573b21217 100644
--- a/src/gallium/targets/egl/egl.c
+++ b/src/gallium/targets/egl/egl.c
@@ -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_radeon.c b/src/gallium/targets/egl/pipe_r300.c
index 35550bcb26..d84bb92539 100644
--- a/src/gallium/targets/egl/pipe_radeon.c
+++ b/src/gallium/targets/egl/pipe_r300.c
@@ -24,4 +24,4 @@ create_screen(int fd)
}
PUBLIC
-DRM_DRIVER_DESCRIPTOR("radeon", "radeon", create_screen)
+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
index 0000000000..486a659258
--- /dev/null
+++ b/src/gallium/targets/egl/pipe_r600.c
@@ -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/graw-xlib/graw_util.c b/src/gallium/targets/graw-xlib/graw_util.c
index 47aca4464d..fc7c9ae6f9 100644
--- a/src/gallium/targets/graw-xlib/graw_util.c
+++ b/src/gallium/targets/graw-xlib/graw_util.c
@@ -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"
diff --git a/src/gallium/targets/graw-xlib/graw_xlib.c b/src/gallium/targets/graw-xlib/graw_xlib.c
index 41120ba3c7..8b64a0b819 100644
--- a/src/gallium/targets/graw-xlib/graw_xlib.c
+++ b/src/gallium/targets/graw-xlib/graw_xlib.c
@@ -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"
diff --git a/src/gallium/targets/libgl-gdi/SConscript b/src/gallium/targets/libgl-gdi/SConscript
index 144084f74f..12fe403f62 100644
--- a/src/gallium/targets/libgl-gdi/SConscript
+++ b/src/gallium/targets/libgl-gdi/SConscript
@@ -17,6 +17,7 @@ if env['platform'] == 'windows':
'user32',
'kernel32',
'ws2_32',
+ talloc,
])
sources = []
diff --git a/src/gallium/targets/libgl-xlib/Makefile b/src/gallium/targets/libgl-xlib/Makefile
index e745023ba5..fe0541543a 100644
--- a/src/gallium/targets/libgl-xlib/Makefile
+++ b/src/gallium/targets/libgl-xlib/Makefile
@@ -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)
diff --git a/src/gallium/targets/libgl-xlib/SConscript b/src/gallium/targets/libgl-xlib/SConscript
index 78703fd096..88e216a65b 100644
--- a/src/gallium/targets/libgl-xlib/SConscript
+++ b/src/gallium/targets/libgl-xlib/SConscript
@@ -35,6 +35,7 @@ env.Prepend(LIBS = [
mesa,
glsl,
gallium,
+ 'talloc'
])
sources = [
diff --git a/src/gallium/targets/libgl-xlib/xlib.c b/src/gallium/targets/libgl-xlib/xlib.c
index 69b4ddd33f..5a9c80c856 100644
--- a/src/gallium/targets/libgl-xlib/xlib.c
+++ b/src/gallium/targets/libgl-xlib/xlib.c
@@ -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 */
diff --git a/src/gallium/tests/python/tests/texture_blit.py b/src/gallium/tests/python/tests/texture_blit.py
index 58706dab93..089d05c623 100755
--- a/src/gallium/tests/python/tests/texture_blit.py
+++ b/src/gallium/tests/python/tests/texture_blit.py
@@ -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
index 0000000000..34dec14271
--- /dev/null
+++ b/src/gallium/tools/addr2line.sh
@@ -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"
diff --git a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c
index 660dbd0c33..d4bf124ce6 100644
--- a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c
+++ b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c
@@ -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);
}
diff --git a/src/gallium/winsys/r600/drm/r600_state.c b/src/gallium/winsys/r600/drm/r600_state.c
index d17d6e7954..71d65f0fea 100644
--- a/src/gallium/winsys/r600/drm/r600_state.c
+++ b/src/gallium/winsys/r600/drm/r600_state.c
@@ -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;
}
diff --git a/src/gallium/winsys/r600/drm/r600_states.h b/src/gallium/winsys/r600/drm/r600_states.h
index e40c77d8f6..09d79d498d 100644
--- a/src/gallium/winsys/r600/drm/r600_states.h
+++ b/src/gallium/winsys/r600/drm/r600_states.h
@@ -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
diff --git a/src/gallium/winsys/r600/drm/r600d.h b/src/gallium/winsys/r600/drm/r600d.h
index 5d13378627..e8c2dc0651 100644
--- a/src/gallium/winsys/r600/drm/r600d.h
+++ b/src/gallium/winsys/r600/drm/r600d.h
@@ -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
diff --git a/src/gallium/winsys/r600/drm/radeon.c b/src/gallium/winsys/r600/drm/radeon.c
index 80b0a1d397..e2d813ebac 100644
--- a/src/gallium/winsys/r600/drm/radeon.c
+++ b/src/gallium/winsys/r600/drm/radeon.c
@@ -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;
-}
diff --git a/src/gallium/winsys/r600/drm/radeon_bo.c b/src/gallium/winsys/r600/drm/radeon_bo.c
index f259ae7fb5..a1306f6e9d 100644
--- a/src/gallium/winsys/r600/drm/radeon_bo.c
+++ b/src/gallium/winsys/r600/drm/radeon_bo.c
@@ -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);
diff --git a/src/gallium/winsys/r600/drm/radeon_ctx.c b/src/gallium/winsys/r600/drm/radeon_ctx.c
index 45b706bb0f..47fca76136 100644
--- a/src/gallium/winsys/r600/drm/radeon_ctx.c
+++ b/src/gallium/winsys/r600/drm/radeon_ctx.c
@@ -30,21 +30,16 @@
#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))
diff --git a/src/gallium/winsys/r600/drm/radeon_draw.c b/src/gallium/winsys/r600/drm/radeon_draw.c
index 4413ed79fb..b992c4a55d 100644
--- a/src/gallium/winsys/r600/drm/radeon_draw.c
+++ b/src/gallium/winsys/r600/drm/radeon_draw.c
@@ -31,111 +31,27 @@
/*
* 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;
}
diff --git a/src/gallium/winsys/r600/drm/radeon_priv.h b/src/gallium/winsys/r600/drm/radeon_priv.h
index 96c0d060f7..84e552ba4d 100644
--- a/src/gallium/winsys/r600/drm/radeon_priv.h
+++ b/src/gallium/winsys/r600/drm/radeon_priv.h
@@ -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
diff --git a/src/gallium/winsys/r600/drm/radeon_state.c b/src/gallium/winsys/r600/drm/radeon_state.c
index 308288557a..ac60485b28 100644
--- a/src/gallium/winsys/r600/drm/radeon_state.c
+++ b/src/gallium/winsys/r600/drm/radeon_state.c
@@ -32,82 +32,116 @@
/*
* 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);
diff --git a/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c b/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c
index b997abda9b..3a76098b65 100644
--- a/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c
+++ b/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c
@@ -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
index 0000000000..be19e29a5a
--- /dev/null
+++ b/src/glsl/.dir-locals.el
@@ -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
index 0000000000..4c212313e4
--- /dev/null
+++ b/src/glsl/.gitignore
@@ -0,0 +1,2 @@
+glsl_compiler
+glsl_parser.output
diff --git a/src/glsl/Makefile b/src/glsl/Makefile
index ca7f2d2ac7..aedca0f0d1 100644
--- a/src/glsl/Makefile
+++ b/src/glsl/Makefile
@@ -1,15 +1,178 @@
-# 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
index 0000000000..5728a8b63d
--- /dev/null
+++ b/src/glsl/Makefile.am
@@ -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
index 0000000000..2e501d6206
--- /dev/null
+++ b/src/glsl/README
@@ -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).
diff --git a/src/glsl/SConscript b/src/glsl/SConscript
index 8e18626c40..a808a5bc5d 100644
--- a/src/glsl/SConscript
+++ b/src/glsl/SConscript
@@ -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
index 0000000000..07ac5f5c6e
--- /dev/null
+++ b/src/glsl/TODO
@@ -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
index 7e011ce7a1..0000000000
--- a/src/glsl/apps/.gitignore
+++ /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
index 39a0df7fea..0000000000
--- a/src/glsl/apps/Makefile
+++ /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
index 5114fc9d0b..0000000000
--- a/src/glsl/apps/compile.c
+++ /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
index 6d5ce6eea3..0000000000
--- a/src/glsl/apps/process.c
+++ /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
index e3fca59ab4..0000000000
--- a/src/glsl/apps/purify.c
+++ /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
index 3d68334bed..0000000000
--- a/src/glsl/apps/tokenise.c
+++ /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
index 8506f35ba1..0000000000
--- a/src/glsl/apps/version.c
+++ /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
index 0000000000..44c31b6e62
--- /dev/null
+++ b/src/glsl/ast.h
@@ -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
index 0000000000..4e83decb92
--- /dev/null
+++ b/src/glsl/ast_expr.cpp
@@ -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
index 0000000000..61012b850a
--- /dev/null
+++ b/src/glsl/ast_function.cpp
@@ -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
index 0000000000..762f802c2b
--- /dev/null
+++ b/src/glsl/ast_to_hir.cpp
@@ -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
index 0000000000..9a957044e7
--- /dev/null
+++ b/src/glsl/ast_type.cpp
@@ -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
index 0000000000..904cd6746c
--- /dev/null
+++ b/src/glsl/autogen.sh
@@ -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
index 0000000000..892b5aa857
--- /dev/null
+++ b/src/glsl/builtin_function.cpp
@@ -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
index 0000000000..7b94aac666
--- /dev/null
+++ b/src/glsl/builtin_types.h
@@ -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
index 0000000000..a7dbe480e9
--- /dev/null
+++ b/src/glsl/builtin_variables.h
@@ -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
index 0000000000..904845307c
--- /dev/null
+++ b/src/glsl/builtins/ir/abs
@@ -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
index 0000000000..d1cfebeff8
--- /dev/null
+++ b/src/glsl/builtins/ir/acos
@@ -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
index 0000000000..2cac0dfb68
--- /dev/null
+++ b/src/glsl/builtins/ir/all
@@ -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
index 0000000000..cc6038a315
--- /dev/null
+++ b/src/glsl/builtins/ir/any
@@ -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
index 0000000000..e230ad614e
--- /dev/null
+++ b/src/glsl/builtins/ir/asin
@@ -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
index 0000000000..04e1898f9f
--- /dev/null
+++ b/src/glsl/builtins/ir/atan
@@ -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
index 0000000000..a26a775049
--- /dev/null
+++ b/src/glsl/builtins/ir/ceil
@@ -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
index 0000000000..2bdc466b26
--- /dev/null
+++ b/src/glsl/builtins/ir/clamp
@@ -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
index 0000000000..88f266eccb
--- /dev/null
+++ b/src/glsl/builtins/ir/cos
@@ -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
index 0000000000..45e0ae427d
--- /dev/null
+++ b/src/glsl/builtins/ir/cosh
@@ -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
index 0000000000..24717a2183
--- /dev/null
+++ b/src/glsl/builtins/ir/cross
@@ -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
index 0000000000..30594d33c7
--- /dev/null
+++ b/src/glsl/builtins/ir/dFdx
@@ -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
index 0000000000..fb5798d3cb
--- /dev/null
+++ b/src/glsl/builtins/ir/dFdy
@@ -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
index 0000000000..dc0d7b9e20
--- /dev/null
+++ b/src/glsl/builtins/ir/degrees
@@ -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
index 0000000000..a2309c484f
--- /dev/null
+++ b/src/glsl/builtins/ir/distance
@@ -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
index 0000000000..a91a6d2c56
--- /dev/null
+++ b/src/glsl/builtins/ir/dot
@@ -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
index 0000000000..c394776770
--- /dev/null
+++ b/src/glsl/builtins/ir/equal
@@ -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
index 0000000000..a73bd6a7f8
--- /dev/null
+++ b/src/glsl/builtins/ir/exp
@@ -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
index 0000000000..a842d3fe65
--- /dev/null
+++ b/src/glsl/builtins/ir/exp2
@@ -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
index 0000000000..d170397238
--- /dev/null
+++ b/src/glsl/builtins/ir/faceforward
@@ -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
index 0000000000..8dd8052799
--- /dev/null
+++ b/src/glsl/builtins/ir/floor
@@ -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
index 0000000000..3f0763d1b3
--- /dev/null
+++ b/src/glsl/builtins/ir/fract
@@ -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
index 0000000000..9ca63dc1e3
--- /dev/null
+++ b/src/glsl/builtins/ir/ftransform
@@ -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
index 0000000000..385e05d6a1
--- /dev/null
+++ b/src/glsl/builtins/ir/fwidth
@@ -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
index 0000000000..ce7bd29bed
--- /dev/null
+++ b/src/glsl/builtins/ir/greaterThan
@@ -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
index 0000000000..de1a9f9516
--- /dev/null
+++ b/src/glsl/builtins/ir/greaterThanEqual
@@ -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
index 0000000000..5b66d2b369
--- /dev/null
+++ b/src/glsl/builtins/ir/inversesqrt
@@ -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
index 0000000000..89ff7f3ef1
--- /dev/null
+++ b/src/glsl/builtins/ir/length
@@ -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
index 0000000000..52113b7046
--- /dev/null
+++ b/src/glsl/builtins/ir/lessThan
@@ -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
index 0000000000..4b240be5d1
--- /dev/null
+++ b/src/glsl/builtins/ir/lessThanEqual
@@ -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
index 0000000000..d168abb5a7
--- /dev/null
+++ b/src/glsl/builtins/ir/log
@@ -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
index 0000000000..b96c6276f0
--- /dev/null
+++ b/src/glsl/builtins/ir/log2
@@ -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
index 0000000000..538da18a79
--- /dev/null
+++ b/src/glsl/builtins/ir/matrixCompMult
@@ -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
index 0000000000..2b5a02868c
--- /dev/null
+++ b/src/glsl/builtins/ir/max
@@ -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
index 0000000000..2deef1118a
--- /dev/null
+++ b/src/glsl/builtins/ir/min
@@ -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
index 0000000000..6bc6f0a43e
--- /dev/null
+++ b/src/glsl/builtins/ir/mix
@@ -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
index 0000000000..aeaea240e2
--- /dev/null
+++ b/src/glsl/builtins/ir/mod
@@ -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
index 0000000000..eb7be35857
--- /dev/null
+++ b/src/glsl/builtins/ir/noise1
@@ -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
index 0000000000..ae4443a704
--- /dev/null
+++ b/src/glsl/builtins/ir/noise2
@@ -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
index 0000000000..30d9681890
--- /dev/null
+++ b/src/glsl/builtins/ir/noise3
@@ -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
index 0000000000..913bef2aa1
--- /dev/null
+++ b/src/glsl/builtins/ir/noise4
@@ -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
index 0000000000..be88a9830d
--- /dev/null
+++ b/src/glsl/builtins/ir/normalize
@@ -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
index 0000000000..b696b06557
--- /dev/null
+++ b/src/glsl/builtins/ir/not
@@ -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
index 0000000000..eeeda79042
--- /dev/null
+++ b/src/glsl/builtins/ir/notEqual
@@ -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
index 0000000000..69ae741e17
--- /dev/null
+++ b/src/glsl/builtins/ir/outerProduct
@@ -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
index 0000000000..a61bc4418e
--- /dev/null
+++ b/src/glsl/builtins/ir/pow
@@ -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
index 0000000000..6a0f5d2e21
--- /dev/null
+++ b/src/glsl/builtins/ir/radians
@@ -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
index 0000000000..8238fdc93f
--- /dev/null
+++ b/src/glsl/builtins/ir/reflect
@@ -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
index 0000000000..522ab41173
--- /dev/null
+++ b/src/glsl/builtins/ir/refract
@@ -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
index 0000000000..1f51718dab
--- /dev/null
+++ b/src/glsl/builtins/ir/sign
@@ -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
index 0000000000..e6009d8ef1
--- /dev/null
+++ b/src/glsl/builtins/ir/sin
@@ -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
index 0000000000..7ad4f58e20
--- /dev/null
+++ b/src/glsl/builtins/ir/sinh
@@ -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
index 0000000000..663eec6341
--- /dev/null
+++ b/src/glsl/builtins/ir/smoothstep
@@ -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
index 0000000000..0302d164ae
--- /dev/null
+++ b/src/glsl/builtins/ir/sqrt
@@ -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
index 0000000000..ce6f435422
--- /dev/null
+++ b/src/glsl/builtins/ir/step
@@ -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
index 0000000000..9979863185
--- /dev/null
+++ b/src/glsl/builtins/ir/tan
@@ -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
index 0000000000..3b7271bf77
--- /dev/null
+++ b/src/glsl/builtins/ir/tanh
@@ -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
index 0000000000..416a0ee467
--- /dev/null
+++ b/src/glsl/builtins/ir/transpose
@@ -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
index 0000000000..25bc62c093
--- /dev/null
+++ b/src/glsl/builtins/profiles/110.frag
@@ -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
index 0000000000..545e59c539
--- /dev/null
+++ b/src/glsl/builtins/profiles/110.vert
@@ -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
index 0000000000..a207435f33
--- /dev/null
+++ b/src/glsl/builtins/profiles/120.frag
@@ -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
index 0000000000..e14c931647
--- /dev/null
+++ b/src/glsl/builtins/profiles/120.vert
@@ -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
index 0000000000..aa7a6adb1d
--- /dev/null
+++ b/src/glsl/builtins/profiles/130.frag
@@ -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
index 0000000000..d0152b0374
--- /dev/null
+++ b/src/glsl/builtins/profiles/130.vert
@@ -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
index 0000000000..8938aa3e97
--- /dev/null
+++ b/src/glsl/builtins/profiles/ARB_texture_rectangle.frag
@@ -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
index 0000000000..8938aa3e97
--- /dev/null
+++ b/src/glsl/builtins/profiles/ARB_texture_rectangle.vert
@@ -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
index 0000000000..d0ce981dd9
--- /dev/null
+++ b/src/glsl/builtins/profiles/EXT_texture_array.frag
@@ -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
index 0000000000..6b1b7f2f16
--- /dev/null
+++ b/src/glsl/builtins/profiles/EXT_texture_array.vert
@@ -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
index 0000000000..c44804f2ef
--- /dev/null
+++ b/src/glsl/builtins/tools/builtin_function.cpp
@@ -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
index 0000000000..5accc1b120
--- /dev/null
+++ b/src/glsl/builtins/tools/generate_builtins.py
@@ -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
index 0000000000..391ad110d3
--- /dev/null
+++ b/src/glsl/builtins/tools/generate_matrixCompMultGLSL.py
@@ -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
index 0000000000..c561cc3ba1
--- /dev/null
+++ b/src/glsl/builtins/tools/generate_outerProductGLSL.py
@@ -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
index 0000000000..8f669ce983
--- /dev/null
+++ b/src/glsl/builtins/tools/generate_transposeGLSL.py
@@ -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
index 0000000000..8bf708b5aa
--- /dev/null
+++ b/src/glsl/builtins/tools/texture_builtins.py
@@ -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
index 04a52df8c3..0000000000
--- a/src/glsl/cl/Makefile
+++ /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
index c1bc6031ce..0000000000
--- a/src/glsl/cl/sl_cl_parse.c
+++ /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
index a954d43927..0000000000
--- a/src/glsl/cl/sl_cl_parse.h
+++ /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
index 0000000000..73ce67de3d
--- /dev/null
+++ b/src/glsl/configure.ac
@@ -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
index 0000000000..dbc37e1926
--- /dev/null
+++ b/src/glsl/glcpp/.gitignore
@@ -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
index 0000000000..81147e6e12
--- /dev/null
+++ b/src/glsl/glcpp/Makefile.am
@@ -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
index 0000000000..0b5ef508ce
--- /dev/null
+++ b/src/glsl/glcpp/README
@@ -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
index 0000000000..0f99ea1bbb
--- /dev/null
+++ b/src/glsl/glcpp/glcpp-lex.c
@@ -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
index 0000000000..8eb84ed138
--- /dev/null
+++ b/src/glsl/glcpp/glcpp-lex.l
@@ -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
index 0000000000..91eb0bf972
--- /dev/null
+++ b/src/glsl/glcpp/glcpp-parse.c
@@ -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
+
+
+
+#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 */
+
+
+/*-----------------------------------------------.
+| 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
index 0000000000..50758930e9
--- /dev/null
+++ b/src/glsl/glcpp/glcpp-parse.h
@@ -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
index 0000000000..3c28edf688
--- /dev/null
+++ b/src/glsl/glcpp/glcpp-parse.y
@@ -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
index 0000000000..56714936bb
--- /dev/null
+++ b/src/glsl/glcpp/glcpp.c
@@ -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
index 0000000000..0bebdb9ae8
--- /dev/null
+++ b/src/glsl/glcpp/glcpp.h
@@ -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
index 0000000000..a1d00c4193
--- /dev/null
+++ b/src/glsl/glcpp/pp.c
@@ -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
index 0000000000..696cb3a74f
--- /dev/null
+++ b/src/glsl/glcpp/tests/000-content-with-spaces.c
@@ -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
index 0000000000..83f7834d54
--- /dev/null
+++ b/src/glsl/glcpp/tests/000-content-with-spaces.c.expected
@@ -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
index 0000000000..cbf2fee0e7
--- /dev/null
+++ b/src/glsl/glcpp/tests/001-define.c
@@ -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
index 0000000000..878fd15d6f
--- /dev/null
+++ b/src/glsl/glcpp/tests/001-define.c.expected
@@ -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
index 0000000000..87d75c6875
--- /dev/null
+++ b/src/glsl/glcpp/tests/002-define-chain.c
@@ -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
index 0000000000..43d484d713
--- /dev/null
+++ b/src/glsl/glcpp/tests/002-define-chain.c.expected
@@ -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
index 0000000000..a18b724eca
--- /dev/null
+++ b/src/glsl/glcpp/tests/003-define-chain-reverse.c
@@ -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
index 0000000000..43d484d713
--- /dev/null
+++ b/src/glsl/glcpp/tests/003-define-chain-reverse.c.expected
@@ -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
index 0000000000..2ac56ea3dc
--- /dev/null
+++ b/src/glsl/glcpp/tests/004-define-recursive.c
@@ -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
index 0000000000..4d2698b7a7
--- /dev/null
+++ b/src/glsl/glcpp/tests/004-define-recursive.c.expected
@@ -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
index 0000000000..f5521df968
--- /dev/null
+++ b/src/glsl/glcpp/tests/005-define-composite-chain.c
@@ -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
index 0000000000..c67358f4f6
--- /dev/null
+++ b/src/glsl/glcpp/tests/005-define-composite-chain.c.expected
@@ -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
index 0000000000..4bb91a1221
--- /dev/null
+++ b/src/glsl/glcpp/tests/006-define-composite-chain-reverse.c
@@ -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
index 0000000000..c67358f4f6
--- /dev/null
+++ b/src/glsl/glcpp/tests/006-define-composite-chain-reverse.c.expected
@@ -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
index 0000000000..5784565bdf
--- /dev/null
+++ b/src/glsl/glcpp/tests/007-define-composite-recursive.c
@@ -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
index 0000000000..30fe4dc1f6
--- /dev/null
+++ b/src/glsl/glcpp/tests/007-define-composite-recursive.c.expected
@@ -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
index 0000000000..b1bd17ec21
--- /dev/null
+++ b/src/glsl/glcpp/tests/008-define-empty.c
@@ -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
index 0000000000..c0f53d75c7
--- /dev/null
+++ b/src/glsl/glcpp/tests/008-define-empty.c.expected
@@ -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
index 0000000000..3fc1fb4424
--- /dev/null
+++ b/src/glsl/glcpp/tests/009-undef.c
@@ -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
index 0000000000..03a7061af0
--- /dev/null
+++ b/src/glsl/glcpp/tests/009-undef.c.expected
@@ -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
index 0000000000..32ff73798b
--- /dev/null
+++ b/src/glsl/glcpp/tests/010-undef-re-define.c
@@ -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
index 0000000000..f4f7efdc2b
--- /dev/null
+++ b/src/glsl/glcpp/tests/010-undef-re-define.c.expected
@@ -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
index 0000000000..d9ce13c228
--- /dev/null
+++ b/src/glsl/glcpp/tests/011-define-func-empty.c
@@ -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
index 0000000000..c0f53d75c7
--- /dev/null
+++ b/src/glsl/glcpp/tests/011-define-func-empty.c.expected
@@ -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
index 0000000000..c2bb730b11
--- /dev/null
+++ b/src/glsl/glcpp/tests/012-define-func-no-args.c
@@ -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
index 0000000000..0353767297
--- /dev/null
+++ b/src/glsl/glcpp/tests/012-define-func-no-args.c.expected
@@ -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
index 0000000000..f78fb8b118
--- /dev/null
+++ b/src/glsl/glcpp/tests/013-define-func-1-arg-unused.c
@@ -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
index 0000000000..878fd15d6f
--- /dev/null
+++ b/src/glsl/glcpp/tests/013-define-func-1-arg-unused.c.expected
@@ -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
index 0000000000..11feb2624b
--- /dev/null
+++ b/src/glsl/glcpp/tests/014-define-func-2-arg-unused.c
@@ -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
index 0000000000..878fd15d6f
--- /dev/null
+++ b/src/glsl/glcpp/tests/014-define-func-2-arg-unused.c.expected
@@ -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
index 0000000000..558da9c617
--- /dev/null
+++ b/src/glsl/glcpp/tests/015-define-object-with-parens.c
@@ -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
index 0000000000..d6f8cb9dc6
--- /dev/null
+++ b/src/glsl/glcpp/tests/015-define-object-with-parens.c.expected
@@ -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
index 0000000000..a2e2404c7c
--- /dev/null
+++ b/src/glsl/glcpp/tests/016-define-func-1-arg.c
@@ -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
index 0000000000..7f1828a3c6
--- /dev/null
+++ b/src/glsl/glcpp/tests/016-define-func-1-arg.c.expected
@@ -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
index 0000000000..c725383527
--- /dev/null
+++ b/src/glsl/glcpp/tests/017-define-func-2-args.c
@@ -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
index 0000000000..9f341dac00
--- /dev/null
+++ b/src/glsl/glcpp/tests/017-define-func-2-args.c.expected
@@ -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
index 0000000000..668130b8f9
--- /dev/null
+++ b/src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c
@@ -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
index 0000000000..43d484d713
--- /dev/null
+++ b/src/glsl/glcpp/tests/018-define-func-macro-as-parameter.c.expected
@@ -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
index 0000000000..c4e62b2550
--- /dev/null
+++ b/src/glsl/glcpp/tests/019-define-func-1-arg-multi.c
@@ -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
index 0000000000..4314fc88d8
--- /dev/null
+++ b/src/glsl/glcpp/tests/019-define-func-1-arg-multi.c.expected
@@ -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
index 0000000000..3049ad1546
--- /dev/null
+++ b/src/glsl/glcpp/tests/020-define-func-2-arg-multi.c
@@ -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
index 0000000000..5648e4fb9d
--- /dev/null
+++ b/src/glsl/glcpp/tests/020-define-func-2-arg-multi.c.expected
@@ -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
index 0000000000..21ddd0e65f
--- /dev/null
+++ b/src/glsl/glcpp/tests/021-define-func-compose.c
@@ -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
index 0000000000..1d62105de4
--- /dev/null
+++ b/src/glsl/glcpp/tests/021-define-func-compose.c.expected
@@ -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
index 0000000000..c20d73a4a2
--- /dev/null
+++ b/src/glsl/glcpp/tests/022-define-func-arg-with-parens.c
@@ -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
index 0000000000..66c1658175
--- /dev/null
+++ b/src/glsl/glcpp/tests/022-define-func-arg-with-parens.c.expected
@@ -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
index 0000000000..7ebfed6516
--- /dev/null
+++ b/src/glsl/glcpp/tests/023-define-extra-whitespace.c
@@ -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
index 0000000000..573829c2d6
--- /dev/null
+++ b/src/glsl/glcpp/tests/023-define-extra-whitespace.c.expected
@@ -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
index 0000000000..e788adce30
--- /dev/null
+++ b/src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c
@@ -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
index 0000000000..ad955fce6e
--- /dev/null
+++ b/src/glsl/glcpp/tests/024-define-chain-to-self-recursion.c.expected
@@ -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
index 0000000000..b433671d1b
--- /dev/null
+++ b/src/glsl/glcpp/tests/025-func-macro-as-non-macro.c
@@ -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
index 0000000000..960f44511a
--- /dev/null
+++ b/src/glsl/glcpp/tests/025-func-macro-as-non-macro.c.expected
@@ -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
index 0000000000..0d83740530
--- /dev/null
+++ b/src/glsl/glcpp/tests/026-define-func-extra-newlines.c
@@ -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
index 0000000000..f0888f21b9
--- /dev/null
+++ b/src/glsl/glcpp/tests/026-define-func-extra-newlines.c.expected
@@ -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
index 0000000000..5ccb52caba
--- /dev/null
+++ b/src/glsl/glcpp/tests/027-define-chain-obj-to-func.c
@@ -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
index 0000000000..aef762e1e6
--- /dev/null
+++ b/src/glsl/glcpp/tests/027-define-chain-obj-to-func.c.expected
@@ -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
index 0000000000..44962a7187
--- /dev/null
+++ b/src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c
@@ -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
index 0000000000..aef762e1e6
--- /dev/null
+++ b/src/glsl/glcpp/tests/028-define-chain-obj-to-non-func.c.expected
@@ -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
index 0000000000..261f7d28fc
--- /dev/null
+++ b/src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c
@@ -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
index 0000000000..aef762e1e6
--- /dev/null
+++ b/src/glsl/glcpp/tests/029-define-chain-obj-to-func-with-args.c.expected
@@ -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
index 0000000000..e56fbefd62
--- /dev/null
+++ b/src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c
@@ -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
index 0000000000..729bdd15f8
--- /dev/null
+++ b/src/glsl/glcpp/tests/030-define-chain-obj-to-func-compose.c.expected
@@ -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
index 0000000000..3f4c8744df
--- /dev/null
+++ b/src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c
@@ -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
index 0000000000..729bdd15f8
--- /dev/null
+++ b/src/glsl/glcpp/tests/031-define-chain-func-to-func-compose.c.expected
@@ -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
index 0000000000..b3ac70f499
--- /dev/null
+++ b/src/glsl/glcpp/tests/032-define-func-self-recurse.c
@@ -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
index 0000000000..541d44db7a
--- /dev/null
+++ b/src/glsl/glcpp/tests/032-define-func-self-recurse.c.expected
@@ -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
index 0000000000..f65e48286c
--- /dev/null
+++ b/src/glsl/glcpp/tests/033-define-func-self-compose.c
@@ -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
index 0000000000..6ea6905d80
--- /dev/null
+++ b/src/glsl/glcpp/tests/033-define-func-self-compose.c.expected
@@ -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
index 0000000000..209a5f7e07
--- /dev/null
+++ b/src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c
@@ -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
index 0000000000..24823b1b67
--- /dev/null
+++ b/src/glsl/glcpp/tests/034-define-func-self-compose-non-func.c.expected
@@ -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
index 0000000000..c307fbe830
--- /dev/null
+++ b/src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c
@@ -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
index 0000000000..137a9ea2db
--- /dev/null
+++ b/src/glsl/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c.expected
@@ -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
index 0000000000..b21ff33673
--- /dev/null
+++ b/src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c
@@ -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
index 0000000000..ff6360bfe4
--- /dev/null
+++ b/src/glsl/glcpp/tests/036-define-func-non-macro-multi-token-argument.c.expected
@@ -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
index 0000000000..b3a2f37f1b
--- /dev/null
+++ b/src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c
@@ -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
index 0000000000..cbadee848a
--- /dev/null
+++ b/src/glsl/glcpp/tests/037-finalize-unexpanded-macro.c.expected
@@ -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
index 0000000000..1407c7d6e3
--- /dev/null
+++ b/src/glsl/glcpp/tests/038-func-arg-with-commas.c
@@ -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
index 0000000000..5a28fb3b66
--- /dev/null
+++ b/src/glsl/glcpp/tests/038-func-arg-with-commas.c.expected
@@ -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
index 0000000000..0f7fe632b5
--- /dev/null
+++ b/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c
@@ -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
index 0000000000..b73869d023
--- /dev/null
+++ b/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected
@@ -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
index 0000000000..caab3ba736
--- /dev/null
+++ b/src/glsl/glcpp/tests/040-token-pasting.c
@@ -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
index 0000000000..36f6699253
--- /dev/null
+++ b/src/glsl/glcpp/tests/040-token-pasting.c.expected
@@ -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
index 0000000000..2cab677d3e
--- /dev/null
+++ b/src/glsl/glcpp/tests/041-if-0.c
@@ -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
index 0000000000..3800024c6f
--- /dev/null
+++ b/src/glsl/glcpp/tests/041-if-0.c.expected
@@ -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
index 0000000000..874a25cf41
--- /dev/null
+++ b/src/glsl/glcpp/tests/042-if-1.c
@@ -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
index 0000000000..e591044adb
--- /dev/null
+++ b/src/glsl/glcpp/tests/042-if-1.c.expected
@@ -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
index 0000000000..323351f9db
--- /dev/null
+++ b/src/glsl/glcpp/tests/043-if-0-else.c
@@ -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
index 0000000000..ee9e677096
--- /dev/null
+++ b/src/glsl/glcpp/tests/043-if-0-else.c.expected
@@ -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
index 0000000000..28dfc25c6f
--- /dev/null
+++ b/src/glsl/glcpp/tests/044-if-1-else.c
@@ -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
index 0000000000..129f5c8542
--- /dev/null
+++ b/src/glsl/glcpp/tests/044-if-1-else.c.expected
@@ -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
index 0000000000..e50f686d46
--- /dev/null
+++ b/src/glsl/glcpp/tests/045-if-0-elif.c
@@ -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
index 0000000000..97a11b4472
--- /dev/null
+++ b/src/glsl/glcpp/tests/045-if-0-elif.c.expected
@@ -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
index 0000000000..130515a01e
--- /dev/null
+++ b/src/glsl/glcpp/tests/046-if-1-elsif.c
@@ -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
index 0000000000..b928b917e3
--- /dev/null
+++ b/src/glsl/glcpp/tests/046-if-1-elsif.c.expected
@@ -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
index 0000000000..e8f0838a9e
--- /dev/null
+++ b/src/glsl/glcpp/tests/047-if-elif-else.c
@@ -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
index 0000000000..e5b53a3fa5
--- /dev/null
+++ b/src/glsl/glcpp/tests/047-if-elif-else.c.expected
@@ -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
index 0000000000..fc4679c3be
--- /dev/null
+++ b/src/glsl/glcpp/tests/048-if-nested.c
@@ -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
index 0000000000..c61fd0b315
--- /dev/null
+++ b/src/glsl/glcpp/tests/048-if-nested.c.expected
@@ -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
index 0000000000..833ea03882
--- /dev/null
+++ b/src/glsl/glcpp/tests/049-if-expression-precedence.c
@@ -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
index 0000000000..569debb0bb
--- /dev/null
+++ b/src/glsl/glcpp/tests/049-if-expression-precedence.c.expected
@@ -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
index 0000000000..34f0f95140
--- /dev/null
+++ b/src/glsl/glcpp/tests/050-if-defined.c
@@ -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
index 0000000000..3f01955ee4
--- /dev/null
+++ b/src/glsl/glcpp/tests/050-if-defined.c.expected
@@ -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
index 0000000000..c3db488e0d
--- /dev/null
+++ b/src/glsl/glcpp/tests/051-if-relational.c
@@ -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
index 0000000000..d2b76f1457
--- /dev/null
+++ b/src/glsl/glcpp/tests/051-if-relational.c.expected
@@ -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
index 0000000000..2d8e45eb61
--- /dev/null
+++ b/src/glsl/glcpp/tests/052-if-bitwise.c
@@ -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
index 0000000000..bb5d92e8d9
--- /dev/null
+++ b/src/glsl/glcpp/tests/052-if-bitwise.c.expected
@@ -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
index 0000000000..d24c54a88d
--- /dev/null
+++ b/src/glsl/glcpp/tests/053-if-divide-and-shift.c
@@ -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
index 0000000000..f97e93673c
--- /dev/null
+++ b/src/glsl/glcpp/tests/053-if-divide-and-shift.c.expected
@@ -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
index 0000000000..3da79a0d96
--- /dev/null
+++ b/src/glsl/glcpp/tests/054-if-with-macros.c
@@ -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
index 0000000000..27ea496962
--- /dev/null
+++ b/src/glsl/glcpp/tests/054-if-with-macros.c.expected
@@ -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
index 0000000000..00f2c2346d
--- /dev/null
+++ b/src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c
@@ -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
index 0000000000..aef762e1e6
--- /dev/null
+++ b/src/glsl/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c.expected
@@ -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
index 0000000000..58701d1f25
--- /dev/null
+++ b/src/glsl/glcpp/tests/056-macro-argument-with-comma.c
@@ -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
index 0000000000..729bdd15f8
--- /dev/null
+++ b/src/glsl/glcpp/tests/056-macro-argument-with-comma.c.expected
@@ -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
index 0000000000..6140232865
--- /dev/null
+++ b/src/glsl/glcpp/tests/057-empty-arguments.c
@@ -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
index 0000000000..4e3aad5217
--- /dev/null
+++ b/src/glsl/glcpp/tests/057-empty-arguments.c.expected
@@ -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
index 0000000000..8ac260c76b
--- /dev/null
+++ b/src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c
@@ -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
index 0000000000..a1c34e5c1f
--- /dev/null
+++ b/src/glsl/glcpp/tests/058-token-pasting-empty-arguments.c.expected
@@ -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
index 0000000000..37b895a423
--- /dev/null
+++ b/src/glsl/glcpp/tests/059-token-pasting-integer.c
@@ -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
index 0000000000..f1a2cd21c1
--- /dev/null
+++ b/src/glsl/glcpp/tests/059-token-pasting-integer.c.expected
@@ -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
index 0000000000..ed80ea879c
--- /dev/null
+++ b/src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c
@@ -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
index 0000000000..c1f0d24a14
--- /dev/null
+++ b/src/glsl/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c.expected
@@ -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
index 0000000000..6dbfd1f62d
--- /dev/null
+++ b/src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c
@@ -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
index 0000000000..111f7d1063
--- /dev/null
+++ b/src/glsl/glcpp/tests/061-define-chain-obj-to-func-multi.c.expected
@@ -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
index 0000000000..d9e439bb89
--- /dev/null
+++ b/src/glsl/glcpp/tests/062-if-0-skips-garbage.c
@@ -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
index 0000000000..6fb66a5e2f
--- /dev/null
+++ b/src/glsl/glcpp/tests/062-if-0-skips-garbage.c.expected
@@ -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
index 0000000000..e641d2f0f9
--- /dev/null
+++ b/src/glsl/glcpp/tests/063-comments.c
@@ -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
index 0000000000..ed4feedd45
--- /dev/null
+++ b/src/glsl/glcpp/tests/063-comments.c.expected
@@ -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
index 0000000000..21326481b8
--- /dev/null
+++ b/src/glsl/glcpp/tests/064-version.c
@@ -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
index 0000000000..3af71113c8
--- /dev/null
+++ b/src/glsl/glcpp/tests/064-version.c.expected
@@ -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
index 0000000000..48aa0f8c3e
--- /dev/null
+++ b/src/glsl/glcpp/tests/065-if-defined-parens.c
@@ -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
index 0000000000..3f01955ee4
--- /dev/null
+++ b/src/glsl/glcpp/tests/065-if-defined-parens.c.expected
@@ -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
index 0000000000..3b0b47349d
--- /dev/null
+++ b/src/glsl/glcpp/tests/066-if-nospace-expression.c
@@ -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
index 0000000000..0e84a7cda3
--- /dev/null
+++ b/src/glsl/glcpp/tests/066-if-nospace-expression.c.expected
@@ -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
index 0000000000..f46cce4e60
--- /dev/null
+++ b/src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c
@@ -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
index 0000000000..3340daaa1f
--- /dev/null
+++ b/src/glsl/glcpp/tests/067-nested-ifdef-ifndef.c.expected
@@ -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
index 0000000000..699ac5144e
--- /dev/null
+++ b/src/glsl/glcpp/tests/068-accidental-pasting.c
@@ -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
index 0000000000..ce41cd6e52
--- /dev/null
+++ b/src/glsl/glcpp/tests/068-accidental-pasting.c.expected
@@ -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
index 0000000000..2b46ead294
--- /dev/null
+++ b/src/glsl/glcpp/tests/069-repeated-argument.c
@@ -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
index 0000000000..755c4d4b56
--- /dev/null
+++ b/src/glsl/glcpp/tests/069-repeated-argument.c.expected
@@ -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
index 0000000000..b6dc2ba075
--- /dev/null
+++ b/src/glsl/glcpp/tests/070-undefined-macro-in-expression.c
@@ -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
index 0000000000..2bb38a1411
--- /dev/null
+++ b/src/glsl/glcpp/tests/070-undefined-macro-in-expression.c.expected
@@ -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
index 0000000000..959d682598
--- /dev/null
+++ b/src/glsl/glcpp/tests/071-punctuator.c
@@ -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
index 0000000000..fee253b745
--- /dev/null
+++ b/src/glsl/glcpp/tests/071-punctuator.c.expected
@@ -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
index 0000000000..e421e9d5e2
--- /dev/null
+++ b/src/glsl/glcpp/tests/072-token-pasting-same-line.c
@@ -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
index 0000000000..c780b43d70
--- /dev/null
+++ b/src/glsl/glcpp/tests/072-token-pasting-same-line.c.expected
@@ -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
index 0000000000..61a48097ca
--- /dev/null
+++ b/src/glsl/glcpp/tests/073-if-in-ifdef.c
@@ -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
index 0000000000..3f2ff2d6cc
--- /dev/null
+++ b/src/glsl/glcpp/tests/073-if-in-ifdef.c.expected
@@ -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
index 0000000000..67aac8977e
--- /dev/null
+++ b/src/glsl/glcpp/tests/074-elif-undef.c
@@ -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
index 0000000000..fd40910d9e
--- /dev/null
+++ b/src/glsl/glcpp/tests/074-elif-undef.c.expected
@@ -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
index 0000000000..264bc4f10e
--- /dev/null
+++ b/src/glsl/glcpp/tests/075-elif-elif-undef.c
@@ -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
index 0000000000..3f2ff2d6cc
--- /dev/null
+++ b/src/glsl/glcpp/tests/075-elif-elif-undef.c.expected
@@ -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
index 0000000000..ebd550ed00
--- /dev/null
+++ b/src/glsl/glcpp/tests/076-elif-undef-nested.c
@@ -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
index 0000000000..6fb66a5e2f
--- /dev/null
+++ b/src/glsl/glcpp/tests/076-elif-undef-nested.c.expected
@@ -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
index 0000000000..81f00bfe27
--- /dev/null
+++ b/src/glsl/glcpp/tests/077-else-without-if.c
@@ -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
index 0000000000..d289b36356
--- /dev/null
+++ b/src/glsl/glcpp/tests/077-else-without-if.c.expected
@@ -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
index 0000000000..60466b3890
--- /dev/null
+++ b/src/glsl/glcpp/tests/078-elif-without-if.c
@@ -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
index 0000000000..7d41f0ac79
--- /dev/null
+++ b/src/glsl/glcpp/tests/078-elif-without-if.c.expected
@@ -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
index 0000000000..69331c3ca9
--- /dev/null
+++ b/src/glsl/glcpp/tests/079-endif-without-if.c
@@ -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
index 0000000000..08dd33546f
--- /dev/null
+++ b/src/glsl/glcpp/tests/079-endif-without-if.c.expected
@@ -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
index 0000000000..a27ba36a36
--- /dev/null
+++ b/src/glsl/glcpp/tests/080-if-without-expression.c
@@ -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
index 0000000000..768ba0f473
--- /dev/null
+++ b/src/glsl/glcpp/tests/080-if-without-expression.c.expected
@@ -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
index 0000000000..79c78663dd
--- /dev/null
+++ b/src/glsl/glcpp/tests/081-elif-without-expression.c
@@ -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
index 0000000000..974f0f550e
--- /dev/null
+++ b/src/glsl/glcpp/tests/081-elif-without-expression.c.expected
@@ -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
index 0000000000..40bf64411c
--- /dev/null
+++ b/src/glsl/glcpp/tests/082-invalid-paste.c
@@ -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
index 0000000000..2c924406b5
--- /dev/null
+++ b/src/glsl/glcpp/tests/082-invalid-paste.c.expected
@@ -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
index 0000000000..9180635092
--- /dev/null
+++ b/src/glsl/glcpp/tests/083-unterminated-if.c
@@ -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
index 0000000000..a69f8bab58
--- /dev/null
+++ b/src/glsl/glcpp/tests/083-unterminated-if.c.expected
@@ -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
index 0000000000..0789ba5e52
--- /dev/null
+++ b/src/glsl/glcpp/tests/084-unbalanced-parentheses.c
@@ -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
index 0000000000..91bea60061
--- /dev/null
+++ b/src/glsl/glcpp/tests/085-incorrect-argument-count.c
@@ -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
index 0000000000..1df30cbb56
--- /dev/null
+++ b/src/glsl/glcpp/tests/085-incorrect-argument-count.c.expected
@@ -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
index 0000000000..fd0c29f0c4
--- /dev/null
+++ b/src/glsl/glcpp/tests/086-reserved-macro-names.c
@@ -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
index 0000000000..6a9df68268
--- /dev/null
+++ b/src/glsl/glcpp/tests/086-reserved-macro-names.c.expected
@@ -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
index 0000000000..ce8dc43057
--- /dev/null
+++ b/src/glsl/glcpp/tests/087-if-comments.c
@@ -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
index 0000000000..827e548fe5
--- /dev/null
+++ b/src/glsl/glcpp/tests/087-if-comments.c.expected
@@ -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
index 0000000000..0e0666b8b3
--- /dev/null
+++ b/src/glsl/glcpp/tests/088-redefine-macro-legitimate.c
@@ -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
index 0000000000..6fb66a5e2f
--- /dev/null
+++ b/src/glsl/glcpp/tests/088-redefine-macro-legitimate.c.expected
@@ -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
index 0000000000..b3d1391e16
--- /dev/null
+++ b/src/glsl/glcpp/tests/089-redefine-macro-error.c
@@ -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
index 0000000000..6209ead559
--- /dev/null
+++ b/src/glsl/glcpp/tests/089-redefine-macro-error.c.expected
@@ -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
index 0000000000..d19bb7faed
--- /dev/null
+++ b/src/glsl/glcpp/tests/090-hash-error.c
@@ -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
index 0000000000..f2f1fbeaf8
--- /dev/null
+++ b/src/glsl/glcpp/tests/090-hash-error.c.expected
@@ -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
index 0000000000..fea35d37b0
--- /dev/null
+++ b/src/glsl/glcpp/tests/091-hash-line.c
@@ -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
index 0000000000..e663398c16
--- /dev/null
+++ b/src/glsl/glcpp/tests/091-hash-line.c.expected
@@ -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
index 0000000000..d1976b1f26
--- /dev/null
+++ b/src/glsl/glcpp/tests/099-c99-example.c
@@ -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
index 0000000000..19be750555
--- /dev/null
+++ b/src/glsl/glcpp/tests/099-c99-example.c.expected
@@ -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
index 0000000000..5dc08ea6ac
--- /dev/null
+++ b/src/glsl/glcpp/tests/glcpp-test
@@ -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
index 0000000000..873df609d3
--- /dev/null
+++ b/src/glsl/glsl_lexer.cpp
@@ -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
index 0000000000..1de1fb4cf7
--- /dev/null
+++ b/src/glsl/glsl_lexer.lpp
@@ -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
index 0000000000..e36bb03c43
--- /dev/null
+++ b/src/glsl/glsl_parser.cpp
@@ -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
+
+
+
+#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 */
+
+
+/*-----------------------------------------------.
+| 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
index 0000000000..3ed90853ad
--- /dev/null
+++ b/src/glsl/glsl_parser.h
@@ -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
index 0000000000..6d99c52503
--- /dev/null
+++ b/src/glsl/glsl_parser.ypp
@@ -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
index 0000000000..bc56e4fcaf
--- /dev/null
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -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
index 0000000000..3ccdab4ef2
--- /dev/null
+++ b/src/glsl/glsl_parser_extras.h
@@ -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
index 0000000000..e9bf89b951
--- /dev/null
+++ b/src/glsl/glsl_symbol_table.cpp
@@ -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
index 0000000000..f26de52432
--- /dev/null
+++ b/src/glsl/glsl_symbol_table.h
@@ -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
index 0000000000..92ad3efafc
--- /dev/null
+++ b/src/glsl/glsl_types.cpp
@@ -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
index 0000000000..b4e83c9833
--- /dev/null
+++ b/src/glsl/glsl_types.h
@@ -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
index 0000000000..3c33127b5f
--- /dev/null
+++ b/src/glsl/hir_field_selection.cpp
@@ -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
index 0000000000..68ad512bf5
--- /dev/null
+++ b/src/glsl/ir.cpp
@@ -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
index 0000000000..0f887a9327
--- /dev/null
+++ b/src/glsl/ir.h
@@ -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
index 0000000000..ff81563f19
--- /dev/null
+++ b/src/glsl/ir_algebraic.cpp
@@ -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
index 0000000000..a833825962
--- /dev/null
+++ b/src/glsl/ir_basic_block.cpp
@@ -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
index 0000000000..dbd678b5c4
--- /dev/null
+++ b/src/glsl/ir_basic_block.h
@@ -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
index 0000000000..1d690a4da7
--- /dev/null
+++ b/src/glsl/ir_clone.cpp
@@ -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
index 0000000000..458dca7977
--- /dev/null
+++ b/src/glsl/ir_constant_expression.cpp
@@ -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
index 0000000000..554c54fae3
--- /dev/null
+++ b/src/glsl/ir_constant_folding.cpp
@@ -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
index 0000000000..76c1ce7013
--- /dev/null
+++ b/src/glsl/ir_constant_propagation.cpp
@@ -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
index 0000000000..1fb73e765e
--- /dev/null
+++ b/src/glsl/ir_constant_variable.cpp
@@ -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
index 0000000000..6c211f0e70
--- /dev/null
+++ b/src/glsl/ir_copy_propagation.cpp
@@ -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
index 0000000000..5cf5e99add
--- /dev/null
+++ b/src/glsl/ir_dead_code.cpp
@@ -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
index 0000000000..4bbedf0ff9
--- /dev/null
+++ b/src/glsl/ir_dead_code_local.cpp
@@ -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
index 0000000000..26554441d3
--- /dev/null
+++ b/src/glsl/ir_dead_functions.cpp
@@ -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
index 0000000000..640d5d64f9
--- /dev/null
+++ b/src/glsl/ir_div_to_mul_rcp.cpp
@@ -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
index 0000000000..78694a2029
--- /dev/null
+++ b/src/glsl/ir_explog_to_explog2.cpp
@@ -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
index 0000000000..7b1b8dbfef
--- /dev/null
+++ b/src/glsl/ir_expression_flattening.cpp
@@ -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
index 0000000000..2eda159000
--- /dev/null
+++ b/src/glsl/ir_expression_flattening.h
@@ -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
index 0000000000..dfdec144b2
--- /dev/null
+++ b/src/glsl/ir_function.cpp
@@ -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
index 0000000000..8bb8e0d9ed
--- /dev/null
+++ b/src/glsl/ir_function_can_inline.cpp
@@ -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
index 0000000000..874602c84f
--- /dev/null
+++ b/src/glsl/ir_function_inlining.cpp
@@ -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
index 0000000000..6db011bbca
--- /dev/null
+++ b/src/glsl/ir_function_inlining.h
@@ -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
index 0000000000..809b08ee62
--- /dev/null
+++ b/src/glsl/ir_hierarchical_visitor.cpp
@@ -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
index 0000000000..afa780dc91
--- /dev/null
+++ b/src/glsl/ir_hierarchical_visitor.h
@@ -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
index 0000000000..6dae4ed2f3
--- /dev/null
+++ b/src/glsl/ir_hv_accept.cpp
@@ -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
index 0000000000..5ab8759958
--- /dev/null
+++ b/src/glsl/ir_if_return.cpp
@@ -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
index 0000000000..6882ef72b9
--- /dev/null
+++ b/src/glsl/ir_if_simplification.cpp
@@ -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
index 0000000000..0b87413941
--- /dev/null
+++ b/src/glsl/ir_if_to_cond_assign.cpp
@@ -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
index 0000000000..a39b384071
--- /dev/null
+++ b/src/glsl/ir_import_prototypes.cpp
@@ -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
index 0000000000..da6de9492b
--- /dev/null
+++ b/src/glsl/ir_mat_op_to_vec.cpp
@@ -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
index 0000000000..71c9472b12
--- /dev/null
+++ b/src/glsl/ir_mod_to_fract.cpp
@@ -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
index 0000000000..b78c87b47f
--- /dev/null
+++ b/src/glsl/ir_noop_swizzle.cpp
@@ -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
index 0000000000..33f4bc78f7
--- /dev/null
+++ b/src/glsl/ir_optimization.h
@@ -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
index 0000000000..f47ad87550
--- /dev/null
+++ b/src/glsl/ir_print_visitor.cpp
@@ -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
index 0000000000..4feeb8c184
--- /dev/null
+++ b/src/glsl/ir_print_visitor.h
@@ -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
index 0000000000..e57e03c307
--- /dev/null
+++ b/src/glsl/ir_reader.cpp
@@ -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
index 0000000000..aef2ca23bd
--- /dev/null
+++ b/src/glsl/ir_reader.h
@@ -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
index 0000000000..613b07c302
--- /dev/null
+++ b/src/glsl/ir_rvalue_visitor.cpp
@@ -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
index 0000000000..31a56beb9b
--- /dev/null
+++ b/src/glsl/ir_rvalue_visitor.h
@@ -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
index 0000000000..b3f1cc0d8b
--- /dev/null
+++ b/src/glsl/ir_set_program_inouts.cpp
@@ -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
index 0000000000..ff3ec936eb
--- /dev/null
+++ b/src/glsl/ir_structure_splitting.cpp
@@ -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
index 0000000000..7ed8c1495e
--- /dev/null
+++ b/src/glsl/ir_sub_to_add_neg.cpp
@@ -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
index 0000000000..0ffb4fa313
--- /dev/null
+++ b/src/glsl/ir_swizzle_swizzle.cpp
@@ -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
index 0000000000..9b569b8284
--- /dev/null
+++ b/src/glsl/ir_tree_grafting.cpp
@@ -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
index 0000000000..9ea11dd400
--- /dev/null
+++ b/src/glsl/ir_validate.cpp
@@ -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
index 0000000000..e638c9602f
--- /dev/null
+++ b/src/glsl/ir_variable.cpp
@@ -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
index 0000000000..7d39abb368
--- /dev/null
+++ b/src/glsl/ir_variable_refcount.cpp
@@ -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
index 0000000000..8b43bad71f
--- /dev/null
+++ b/src/glsl/ir_variable_refcount.h
@@ -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
index 0000000000..cd8dedf2fe
--- /dev/null
+++ b/src/glsl/ir_vec_index_to_cond_assign.cpp
@@ -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
index 0000000000..969dc8f94a
--- /dev/null
+++ b/src/glsl/ir_vec_index_to_swizzle.cpp
@@ -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
index 0000000000..b87d737318
--- /dev/null
+++ b/src/glsl/ir_visitor.h
@@ -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
index 0000000000..78c8b48cf1
--- /dev/null
+++ b/src/glsl/link_functions.cpp
@@ -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
index 0000000000..e0823c3af4
--- /dev/null
+++ b/src/glsl/linker.cpp
@@ -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
index 0000000000..a8ce16a7ec
--- /dev/null
+++ b/src/glsl/linker.h
@@ -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
index 0000000000..a70b79d571
--- /dev/null
+++ b/src/glsl/list.h
@@ -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
index 0000000000..cb9f8a5277
--- /dev/null
+++ b/src/glsl/main.cpp
@@ -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
index fda1c4202b..0000000000
--- a/src/glsl/pp/Makefile
+++ /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
index b8e1e99fc8..0000000000
--- a/src/glsl/pp/sl_pp_context.c
+++ /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
index e6244f6257..0000000000
--- a/src/glsl/pp/sl_pp_context.h
+++ /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
index 370e6aa660..0000000000
--- a/src/glsl/pp/sl_pp_define.c
+++ /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
index 062139e6ac..0000000000
--- a/src/glsl/pp/sl_pp_dict.c
+++ /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_error.c b/src/glsl/pp/sl_pp_error.c
deleted file mode 100644
index 482b67fcaf..0000000000
--- a/src/glsl/pp/sl_pp_error.c
+++ /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
index c3f48356b0..0000000000
--- a/src/glsl/pp/sl_pp_expression.c
+++ /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
index 522263bb25..0000000000
--- a/src/glsl/pp/sl_pp_expression.h
+++ /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
index 00dbdcf22b..0000000000
--- a/src/glsl/pp/sl_pp_extension.c
+++ /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
index 6b7a1590b4..0000000000
--- a/src/glsl/pp/sl_pp_if.c
+++ /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
index 51581c7bb5..0000000000
--- a/src/glsl/pp/sl_pp_line.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL 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
index 2cf9ea342b..0000000000
--- a/src/glsl/pp/sl_pp_macro.c
+++ /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
index 6e65a0a588..0000000000
--- a/src/glsl/pp/sl_pp_macro.h
+++ /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
index 6789704db0..0000000000
--- a/src/glsl/pp/sl_pp_pragma.c
+++ /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
index 2f12393237..0000000000
--- a/src/glsl/pp/sl_pp_process.c
+++ /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
index 04e9be4398..0000000000
--- a/src/glsl/pp/sl_pp_process.h
+++ /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
index 66ced6cf58..0000000000
--- a/src/glsl/pp/sl_pp_public.h
+++ /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
index acc000cf3d..0000000000
--- a/src/glsl/pp/sl_pp_purify.c
+++ /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
index c0f55cbfd8..0000000000
--- a/src/glsl/pp/sl_pp_purify.h
+++ /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
index a708978700..0000000000
--- a/src/glsl/pp/sl_pp_token.c
+++ /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
index a12b193401..0000000000
--- a/src/glsl/pp/sl_pp_token.h
+++ /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
index 43be49670b..0000000000
--- a/src/glsl/pp/sl_pp_token_util.c
+++ /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
index 35d72101ca..0000000000
--- a/src/glsl/pp/sl_pp_token_util.h
+++ /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
index 6735c05e8a..0000000000
--- a/src/glsl/pp/sl_pp_version.c
+++ /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/mesa/slang/library/slang_builtin_120_fragment.gc b/src/glsl/program.h
index 7d516046a1..893169b6cc 100644
--- a/src/mesa/slang/library/slang_builtin_120_fragment.gc
+++ b/src/glsl/program.h
@@ -1,8 +1,7 @@
/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 2006 Brian Paul All Rights Reserved.
+ * 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"),
@@ -22,9 +21,7 @@
* 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;
+#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
index 0000000000..4458c48d6b
--- /dev/null
+++ b/src/glsl/s_expression.cpp
@@ -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
index 0000000000..aa22475a1b
--- /dev/null
+++ b/src/glsl/s_expression.h
@@ -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
index 0000000000..d14135fb3a
--- /dev/null
+++ b/src/glsl/tests/array-01.glsl
@@ -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
index 0000000000..d743617158
--- /dev/null
+++ b/src/glsl/tests/array-02.glsl
@@ -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
index 0000000000..0026913f01
--- /dev/null
+++ b/src/glsl/tests/array-03.glsl
@@ -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
index 0000000000..70f434d8ab
--- /dev/null
+++ b/src/glsl/tests/array-04.glsl
@@ -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
index 0000000000..168704096b
--- /dev/null
+++ b/src/glsl/tests/array-05.glsl
@@ -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
index 0000000000..46b43795be
--- /dev/null
+++ b/src/glsl/tests/array-06.glsl
@@ -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
index 0000000000..161ffbf2f2
--- /dev/null
+++ b/src/glsl/tests/array-07.glsl
@@ -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
index 0000000000..4bf0c6bd51
--- /dev/null
+++ b/src/glsl/tests/array-08.glsl
@@ -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
index 0000000000..cad6d0e54e
--- /dev/null
+++ b/src/glsl/tests/array-09.glsl
@@ -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
index 0000000000..019aa21150
--- /dev/null
+++ b/src/glsl/tests/array-10.glsl
@@ -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
index 0000000000..51d94e9477
--- /dev/null
+++ b/src/glsl/tests/array-11.glsl
@@ -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
index 0000000000..7fc9579452
--- /dev/null
+++ b/src/glsl/tests/array-12.glsl
@@ -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
index 0000000000..cc7e29a5f7
--- /dev/null
+++ b/src/glsl/tests/array-13.glsl
@@ -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
index 0000000000..18e9e4468a
--- /dev/null
+++ b/src/glsl/tests/attribute-01.glsl
@@ -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
index 0000000000..6b6df74d25
--- /dev/null
+++ b/src/glsl/tests/attribute-02.glsl
@@ -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
index 0000000000..870de9e814
--- /dev/null
+++ b/src/glsl/tests/attribute-03.glsl
@@ -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
index 0000000000..14af2fcaad
--- /dev/null
+++ b/src/glsl/tests/attribute-04.glsl
@@ -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
index 0000000000..18822c7854
--- /dev/null
+++ b/src/glsl/tests/attribute-05.glsl
@@ -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
index 0000000000..f18027b81a
--- /dev/null
+++ b/src/glsl/tests/attribute-06.glsl
@@ -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
index 0000000000..0af13ba84b
--- /dev/null
+++ b/src/glsl/tests/attribute-07.glsl
@@ -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
index 0000000000..b069c04d1b
--- /dev/null
+++ b/src/glsl/tests/attribute-08.glsl
@@ -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
index 0000000000..6a607244b9
--- /dev/null
+++ b/src/glsl/tests/attribute-09.glsl
@@ -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
index 0000000000..6f5ef63a01
--- /dev/null
+++ b/src/glsl/tests/attribute-10.glsl
@@ -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
index 0000000000..47cb5a0583
--- /dev/null
+++ b/src/glsl/tests/attribute-11.glsl
@@ -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
index 0000000000..d89c313117
--- /dev/null
+++ b/src/glsl/tests/condition-01.glsl
@@ -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
index 0000000000..cbd0e18d9a
--- /dev/null
+++ b/src/glsl/tests/condition-02.glsl
@@ -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
index 0000000000..9af5d7aa47
--- /dev/null
+++ b/src/glsl/tests/condition-03.glsl
@@ -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
index 0000000000..f440b7e995
--- /dev/null
+++ b/src/glsl/tests/condition-04.glsl
@@ -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
index 0000000000..3dff18f519
--- /dev/null
+++ b/src/glsl/tests/condition-05.glsl
@@ -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
index 0000000000..fdfaf89866
--- /dev/null
+++ b/src/glsl/tests/constructor-01.glsl
@@ -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
index 0000000000..47acbe9db1
--- /dev/null
+++ b/src/glsl/tests/constructor-02.glsl
@@ -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
index 0000000000..07ec225633
--- /dev/null
+++ b/src/glsl/tests/constructor-03.glsl
@@ -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
index 0000000000..19d5e011de
--- /dev/null
+++ b/src/glsl/tests/constructor-04.glsl
@@ -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
index 0000000000..9c74f75a40
--- /dev/null
+++ b/src/glsl/tests/constructor-05.glsl
@@ -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
index 0000000000..d77a5f9e89
--- /dev/null
+++ b/src/glsl/tests/constructor-06.glsl
@@ -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
index 0000000000..92322506ed
--- /dev/null
+++ b/src/glsl/tests/constructor-07.glsl
@@ -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
index 0000000000..27153f0cda
--- /dev/null
+++ b/src/glsl/tests/constructor-08.glsl
@@ -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
index 0000000000..1985699b30
--- /dev/null
+++ b/src/glsl/tests/constructor-09.glsl
@@ -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
index 0000000000..0eaa2397ab
--- /dev/null
+++ b/src/glsl/tests/function-01.glsl
@@ -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
index 0000000000..941fcc1ef7
--- /dev/null
+++ b/src/glsl/tests/function-02.glsl
@@ -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
index 0000000000..b0da42f8e9
--- /dev/null
+++ b/src/glsl/tests/function-03.glsl
@@ -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
index 0000000000..dfc0d2b7a6
--- /dev/null
+++ b/src/glsl/tests/function-04.glsl
@@ -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
index 0000000000..43365bf606
--- /dev/null
+++ b/src/glsl/tests/function-05.glsl
@@ -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
index 0000000000..ca9abd54f7
--- /dev/null
+++ b/src/glsl/tests/if-01.glsl
@@ -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
index 0000000000..7adccea043
--- /dev/null
+++ b/src/glsl/tests/if-02.glsl
@@ -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
index 0000000000..179618c716
--- /dev/null
+++ b/src/glsl/tests/if-03.glsl
@@ -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
index 0000000000..7b711fb7ed
--- /dev/null
+++ b/src/glsl/tests/if-04.glsl
@@ -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
index 0000000000..f46416c8f6
--- /dev/null
+++ b/src/glsl/tests/matrix-01.glsl
@@ -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
index 0000000000..0630722b79
--- /dev/null
+++ b/src/glsl/tests/matrix-02.glsl
@@ -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
index 0000000000..925dc80625
--- /dev/null
+++ b/src/glsl/tests/matrix-03.glsl
@@ -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
index 0000000000..5275619b31
--- /dev/null
+++ b/src/glsl/tests/matrix-04.glsl
@@ -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
index 0000000000..74e1fd2514
--- /dev/null
+++ b/src/glsl/tests/matrix-05.glsl
@@ -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
index 0000000000..0a512b8523
--- /dev/null
+++ b/src/glsl/tests/matrix-06.glsl
@@ -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
index 0000000000..0b59aa69d5
--- /dev/null
+++ b/src/glsl/tests/matrix-07.glsl
@@ -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
index 0000000000..38138d22de
--- /dev/null
+++ b/src/glsl/tests/matrix-08.glsl
@@ -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
index 0000000000..18afbcacea
--- /dev/null
+++ b/src/glsl/tests/matrix-09.glsl
@@ -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
index 0000000000..20b55180cb
--- /dev/null
+++ b/src/glsl/tests/matrix-10.glsl
@@ -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
index 0000000000..b485106e9d
--- /dev/null
+++ b/src/glsl/tests/parameters-01.glsl
@@ -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
index 0000000000..7ff5f59ab7
--- /dev/null
+++ b/src/glsl/tests/parameters-02.glsl
@@ -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
index 0000000000..7ec30f80cc
--- /dev/null
+++ b/src/glsl/tests/parameters-03.glsl
@@ -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
index 0000000000..54ec3572a2
--- /dev/null
+++ b/src/glsl/tests/qualifier-01.glsl
@@ -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
index 0000000000..b635d52aa2
--- /dev/null
+++ b/src/glsl/tests/qualifier-02.glsl
@@ -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
index 0000000000..7e448034a7
--- /dev/null
+++ b/src/glsl/tests/qualifier-03.glsl
@@ -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
index 0000000000..d03cafc1db
--- /dev/null
+++ b/src/glsl/tests/qualifier-04.glsl
@@ -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
index 0000000000..15281f3384
--- /dev/null
+++ b/src/glsl/tests/qualifier-05.glsl
@@ -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
index 0000000000..1907a087c8
--- /dev/null
+++ b/src/glsl/tests/qualifier-06.glsl
@@ -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
index 0000000000..12568a57db
--- /dev/null
+++ b/src/glsl/tests/qualifier-07.glsl
@@ -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
index 0000000000..3268fa178c
--- /dev/null
+++ b/src/glsl/tests/swiz-01.glsl
@@ -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
index 0000000000..e3f043c47b
--- /dev/null
+++ b/src/glsl/tests/swiz-02.glsl
@@ -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
index 0000000000..5719edc0b6
--- /dev/null
+++ b/src/glsl/tests/void-01.glsl
@@ -0,0 +1,2 @@
+/* FAIL - cannot declare a variable as having type `void' */
+void foo;
diff --git a/src/glut/glx/glut_init.c b/src/glut/glx/glut_init.c
index 842aefc93c..213819e751 100644
--- a/src/glut/glx/glut_init.c
+++ b/src/glut/glx/glut_init.c
@@ -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,
diff --git a/src/glx/Makefile b/src/glx/Makefile
index 9a22d0c547..ba5708ffed 100644
--- a/src/glx/Makefile
+++ b/src/glx/Makefile
@@ -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)
diff --git a/src/mapi/glapi/gen/glX_proto_send.py b/src/mapi/glapi/gen/glX_proto_send.py
index 0ca0ff92a6..bd41c9e667 100644
--- a/src/mapi/glapi/gen/glX_proto_send.py
+++ b/src/mapi/glapi/gen/glX_proto_send.py
@@ -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 */
{
diff --git a/src/mapi/glapi/glapi.h b/src/mapi/glapi/glapi.h
index a74884d595..a0bb078106 100644
--- a/src/mapi/glapi/glapi.h
+++ b/src/mapi/glapi/glapi.h
@@ -44,10 +44,30 @@
#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
@@ -57,32 +77,106 @@
#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 */
diff --git a/src/mapi/glapi/glapi_dispatch.c b/src/mapi/glapi/glapi_dispatch.c
index ae59140ad3..7421a36d35 100644
--- a/src/mapi/glapi/glapi_dispatch.c
+++ b/src/mapi/glapi/glapi_dispatch.c
@@ -37,18 +37,9 @@
* \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))
diff --git a/src/mapi/glapi/glapi_entrypoint.c b/src/mapi/glapi/glapi_entrypoint.c
index 82c68c27c8..993ccb94c2 100644
--- a/src/mapi/glapi/glapi_entrypoint.c
+++ b/src/mapi/glapi/glapi_entrypoint.c
@@ -29,15 +29,6 @@
*/
-#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"
diff --git a/src/mapi/glapi/glapi_getproc.c b/src/mapi/glapi/glapi_getproc.c
index 3c134f929d..dc4905b64e 100644
--- a/src/mapi/glapi/glapi_getproc.c
+++ b/src/mapi/glapi/glapi_getproc.c
@@ -30,15 +30,6 @@
*/
-#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"
diff --git a/src/mapi/glapi/glapi_nop.c b/src/mapi/glapi/glapi_nop.c
index 9709551ee7..9b09297150 100644
--- a/src/mapi/glapi/glapi_nop.c
+++ b/src/mapi/glapi/glapi_nop.c
@@ -38,28 +38,11 @@
-#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)
{
}
diff --git a/src/mapi/glapi/glapi_priv.h b/src/mapi/glapi/glapi_priv.h
index 1c2a704211..89f81c723e 100644
--- a/src/mapi/glapi/glapi_priv.h
+++ b/src/mapi/glapi/glapi_priv.h
@@ -26,9 +26,30 @@
#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 */
diff --git a/src/mapi/glapi/glthread.c b/src/mapi/glapi/glthread.c
index 9dbc0e9a56..00915380f9 100644
--- a/src/mapi/glapi/glthread.c
+++ b/src/mapi/glapi/glthread.c
@@ -1,4 +1,4 @@
-#include "glthread.h"
+#include "glapi/glapi.h"
unsigned long
_glthread_GetID(void)
diff --git a/src/mapi/glapi/glthread.h b/src/mapi/glapi/glthread.h
index 54292706ac..fc4ece7c33 100644
--- a/src/mapi/glapi/glthread.h
+++ b/src/mapi/glapi/glthread.h
@@ -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 */
diff --git a/src/mapi/mapi/entry_x86-64_tls.h b/src/mapi/mapi/entry_x86-64_tls.h
index d4c9907b89..0f6e8125e8 100644
--- a/src/mapi/mapi/entry_x86-64_tls.h
+++ b/src/mapi/mapi/entry_x86-64_tls.h
@@ -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)"
diff --git a/src/mapi/mapi/entry_x86_tls.h b/src/mapi/mapi/entry_x86_tls.h
index de0498181d..ff2b9575f6 100644
--- a/src/mapi/mapi/entry_x86_tls.h
+++ b/src/mapi/mapi/entry_x86_tls.h
@@ -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
diff --git a/src/mapi/mapi/entry_x86_tsd.h b/src/mapi/mapi/entry_x86_tsd.h
index d31e0676f0..fbf4ec5497 100644
--- a/src/mapi/mapi/entry_x86_tsd.h
+++ b/src/mapi/mapi/entry_x86_tsd.h
@@ -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
diff --git a/src/mapi/mapi/mapi.h b/src/mapi/mapi/mapi.h
index 8832b3dfb6..c7e43e22e9 100644
--- a/src/mapi/mapi/mapi.h
+++ b/src/mapi/mapi/mapi.h
@@ -31,26 +31,36 @@
#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_ */
diff --git a/src/mapi/mapi/u_current.c b/src/mapi/mapi/u_current.c
index 91547c4830..ed9ccfe229 100644
--- a/src/mapi/mapi/u_current.c
+++ b/src/mapi/mapi/u_current.c
@@ -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
}
diff --git a/src/mapi/mapi/u_current.h b/src/mapi/mapi/u_current.h
index a6256f5b51..62e54c6c93 100644
--- a/src/mapi/mapi/u_current.h
+++ b/src/mapi/mapi/u_current.h
@@ -1,93 +1,102 @@
#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_ */
diff --git a/src/mapi/vgapi/SConscript b/src/mapi/vgapi/SConscript
index bf51264ab9..20d7f2744d 100644
--- a/src/mapi/vgapi/SConscript
+++ b/src/mapi/vgapi/SConscript
@@ -18,6 +18,7 @@ if env['platform'] != 'winddk':
env.Append(CPPDEFINES = [
'MAPI_ABI_HEADER=\\"vgapi/vgapi_tmp.h\\"',
+ 'MAPI_DLL_EXPORTS',
'KHRONOS_DLL_EXPORTS',
])
diff --git a/src/mesa/Makefile b/src/mesa/Makefile
index 7073c92240..ef31fd24f0 100644
--- a/src/mesa/Makefile
+++ b/src/mesa/Makefile
@@ -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
@@ -121,12 +139,6 @@ asm_subdirs:
######################################################################
-# GLSL built-in library
-glsl_builtin:
- (cd slang/library && $(MAKE)) || exit 1 ;
-
-
-######################################################################
# Dependency generation
depend: $(ALL_SOURCES)
@@ -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
diff --git a/src/mesa/SConscript b/src/mesa/SConscript
index d31b957234..28598f4a17 100644
--- a/src/mesa/SConscript
+++ b/src/mesa/SConscript
@@ -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
#
diff --git a/src/mesa/drivers/dri/Makefile.template b/src/mesa/drivers/dri/Makefile.template
index 8cb25439e4..a00018cafa 100644
--- a/src/mesa/drivers/dri/Makefile.template
+++ b/src/mesa/drivers/dri/Makefile.template
@@ -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 $@
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
index dce84ef0de..a581c6663f 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -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;
}
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
index bc647ff813..5096d22cad 100644
--- a/src/mesa/drivers/dri/common/dri_util.h
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -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;
};
diff --git a/src/mesa/drivers/dri/i915/i830_context.c b/src/mesa/drivers/dri/i915/i830_context.c
index d52ea9812f..8ddce6d82a 100644
--- a/src/mesa/drivers/dri/i915/i830_context.c
+++ b/src/mesa/drivers/dri/i915/i830_context.c
@@ -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"
diff --git a/src/mesa/drivers/dri/i915/i915_context.c b/src/mesa/drivers/dri/i915/i915_context.c
index b3fe1c05d6..d8715cf026 100644
--- a/src/mesa/drivers/dri/i915/i915_context.c
+++ b/src/mesa/drivers/dri/i915/i915_context.c
@@ -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,
diff --git a/src/mesa/drivers/dri/i915/i915_fragprog.c b/src/mesa/drivers/dri/i915/i915_fragprog.c
index f1505dc5e7..4a2e6209d0 100644
--- a/src/mesa/drivers/dri/i915/i915_fragprog.c
+++ b/src/mesa/drivers/dri/i915/i915_fragprog.c
@@ -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);
diff --git a/src/mesa/drivers/dri/i965/Makefile b/src/mesa/drivers/dri/i965/Makefile
index e381a5c714..bea48e1313 100644
--- a/src/mesa/drivers/dri/i965/Makefile
+++ b/src/mesa/drivers/dri/i965/Makefile
@@ -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
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index 6d064b822e..d2b20165f9 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -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;
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index cc4e6638e8..703a7de78d 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -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
diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h
index f7a68cead7..6b8e9e05d0 100644
--- a/src/mesa/drivers/dri/i965/brw_defines.h
+++ b/src/mesa/drivers/dri/i965/brw_defines.h
@@ -686,6 +686,9 @@
#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
diff --git a/src/mesa/drivers/dri/i965/brw_disasm.c b/src/mesa/drivers/dri/i965/brw_disasm.c
index d230714536..f74a236834 100644
--- a/src/mesa/drivers/dri/i965/brw_disasm.c
+++ b/src/mesa/drivers/dri/i965/brw_disasm.c
@@ -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);
diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c
index f07aab86e9..249e874ab1 100644
--- a/src/mesa/drivers/dri/i965/brw_draw_upload.c
+++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c
@@ -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) |
diff --git a/src/mesa/drivers/dri/i965/brw_eu.c b/src/mesa/drivers/dri/i965/brw_eu.c
index 4e7c1226ad..2ff39e8e64 100644
--- a/src/mesa/drivers/dri/i965/brw_eu.c
+++ b/src/mesa/drivers/dri/i965/brw_eu.c
@@ -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]);
diff --git a/src/mesa/drivers/dri/i965/brw_eu.h b/src/mesa/drivers/dri/i965/brw_eu.h
index ffdddd0a38..c63db16460 100644
--- a/src/mesa/drivers/dri/i965/brw_eu.h
+++ b/src/mesa/drivers/dri/i965/brw_eu.h
@@ -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,
diff --git a/src/mesa/drivers/dri/i965/brw_eu_emit.c b/src/mesa/drivers/dri/i965/brw_eu_emit.c
index 0d5d17f501..0906150613 100644
--- a/src/mesa/drivers/dri/i965/brw_eu_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_eu_emit.c
@@ -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
index 0000000000..34c5d5262f
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -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
index 0000000000..d8d58a9467
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp
@@ -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
index 0000000000..00d5c20248
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp
@@ -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;
+}
+}
diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c
index 572175f463..6eeaba7772 100644
--- a/src/mesa/drivers/dri/i965/brw_misc_state.c
+++ b/src/mesa/drivers/dri/i965/brw_misc_state.c
@@ -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);
diff --git a/src/mesa/drivers/dri/i965/brw_optimize.c b/src/mesa/drivers/dri/i965/brw_optimize.c
index 8aa6fb6cc6..cbed2bd5cb 100644
--- a/src/mesa/drivers/dri/i965/brw_optimize.c
+++ b/src/mesa/drivers/dri/i965/brw_optimize.c
@@ -32,12 +32,7 @@
#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)
diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c
index 4b08d2599b..bc152204a4 100644
--- a/src/mesa/drivers/dri/i965/brw_program.c
+++ b/src/mesa/drivers/dri/i965/brw_program.c
@@ -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;
}
diff --git a/src/mesa/drivers/dri/i965/brw_state.h b/src/mesa/drivers/dri/i965/brw_state.h
index af08446f2d..c5d296b129 100644
--- a/src/mesa/drivers/dri/i965/brw_state.h
+++ b/src/mesa/drivers/dri/i965/brw_state.h
@@ -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;
/***********************************************************************
diff --git a/src/mesa/drivers/dri/i965/brw_state_upload.c b/src/mesa/drivers/dri/i965/brw_state_upload.c
index f92a19c2aa..a0c130557e 100644
--- a/src/mesa/drivers/dri/i965/brw_state_upload.c
+++ b/src/mesa/drivers/dri/i965/brw_state_upload.c
@@ -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 {
diff --git a/src/mesa/drivers/dri/i965/brw_structs.h b/src/mesa/drivers/dri/i965/brw_structs.h
index 2fde42a706..2a118e01c5 100644
--- a/src/mesa/drivers/dri/i965/brw_structs.h
+++ b/src/mesa/drivers/dri/i965/brw_structs.h
@@ -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;
diff --git a/src/mesa/drivers/dri/i965/brw_vs.c b/src/mesa/drivers/dri/i965/brw_vs.c
index 9a832af9a9..9f90e1e5e5 100644
--- a/src/mesa/drivers/dri/i965/brw_vs.c
+++ b/src/mesa/drivers/dri/i965/brw_vs.c
@@ -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.
*/
diff --git a/src/mesa/drivers/dri/i965/brw_vs_emit.c b/src/mesa/drivers/dri/i965/brw_vs_emit.c
index b6b558e9a6..1d88c6b5a4 100644
--- a/src/mesa/drivers/dri/i965/brw_vs_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_vs_emit.c
@@ -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");
}
}
diff --git a/src/mesa/drivers/dri/i965/brw_vtbl.c b/src/mesa/drivers/dri/i965/brw_vtbl.c
index 14227a5133..8f1601d10f 100644
--- a/src/mesa/drivers/dri/i965/brw_vtbl.c
+++ b/src/mesa/drivers/dri/i965/brw_vtbl.c
@@ -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);
diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c
index e182fc3202..d70be7bda2 100644
--- a/src/mesa/drivers/dri/i965/brw_wm.c
+++ b/src/mesa/drivers/dri/i965/brw_wm.c
@@ -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)
diff --git a/src/mesa/drivers/dri/i965/brw_wm.h b/src/mesa/drivers/dri/i965/brw_wm.h
index f40977fab8..2639d4f26b 100644
--- a/src/mesa/drivers/dri/i965/brw_wm.h
+++ b/src/mesa/drivers/dri/i965/brw_wm.h
@@ -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
diff --git a/src/mesa/drivers/dri/i965/brw_wm_debug.c b/src/mesa/drivers/dri/i965/brw_wm_debug.c
index a78cc8b54e..6a91251a80 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_debug.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_debug.c
@@ -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("?");
}
diff --git a/src/mesa/drivers/dri/i965/brw_wm_emit.c b/src/mesa/drivers/dri/i965/brw_wm_emit.c
index d9fa2e6335..f3ad01b3fe 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_emit.c
@@ -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);
}
@@ -873,13 +923,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) {
brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF);
@@ -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");
}
}
diff --git a/src/mesa/drivers/dri/i965/brw_wm_fp.c b/src/mesa/drivers/dri/i965/brw_wm_fp.c
index 0bef874b88..3870bf10fc 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_fp.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_fp.c
@@ -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");
}
diff --git a/src/mesa/drivers/dri/i965/brw_wm_glsl.c b/src/mesa/drivers/dri/i965/brw_wm_glsl.c
index 575f89b17f..c1083c5942 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_glsl.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_glsl.c
@@ -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");
}
}
diff --git a/src/mesa/drivers/dri/i965/brw_wm_iz.c b/src/mesa/drivers/dri/i965/brw_wm_iz.c
index 5e399ac62a..8505ef1951 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_iz.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_iz.c
@@ -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;
}
diff --git a/src/mesa/drivers/dri/i965/brw_wm_pass0.c b/src/mesa/drivers/dri/i965/brw_wm_pass0.c
index 05de85a957..8fc960b445 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_pass0.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_pass0.c
@@ -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] );
}
diff --git a/src/mesa/drivers/dri/i965/brw_wm_pass1.c b/src/mesa/drivers/dri/i965/brw_wm_pass1.c
index b449394029..962515a99e 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_pass1.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_pass1.c
@@ -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;
diff --git a/src/mesa/drivers/dri/i965/brw_wm_pass2.c b/src/mesa/drivers/dri/i965/brw_wm_pass2.c
index 31303febf0..54acb3038b 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_pass2.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_pass2.c
@@ -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;
diff --git a/src/mesa/drivers/dri/i965/brw_wm_state.c b/src/mesa/drivers/dri/i965/brw_wm_state.c
index c1cf4db1ca..6699d0a73e 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_state.c
@@ -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;
diff --git a/src/mesa/drivers/dri/i965/gen6_cc.c b/src/mesa/drivers/dri/i965/gen6_cc.c
index f7acad6912..26f1070a16 100644
--- a/src/mesa/drivers/dri/i965/gen6_cc.c
+++ b/src/mesa/drivers/dri/i965/gen6_cc.c
@@ -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);
diff --git a/src/mesa/drivers/dri/i965/gen6_wm_state.c b/src/mesa/drivers/dri/i965/gen6_wm_state.c
index 863c85449d..2cd640de17 100644
--- a/src/mesa/drivers/dri/i965/gen6_wm_state.c
+++ b/src/mesa/drivers/dri/i965/gen6_wm_state.c
@@ -34,18 +34,59 @@
#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)
{
struct intel_context *intel = &brw->intel;
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);
diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.c b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
index 8ab41f8d27..117d4daf3b 100644
--- a/src/mesa/drivers/dri/intel/intel_buffer_objects.c
+++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
@@ -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);
diff --git a/src/mesa/drivers/dri/intel/intel_chipset.h b/src/mesa/drivers/dri/intel/intel_chipset.h
index 72a74322ee..b5f180bbc8 100644
--- a/src/mesa/drivers/dri/intel/intel_chipset.h
+++ b/src/mesa/drivers/dri/intel/intel_chipset.h
@@ -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 || \
@@ -119,7 +120,8 @@
#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) || \
diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c
index e19f44035f..a9ba93d24b 100644
--- a/src/mesa/drivers/dri/intel/intel_context.c
+++ b/src/mesa/drivers/dri/intel/intel_context.c
@@ -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
*/
diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h
index c7ac2de01e..28d53284fd 100644
--- a/src/mesa/drivers/dri/intel/intel_context.h
+++ b/src/mesa/drivers/dri/intel/intel_context.h
@@ -32,14 +32,26 @@
#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
diff --git a/src/mesa/drivers/dri/intel/intel_extensions.c b/src/mesa/drivers/dri/intel/intel_extensions.c
index edba1fc2f2..bf22a423fc 100644
--- a/src/mesa/drivers/dri/intel/intel_extensions.c
+++ b/src/mesa/drivers/dri/intel/intel_extensions.c
@@ -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 },
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c
index 4a83886fc1..2693b5fa72 100644
--- a/src/mesa/drivers/dri/intel/intel_fbo.c
+++ b/src/mesa/drivers/dri/intel/intel_fbo.c
@@ -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? */
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
index 39ac0205fa..d316d34d69 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
@@ -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,
diff --git a/src/mesa/drivers/dri/intel/intel_regions.c b/src/mesa/drivers/dri/intel/intel_regions.c
index 680d18ba29..e87e29462c 100644
--- a/src/mesa/drivers/dri/intel/intel_regions.c
+++ b/src/mesa/drivers/dri/intel/intel_regions.c
@@ -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;
}
diff --git a/src/mesa/drivers/dri/intel/intel_regions.h b/src/mesa/drivers/dri/intel/intel_regions.h
index 6bbed32f2a..8464a5e937 100644
--- a/src/mesa/drivers/dri/intel/intel_regions.h
+++ b/src/mesa/drivers/dri/intel/intel_regions.h
@@ -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);
diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
index 15a465c640..0a542a7303 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -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[] = {
diff --git a/src/mesa/drivers/dri/intel/intel_tex.h b/src/mesa/drivers/dri/intel/intel_tex.h
index 4bb012dc65..cd77dd5b8e 100644
--- a/src/mesa/drivers/dri/intel/intel_tex.h
+++ b/src/mesa/drivers/dri/intel/intel_tex.h
@@ -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);
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_driver.c b/src/mesa/drivers/dri/nouveau/nouveau_driver.c
index 4ec864c181..6452fe218e 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_driver.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_driver.c
@@ -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
}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_fbo.c b/src/mesa/drivers/dri/nouveau/nouveau_fbo.c
index bd1273beea..32d8f2d0f9 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_fbo.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_fbo.c
@@ -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
}
diff --git a/src/mesa/drivers/dri/r300/compiler/Makefile b/src/mesa/drivers/dri/r300/compiler/Makefile
index 3167d49bca..d0eb170784 100644
--- a/src/mesa/drivers/dri/r300/compiler/Makefile
+++ b/src/mesa/drivers/dri/r300/compiler/Makefile
@@ -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 \
diff --git a/src/mesa/drivers/dri/r300/compiler/SConscript b/src/mesa/drivers/dri/r300/compiler/SConscript
index c6f47a6f8a..847857b142 100755
--- a/src/mesa/drivers/dri/r300/compiler/SConscript
+++ b/src/mesa/drivers/dri/r300/compiler/SConscript
@@ -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',
diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
index d2fa816894..8613ec5109 100644
--- a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
+++ b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
@@ -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);
+ }
+ }
}
diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
index 666c9c2a7a..b05b3aabf3 100644
--- a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
+++ b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
@@ -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);
}
}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.h b/src/mesa/drivers/dri/r300/compiler/radeon_code.h
index 896246d203..f76676fae8 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_code.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_code.h
@@ -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;
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
index 7c42eb3ae5..5155b912e1 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
@@ -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
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c
index faf531b412..acdb371de9 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c
@@ -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);
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c b/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c
index 2ea830be7f..da495a3afa 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c
@@ -95,6 +95,12 @@ struct rc_opcode_info rc_opcodes[MAX_RC_OPCODE] = {
.IsComponentwise = 1
},
{
+ .Opcode = RC_OPCODE_DP2,
+ .Name = "DP2",
+ .NumSrcRegs = 2,
+ .HasDstReg = 1
+ },
+ {
.Opcode = RC_OPCODE_DP3,
.Name = "DP3",
.NumSrcRegs = 2,
@@ -295,6 +301,13 @@ struct rc_opcode_info rc_opcodes[MAX_RC_OPCODE] = {
.IsComponentwise = 1
},
{
+ .Opcode = RC_OPCODE_SSG,
+ .Name = "SSG",
+ .NumSrcRegs = 1,
+ .HasDstReg = 1,
+ .IsComponentwise = 1
+ },
+ {
.Opcode = RC_OPCODE_SUB,
.Name = "SUB",
.NumSrcRegs = 2,
@@ -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;
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.h b/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.h
index 6e18d6eb3f..d3f639c870 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.h
@@ -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,
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c b/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c
index 407a0a55ee..8327e9aced 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c
@@ -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);
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c
index 857aae5514..704a7bb2d2 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c
@@ -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;
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c
index 9c4b65f4c0..ddce590ee6 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c
@@ -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
index 0000000000..be89e9fa5b
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.c
@@ -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
index 0000000000..0d3a26ca1c
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.h
@@ -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
diff --git a/src/mesa/drivers/dri/r300/r300_fragprog_common.c b/src/mesa/drivers/dri/r300/r300_fragprog_common.c
index 95f4306f60..7b6521c748 100644
--- a/src/mesa/drivers/dri/r300/r300_fragprog_common.c
+++ b/src/mesa/drivers/dri/r300/r300_fragprog_common.c
@@ -38,7 +38,6 @@
#include "r300_fragprog_common.h"
-#include "program/prog_parameter.h"
#include "program/prog_print.h"
#include "compiler/radeon_compiler.h"
diff --git a/src/mesa/drivers/dri/r600/Makefile b/src/mesa/drivers/dri/r600/Makefile
index 17915621ee..03c17540e0 100644
--- a/src/mesa/drivers/dri/r600/Makefile
+++ b/src/mesa/drivers/dri/r600/Makefile
@@ -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
index 0000000000..f925f215bc
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_chip.c
@@ -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
index 0000000000..2ea5cd213c
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_chip.h
@@ -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
index 0000000000..65b5898efa
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_context.c
@@ -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/slang/slang_link.h b/src/mesa/drivers/dri/r600/evergreen_context.h
index 3e9fa2d743..4e50999c98 100644
--- a/src/mesa/slang/slang_link.h
+++ b/src/mesa/drivers/dri/r600/evergreen_context.h
@@ -1,8 +1,5 @@
/*
- * Mesa 3-D graphics library
- * Version: 7.2
- *
- * Copyright (C) 2008 Brian Paul All Rights Reserved.
+ * 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"),
@@ -17,21 +14,25 @@
* THE SOFTWARE IS PROVIDED "AS 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
+ * 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.
*/
-#ifndef SLANG_LINK_H
-#define SLANG_LINK_H 1
+/*
+ * 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_
-#include "main/mtypes.h"
-extern void
-_slang_link(GLcontext *ctx, GLhandleARB h,
- struct gl_shader_program *shProg);
-#endif
diff --git a/src/mesa/drivers/dri/r600/evergreen_diff.h b/src/mesa/drivers/dri/r600/evergreen_diff.h
new file mode 100644
index 0000000000..c3a5fd0a38
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_diff.h
@@ -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
index 0000000000..b53ff424a0
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_fragprog.c
@@ -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
index 0000000000..0e200bf383
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_fragprog.h
@@ -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/slang/slang_log.h b/src/mesa/drivers/dri/r600/evergreen_ioctl.c
index 544a26654e..5c1270790d 100644
--- a/src/mesa/slang/slang_log.h
+++ b/src/mesa/drivers/dri/r600/evergreen_ioctl.c
@@ -1,8 +1,5 @@
/*
- * Mesa 3-D graphics library
- * Version: 6.5.3
- *
- * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
+ * 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"),
@@ -17,43 +14,40 @@
* THE SOFTWARE IS PROVIDED "AS 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
+ * 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 SLANG_LOG_H
-#define SLANG_LOG_H
-
+#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"
-typedef struct slang_info_log_
-{
- char *text;
- GLboolean dont_free_text;
- GLboolean error_flag;
-} slang_info_log;
-
+#include "radeon_common.h"
+#include "r600_context.h"
-extern void
-slang_info_log_construct(slang_info_log *);
+#include "evergreen_ioctl.h"
-extern void
-slang_info_log_destruct(slang_info_log *);
+#include "r700_clear.h"
-extern int
-slang_info_log_print(slang_info_log *, const char *, ...);
+void evergreenClear(GLcontext * ctx, GLbitfield mask)
+{
+ r700Clear(ctx, mask);
+}
-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 */
+void evergreenInitIoctlFuncs(struct dd_function_table *functions)
+{
+ functions->Clear = evergreenClear;
+ functions->Finish = radeonFinish;
+ functions->Flush = radeonFlush;
+}
diff --git a/src/mesa/slang/slang_mem.h b/src/mesa/drivers/dri/r600/evergreen_ioctl.h
index b5bfae2479..3c663a7083 100644
--- a/src/mesa/slang/slang_mem.h
+++ b/src/mesa/drivers/dri/r600/evergreen_ioctl.h
@@ -1,8 +1,5 @@
/*
- * Mesa 3-D graphics library
- * Version: 6.5.3
- *
- * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
+ * 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"),
@@ -17,39 +14,23 @@
* THE SOFTWARE IS PROVIDED "AS 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
+ * 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 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);
+#ifndef _EVERGREEN_IOCTL_H_
+#define _EVERGREEN_IOCTL_H_
-extern void
-_slang_free(void *addr);
+#include "r600_context.h"
+#include "radeon_drm.h"
+extern void evergreenClear(GLcontext * ctx, GLbitfield mask);
+extern void evergreenInitIoctlFuncs(struct dd_function_table *functions);
-#endif
+#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
index 0000000000..8c250699ec
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_off.h
@@ -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
index 0000000000..9fe523234c
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_oglprog.c
@@ -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/slang/slang_emit.h b/src/mesa/drivers/dri/r600/evergreen_oglprog.h
index f93d6b00d6..1cf3e79d05 100644
--- a/src/mesa/slang/slang_emit.h
+++ b/src/mesa/drivers/dri/r600/evergreen_oglprog.h
@@ -1,8 +1,5 @@
/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * Copyright (C) 2005-2008 Brian Paul All Rights Reserved.
+ * 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"),
@@ -17,33 +14,20 @@
* THE SOFTWARE IS PROVIDED "AS 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
+ * 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.
*/
-#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);
-
+/*
+ * Authors:
+ * Richard Li <RichardZ.Li@amd.com>, <richardradeon@gmail.com>
+ */
-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);
+#ifndef _EVERGREEN_OGLPROG_H_
+#define _EVERGREEN_OGLPROG_H_
+#include "r600_context.h"
+extern void evergreenInitShaderFuncs(struct dd_function_table *functions);
-#endif /* SLANG_EMIT_H */
+#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
index 0000000000..85b2f9d6ab
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_render.c
@@ -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
index 0000000000..b1a536e76f
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_sq.h
@@ -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
index 0000000000..931478caa5
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_state.c
@@ -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
index 0000000000..ffdb56b38a
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_state.h
@@ -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
index 0000000000..8b42045ebb
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_tex.c
@@ -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
index 0000000000..b43508a9ea
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_tex.h
@@ -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
index 0000000000..4f3db00c7d
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_vertprog.c
@@ -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
index 0000000000..5853902115
--- /dev/null
+++ b/src/mesa/drivers/dri/r600/evergreen_vertprog.h
@@ -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_ */
diff --git a/src/mesa/drivers/dri/r600/r600_blit.c b/src/mesa/drivers/dri/r600/r600_blit.c
index 27acff9c16..ef47ae1c05 100644
--- a/src/mesa/drivers/dri/r600/r600_blit.c
+++ b/src/mesa/drivers/dri/r600/r600_blit.c
@@ -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 */
diff --git a/src/mesa/drivers/dri/r600/r600_cmdbuf.c b/src/mesa/drivers/dri/r600/r600_cmdbuf.c
index 8013553f67..b3331fc8b8 100644
--- a/src/mesa/drivers/dri/r600/r600_cmdbuf.c
+++ b/src/mesa/drivers/dri/r600/r600_cmdbuf.c
@@ -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,
diff --git a/src/mesa/drivers/dri/r600/r600_cmdbuf.h b/src/mesa/drivers/dri/r600/r600_cmdbuf.h
index 78fccd0b60..801bb013f6 100644
--- a/src/mesa/drivers/dri/r600/r600_cmdbuf.h
+++ b/src/mesa/drivers/dri/r600/r600_cmdbuf.h
@@ -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__ */
diff --git a/src/mesa/drivers/dri/r600/r600_context.c b/src/mesa/drivers/dri/r600/r600_context.c
index 389b0412ba..bb959e7d2d 100644
--- a/src/mesa/drivers/dri/r600/r600_context.c
+++ b/src/mesa/drivers/dri/r600/r600_context.c
@@ -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);
+}
+
diff --git a/src/mesa/drivers/dri/r600/r600_context.h b/src/mesa/drivers/dri/r600/r600_context.h
index 063dd7c49a..6a83196648 100644
--- a/src/mesa/drivers/dri/r600/r600_context.h
+++ b/src/mesa/drivers/dri/r600/r600_context.h
@@ -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
diff --git a/src/mesa/drivers/dri/r600/r600_emit.c b/src/mesa/drivers/dri/r600/r600_emit.c
index 1eb89a5305..a840106c14 100644
--- a/src/mesa/drivers/dri/r600/r600_emit.c
+++ b/src/mesa/drivers/dri/r600/r600_emit.c
@@ -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,
diff --git a/src/mesa/drivers/dri/r600/r600_emit.h b/src/mesa/drivers/dri/r600/r600_emit.h
index 661774d11e..259561539f 100644
--- a/src/mesa/drivers/dri/r600/r600_emit.h
+++ b/src/mesa/drivers/dri/r600/r600_emit.h
@@ -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
diff --git a/src/mesa/drivers/dri/r600/r600_texstate.c b/src/mesa/drivers/dri/r600/r600_texstate.c
index ba3690b70e..fd928cfe5d 100644
--- a/src/mesa/drivers/dri/r600/r600_texstate.c
+++ b/src/mesa/drivers/dri/r600/r600_texstate.c
@@ -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);
diff --git a/src/mesa/drivers/dri/r600/r700_assembler.c b/src/mesa/drivers/dri/r600/r700_assembler.c
index 9c954cbf70..45ff9c0624 100644
--- a/src/mesa/drivers/dri/r600/r700_assembler.c
+++ b/src/mesa/drivers/dri/r600/r700_assembler.c
@@ -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.barrier = 0x1;
+ 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;
+ }
}
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;
diff --git a/src/mesa/drivers/dri/r600/r700_assembler.h b/src/mesa/drivers/dri/r600/r700_assembler.h
index dbc6cdb190..d357b0e3ec 100644
--- a/src/mesa/drivers/dri/r600/r700_assembler.h
+++ b/src/mesa/drivers/dri/r600/r700_assembler.h
@@ -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,
diff --git a/src/mesa/drivers/dri/r600/r700_chip.c b/src/mesa/drivers/dri/r600/r700_chip.c
index bf8063391a..71f1af7562 100644
--- a/src/mesa/drivers/dri/r600/r700_chip.c
+++ b/src/mesa/drivers/dri/r600/r700_chip.c
@@ -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;
}
diff --git a/src/mesa/drivers/dri/r600/r700_chip.h b/src/mesa/drivers/dri/r600/r700_chip.h
index 0b6b72f850..ebf1840a79 100644
--- a/src/mesa/drivers/dri/r600/r700_chip.h
+++ b/src/mesa/drivers/dri/r600/r700_chip.h
@@ -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_ */
diff --git a/src/mesa/drivers/dri/r600/r700_fragprog.c b/src/mesa/drivers/dri/r600/r700_fragprog.c
index f9d84b6ed6..6fdd93a330 100644
--- a/src/mesa/drivers/dri/r600/r700_fragprog.c
+++ b/src/mesa/drivers/dri/r600/r700_fragprog.c
@@ -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;
diff --git a/src/mesa/drivers/dri/r600/r700_fragprog.h b/src/mesa/drivers/dri/r600/r700_fragprog.h
index 39c59c9201..aaa6043d5d 100644
--- a/src/mesa/drivers/dri/r600/r700_fragprog.h
+++ b/src/mesa/drivers/dri/r600/r700_fragprog.h
@@ -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_*/
diff --git a/src/mesa/drivers/dri/r600/r700_oglprog.c b/src/mesa/drivers/dri/r600/r700_oglprog.c
index 8351792511..e0c9179004 100644
--- a/src/mesa/drivers/dri/r600/r700_oglprog.c
+++ b/src/mesa/drivers/dri/r600/r700_oglprog.c
@@ -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;
diff --git a/src/mesa/drivers/dri/r600/r700_render.c b/src/mesa/drivers/dri/r600/r700_render.c
index c5771f9fd0..f90c69c416 100644
--- a/src/mesa/drivers/dri/r600/r700_render.c
+++ b/src/mesa/drivers/dri/r600/r700_render.c
@@ -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
diff --git a/src/mesa/drivers/dri/r600/r700_state.c b/src/mesa/drivers/dri/r600/r700_state.c
index 5ea8918611..925b4ffe6d 100644
--- a/src/mesa/drivers/dri/r600/r700_state.c
+++ b/src/mesa/drivers/dri/r600/r700_state.c
@@ -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);
diff --git a/src/mesa/drivers/dri/r600/r700_vertprog.c b/src/mesa/drivers/dri/r600/r700_vertprog.c
index 6a2a09eaf1..7ed4b7d238 100644
--- a/src/mesa/drivers/dri/r600/r700_vertprog.c
+++ b/src/mesa/drivers/dri/r600/r700_vertprog.c
@@ -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;
diff --git a/src/mesa/drivers/dri/r600/r700_vertprog.h b/src/mesa/drivers/dri/r600/r700_vertprog.h
index 645c9ac84a..9acdc8e350 100644
--- a/src/mesa/drivers/dri/r600/r700_vertprog.h
+++ b/src/mesa/drivers/dri/r600/r700_vertprog.h
@@ -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_ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_chipset.h b/src/mesa/drivers/dri/radeon/radeon_chipset.h
index 7d54fabebb..61106fbc43 100644
--- a/src/mesa/drivers/dri/radeon/radeon_chipset.h
+++ b/src/mesa/drivers/dri/radeon/radeon_chipset.h
@@ -400,6 +400,46 @@
#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
};
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.c b/src/mesa/drivers/dri/radeon/radeon_common_context.c
index 92663bf66d..07f7cba354 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common_context.c
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.c
@@ -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";
}
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h
index f06e5fdf24..024e31f8ec 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common_context.h
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h
@@ -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;
diff --git a/src/mesa/drivers/dri/radeon/radeon_fbo.c b/src/mesa/drivers/dri/radeon/radeon_fbo.c
index 517485091a..0597d4250d 100644
--- a/src/mesa/drivers/dri/radeon/radeon_fbo.c
+++ b/src/mesa/drivers/dri/radeon/radeon_fbo.c
@@ -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
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
index c6e5f110ea..ddfde3edaf 100644
--- a/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
+++ b/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c
@@ -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;
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c
index fa97a19302..2ea77e56c7 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.c
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.c
@@ -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
index 6da9f93f59..0000000000
--- a/src/mesa/drivers/glslcompiler/Makefile
+++ /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
index 7259bf4c56..0000000000
--- a/src/mesa/drivers/glslcompiler/glslcompiler.c
+++ /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;
-}
diff --git a/src/mesa/drivers/osmesa/Makefile b/src/mesa/drivers/osmesa/Makefile
index c6b4a04085..39ab09af80 100644
--- a/src/mesa/drivers/osmesa/Makefile
+++ b/src/mesa/drivers/osmesa/Makefile
@@ -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)
diff --git a/src/mesa/drivers/x11/Makefile b/src/mesa/drivers/x11/Makefile
index b5b0c1f11a..f759da0a97 100644
--- a/src/mesa/drivers/x11/Makefile
+++ b/src/mesa/drivers/x11/Makefile
@@ -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)
diff --git a/src/mesa/main/accum.h b/src/mesa/main/accum.h
index 63740f07ed..c2b74b23cb 100644
--- a/src/mesa/main/accum.h
+++ b/src/mesa/main/accum.h
@@ -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
diff --git a/src/mesa/main/attrib.h b/src/mesa/main/attrib.h
index 6b48a17663..83b28a65b7 100644
--- a/src/mesa/main/attrib.h
+++ b/src/mesa/main/attrib.h
@@ -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 )
{
diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c
index 4e232b5731..4797f29b4d 100644
--- a/src/mesa/main/bufferobj.c
+++ b/src/mesa/main/bufferobj.c
@@ -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;
}
diff --git a/src/mesa/main/colortab.h b/src/mesa/main/colortab.h
index 652fb58246..744f092d93 100644
--- a/src/mesa/main/colortab.h
+++ b/src/mesa/main/colortab.h
@@ -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
diff --git a/src/mesa/main/compiler.h b/src/mesa/main/compiler.h
index e0507ccf86..ded69c3106 100644
--- a/src/mesa/main/compiler.h
+++ b/src/mesa/main/compiler.h
@@ -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
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index b01fed1781..8e34ec4124 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -140,6 +140,10 @@
#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 */
diff --git a/src/mesa/main/convolve.h b/src/mesa/main/convolve.h
index 59492bc7c5..d1401885df 100644
--- a/src/mesa/main/convolve.h
+++ b/src/mesa/main/convolve.h
@@ -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
index 0000000000..ea6e6bf118
--- /dev/null
+++ b/src/mesa/main/core.h
@@ -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 */
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index 825073ca88..8a20a66363 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -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 );
diff --git a/src/mesa/main/depthstencil.c b/src/mesa/main/depthstencil.c
index 885e718a76..dbaa841645 100644
--- a/src/mesa/main/depthstencil.c
+++ b/src/mesa/main/depthstencil.c
@@ -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;
diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c
index 727414d529..5042e14a54 100644
--- a/src/mesa/main/dlist.c
+++ b/src/mesa/main/dlist.c
@@ -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 */
diff --git a/src/mesa/main/dlist.h b/src/mesa/main/dlist.h
index f8255facc5..d3f5c5cb4e 100644
--- a/src/mesa/main/dlist.h
+++ b/src/mesa/main/dlist.h
@@ -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)
diff --git a/src/mesa/main/es_generator.py b/src/mesa/main/es_generator.py
index 9a8f5a6f5e..ecb34bb5cd 100644
--- a/src/mesa/main/es_generator.py
+++ b/src/mesa/main/es_generator.py
@@ -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
diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
index 19a1eebe6e..c9862ca29e 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -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;
}
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index 9a84e5a79c..f80dd85993 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -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;
}
diff --git a/src/mesa/main/feedback.h b/src/mesa/main/feedback.h
index 3e8283ed23..0762930044 100644
--- a/src/mesa/main/feedback.h
+++ b/src/mesa/main/feedback.h
@@ -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
diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c
index 90449cc04f..112d7a0088 100644
--- a/src/mesa/main/formats.c
+++ b/src/mesa/main/formats.c
@@ -940,6 +940,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
*/
diff --git a/src/mesa/main/formats.h b/src/mesa/main/formats.h
index ad176caaa0..e9467f486b 100644
--- a/src/mesa/main/formats.h
+++ b/src/mesa/main/formats.h
@@ -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);
diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c
index e0aac26f62..a98c09cfbf 100644
--- a/src/mesa/main/framebuffer.c
+++ b/src/mesa/main/framebuffer.c
@@ -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
diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c
index 632dadd1a5..a3cb5ec168 100644
--- a/src/mesa/main/get.c
+++ b/src/mesa/main/get.c
@@ -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)
diff --git a/src/mesa/main/getstring.c b/src/mesa/main/getstring.c
index 7961ad7e7d..5e4fcd599c 100644
--- a/src/mesa/main/getstring.c
+++ b/src/mesa/main/getstring.c
@@ -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
diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h
index 9c2ffd66d6..751f206501 100644
--- a/src/mesa/main/imports.h
+++ b/src/mesa/main/imports.h
@@ -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
}
diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c
index c0c29f7889..678d17a2a3 100644
--- a/src/mesa/main/mipmap.c
+++ b/src/mesa/main/mipmap.c
@@ -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;
}
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 8d92892ad7..d44eff69cc 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -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 */
diff --git a/src/mesa/main/querymatrix.c b/src/mesa/main/querymatrix.c
index 32aaa79f7f..36236eb9a7 100644
--- a/src/mesa/main/querymatrix.c
+++ b/src/mesa/main/querymatrix.c
@@ -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. */
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index 9cb2391035..cc350c93b9 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -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);
}
}
diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c
index 14bbb2e4bc..59198d788b 100644
--- a/src/mesa/main/shaderobj.c
+++ b/src/mesa/main/shaderobj.c
@@ -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;
}
diff --git a/src/mesa/main/shaderobj.h b/src/mesa/main/shaderobj.h
index d6b37b4596..4800046375 100644
--- a/src/mesa/main/shaderobj.h
+++ b/src/mesa/main/shaderobj.h
@@ -27,8 +27,22 @@
#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 */
diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c
index cbe004518a..ea7e503cf3 100644
--- a/src/mesa/main/shared.c
+++ b/src/mesa/main/shared.c
@@ -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
*/
diff --git a/src/mesa/main/texcompress_s3tc.c b/src/mesa/main/texcompress_s3tc.c
index c70792cab6..8e05980262 100644
--- a/src/mesa/main/texcompress_s3tc.c
+++ b/src/mesa/main/texcompress_s3tc.c
@@ -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;
diff --git a/src/mesa/main/transformfeedback.c b/src/mesa/main/transformfeedback.c
index f86f1911d1..5c8c1fd225 100644
--- a/src/mesa/main/transformfeedback.c
+++ b/src/mesa/main/transformfeedback.c
@@ -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;
}
diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c
index d68a7768df..a5d7da51f0 100644
--- a/src/mesa/main/uniforms.c
+++ b/src/mesa/main/uniforms.c
@@ -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);
}
diff --git a/src/mesa/main/uniforms.h b/src/mesa/main/uniforms.h
index ef98fe16bb..f823c61444 100644
--- a/src/mesa/main/uniforms.h
+++ b/src/mesa/main/uniforms.h
@@ -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);
diff --git a/src/mesa/program/hash_table.c b/src/mesa/program/hash_table.c
index fa6ba2bfdf..f7ef366c1a 100644
--- a/src/mesa/program/hash_table.c
+++ b/src/mesa/program/hash_table.c
@@ -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;
+}
diff --git a/src/mesa/program/hash_table.h b/src/mesa/program/hash_table.h
index e750906f96..f1c4fdcd1f 100644
--- a/src/mesa/program/hash_table.h
+++ b/src/mesa/program/hash_table.h
@@ -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
index 0000000000..f0e14b8ece
--- /dev/null
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -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
index 0000000000..ecaacde4bb
--- /dev/null
+++ b/src/mesa/program/ir_to_mesa.h
@@ -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
diff --git a/src/mesa/program/prog_execute.c b/src/mesa/program/prog_execute.c
index 1670c91b6a..2ae5bc572a 100644
--- a/src/mesa/program/prog_execute.c
+++ b/src/mesa/program/prog_execute.c
@@ -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;
}
diff --git a/src/mesa/program/prog_instruction.h b/src/mesa/program/prog_instruction.h
index 098b366ab5..ca90de7ce1 100644
--- a/src/mesa/program/prog_instruction.h
+++ b/src/mesa/program/prog_instruction.h
@@ -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.
*/
diff --git a/src/mesa/program/prog_optimize.c b/src/mesa/program/prog_optimize.c
index c78187c983..0dc779073d 100644
--- a/src/mesa/program/prog_optimize.c
+++ b/src/mesa/program/prog_optimize.c
@@ -34,7 +34,12 @@
#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;
}
diff --git a/src/mesa/program/prog_parameter.c b/src/mesa/program/prog_parameter.c
index aac488c79a..6bf8a081b0 100644
--- a/src/mesa/program/prog_parameter.c
+++ b/src/mesa/program/prog_parameter.c
@@ -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) {
diff --git a/src/mesa/program/prog_parameter.h b/src/mesa/program/prog_parameter.h
index cc3378ae20..10cbbe57a6 100644
--- a/src/mesa/program/prog_parameter.h
+++ b/src/mesa/program/prog_parameter.h
@@ -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.
@@ -132,19 +131,6 @@ _mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
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,
GLbitfield flags);
diff --git a/src/mesa/program/prog_print.c b/src/mesa/program/prog_print.c
index 6056c459e4..00aa6de963 100644
--- a/src/mesa/program/prog_print.c
+++ b/src/mesa/program/prog_print.c
@@ -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);
diff --git a/src/mesa/program/prog_print.h b/src/mesa/program/prog_print.h
index 4667373f37..78b90aeb4d 100644
--- a/src/mesa/program/prog_print.h
+++ b/src/mesa/program/prog_print.h
@@ -66,6 +66,13 @@ 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);
diff --git a/src/mesa/program/prog_uniform.c b/src/mesa/program/prog_uniform.c
index 5aa9878d43..28acb8871a 100644
--- a/src/mesa/program/prog_uniform.c
+++ b/src/mesa/program/prog_uniform.c
@@ -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);
}
diff --git a/src/mesa/program/prog_uniform.h b/src/mesa/program/prog_uniform.h
index 7988d534a7..67f78006ea 100644
--- a/src/mesa/program/prog_uniform.h
+++ b/src/mesa/program/prog_uniform.h
@@ -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;
};
diff --git a/src/mesa/program/symbol_table.c b/src/mesa/program/symbol_table.c
index 6a5d686897..09e7cb44ef 100644
--- a/src/mesa/program/symbol_table.c
+++ b/src/mesa/program/symbol_table.c
@@ -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);
}
diff --git a/src/mesa/program/symbol_table.h b/src/mesa/program/symbol_table.h
index 0c054ef139..1d570fc1a0 100644
--- a/src/mesa/program/symbol_table.h
+++ b/src/mesa/program/symbol_table.h
@@ -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
index 674b786ac0..0000000000
--- a/src/mesa/slang/descrip.mms
+++ /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
index 02a89fc7df..0000000000
--- a/src/mesa/slang/library/.gitignore
+++ /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
index f546a03907..0000000000
--- a/src/mesa/slang/library/Makefile
+++ /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
index 5112cefb3e..0000000000
--- a/src/mesa/slang/library/SConscript
+++ /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
index 04c5ec2ec5..0000000000
--- a/src/mesa/slang/library/slang_120_core.gc
+++ /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
index c6264c3b47..0000000000
--- a/src/mesa/slang/library/slang_builtin_120_common.gc
+++ /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_common_builtin.gc b/src/mesa/slang/library/slang_common_builtin.gc
deleted file mode 100644
index 1f5ddbc1ee..0000000000
--- a/src/mesa/slang/library/slang_common_builtin.gc
+++ /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
index 0a0d15903b..0000000000
--- a/src/mesa/slang/library/slang_core.gc
+++ /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
index 54a80ea0e0..0000000000
--- a/src/mesa/slang/library/slang_fragment_builtin.gc
+++ /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
index 07524912ba..0000000000
--- a/src/mesa/slang/library/slang_geometry_builtin.gc
+++ /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
index 0c67c2ef20..0000000000
--- a/src/mesa/slang/library/slang_vertex_builtin.gc
+++ /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
index a7e0efcb7b..0000000000
--- a/src/mesa/slang/slang_builtin.c
+++ /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
index dc92f83f8e..0000000000
--- a/src/mesa/slang/slang_builtin.h
+++ /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
index 95787e4409..0000000000
--- a/src/mesa/slang/slang_codegen.c
+++ /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
index ff0279bbfe..0000000000
--- a/src/mesa/slang/slang_codegen.h
+++ /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
index de1bb56cd9..0000000000
--- a/src/mesa/slang/slang_compile.c
+++ /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
index 6061f878e7..0000000000
--- a/src/mesa/slang/slang_compile.h
+++ /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
index 4dd885176d..0000000000
--- a/src/mesa/slang/slang_compile_function.c
+++ /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
index 0eced3ca1a..0000000000
--- a/src/mesa/slang/slang_compile_function.h
+++ /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
index 5441d60df5..0000000000
--- a/src/mesa/slang/slang_compile_operation.c
+++ /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
index b8c5f214cf..0000000000
--- a/src/mesa/slang/slang_compile_operation.h
+++ /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
index e6c38730d7..0000000000
--- a/src/mesa/slang/slang_compile_struct.c
+++ /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
index 7be6f204e1..0000000000
--- a/src/mesa/slang/slang_compile_struct.h
+++ /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
index 23c08a9039..0000000000
--- a/src/mesa/slang/slang_compile_variable.c
+++ /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
index 48dc6efca4..0000000000
--- a/src/mesa/slang/slang_compile_variable.h
+++ /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
index a9aa6fe1c3..0000000000
--- a/src/mesa/slang/slang_emit.c
+++ /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_ir.c b/src/mesa/slang/slang_ir.c
deleted file mode 100644
index 078c9369a8..0000000000
--- a/src/mesa/slang/slang_ir.c
+++ /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
index ce9a6c5a48..0000000000
--- a/src/mesa/slang/slang_ir.h
+++ /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
index 24881d5b6e..0000000000
--- a/src/mesa/slang/slang_label.c
+++ /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
index b0cff3a8e8..0000000000
--- a/src/mesa/slang/slang_label.h
+++ /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
index c21f67256a..0000000000
--- a/src/mesa/slang/slang_link.c
+++ /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_log.c b/src/mesa/slang/slang_log.c
deleted file mode 100644
index 9ff21417bc..0000000000
--- a/src/mesa/slang/slang_log.c
+++ /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_mem.c b/src/mesa/slang/slang_mem.c
deleted file mode 100644
index 5eaa7c4427..0000000000
--- a/src/mesa/slang/slang_mem.c
+++ /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_print.c b/src/mesa/slang/slang_print.c
deleted file mode 100644
index 6b34f395fd..0000000000
--- a/src/mesa/slang/slang_print.c
+++ /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
index 99da304143..0000000000
--- a/src/mesa/slang/slang_print.h
+++ /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
index 13b9ca3c87..0000000000
--- a/src/mesa/slang/slang_simplify.c
+++ /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
index 37fb938d4f..0000000000
--- a/src/mesa/slang/slang_simplify.h
+++ /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
index 656e15670d..0000000000
--- a/src/mesa/slang/slang_storage.c
+++ /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
index 1876a36dd6..0000000000
--- a/src/mesa/slang/slang_storage.h
+++ /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
index d039a12e98..0000000000
--- a/src/mesa/slang/slang_typeinfo.c
+++ /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
index 2251b06325..0000000000
--- a/src/mesa/slang/slang_typeinfo.h
+++ /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
index c1d57409a4..0000000000
--- a/src/mesa/slang/slang_utility.c
+++ /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
index cb9b6d2aaa..0000000000
--- a/src/mesa/slang/slang_utility.h
+++ /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
index 8371631578..0000000000
--- a/src/mesa/slang/slang_vartable.c
+++ /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
index 97945b89d0..0000000000
--- a/src/mesa/slang/slang_vartable.h
+++ /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 */
diff --git a/src/mesa/sources.mak b/src/mesa/sources.mak
index f01b60c4fc..9156024d47 100644
--- a/src/mesa/sources.mak
+++ b/src/mesa/sources.mak
@@ -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
diff --git a/src/mesa/state_tracker/st_cb_accum.h b/src/mesa/state_tracker/st_cb_accum.h
index 7d52481c82..06425dc8a3 100644
--- a/src/mesa/state_tracker/st_cb_accum.h
+++ b/src/mesa/state_tracker/st_cb_accum.h
@@ -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)
{
diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c
index 0b8ecd27cb..8da5cbb5e6 100644
--- a/src/mesa/state_tracker/st_cb_bitmap.c
+++ b/src/mesa/state_tracker/st_cb_bitmap.c
@@ -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));
diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c
index 1f73f503f6..536748402f 100644
--- a/src/mesa/state_tracker/st_cb_blit.c
+++ b/src/mesa/state_tracker/st_cb_blit.c
@@ -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) {
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index 69a3dd45e8..1147b1950e 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -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);
}
diff --git a/src/mesa/state_tracker/st_cb_eglimage.c b/src/mesa/state_tracker/st_cb_eglimage.c
index 037e576fab..3145416383 100644
--- a/src/mesa/state_tracker/st_cb_eglimage.c
+++ b/src/mesa/state_tracker/st_cb_eglimage.c
@@ -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;
diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c
index 13119ce203..71bd4729e0 100644
--- a/src/mesa/state_tracker/st_cb_fbo.c
+++ b/src/mesa/state_tracker/st_cb_fbo.c
@@ -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;
@@ -448,6 +448,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;
*/
diff --git a/src/mesa/state_tracker/st_cb_fbo.h b/src/mesa/state_tracker/st_cb_fbo.h
index 62a9bbcb25..3e9815c1b1 100644
--- a/src/mesa/state_tracker/st_cb_fbo.h
+++ b/src/mesa/state_tracker/st_cb_fbo.h
@@ -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 */
diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c
index b8493dab93..6ab03ec939 100644
--- a/src/mesa/state_tracker/st_cb_readpixels.c
+++ b/src/mesa/state_tracker/st_cb_readpixels.c
@@ -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) {
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 4c3e3688dd..9eb14033ee 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -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;
}
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index 2ce5f08753..3b046962ef 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -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];
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index 60c25fb8f0..991feee300 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -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;
diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c
index 5b05489270..318e08886c 100644
--- a/src/mesa/state_tracker/st_draw.c
+++ b/src/mesa/state_tracker/st_draw.c
@@ -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);
diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c
index 5cf2666334..df05c7f70d 100644
--- a/src/mesa/state_tracker/st_draw_feedback.c
+++ b/src/mesa/state_tracker/st_draw_feedback.c
@@ -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);
}
}
diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c
index 90e78679e4..6cd74db897 100644
--- a/src/mesa/state_tracker/st_extensions.c
+++ b/src/mesa/state_tracker/st_extensions.c
@@ -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;
}
diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c
index c9fa7a62e1..1ed79524b2 100644
--- a/src/mesa/state_tracker/st_format.c
+++ b/src/mesa/state_tracker/st_format.c
@@ -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 {
diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c
index 2afc682e0b..ccce574c36 100644
--- a/src/mesa/state_tracker/st_manager.c
+++ b/src/mesa/state_tracker/st_manager.c
@@ -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);
}
diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c
index a19dcc9253..0ed822b8c2 100644
--- a/src/mesa/state_tracker/st_mesa_to_tgsi.c
+++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c
@@ -32,9 +32,10 @@
*/
#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"
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 91528c227b..8c2d8b6154 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -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;
diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c
index add6e949df..c6cf2ba061 100644
--- a/src/mesa/state_tracker/st_texture.c
+++ b/src/mesa/state_tracker/st_texture.c
@@ -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);
diff --git a/src/mesa/swrast/s_context.c b/src/mesa/swrast/s_context.c
index d8d8a80b7d..f76a2b68ec 100644
--- a/src/mesa/swrast/s_context.c
+++ b/src/mesa/swrast/s_context.c
@@ -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");
}
diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
index c32a504443..1759e57887 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -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'
diff --git a/src/mesa/x86/3dnow.h b/src/mesa/x86/3dnow.h
index df9f2638d7..1c1fedcd4f 100644
--- a/src/mesa/x86/3dnow.h
+++ b/src/mesa/x86/3dnow.h
@@ -31,8 +31,6 @@
#ifndef __3DNOW_H__
#define __3DNOW_H__
-#include "math/m_xform.h"
-
void _mesa_init_3dnow_transform_asm( void );
#endif
diff --git a/src/mesa/x86/common_x86.c b/src/mesa/x86/common_x86.c
index 5efdb4f24a..f763a3aa8a 100644
--- a/src/mesa/x86/common_x86.c
+++ b/src/mesa/x86/common_x86.c
@@ -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 */
}
diff --git a/src/mesa/x86/mmx.h b/src/mesa/x86/mmx.h
index 5641936bdb..47a0d4b54d 100644
--- a/src/mesa/x86/mmx.h
+++ b/src/mesa/x86/mmx.h
@@ -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,
diff --git a/src/mesa/x86/sse.h b/src/mesa/x86/sse.h
index 521f91e411..e92ddc1394 100644
--- a/src/mesa/x86/sse.h
+++ b/src/mesa/x86/sse.h
@@ -31,8 +31,6 @@
#ifndef __SSE_H__
#define __SSE_H__
-#include "math/m_xform.h"
-
void _mesa_init_sse_transform_asm( void );
#endif
diff --git a/src/mesa/x86/x86_xform.c b/src/mesa/x86/x86_xform.c
index c834e2b468..3dcc55e16b 100644
--- a/src/mesa/x86/x86_xform.c
+++ b/src/mesa/x86/x86_xform.c
@@ -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
index 0000000000..3bf7029bb2
--- /dev/null
+++ b/src/talloc/SConscript
@@ -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
index 0000000000..94a9ed024d
--- /dev/null
+++ b/src/talloc/gpl-3.0.txt
@@ -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
index 0000000000..65c5ca88a6
--- /dev/null
+++ b/src/talloc/lgpl-3.0.txt
@@ -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
index 0000000000..cc01346a7f
--- /dev/null
+++ b/src/talloc/talloc.c
@@ -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
index 0000000000..13d7a159ce
--- /dev/null
+++ b/src/talloc/talloc.def
@@ -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
index 0000000000..f549a17fba
--- /dev/null
+++ b/src/talloc/talloc.h
@@ -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
index 0000000000..01de806662
--- /dev/null
+++ b/src/talloc/talloc_guide.txt
@@ -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