Merge remote branch 'origin/master' into pipe-video
authorChristian König <deathsimple@vodafone.de>
Thu, 24 Feb 2011 21:02:42 +0000 (22:02 +0100)
committerChristian König <deathsimple@vodafone.de>
Thu, 24 Feb 2011 21:02:42 +0000 (22:02 +0100)
Conflicts:
configure.ac
src/gallium/auxiliary/Makefile
src/gallium/auxiliary/SConscript
src/gallium/drivers/r600/r600_asm.c
src/gallium/drivers/r600/r600_asm.h
src/gallium/drivers/r600/r600_shader.c
src/gallium/drivers/r600/r600_state_inlines.h
src/gallium/drivers/r600/r600_texture.c

683 files changed:
Makefile
SConstruct
common.py
configs/autoconf.in
configs/default
configs/freebsd-dri
configs/linux-dri
configs/linux-dri-xcb
configs/linux-egl
configs/linux-indirect
configs/linux-llvm
configure.ac
docs/GL3.txt
docs/envvars.html
docs/relnotes-7.11.html
docs/shading.html
docs/sourcetree.html
include/EGL/eglplatform.h
include/GL/internal/dri_interface.h
scons/crossmingw.py
scons/gallium.py [changed mode: 0644->0755]
scons/llvm.py
src/SConscript
src/egl/Makefile
src/egl/drivers/dri2/Makefile
src/egl/drivers/dri2/egl_dri2.c
src/egl/drivers/dri2/egl_dri2.h [new file with mode: 0644]
src/egl/drivers/dri2/platform_drm.c [new file with mode: 0644]
src/egl/drivers/dri2/platform_wayland.c [new file with mode: 0644]
src/egl/drivers/dri2/platform_x11.c [new file with mode: 0644]
src/egl/main/Makefile
src/egl/main/egldisplay.c
src/egl/main/egldisplay.h
src/egl/main/egldriver.c
src/egl/wayland/Makefile [new file with mode: 0644]
src/egl/wayland/wayland-egl-priv.h [new file with mode: 0644]
src/egl/wayland/wayland-egl.c [new file with mode: 0644]
src/egl/wayland/wayland-egl.pc.in [new file with mode: 0644]
src/gallium/SConscript
src/gallium/auxiliary/Makefile
src/gallium/auxiliary/SConscript
src/gallium/auxiliary/cso_cache/cso_context.c
src/gallium/auxiliary/cso_cache/cso_context.h
src/gallium/auxiliary/draw/draw_context.c
src/gallium/auxiliary/draw/draw_llvm.c
src/gallium/auxiliary/draw/draw_llvm.h
src/gallium/auxiliary/draw/draw_pipe.c
src/gallium/auxiliary/draw/draw_pipe_aaline.c
src/gallium/auxiliary/draw/draw_pipe_pstipple.c
src/gallium/auxiliary/draw/draw_pipe_validate.c
src/gallium/auxiliary/draw/draw_private.h
src/gallium/auxiliary/draw/draw_pt.c
src/gallium/auxiliary/draw/draw_pt_fetch.c
src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
src/gallium/auxiliary/gallivm/lp_bld_conv.c
src/gallium/auxiliary/gallivm/lp_bld_init.c
src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c
src/gallium/auxiliary/rtasm/rtasm_x86sse.c
src/gallium/auxiliary/tgsi/tgsi_build.c
src/gallium/auxiliary/tgsi/tgsi_dump.c
src/gallium/auxiliary/tgsi/tgsi_exec.c
src/gallium/auxiliary/tgsi/tgsi_exec.h
src/gallium/auxiliary/tgsi/tgsi_info.c
src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
src/gallium/auxiliary/tgsi/tgsi_parse.c
src/gallium/auxiliary/tgsi/tgsi_parse.h
src/gallium/auxiliary/tgsi/tgsi_sanity.c
src/gallium/auxiliary/tgsi/tgsi_sse2.c
src/gallium/auxiliary/tgsi/tgsi_text.c
src/gallium/auxiliary/tgsi/tgsi_ureg.c
src/gallium/auxiliary/tgsi/tgsi_ureg.h
src/gallium/auxiliary/tgsi/tgsi_util.c
src/gallium/auxiliary/translate/translate_cache.c
src/gallium/auxiliary/util/dbghelp.h [new file with mode: 0644]
src/gallium/auxiliary/util/u_blit.c
src/gallium/auxiliary/util/u_blitter.c
src/gallium/auxiliary/util/u_blitter.h
src/gallium/auxiliary/util/u_debug.c
src/gallium/auxiliary/util/u_debug.h
src/gallium/auxiliary/util/u_debug_refcnt.c
src/gallium/auxiliary/util/u_debug_symbol.c
src/gallium/auxiliary/util/u_draw_quad.c
src/gallium/auxiliary/util/u_draw_quad.h
src/gallium/auxiliary/util/u_dump_state.c
src/gallium/auxiliary/util/u_format.h
src/gallium/auxiliary/util/u_gen_mipmap.c
src/gallium/auxiliary/util/u_index_modify.c
src/gallium/auxiliary/util/u_inlines.h
src/gallium/auxiliary/util/u_math.h
src/gallium/auxiliary/util/u_resource.c
src/gallium/auxiliary/util/u_tile.c
src/gallium/auxiliary/util/u_tile.h
src/gallium/auxiliary/util/u_transfer.c
src/gallium/auxiliary/util/u_transfer.h
src/gallium/auxiliary/util/u_upload_mgr.c
src/gallium/auxiliary/util/u_vbuf_mgr.c [new file with mode: 0644]
src/gallium/auxiliary/util/u_vbuf_mgr.h [new file with mode: 0644]
src/gallium/auxiliary/vl/vl_compositor.c
src/gallium/auxiliary/vl/vl_idct.c
src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c
src/gallium/auxiliary/vl/vl_vertex_buffers.c
src/gallium/docs/d3d11ddi.txt
src/gallium/docs/source/context.rst
src/gallium/docs/source/screen.rst
src/gallium/docs/source/tgsi.rst
src/gallium/drivers/cell/ppu/cell_state_vertex.c
src/gallium/drivers/failover/fo_state.c
src/gallium/drivers/galahad/glhd_context.c
src/gallium/drivers/i915/TODO
src/gallium/drivers/i915/i915_context.c
src/gallium/drivers/i915/i915_context.h
src/gallium/drivers/i915/i915_debug.c
src/gallium/drivers/i915/i915_debug.h
src/gallium/drivers/i915/i915_flush.c
src/gallium/drivers/i915/i915_resource_texture.c
src/gallium/drivers/i915/i915_screen.c
src/gallium/drivers/i915/i915_screen.h
src/gallium/drivers/i915/i915_state.c
src/gallium/drivers/i915/i915_state_dynamic.c
src/gallium/drivers/i915/i915_state_emit.c
src/gallium/drivers/i915/i915_state_immediate.c
src/gallium/drivers/i915/i915_winsys.h
src/gallium/drivers/i965/brw_pipe_vertex.c
src/gallium/drivers/identity/id_context.c
src/gallium/drivers/llvmpipe/SConscript
src/gallium/drivers/llvmpipe/lp_flush.c
src/gallium/drivers/llvmpipe/lp_state_vertex.c
src/gallium/drivers/llvmpipe/lp_test_main.c
src/gallium/drivers/noop/noop_state.c
src/gallium/drivers/nv50/nv50_pc_optimize.c
src/gallium/drivers/nv50/nv50_query.c
src/gallium/drivers/nv50/nv50_state.c
src/gallium/drivers/nv50/nv50_tgsi_to_nc.c
src/gallium/drivers/nvc0/nvc0_3d.xml.h
src/gallium/drivers/nvc0/nvc0_buffer.c
src/gallium/drivers/nvc0/nvc0_context.c
src/gallium/drivers/nvc0/nvc0_context.h
src/gallium/drivers/nvc0/nvc0_fence.c
src/gallium/drivers/nvc0/nvc0_fence.h
src/gallium/drivers/nvc0/nvc0_miptree.c
src/gallium/drivers/nvc0/nvc0_mm.c
src/gallium/drivers/nvc0/nvc0_pc.c
src/gallium/drivers/nvc0/nvc0_pc.h
src/gallium/drivers/nvc0/nvc0_pc_emit.c
src/gallium/drivers/nvc0/nvc0_pc_optimize.c
src/gallium/drivers/nvc0/nvc0_pc_print.c
src/gallium/drivers/nvc0/nvc0_pc_regalloc.c
src/gallium/drivers/nvc0/nvc0_program.c
src/gallium/drivers/nvc0/nvc0_program.h
src/gallium/drivers/nvc0/nvc0_push.c
src/gallium/drivers/nvc0/nvc0_query.c
src/gallium/drivers/nvc0/nvc0_resource.h
src/gallium/drivers/nvc0/nvc0_screen.c
src/gallium/drivers/nvc0/nvc0_screen.h
src/gallium/drivers/nvc0/nvc0_shader_state.c
src/gallium/drivers/nvc0/nvc0_state.c
src/gallium/drivers/nvc0/nvc0_state_validate.c
src/gallium/drivers/nvc0/nvc0_stateobj.h
src/gallium/drivers/nvc0/nvc0_surface.c
src/gallium/drivers/nvc0/nvc0_tex.c
src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c
src/gallium/drivers/nvc0/nvc0_transfer.c
src/gallium/drivers/nvc0/nvc0_vbo.c
src/gallium/drivers/nvc0/nvc0_winsys.h
src/gallium/drivers/nvfx/nvfx_vbo.c
src/gallium/drivers/r300/r300_blit.c
src/gallium/drivers/r300/r300_cb.h
src/gallium/drivers/r300/r300_chipset.c
src/gallium/drivers/r300/r300_chipset.h
src/gallium/drivers/r300/r300_context.c
src/gallium/drivers/r300/r300_context.h
src/gallium/drivers/r300/r300_cs.h
src/gallium/drivers/r300/r300_debug.c
src/gallium/drivers/r300/r300_emit.c
src/gallium/drivers/r300/r300_flush.c
src/gallium/drivers/r300/r300_fs.c
src/gallium/drivers/r300/r300_hyperz.c
src/gallium/drivers/r300/r300_hyperz.h
src/gallium/drivers/r300/r300_query.c
src/gallium/drivers/r300/r300_reg.h
src/gallium/drivers/r300/r300_render.c
src/gallium/drivers/r300/r300_render_translate.c
src/gallium/drivers/r300/r300_resource.c
src/gallium/drivers/r300/r300_screen.c
src/gallium/drivers/r300/r300_screen.h
src/gallium/drivers/r300/r300_screen_buffer.c
src/gallium/drivers/r300/r300_screen_buffer.h
src/gallium/drivers/r300/r300_state.c
src/gallium/drivers/r300/r300_state_derived.c
src/gallium/drivers/r300/r300_state_inlines.h
src/gallium/drivers/r300/r300_texture.c
src/gallium/drivers/r300/r300_texture.h
src/gallium/drivers/r300/r300_texture_desc.c
src/gallium/drivers/r300/r300_texture_desc.h
src/gallium/drivers/r300/r300_tgsi_to_rc.c
src/gallium/drivers/r300/r300_tgsi_to_rc.h
src/gallium/drivers/r300/r300_transfer.c
src/gallium/drivers/r300/r300_vs.c
src/gallium/drivers/r300/r300_winsys.h
src/gallium/drivers/r600/Makefile
src/gallium/drivers/r600/SConscript
src/gallium/drivers/r600/eg_state_inlines.h
src/gallium/drivers/r600/evergreen_state.c
src/gallium/drivers/r600/evergreend.h
src/gallium/drivers/r600/r600.h
src/gallium/drivers/r600/r600_asm.c
src/gallium/drivers/r600/r600_asm.h
src/gallium/drivers/r600/r600_blit.c
src/gallium/drivers/r600/r600_buffer.c
src/gallium/drivers/r600/r600_pipe.c
src/gallium/drivers/r600/r600_pipe.h
src/gallium/drivers/r600/r600_resource.h
src/gallium/drivers/r600/r600_shader.c
src/gallium/drivers/r600/r600_shader.h
src/gallium/drivers/r600/r600_state.c
src/gallium/drivers/r600/r600_state_common.c
src/gallium/drivers/r600/r600_state_inlines.h
src/gallium/drivers/r600/r600_texture.c
src/gallium/drivers/r600/r600_translate.c
src/gallium/drivers/r600/r600_upload.c [deleted file]
src/gallium/drivers/r600/r600d.h
src/gallium/drivers/rbug/rbug_context.c
src/gallium/drivers/rbug/rbug_objects.c
src/gallium/drivers/softpipe/sp_context.c
src/gallium/drivers/softpipe/sp_context.h
src/gallium/drivers/softpipe/sp_flush.c
src/gallium/drivers/softpipe/sp_screen.c
src/gallium/drivers/softpipe/sp_setup.c
src/gallium/drivers/softpipe/sp_state_sampler.c
src/gallium/drivers/softpipe/sp_state_vertex.c
src/gallium/drivers/softpipe/sp_tex_sample.c
src/gallium/drivers/softpipe/sp_tex_tile_cache.c
src/gallium/drivers/softpipe/sp_tex_tile_cache.h
src/gallium/drivers/softpipe/sp_texture.c
src/gallium/drivers/softpipe/sp_tile_cache.c
src/gallium/drivers/svga/svga_context.c
src/gallium/drivers/svga/svga_context.h
src/gallium/drivers/svga/svga_draw.c
src/gallium/drivers/svga/svga_draw_arrays.c
src/gallium/drivers/svga/svga_draw_elements.c
src/gallium/drivers/svga/svga_pipe_blit.c
src/gallium/drivers/svga/svga_pipe_draw.c
src/gallium/drivers/svga/svga_pipe_flush.c
src/gallium/drivers/svga/svga_pipe_misc.c
src/gallium/drivers/svga/svga_pipe_rasterizer.c
src/gallium/drivers/svga/svga_pipe_sampler.c
src/gallium/drivers/svga/svga_pipe_vertex.c
src/gallium/drivers/svga/svga_resource.c
src/gallium/drivers/svga/svga_resource_buffer.c
src/gallium/drivers/svga/svga_resource_buffer.h
src/gallium/drivers/svga/svga_resource_buffer_upload.c
src/gallium/drivers/svga/svga_resource_texture.c
src/gallium/drivers/svga/svga_sampler_view.c
src/gallium/drivers/svga/svga_sampler_view.h
src/gallium/drivers/svga/svga_screen.c
src/gallium/drivers/svga/svga_state.h
src/gallium/drivers/svga/svga_state_framebuffer.c
src/gallium/drivers/svga/svga_state_need_swtnl.c
src/gallium/drivers/svga/svga_state_tss.c
src/gallium/drivers/svga/svga_state_vs.c
src/gallium/drivers/svga/svga_surface.c
src/gallium/drivers/svga/svga_surface.h
src/gallium/drivers/svga/svga_swtnl_backend.c
src/gallium/drivers/svga/svga_swtnl_draw.c
src/gallium/drivers/svga/svga_swtnl_state.c
src/gallium/drivers/svga/svga_tgsi_insn.c
src/gallium/drivers/svga/svgadump/svga_shader_op.c
src/gallium/drivers/trace/tr_context.c
src/gallium/drivers/trace/tr_dump_state.c
src/gallium/include/pipe/p_context.h
src/gallium/include/pipe/p_defines.h
src/gallium/include/pipe/p_format.h
src/gallium/include/pipe/p_shader_tokens.h
src/gallium/include/pipe/p_state.h
src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp
src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h
src/gallium/state_trackers/dri/common/dri_context.c
src/gallium/state_trackers/dri/common/dri_drawable.c
src/gallium/state_trackers/dri/common/dri_drawable.h
src/gallium/state_trackers/dri/common/dri_screen.c
src/gallium/state_trackers/dri/drm/dri2.c
src/gallium/state_trackers/dri/drm/dri2_buffer.h [new file with mode: 0644]
src/gallium/state_trackers/egl/Makefile
src/gallium/state_trackers/egl/common/egl_g3d.c
src/gallium/state_trackers/egl/common/egl_g3d_image.c
src/gallium/state_trackers/egl/common/native.h
src/gallium/state_trackers/egl/common/native_helper.c
src/gallium/state_trackers/egl/common/native_helper.h
src/gallium/state_trackers/egl/drm/native_drm.c
src/gallium/state_trackers/egl/wayland/native_wayland.c [new file with mode: 0644]
src/gallium/state_trackers/egl/wayland/native_wayland.h [new file with mode: 0644]
src/gallium/state_trackers/egl/x11/native_dri2.c
src/gallium/state_trackers/python/p_context.i
src/gallium/state_trackers/python/p_device.i
src/gallium/state_trackers/vega/Makefile
src/gallium/state_trackers/vega/SConscript
src/gallium/state_trackers/vega/api_filters.c
src/gallium/state_trackers/vega/api_images.c
src/gallium/state_trackers/vega/api_masks.c
src/gallium/state_trackers/vega/api_paint.c
src/gallium/state_trackers/vega/api_params.c
src/gallium/state_trackers/vega/api_path.c
src/gallium/state_trackers/vega/api_text.c
src/gallium/state_trackers/vega/handle.c [new file with mode: 0644]
src/gallium/state_trackers/vega/handle.h [new file with mode: 0644]
src/gallium/state_trackers/vega/image.c
src/gallium/state_trackers/vega/paint.c
src/gallium/state_trackers/vega/paint.h
src/gallium/state_trackers/vega/polygon.c
src/gallium/state_trackers/vega/renderer.c
src/gallium/state_trackers/vega/shader.c
src/gallium/state_trackers/vega/vg_context.c
src/gallium/state_trackers/vega/vg_context.h
src/gallium/state_trackers/vega/vg_manager.c
src/gallium/state_trackers/vega/vgu.c
src/gallium/state_trackers/wgl/SConscript
src/gallium/state_trackers/wgl/stw_device.c
src/gallium/state_trackers/xorg/xorg_crtc.c
src/gallium/state_trackers/xorg/xorg_renderer.c
src/gallium/state_trackers/xorg/xvmc/subpicture.c
src/gallium/state_trackers/xorg/xvmc/surface.c
src/gallium/targets/SConscript.dri
src/gallium/targets/dri-r300/Makefile
src/gallium/targets/dri-r300/SConscript
src/gallium/targets/dri-r600/SConscript
src/gallium/targets/dri-vmwgfx/Makefile
src/gallium/targets/egl-static/SConscript
src/gallium/targets/egl/Makefile
src/gallium/targets/libgl-gdi/SConscript
src/gallium/targets/libgl-xlib/SConscript
src/gallium/targets/xorg-radeon/Makefile
src/gallium/tests/graw/SConscript
src/gallium/tests/graw/fs-test.c
src/gallium/tests/graw/gs-test.c
src/gallium/tests/graw/quad-sample.c [new file with mode: 0644]
src/gallium/tests/graw/quad-tex.c
src/gallium/tests/graw/shader-leak.c
src/gallium/tests/graw/tri-gs.c
src/gallium/tests/graw/tri-instanced.c
src/gallium/tests/graw/tri.c
src/gallium/tests/graw/vs-test.c
src/gallium/tests/trivial/quad-tex.c
src/gallium/tests/trivial/tri.c
src/gallium/winsys/SConscript
src/gallium/winsys/i915/drm/i915_drm_batchbuffer.c
src/gallium/winsys/i915/sw/i915_sw_batchbuffer.c
src/gallium/winsys/i915/sw/i915_sw_buffer.c
src/gallium/winsys/r600/drm/SConscript
src/gallium/winsys/r600/drm/evergreen_hw_context.c
src/gallium/winsys/r600/drm/r600_bo.c
src/gallium/winsys/r600/drm/r600_drm.c
src/gallium/winsys/r600/drm/r600_hw_context.c
src/gallium/winsys/r600/drm/r600_priv.h
src/gallium/winsys/r600/drm/radeon_bo.c
src/gallium/winsys/r600/drm/radeon_pciid.c
src/gallium/winsys/radeon/drm/Makefile
src/gallium/winsys/radeon/drm/SConscript
src/gallium/winsys/radeon/drm/radeon_drm_bo.c [new file with mode: 0644]
src/gallium/winsys/radeon/drm/radeon_drm_bo.h [new file with mode: 0644]
src/gallium/winsys/radeon/drm/radeon_drm_buffer.c [deleted file]
src/gallium/winsys/radeon/drm/radeon_drm_buffer.h [deleted file]
src/gallium/winsys/radeon/drm/radeon_drm_common.c
src/gallium/winsys/radeon/drm/radeon_drm_cs.c
src/gallium/winsys/radeon/drm/radeon_drm_cs.h
src/gallium/winsys/radeon/drm/radeon_r300.c [deleted file]
src/gallium/winsys/radeon/drm/radeon_winsys.h
src/gallium/winsys/svga/drm/vmw_buffer.c
src/gallium/winsys/svga/drm/vmw_context.c
src/gallium/winsys/sw/xlib/SConscript
src/glsl/Makefile
src/glsl/SConscript
src/glsl/ast.h
src/glsl/ast_expr.cpp
src/glsl/ast_function.cpp
src/glsl/ast_to_hir.cpp
src/glsl/ast_type.cpp
src/glsl/builtins/profiles/130.frag
src/glsl/builtins/profiles/130.vert
src/glsl/builtins/tools/generate_builtins.py
src/glsl/builtins/tools/texture_builtins.py
src/glsl/configure.ac [deleted file]
src/glsl/glcpp/glcpp-lex.c
src/glsl/glcpp/glcpp-lex.l
src/glsl/glcpp/glcpp-parse.c
src/glsl/glcpp/glcpp-parse.y
src/glsl/glcpp/glcpp.c
src/glsl/glcpp/glcpp.h
src/glsl/glcpp/pp.c
src/glsl/glsl_lexer.cpp
src/glsl/glsl_lexer.lpp
src/glsl/glsl_parser.cpp
src/glsl/glsl_parser.h
src/glsl/glsl_parser.ypp
src/glsl/glsl_parser_extras.cpp
src/glsl/glsl_parser_extras.h
src/glsl/glsl_symbol_table.cpp
src/glsl/glsl_symbol_table.h
src/glsl/glsl_types.cpp
src/glsl/glsl_types.h
src/glsl/ir.cpp
src/glsl/ir.h
src/glsl/ir_clone.cpp
src/glsl/ir_constant_expression.cpp
src/glsl/ir_expression_flattening.cpp
src/glsl/ir_function.cpp
src/glsl/ir_hv_accept.cpp
src/glsl/ir_import_prototypes.cpp
src/glsl/ir_optimization.h
src/glsl/ir_print_visitor.cpp
src/glsl/ir_reader.cpp
src/glsl/ir_rvalue_visitor.cpp
src/glsl/ir_validate.cpp
src/glsl/ir_variable.cpp
src/glsl/ir_variable_refcount.h
src/glsl/link_functions.cpp
src/glsl/linker.cpp
src/glsl/list.h
src/glsl/loop_analysis.cpp
src/glsl/loop_controls.cpp
src/glsl/loop_unroll.cpp
src/glsl/lower_discard.cpp
src/glsl/lower_if_to_cond_assign.cpp
src/glsl/lower_mat_op_to_vec.cpp
src/glsl/lower_noise.cpp
src/glsl/lower_texture_projection.cpp
src/glsl/lower_variable_index_to_cond_assign.cpp
src/glsl/lower_vec_index_to_cond_assign.cpp
src/glsl/lower_vec_index_to_swizzle.cpp
src/glsl/lower_vector.cpp
src/glsl/main.cpp
src/glsl/opt_algebraic.cpp
src/glsl/opt_constant_folding.cpp
src/glsl/opt_constant_propagation.cpp
src/glsl/opt_constant_variable.cpp
src/glsl/opt_copy_propagation.cpp
src/glsl/opt_copy_propagation_elements.cpp [new file with mode: 0644]
src/glsl/opt_dead_code_local.cpp
src/glsl/opt_dead_functions.cpp
src/glsl/opt_function_inlining.cpp
src/glsl/opt_structure_splitting.cpp
src/glsl/opt_tree_grafting.cpp
src/glsl/ralloc.c [new file with mode: 0644]
src/glsl/ralloc.h [new file with mode: 0644]
src/glsl/s_expression.cpp
src/glsl/s_expression.h
src/glx/dri2_glx.c
src/glx/dri_glx.c
src/glx/drisw_glx.c
src/glx/glx_pbuffer.c
src/glx/glxclient.h
src/glx/glxcmds.c
src/glx/glxext.c
src/mapi/es1api/.gitignore
src/mapi/es1api/Makefile
src/mapi/es2api/.gitignore
src/mapi/glapi/Makefile
src/mapi/glapi/SConscript
src/mapi/glapi/gen/gl_x86-64_asm.py
src/mapi/glapi/gen/gl_x86_asm.py
src/mapi/glapi/glapi.h
src/mapi/glapi/glapi_x86-64.S
src/mapi/glapi/glapi_x86.S
src/mapi/mapi/entry.c
src/mapi/shared-glapi/.gitignore [new file with mode: 0644]
src/mapi/shared-glapi/Makefile
src/mapi/shared-glapi/SConscript [new file with mode: 0644]
src/mapi/vgapi/Makefile
src/mesa/Makefile
src/mesa/SConscript
src/mesa/drivers/beos/GLView.cpp
src/mesa/drivers/common/driverfuncs.c
src/mesa/drivers/dri/Makefile.template
src/mesa/drivers/dri/common/dri_metaops.c [deleted file]
src/mesa/drivers/dri/common/dri_metaops.h [deleted file]
src/mesa/drivers/dri/common/dri_util.c
src/mesa/drivers/dri/common/dri_util.h
src/mesa/drivers/dri/common/drisw_util.c
src/mesa/drivers/dri/i810/i810context.c
src/mesa/drivers/dri/i915/i830_vtbl.c
src/mesa/drivers/dri/i915/i915_context.c
src/mesa/drivers/dri/i915/i915_context.h
src/mesa/drivers/dri/i915/i915_fragprog.c
src/mesa/drivers/dri/i915/i915_program.c
src/mesa/drivers/dri/i915/i915_reg.h
src/mesa/drivers/dri/i915/i915_state.c
src/mesa/drivers/dri/i915/i915_vtbl.c
src/mesa/drivers/dri/i915/intel_render.c
src/mesa/drivers/dri/i915/intel_tris.c
src/mesa/drivers/dri/i965/brw_cc.c
src/mesa/drivers/dri/i965/brw_context.h
src/mesa/drivers/dri/i965/brw_cubemap_normalize.cpp
src/mesa/drivers/dri/i965/brw_curbe.c
src/mesa/drivers/dri/i965/brw_defines.h
src/mesa/drivers/dri/i965/brw_draw.c
src/mesa/drivers/dri/i965/brw_draw_upload.c
src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_fs.h
src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp
src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp
src/mesa/drivers/dri/i965/brw_fs_schedule_instructions.cpp
src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp
src/mesa/drivers/dri/i965/brw_misc_state.c
src/mesa/drivers/dri/i965/brw_program.c
src/mesa/drivers/dri/i965/brw_queryobj.c
src/mesa/drivers/dri/i965/brw_state.h
src/mesa/drivers/dri/i965/brw_state_batch.c
src/mesa/drivers/dri/i965/brw_state_cache.c
src/mesa/drivers/dri/i965/brw_state_dump.c
src/mesa/drivers/dri/i965/brw_state_upload.c
src/mesa/drivers/dri/i965/brw_util.c
src/mesa/drivers/dri/i965/brw_util.h
src/mesa/drivers/dri/i965/brw_vs_surface_state.c
src/mesa/drivers/dri/i965/brw_vtbl.c
src/mesa/drivers/dri/i965/brw_wm.c
src/mesa/drivers/dri/i965/brw_wm_state.c
src/mesa/drivers/dri/i965/brw_wm_surface_state.c
src/mesa/drivers/dri/i965/gen6_cc.c
src/mesa/drivers/dri/i965/gen6_sf_state.c
src/mesa/drivers/dri/intel/intel_batchbuffer.c
src/mesa/drivers/dri/intel/intel_batchbuffer.h
src/mesa/drivers/dri/intel/intel_blit.c
src/mesa/drivers/dri/intel/intel_buffer_objects.c
src/mesa/drivers/dri/intel/intel_buffer_objects.h
src/mesa/drivers/dri/intel/intel_context.c
src/mesa/drivers/dri/intel/intel_context.h
src/mesa/drivers/dri/intel/intel_extensions.c
src/mesa/drivers/dri/intel/intel_fbo.c
src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
src/mesa/drivers/dri/intel/intel_pixel_read.c
src/mesa/drivers/dri/intel/intel_regions.c
src/mesa/drivers/dri/intel/intel_screen.c
src/mesa/drivers/dri/intel/intel_syncobj.c
src/mesa/drivers/dri/intel/intel_tex.h
src/mesa/drivers/dri/intel/intel_tex_copy.c
src/mesa/drivers/dri/intel/intel_tex_image.c
src/mesa/drivers/dri/mach64/mach64_context.c
src/mesa/drivers/dri/mga/mga_xmesa.c
src/mesa/drivers/dri/nouveau/nouveau_context.c
src/mesa/drivers/dri/r128/r128_context.c
src/mesa/drivers/dri/r200/r200_vertprog.c
src/mesa/drivers/dri/r300/compiler/r300_fragprog.c
src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c
src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c
src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c
src/mesa/drivers/dri/r300/compiler/radeon_code.h
src/mesa/drivers/dri/r300/compiler/radeon_compiler.c
src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c
src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h
src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c
src/mesa/drivers/dri/r300/compiler/radeon_optimize.c
src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c
src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c
src/mesa/drivers/dri/r300/compiler/radeon_program.h
src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c
src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c
src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h
src/mesa/drivers/dri/r300/compiler/radeon_program_print.c
src/mesa/drivers/dri/r300/r300_blit.c
src/mesa/drivers/dri/r300/r300_fragprog_common.c
src/mesa/drivers/dri/r300/r300_reg.h
src/mesa/drivers/dri/r300/radeon_mesa_to_rc.c
src/mesa/drivers/dri/r600/evergreen_fragprog.c
src/mesa/drivers/dri/r600/r700_fragprog.c
src/mesa/drivers/dri/radeon/radeon_chipset.h
src/mesa/drivers/dri/radeon/radeon_common.c
src/mesa/drivers/dri/radeon/radeon_common_context.c
src/mesa/drivers/dri/radeon/radeon_common_context.h
src/mesa/drivers/dri/radeon/radeon_fbo.c
src/mesa/drivers/dri/radeon/radeon_screen.c
src/mesa/drivers/dri/savage/savage_xmesa.c
src/mesa/drivers/dri/sis/sis_context.c
src/mesa/drivers/dri/swrast/swrast.c
src/mesa/drivers/dri/tdfx/tdfx_context.c
src/mesa/drivers/dri/unichrome/via_context.c
src/mesa/drivers/fbdev/glfbdev.c
src/mesa/drivers/osmesa/Makefile
src/mesa/drivers/osmesa/osmesa.c
src/mesa/drivers/windows/gdi/wmesa.c
src/mesa/drivers/windows/gldirect/dglcontext.c
src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c
src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c
src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c
src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c
src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c
src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c
src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c
src/mesa/drivers/x11/fakeglx.c
src/mesa/drivers/x11/xm_api.c
src/mesa/drivers/x11/xmesa.h
src/mesa/main/APIspec.xml
src/mesa/main/accum.c
src/mesa/main/arrayobj.c
src/mesa/main/blend.c
src/mesa/main/bufferobj.c
src/mesa/main/context.c
src/mesa/main/context.h
src/mesa/main/debug.c
src/mesa/main/debug.h
src/mesa/main/depth.c
src/mesa/main/dlist.c
src/mesa/main/drawpix.c
src/mesa/main/enable.c
src/mesa/main/extensions.c
src/mesa/main/fbobject.c
src/mesa/main/fbobject.h
src/mesa/main/formats.c
src/mesa/main/formats.h
src/mesa/main/framebuffer.c
src/mesa/main/hint.c
src/mesa/main/image.c
src/mesa/main/imports.c
src/mesa/main/imports.h
src/mesa/main/lines.c
src/mesa/main/mipmap.c
src/mesa/main/mtypes.h
src/mesa/main/queryobj.c
src/mesa/main/readpix.c
src/mesa/main/renderbuffer.c
src/mesa/main/shaderapi.c
src/mesa/main/shaderobj.c
src/mesa/main/state.c
src/mesa/main/stencil.c
src/mesa/main/texformat.c
src/mesa/main/texgetimage.c
src/mesa/main/teximage.c
src/mesa/main/texparam.c
src/mesa/main/uniforms.c
src/mesa/main/varray.c
src/mesa/program/ir_to_mesa.cpp
src/mesa/program/register_allocate.c
src/mesa/program/sampler.cpp
src/mesa/state_tracker/st_atom_blend.c
src/mesa/state_tracker/st_atom_framebuffer.c
src/mesa/state_tracker/st_atom_pixeltransfer.c
src/mesa/state_tracker/st_atom_rasterizer.c
src/mesa/state_tracker/st_atom_sampler.c
src/mesa/state_tracker/st_atom_viewport.c
src/mesa/state_tracker/st_cb_accum.c
src/mesa/state_tracker/st_cb_bitmap.c
src/mesa/state_tracker/st_cb_bufferobjects.c
src/mesa/state_tracker/st_cb_clear.c
src/mesa/state_tracker/st_cb_drawpixels.c
src/mesa/state_tracker/st_cb_drawtex.c
src/mesa/state_tracker/st_cb_fbo.c
src/mesa/state_tracker/st_cb_readpixels.c
src/mesa/state_tracker/st_cb_texture.c
src/mesa/state_tracker/st_context.c
src/mesa/state_tracker/st_context.h
src/mesa/state_tracker/st_draw.c
src/mesa/state_tracker/st_draw_feedback.c
src/mesa/state_tracker/st_extensions.c
src/mesa/state_tracker/st_format.c
src/mesa/state_tracker/st_format.h
src/mesa/state_tracker/st_gen_mipmap.c
src/mesa/state_tracker/st_manager.c
src/mesa/state_tracker/st_mesa_to_tgsi.c
src/mesa/state_tracker/st_program.c
src/mesa/state_tracker/st_texture.c
src/mesa/state_tracker/st_texture.h
src/mesa/swrast/s_trispan.h [deleted file]
src/mesa/tnl/t_draw.c
src/mesa/vbo/vbo.h
src/mesa/vbo/vbo_exec.h
src/mesa/vbo/vbo_exec_api.c
src/mesa/vbo/vbo_exec_array.c
src/mesa/vbo/vbo_exec_draw.c
src/mesa/vbo/vbo_save_api.c
src/mesa/vbo/vbo_save_draw.c
src/mesa/x86-64/xform4.S
src/mesa/x86/read_rgba_span_x86.S
src/talloc/SConscript [deleted file]
src/talloc/gpl-3.0.txt [deleted file]
src/talloc/lgpl-3.0.txt [deleted file]
src/talloc/talloc.c [deleted file]
src/talloc/talloc.def [deleted file]
src/talloc/talloc.h [deleted file]
src/talloc/talloc_guide.txt [deleted file]

index 1bab521c599ab4510410a6a69e060ccf649366b1..cb9943d7a2128ba1c84c3ca7d2f1aba2dda86cb1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -232,6 +232,7 @@ MAIN_FILES = \
        $(DIRECTORY)/src/glsl/README                                    \
        $(DIRECTORY)/src/glsl/glcpp/*.[chly]                            \
        $(DIRECTORY)/src/glsl/glcpp/README                              \
+       $(DIRECTORY)/src/glsl/builtins                                  \
        $(DIRECTORY)/src/Makefile                                       \
        $(DIRECTORY)/src/mesa/Makefile*                                 \
        $(DIRECTORY)/src/mesa/sources.mak                               \
@@ -283,8 +284,7 @@ MAIN_FILES = \
        $(DIRECTORY)/src/mesa/x86/*.S                                   \
        $(DIRECTORY)/src/mesa/x86/rtasm/*.[ch]                          \
        $(DIRECTORY)/src/mesa/x86-64/*.[chS]                            \
-       $(DIRECTORY)/src/mesa/x86-64/Makefile                           \
-       $(DIRECTORY)/windows/VC8/
+       $(DIRECTORY)/src/mesa/x86-64/Makefile
 
 MAPI_FILES = \
        $(DIRECTORY)/include/GLES/*.h                                   \
index 368ad83edf3f552bf837c9368784370c8e885d92..8607d2cd8e0ab726039d02202e067c158ae75ff4 100644 (file)
@@ -56,6 +56,12 @@ else:
 
 Help(opts.GenerateHelpText(env))
 
+# fail early for a common error on windows
+if env['gles']:
+    try:
+        import libxml2
+    except ImportError:
+        raise SCons.Errors.UserError, "GLES requires libxml2-python to build"
 
 #######################################################################
 # Environment setup
@@ -115,8 +121,6 @@ if env['platform'] in ('posix', 'linux', 'freebsd', 'darwin'):
 # for debugging
 #print env.Dump()
 
-Export('env')
-
 
 #######################################################################
 # Invoke host SConscripts 
@@ -126,7 +130,7 @@ Export('env')
 #
 
 # Create host environent
-if env['platform'] != common.host_platform:
+if env['crosscompile'] and env['platform'] != 'embedded':
     host_env = Environment(
         options = opts,
         # no tool used
@@ -143,13 +147,25 @@ if env['platform'] != common.host_platform:
 
     host_env.Tool('gallium')
 
+    host_env['hostonly'] = True
+    assert host_env['crosscompile'] == False
+
+    if host_env['msvc']:
+        host_env.Append(CPPPATH = ['#include/c99'])
+
+    target_env = env
+    env = host_env
+    Export('env')
+
     SConscript(
-        'src/glsl/SConscript',
+        'src/SConscript',
         variant_dir = host_env['build_dir'],
         duplicate = 0, # http://www.scons.org/doc/0.97/HTML/scons-user/x2261.html
-        exports={'env':host_env},
     )
 
+    env = target_env
+
+Export('env')
 
 #######################################################################
 # Invoke SConscripts
index 76184d577a3433231885a10755ab4f0b73905e0d..b44f20e821667030383adf9dd70f2c07c2b53501 100644 (file)
--- a/common.py
+++ b/common.py
@@ -14,13 +14,7 @@ import SCons.Script.SConscript
 #######################################################################
 # Defaults
 
-_platform_map = {
-       'linux2': 'linux',
-       'win32': 'windows',
-}
-
-host_platform = sys.platform
-host_platform = _platform_map.get(host_platform, host_platform)
+host_platform = _platform.system().lower()
 
 # Search sys.argv[] for a "platform=foo" argument since we don't have
 # an 'env' variable at this point.
@@ -29,8 +23,6 @@ if 'platform' in SCons.Script.ARGUMENTS:
 else:
     target_platform = host_platform
 
-cross_compiling = target_platform != host_platform
-
 _machine_map = {
        'x86': 'x86',
        'i386': 'x86',
@@ -38,6 +30,7 @@ _machine_map = {
        'i586': 'x86',
        'i686': 'x86',
        'ppc' : 'ppc',
+       'AMD64': 'x86_64',
        'x86_64': 'x86_64',
 }
 
@@ -52,7 +45,7 @@ host_machine = _machine_map.get(host_machine, 'generic')
 default_machine = host_machine
 default_toolchain = 'default'
 
-if target_platform == 'windows' and cross_compiling:
+if target_platform == 'windows' and host_platform != 'windows':
     default_machine = 'x86'
     default_toolchain = 'crossmingw'
 
@@ -88,8 +81,9 @@ def AddOptions(opts):
        opts.Add(EnumOption('machine', 'use machine-specific assembly code', default_machine,
                                                                                         allowed_values=('generic', 'ppc', 'x86', 'x86_64')))
        opts.Add(EnumOption('platform', 'target platform', host_platform,
-                                                                                        allowed_values=('linux', 'cell', 'windows', 'winddk', 'wince', 'darwin', 'embedded', 'cygwin', 'sunos5', 'freebsd8')))
+                                                                                        allowed_values=('linux', 'cell', 'windows', 'winddk', 'wince', 'darwin', 'embedded', 'cygwin_nt-5.1', 'cygwin_nt-6.1', 'sunos5', 'freebsd8')))
        opts.Add('toolchain', 'compiler toolchain', default_toolchain)
+       opts.Add(BoolOption('gles', 'EXPERIMENTAL: enable OpenGL ES support', 'no'))
        opts.Add(BoolOption('llvm', 'use LLVM', default_llvm))
        opts.Add(BoolOption('debug', 'DEPRECATED: debug build', 'yes'))
        opts.Add(BoolOption('profile', 'DEPRECATED: profile build', 'no'))
index dc8f8622416a00f52745299547732aa191045534..9defba21afbf16b0c3d02bd26cf8e2a620fb9a6b 100644 (file)
@@ -16,10 +16,12 @@ PIC_FLAGS = @PIC_FLAGS@
 DEFINES = @DEFINES@
 API_DEFINES = @API_DEFINES@
 SHARED_GLAPI = @SHARED_GLAPI@
-CFLAGS = @CPPFLAGS@ @CFLAGS@ \
+CFLAGS_NOVISIBILITY = @CPPFLAGS@ @CFLAGS@ \
        $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(ASM_FLAGS) $(DEFINES)
-CXXFLAGS = @CPPFLAGS@ @CXXFLAGS@ \
+CXXFLAGS_NOVISIBILITY = @CPPFLAGS@ @CXXFLAGS@ \
        $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES)
+CFLAGS = $(CFLAGS_NOVISIBILITY) @VISIBILITY_CFLAGS@
+CXXFLAGS = $(CXXFLAGS_NOVISIBILITY) @VISIBILITY_CXXFLAGS@
 LDFLAGS = @LDFLAGS@
 EXTRA_LIB_PATH = @EXTRA_LIB_PATH@
 RADEON_CFLAGS = @RADEON_CFLAGS@
@@ -34,9 +36,8 @@ LLVM_LIBS = @LLVM_LIBS@
 GLW_CFLAGS = @GLW_CFLAGS@
 GLUT_CFLAGS = @GLUT_CFLAGS@
 GLX_TLS = @GLX_TLS@
-
-TALLOC_LIBS = @TALLOC_LIBS@
-TALLOC_CFLAGS = @TALLOC_CFLAGS@
+DRI_CFLAGS = @DRI_CFLAGS@
+DRI_CXXFLAGS = @DRI_CXXFLAGS@
 
 # dlopen
 DLOPEN_LIBS = @DLOPEN_LIBS@
@@ -67,6 +68,7 @@ GLESv1_CM_LIB = GLESv1_CM
 GLESv2_LIB = GLESv2
 VG_LIB = OpenVG
 GLAPI_LIB = glapi
+WAYLAND_EGL_LIB = wayland-egl
 
 # Library names (actual file names)
 GL_LIB_NAME = @GL_LIB_NAME@
@@ -79,6 +81,7 @@ GLESv1_CM_LIB_NAME = @GLESv1_CM_LIB_NAME@
 GLESv2_LIB_NAME = @GLESv2_LIB_NAME@
 VG_LIB_NAME = @VG_LIB_NAME@
 GLAPI_LIB_NAME = @GLAPI_LIB_NAME@
+WAYLAND_EGL_LIB_NAME = @WAYLAND_EGL_LIB_NAME@
 
 # Globs used to install the lib and all symlinks
 GL_LIB_GLOB = @GL_LIB_GLOB@
@@ -91,6 +94,7 @@ GLESv1_CM_LIB_GLOB = @GLESv1_CM_LIB_GLOB@
 GLESv2_LIB_GLOB = @GLESv2_LIB_GLOB@
 VG_LIB_GLOB = @VG_LIB_GLOB@
 GLAPI_LIB_GLOB = @GLAPI_LIB_GLOB@
+WAYLAND_EGL_LIB_GLOB = @WAYLAND_EGL_LIB_GLOB@
 
 # Directories to build
 LIB_DIR = @LIB_DIR@
@@ -107,7 +111,10 @@ GALLIUM_AUXILIARIES = $(TOP)/src/gallium/auxiliary/libgallium.a
 GALLIUM_DRIVERS = $(foreach DIR,$(GALLIUM_DRIVERS_DIRS),$(TOP)/src/gallium/drivers/$(DIR)/lib$(DIR).a)
 
 # Driver specific build vars
-DRI_DIRS = @DRI_DIRS@ 
+DRI_DIRS = @DRI_DIRS@
+DRICORE_GLSL_LIBS = @DRICORE_GLSL_LIBS@
+DRICORE_LIBS = @DRICORE_LIBS@
+DRICORE_LIB_DEPS = @DRICORE_LIB_DEPS@
 EGL_PLATFORMS = @EGL_PLATFORMS@
 EGL_CLIENT_APIS = @EGL_CLIENT_APIS@
 
@@ -134,8 +141,10 @@ GLESv1_CM_LIB_DEPS = $(EXTRA_LIB_PATH) @GLESv1_CM_LIB_DEPS@
 GLESv2_LIB_DEPS = $(EXTRA_LIB_PATH) @GLESv2_LIB_DEPS@
 VG_LIB_DEPS = $(EXTRA_LIB_PATH) @VG_LIB_DEPS@
 GLAPI_LIB_DEPS = $(EXTRA_LIB_PATH) @GLAPI_LIB_DEPS@
+WAYLAND_EGL_LIB_DEPS = $(EXTRA_LIBPATH) @WAYLAND_EGL_LIB_DEPS@
 
 # DRI dependencies
+MESA_MODULES = @MESA_MODULES@
 DRI_LIB_DEPS = $(EXTRA_LIB_PATH) @DRI_LIB_DEPS@
 LIBDRM_CFLAGS = @LIBDRM_CFLAGS@
 LIBDRM_LIB = @LIBDRM_LIBS@
@@ -193,11 +202,16 @@ GLESv2_PC_LIB_PRIV = @GLESv2_PC_LIB_PRIV@
 EGL_PC_REQ_PRIV = @GL_PC_REQ_PRIV@
 EGL_PC_LIB_PRIV = @GL_PC_LIB_PRIV@
 EGL_PC_CFLAGS = @GL_PC_CFLAGS@
+WAYLAND_EGL_PC_REQ_PRIV = @WAYLAND_EGL_PC_REQ_PRIV@
+WAYLAND_EGL_PC_LIB_PRIV = @WAYLAND_EGL_PC_LIB_PRIV@
+WAYLAND_EGL_PC_CFLAGS = @WAYLAND_EGL_PC_CFLAGS@
 
 XCB_DRI2_CFLAGS = @XCB_DRI2_CFLAGS@
 XCB_DRI2_LIBS = @XCB_DRI2_LIBS@
 LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@
 LIBUDEV_LIBS = @LIBUDEV_LIBS@
+WAYLAND_CFLAGS = @WAYLAND_CFLAGS@
+WAYLAND_LIBS = @WAYLAND_LIBS@
 
 MESA_LLVM = @MESA_LLVM@
 
index 9030cf5b9dfe4864217c64e876a399ff10182d28..0582a0210af884003e5040818ace78950b6d0e6d 100644 (file)
@@ -60,6 +60,7 @@ GLESv1_CM_LIB = GLESv1_CM
 GLESv2_LIB = GLESv2
 VG_LIB = OpenVG
 GLAPI_LIB = glapi
+WAYLAND_EGL_LIB = wayland-egl
 
 
 # Library names (actual file names)
@@ -73,6 +74,7 @@ GLESv1_CM_LIB_NAME = lib$(GLESv1_CM_LIB).so
 GLESv2_LIB_NAME = lib$(GLESv2_LIB).so
 VG_LIB_NAME = lib$(VG_LIB).so
 GLAPI_LIB_NAME = lib$(GLAPI_LIB).so
+WAYLAND_EGL_LIB_NAME = lib$(WAYLAND_EGL_LIB).so
 
 # globs used to install the lib and all symlinks
 GL_LIB_GLOB = $(GL_LIB_NAME)*
@@ -85,9 +87,10 @@ GLESv1_CM_LIB_GLOB = $(GLESv1_CM_LIB_NAME)*
 GLESv2_LIB_GLOB = $(GLESv2_LIB_NAME)*
 VG_LIB_GLOB = $(VG_LIB_NAME)*
 GLAPI_LIB_GLOB = $(GLAPI_LIB_NAME)*
+WAYLAND_EGL_LIB_GLOB = $(WAYLAND_EGL_LIB_NAME)*
 
-TALLOC_LIBS = `pkg-config --libs talloc`
-TALLOC_CFLAGS = `pkg-config --cflags talloc`
+DRI_CFLAGS = $(CFLAGS)
+DRI_CXXFLAGS = $(CXXFLAGS)
 
 # Optional assembly language optimization files for libGL
 MESA_ASM_SOURCES = 
@@ -123,7 +126,7 @@ EGL_CLIENT_APIS = $(GL_LIB)
 
 # Library dependencies
 #EXTRA_LIB_PATH ?=
-GL_LIB_DEPS     = $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread $(TALLOC_LIBS)
+GL_LIB_DEPS     = $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread
 EGL_LIB_DEPS    = $(EXTRA_LIB_PATH) -ldl -lpthread
 OSMESA_LIB_DEPS = $(EXTRA_LIB_PATH) -L$(TOP)/$(LIB_DIR) -l$(GL_LIB)
 GLU_LIB_DEPS    = $(EXTRA_LIB_PATH) -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) -lm
@@ -134,6 +137,7 @@ GLESv1_CM_LIB_DEPS = $(EXTRA_LIB_PATH) -lpthread
 GLESv2_LIB_DEPS = $(EXTRA_LIB_PATH) -lpthread
 VG_LIB_DEPS    = $(EXTRA_LIB_PATH) -lpthread
 GLAPI_LIB_DEPS = $(EXTRA_LIB_PATH) -lpthread
+WAYLAND_EGL_LIB_DEPS = $(EXTRA_LIB_PATH) -lwayland-client -ldrm
 
 # Program dependencies - specific GL/glut libraries added in Makefiles
 APP_LIB_DEPS = -lm
@@ -182,3 +186,6 @@ GLESv2_PC_CFLAGS =
 VG_PC_REQ_PRIV =
 VG_PC_LIB_PRIV =
 VG_PC_CFLAGS =
+WAYLAND_EGL_PC_REQ_PRIV =
+WAYLAND_EGL_PC_LIB_PRIV =
+WAYLAND_EGL_PC_CFLAGS =
index a4aa82e96df0f0514678c7cf0a69a32848d8f191..23cf58a3bf58657e21ae7e43c50097b354424bcc 100644 (file)
@@ -30,9 +30,11 @@ ASM_SOURCES =
 MESA_ASM_SOURCES = 
 
 # Library/program dependencies
+MESA_MODULES  = $(TOP)/src/mesa/libmesa.a
+
 LIBDRM_CFLAGS = `pkg-config --cflags libdrm`
 LIBDRM_LIB = `pkg-config --libs libdrm`
-DRI_LIB_DEPS = -L/usr/local/lib -lm -pthread -lexpat $(LIBDRM_LIB)
+DRI_LIB_DEPS = $(MESA_MODULES) -L/usr/local/lib -lm -pthread -lexpat $(LIBDRM_LIB)
 GL_LIB_DEPS = -L/usr/local/lib -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \
        -lm -pthread $(LIBDRM_LIB)
 
index 9a0253f919b18def99bec183237797b84b0a0883..ce2da8317d754443ad88d6d75b16f4e84b395ddf 100644 (file)
@@ -43,9 +43,11 @@ MESA_ASM_SOURCES =
 # Library/program dependencies
 EXTRA_LIB_PATH=-L/usr/X11R6/lib
 
+MESA_MODULES  = $(TOP)/src/mesa/libmesa.a
+
 LIBDRM_CFLAGS = $(shell pkg-config --cflags libdrm)
 LIBDRM_LIB = $(shell pkg-config --libs libdrm)
-DRI_LIB_DEPS  = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl -ltalloc $(LIBDRM_LIB)
+DRI_LIB_DEPS  = $(MESA_MODULES) $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB)
 GL_LIB_DEPS   = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \
                -lm -lpthread -ldl $(LIBDRM_LIB)
 
index 8092a048d7c5add318394002b92341b578ca1884..7518080703b9266c30615f5ae783c74b62126584 100644 (file)
@@ -41,9 +41,11 @@ MESA_ASM_SOURCES =
 # Library/program dependencies
 EXTRA_LIB_PATH=$(shell pkg-config --libs-only-L x11)
 
+MESA_MODULES  = $(TOP)/src/mesa/libmesa.a
+
 LIBDRM_CFLAGS = $(shell pkg-config --cflags libdrm)
 LIBDRM_LIB = $(shell pkg-config --libs libdrm)
-DRI_LIB_DEPS  = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB)
+DRI_LIB_DEPS  = $(MESA_MODULES) $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB)
 GL_LIB_DEPS   = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lm -lpthread -ldl \
                 $(LIBDRM_LIB) $(shell pkg-config --libs xcb) $(shell pkg-config --libs x11-xcb) $(shell pkg-config --libs xcb-glx)
 
index 6393e942c791a85d249046ba3befb01eaf5d7082..216bcbab321f907ccea98212f529debbc2566a95 100644 (file)
@@ -38,9 +38,11 @@ MESA_ASM_SOURCES =
 # Library/program dependencies
 EXTRA_LIB_PATH=-L/usr/X11R6/lib
 
+MESA_MODULES  = $(TOP)/src/mesa/libmesa.a
+
 LIBDRM_CFLAGS = $(shell pkg-config --cflags libdrm)
 LIBDRM_LIB = $(shell pkg-config --libs libdrm)
-DRI_LIB_DEPS  = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB)
+DRI_LIB_DEPS  = $(MESA_MODULES) $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB)
 GL_LIB_DEPS   = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \
                -lm -lpthread -ldl \
                 $(LIBDRM_LIB)
index 272d34e8407fb95cdad5ba43ac77079318943e9a..507382adced86245b87a46aedcf8b5ae3aa1d5f7 100644 (file)
@@ -42,7 +42,8 @@ MESA_ASM_SOURCES =
 # Library/program dependencies
 EXTRA_LIB_PATH=-L/usr/X11R6/lib
 
-DRI_LIB_DEPS  = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl
+MESA_MODULES  = $(TOP)/src/mesa/libmesa.a
+DRI_LIB_DEPS  = $(MESA_MODULES) $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl
 GL_LIB_DEPS   = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lm -lpthread -ldl
 
 
index 22de0662ee1b235708801efbe746422ff4ddf340..e6999539a17d8db80e44a716ebca20bfa5ba5bc4 100644 (file)
@@ -41,4 +41,4 @@ else
 endif
 
 LD = g++
-GL_LIB_DEPS = $(LLVM_LDFLAGS) $(LLVM_LIBS) $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread -ltalloc -lstdc++ -ludis86
+GL_LIB_DEPS = $(LLVM_LDFLAGS) $(LLVM_LIBS) $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread -lstdc++ -ludis86
index 2f1e94a791239b556b8d6d3736b0908d2cffb4eb..19455eed186bbf3c253e30fbc7686cf63a64a1f2 100644 (file)
@@ -20,6 +20,7 @@ AC_CANONICAL_HOST
 dnl Versions for external dependencies
 LIBDRM_REQUIRED=2.4.23
 LIBDRM_RADEON_REQUIRED=2.4.23
+LIBDRM_INTEL_REQUIRED=2.4.23
 DRI2PROTO_REQUIRED=2.1
 GLPROTO_REQUIRED=1.4.11
 LIBDRM_XORG_REQUIRED=2.4.23
@@ -150,9 +151,13 @@ if test "x$GCC" = xyes; then
     # Enable -fvisibility=hidden if using a gcc that supports it
     save_CFLAGS="$CFLAGS"
     AC_MSG_CHECKING([whether $CC supports -fvisibility=hidden])
-    CFLAGS="$CFLAGS -fvisibility=hidden"
+    VISIBILITY_CFLAGS="-fvisibility=hidden"
+    CFLAGS="$CFLAGS $VISIBILITY_CFLAGS"
     AC_LINK_IFELSE([AC_LANG_PROGRAM()], AC_MSG_RESULT([yes]),
-                  [CFLAGS="$save_CFLAGS" ; AC_MSG_RESULT([no])]);
+                  [VISIBILITY_CFLAGS=""; AC_MSG_RESULT([no])]);
+
+    # Restore CFLAGS; VISIBILITY_CFLAGS are added to it where needed.
+    CFLAGS=$save_CFLAGS
 
     # Work around aliasing bugs - developers should comment this out
     CFLAGS="$CFLAGS -fno-strict-aliasing"
@@ -163,14 +168,21 @@ if test "x$GXX" = xyes; then
     # Enable -fvisibility=hidden if using a gcc that supports it
     save_CXXFLAGS="$CXXFLAGS"
     AC_MSG_CHECKING([whether $CXX supports -fvisibility=hidden])
-    CXXFLAGS="$CXXFLAGS -fvisibility=hidden"
+    VISIBILITY_CXXFLAGS="-fvisibility=hidden"
+    CXXFLAGS="$CXXFLAGS $VISIBILITY_CXXFLAGS"
     AC_LINK_IFELSE([AC_LANG_PROGRAM()], AC_MSG_RESULT([yes]),
-                  [CXXFLAGS="$save_CXXFLAGS" ; AC_MSG_RESULT([no])]);
+                  [VISIBILITY_CXXFLAGS="" ; AC_MSG_RESULT([no])]);
+
+    # Restore CXXFLAGS; VISIBILITY_CXXFLAGS are added to it where needed.
+    CXXFLAGS=$save_CXXFLAGS
 
     # Work around aliasing bugs - developers should comment this out
     CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"
 fi
 
+AC_SUBST([VISIBILITY_CFLAGS])
+AC_SUBST([VISIBILITY_CXXFLAGS])
+
 dnl These should be unnecessary, but let the user set them if they want
 AC_ARG_VAR([OPT_FLAGS], [Additional optimization flags for the compiler.
     Default is to use CFLAGS.])
@@ -317,6 +329,7 @@ GLESv1_CM_LIB_NAME='lib$(GLESv1_CM_LIB).'${LIB_EXTENSION}
 GLESv2_LIB_NAME='lib$(GLESv2_LIB).'${LIB_EXTENSION}
 VG_LIB_NAME='lib$(VG_LIB).'${LIB_EXTENSION}
 GLAPI_LIB_NAME='lib$(GLAPI_LIB).'${LIB_EXTENSION}
+WAYLAND_EGL_LIB_NAME='lib$(WAYLAND_EGL_LIB).'${LIB_EXTENSION}
 
 GL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
 GLU_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLU_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
@@ -329,6 +342,7 @@ GLESv1_CM_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLESv1_CM_LIB)'${LIB_VERSION_SEPARATOR}'
 GLESv2_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLESv2_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
 VG_LIB_GLOB=${LIB_PREFIX_GLOB}'$(VG_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
 GLAPI_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLAPI_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
+WAYLAND_EGL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(WAYLAND_EGL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
 
 AC_SUBST([GL_LIB_NAME])
 AC_SUBST([GLU_LIB_NAME])
@@ -340,6 +354,7 @@ AC_SUBST([GLESv1_CM_LIB_NAME])
 AC_SUBST([GLESv2_LIB_NAME])
 AC_SUBST([VG_LIB_NAME])
 AC_SUBST([GLAPI_LIB_NAME])
+AC_SUBST([WAYLAND_EGL_LIB_NAME])
 
 AC_SUBST([GL_LIB_GLOB])
 AC_SUBST([GLU_LIB_GLOB])
@@ -351,6 +366,7 @@ AC_SUBST([GLESv1_CM_LIB_GLOB])
 AC_SUBST([GLESv2_LIB_GLOB])
 AC_SUBST([VG_LIB_GLOB])
 AC_SUBST([GLAPI_LIB_GLOB])
+AC_SUBST([WAYLAND_EGL_LIB_GLOB])
 
 dnl
 dnl Arch/platform-specific settings
@@ -582,10 +598,6 @@ xno)
     ;;
 esac
 
-PKG_CHECK_MODULES([TALLOC], [talloc])
-AC_SUBST([TALLOC_LIBS])
-AC_SUBST([TALLOC_CFLAGS])
-
 dnl
 dnl Driver specific build directories
 dnl
@@ -602,7 +614,7 @@ GALLIUM_DRIVERS_DIRS="softpipe failover galahad trace rbug noop identity"
 GALLIUM_STATE_TRACKERS_DIRS=""
 
 # build shared-glapi if enabled for OpenGL or if OpenGL ES is enabled
-case "x$enabled_shared_glapi$enable_gles1$enable_gles2" in
+case "x$enable_shared_glapi$enable_gles1$enable_gles2" in
 x*yes*)
     CORE_DIRS="$CORE_DIRS mapi/shared-glapi"
     ;;
@@ -734,8 +746,8 @@ xlib)
         GL_PC_LIB_PRIV="$GL_LIB_DEPS"
         GL_PC_CFLAGS="$X11_INCLUDES"
     fi
-    GL_LIB_DEPS="$GL_LIB_DEPS $SELINUX_LIBS -lm -lpthread $TALLOC_LIBS"
-    GL_PC_LIB_PRIV="$GL_PC_LIB_PRIV $SELINUX_LIBS -lm -lpthread $TALLOC_LIBS"
+    GL_LIB_DEPS="$GL_LIB_DEPS $SELINUX_LIBS -lm -lpthread"
+    GL_PC_LIB_PRIV="$GL_PC_LIB_PRIV $SELINUX_LIBS -lm -lpthread"
 
     # if static, move the external libraries to the programs
     # and empty the libraries for libGL
@@ -818,10 +830,45 @@ AC_SUBST([GLESv2_PC_LIB_PRIV])
 GLAPI_LIB_DEPS="-lpthread"
 AC_SUBST([GLAPI_LIB_DEPS])
 
+
+dnl Setup default DRI CFLAGS
+DRI_CFLAGS='$(CFLAGS)'
+DRI_CXXFLAGS='$(CXXFLAGS)'
+DRI_LIB_DEPS='$(TOP)/src/mesa/libmesa.a'
+MESA_MODULES='$(TOP)/src/mesa/libmesa.a'
+
+AC_ARG_ENABLE([shared-dricore],
+    [AS_HELP_STRING([--enable-shared-dricore],
+        [link DRI modules with shared core DRI routines @<:@default=disabled@:>@])],
+    [enable_dricore="$enableval"],
+    [enable_dricore=no])
+if test "$mesa_driver" = dri ; then
+   if test "$enable_dricore" = yes ; then
+      if test "$GCC$GXX" != yesyes ; then
+        AC_MSG_WARN([Shared dricore requires GCC-compatible rpath handling.  Disabling shared dricore])
+        enable_dricore=no
+      else
+        DRICORE_GLSL_LIBS='$(TOP)/$(LIB_DIR)/libglsl.so'
+        DRICORE_LIBS='$(TOP)/$(LIB_DIR)/libdricore.so'
+        DRICORE_LIB_DEPS='-L$(TOP)/$(LIB_DIR) -Wl,-R$(DRI_DRIVER_INSTALL_DIR) -lglsl'
+        DRI_LIB_DEPS='-L$(TOP)/$(LIB_DIR) -Wl,-R$(DRI_DRIVER_INSTALL_DIR) -ldricore -lglsl'
+        DRI_CFLAGS='$(CFLAGS_NOVISIBILITY) -DUSE_DRICORE'
+        DRI_CXXFLAGS='$(CXXFLAGS_NOVISIBILITY) -DUSE_DRICORE'
+        MESA_MODULES='$(DRICORE_LIBS) $(DRICORE_GLSL_LIBS)'
+      fi
+   fi
+fi
+AC_SUBST([DRICORE_LIBS])
+AC_SUBST([DRICORE_GLSL_LIBS])
+AC_SUBST([DRICORE_LIB_DEPS])
+AC_SUBST([DRI_CXXFLAGS])
+AC_SUBST([DRI_CFLAGS])
+AC_SUBST([MESA_MODULES])
+
 AC_SUBST([HAVE_XF86VIDMODE])
 
 PKG_CHECK_MODULES([LIBDRM_RADEON],
-                 [libdrm_radeon libdrm >= $LIBDRM_RADEON_REQUIRED],
+                 [libdrm_radeon >= $LIBDRM_RADEON_REQUIRED],
                  HAVE_LIBDRM_RADEON=yes,
                  HAVE_LIBDRM_RADEON=no)
 
@@ -843,6 +890,9 @@ AC_ARG_ENABLE([glx-tls],
     [GLX_USE_TLS=no])
 AC_SUBST(GLX_TLS, ${GLX_USE_TLS})
 
+AS_IF([test "x$GLX_USE_TLS" = xyes],
+      [DEFINES="${DEFINES} -DGLX_USE_TLS -DPTHREADS"])
+
 dnl
 dnl More DRI setup
 dnl
@@ -898,11 +948,6 @@ esac
 
 dnl Set DRI_DIRS, DEFINES and LIB_DEPS
 if test "$mesa_driver" = dri -o "$mesa_driver" = no; then
-    # Use TLS in GLX?
-    if test "x$GLX_USE_TLS" = xyes; then
-        DEFINES="$DEFINES -DGLX_USE_TLS -DPTHREADS"
-    fi
-
     # Platform specific settings and drivers to build
     case "$host_os" in
     linux*)
@@ -988,8 +1033,8 @@ if test "$mesa_driver" = dri -o "$mesa_driver" = no; then
             [AC_MSG_ERROR([Expat required for DRI.])])
     fi
 
-    # put all the necessary libs together
-    DRI_LIB_DEPS="$SELINUX_LIBS $LIBDRM_LIBS $EXPAT_LIB -lm -lpthread $DLOPEN_LIBS $TALLOC_LIBS"
+    # put all the necessary libs together, including possibly libdricore
+    DRI_LIB_DEPS="$DRI_LIB_DEPS $SELINUX_LIBS $LIBDRM_LIBS $EXPAT_LIB -lm -lpthread $DLOPEN_LIBS"
 fi
 AC_SUBST([DRI_DIRS])
 AC_SUBST([EXPAT_INCLUDES])
@@ -997,7 +1042,7 @@ AC_SUBST([DRI_LIB_DEPS])
 
 case $DRI_DIRS in
 *i915*|*i965*)
-    PKG_CHECK_MODULES([INTEL], [libdrm_intel >= 2.4.23])
+    PKG_CHECK_MODULES([INTEL], [libdrm_intel >= $LIBDRM_INTEL_REQUIRED])
     ;;
 esac
 
@@ -1065,12 +1110,12 @@ case "$DRIVER_DIRS" in
 *osmesa*)
     # only link libraries with osmesa if shared
     if test "$enable_static" = no; then
-        OSMESA_LIB_DEPS="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS $TALLOC_LIBS"
+        OSMESA_LIB_DEPS="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS"
     else
         OSMESA_LIB_DEPS=""
     fi
     OSMESA_MESA_DEPS=""
-    OSMESA_PC_LIB_PRIV="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS $TALLOC_LIBS"
+    OSMESA_PC_LIB_PRIV="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS"
     ;;
 esac
 AC_SUBST([OSMESA_LIB_DEPS])
@@ -1539,6 +1584,8 @@ AC_ARG_WITH([egl-displays],
     [with_egl_platforms="$withval"])
 
 EGL_PLATFORMS=""
+WAYLAND_EGL_LIB_DEPS=""
+
 case "$with_egl_platforms" in
 yes)
     if test "x$enable_egl" = xyes && test "x$mesa_driver" != xosmesa; then
@@ -1556,16 +1603,31 @@ yes)
     egl_platforms=`IFS=', '; echo $with_egl_platforms`
     for plat in $egl_platforms; do
         test -d "$srcdir/src/gallium/state_trackers/egl/$plat" || \
-            AC_MSG_ERROR([EGL platform '$plat' does't exist])
+            AC_MSG_ERROR([EGL platform '$plat' doesn't exist])
         if test "$plat" = "fbdev"; then
                 GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/fbdev"
         fi
+       if test "$plat" = "wayland"; then
+               PKG_CHECK_MODULES([WAYLAND], [wayland-client],, \
+                                 [AC_MSG_ERROR([cannot find libwayland-client])])
+               WAYLAND_EGL_LIB_DEPS="$WAYLAND_LIBS $LIBDRM_LIBS"
+       fi
     done
     EGL_PLATFORMS="$egl_platforms"
     ;;
 esac
 AC_SUBST([EGL_PLATFORMS])
 
+AC_SUBST([WAYLAND_EGL_LIB_DEPS])
+WAYLAND_EGL_PC_REQ_PRIV="wayland-client libdrm"
+WAYLAND_EGL_PC_LIB_PRIV=
+WAYLAND_EGL_PC_CFLAGS=
+
+AC_SUBST([WAYLAND_EGL_PC_REQ_PRIV])
+AC_SUBST([WAYLAND_EGL_PC_LIB_PRIV])
+AC_SUBST([WAYLAND_EGL_PC_CFLAGS])
+
+
 AC_ARG_WITH([egl-driver-dir],
     [AS_HELP_STRING([--with-egl-driver-dir=DIR],
                     [directory for EGL drivers [[default=${libdir}/egl]]])],
@@ -1705,20 +1767,12 @@ AC_ARG_ENABLE([gallium-radeon],
     [enable_gallium_radeon="$enableval"],
     [enable_gallium_radeon=auto])
 if test "x$enable_gallium_radeon" = xauto; then
-    if test "x$HAVE_LIBDRM_RADEON" = xyes; then
-       GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300"
-       gallium_check_st "radeon/drm" "dri-r300"
-    else
-       AC_MSG_WARN([libdrm_radeon is missing, not building gallium-radeon (r300)])
-    fi
+    GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300"
+    gallium_check_st "radeon/drm" "dri-r300"
 fi
 if test "x$enable_gallium_radeon" = xyes; then
-    if test "x$HAVE_LIBDRM_RADEON" = xyes; then
-       GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300"
-       gallium_check_st "radeon/drm" "dri-r300" "xorg-radeon"
-    else
-       AC_MSG_ERROR([libdrm_radeon is missing, cannot build gallium-radeon (r300)])
-    fi
+    GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300"
+    gallium_check_st "radeon/drm" "dri-r300" "xorg-radeon"
 fi
 
 dnl
@@ -1730,12 +1784,8 @@ AC_ARG_ENABLE([gallium-r600],
     [enable_gallium_r600="$enableval"],
     [enable_gallium_r600=auto])
 if test "x$enable_gallium_r600" = xyes; then
-    if test "x$HAVE_LIBDRM_RADEON" = xyes; then
-       GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r600"
-       gallium_check_st "r600/drm" "dri-r600" "xvmc-r600" "va-r600"
-    else
-       AC_MSG_ERROR([libdrm_radeon is missing, cannot build gallium-r600])
-    fi
+    GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r600"
+    gallium_check_st "r600/drm" "dri-r600" "xvmc-r600"
 fi
 
 dnl
@@ -1860,6 +1910,7 @@ if test "$mesa_driver" != no; then
         fi
         echo "        DRI driver dir:  $DRI_DRIVER_INSTALL_DIR"
         echo "        Use XCB:         $enable_xcb"
+        echo "        Shared dricore:  $enable_dricore"
     fi
 fi
 echo ""
index 93bd56d2c4c147df4059fdb807a83da0a8be1b8a..9ff25a9529743155ce3d02b67e7b9c03e62117fc 100644 (file)
@@ -15,10 +15,13 @@ GL 3.0:
 GLSL changes (GL_EXT_gpu_shader4, etc)                not started
 Conditional rendering (GL_NV_conditional_render)      DONE (swrast & softpipe)
 Map buffer subranges (GL_ARB_map_buffer_range)        DONE
-Float textures, renderbuffers                         some infrastructure done
- (incl. GL_EXT_packed_float, GL_EXT_shared_exponent)
+Clamping controls (GL_ARB_color_buffer_float)         BRANCH ~mareko/mesa floating2
+Float textures, renderbuffers (GL_ARB_texture_float)  BRANCH ~mareko/mesa floating2
+GL_EXT_packed_float                                   not started
+GL_EXT_texture_shared_exponent                        not started
+Float depth buffers (GL_ARB_depth_buffer_float)       not started
 Framebuffer objects (GL_EXT_framebuffer_object)       DONE
-Half-float                                            some infrastructure done
+Half-float                                            DONE
 Multisample blit                                      DONE
 Non-normalized Integer texture/framebuffer formats    ~50% done
 1D/2D Texture arrays                                  core Mesa, swrast done
@@ -30,7 +33,7 @@ Transform feedback (GL_EXT_transform_feedback)        ~50% done
    glBindFragDataLocation, glGetFragDataLocation,
    glBindBufferRange, glBindBufferBase commands
 Vertex array objects (GL_APPLE_vertex_array_object)   DONE
-sRGB framebuffer format (GL_EXT_framebuffer_sRGB)     not started
+sRGB framebuffer format (GL_EXT_framebuffer_sRGB)     core GL done (i965, gallium), GLX todo
 glClearBuffer commands                                DONE
 glGetStringi command                                  DONE
 glTexParameterI, glGetTexParameterI commands          DONE
@@ -48,7 +51,7 @@ Primitive restart (GL_NV_primitive_restart)           DONE (gallium)
 Texture buffer objs (GL_ARB_texture_buffer_object)    not started
 Rectangular textures (GL_ARB_texture_rectangle)       DONE
 Uniform buffer objs (GL_ARB_uniform_buffer_object)    not started
-Signed normalized texture formats                     ~50% done
+Signed normalized textures (GL_EXT_texture_snorm)     ~50% done
 
 
 GL 3.2:
index fd1700a02f14aeeb0540f450702edd5527d3c4f6..c8be8437176ad380a34c7c2f0762ad5f982ca675 100644 (file)
@@ -9,17 +9,38 @@
 <H1>Environment Variables</H1>
 
 <p>
-Mesa supports the following environment variables:
+Normally, no environment variables need to be set.  Most of the environment
+variables used by Mesa/Gallium are for debugging purposes, but they can
+sometimes be useful for debugging end-user issues.
 </p>
+
+
+<H2>LibGL environment variables</H2>
+
+<ul>
+<li>LIBGL_DEBUG - If defined debug information will be printed to stderr.
+   If set to 'verbose' additional information will be printed.
+<li>LIBGL_DRIVERS_PATH - colon-separated list of paths to search for DRI drivers
+<li>LIBGL_ALWAYS_INDIRECT - forces an indirect rendering context/connection.
+<li>LIBGL_ALWAYS_SOFTWARE - if set, always use software rendering
+<li>LIBGL_NO_DRAWARRAYS - if set do not use DrawArrays GLX protocol (for debugging)
+</ul>
+
+
+
+<H2>Core Mesa environment variables</H2>
+
 <ul>
 <li>MESA_NO_ASM - if set, disables all assembly language optimizations
 <li>MESA_NO_MMX - if set, disables Intel MMX optimizations
 <li>MESA_NO_3DNOW - if set, disables AMD 3DNow! optimizations
 <li>MESA_NO_SSE - if set, disables Intel SSE optimizations
-<li>MESA_DEBUG - if set, error messages are printed to stderr.
-If the value of MESA_DEBUG is "FP" floating point arithmetic errors will
-generate exceptions.
-<li>MESA_NO_DITHER - if set, disables dithering, overriding glEnable(GL_DITHER)
+<li>MESA_DEBUG - if set, error messages are printed to stderr.  For example,
+   if the application generates a GL_INVALID_ENUM error, a corresponding error
+   message indicating where the error occured, and possibly why, will be
+   printed to stderr.<br>
+   If the value of MESA_DEBUG is 'FP' floating point arithmetic errors will
+   generate exceptions.
 <li>MESA_TEX_PROG - if set, implement conventional texture env modes with
 fragment programs (intended for developers only)
 <li>MESA_TNL_PROG - if set, implement conventional vertex transformation
@@ -28,11 +49,14 @@ Setting this variable automatically sets the MESA_TEX_PROG variable as well.
 <li>MESA_EXTENSION_OVERRIDE - can be used to enable/disable extensions.
 A value such as "GL_EXT_foo -GL_EXT_bar" will enable the GL_EXT_foo extension
 and disable the GL_EXT_bar extension.
-<li>MESA_GLSL - <a href="shading.html#envvars">shading language options</a>
+<li>MESA_GLSL - <a href="shading.html#envvars">shading language compiler options</a>
 </ul>
 
+
+<H2>Mesa Xlib driver environment variables</H2>
+
 <p>
-The following are only applicable to the Xlib software driver.
+The following are only applicable to the Mesa Xlib software driver.
 See the <A HREF="xlibdriver.html">Xlib software driver page</A> for details.
 </p>
 <ul>
@@ -51,9 +75,8 @@ See the <A HREF="xlibdriver.html">Xlib software driver page</A> for details.
 </ul>
 
 
-<p>
-These environment variables are for the Intel i945/i965 drivers:
-</p>
+<h2>i945/i965 driver environment variables (non-Gallium)</h2>
+
 <ul>
 <li>INTEL_STRICT_CONFORMANCE - if set to 1, enable sw fallbacks to improve
     OpenGL conformance.  If set to 2, always use software rendering.
@@ -62,17 +85,71 @@ These environment variables are for the Intel i945/i965 drivers:
 </ul>
 
 
-<p>
-These environment variables are for the Radeon R300 driver:
-</p>
+<h2>Radeon R300 driver environment variables (non-Gallium)</h2>
+
 <ul>
 <li>R300_NO_TCL - if set, disable hardware-accelerated Transform/Clip/Lighting.
 </ul>
 
+
+<h2>EGL environment variables</h2>
+
 <p>
 Mesa EGL supports different sets of environment variables.  See the
 <a href="egl.html">Mesa EGL</a> page for the details.
 </p>
 
+
+<h2>Gallium environment variables</h2>
+
+<ul>
+<li>GALLIUM_PRINT_OPTIONS - if non-zero, print all the Gallium environment
+    variables which are used, and their current values.
+<li>GALLIUM_NOSSE - if non-zero, do not use SSE runtime code generation for
+    shader execution
+<li>GALLIUM_NOPPC - if non-zero, do not use PPC runtime code generation for
+    shader execution
+<li>GALLIUM_DUMP_CPU - if non-zero, print information about the CPU on start-up
+<li>TGSI_PRINT_SANITY - if set, do extra sanity checking on TGSI shaders and
+    print any errors to stderr.
+<LI>DRAW_FSE - ???
+<LI>DRAW_NO_FSE - ???
+<li>DRAW_USE_LLVM - if set to zero, the draw module will not use LLVM to execute
+    shaders, vertex fetch, etc.
+</ul>
+
+<h3>Softpipe driver environment variables</h3>
+<ul>
+<li>SOFTPIPE_DUMP_FS - if set, the softpipe driver will print fragment shaders
+    to stderr
+<li>SOFTPIPE_DUMP_GS - if set, the softpipe driver will print geometry shaders
+    to stderr
+<li>SOFTPIPE_NO_RAST - if set, rasterization is no-op'd.  For profiling purposes.
+</ul>
+
+
+<h3>LLVMpipe driver environment variables</h3>
+<ul>
+<li>LP_NO_RAST - if set LLVMpipe will no-op rasterization
+<li>LP_DEBUG - a comma-separated list of debug options is acceptec.  See the
+    source code for details.
+<li>LP_PERF - a comma-separated list of options to selectively no-op various
+    parts of the driver.  See the source code for details.
+<li>LP_NUM_THREADS - an integer indicating how many threads to use for rendering.
+    Zero turns of threading completely.  The default value is the number of CPU
+    cores present.
+</ul>
+
+
+<p>
+Other Gallium drivers have their own environment variables.  These may change
+frequently so the source code should be consulted for details.
+</p>
+
+
+<br>
+<br>
+
+
 </BODY>
 </HTML>
index b0350a22f38c6d73abd320e1a27d53ccce416ef0..6c6622ed3f432c62a053a4803915244c35b14a69 100644 (file)
@@ -49,8 +49,10 @@ tbd
 
 
 <h2>Changes</h2>
-
-<p>tbd</p>
+<ul>
+<li>The Windows MSVC project files have been removed.  They haven't been maintained
+in quite a while.  Building with SCons is an alterantive.
+</ul>
 
 
 </body>
index c41d4a9be2b18e73bb6006774e5acc4d2e790782..aba3959742929273b8792b2c98d4fdcea6349cbe 100644 (file)
@@ -167,7 +167,7 @@ Here's an example of using the compiler to compile a vertex shader and
 emit GL_ARB_vertex_program-style instructions:
 </p>
 <pre>
-    src/glsl/glslcompiler --dump-ast myshader.vert
+    src/glsl/glsl_compiler --dump-ast myshader.vert
 </pre>
 
 Options include
index 00dc4e7c9f4665a4f08f5327f6e7a28973f263a3..08a9a50e9ec11bf5565501f41faae01dc867b55e 100644 (file)
@@ -23,6 +23,7 @@ each directory.
     <ul>
     <li><b>docs</b> - EGL documentation
     <li><b>drivers</b> - EGL drivers
+    <li><b>glsl</b> - the GLSL compiler
     <li><b>main</b> - main EGL library implementation.  This is where all
         the EGL API functions are implemented, like eglCreateContext().
     </ul>
index 33a3e5f889135bd83558e516c2e8c0b21e6cb7c7..005b29444048edd32a2a134919ffc8c45f0c8597 100644 (file)
@@ -78,6 +78,12 @@ typedef int   EGLNativeDisplayType;
 typedef void *EGLNativeWindowType;
 typedef void *EGLNativePixmapType;
 
+#elif defined(WL_EGL_PLATFORM)
+
+typedef struct wl_egl_display *EGLNativeDisplayType;
+typedef struct wl_egl_pixmap  *EGLNativePixmapType;
+typedef struct wl_egl_window  *EGLNativeWindowType;
+
 #elif defined(__unix__) || defined(__unix)
 
 #ifdef MESA_EGL_NO_X11_HEADERS
index 39aa68bc8ca1ff79951fa5cacca4a0dd349e661d..2fb729afcdfca68ed37513336f033af79783a14f 100644 (file)
@@ -499,6 +499,7 @@ struct __DRIuseInvalidateExtensionRec {
 #define __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE    45
 #define __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS   46
 #define __DRI_ATTRIB_YINVERTED                 47
+#define __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE  48
 
 /* __DRI_ATTRIB_RENDER_TYPE */
 #define __DRI_ATTRIB_RGBA_BIT                  0x01    
@@ -656,7 +657,7 @@ struct __DRIlegacyExtensionRec {
  * conjunction with the core extension.
  */
 #define __DRI_SWRAST "DRI_SWRast"
-#define __DRI_SWRAST_VERSION 1
+#define __DRI_SWRAST_VERSION 2
 
 struct __DRIswrastExtensionRec {
     __DRIextension base;
@@ -669,6 +670,13 @@ struct __DRIswrastExtensionRec {
     __DRIdrawable *(*createNewDrawable)(__DRIscreen *screen,
                                        const __DRIconfig *config,
                                        void *loaderPrivate);
+
+   /* Since version 2 */
+   __DRIcontext *(*createNewContextForAPI)(__DRIscreen *screen,
+                                           int api,
+                                           const __DRIconfig *config,
+                                           __DRIcontext *shared,
+                                           void *data);
 };
 
 /**
@@ -778,6 +786,14 @@ struct __DRIdri2ExtensionRec {
                                           const __DRIconfig *config,
                                           __DRIcontext *shared,
                                           void *data);
+
+   __DRIbuffer *(*allocateBuffer)(__DRIscreen *screen,
+                                 unsigned int attachment,
+                                 unsigned int format,
+                                 int width,
+                                 int height);
+   void (*releaseBuffer)(__DRIscreen *screen,
+                        __DRIbuffer *buffer);
 };
 
 
index 8af0d93f01abbc67aca0094e556a5749cee7f755..cc046229e2c6dcfc93da4099c3633bf107087330 100644 (file)
@@ -194,5 +194,8 @@ def generate(env):
     env.AppendUnique(SHLINKFLAGS = ['-Wl,--enable-stdcall-fixup'])
     #env.AppendUnique(SHLINKFLAGS = ['-Wl,--kill-at'])
 
+    # Avoid depending on gcc runtime DLLs
+    env.AppendUnique(LINKFLAGS = ['-static-libgcc'])
+
 def exists(env):
     return find(env)
old mode 100644 (file)
new mode 100755 (executable)
index 75e9b9e..9118257
@@ -35,6 +35,7 @@ import os
 import os.path
 import re
 import subprocess
+import platform as _platform
 
 import SCons.Action
 import SCons.Builder
@@ -141,6 +142,10 @@ def pkg_config_modules(env, name, modules):
 def generate(env):
     """Common environment generation code"""
 
+    # Tell tools which machine to compile for
+    env['TARGET_ARCH'] = env['machine']
+    env['MSVS_ARCH'] = env['machine']
+
     # Toolchain
     platform = env['platform']
     if env['toolchain'] == 'default':
@@ -175,6 +180,10 @@ def generate(env):
     env['gcc'] = 'gcc' in os.path.basename(env['CC']).split('-')
     env['msvc'] = env['CC'] == 'cl'
 
+    if env['msvc'] and env['toolchain'] == 'default' and env['machine'] == 'x86_64':
+        # MSVC x64 support is broken in earlier versions of scons
+        env.EnsurePythonVersion(2, 0)
+
     # shortcuts
     machine = env['machine']
     platform = env['platform']
@@ -183,6 +192,25 @@ def generate(env):
     gcc = env['gcc']
     msvc = env['msvc']
 
+    # Determine whether we are cross compiling; in particular, whether we need
+    # to compile code generators with a different compiler as the target code.
+    host_platform = _platform.system().lower()
+    host_machine = os.environ.get('PROCESSOR_ARCHITEW6432', os.environ.get('PROCESSOR_ARCHITECTURE', _platform.machine()))
+    host_machine = {
+        'x86': 'x86',
+        'i386': 'x86',
+        'i486': 'x86',
+        'i586': 'x86',
+        'i686': 'x86',
+        'ppc' : 'ppc',
+        'AMD64': 'x86_64',
+        'x86_64': 'x86_64',
+    }.get(host_machine, 'generic')
+    env['crosscompile'] = platform != host_platform
+    if machine == 'x86_64' and host_machine != 'x86_64':
+        env['crosscompile'] = True
+    env['hostonly'] = False
+
     # Backwards compatability with the debug= profile= options
     if env['build'] == 'debug':
         if not env['debug']:
@@ -349,12 +377,15 @@ def generate(env):
                 '-m32',
                 #'-march=pentium4',
             ]
-            if distutils.version.LooseVersion(ccversion) >= distutils.version.LooseVersion('4.2'):
+            if distutils.version.LooseVersion(ccversion) >= distutils.version.LooseVersion('4.2') \
+               and (platform != 'windows' or env['build'] == 'debug' or True):
                 # NOTE: We need to ensure stack is realigned given that we
                 # produce shared objects, and have no control over the stack
                 # alignment policy of the application. Therefore we need
                 # -mstackrealign ore -mincoming-stack-boundary=2.
                 #
+                # XXX: -O and -mstackrealign causes stack corruption on MinGW
+                #
                 # XXX: We could have SSE without -mstackrealign if we always used
                 # __attribute__((force_align_arg_pointer)), but that's not
                 # always the case.
@@ -402,13 +433,19 @@ def generate(env):
               '/Od', # disable optimizations
               '/Oi', # enable intrinsic functions
               '/Oy-', # disable frame pointer omission
-              '/GL-', # disable whole program optimization
             ]
         else:
             ccflags += [
                 '/O2', # optimize for speed
+            ]
+        if env['build'] == 'release':
+            ccflags += [
                 '/GL', # enable whole program optimization
             ]
+        else:
+            ccflags += [
+                '/GL-', # disable whole program optimization
+            ]
         ccflags += [
             '/fp:fast', # fast floating point 
             '/W3', # warning level
@@ -498,7 +535,7 @@ def generate(env):
         else:
             env['_LIBFLAGS'] = '-Wl,--start-group ' + env['_LIBFLAGS'] + ' -Wl,--end-group'
     if msvc:
-        if env['build'] != 'debug':
+        if env['build'] == 'release':
             # enable Link-time Code Generation
             linkflags += ['/LTCG']
             env.Append(ARFLAGS = ['/LTCG'])
@@ -551,6 +588,10 @@ def generate(env):
     env.Append(LINKFLAGS = linkflags)
     env.Append(SHLINKFLAGS = shlinkflags)
 
+    # We have C++ in several libraries, so always link with the C++ compiler
+    if env['gcc']:
+        env['LINK'] = env['CXX']
+
     # Default libs
     env.Append(LIBS = [])
 
index 1b033acb1b3f50d848de1fc694da9e2cdb903719..3fef9e0900d59b2cd57a719cbd5d69aa0571683c 100644 (file)
@@ -147,8 +147,6 @@ def generate(env):
         except OSError:
             print 'scons: llvm-config version %s failed' % llvm_version
             return
-        else:
-            env['LINK'] = env['CXX']
 
     assert llvm_version is not None
     env['llvm'] = True
index 201812c5ac3f1199c79c50ff34c203724f28278a..f11894f2990a5709797d40ca42d267792318bd9e 100644 (file)
@@ -1,13 +1,21 @@
 Import('*')
 
+
 if env['platform'] == 'windows':
     SConscript('getopt/SConscript')
-    SConscript('talloc/SConscript')
-else:
-    talloc = 'talloc'
-    Export('talloc')
 
 SConscript('glsl/SConscript')
+
+if env['hostonly']:
+    # We are just compiling the things necessary on the host for cross
+    # compilation
+    Return()
+
+
+# When env['gles'] is set, the targets defined in mapi/glapi/SConscript are not
+# used.  libgl-xlib and libgl-gdi adapt themselves to use the targets defined
+# in mapi/glapi-shared/SConscript.  mesa/SConscript also adapts itself to
+# enable OpenGL ES support.
 SConscript('mapi/glapi/SConscript')
 SConscript('mesa/SConscript')
 
@@ -17,5 +25,8 @@ if env['platform'] != 'embedded':
     SConscript('egl/main/SConscript')
     SConscript('glut/glx/SConscript')
 
+    if env['gles']:
+        SConscript('mapi/shared-glapi/SConscript')
+
 SConscript('gallium/SConscript')
 
index 50f227f07dac1ea9865580231c8c051ae0150014..52daf2efa7e2705dd22cba96ec94acfcfc398aec 100644 (file)
@@ -5,6 +5,10 @@ include $(TOP)/configs/current
 
 SUBDIRS = drivers main
 
+ifneq ($(findstring wayland, $(EGL_PLATFORMS)),)
+SUBDIRS += wayland
+endif
+
 
 default: subdirs
 
index 553ee8771f8457a932e989a2438b3a670b3a896f..89e9dd7970a46c3b6d188a3c25d3f28e892a54b8 100644 (file)
@@ -4,7 +4,7 @@ TOP = ../../../..
 include $(TOP)/configs/current
 
 EGL_DRIVER = egl_dri2
-EGL_SOURCES = egl_dri2.c
+EGL_SOURCES = egl_dri2.c platform_x11.c platform_drm.c
 
 EGL_INCLUDES = \
        -I$(TOP)/include \
@@ -20,4 +20,15 @@ EGL_LIBS = $(XCB_DRI2_LIBS) $(LIBUDEV_LIBS) $(DLOPEN_LIBS) $(LIBDRM_LIB)
 EGL_CFLAGS = -D_EGL_MAIN=_eglBuiltInDriverDRI2
 EGL_BUILTIN = true
 
+ifeq ($(SHARED_GLAPI),1)
+EGL_CFLAGS += -DHAVE_SHARED_GLAPI
+endif
+
+ifneq ($(findstring wayland, $(EGL_PLATFORMS)),)
+EGL_SOURCES += platform_wayland.c
+EGL_INCLUDES += -DHAVE_WAYLAND_PLATFORM $(WAYLAND_CFLAGS) \
+               -I$(TOP)/src/egl/wayland
+EGL_LIBS += $(WAYLAND_LIBS)
+endif
+
 include ../Makefile.template
index 6fc1e49e773e08b8ed117d0b19c1401b32ea9a8f..99f87f076c1dba4b9661f4ba87ae903b39351911 100644 (file)
 #include <xf86drm.h>
 #include <GL/gl.h>
 #include <GL/internal/dri_interface.h>
-#include <xcb/xcb.h>
-#include <xcb/dri2.h>
-#include <xcb/xfixes.h>
-#include <X11/Xlib-xcb.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#ifdef HAVE_LIBUDEV
-#include <libudev.h>
-#endif
-
-#include "eglconfig.h"
-#include "eglcontext.h"
-#include "egldisplay.h"
-#include "egldriver.h"
-#include "eglcurrent.h"
-#include "egllog.h"
-#include "eglsurface.h"
-#include "eglimage.h"
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-
-struct dri2_egl_driver
-{
-   _EGLDriver base;
-
-   _EGLProc (*get_proc_address)(const char *procname);
-   void (*glFlush)(void);
-};
-
-struct dri2_egl_display
-{
-   xcb_connection_t         *conn;
-   int                       dri2_major;
-   int                       dri2_minor;
-   __DRIscreen              *dri_screen;
-   const __DRIconfig       **driver_configs;
-   void                     *driver;
-   __DRIcoreExtension       *core;
-   __DRIdri2Extension       *dri2;
-   __DRI2flushExtension     *flush;
-   __DRItexBufferExtension  *tex_buffer;
-   __DRIimageExtension      *image;
-   int                       fd;
-
-   char                     *device_name;
-   char                     *driver_name;
-
-   __DRIdri2LoaderExtension  loader_extension;
-   const __DRIextension     *extensions[3];
-};
-
-struct dri2_egl_context
-{
-   _EGLContext   base;
-   __DRIcontext *dri_context;
-};
-
-struct dri2_egl_surface
-{
-   _EGLSurface          base;
-   __DRIdrawable       *dri_drawable;
-   xcb_drawable_t       drawable;
-   __DRIbuffer          buffers[5];
-   int                  buffer_count;
-   xcb_xfixes_region_t  region;
-   int                  have_fake_front;
-   int                  swap_interval;
-};
-
-struct dri2_egl_config
-{
-   _EGLConfig         base;
-   const __DRIconfig *dri_config;
-};
-
-struct dri2_egl_image
-{
-   _EGLImage   base;
-   __DRIimage *dri_image;
-};
-
-/* standard typecasts */
-_EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl)
-_EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj)
+#include "egl_dri2.h"
 
-static const __DRIuseInvalidateExtension use_invalidate = {
+const __DRIuseInvalidateExtension use_invalidate = {
    { __DRI_USE_INVALIDATE, 1 }
 };
 
@@ -177,15 +96,18 @@ EGLint dri2_to_egl_attribute_map[] = {
    EGL_Y_INVERTED_NOK,         /* __DRI_ATTRIB_YINVERTED */
 };
 
-static struct dri2_egl_config *
+struct dri2_egl_config *
 dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
-               int depth, EGLint surface_type)
+               int depth, EGLint surface_type, const EGLint *attr_list)
 {
    struct dri2_egl_config *conf;
    struct dri2_egl_display *dri2_dpy;
    _EGLConfig base;
    unsigned int attrib, value, double_buffer;
    EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
+   _EGLConfig *matching_config;
+   EGLint num_configs = 0;
+   EGLint config_id;
    int i;
 
    dri2_dpy = disp->DriverData;
@@ -238,15 +160,9 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
       }
    }
 
-   /* In EGL, double buffer or not isn't a config attribute.  Pixmaps
-    * surfaces are always single buffered, pbuffer surfaces are always
-    * back buffers and windows can be either, selected by passing an
-    * attribute at window surface construction time.  To support this
-    * we ignore all double buffer configs and manipulate the buffer we
-    * return in the getBuffer callback to get the behaviour we want. */
-
-   if (double_buffer)
-      return NULL;
+   if (attr_list)
+      for (i = 0; attr_list[i] != EGL_NONE; i += 2)
+         _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]);
 
    if (depth > 0 && depth != base.BufferSize)
       return NULL;
@@ -254,7 +170,8 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
    base.NativeRenderable = EGL_TRUE;
 
    base.SurfaceType = surface_type;
-   if (surface_type & (EGL_PIXMAP_BIT | EGL_PBUFFER_BIT)) {
+   if (surface_type & (EGL_PBUFFER_BIT |
+       (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) {
       base.BindToTextureRGB = bind_to_texture_rgb;
       if (base.AlphaSize > 0)
          base.BindToTextureRGBA = bind_to_texture_rgba;
@@ -268,110 +185,49 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
       return NULL;
    }
 
-   conf = malloc(sizeof *conf);
-   if (conf != NULL) {
-      memcpy(&conf->base, &base, sizeof base);
-      conf->dri_config = dri_config;
-      _eglLinkConfig(&conf->base);
-   }
+   config_id = base.ConfigID;
+   base.ConfigID    = EGL_DONT_CARE;
+   base.SurfaceType = EGL_DONT_CARE;
+   num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1,
+                                 (_EGLArrayForEach) _eglMatchConfig, &base);
 
-   return conf;
-}
+   if (num_configs == 1) {
+      conf = (struct dri2_egl_config *) matching_config;
 
-/**
- * Process list of buffer received from the server
- *
- * Processes the list of buffers received in a reply from the server to either
- * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
- */
-static void
-dri2_process_buffers(struct dri2_egl_surface *dri2_surf,
-                    xcb_dri2_dri2_buffer_t *buffers, unsigned count)
-{
-   struct dri2_egl_display *dri2_dpy =
-      dri2_egl_display(dri2_surf->base.Resource.Display);
-   xcb_rectangle_t rectangle;
-   unsigned i;
-
-   dri2_surf->buffer_count = count;
-   dri2_surf->have_fake_front = 0;
-
-   /* This assumes the DRI2 buffer attachment tokens matches the
-    * __DRIbuffer tokens. */
-   for (i = 0; i < count; i++) {
-      dri2_surf->buffers[i].attachment = buffers[i].attachment;
-      dri2_surf->buffers[i].name = buffers[i].name;
-      dri2_surf->buffers[i].pitch = buffers[i].pitch;
-      dri2_surf->buffers[i].cpp = buffers[i].cpp;
-      dri2_surf->buffers[i].flags = buffers[i].flags;
-
-      /* We only use the DRI drivers single buffer configs.  This
-       * means that if we try to render to a window, DRI2 will give us
-       * the fake front buffer, which we'll use as a back buffer.
-       * Note that EGL doesn't require that several clients rendering
-       * to the same window must see the same aux buffers. */
-      if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
-         dri2_surf->have_fake_front = 1;
+      if (double_buffer && !conf->dri_double_config)
+         conf->dri_double_config = dri_config;
+      else if (!double_buffer && !conf->dri_single_config)
+         conf->dri_single_config = dri_config;
+      else
+         /* a similar config type is already added
+          * => attach it as new config
+          */
+         num_configs = 0;
    }
 
-   if (dri2_surf->region != XCB_NONE)
-      xcb_xfixes_destroy_region(dri2_dpy->conn, dri2_surf->region);
+   if (num_configs == 0) {
+      conf = malloc(sizeof *conf);
+      if (conf == NULL)
+         return NULL;
 
-   rectangle.x = 0;
-   rectangle.y = 0;
-   rectangle.width = dri2_surf->base.Width;
-   rectangle.height = dri2_surf->base.Height;
-   dri2_surf->region = xcb_generate_id(dri2_dpy->conn);
-   xcb_xfixes_create_region(dri2_dpy->conn, dri2_surf->region, 1, &rectangle);
-}
-
-static __DRIbuffer *
-dri2_get_buffers(__DRIdrawable * driDrawable,
-               int *width, int *height,
-               unsigned int *attachments, int count,
-               int *out_count, void *loaderPrivate)
-{
-   struct dri2_egl_surface *dri2_surf = loaderPrivate;
-   struct dri2_egl_display *dri2_dpy =
-      dri2_egl_display(dri2_surf->base.Resource.Display);
-   xcb_dri2_dri2_buffer_t *buffers;
-   xcb_dri2_get_buffers_reply_t *reply;
-   xcb_dri2_get_buffers_cookie_t cookie;
-
-   (void) driDrawable;
-
-   cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
-                                           dri2_surf->drawable,
-                                           count, count, attachments);
-   reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, cookie, NULL);
-   buffers = xcb_dri2_get_buffers_buffers (reply);
-   if (buffers == NULL)
-      return NULL;
-
-   *out_count = reply->count;
-   dri2_surf->base.Width = *width = reply->width;
-   dri2_surf->base.Height = *height = reply->height;
-   dri2_process_buffers(dri2_surf, buffers, *out_count);                      
-
-   free(reply);
-
-   return dri2_surf->buffers;
-}
-
-static void
-dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
-{
-   (void) driDrawable;
+      memcpy(&conf->base, &base, sizeof base);
+      if (double_buffer) {
+         conf->dri_double_config = dri_config;
+         conf->dri_single_config = NULL;
+      } else {
+         conf->dri_single_config = dri_config;
+         conf->dri_double_config = NULL;
+      }
+      conf->base.SurfaceType = 0;
+      conf->base.ConfigID = config_id;
 
-   /* FIXME: Does EGL support front buffer rendering at all? */
+      _eglLinkConfig(&conf->base);
+   }
 
-#if 0
-   struct dri2_egl_surface *dri2_surf = loaderPrivate;
+   conf->base.SurfaceType |= surface_type & (!double_buffer ? EGL_PIXMAP_BIT:
+         (EGL_WINDOW_BIT | EGL_PBUFFER_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT));
 
-   dri2WaitGL(dri2_surf);
-#else
-   (void) loaderPrivate;
-#endif
+   return conf;
 }
 
 static __DRIimage *
@@ -394,49 +250,11 @@ dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
    return dri2_img->dri_image;
 }
 
-static const __DRIimageLookupExtension image_lookup_extension = {
+const __DRIimageLookupExtension image_lookup_extension = {
    { __DRI_IMAGE_LOOKUP, 1 },
    dri2_lookup_egl_image
 };
 
-static __DRIbuffer *
-dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
-                            int *width, int *height,
-                            unsigned int *attachments, int count,
-                            int *out_count, void *loaderPrivate)
-{
-   struct dri2_egl_surface *dri2_surf = loaderPrivate;
-   struct dri2_egl_display *dri2_dpy =
-      dri2_egl_display(dri2_surf->base.Resource.Display);
-   xcb_dri2_dri2_buffer_t *buffers;
-   xcb_dri2_get_buffers_with_format_reply_t *reply;
-   xcb_dri2_get_buffers_with_format_cookie_t cookie;
-   xcb_dri2_attach_format_t *format_attachments;
-
-   (void) driDrawable;
-
-   format_attachments = (xcb_dri2_attach_format_t *) attachments;
-   cookie = xcb_dri2_get_buffers_with_format_unchecked (dri2_dpy->conn,
-                                                       dri2_surf->drawable,
-                                                       count, count,
-                                                       format_attachments);
-
-   reply = xcb_dri2_get_buffers_with_format_reply (dri2_dpy->conn,
-                                                  cookie, NULL);
-   if (reply == NULL)
-      return NULL;
-
-   buffers = xcb_dri2_get_buffers_with_format_buffers (reply);
-   dri2_surf->base.Width = *width = reply->width;
-   dri2_surf->base.Height = *height = reply->height;
-   *out_count = reply->count;
-   dri2_process_buffers(dri2_surf, buffers, *out_count);                      
-
-   free(reply);
-
-   return dri2_surf->buffers;
-}
-
 static const char dri_driver_path[] = DEFAULT_DRIVER_DIR;
 
 struct dri2_extension_match {
@@ -458,6 +276,17 @@ static struct dri2_extension_match dri2_core_extensions[] = {
    { NULL, 0, 0 }
 };
 
+static struct dri2_extension_match swrast_driver_extensions[] = {
+   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
+   { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) },
+   { NULL }
+};
+
+static struct dri2_extension_match swrast_core_extensions[] = {
+   { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
+   { NULL }
+};
+
 static EGLBoolean
 dri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
                     struct dri2_extension_match *matches,
@@ -491,180 +320,7 @@ dri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
    return ret;
 }
 
-static char *
-dri2_strndup(const char *s, int length)
-{
-   char *d;
-
-   d = malloc(length + 1);
-   if (d == NULL)
-      return NULL;
-
-   memcpy(d, s, length);
-   d[length] = '\0';
-
-   return d;
-}
-
-static EGLBoolean
-dri2_connect(struct dri2_egl_display *dri2_dpy)
-{
-   xcb_xfixes_query_version_reply_t *xfixes_query;
-   xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
-   xcb_dri2_query_version_reply_t *dri2_query;
-   xcb_dri2_query_version_cookie_t dri2_query_cookie;
-   xcb_dri2_connect_reply_t *connect;
-   xcb_dri2_connect_cookie_t connect_cookie;
-   xcb_generic_error_t *error;
-   xcb_screen_iterator_t s;
-
-   xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id);
-   xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id);
-
-   xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn,
-                                                 XCB_XFIXES_MAJOR_VERSION,
-                                                 XCB_XFIXES_MINOR_VERSION);
-   
-   dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->conn,
-                                              XCB_DRI2_MAJOR_VERSION,
-                                              XCB_DRI2_MINOR_VERSION);
-
-   s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
-   connect_cookie = xcb_dri2_connect_unchecked (dri2_dpy->conn,
-                                               s.data->root,
-                                               XCB_DRI2_DRIVER_TYPE_DRI);
-   
-   xfixes_query =
-      xcb_xfixes_query_version_reply (dri2_dpy->conn,
-                                     xfixes_query_cookie, &error);
-   if (xfixes_query == NULL ||
-       error != NULL || xfixes_query->major_version < 2) {
-      _eglLog(_EGL_FATAL, "DRI2: failed to query xfixes version");
-      free(error);
-      return EGL_FALSE;
-   }
-   free(xfixes_query);
-
-   dri2_query =
-      xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error);
-   if (dri2_query == NULL || error != NULL) {
-      _eglLog(_EGL_FATAL, "DRI2: failed to query version");
-      free(error);
-      return EGL_FALSE;
-   }
-   dri2_dpy->dri2_major = dri2_query->major_version;
-   dri2_dpy->dri2_minor = dri2_query->minor_version;
-   free(dri2_query);
-
-   connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL);
-   if (connect == NULL ||
-       connect->driver_name_length + connect->device_name_length == 0) {
-      _eglLog(_EGL_FATAL, "DRI2: failed to authenticate");
-      return EGL_FALSE;
-   }
-
-   dri2_dpy->device_name =
-      dri2_strndup(xcb_dri2_connect_device_name (connect),
-                  xcb_dri2_connect_device_name_length (connect));
-                  
-   dri2_dpy->driver_name =
-      dri2_strndup(xcb_dri2_connect_driver_name (connect),
-                  xcb_dri2_connect_driver_name_length (connect));
-
-   if (dri2_dpy->device_name == NULL || dri2_dpy->driver_name == NULL) {
-      free(dri2_dpy->device_name);
-      free(dri2_dpy->driver_name);
-      free(connect);
-      return EGL_FALSE;
-   }
-   free(connect);
-
-   return EGL_TRUE;
-}
-
-static EGLBoolean
-dri2_authenticate(struct dri2_egl_display *dri2_dpy)
-{
-   xcb_dri2_authenticate_reply_t *authenticate;
-   xcb_dri2_authenticate_cookie_t authenticate_cookie;
-   xcb_screen_iterator_t s;
-   drm_magic_t magic;
-
-   if (drmGetMagic(dri2_dpy->fd, &magic)) {
-      _eglLog(_EGL_FATAL, "DRI2: failed to get drm magic");
-      return EGL_FALSE;
-   }
-
-   s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
-   authenticate_cookie =
-      xcb_dri2_authenticate_unchecked(dri2_dpy->conn, s.data->root, magic);
-   authenticate =
-      xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL);
-   if (authenticate == NULL || !authenticate->authenticated) {
-      _eglLog(_EGL_FATAL, "DRI2: failed to authenticate");
-      free(authenticate);
-      return EGL_FALSE;
-   }
-
-   free(authenticate);
-
-   return EGL_TRUE;
-}
-
-static EGLBoolean
-dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
-                            _EGLDisplay *disp)
-{
-   xcb_screen_iterator_t s;
-   xcb_depth_iterator_t d;
-   xcb_visualtype_t *visuals;
-   int i, j, id;
-   struct dri2_egl_config *conf;
-   EGLint surface_type;
-
-   s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
-   d = xcb_screen_allowed_depths_iterator(s.data);
-   id = 1;
-
-   surface_type =
-      EGL_WINDOW_BIT |
-      EGL_PIXMAP_BIT |
-      EGL_PBUFFER_BIT |
-      EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
-
-   while (d.rem > 0) {
-      EGLBoolean class_added[6] = { 0, };
-
-      visuals = xcb_depth_visuals(d.data);
-      for (i = 0; i < xcb_depth_visuals_length(d.data); i++) {
-        if (class_added[visuals[i]._class])
-           continue;
-
-        class_added[visuals[i]._class] = EGL_TRUE;
-        for (j = 0; dri2_dpy->driver_configs[j]; j++) {
-           conf = dri2_add_config(disp, dri2_dpy->driver_configs[j],
-                                  id++, d.data->depth, surface_type);
-           if (conf == NULL)
-              continue;
-           _eglSetConfigKey(&conf->base,
-                            EGL_NATIVE_VISUAL_ID, visuals[i].visual_id);
-           _eglSetConfigKey(&conf->base,
-                            EGL_NATIVE_VISUAL_TYPE, visuals[i]._class);
-        }
-      }
-
-      xcb_depth_next(&d);      
-   }
-
-   if (!_eglGetArraySize(disp->Configs)) {
-      _eglLog(_EGL_WARNING, "DRI2: failed to create any config");
-      return EGL_FALSE;
-   }
-
-   return EGL_TRUE;
-}
-
-static EGLBoolean
+EGLBoolean
 dri2_load_driver(_EGLDisplay *disp)
 {
    struct dri2_egl_display *dri2_dpy = disp->DriverData;
@@ -718,15 +374,22 @@ dri2_load_driver(_EGLDisplay *disp)
       return EGL_FALSE;
    }
 
-   if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) {
-      dlclose(dri2_dpy->driver);
-      return EGL_FALSE;
-   }
+   if (strcmp(dri2_dpy->driver_name, "swrast") == 0) {
+      if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) {
+         dlclose(dri2_dpy->driver);
+         return EGL_FALSE;
+      }
+   } else {
+      if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) {
+         dlclose(dri2_dpy->driver);
+         return EGL_FALSE;
+      }
+   } 
 
    return EGL_TRUE;
 }
 
-static EGLBoolean
+EGLBoolean
 dri2_create_screen(_EGLDisplay *disp)
 {
    const __DRIextension **extensions;
@@ -734,9 +397,17 @@ dri2_create_screen(_EGLDisplay *disp)
    unsigned int api_mask;
 
    dri2_dpy = disp->DriverData;
-   dri2_dpy->dri_screen =
-      dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions,
-                                     &dri2_dpy->driver_configs, disp);
+
+   if (dri2_dpy->dri2) {
+      dri2_dpy->dri_screen =
+         dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions,
+                                        &dri2_dpy->driver_configs, disp);
+   } else {
+      assert(dri2_dpy->swrast);
+      dri2_dpy->dri_screen =
+         dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions,
+                                           &dri2_dpy->driver_configs, disp);
+   }
 
    if (dri2_dpy->dri_screen == NULL) {
       _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
@@ -744,13 +415,28 @@ dri2_create_screen(_EGLDisplay *disp)
    }
 
    extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
-   if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
-      goto cleanup_dri_screen;
+   
+   if (dri2_dpy->dri2) {
+      if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
+         goto cleanup_dri_screen;
+   } else {
+      assert(dri2_dpy->swrast);
+      if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions))
+         goto cleanup_dri_screen;
+   }
 
-   if (dri2_dpy->dri2->base.version >= 2)
-      api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
-   else
-      api_mask = 1 << __DRI_API_OPENGL;
+   if (dri2_dpy->dri2) {
+      if (dri2_dpy->dri2->base.version >= 2)
+         api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
+      else
+         api_mask = 1 << __DRI_API_OPENGL;
+   } else {
+      assert(dri2_dpy->swrast);
+      if (dri2_dpy->swrast->base.version >= 2)
+         api_mask = 1 << __DRI_API_OPENGL | 1 << __DRI_API_GLES | 1 << __DRI_API_GLES2;
+      else
+         api_mask = 1 << __DRI_API_OPENGL;
+   }
 
    disp->ClientAPIs = 0;
    if (api_mask & (1 <<__DRI_API_OPENGL))
@@ -760,710 +446,29 @@ dri2_create_screen(_EGLDisplay *disp)
    if (api_mask & (1 << __DRI_API_GLES2))
       disp->ClientAPIs |= EGL_OPENGL_ES2_BIT;
 
-   if (dri2_dpy->dri2->base.version >= 2) {
-      disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
-      disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
-      disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
-   }
-
-   return EGL_TRUE;
-
- cleanup_dri_screen:
-   dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
-
-   return EGL_FALSE;
-}
-
-static EGLBoolean
-dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp)
-{
-   struct dri2_egl_display *dri2_dpy;
-
-   (void) drv;
-
-   dri2_dpy = malloc(sizeof *dri2_dpy);
-   if (!dri2_dpy)
-      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
-
-   disp->DriverData = (void *) dri2_dpy;
-   if (disp->PlatformDisplay == NULL) {
-      dri2_dpy->conn = xcb_connect(0, 0);
-   } else {
-      dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay);
-   }
-
-   if (xcb_connection_has_error(dri2_dpy->conn)) {
-      _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed");
-      goto cleanup_dpy;
-   }
-
-   if (dri2_dpy->conn) {
-      if (!dri2_connect(dri2_dpy))
-        goto cleanup_conn;
-   }
-
-   if (!dri2_load_driver(disp))
-      goto cleanup_conn;
-
-   dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR);
-   if (dri2_dpy->fd == -1) {
-      _eglLog(_EGL_WARNING,
-             "DRI2: could not open %s (%s)", dri2_dpy->device_name,
-              strerror(errno));
-      goto cleanup_driver;
-   }
-
-   if (dri2_dpy->conn) {
-      if (!dri2_authenticate(dri2_dpy))
-        goto cleanup_fd;
-   }
-
-   if (dri2_dpy->dri2_minor >= 1) {
-      dri2_dpy->loader_extension.base.name = __DRI_DRI2_LOADER;
-      dri2_dpy->loader_extension.base.version = 3;
-      dri2_dpy->loader_extension.getBuffers = dri2_get_buffers;
-      dri2_dpy->loader_extension.flushFrontBuffer = dri2_flush_front_buffer;
-      dri2_dpy->loader_extension.getBuffersWithFormat =
-        dri2_get_buffers_with_format;
+   if (dri2_dpy->dri2) {
+      if (dri2_dpy->dri2->base.version >= 2) {
+         disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
+         disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
+         disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
+      }
    } else {
-      dri2_dpy->loader_extension.base.name = __DRI_DRI2_LOADER;
-      dri2_dpy->loader_extension.base.version = 2;
-      dri2_dpy->loader_extension.getBuffers = dri2_get_buffers;
-      dri2_dpy->loader_extension.flushFrontBuffer = dri2_flush_front_buffer;
-      dri2_dpy->loader_extension.getBuffersWithFormat = NULL;
-   }
-      
-   dri2_dpy->extensions[0] = &dri2_dpy->loader_extension.base;
-   dri2_dpy->extensions[1] = &image_lookup_extension.base;
-   dri2_dpy->extensions[2] = NULL;
-
-   if (!dri2_create_screen(disp))
-      goto cleanup_fd;
-
-   if (dri2_dpy->conn) {
-      if (!dri2_add_configs_for_visuals(dri2_dpy, disp))
-        goto cleanup_configs;
+      assert(dri2_dpy->swrast);
+      if (dri2_dpy->swrast->base.version >= 2) {
+         disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
+         disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
+         disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
+      }
    }
 
-   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;
-   disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
-   disp->Extensions.NOK_swap_region = EGL_TRUE;
-   disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
-
-   /* we're supporting EGL 1.4 */
-   disp->VersionMajor = 1;
-   disp->VersionMinor = 4;
-
    return EGL_TRUE;
 
- cleanup_configs:
-   _eglCleanupDisplay(disp);
+ cleanup_dri_screen:
    dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
- cleanup_fd:
-   close(dri2_dpy->fd);
- cleanup_driver:
-   dlclose(dri2_dpy->driver);
- cleanup_conn:
-   if (disp->PlatformDisplay == NULL)
-      xcb_disconnect(dri2_dpy->conn);
- cleanup_dpy:
-   free(dri2_dpy);
-
-   return EGL_FALSE;
-}
-
-#ifdef HAVE_LIBUDEV
-
-struct dri2_driver_map {
-   int vendor_id;
-   const char *driver;
-   const int *chip_ids;
-   int num_chips_ids;
-};
-
-const int i915_chip_ids[] = {
-   0x3577, /* PCI_CHIP_I830_M */
-   0x2562, /* PCI_CHIP_845_G */
-   0x3582, /* PCI_CHIP_I855_GM */
-   0x2572, /* PCI_CHIP_I865_G */
-   0x2582, /* PCI_CHIP_I915_G */
-   0x258a, /* PCI_CHIP_E7221_G */
-   0x2592, /* PCI_CHIP_I915_GM */
-   0x2772, /* PCI_CHIP_I945_G */
-   0x27a2, /* PCI_CHIP_I945_GM */
-   0x27ae, /* PCI_CHIP_I945_GME */
-   0x29b2, /* PCI_CHIP_Q35_G */
-   0x29c2, /* PCI_CHIP_G33_G */
-   0x29d2, /* PCI_CHIP_Q33_G */
-   0xa001, /* PCI_CHIP_IGD_G */
-   0xa011, /* Pineview */
-};
-
-const int i965_chip_ids[] = {
-   0x0042, /* PCI_CHIP_ILD_G */
-   0x0046, /* PCI_CHIP_ILM_G */
-   0x0102, /* PCI_CHIP_SANDYBRIDGE_GT1 */
-   0x0106, /* PCI_CHIP_SANDYBRIDGE_M_GT1 */
-   0x010a, /* PCI_CHIP_SANDYBRIDGE_S */
-   0x0112, /* PCI_CHIP_SANDYBRIDGE_GT2 */
-   0x0116, /* PCI_CHIP_SANDYBRIDGE_M_GT2 */
-   0x0122, /* PCI_CHIP_SANDYBRIDGE_GT2_PLUS */
-   0x0126, /* PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS */
-   0x29a2, /* PCI_CHIP_I965_G */
-   0x2992, /* PCI_CHIP_I965_Q */
-   0x2982, /* PCI_CHIP_I965_G_1 */
-   0x2972, /* PCI_CHIP_I946_GZ */
-   0x2a02, /* PCI_CHIP_I965_GM */
-   0x2a12, /* PCI_CHIP_I965_GME */
-   0x2a42, /* PCI_CHIP_GM45_GM */
-   0x2e02, /* PCI_CHIP_IGD_E_G */
-   0x2e12, /* PCI_CHIP_Q45_G */
-   0x2e22, /* PCI_CHIP_G45_G */
-   0x2e32, /* PCI_CHIP_G41_G */
-   0x2e42, /* PCI_CHIP_B43_G */
-   0x2e92, /* PCI_CHIP_B43_G1 */
-};
-
-const int r100_chip_ids[] = {
-   0x4C57, /* PCI_CHIP_RADEON_LW */
-   0x4C58, /* PCI_CHIP_RADEON_LX */
-   0x4C59, /* PCI_CHIP_RADEON_LY */
-   0x4C5A, /* PCI_CHIP_RADEON_LZ */
-   0x5144, /* PCI_CHIP_RADEON_QD */
-   0x5145, /* PCI_CHIP_RADEON_QE */
-   0x5146, /* PCI_CHIP_RADEON_QF */
-   0x5147, /* PCI_CHIP_RADEON_QG */
-   0x5159, /* PCI_CHIP_RADEON_QY */
-   0x515A, /* PCI_CHIP_RADEON_QZ */
-   0x5157, /* PCI_CHIP_RV200_QW */
-   0x5158, /* PCI_CHIP_RV200_QX */
-   0x515E, /* PCI_CHIP_RN50_515E */
-   0x5969, /* PCI_CHIP_RN50_5969 */
-   0x4136, /* PCI_CHIP_RS100_4136 */
-   0x4336, /* PCI_CHIP_RS100_4336 */
-   0x4137, /* PCI_CHIP_RS200_4137 */
-   0x4337, /* PCI_CHIP_RS200_4337 */
-   0x4237, /* PCI_CHIP_RS250_4237 */
-   0x4437, /* PCI_CHIP_RS250_4437 */
-};
-
-const int r200_chip_ids[] = {
-   0x5148, /* PCI_CHIP_R200_QH */
-   0x514C, /* PCI_CHIP_R200_QL */
-   0x514D, /* PCI_CHIP_R200_QM */
-   0x4242, /* PCI_CHIP_R200_BB */
-   0x4243, /* PCI_CHIP_R200_BC */
-   0x4966, /* PCI_CHIP_RV250_If */
-   0x4967, /* PCI_CHIP_RV250_Ig */
-   0x4C64, /* PCI_CHIP_RV250_Ld */
-   0x4C66, /* PCI_CHIP_RV250_Lf */
-   0x4C67, /* PCI_CHIP_RV250_Lg */
-   0x5960, /* PCI_CHIP_RV280_5960 */
-   0x5961, /* PCI_CHIP_RV280_5961 */
-   0x5962, /* PCI_CHIP_RV280_5962 */
-   0x5964, /* PCI_CHIP_RV280_5964 */
-   0x5965, /* PCI_CHIP_RV280_5965 */
-   0x5C61, /* PCI_CHIP_RV280_5C61 */
-   0x5C63, /* PCI_CHIP_RV280_5C63 */
-   0x5834, /* PCI_CHIP_RS300_5834 */
-   0x5835, /* PCI_CHIP_RS300_5835 */
-   0x7834, /* PCI_CHIP_RS350_7834 */
-   0x7835, /* PCI_CHIP_RS350_7835 */
-};
-
-const int r300_chip_ids[] = {
-   0x4144, /* PCI_CHIP_R300_AD */
-   0x4145, /* PCI_CHIP_R300_AE */
-   0x4146, /* PCI_CHIP_R300_AF */
-   0x4147, /* PCI_CHIP_R300_AG */
-   0x4E44, /* PCI_CHIP_R300_ND */
-   0x4E45, /* PCI_CHIP_R300_NE */
-   0x4E46, /* PCI_CHIP_R300_NF */
-   0x4E47, /* PCI_CHIP_R300_NG */
-   0x4E48, /* PCI_CHIP_R350_NH */
-   0x4E49, /* PCI_CHIP_R350_NI */
-   0x4E4B, /* PCI_CHIP_R350_NK */
-   0x4148, /* PCI_CHIP_R350_AH */
-   0x4149, /* PCI_CHIP_R350_AI */
-   0x414A, /* PCI_CHIP_R350_AJ */
-   0x414B, /* PCI_CHIP_R350_AK */
-   0x4E4A, /* PCI_CHIP_R360_NJ */
-   0x4150, /* PCI_CHIP_RV350_AP */
-   0x4151, /* PCI_CHIP_RV350_AQ */
-   0x4152, /* PCI_CHIP_RV350_AR */
-   0x4153, /* PCI_CHIP_RV350_AS */
-   0x4154, /* PCI_CHIP_RV350_AT */
-   0x4155, /* PCI_CHIP_RV350_AU */
-   0x4156, /* PCI_CHIP_RV350_AV */
-   0x4E50, /* PCI_CHIP_RV350_NP */
-   0x4E51, /* PCI_CHIP_RV350_NQ */
-   0x4E52, /* PCI_CHIP_RV350_NR */
-   0x4E53, /* PCI_CHIP_RV350_NS */
-   0x4E54, /* PCI_CHIP_RV350_NT */
-   0x4E56, /* PCI_CHIP_RV350_NV */
-   0x5460, /* PCI_CHIP_RV370_5460 */
-   0x5462, /* PCI_CHIP_RV370_5462 */
-   0x5464, /* PCI_CHIP_RV370_5464 */
-   0x5B60, /* PCI_CHIP_RV370_5B60 */
-   0x5B62, /* PCI_CHIP_RV370_5B62 */
-   0x5B63, /* PCI_CHIP_RV370_5B63 */
-   0x5B64, /* PCI_CHIP_RV370_5B64 */
-   0x5B65, /* PCI_CHIP_RV370_5B65 */
-   0x3150, /* PCI_CHIP_RV380_3150 */
-   0x3152, /* PCI_CHIP_RV380_3152 */
-   0x3154, /* PCI_CHIP_RV380_3154 */
-   0x3155, /* PCI_CHIP_RV380_3155 */
-   0x3E50, /* PCI_CHIP_RV380_3E50 */
-   0x3E54, /* PCI_CHIP_RV380_3E54 */
-   0x4A48, /* PCI_CHIP_R420_JH */
-   0x4A49, /* PCI_CHIP_R420_JI */
-   0x4A4A, /* PCI_CHIP_R420_JJ */
-   0x4A4B, /* PCI_CHIP_R420_JK */
-   0x4A4C, /* PCI_CHIP_R420_JL */
-   0x4A4D, /* PCI_CHIP_R420_JM */
-   0x4A4E, /* PCI_CHIP_R420_JN */
-   0x4A4F, /* PCI_CHIP_R420_JO */
-   0x4A50, /* PCI_CHIP_R420_JP */
-   0x4A54, /* PCI_CHIP_R420_JT */
-   0x5548, /* PCI_CHIP_R423_UH */
-   0x5549, /* PCI_CHIP_R423_UI */
-   0x554A, /* PCI_CHIP_R423_UJ */
-   0x554B, /* PCI_CHIP_R423_UK */
-   0x5550, /* PCI_CHIP_R423_5550 */
-   0x5551, /* PCI_CHIP_R423_UQ */
-   0x5552, /* PCI_CHIP_R423_UR */
-   0x5554, /* PCI_CHIP_R423_UT */
-   0x5D57, /* PCI_CHIP_R423_5D57 */
-   0x554C, /* PCI_CHIP_R430_554C */
-   0x554D, /* PCI_CHIP_R430_554D */
-   0x554E, /* PCI_CHIP_R430_554E */
-   0x554F, /* PCI_CHIP_R430_554F */
-   0x5D48, /* PCI_CHIP_R430_5D48 */
-   0x5D49, /* PCI_CHIP_R430_5D49 */
-   0x5D4A, /* PCI_CHIP_R430_5D4A */
-   0x5D4C, /* PCI_CHIP_R480_5D4C */
-   0x5D4D, /* PCI_CHIP_R480_5D4D */
-   0x5D4E, /* PCI_CHIP_R480_5D4E */
-   0x5D4F, /* PCI_CHIP_R480_5D4F */
-   0x5D50, /* PCI_CHIP_R480_5D50 */
-   0x5D52, /* PCI_CHIP_R480_5D52 */
-   0x4B49, /* PCI_CHIP_R481_4B49 */
-   0x4B4A, /* PCI_CHIP_R481_4B4A */
-   0x4B4B, /* PCI_CHIP_R481_4B4B */
-   0x4B4C, /* PCI_CHIP_R481_4B4C */
-   0x564A, /* PCI_CHIP_RV410_564A */
-   0x564B, /* PCI_CHIP_RV410_564B */
-   0x564F, /* PCI_CHIP_RV410_564F */
-   0x5652, /* PCI_CHIP_RV410_5652 */
-   0x5653, /* PCI_CHIP_RV410_5653 */
-   0x5657, /* PCI_CHIP_RV410_5657 */
-   0x5E48, /* PCI_CHIP_RV410_5E48 */
-   0x5E4A, /* PCI_CHIP_RV410_5E4A */
-   0x5E4B, /* PCI_CHIP_RV410_5E4B */
-   0x5E4C, /* PCI_CHIP_RV410_5E4C */
-   0x5E4D, /* PCI_CHIP_RV410_5E4D */
-   0x5E4F, /* PCI_CHIP_RV410_5E4F */
-   0x5A41, /* PCI_CHIP_RS400_5A41 */
-   0x5A42, /* PCI_CHIP_RS400_5A42 */
-   0x5A61, /* PCI_CHIP_RC410_5A61 */
-   0x5A62, /* PCI_CHIP_RC410_5A62 */
-   0x5954, /* PCI_CHIP_RS480_5954 */
-   0x5955, /* PCI_CHIP_RS480_5955 */
-   0x5974, /* PCI_CHIP_RS482_5974 */
-   0x5975, /* PCI_CHIP_RS482_5975 */
-   0x7100, /* PCI_CHIP_R520_7100 */
-   0x7101, /* PCI_CHIP_R520_7101 */
-   0x7102, /* PCI_CHIP_R520_7102 */
-   0x7103, /* PCI_CHIP_R520_7103 */
-   0x7104, /* PCI_CHIP_R520_7104 */
-   0x7105, /* PCI_CHIP_R520_7105 */
-   0x7106, /* PCI_CHIP_R520_7106 */
-   0x7108, /* PCI_CHIP_R520_7108 */
-   0x7109, /* PCI_CHIP_R520_7109 */
-   0x710A, /* PCI_CHIP_R520_710A */
-   0x710B, /* PCI_CHIP_R520_710B */
-   0x710C, /* PCI_CHIP_R520_710C */
-   0x710E, /* PCI_CHIP_R520_710E */
-   0x710F, /* PCI_CHIP_R520_710F */
-   0x7140, /* PCI_CHIP_RV515_7140 */
-   0x7141, /* PCI_CHIP_RV515_7141 */
-   0x7142, /* PCI_CHIP_RV515_7142 */
-   0x7143, /* PCI_CHIP_RV515_7143 */
-   0x7144, /* PCI_CHIP_RV515_7144 */
-   0x7145, /* PCI_CHIP_RV515_7145 */
-   0x7146, /* PCI_CHIP_RV515_7146 */
-   0x7147, /* PCI_CHIP_RV515_7147 */
-   0x7149, /* PCI_CHIP_RV515_7149 */
-   0x714A, /* PCI_CHIP_RV515_714A */
-   0x714B, /* PCI_CHIP_RV515_714B */
-   0x714C, /* PCI_CHIP_RV515_714C */
-   0x714D, /* PCI_CHIP_RV515_714D */
-   0x714E, /* PCI_CHIP_RV515_714E */
-   0x714F, /* PCI_CHIP_RV515_714F */
-   0x7151, /* PCI_CHIP_RV515_7151 */
-   0x7152, /* PCI_CHIP_RV515_7152 */
-   0x7153, /* PCI_CHIP_RV515_7153 */
-   0x715E, /* PCI_CHIP_RV515_715E */
-   0x715F, /* PCI_CHIP_RV515_715F */
-   0x7180, /* PCI_CHIP_RV515_7180 */
-   0x7181, /* PCI_CHIP_RV515_7181 */
-   0x7183, /* PCI_CHIP_RV515_7183 */
-   0x7186, /* PCI_CHIP_RV515_7186 */
-   0x7187, /* PCI_CHIP_RV515_7187 */
-   0x7188, /* PCI_CHIP_RV515_7188 */
-   0x718A, /* PCI_CHIP_RV515_718A */
-   0x718B, /* PCI_CHIP_RV515_718B */
-   0x718C, /* PCI_CHIP_RV515_718C */
-   0x718D, /* PCI_CHIP_RV515_718D */
-   0x718F, /* PCI_CHIP_RV515_718F */
-   0x7193, /* PCI_CHIP_RV515_7193 */
-   0x7196, /* PCI_CHIP_RV515_7196 */
-   0x719B, /* PCI_CHIP_RV515_719B */
-   0x719F, /* PCI_CHIP_RV515_719F */
-   0x7200, /* PCI_CHIP_RV515_7200 */
-   0x7210, /* PCI_CHIP_RV515_7210 */
-   0x7211, /* PCI_CHIP_RV515_7211 */
-   0x71C0, /* PCI_CHIP_RV530_71C0 */
-   0x71C1, /* PCI_CHIP_RV530_71C1 */
-   0x71C2, /* PCI_CHIP_RV530_71C2 */
-   0x71C3, /* PCI_CHIP_RV530_71C3 */
-   0x71C4, /* PCI_CHIP_RV530_71C4 */
-   0x71C5, /* PCI_CHIP_RV530_71C5 */
-   0x71C6, /* PCI_CHIP_RV530_71C6 */
-   0x71C7, /* PCI_CHIP_RV530_71C7 */
-   0x71CD, /* PCI_CHIP_RV530_71CD */
-   0x71CE, /* PCI_CHIP_RV530_71CE */
-   0x71D2, /* PCI_CHIP_RV530_71D2 */
-   0x71D4, /* PCI_CHIP_RV530_71D4 */
-   0x71D5, /* PCI_CHIP_RV530_71D5 */
-   0x71D6, /* PCI_CHIP_RV530_71D6 */
-   0x71DA, /* PCI_CHIP_RV530_71DA */
-   0x71DE, /* PCI_CHIP_RV530_71DE */
-   0x7281, /* PCI_CHIP_RV560_7281 */
-   0x7283, /* PCI_CHIP_RV560_7283 */
-   0x7287, /* PCI_CHIP_RV560_7287 */
-   0x7290, /* PCI_CHIP_RV560_7290 */
-   0x7291, /* PCI_CHIP_RV560_7291 */
-   0x7293, /* PCI_CHIP_RV560_7293 */
-   0x7297, /* PCI_CHIP_RV560_7297 */
-   0x7280, /* PCI_CHIP_RV570_7280 */
-   0x7288, /* PCI_CHIP_RV570_7288 */
-   0x7289, /* PCI_CHIP_RV570_7289 */
-   0x728B, /* PCI_CHIP_RV570_728B */
-   0x728C, /* PCI_CHIP_RV570_728C */
-   0x7240, /* PCI_CHIP_R580_7240 */
-   0x7243, /* PCI_CHIP_R580_7243 */
-   0x7244, /* PCI_CHIP_R580_7244 */
-   0x7245, /* PCI_CHIP_R580_7245 */
-   0x7246, /* PCI_CHIP_R580_7246 */
-   0x7247, /* PCI_CHIP_R580_7247 */
-   0x7248, /* PCI_CHIP_R580_7248 */
-   0x7249, /* PCI_CHIP_R580_7249 */
-   0x724A, /* PCI_CHIP_R580_724A */
-   0x724B, /* PCI_CHIP_R580_724B */
-   0x724C, /* PCI_CHIP_R580_724C */
-   0x724D, /* PCI_CHIP_R580_724D */
-   0x724E, /* PCI_CHIP_R580_724E */
-   0x724F, /* PCI_CHIP_R580_724F */
-   0x7284, /* PCI_CHIP_R580_7284 */
-   0x793F, /* PCI_CHIP_RS600_793F */
-   0x7941, /* PCI_CHIP_RS600_7941 */
-   0x7942, /* PCI_CHIP_RS600_7942 */
-   0x791E, /* PCI_CHIP_RS690_791E */
-   0x791F, /* PCI_CHIP_RS690_791F */
-   0x796C, /* PCI_CHIP_RS740_796C */
-   0x796D, /* PCI_CHIP_RS740_796D */
-   0x796E, /* PCI_CHIP_RS740_796E */
-   0x796F, /* PCI_CHIP_RS740_796F */
-};
-
-const int r600_chip_ids[] = {
-   0x9400, /* PCI_CHIP_R600_9400 */
-   0x9401, /* PCI_CHIP_R600_9401 */
-   0x9402, /* PCI_CHIP_R600_9402 */
-   0x9403, /* PCI_CHIP_R600_9403 */
-   0x9405, /* PCI_CHIP_R600_9405 */
-   0x940A, /* PCI_CHIP_R600_940A */
-   0x940B, /* PCI_CHIP_R600_940B */
-   0x940F, /* PCI_CHIP_R600_940F */
-   0x94C0, /* PCI_CHIP_RV610_94C0 */
-   0x94C1, /* PCI_CHIP_RV610_94C1 */
-   0x94C3, /* PCI_CHIP_RV610_94C3 */
-   0x94C4, /* PCI_CHIP_RV610_94C4 */
-   0x94C5, /* PCI_CHIP_RV610_94C5 */
-   0x94C6, /* PCI_CHIP_RV610_94C6 */
-   0x94C7, /* PCI_CHIP_RV610_94C7 */
-   0x94C8, /* PCI_CHIP_RV610_94C8 */
-   0x94C9, /* PCI_CHIP_RV610_94C9 */
-   0x94CB, /* PCI_CHIP_RV610_94CB */
-   0x94CC, /* PCI_CHIP_RV610_94CC */
-   0x94CD, /* PCI_CHIP_RV610_94CD */
-   0x9580, /* PCI_CHIP_RV630_9580 */
-   0x9581, /* PCI_CHIP_RV630_9581 */
-   0x9583, /* PCI_CHIP_RV630_9583 */
-   0x9586, /* PCI_CHIP_RV630_9586 */
-   0x9587, /* PCI_CHIP_RV630_9587 */
-   0x9588, /* PCI_CHIP_RV630_9588 */
-   0x9589, /* PCI_CHIP_RV630_9589 */
-   0x958A, /* PCI_CHIP_RV630_958A */
-   0x958B, /* PCI_CHIP_RV630_958B */
-   0x958C, /* PCI_CHIP_RV630_958C */
-   0x958D, /* PCI_CHIP_RV630_958D */
-   0x958E, /* PCI_CHIP_RV630_958E */
-   0x958F, /* PCI_CHIP_RV630_958F */
-   0x9500, /* PCI_CHIP_RV670_9500 */
-   0x9501, /* PCI_CHIP_RV670_9501 */
-   0x9504, /* PCI_CHIP_RV670_9504 */
-   0x9505, /* PCI_CHIP_RV670_9505 */
-   0x9506, /* PCI_CHIP_RV670_9506 */
-   0x9507, /* PCI_CHIP_RV670_9507 */
-   0x9508, /* PCI_CHIP_RV670_9508 */
-   0x9509, /* PCI_CHIP_RV670_9509 */
-   0x950F, /* PCI_CHIP_RV670_950F */
-   0x9511, /* PCI_CHIP_RV670_9511 */
-   0x9515, /* PCI_CHIP_RV670_9515 */
-   0x9517, /* PCI_CHIP_RV670_9517 */
-   0x9519, /* PCI_CHIP_RV670_9519 */
-   0x95C0, /* PCI_CHIP_RV620_95C0 */
-   0x95C2, /* PCI_CHIP_RV620_95C2 */
-   0x95C4, /* PCI_CHIP_RV620_95C4 */
-   0x95C5, /* PCI_CHIP_RV620_95C5 */
-   0x95C6, /* PCI_CHIP_RV620_95C6 */
-   0x95C7, /* PCI_CHIP_RV620_95C7 */
-   0x95C9, /* PCI_CHIP_RV620_95C9 */
-   0x95CC, /* PCI_CHIP_RV620_95CC */
-   0x95CD, /* PCI_CHIP_RV620_95CD */
-   0x95CE, /* PCI_CHIP_RV620_95CE */
-   0x95CF, /* PCI_CHIP_RV620_95CF */
-   0x9590, /* PCI_CHIP_RV635_9590 */
-   0x9591, /* PCI_CHIP_RV635_9591 */
-   0x9593, /* PCI_CHIP_RV635_9593 */
-   0x9595, /* PCI_CHIP_RV635_9595 */
-   0x9596, /* PCI_CHIP_RV635_9596 */
-   0x9597, /* PCI_CHIP_RV635_9597 */
-   0x9598, /* PCI_CHIP_RV635_9598 */
-   0x9599, /* PCI_CHIP_RV635_9599 */
-   0x959B, /* PCI_CHIP_RV635_959B */
-   0x9610, /* PCI_CHIP_RS780_9610 */
-   0x9611, /* PCI_CHIP_RS780_9611 */
-   0x9612, /* PCI_CHIP_RS780_9612 */
-   0x9613, /* PCI_CHIP_RS780_9613 */
-   0x9614, /* PCI_CHIP_RS780_9614 */
-   0x9615, /* PCI_CHIP_RS780_9615 */
-   0x9616, /* PCI_CHIP_RS780_9616 */
-   0x9710, /* PCI_CHIP_RS880_9710 */
-   0x9711, /* PCI_CHIP_RS880_9711 */
-   0x9712, /* PCI_CHIP_RS880_9712 */
-   0x9713, /* PCI_CHIP_RS880_9713 */
-   0x9714, /* PCI_CHIP_RS880_9714 */
-   0x9715, /* PCI_CHIP_RS880_9715 */
-   0x9440, /* PCI_CHIP_RV770_9440 */
-   0x9441, /* PCI_CHIP_RV770_9441 */
-   0x9442, /* PCI_CHIP_RV770_9442 */
-   0x9443, /* PCI_CHIP_RV770_9443 */
-   0x9444, /* PCI_CHIP_RV770_9444 */
-   0x9446, /* PCI_CHIP_RV770_9446 */
-   0x944A, /* PCI_CHIP_RV770_944A */
-   0x944B, /* PCI_CHIP_RV770_944B */
-   0x944C, /* PCI_CHIP_RV770_944C */
-   0x944E, /* PCI_CHIP_RV770_944E */
-   0x9450, /* PCI_CHIP_RV770_9450 */
-   0x9452, /* PCI_CHIP_RV770_9452 */
-   0x9456, /* PCI_CHIP_RV770_9456 */
-   0x945A, /* PCI_CHIP_RV770_945A */
-   0x945B, /* PCI_CHIP_RV770_945B */
-   0x945E, /* PCI_CHIP_RV770_945E */
-   0x9460, /* PCI_CHIP_RV790_9460 */
-   0x9462, /* PCI_CHIP_RV790_9462 */
-   0x946A, /* PCI_CHIP_RV770_946A */
-   0x946B, /* PCI_CHIP_RV770_946B */
-   0x947A, /* PCI_CHIP_RV770_947A */
-   0x947B, /* PCI_CHIP_RV770_947B */
-   0x9480, /* PCI_CHIP_RV730_9480 */
-   0x9487, /* PCI_CHIP_RV730_9487 */
-   0x9488, /* PCI_CHIP_RV730_9488 */
-   0x9489, /* PCI_CHIP_RV730_9489 */
-   0x948A, /* PCI_CHIP_RV730_948A */
-   0x948F, /* PCI_CHIP_RV730_948F */
-   0x9490, /* PCI_CHIP_RV730_9490 */
-   0x9491, /* PCI_CHIP_RV730_9491 */
-   0x9495, /* PCI_CHIP_RV730_9495 */
-   0x9498, /* PCI_CHIP_RV730_9498 */
-   0x949C, /* PCI_CHIP_RV730_949C */
-   0x949E, /* PCI_CHIP_RV730_949E */
-   0x949F, /* PCI_CHIP_RV730_949F */
-   0x9540, /* PCI_CHIP_RV710_9540 */
-   0x9541, /* PCI_CHIP_RV710_9541 */
-   0x9542, /* PCI_CHIP_RV710_9542 */
-   0x954E, /* PCI_CHIP_RV710_954E */
-   0x954F, /* PCI_CHIP_RV710_954F */
-   0x9552, /* PCI_CHIP_RV710_9552 */
-   0x9553, /* PCI_CHIP_RV710_9553 */
-   0x9555, /* PCI_CHIP_RV710_9555 */
-   0x9557, /* PCI_CHIP_RV710_9557 */
-   0x955F, /* PCI_CHIP_RV710_955F */
-   0x94A0, /* PCI_CHIP_RV740_94A0 */
-   0x94A1, /* PCI_CHIP_RV740_94A1 */
-   0x94A3, /* PCI_CHIP_RV740_94A3 */
-   0x94B1, /* PCI_CHIP_RV740_94B1 */
-   0x94B3, /* PCI_CHIP_RV740_94B3 */
-   0x94B4, /* PCI_CHIP_RV740_94B4 */
-   0x94B5, /* PCI_CHIP_RV740_94B5 */
-   0x94B9, /* PCI_CHIP_RV740_94B9 */
-   0x68E0, /* PCI_CHIP_CEDAR_68E0 */
-   0x68E1, /* PCI_CHIP_CEDAR_68E1 */
-   0x68E4, /* PCI_CHIP_CEDAR_68E4 */
-   0x68E5, /* PCI_CHIP_CEDAR_68E5 */
-   0x68E8, /* PCI_CHIP_CEDAR_68E8 */
-   0x68E9, /* PCI_CHIP_CEDAR_68E9 */
-   0x68F1, /* PCI_CHIP_CEDAR_68F1 */
-   0x68F8, /* PCI_CHIP_CEDAR_68F8 */
-   0x68F9, /* PCI_CHIP_CEDAR_68F9 */
-   0x68FE, /* PCI_CHIP_CEDAR_68FE */
-   0x68C0, /* PCI_CHIP_REDWOOD_68C0 */
-   0x68C1, /* PCI_CHIP_REDWOOD_68C1 */
-   0x68C8, /* PCI_CHIP_REDWOOD_68C8 */
-   0x68C9, /* PCI_CHIP_REDWOOD_68C9 */
-   0x68D8, /* PCI_CHIP_REDWOOD_68D8 */
-   0x68D9, /* PCI_CHIP_REDWOOD_68D9 */
-   0x68DA, /* PCI_CHIP_REDWOOD_68DA */
-   0x68DE, /* PCI_CHIP_REDWOOD_68DE */
-   0x68A0, /* PCI_CHIP_JUNIPER_68A0 */
-   0x68A1, /* PCI_CHIP_JUNIPER_68A1 */
-   0x68A8, /* PCI_CHIP_JUNIPER_68A8 */
-   0x68A9, /* PCI_CHIP_JUNIPER_68A9 */
-   0x68B0, /* PCI_CHIP_JUNIPER_68B0 */
-   0x68B8, /* PCI_CHIP_JUNIPER_68B8 */
-   0x68B9, /* PCI_CHIP_JUNIPER_68B9 */
-   0x68BE, /* PCI_CHIP_JUNIPER_68BE */
-   0x6880, /* PCI_CHIP_CYPRESS_6880 */
-   0x6888, /* PCI_CHIP_CYPRESS_6888 */
-   0x6889, /* PCI_CHIP_CYPRESS_6889 */
-   0x688A, /* PCI_CHIP_CYPRESS_688A */
-   0x6898, /* PCI_CHIP_CYPRESS_6898 */
-   0x6899, /* PCI_CHIP_CYPRESS_6899 */
-   0x689E, /* PCI_CHIP_CYPRESS_689E */
-   0x689C, /* PCI_CHIP_HEMLOCK_689C */
-   0x689D, /* PCI_CHIP_HEMLOCK_689D */
-};
-
-const struct dri2_driver_map driver_map[] = {
-   { 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids) },
-   { 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids) },
-   { 0x1002, "radeon", r100_chip_ids, ARRAY_SIZE(r100_chip_ids) },
-   { 0x1002, "r200", r200_chip_ids, ARRAY_SIZE(r200_chip_ids) },
-   { 0x1002, "r300", r300_chip_ids, ARRAY_SIZE(r300_chip_ids) },
-   { 0x1002, "r600", r600_chip_ids, ARRAY_SIZE(r600_chip_ids) },
-};
-
-static char *
-dri2_get_driver_for_fd(int fd)
-{
-   struct udev *udev;
-   struct udev_device *device, *parent;
-   struct stat buf;
-   const char *pci_id;
-   char *driver = NULL;
-   int vendor_id, chip_id, i, j;
-
-   udev = udev_new();
-   if (fstat(fd, &buf) < 0) {
-      _eglLog(_EGL_WARNING, "EGL-DRI2: failed to stat fd %d", fd);
-      goto out;
-   }
-
-   device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev);
-   if (device == NULL) {
-      _eglLog(_EGL_WARNING,
-             "EGL-DRI2: could not create udev device for fd %d", fd);
-      goto out;
-   }
-
-   parent = udev_device_get_parent(device);
-   if (parent == NULL) {
-      _eglLog(_EGL_WARNING, "DRI2: could not get parent device");
-      goto out;
-   }
-
-   pci_id = udev_device_get_property_value(parent, "PCI_ID");
-   if (pci_id == NULL || sscanf(pci_id, "%x:%x", &vendor_id, &chip_id) != 2) {
-      _eglLog(_EGL_WARNING, "EGL-DRI2: malformed or no PCI ID");
-      goto out;
-   }
-
-   for (i = 0; i < ARRAY_SIZE(driver_map); i++) {
-      if (vendor_id != driver_map[i].vendor_id)
-        continue;
-      for (j = 0; j < driver_map[i].num_chips_ids; j++)
-        if (driver_map[i].chip_ids[j] == chip_id) {
-           driver = strdup(driver_map[i].driver);
-           _eglLog(_EGL_DEBUG, "pci id for %d: %04x:%04x, driver %s",
-                   fd, vendor_id, chip_id, driver);
-           goto out;
-        }
-   }
-
- out:
-   udev_device_unref(device);
-   udev_unref(udev);
-
-   return driver;
-}
-
-static EGLBoolean
-dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
-{
-   struct dri2_egl_display *dri2_dpy;
-   int i;
-
-   dri2_dpy = malloc(sizeof *dri2_dpy);
-   if (!dri2_dpy)
-      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
-
-   disp->DriverData = (void *) dri2_dpy;
-   dri2_dpy->fd = (int) disp->PlatformDisplay;
-
-   dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd);
-   if (dri2_dpy->driver_name == NULL)
-      return _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name");
-
-   if (!dri2_load_driver(disp))
-      goto cleanup_driver_name;
-
-   dri2_dpy->extensions[0] = &image_lookup_extension.base;
-   dri2_dpy->extensions[1] = &use_invalidate.base;
-   dri2_dpy->extensions[2] = NULL;
-
-   if (!dri2_create_screen(disp))
-      goto cleanup_driver;
-
-   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;
-
-   /* we're supporting EGL 1.4 */
-   disp->VersionMajor = 1;
-   disp->VersionMinor = 4;
-
-   return EGL_TRUE;
-
- cleanup_driver:
-   dlclose(dri2_dpy->driver);
- cleanup_driver_name:
-   free(dri2_dpy->driver_name);
 
    return EGL_FALSE;
 }
 
-#endif
-
 /**
  * Called via eglInitialize(), GLX_drv->API.Initialize().
  */
@@ -1485,6 +490,12 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp)
       if (disp->Options.TestOnly)
          return EGL_TRUE;
       return dri2_initialize_drm(drv, disp);
+#ifdef HAVE_WAYLAND_PLATFORM
+   case _EGL_PLATFORM_WAYLAND:
+      if (disp->Options.TestOnly)
+         return EGL_TRUE;
+      return dri2_initialize_wayland(drv, disp);
+#endif
 #endif
 
    default:
@@ -1504,7 +515,8 @@ dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
    _eglCleanupDisplay(disp);
 
    dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
-   close(dri2_dpy->fd);
+   if (dri2_dpy->fd)
+      close(dri2_dpy->fd);
    dlclose(dri2_dpy->driver);
    if (disp->PlatformDisplay == NULL)
       xcb_disconnect(dri2_dpy->conn);
@@ -1562,28 +574,61 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
       return NULL;
    }
 
-   if (conf != NULL)
-      dri_config = dri2_config->dri_config;
+   if (conf != NULL) {
+      /* The config chosen here isn't necessarily
+       * used for surfaces later.
+       * A pixmap surface will use the single config.
+       * This opportunity depends on disabling the
+       * doubleBufferMode check in
+       * src/mesa/main/context.c:check_compatible()
+       */
+      if (dri2_config->dri_double_config)
+         dri_config = dri2_config->dri_double_config;
+      else
+         dri_config = dri2_config->dri_single_config;
+   }
    else
       dri_config = NULL;
 
-   if (dri2_dpy->dri2->base.version >= 2) {
-      dri2_ctx->dri_context =
-        dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
-                                               api,
-                                               dri_config,
-                                               dri2_ctx_shared ? 
-                                               dri2_ctx_shared->dri_context : NULL,
-                                               dri2_ctx);
-   } else if (api == __DRI_API_OPENGL) {
-      dri2_ctx->dri_context =
-        dri2_dpy->dri2->createNewContext(dri2_dpy->dri_screen,
-                                         dri2_config->dri_config,
-                                         dri2_ctx_shared ? 
-                                         dri2_ctx_shared->dri_context : NULL,
-                                         dri2_ctx);
+   if (dri2_dpy->dri2) {
+      if (dri2_dpy->dri2->base.version >= 2) {
+        dri2_ctx->dri_context =
+           dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
+                                                  api,
+                                                  dri_config,
+                                                  dri2_ctx_shared ? 
+                                                  dri2_ctx_shared->dri_context : NULL,
+                                                  dri2_ctx);
+      } else if (api == __DRI_API_OPENGL) {
+        dri2_ctx->dri_context =
+           dri2_dpy->dri2->createNewContext(dri2_dpy->dri_screen,
+                                            dri_config,
+                                            dri2_ctx_shared ? 
+                                            dri2_ctx_shared->dri_context : NULL,
+                                            dri2_ctx);
+      } else {
+        /* fail */
+      }
    } else {
-      /* fail */
+      assert(dri2_dpy->swrast);
+      if (dri2_dpy->swrast->base.version >= 2) {
+        dri2_ctx->dri_context =
+           dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
+                                                    api,
+                                                    dri_config,
+                                                    dri2_ctx_shared ? 
+                                                    dri2_ctx_shared->dri_context : NULL,
+                                                    dri2_ctx);
+      } else if (api == __DRI_API_OPENGL) {
+        dri2_ctx->dri_context =
+           dri2_dpy->core->createNewContext(dri2_dpy->dri_screen,
+                                            dri_config,
+                                            dri2_ctx_shared ?
+                                            dri2_ctx_shared->dri_context : NULL,
+                                            dri2_ctx);
+      } else {
+        /* fail */
+      }
    }
 
    if (!dri2_ctx->dri_context)
@@ -1596,29 +641,6 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
    return NULL;
 }
 
-static EGLBoolean
-dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
-{
-   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
-   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
-
-   (void) drv;
-
-   if (!_eglPutSurface(surf))
-      return EGL_TRUE;
-
-   (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
-   
-   xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable);
-
-   if (surf->Type == EGL_PBUFFER_BIT)
-      xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable);
-
-   free(surf);
-
-   return EGL_TRUE;
-}
-
 /**
  * Called via eglMakeCurrent(), drv->API.MakeCurrent().
  */
@@ -1648,19 +670,20 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
    rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL;
    cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
 
+   if (old_ctx) {
+      __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
+      dri2_dpy->core->unbindContext(old_cctx);
+   }
+
    if ((cctx == NULL && ddraw == NULL && rdraw == NULL) ||
        dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
-      dri2_destroy_surface(drv, disp, old_dsurf);
-      dri2_destroy_surface(drv, disp, old_rsurf);
-      if (old_ctx) {
-         /* unbind the old context only when there is no new context bound */
-         if (!ctx) {
-            __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
-            dri2_dpy->core->unbindContext(old_cctx);
-         }
-         /* no destroy? */
+      if (old_dsurf)
+         drv->API.DestroySurface(drv, disp, old_dsurf);
+      if (old_rsurf)
+         drv->API.DestroySurface(drv, disp, old_rsurf);
+      /* no destroy? */
+      if (old_ctx)
          _eglPutContext(old_ctx);
-      }
 
       return EGL_TRUE;
    } else {
@@ -1682,190 +705,6 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
    }
 }
 
-/**
- * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
- */
-static _EGLSurface *
-dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
-                   _EGLConfig *conf, EGLNativeWindowType window,
-                   const EGLint *attrib_list)
-{
-   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
-   struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
-   struct dri2_egl_surface *dri2_surf;
-   xcb_get_geometry_cookie_t cookie;
-   xcb_get_geometry_reply_t *reply;
-   xcb_screen_iterator_t s;
-   xcb_generic_error_t *error;
-
-   (void) drv;
-
-   dri2_surf = malloc(sizeof *dri2_surf);
-   if (!dri2_surf) {
-      _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
-      return NULL;
-   }
-   
-   if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
-      goto cleanup_surf;
-
-   dri2_surf->region = XCB_NONE;
-   if (type == EGL_PBUFFER_BIT) {
-      dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn);
-      s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
-      xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize,
-                       dri2_surf->drawable, s.data->root,
-                       dri2_surf->base.Width, dri2_surf->base.Height);
-   } else {
-      dri2_surf->drawable = window;
-   }
-
-   dri2_surf->dri_drawable = 
-      (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
-                                           dri2_conf->dri_config, dri2_surf);
-   if (dri2_surf->dri_drawable == NULL) {
-      _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
-      goto cleanup_pixmap;
-   }
-
-   xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable);
-
-   if (type != EGL_PBUFFER_BIT) {
-      cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
-      reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
-      if (reply == NULL || error != NULL) {
-        _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
-        free(error);
-        goto cleanup_dri_drawable;
-      }
-
-      dri2_surf->base.Width = reply->width;
-      dri2_surf->base.Height = reply->height;
-      free(reply);
-   }
-
-   return &dri2_surf->base;
-
- cleanup_dri_drawable:
-   dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
- cleanup_pixmap:
-   if (type == EGL_PBUFFER_BIT)
-      xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable);
- cleanup_surf:
-   free(dri2_surf);
-
-   return NULL;
-}
-
-/**
- * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
- */
-static _EGLSurface *
-dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
-                          _EGLConfig *conf, EGLNativeWindowType window,
-                          const EGLint *attrib_list)
-{
-   return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
-                             window, attrib_list);
-}
-
-static _EGLSurface *
-dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
-                          _EGLConfig *conf, EGLNativePixmapType pixmap,
-                          const EGLint *attrib_list)
-{
-   return dri2_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
-                             pixmap, attrib_list);
-}
-
-static _EGLSurface *
-dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
-                           _EGLConfig *conf, const EGLint *attrib_list)
-{
-   return dri2_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
-                             XCB_WINDOW_NONE, attrib_list);
-}
-
-static EGLBoolean
-dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp,
-                _EGLSurface *draw, xcb_xfixes_region_t region)
-{
-   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
-   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
-   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
-   _EGLContext *ctx;
-   xcb_dri2_copy_region_cookie_t cookie;
-
-   if (dri2_drv->glFlush) {
-      ctx = _eglGetCurrentContext();
-      if (ctx && ctx->DrawSurface == &dri2_surf->base)
-         dri2_drv->glFlush();
-   }
-
-   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
-
-#if 0
-   /* FIXME: Add support for dri swapbuffers, that'll give us swap
-    * interval and page flipping (at least for fullscreen windows) as
-    * well as the page flip event.  Unless surface->SwapBehavior is
-    * EGL_BUFFER_PRESERVED. */
-#if __DRI2_FLUSH_VERSION >= 2
-   if (pdraw->psc->f)
-      (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable);
-#endif
-#endif
-
-   if (!dri2_surf->have_fake_front)
-      return EGL_TRUE;
-
-   cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->conn,
-                                          dri2_surf->drawable,
-                                          region,
-                                          XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
-                                          XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT);
-   free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL));
-
-   return EGL_TRUE;
-}
-
-static EGLBoolean
-dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
-{
-   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
-
-   return dri2_copy_region(drv, disp, draw, dri2_surf->region);
-}
-
-static EGLBoolean
-dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
-                        EGLint numRects, const EGLint *rects)
-{
-   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
-   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
-   EGLBoolean ret;
-   xcb_xfixes_region_t region;
-   xcb_rectangle_t rectangles[16];
-   int i;
-
-   if (numRects > (int)ARRAY_SIZE(rectangles))
-      return dri2_copy_region(drv, disp, draw, dri2_surf->region);
-
-   /* FIXME: Invert y here? */
-   for (i = 0; i < numRects; i++) {
-      rectangles[i].x = rects[i * 4];
-      rectangles[i].y = rects[i * 4 + 1];
-      rectangles[i].width = rects[i * 4 + 2];
-      rectangles[i].height = rects[i * 4 + 3];
-   }
-
-   region = xcb_generate_id(dri2_dpy->conn);
-   xcb_xfixes_create_region(dri2_dpy->conn, region, numRects, rectangles);
-   ret = dri2_copy_region(drv, disp, draw, region);
-   xcb_xfixes_destroy_region(dri2_dpy->conn, region);
-
-   return ret;
-}
-
 /*
  * Called from eglGetProcAddress() via drv->API.GetProcAddress().
  */
@@ -1906,33 +745,6 @@ dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine)
    return EGL_TRUE;
 }
 
-static EGLBoolean
-dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
-                 EGLNativePixmapType target)
-{
-   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
-   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
-   xcb_gcontext_t gc;
-
-   (void) drv;
-
-   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
-
-   gc = xcb_generate_id(dri2_dpy->conn);
-   xcb_create_gc(dri2_dpy->conn, gc, target, 0, NULL);
-   xcb_copy_area(dri2_dpy->conn,
-                 dri2_surf->drawable,
-                 target,
-                 gc,
-                 0, 0,
-                 0, 0,
-                 dri2_surf->base.Width,
-                 dri2_surf->base.Height);
-   xcb_free_gc(dri2_dpy->conn, gc);
-
-   return EGL_TRUE;
-}
-
 static EGLBoolean
 dri2_bind_tex_image(_EGLDriver *drv,
                    _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
@@ -2008,94 +820,6 @@ dri2_release_tex_image(_EGLDriver *drv,
    return EGL_TRUE;
 }
 
-static _EGLImage *
-dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
-                            EGLClientBuffer buffer, const EGLint *attr_list)
-{
-   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
-   struct dri2_egl_image *dri2_img;
-   unsigned int attachments[1];
-   xcb_drawable_t drawable;
-   xcb_dri2_get_buffers_cookie_t buffers_cookie;
-   xcb_dri2_get_buffers_reply_t *buffers_reply;
-   xcb_dri2_dri2_buffer_t *buffers;
-   xcb_get_geometry_cookie_t geometry_cookie;
-   xcb_get_geometry_reply_t *geometry_reply;
-   xcb_generic_error_t *error;
-   int stride, format;
-
-   (void) ctx;
-
-   drawable = (xcb_drawable_t) buffer;
-   xcb_dri2_create_drawable (dri2_dpy->conn, drawable);
-   attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT;
-   buffers_cookie =
-      xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
-                                     drawable, 1, 1, attachments);
-   geometry_cookie = xcb_get_geometry (dri2_dpy->conn, drawable);
-   buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn,
-                                              buffers_cookie, NULL);
-   buffers = xcb_dri2_get_buffers_buffers (buffers_reply);
-   if (buffers == NULL) {
-      return NULL;
-   }
-
-   geometry_reply = xcb_get_geometry_reply (dri2_dpy->conn,
-                                           geometry_cookie, &error);
-   if (geometry_reply == NULL || error != NULL) {
-      _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
-      free(error);
-      free(buffers_reply);
-   }
-
-   switch (geometry_reply->depth) {
-   case 16:
-      format = __DRI_IMAGE_FORMAT_RGB565;
-      break;
-   case 24:
-      format = __DRI_IMAGE_FORMAT_XRGB8888;
-      break;
-   case 32:
-      format = __DRI_IMAGE_FORMAT_ARGB8888;
-      break;
-   default:
-      _eglError(EGL_BAD_PARAMETER,
-               "dri2_create_image_khr: unsupported pixmap depth");
-      free(buffers_reply);
-      free(geometry_reply);
-      return NULL;
-   }
-
-   dri2_img = malloc(sizeof *dri2_img);
-   if (!dri2_img) {
-      free(buffers_reply);
-      free(geometry_reply);
-      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
-      return EGL_NO_IMAGE_KHR;
-   }
-
-   if (!_eglInitImage(&dri2_img->base, disp)) {
-      free(buffers_reply);
-      free(geometry_reply);
-      return EGL_NO_IMAGE_KHR;
-   }
-
-   stride = buffers[0].pitch / buffers[0].cpp;
-   dri2_img->dri_image =
-      dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
-                                          buffers_reply->width,
-                                          buffers_reply->height,
-                                          format,
-                                          buffers[0].name,
-                                          stride,
-                                          dri2_img);
-
-   free(buffers_reply);
-   free(geometry_reply);
-
-   return &dri2_img->base;
-}
-
 static _EGLImage *
 dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
                                   EGLClientBuffer buffer,
@@ -2191,7 +915,7 @@ dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
    return &dri2_img->base;
 }
 
-static _EGLImage *
+_EGLImage *
 dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
                      _EGLContext *ctx, EGLenum target,
                      EGLClientBuffer buffer, const EGLint *attr_list)
@@ -2199,8 +923,6 @@ dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
    (void) drv;
 
    switch (target) {
-   case EGL_NATIVE_PIXMAP_KHR:
-      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:
@@ -2337,6 +1059,9 @@ static void
 dri2_unload(_EGLDriver *drv)
 {
    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
+
+   if (dri2_drv->handle)
+      dlclose(dri2_drv->handle);
    free(dri2_drv);
 }
 
@@ -2344,23 +1069,30 @@ static EGLBoolean
 dri2_load(_EGLDriver *drv)
 {
    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
+#ifdef HAVE_SHARED_GLAPI
+   const char *libname = "libglapi.so.0";
+#else
+   /*
+    * Both libGL.so and libglapi.so are glapi providers.  There is no way to
+    * tell which one to load.
+    */
+   const char *libname = NULL;
+#endif
    void *handle;
 
-   handle = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
+   /* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */
+   handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
    if (handle) {
       dri2_drv->get_proc_address = (_EGLProc (*)(const char *))
          dlsym(handle, "_glapi_get_proc_address");
-      /* no need to keep a reference */
-      dlclose(handle);
+      if (!dri2_drv->get_proc_address || !libname) {
+         /* no need to keep a reference */
+         dlclose(handle);
+         handle = NULL;
+      }
    }
 
-   /*
-    * If glapi is not available, loading DRI drivers will fail.  Ideally, we
-    * should load one of libGL, libGLESv1_CM, or libGLESv2 and go on.  But if
-    * the app has loaded another one of them with RTLD_LOCAL, there may be
-    * unexpected behaviors later because there will be two copies of glapi
-    * (with global variables of the same names!) in the memory.
-    */
+   /* if glapi is not available, loading DRI drivers will fail */
    if (!dri2_drv->get_proc_address) {
       _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address");
       return EGL_FALSE;
@@ -2369,6 +1101,8 @@ dri2_load(_EGLDriver *drv)
    dri2_drv->glFlush = (void (*)(void))
       dri2_drv->get_proc_address("glFlush");
 
+   dri2_drv->handle = handle;
+
    return EGL_TRUE;
 }
 
@@ -2397,20 +1131,13 @@ _EGL_MAIN(const char *args)
    dri2_drv->base.API.Terminate = dri2_terminate;
    dri2_drv->base.API.CreateContext = dri2_create_context;
    dri2_drv->base.API.MakeCurrent = dri2_make_current;
-   dri2_drv->base.API.CreateWindowSurface = dri2_create_window_surface;
-   dri2_drv->base.API.CreatePixmapSurface = dri2_create_pixmap_surface;
-   dri2_drv->base.API.CreatePbufferSurface = dri2_create_pbuffer_surface;
-   dri2_drv->base.API.DestroySurface = dri2_destroy_surface;
-   dri2_drv->base.API.SwapBuffers = dri2_swap_buffers;
    dri2_drv->base.API.GetProcAddress = dri2_get_proc_address;
    dri2_drv->base.API.WaitClient = dri2_wait_client;
    dri2_drv->base.API.WaitNative = dri2_wait_native;
-   dri2_drv->base.API.CopyBuffers = dri2_copy_buffers;
    dri2_drv->base.API.BindTexImage = dri2_bind_tex_image;
    dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image;
    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;
 
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
new file mode 100644 (file)
index 0000000..235e30d
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright © 2011 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:
+ *    Kristian Høgsberg <krh@bitplanet.net>
+ */
+
+#ifndef EGL_DRI2_INCLUDED
+#define EGL_DRI2_INCLUDED
+
+#include <xcb/xcb.h>
+#include <xcb/dri2.h>
+#include <xcb/xfixes.h>
+#include <X11/Xlib-xcb.h>
+
+#ifdef HAVE_WAYLAND_PLATFORM
+#include <wayland-client.h>
+#include "wayland-egl-priv.h"
+#endif
+
+#include <GL/gl.h>
+#include <GL/internal/dri_interface.h>
+
+#include "eglconfig.h"
+#include "eglcontext.h"
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglcurrent.h"
+#include "egllog.h"
+#include "eglsurface.h"
+#include "eglimage.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+struct dri2_egl_driver
+{
+   _EGLDriver base;
+
+   void *handle;
+   _EGLProc (*get_proc_address)(const char *procname);
+   void (*glFlush)(void);
+};
+
+struct dri2_egl_display
+{
+   xcb_connection_t         *conn;
+   int                       dri2_major;
+   int                       dri2_minor;
+   __DRIscreen              *dri_screen;
+   const __DRIconfig       **driver_configs;
+   void                     *driver;
+   __DRIcoreExtension       *core;
+   __DRIdri2Extension       *dri2;
+   __DRIswrastExtension     *swrast;
+   __DRI2flushExtension     *flush;
+   __DRItexBufferExtension  *tex_buffer;
+   __DRIimageExtension      *image;
+   int                       fd;
+
+   char                     *device_name;
+   char                     *driver_name;
+
+   __DRIdri2LoaderExtension    dri2_loader_extension;
+   __DRIswrastLoaderExtension  swrast_loader_extension;
+   const __DRIextension     *extensions[3];
+#ifdef HAVE_WAYLAND_PLATFORM
+   struct wl_egl_display    *wl_dpy;
+#endif
+};
+
+struct dri2_egl_context
+{
+   _EGLContext   base;
+   __DRIcontext *dri_context;
+};
+
+#ifdef HAVE_WAYLAND_PLATFORM
+enum wayland_buffer_type {
+   WL_BUFFER_FRONT,
+   WL_BUFFER_BACK,
+   WL_BUFFER_COUNT
+};
+
+#define __DRI_BUFFER_COUNT 10
+#endif
+
+enum dri2_surface_type {
+   DRI2_WINDOW_SURFACE,
+   DRI2_PIXMAP_SURFACE,
+   DRI2_PBUFFER_SURFACE
+};
+
+struct dri2_egl_surface
+{
+   _EGLSurface          base;
+   __DRIdrawable       *dri_drawable;
+   xcb_drawable_t       drawable;
+   __DRIbuffer          buffers[5];
+   int                  buffer_count;
+   xcb_xfixes_region_t  region;
+   int                  have_fake_front;
+   int                  swap_interval;
+
+   int                  depth;
+   int                  bytes_per_pixel;
+   xcb_gcontext_t       gc;
+   xcb_gcontext_t       swapgc;
+
+   enum dri2_surface_type type;
+#ifdef HAVE_WAYLAND_PLATFORM
+   struct wl_egl_window  *wl_win;
+   struct wl_egl_pixmap  *wl_pix;
+   struct wl_buffer      *wl_drm_buffer[WL_BUFFER_COUNT];
+   int                    dx;
+   int                    dy;
+   __DRIbuffer           *dri_buffers[__DRI_BUFFER_COUNT];
+   __DRIbuffer           *pending_buffer;
+   EGLBoolean             block_swap_buffers;
+#endif
+};
+
+struct dri2_egl_buffer {
+   __DRIbuffer *dri_buffer;
+   struct dri2_egl_display *dri2_dpy;
+};
+
+
+struct dri2_egl_config
+{
+   _EGLConfig         base;
+   const __DRIconfig *dri_single_config;
+   const __DRIconfig *dri_double_config;
+};
+
+struct dri2_egl_image
+{
+   _EGLImage   base;
+   __DRIimage *dri_image;
+};
+
+/* standard typecasts */
+_EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl)
+_EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj)
+
+extern const __DRIimageLookupExtension image_lookup_extension;
+extern const __DRIuseInvalidateExtension use_invalidate;
+
+EGLBoolean
+dri2_load_driver(_EGLDisplay *disp);
+
+EGLBoolean
+dri2_create_screen(_EGLDisplay *disp);
+
+struct dri2_egl_config *
+dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
+               int depth, EGLint surface_type, const EGLint *attr_list);
+
+_EGLImage *
+dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
+                     _EGLContext *ctx, EGLenum target,
+                     EGLClientBuffer buffer, const EGLint *attr_list);
+
+EGLBoolean
+dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp);
+
+EGLBoolean
+dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp);
+
+EGLBoolean
+dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp);
+
+char *
+dri2_get_driver_for_fd(int fd);
+
+#endif /* EGL_DRI2_INCLUDED */
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
new file mode 100644 (file)
index 0000000..3dab899
--- /dev/null
@@ -0,0 +1,683 @@
+/*
+ * Copyright © 2011 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:
+ *    Kristian Høgsberg <krh@bitplanet.net>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <limits.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <xf86drm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_LIBUDEV
+#include <libudev.h>
+#endif
+
+#include "egl_dri2.h"
+
+
+#ifdef HAVE_LIBUDEV
+
+struct dri2_driver_map {
+   int vendor_id;
+   const char *driver;
+   const int *chip_ids;
+   int num_chips_ids;
+};
+
+const int i915_chip_ids[] = {
+   0x3577, /* PCI_CHIP_I830_M */
+   0x2562, /* PCI_CHIP_845_G */
+   0x3582, /* PCI_CHIP_I855_GM */
+   0x2572, /* PCI_CHIP_I865_G */
+   0x2582, /* PCI_CHIP_I915_G */
+   0x258a, /* PCI_CHIP_E7221_G */
+   0x2592, /* PCI_CHIP_I915_GM */
+   0x2772, /* PCI_CHIP_I945_G */
+   0x27a2, /* PCI_CHIP_I945_GM */
+   0x27ae, /* PCI_CHIP_I945_GME */
+   0x29b2, /* PCI_CHIP_Q35_G */
+   0x29c2, /* PCI_CHIP_G33_G */
+   0x29d2, /* PCI_CHIP_Q33_G */
+   0xa001, /* PCI_CHIP_IGD_G */
+   0xa011, /* Pineview */
+};
+
+const int i965_chip_ids[] = {
+   0x0042, /* PCI_CHIP_ILD_G */
+   0x0046, /* PCI_CHIP_ILM_G */
+   0x0102, /* PCI_CHIP_SANDYBRIDGE_GT1 */
+   0x0106, /* PCI_CHIP_SANDYBRIDGE_M_GT1 */
+   0x010a, /* PCI_CHIP_SANDYBRIDGE_S */
+   0x0112, /* PCI_CHIP_SANDYBRIDGE_GT2 */
+   0x0116, /* PCI_CHIP_SANDYBRIDGE_M_GT2 */
+   0x0122, /* PCI_CHIP_SANDYBRIDGE_GT2_PLUS */
+   0x0126, /* PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS */
+   0x29a2, /* PCI_CHIP_I965_G */
+   0x2992, /* PCI_CHIP_I965_Q */
+   0x2982, /* PCI_CHIP_I965_G_1 */
+   0x2972, /* PCI_CHIP_I946_GZ */
+   0x2a02, /* PCI_CHIP_I965_GM */
+   0x2a12, /* PCI_CHIP_I965_GME */
+   0x2a42, /* PCI_CHIP_GM45_GM */
+   0x2e02, /* PCI_CHIP_IGD_E_G */
+   0x2e12, /* PCI_CHIP_Q45_G */
+   0x2e22, /* PCI_CHIP_G45_G */
+   0x2e32, /* PCI_CHIP_G41_G */
+   0x2e42, /* PCI_CHIP_B43_G */
+   0x2e92, /* PCI_CHIP_B43_G1 */
+};
+
+const int r100_chip_ids[] = {
+   0x4C57, /* PCI_CHIP_RADEON_LW */
+   0x4C58, /* PCI_CHIP_RADEON_LX */
+   0x4C59, /* PCI_CHIP_RADEON_LY */
+   0x4C5A, /* PCI_CHIP_RADEON_LZ */
+   0x5144, /* PCI_CHIP_RADEON_QD */
+   0x5145, /* PCI_CHIP_RADEON_QE */
+   0x5146, /* PCI_CHIP_RADEON_QF */
+   0x5147, /* PCI_CHIP_RADEON_QG */
+   0x5159, /* PCI_CHIP_RADEON_QY */
+   0x515A, /* PCI_CHIP_RADEON_QZ */
+   0x5157, /* PCI_CHIP_RV200_QW */
+   0x5158, /* PCI_CHIP_RV200_QX */
+   0x515E, /* PCI_CHIP_RN50_515E */
+   0x5969, /* PCI_CHIP_RN50_5969 */
+   0x4136, /* PCI_CHIP_RS100_4136 */
+   0x4336, /* PCI_CHIP_RS100_4336 */
+   0x4137, /* PCI_CHIP_RS200_4137 */
+   0x4337, /* PCI_CHIP_RS200_4337 */
+   0x4237, /* PCI_CHIP_RS250_4237 */
+   0x4437, /* PCI_CHIP_RS250_4437 */
+};
+
+const int r200_chip_ids[] = {
+   0x5148, /* PCI_CHIP_R200_QH */
+   0x514C, /* PCI_CHIP_R200_QL */
+   0x514D, /* PCI_CHIP_R200_QM */
+   0x4242, /* PCI_CHIP_R200_BB */
+   0x4966, /* PCI_CHIP_RV250_If */
+   0x4967, /* PCI_CHIP_RV250_Ig */
+   0x4C64, /* PCI_CHIP_RV250_Ld */
+   0x4C66, /* PCI_CHIP_RV250_Lf */
+   0x4C67, /* PCI_CHIP_RV250_Lg */
+   0x5960, /* PCI_CHIP_RV280_5960 */
+   0x5961, /* PCI_CHIP_RV280_5961 */
+   0x5962, /* PCI_CHIP_RV280_5962 */
+   0x5964, /* PCI_CHIP_RV280_5964 */
+   0x5965, /* PCI_CHIP_RV280_5965 */
+   0x5C61, /* PCI_CHIP_RV280_5C61 */
+   0x5C63, /* PCI_CHIP_RV280_5C63 */
+   0x5834, /* PCI_CHIP_RS300_5834 */
+   0x5835, /* PCI_CHIP_RS300_5835 */
+   0x7834, /* PCI_CHIP_RS350_7834 */
+   0x7835, /* PCI_CHIP_RS350_7835 */
+};
+
+const int r300_chip_ids[] = {
+   0x4144, /* PCI_CHIP_R300_AD */
+   0x4145, /* PCI_CHIP_R300_AE */
+   0x4146, /* PCI_CHIP_R300_AF */
+   0x4147, /* PCI_CHIP_R300_AG */
+   0x4E44, /* PCI_CHIP_R300_ND */
+   0x4E45, /* PCI_CHIP_R300_NE */
+   0x4E46, /* PCI_CHIP_R300_NF */
+   0x4E47, /* PCI_CHIP_R300_NG */
+   0x4E48, /* PCI_CHIP_R350_NH */
+   0x4E49, /* PCI_CHIP_R350_NI */
+   0x4E4B, /* PCI_CHIP_R350_NK */
+   0x4148, /* PCI_CHIP_R350_AH */
+   0x4149, /* PCI_CHIP_R350_AI */
+   0x414A, /* PCI_CHIP_R350_AJ */
+   0x414B, /* PCI_CHIP_R350_AK */
+   0x4E4A, /* PCI_CHIP_R360_NJ */
+   0x4150, /* PCI_CHIP_RV350_AP */
+   0x4151, /* PCI_CHIP_RV350_AQ */
+   0x4152, /* PCI_CHIP_RV350_AR */
+   0x4153, /* PCI_CHIP_RV350_AS */
+   0x4154, /* PCI_CHIP_RV350_AT */
+   0x4155, /* PCI_CHIP_RV350_AU */
+   0x4156, /* PCI_CHIP_RV350_AV */
+   0x4E50, /* PCI_CHIP_RV350_NP */
+   0x4E51, /* PCI_CHIP_RV350_NQ */
+   0x4E52, /* PCI_CHIP_RV350_NR */
+   0x4E53, /* PCI_CHIP_RV350_NS */
+   0x4E54, /* PCI_CHIP_RV350_NT */
+   0x4E56, /* PCI_CHIP_RV350_NV */
+   0x5460, /* PCI_CHIP_RV370_5460 */
+   0x5462, /* PCI_CHIP_RV370_5462 */
+   0x5464, /* PCI_CHIP_RV370_5464 */
+   0x5B60, /* PCI_CHIP_RV370_5B60 */
+   0x5B62, /* PCI_CHIP_RV370_5B62 */
+   0x5B63, /* PCI_CHIP_RV370_5B63 */
+   0x5B64, /* PCI_CHIP_RV370_5B64 */
+   0x5B65, /* PCI_CHIP_RV370_5B65 */
+   0x3150, /* PCI_CHIP_RV380_3150 */
+   0x3152, /* PCI_CHIP_RV380_3152 */
+   0x3154, /* PCI_CHIP_RV380_3154 */
+   0x3155, /* PCI_CHIP_RV380_3155 */
+   0x3E50, /* PCI_CHIP_RV380_3E50 */
+   0x3E54, /* PCI_CHIP_RV380_3E54 */
+   0x4A48, /* PCI_CHIP_R420_JH */
+   0x4A49, /* PCI_CHIP_R420_JI */
+   0x4A4A, /* PCI_CHIP_R420_JJ */
+   0x4A4B, /* PCI_CHIP_R420_JK */
+   0x4A4C, /* PCI_CHIP_R420_JL */
+   0x4A4D, /* PCI_CHIP_R420_JM */
+   0x4A4E, /* PCI_CHIP_R420_JN */
+   0x4A4F, /* PCI_CHIP_R420_JO */
+   0x4A50, /* PCI_CHIP_R420_JP */
+   0x4A54, /* PCI_CHIP_R420_JT */
+   0x5548, /* PCI_CHIP_R423_UH */
+   0x5549, /* PCI_CHIP_R423_UI */
+   0x554A, /* PCI_CHIP_R423_UJ */
+   0x554B, /* PCI_CHIP_R423_UK */
+   0x5550, /* PCI_CHIP_R423_5550 */
+   0x5551, /* PCI_CHIP_R423_UQ */
+   0x5552, /* PCI_CHIP_R423_UR */
+   0x5554, /* PCI_CHIP_R423_UT */
+   0x5D57, /* PCI_CHIP_R423_5D57 */
+   0x554C, /* PCI_CHIP_R430_554C */
+   0x554D, /* PCI_CHIP_R430_554D */
+   0x554E, /* PCI_CHIP_R430_554E */
+   0x554F, /* PCI_CHIP_R430_554F */
+   0x5D48, /* PCI_CHIP_R430_5D48 */
+   0x5D49, /* PCI_CHIP_R430_5D49 */
+   0x5D4A, /* PCI_CHIP_R430_5D4A */
+   0x5D4C, /* PCI_CHIP_R480_5D4C */
+   0x5D4D, /* PCI_CHIP_R480_5D4D */
+   0x5D4E, /* PCI_CHIP_R480_5D4E */
+   0x5D4F, /* PCI_CHIP_R480_5D4F */
+   0x5D50, /* PCI_CHIP_R480_5D50 */
+   0x5D52, /* PCI_CHIP_R480_5D52 */
+   0x4B49, /* PCI_CHIP_R481_4B49 */
+   0x4B4A, /* PCI_CHIP_R481_4B4A */
+   0x4B4B, /* PCI_CHIP_R481_4B4B */
+   0x4B4C, /* PCI_CHIP_R481_4B4C */
+   0x564A, /* PCI_CHIP_RV410_564A */
+   0x564B, /* PCI_CHIP_RV410_564B */
+   0x564F, /* PCI_CHIP_RV410_564F */
+   0x5652, /* PCI_CHIP_RV410_5652 */
+   0x5653, /* PCI_CHIP_RV410_5653 */
+   0x5657, /* PCI_CHIP_RV410_5657 */
+   0x5E48, /* PCI_CHIP_RV410_5E48 */
+   0x5E4A, /* PCI_CHIP_RV410_5E4A */
+   0x5E4B, /* PCI_CHIP_RV410_5E4B */
+   0x5E4C, /* PCI_CHIP_RV410_5E4C */
+   0x5E4D, /* PCI_CHIP_RV410_5E4D */
+   0x5E4F, /* PCI_CHIP_RV410_5E4F */
+   0x5A41, /* PCI_CHIP_RS400_5A41 */
+   0x5A42, /* PCI_CHIP_RS400_5A42 */
+   0x5A61, /* PCI_CHIP_RC410_5A61 */
+   0x5A62, /* PCI_CHIP_RC410_5A62 */
+   0x5954, /* PCI_CHIP_RS480_5954 */
+   0x5955, /* PCI_CHIP_RS480_5955 */
+   0x5974, /* PCI_CHIP_RS482_5974 */
+   0x5975, /* PCI_CHIP_RS482_5975 */
+   0x7100, /* PCI_CHIP_R520_7100 */
+   0x7101, /* PCI_CHIP_R520_7101 */
+   0x7102, /* PCI_CHIP_R520_7102 */
+   0x7103, /* PCI_CHIP_R520_7103 */
+   0x7104, /* PCI_CHIP_R520_7104 */
+   0x7105, /* PCI_CHIP_R520_7105 */
+   0x7106, /* PCI_CHIP_R520_7106 */
+   0x7108, /* PCI_CHIP_R520_7108 */
+   0x7109, /* PCI_CHIP_R520_7109 */
+   0x710A, /* PCI_CHIP_R520_710A */
+   0x710B, /* PCI_CHIP_R520_710B */
+   0x710C, /* PCI_CHIP_R520_710C */
+   0x710E, /* PCI_CHIP_R520_710E */
+   0x710F, /* PCI_CHIP_R520_710F */
+   0x7140, /* PCI_CHIP_RV515_7140 */
+   0x7141, /* PCI_CHIP_RV515_7141 */
+   0x7142, /* PCI_CHIP_RV515_7142 */
+   0x7143, /* PCI_CHIP_RV515_7143 */
+   0x7144, /* PCI_CHIP_RV515_7144 */
+   0x7145, /* PCI_CHIP_RV515_7145 */
+   0x7146, /* PCI_CHIP_RV515_7146 */
+   0x7147, /* PCI_CHIP_RV515_7147 */
+   0x7149, /* PCI_CHIP_RV515_7149 */
+   0x714A, /* PCI_CHIP_RV515_714A */
+   0x714B, /* PCI_CHIP_RV515_714B */
+   0x714C, /* PCI_CHIP_RV515_714C */
+   0x714D, /* PCI_CHIP_RV515_714D */
+   0x714E, /* PCI_CHIP_RV515_714E */
+   0x714F, /* PCI_CHIP_RV515_714F */
+   0x7151, /* PCI_CHIP_RV515_7151 */
+   0x7152, /* PCI_CHIP_RV515_7152 */
+   0x7153, /* PCI_CHIP_RV515_7153 */
+   0x715E, /* PCI_CHIP_RV515_715E */
+   0x715F, /* PCI_CHIP_RV515_715F */
+   0x7180, /* PCI_CHIP_RV515_7180 */
+   0x7181, /* PCI_CHIP_RV515_7181 */
+   0x7183, /* PCI_CHIP_RV515_7183 */
+   0x7186, /* PCI_CHIP_RV515_7186 */
+   0x7187, /* PCI_CHIP_RV515_7187 */
+   0x7188, /* PCI_CHIP_RV515_7188 */
+   0x718A, /* PCI_CHIP_RV515_718A */
+   0x718B, /* PCI_CHIP_RV515_718B */
+   0x718C, /* PCI_CHIP_RV515_718C */
+   0x718D, /* PCI_CHIP_RV515_718D */
+   0x718F, /* PCI_CHIP_RV515_718F */
+   0x7193, /* PCI_CHIP_RV515_7193 */
+   0x7196, /* PCI_CHIP_RV515_7196 */
+   0x719B, /* PCI_CHIP_RV515_719B */
+   0x719F, /* PCI_CHIP_RV515_719F */
+   0x7200, /* PCI_CHIP_RV515_7200 */
+   0x7210, /* PCI_CHIP_RV515_7210 */
+   0x7211, /* PCI_CHIP_RV515_7211 */
+   0x71C0, /* PCI_CHIP_RV530_71C0 */
+   0x71C1, /* PCI_CHIP_RV530_71C1 */
+   0x71C2, /* PCI_CHIP_RV530_71C2 */
+   0x71C3, /* PCI_CHIP_RV530_71C3 */
+   0x71C4, /* PCI_CHIP_RV530_71C4 */
+   0x71C5, /* PCI_CHIP_RV530_71C5 */
+   0x71C6, /* PCI_CHIP_RV530_71C6 */
+   0x71C7, /* PCI_CHIP_RV530_71C7 */
+   0x71CD, /* PCI_CHIP_RV530_71CD */
+   0x71CE, /* PCI_CHIP_RV530_71CE */
+   0x71D2, /* PCI_CHIP_RV530_71D2 */
+   0x71D4, /* PCI_CHIP_RV530_71D4 */
+   0x71D5, /* PCI_CHIP_RV530_71D5 */
+   0x71D6, /* PCI_CHIP_RV530_71D6 */
+   0x71DA, /* PCI_CHIP_RV530_71DA */
+   0x71DE, /* PCI_CHIP_RV530_71DE */
+   0x7281, /* PCI_CHIP_RV560_7281 */
+   0x7283, /* PCI_CHIP_RV560_7283 */
+   0x7287, /* PCI_CHIP_RV560_7287 */
+   0x7290, /* PCI_CHIP_RV560_7290 */
+   0x7291, /* PCI_CHIP_RV560_7291 */
+   0x7293, /* PCI_CHIP_RV560_7293 */
+   0x7297, /* PCI_CHIP_RV560_7297 */
+   0x7280, /* PCI_CHIP_RV570_7280 */
+   0x7288, /* PCI_CHIP_RV570_7288 */
+   0x7289, /* PCI_CHIP_RV570_7289 */
+   0x728B, /* PCI_CHIP_RV570_728B */
+   0x728C, /* PCI_CHIP_RV570_728C */
+   0x7240, /* PCI_CHIP_R580_7240 */
+   0x7243, /* PCI_CHIP_R580_7243 */
+   0x7244, /* PCI_CHIP_R580_7244 */
+   0x7245, /* PCI_CHIP_R580_7245 */
+   0x7246, /* PCI_CHIP_R580_7246 */
+   0x7247, /* PCI_CHIP_R580_7247 */
+   0x7248, /* PCI_CHIP_R580_7248 */
+   0x7249, /* PCI_CHIP_R580_7249 */
+   0x724A, /* PCI_CHIP_R580_724A */
+   0x724B, /* PCI_CHIP_R580_724B */
+   0x724C, /* PCI_CHIP_R580_724C */
+   0x724D, /* PCI_CHIP_R580_724D */
+   0x724E, /* PCI_CHIP_R580_724E */
+   0x724F, /* PCI_CHIP_R580_724F */
+   0x7284, /* PCI_CHIP_R580_7284 */
+   0x793F, /* PCI_CHIP_RS600_793F */
+   0x7941, /* PCI_CHIP_RS600_7941 */
+   0x7942, /* PCI_CHIP_RS600_7942 */
+   0x791E, /* PCI_CHIP_RS690_791E */
+   0x791F, /* PCI_CHIP_RS690_791F */
+   0x796C, /* PCI_CHIP_RS740_796C */
+   0x796D, /* PCI_CHIP_RS740_796D */
+   0x796E, /* PCI_CHIP_RS740_796E */
+   0x796F, /* PCI_CHIP_RS740_796F */
+};
+
+const int r600_chip_ids[] = {
+   0x9400, /* PCI_CHIP_R600_9400 */
+   0x9401, /* PCI_CHIP_R600_9401 */
+   0x9402, /* PCI_CHIP_R600_9402 */
+   0x9403, /* PCI_CHIP_R600_9403 */
+   0x9405, /* PCI_CHIP_R600_9405 */
+   0x940A, /* PCI_CHIP_R600_940A */
+   0x940B, /* PCI_CHIP_R600_940B */
+   0x940F, /* PCI_CHIP_R600_940F */
+   0x94C0, /* PCI_CHIP_RV610_94C0 */
+   0x94C1, /* PCI_CHIP_RV610_94C1 */
+   0x94C3, /* PCI_CHIP_RV610_94C3 */
+   0x94C4, /* PCI_CHIP_RV610_94C4 */
+   0x94C5, /* PCI_CHIP_RV610_94C5 */
+   0x94C6, /* PCI_CHIP_RV610_94C6 */
+   0x94C7, /* PCI_CHIP_RV610_94C7 */
+   0x94C8, /* PCI_CHIP_RV610_94C8 */
+   0x94C9, /* PCI_CHIP_RV610_94C9 */
+   0x94CB, /* PCI_CHIP_RV610_94CB */
+   0x94CC, /* PCI_CHIP_RV610_94CC */
+   0x94CD, /* PCI_CHIP_RV610_94CD */
+   0x9580, /* PCI_CHIP_RV630_9580 */
+   0x9581, /* PCI_CHIP_RV630_9581 */
+   0x9583, /* PCI_CHIP_RV630_9583 */
+   0x9586, /* PCI_CHIP_RV630_9586 */
+   0x9587, /* PCI_CHIP_RV630_9587 */
+   0x9588, /* PCI_CHIP_RV630_9588 */
+   0x9589, /* PCI_CHIP_RV630_9589 */
+   0x958A, /* PCI_CHIP_RV630_958A */
+   0x958B, /* PCI_CHIP_RV630_958B */
+   0x958C, /* PCI_CHIP_RV630_958C */
+   0x958D, /* PCI_CHIP_RV630_958D */
+   0x958E, /* PCI_CHIP_RV630_958E */
+   0x958F, /* PCI_CHIP_RV630_958F */
+   0x9500, /* PCI_CHIP_RV670_9500 */
+   0x9501, /* PCI_CHIP_RV670_9501 */
+   0x9504, /* PCI_CHIP_RV670_9504 */
+   0x9505, /* PCI_CHIP_RV670_9505 */
+   0x9506, /* PCI_CHIP_RV670_9506 */
+   0x9507, /* PCI_CHIP_RV670_9507 */
+   0x9508, /* PCI_CHIP_RV670_9508 */
+   0x9509, /* PCI_CHIP_RV670_9509 */
+   0x950F, /* PCI_CHIP_RV670_950F */
+   0x9511, /* PCI_CHIP_RV670_9511 */
+   0x9515, /* PCI_CHIP_RV670_9515 */
+   0x9517, /* PCI_CHIP_RV670_9517 */
+   0x9519, /* PCI_CHIP_RV670_9519 */
+   0x95C0, /* PCI_CHIP_RV620_95C0 */
+   0x95C2, /* PCI_CHIP_RV620_95C2 */
+   0x95C4, /* PCI_CHIP_RV620_95C4 */
+   0x95C5, /* PCI_CHIP_RV620_95C5 */
+   0x95C6, /* PCI_CHIP_RV620_95C6 */
+   0x95C7, /* PCI_CHIP_RV620_95C7 */
+   0x95C9, /* PCI_CHIP_RV620_95C9 */
+   0x95CC, /* PCI_CHIP_RV620_95CC */
+   0x95CD, /* PCI_CHIP_RV620_95CD */
+   0x95CE, /* PCI_CHIP_RV620_95CE */
+   0x95CF, /* PCI_CHIP_RV620_95CF */
+   0x9590, /* PCI_CHIP_RV635_9590 */
+   0x9591, /* PCI_CHIP_RV635_9591 */
+   0x9593, /* PCI_CHIP_RV635_9593 */
+   0x9595, /* PCI_CHIP_RV635_9595 */
+   0x9596, /* PCI_CHIP_RV635_9596 */
+   0x9597, /* PCI_CHIP_RV635_9597 */
+   0x9598, /* PCI_CHIP_RV635_9598 */
+   0x9599, /* PCI_CHIP_RV635_9599 */
+   0x959B, /* PCI_CHIP_RV635_959B */
+   0x9610, /* PCI_CHIP_RS780_9610 */
+   0x9611, /* PCI_CHIP_RS780_9611 */
+   0x9612, /* PCI_CHIP_RS780_9612 */
+   0x9613, /* PCI_CHIP_RS780_9613 */
+   0x9614, /* PCI_CHIP_RS780_9614 */
+   0x9615, /* PCI_CHIP_RS780_9615 */
+   0x9616, /* PCI_CHIP_RS780_9616 */
+   0x9710, /* PCI_CHIP_RS880_9710 */
+   0x9711, /* PCI_CHIP_RS880_9711 */
+   0x9712, /* PCI_CHIP_RS880_9712 */
+   0x9713, /* PCI_CHIP_RS880_9713 */
+   0x9714, /* PCI_CHIP_RS880_9714 */
+   0x9715, /* PCI_CHIP_RS880_9715 */
+   0x9440, /* PCI_CHIP_RV770_9440 */
+   0x9441, /* PCI_CHIP_RV770_9441 */
+   0x9442, /* PCI_CHIP_RV770_9442 */
+   0x9443, /* PCI_CHIP_RV770_9443 */
+   0x9444, /* PCI_CHIP_RV770_9444 */
+   0x9446, /* PCI_CHIP_RV770_9446 */
+   0x944A, /* PCI_CHIP_RV770_944A */
+   0x944B, /* PCI_CHIP_RV770_944B */
+   0x944C, /* PCI_CHIP_RV770_944C */
+   0x944E, /* PCI_CHIP_RV770_944E */
+   0x9450, /* PCI_CHIP_RV770_9450 */
+   0x9452, /* PCI_CHIP_RV770_9452 */
+   0x9456, /* PCI_CHIP_RV770_9456 */
+   0x945A, /* PCI_CHIP_RV770_945A */
+   0x945B, /* PCI_CHIP_RV770_945B */
+   0x945E, /* PCI_CHIP_RV770_945E */
+   0x9460, /* PCI_CHIP_RV790_9460 */
+   0x9462, /* PCI_CHIP_RV790_9462 */
+   0x946A, /* PCI_CHIP_RV770_946A */
+   0x946B, /* PCI_CHIP_RV770_946B */
+   0x947A, /* PCI_CHIP_RV770_947A */
+   0x947B, /* PCI_CHIP_RV770_947B */
+   0x9480, /* PCI_CHIP_RV730_9480 */
+   0x9487, /* PCI_CHIP_RV730_9487 */
+   0x9488, /* PCI_CHIP_RV730_9488 */
+   0x9489, /* PCI_CHIP_RV730_9489 */
+   0x948A, /* PCI_CHIP_RV730_948A */
+   0x948F, /* PCI_CHIP_RV730_948F */
+   0x9490, /* PCI_CHIP_RV730_9490 */
+   0x9491, /* PCI_CHIP_RV730_9491 */
+   0x9495, /* PCI_CHIP_RV730_9495 */
+   0x9498, /* PCI_CHIP_RV730_9498 */
+   0x949C, /* PCI_CHIP_RV730_949C */
+   0x949E, /* PCI_CHIP_RV730_949E */
+   0x949F, /* PCI_CHIP_RV730_949F */
+   0x9540, /* PCI_CHIP_RV710_9540 */
+   0x9541, /* PCI_CHIP_RV710_9541 */
+   0x9542, /* PCI_CHIP_RV710_9542 */
+   0x954E, /* PCI_CHIP_RV710_954E */
+   0x954F, /* PCI_CHIP_RV710_954F */
+   0x9552, /* PCI_CHIP_RV710_9552 */
+   0x9553, /* PCI_CHIP_RV710_9553 */
+   0x9555, /* PCI_CHIP_RV710_9555 */
+   0x9557, /* PCI_CHIP_RV710_9557 */
+   0x955F, /* PCI_CHIP_RV710_955F */
+   0x94A0, /* PCI_CHIP_RV740_94A0 */
+   0x94A1, /* PCI_CHIP_RV740_94A1 */
+   0x94A3, /* PCI_CHIP_RV740_94A3 */
+   0x94B1, /* PCI_CHIP_RV740_94B1 */
+   0x94B3, /* PCI_CHIP_RV740_94B3 */
+   0x94B4, /* PCI_CHIP_RV740_94B4 */
+   0x94B5, /* PCI_CHIP_RV740_94B5 */
+   0x94B9, /* PCI_CHIP_RV740_94B9 */
+   0x68E0, /* PCI_CHIP_CEDAR_68E0 */
+   0x68E1, /* PCI_CHIP_CEDAR_68E1 */
+   0x68E4, /* PCI_CHIP_CEDAR_68E4 */
+   0x68E5, /* PCI_CHIP_CEDAR_68E5 */
+   0x68E8, /* PCI_CHIP_CEDAR_68E8 */
+   0x68E9, /* PCI_CHIP_CEDAR_68E9 */
+   0x68F1, /* PCI_CHIP_CEDAR_68F1 */
+   0x68F8, /* PCI_CHIP_CEDAR_68F8 */
+   0x68F9, /* PCI_CHIP_CEDAR_68F9 */
+   0x68FE, /* PCI_CHIP_CEDAR_68FE */
+   0x68C0, /* PCI_CHIP_REDWOOD_68C0 */
+   0x68C1, /* PCI_CHIP_REDWOOD_68C1 */
+   0x68C8, /* PCI_CHIP_REDWOOD_68C8 */
+   0x68C9, /* PCI_CHIP_REDWOOD_68C9 */
+   0x68D8, /* PCI_CHIP_REDWOOD_68D8 */
+   0x68D9, /* PCI_CHIP_REDWOOD_68D9 */
+   0x68DA, /* PCI_CHIP_REDWOOD_68DA */
+   0x68DE, /* PCI_CHIP_REDWOOD_68DE */
+   0x68A0, /* PCI_CHIP_JUNIPER_68A0 */
+   0x68A1, /* PCI_CHIP_JUNIPER_68A1 */
+   0x68A8, /* PCI_CHIP_JUNIPER_68A8 */
+   0x68A9, /* PCI_CHIP_JUNIPER_68A9 */
+   0x68B0, /* PCI_CHIP_JUNIPER_68B0 */
+   0x68B8, /* PCI_CHIP_JUNIPER_68B8 */
+   0x68B9, /* PCI_CHIP_JUNIPER_68B9 */
+   0x68BE, /* PCI_CHIP_JUNIPER_68BE */
+   0x6880, /* PCI_CHIP_CYPRESS_6880 */
+   0x6888, /* PCI_CHIP_CYPRESS_6888 */
+   0x6889, /* PCI_CHIP_CYPRESS_6889 */
+   0x688A, /* PCI_CHIP_CYPRESS_688A */
+   0x6898, /* PCI_CHIP_CYPRESS_6898 */
+   0x6899, /* PCI_CHIP_CYPRESS_6899 */
+   0x689E, /* PCI_CHIP_CYPRESS_689E */
+   0x689C, /* PCI_CHIP_HEMLOCK_689C */
+   0x689D, /* PCI_CHIP_HEMLOCK_689D */
+   0x9802, /* PCI_CHIP_PALM_9802 */
+   0x9803, /* PCI_CHIP_PALM_9803 */
+   0x9804, /* PCI_CHIP_PALM_9804 */
+   0x9805, /* PCI_CHIP_PALM_9805 */
+   0x6720, /* PCI_CHIP_BARTS_6720 */
+   0x6721, /* PCI_CHIP_BARTS_6721 */
+   0x6722, /* PCI_CHIP_BARTS_6722 */
+   0x6723, /* PCI_CHIP_BARTS_6723 */
+   0x6724, /* PCI_CHIP_BARTS_6724 */
+   0x6725, /* PCI_CHIP_BARTS_6725 */
+   0x6726, /* PCI_CHIP_BARTS_6726 */
+   0x6727, /* PCI_CHIP_BARTS_6727 */
+   0x6728, /* PCI_CHIP_BARTS_6728 */
+   0x6729, /* PCI_CHIP_BARTS_6729 */
+   0x6738, /* PCI_CHIP_BARTS_6738 */
+   0x6739, /* PCI_CHIP_BARTS_6738 */
+   0x6740, /* PCI_CHIP_TURKS_6740 */
+   0x6741, /* PCI_CHIP_TURKS_6741 */
+   0x6742, /* PCI_CHIP_TURKS_6742 */
+   0x6743, /* PCI_CHIP_TURKS_6743 */
+   0x6744, /* PCI_CHIP_TURKS_6744 */
+   0x6745, /* PCI_CHIP_TURKS_6745 */
+   0x6746, /* PCI_CHIP_TURKS_6746 */
+   0x6747, /* PCI_CHIP_TURKS_6747 */
+   0x6748, /* PCI_CHIP_TURKS_6748 */
+   0x6749, /* PCI_CHIP_TURKS_6749 */
+   0x6750, /* PCI_CHIP_TURKS_6750 */
+   0x6758, /* PCI_CHIP_TURKS_6758 */
+   0x6759, /* PCI_CHIP_TURKS_6759 */
+   0x6760, /* PCI_CHIP_CAICOS_6760 */
+   0x6761, /* PCI_CHIP_CAICOS_6761 */
+   0x6762, /* PCI_CHIP_CAICOS_6762 */
+   0x6763, /* PCI_CHIP_CAICOS_6763 */
+   0x6764, /* PCI_CHIP_CAICOS_6764 */
+   0x6765, /* PCI_CHIP_CAICOS_6765 */
+   0x6766, /* PCI_CHIP_CAICOS_6766 */
+   0x6767, /* PCI_CHIP_CAICOS_6767 */
+   0x6768, /* PCI_CHIP_CAICOS_6768 */
+   0x6770, /* PCI_CHIP_CAICOS_6770 */
+   0x6779, /* PCI_CHIP_CAICOS_6779 */
+};
+
+const struct dri2_driver_map driver_map[] = {
+   { 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids) },
+   { 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids) },
+   { 0x1002, "radeon", r100_chip_ids, ARRAY_SIZE(r100_chip_ids) },
+   { 0x1002, "r200", r200_chip_ids, ARRAY_SIZE(r200_chip_ids) },
+   { 0x1002, "r300", r300_chip_ids, ARRAY_SIZE(r300_chip_ids) },
+   { 0x1002, "r600", r600_chip_ids, ARRAY_SIZE(r600_chip_ids) },
+   { 0x10de, "nouveau", NULL, -1 },
+};
+
+char *
+dri2_get_driver_for_fd(int fd)
+{
+   struct udev *udev;
+   struct udev_device *device, *parent;
+   struct stat buf;
+   const char *pci_id;
+   char *driver = NULL;
+   int vendor_id, chip_id, i, j;
+
+   udev = udev_new();
+   if (fstat(fd, &buf) < 0) {
+      _eglLog(_EGL_WARNING, "EGL-DRI2: failed to stat fd %d", fd);
+      goto out;
+   }
+
+   device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev);
+   if (device == NULL) {
+      _eglLog(_EGL_WARNING,
+             "EGL-DRI2: could not create udev device for fd %d", fd);
+      goto out;
+   }
+
+   parent = udev_device_get_parent(device);
+   if (parent == NULL) {
+      _eglLog(_EGL_WARNING, "DRI2: could not get parent device");
+      goto out;
+   }
+
+   pci_id = udev_device_get_property_value(parent, "PCI_ID");
+   if (pci_id == NULL || sscanf(pci_id, "%x:%x", &vendor_id, &chip_id) != 2) {
+      _eglLog(_EGL_WARNING, "EGL-DRI2: malformed or no PCI ID");
+      goto out;
+   }
+
+   for (i = 0; i < ARRAY_SIZE(driver_map); i++) {
+      if (vendor_id != driver_map[i].vendor_id)
+        continue;
+      if (driver_map[i].num_chips_ids == -1) {
+           driver = strdup(driver_map[i].driver);
+           _eglLog(_EGL_DEBUG, "pci id for %d: %04x:%04x, driver %s",
+                   fd, vendor_id, chip_id, driver);
+           goto out;
+      }
+
+      for (j = 0; j < driver_map[i].num_chips_ids; j++)
+        if (driver_map[i].chip_ids[j] == chip_id) {
+           driver = strdup(driver_map[i].driver);
+           _eglLog(_EGL_DEBUG, "pci id for %d: %04x:%04x, driver %s",
+                   fd, vendor_id, chip_id, driver);
+           goto out;
+        }
+   }
+
+ out:
+   udev_device_unref(device);
+   udev_unref(udev);
+
+   return driver;
+}
+
+EGLBoolean
+dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
+{
+   struct dri2_egl_display *dri2_dpy;
+   int i;
+
+   dri2_dpy = malloc(sizeof *dri2_dpy);
+   if (!dri2_dpy)
+      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
+   
+   memset(dri2_dpy, 0, sizeof *dri2_dpy);
+
+   disp->DriverData = (void *) dri2_dpy;
+   dri2_dpy->fd = (int) disp->PlatformDisplay;
+
+   dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd);
+   if (dri2_dpy->driver_name == NULL)
+      return _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name");
+
+   if (!dri2_load_driver(disp))
+      goto cleanup_driver_name;
+
+   dri2_dpy->extensions[0] = &image_lookup_extension.base;
+   dri2_dpy->extensions[1] = &use_invalidate.base;
+   dri2_dpy->extensions[2] = NULL;
+
+   if (!dri2_create_screen(disp))
+      goto cleanup_driver;
+
+   for (i = 0; dri2_dpy->driver_configs[i]; i++)
+      dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, 0, NULL);
+
+   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;
+
+   /* we're supporting EGL 1.4 */
+   disp->VersionMajor = 1;
+   disp->VersionMinor = 4;
+
+   return EGL_TRUE;
+
+ cleanup_driver:
+   dlclose(dri2_dpy->driver);
+ cleanup_driver_name:
+   free(dri2_dpy->driver_name);
+
+   return EGL_FALSE;
+}
+
+#endif
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
new file mode 100644 (file)
index 0000000..21b4406
--- /dev/null
@@ -0,0 +1,673 @@
+/*
+ * Copyright © 2011 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:
+ *    Kristian Høgsberg <krh@bitplanet.net>
+ *    Benjamin Franzke <benjaminfranzke@googlemail.com>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "egl_dri2.h"
+
+static void
+sync_callback(void *data)
+{
+   int *done = data;
+
+   *done = 1;
+}
+
+static void
+force_roundtrip(struct wl_display *display)
+{
+   int done = 0;
+
+   wl_display_sync_callback(display, sync_callback, &done);
+   wl_display_iterate(display, WL_DISPLAY_WRITABLE);
+   while (!done)
+      wl_display_iterate(display, WL_DISPLAY_READABLE);
+}
+
+
+/**
+ * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
+ */
+static _EGLSurface *
+dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
+                   _EGLConfig *conf, EGLNativeWindowType window,
+                   const EGLint *attrib_list)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
+   struct dri2_egl_surface *dri2_surf;
+   struct dri2_egl_buffer *dri2_buf;
+   int i;
+
+   (void) drv;
+
+   dri2_surf = malloc(sizeof *dri2_surf);
+   if (!dri2_surf) {
+      _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
+      return NULL;
+   }
+   
+   if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
+      goto cleanup_surf;
+
+   for (i = 0; i < WL_BUFFER_COUNT; ++i)
+      dri2_surf->wl_drm_buffer[i] = NULL;
+
+   for (i = 0; i < __DRI_BUFFER_COUNT; ++i)
+      dri2_surf->dri_buffers[i] = NULL;
+
+   dri2_surf->pending_buffer = NULL;
+   dri2_surf->block_swap_buffers = EGL_FALSE;
+
+   switch (type) {
+   case EGL_WINDOW_BIT:
+      dri2_surf->wl_win = (struct wl_egl_window *) window;
+      dri2_surf->type = DRI2_WINDOW_SURFACE;
+
+      dri2_surf->base.Width =  -1;
+      dri2_surf->base.Height = -1;
+      break;
+   case EGL_PIXMAP_BIT:
+      dri2_surf->wl_pix = (struct wl_egl_pixmap *) window;
+      dri2_surf->type = DRI2_PIXMAP_SURFACE;
+
+      dri2_surf->base.Width  = dri2_surf->wl_pix->width;
+      dri2_surf->base.Height = dri2_surf->wl_pix->height;
+
+      if (dri2_surf->wl_pix->name > 0) {
+         dri2_buf = dri2_surf->wl_pix->driver_private;
+         dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT] = dri2_buf->dri_buffer;
+      }
+      break;
+   default: 
+      goto cleanup_surf;
+   }
+
+   dri2_surf->dri_drawable = 
+      (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
+                                           type == EGL_WINDOW_BIT ?
+                                           dri2_conf->dri_double_config : 
+                                           dri2_conf->dri_single_config,
+                                           dri2_surf);
+   if (dri2_surf->dri_drawable == NULL) {
+      _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
+      goto cleanup_dri_drawable;
+   }
+
+   return &dri2_surf->base;
+
+ cleanup_dri_drawable:
+   dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
+ cleanup_surf:
+   free(dri2_surf);
+
+   return NULL;
+}
+
+/**
+ * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
+ */
+static _EGLSurface *
+dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
+                          _EGLConfig *conf, EGLNativeWindowType window,
+                          const EGLint *attrib_list)
+{
+   return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
+                             window, attrib_list);
+}
+
+static _EGLSurface *
+dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
+                          _EGLConfig *conf, EGLNativePixmapType pixmap,
+                          const EGLint *attrib_list)
+{
+   return dri2_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
+                             pixmap, attrib_list);
+}
+
+/**
+ * Called via eglDestroySurface(), drv->API.DestroySurface().
+ */
+static EGLBoolean
+dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
+   int i;
+
+   (void) drv;
+
+   if (!_eglPutSurface(surf))
+      return EGL_TRUE;
+
+   (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
+
+   for (i = 0; i < WL_BUFFER_COUNT; ++i)
+      if (dri2_surf->wl_drm_buffer[i])
+         wl_buffer_destroy(dri2_surf->wl_drm_buffer[i]);
+
+   for (i = 0; i < __DRI_BUFFER_COUNT; ++i)
+      if (dri2_surf->dri_buffers[i] && !(i == __DRI_BUFFER_FRONT_LEFT &&
+          dri2_surf->type == DRI2_PIXMAP_SURFACE))
+         dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
+                                       dri2_surf->dri_buffers[i]);
+
+   free(surf);
+
+   return EGL_TRUE;
+}
+
+static void
+dri2_wl_egl_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap)
+{
+   struct dri2_egl_buffer *dri2_buf = egl_pixmap->driver_private;
+
+   assert(dri2_buf);
+
+   dri2_buf->dri2_dpy->dri2->releaseBuffer(dri2_buf->dri2_dpy->dri_screen,
+                                           dri2_buf->dri_buffer);
+
+   free(dri2_buf);
+   
+   egl_pixmap->driver_private = NULL;
+   egl_pixmap->destroy = NULL;
+   egl_pixmap->name = 0;
+}
+
+static void
+dri2_process_back_buffer(struct dri2_egl_surface *dri2_surf, unsigned format)
+{
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+
+   (void) format;
+
+   switch (dri2_surf->type) {
+   case DRI2_WINDOW_SURFACE:
+      /* allocate a front buffer for our double-buffered window*/
+      dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT] = 
+         dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
+               __DRI_BUFFER_FRONT_LEFT, format,
+               dri2_surf->base.Width, dri2_surf->base.Height);
+      break;
+   default:
+      break;
+   }
+}
+
+static void
+dri2_process_front_buffer(struct dri2_egl_surface *dri2_surf, unsigned format)
+{
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+   struct dri2_egl_buffer *dri2_buf;
+
+   switch (dri2_surf->type) {
+   case DRI2_PIXMAP_SURFACE:
+      dri2_buf = malloc(sizeof *dri2_buf);
+      if (!dri2_buf)
+         return;
+
+      dri2_buf->dri_buffer = dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT];
+      dri2_buf->dri2_dpy   = dri2_dpy;
+
+      dri2_surf->wl_pix->name           = dri2_buf->dri_buffer->name;
+      dri2_surf->wl_pix->stride         = dri2_buf->dri_buffer->pitch;
+      dri2_surf->wl_pix->driver_private = dri2_buf;
+      dri2_surf->wl_pix->destroy        = dri2_wl_egl_pixmap_destroy;
+      break;
+   default:
+      break;
+   }
+}
+
+static void
+dri2_release_pending_buffer(void *data)
+{
+   struct dri2_egl_surface *dri2_surf = data;
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+
+   /* FIXME: print internal error */
+   if (!dri2_surf->pending_buffer)
+      return;
+   
+   dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
+                                 dri2_surf->pending_buffer);
+   dri2_surf->pending_buffer = NULL;
+}
+
+static void
+dri2_release_buffers(struct dri2_egl_surface *dri2_surf)
+{
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+   int i;
+
+   for (i = 0; i < __DRI_BUFFER_COUNT; ++i) {
+      if (dri2_surf->dri_buffers[i]) {
+         switch (i) {
+         case __DRI_BUFFER_FRONT_LEFT:
+            if (dri2_surf->pending_buffer)
+               force_roundtrip(dri2_dpy->wl_dpy->display);
+            dri2_surf->pending_buffer = dri2_surf->dri_buffers[i];
+            wl_display_sync_callback(dri2_dpy->wl_dpy->display,
+                                     dri2_release_pending_buffer, dri2_surf);
+            break;
+         default:
+            dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
+                                          dri2_surf->dri_buffers[i]);
+            break;
+         }
+         dri2_surf->dri_buffers[i] = NULL;
+      }
+   }
+}
+
+static __DRIbuffer *
+dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
+                            int *width, int *height,
+                            unsigned int *attachments, int count,
+                            int *out_count, void *loaderPrivate)
+{
+   struct dri2_egl_surface *dri2_surf = loaderPrivate;
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+   int i;
+
+   if (dri2_surf->type == DRI2_WINDOW_SURFACE &&
+       (dri2_surf->base.Width != dri2_surf->wl_win->width || 
+        dri2_surf->base.Height != dri2_surf->wl_win->height)) {
+
+      dri2_release_buffers(dri2_surf);
+
+      dri2_surf->base.Width  = dri2_surf->wl_win->width;
+      dri2_surf->base.Height = dri2_surf->wl_win->height;
+      dri2_surf->dx = dri2_surf->wl_win->dx;
+      dri2_surf->dy = dri2_surf->wl_win->dy;
+
+      for (i = 0; i < WL_BUFFER_COUNT; ++i) {
+         if (dri2_surf->wl_drm_buffer[i])
+            wl_buffer_destroy(dri2_surf->wl_drm_buffer[i]);
+         dri2_surf->wl_drm_buffer[i]  = NULL;
+      }
+   }
+
+   dri2_surf->buffer_count = 0;
+   for (i = 0; i < 2*count; i+=2) {
+      assert(attachments[i] < __DRI_BUFFER_COUNT);
+      assert(dri2_surf->buffer_count < 5);
+
+      if (dri2_surf->dri_buffers[attachments[i]] == NULL) {
+
+         dri2_surf->dri_buffers[attachments[i]] =
+            dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
+                  attachments[i], attachments[i+1],
+                  dri2_surf->base.Width, dri2_surf->base.Height);
+
+         if (!dri2_surf->dri_buffers[attachments[i]]) 
+            continue;
+
+         if (attachments[i] == __DRI_BUFFER_FRONT_LEFT)
+            dri2_process_front_buffer(dri2_surf, attachments[i+1]);
+         else if (attachments[i] == __DRI_BUFFER_BACK_LEFT)
+            dri2_process_back_buffer(dri2_surf, attachments[i+1]);
+      }
+
+      memcpy(&dri2_surf->buffers[dri2_surf->buffer_count],
+             dri2_surf->dri_buffers[attachments[i]],
+             sizeof(__DRIbuffer));
+
+      dri2_surf->buffer_count++;
+   }
+
+   assert(dri2_surf->type == DRI2_PIXMAP_SURFACE ||
+          dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]);
+
+   *out_count = dri2_surf->buffer_count;
+   if (dri2_surf->buffer_count == 0)
+          return NULL;
+
+   *width = dri2_surf->base.Width;
+   *height = dri2_surf->base.Height;
+
+   return dri2_surf->buffers;
+}
+
+static __DRIbuffer *
+dri2_get_buffers(__DRIdrawable * driDrawable,
+                int *width, int *height,
+                unsigned int *attachments, int count,
+                int *out_count, void *loaderPrivate)
+{
+   unsigned int *attachments_with_format;
+   __DRIbuffer *buffer;
+   const unsigned int format = 32;
+   int i;
+
+   attachments_with_format = calloc(count * 2, sizeof(unsigned int));
+   if (!attachments_with_format) {
+      *out_count = 0;
+      return NULL;
+   }
+
+   for (i = 0; i < count; ++i) {
+      attachments_with_format[2*i] = attachments[i];
+      attachments_with_format[2*i + 1] = format;
+   }
+
+   buffer =
+      dri2_get_buffers_with_format(driDrawable,
+                                  width, height,
+                                  attachments_with_format, count,
+                                  out_count, loaderPrivate);
+
+   free(attachments_with_format);
+
+   return buffer;
+}
+
+
+static void
+dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
+{
+   (void) driDrawable;
+
+   /* FIXME: Does EGL support front buffer rendering at all? */
+
+#if 0
+   struct dri2_egl_surface *dri2_surf = loaderPrivate;
+
+   dri2WaitGL(dri2_surf);
+#else
+   (void) loaderPrivate;
+#endif
+}
+
+static struct wl_buffer *
+wayland_create_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
+{
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+
+   return wl_drm_create_buffer(dri2_dpy->wl_dpy->drm, buffer->name,
+                               dri2_surf->base.Width, dri2_surf->base.Height,
+                               buffer->pitch, dri2_surf->wl_win->visual);
+}
+
+static void
+wayland_frame_callback(void *data, uint32_t time)
+{
+   struct dri2_egl_surface *dri2_surf = data;
+
+   dri2_surf->block_swap_buffers = EGL_FALSE;
+}
+
+static inline void
+pointer_swap(const void **p1, const void **p2)
+{
+   const void *tmp = *p1;
+   *p1 = *p2;
+   *p2 = tmp;
+}
+
+/**
+ * Called via eglSwapBuffers(), drv->API.SwapBuffers().
+ */
+static EGLBoolean
+dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
+   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
+
+   while (dri2_surf->block_swap_buffers)
+      wl_display_iterate(dri2_dpy->wl_dpy->display, WL_DISPLAY_READABLE);
+
+   dri2_surf->block_swap_buffers = EGL_TRUE;
+   wl_display_frame_callback(dri2_dpy->wl_dpy->display,
+        wayland_frame_callback, dri2_surf);
+
+   if (dri2_surf->type == DRI2_WINDOW_SURFACE) {
+      pointer_swap(
+           (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT],
+           (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]);
+
+      dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]->attachment = 
+        __DRI_BUFFER_FRONT_LEFT;
+      dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->attachment = 
+        __DRI_BUFFER_BACK_LEFT;
+
+      pointer_swap((const void **) &dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT],
+                  (const void **) &dri2_surf->wl_drm_buffer[WL_BUFFER_BACK]);
+
+      if (!dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT])
+        dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT] =
+           wayland_create_buffer(dri2_surf,
+                 dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]);
+
+      wl_surface_attach(dri2_surf->wl_win->surface,
+           dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT],
+           dri2_surf->dx, dri2_surf->dy);
+
+      dri2_surf->wl_win->attached_width  = dri2_surf->base.Width;
+      dri2_surf->wl_win->attached_height = dri2_surf->base.Height;
+      /* reset resize growing parameters */
+      dri2_surf->dx = 0;
+      dri2_surf->dy = 0;
+
+      wl_surface_damage(dri2_surf->wl_win->surface, 0, 0,
+           dri2_surf->base.Width, dri2_surf->base.Height);
+   }
+
+   _EGLContext *ctx;
+   if (dri2_drv->glFlush) {
+      ctx = _eglGetCurrentContext();
+      if (ctx && ctx->DrawSurface == &dri2_surf->base)
+         dri2_drv->glFlush();
+   }
+
+   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
+   (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
+
+   return EGL_TRUE;
+}
+
+/**
+ * Called via eglCreateImageKHR(), drv->API.CreateImageKHR().
+ */
+static _EGLImage *
+dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
+                            EGLClientBuffer buffer, const EGLint *attr_list)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct wl_egl_pixmap *wl_egl_pixmap = (struct wl_egl_pixmap *) buffer;
+   struct dri2_egl_buffer *dri2_buf;
+   EGLint wl_attr_list[] = {
+               EGL_WIDTH,              0,
+               EGL_HEIGHT,             0,
+               EGL_DRM_BUFFER_STRIDE_MESA,     0,
+               EGL_DRM_BUFFER_FORMAT_MESA,     EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
+               EGL_NONE
+   };
+
+   dri2_buf = malloc(sizeof *dri2_buf);
+   if (!dri2_buf)
+           return NULL;
+
+   dri2_buf->dri2_dpy = dri2_dpy;
+   dri2_buf->dri_buffer =
+      dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
+                                    __DRI_BUFFER_FRONT_LEFT, 32,
+                                    wl_egl_pixmap->width,
+                                    wl_egl_pixmap->height);
+
+   wl_egl_pixmap->name    = dri2_buf->dri_buffer->name;
+   wl_egl_pixmap->stride  = dri2_buf->dri_buffer->pitch;
+   wl_egl_pixmap->destroy = dri2_wl_egl_pixmap_destroy;
+   wl_egl_pixmap->driver_private = dri2_buf;
+
+   wl_attr_list[1] = wl_egl_pixmap->width;
+   wl_attr_list[3] = wl_egl_pixmap->height;
+   wl_attr_list[5] = wl_egl_pixmap->stride / 4;
+
+
+   return dri2_create_image_khr(disp->Driver, disp, ctx, EGL_DRM_BUFFER_MESA,
+              (EGLClientBuffer)(intptr_t) wl_egl_pixmap->name, wl_attr_list);
+}
+
+static _EGLImage *
+dri2_wayland_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
+                             _EGLContext *ctx, EGLenum target,
+                             EGLClientBuffer buffer, const EGLint *attr_list)
+{
+   (void) drv;
+
+   switch (target) {
+   case EGL_NATIVE_PIXMAP_KHR:
+      return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
+   default:
+      return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
+   }
+}
+
+/**
+ * Called via eglTerminate(), drv->API.Terminate().
+ */
+static EGLBoolean
+dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+   _eglReleaseDisplayResources(drv, disp);
+   _eglCleanupDisplay(disp);
+
+   dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
+   close(dri2_dpy->fd);
+   dlclose(dri2_dpy->driver);
+   free(dri2_dpy->driver_name);
+   free(dri2_dpy);
+   disp->DriverData = NULL;
+
+   return EGL_TRUE;
+}
+
+EGLBoolean
+dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
+{
+   struct dri2_egl_display *dri2_dpy;
+   int i;
+
+   drv->API.CreateWindowSurface = dri2_create_window_surface;
+   drv->API.CreatePixmapSurface = dri2_create_pixmap_surface;
+   drv->API.DestroySurface = dri2_destroy_surface;
+   drv->API.SwapBuffers = dri2_swap_buffers;
+   drv->API.CreateImageKHR = dri2_wayland_create_image_khr;
+   drv->API.Terminate = dri2_terminate;
+
+   dri2_dpy = malloc(sizeof *dri2_dpy);
+   if (!dri2_dpy)
+      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
+
+   memset(dri2_dpy, 0, sizeof *dri2_dpy);
+
+   disp->DriverData = (void *) dri2_dpy;
+   dri2_dpy->wl_dpy = disp->PlatformDisplay;
+
+   if (dri2_dpy->wl_dpy->fd == -1)
+      force_roundtrip(dri2_dpy->wl_dpy->display);
+   if (dri2_dpy->wl_dpy->fd == -1)
+      goto cleanup_dpy;
+
+   dri2_dpy->fd = dup(dri2_dpy->wl_dpy->fd);
+   if (dri2_dpy->fd < 0) {
+      _eglError(EGL_BAD_ALLOC, "DRI2: failed to dup fd");
+      goto cleanup_dpy;
+   }
+
+   if (!dri2_dpy->wl_dpy->authenticated)
+      force_roundtrip(dri2_dpy->wl_dpy->display);
+   if (!dri2_dpy->wl_dpy->authenticated)
+      goto cleanup_dpy;
+
+   dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd);
+   if (dri2_dpy->driver_name == NULL) {
+      _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name");
+      goto cleanup_fd;
+   }
+
+   if (!dri2_load_driver(disp))
+      goto cleanup_driver_name;
+
+   dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
+   dri2_dpy->dri2_loader_extension.base.version = 3;
+   dri2_dpy->dri2_loader_extension.getBuffers = dri2_get_buffers;
+   dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_flush_front_buffer;
+   dri2_dpy->dri2_loader_extension.getBuffersWithFormat =
+      dri2_get_buffers_with_format;
+      
+   dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base;
+   dri2_dpy->extensions[1] = &image_lookup_extension.base;
+   dri2_dpy->extensions[2] = NULL;
+
+   if (!dri2_create_screen(disp))
+      goto cleanup_driver;
+
+   for (i = 0; dri2_dpy->driver_configs[i]; i++)
+      dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0,
+                     EGL_WINDOW_BIT | EGL_PIXMAP_BIT, NULL);
+
+
+   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;
+   disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
+
+   /* we're supporting EGL 1.4 */
+   disp->VersionMajor = 1;
+   disp->VersionMinor = 4;
+
+   return EGL_TRUE;
+
+ cleanup_driver:
+   dlclose(dri2_dpy->driver);
+ cleanup_driver_name:
+   free(dri2_dpy->driver_name);
+ cleanup_fd:
+   close(dri2_dpy->fd);
+ cleanup_dpy:
+   free(dri2_dpy);
+   
+   return EGL_FALSE;
+}
diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c
new file mode 100644 (file)
index 0000000..50310ee
--- /dev/null
@@ -0,0 +1,1058 @@
+/*
+ * Copyright © 2011 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:
+ *    Kristian Høgsberg <krh@bitplanet.net>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <limits.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <xf86drm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "egl_dri2.h"
+
+static void
+swrastCreateDrawable(struct dri2_egl_display * dri2_dpy,
+                     struct dri2_egl_surface * dri2_surf,
+                     int depth)
+{
+   uint32_t           mask;
+   const uint32_t     function = GXcopy;
+   uint32_t           valgc[2];
+   
+   /* create GC's */
+   dri2_surf->gc = xcb_generate_id(dri2_dpy->conn);
+   mask = XCB_GC_FUNCTION;
+   xcb_create_gc(dri2_dpy->conn, dri2_surf->gc, dri2_surf->drawable, mask, &function);
+
+   dri2_surf->swapgc = xcb_generate_id(dri2_dpy->conn);
+   mask = XCB_GC_FUNCTION | XCB_GC_GRAPHICS_EXPOSURES;
+   valgc[0] = function;
+   valgc[1] = False;
+   xcb_create_gc(dri2_dpy->conn, dri2_surf->swapgc, dri2_surf->drawable, mask, valgc);
+   dri2_surf->depth = depth;
+   switch (depth) {
+      case 32:
+      case 24:
+         dri2_surf->bytes_per_pixel = 4;
+         break;
+      case 16:
+         dri2_surf->bytes_per_pixel = 2;
+         break;
+      case 8:
+         dri2_surf->bytes_per_pixel = 1;
+         break;
+      case 0:
+         dri2_surf->bytes_per_pixel = 0;
+         break;
+      default:
+         _eglLog(_EGL_WARNING, "unsupported depth %d", depth);
+   }
+}
+
+static void
+swrastDestroyDrawable(struct dri2_egl_display * dri2_dpy,
+                      struct dri2_egl_surface * dri2_surf)
+{
+   xcb_free_gc(dri2_dpy->conn, dri2_surf->gc);
+   xcb_free_gc(dri2_dpy->conn, dri2_surf->swapgc);
+}
+
+static void
+swrastGetDrawableInfo(__DRIdrawable * draw,
+                      int *x, int *y, int *w, int *h,
+                      void *loaderPrivate)
+{
+   struct dri2_egl_surface *dri2_surf = loaderPrivate;
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
+
+   xcb_get_geometry_cookie_t cookie;
+   xcb_get_geometry_reply_t *reply;
+   xcb_generic_error_t *error;
+
+   *w = *h = 0;
+   cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
+   reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
+   if (reply == NULL)
+      return;
+
+   if (error != NULL) {
+      _eglLog(_EGL_WARNING, "error in xcb_get_geometry");
+      free(error);
+   } else {
+      *w = reply->width;
+      *h = reply->height;
+   }
+   free(reply);
+}
+
+static void
+swrastPutImage(__DRIdrawable * draw, int op,
+               int x, int y, int w, int h,
+               char *data, void *loaderPrivate)
+{
+   struct dri2_egl_surface *dri2_surf = loaderPrivate;
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
+
+   xcb_gcontext_t gc;
+
+   switch (op) {
+   case __DRI_SWRAST_IMAGE_OP_DRAW:
+      gc = dri2_surf->gc;
+      break;
+   case __DRI_SWRAST_IMAGE_OP_SWAP:
+      gc = dri2_surf->swapgc;
+      break;
+   default:
+      return;
+   }
+
+   xcb_put_image(dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, dri2_surf->drawable,
+                 gc, w, h, x, y, 0, dri2_surf->depth,
+                 w*h*dri2_surf->bytes_per_pixel, (const uint8_t *)data);
+}
+
+static void
+swrastGetImage(__DRIdrawable * read,
+               int x, int y, int w, int h,
+               char *data, void *loaderPrivate)
+{
+   struct dri2_egl_surface *dri2_surf = loaderPrivate;
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
+
+   xcb_get_image_cookie_t cookie;
+   xcb_get_image_reply_t *reply;
+   xcb_generic_error_t *error;
+
+   cookie = xcb_get_image (dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
+                           dri2_surf->drawable, x, y, w, h, ~0);
+   reply = xcb_get_image_reply (dri2_dpy->conn, cookie, &error);
+   if (reply == NULL)
+      return;
+
+   if (error != NULL) {
+      _eglLog(_EGL_WARNING, "error in xcb_get_image");
+      free(error);
+   } else {
+      uint32_t bytes = xcb_get_image_data_length(reply);
+      uint8_t *idata = xcb_get_image_data(reply);
+      memcpy(data, idata, bytes);
+   }
+   free(reply);
+}
+
+
+/**
+ * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
+ */
+static _EGLSurface *
+dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
+                   _EGLConfig *conf, EGLNativeWindowType window,
+                   const EGLint *attrib_list)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
+   struct dri2_egl_surface *dri2_surf;
+   xcb_get_geometry_cookie_t cookie;
+   xcb_get_geometry_reply_t *reply;
+   xcb_screen_iterator_t s;
+   xcb_generic_error_t *error;
+
+   (void) drv;
+
+   dri2_surf = malloc(sizeof *dri2_surf);
+   if (!dri2_surf) {
+      _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
+      return NULL;
+   }
+   
+   if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
+      goto cleanup_surf;
+
+   dri2_surf->region = XCB_NONE;
+   if (type == EGL_PBUFFER_BIT) {
+      dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn);
+      s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
+      xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize,
+                       dri2_surf->drawable, s.data->root,
+                       dri2_surf->base.Width, dri2_surf->base.Height);
+   } else {
+      dri2_surf->drawable = window;
+   }
+
+   if (dri2_dpy->dri2) {
+      dri2_surf->dri_drawable = 
+        (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
+                                              type == EGL_WINDOW_BIT ?
+                                              dri2_conf->dri_double_config : 
+                                              dri2_conf->dri_single_config,
+                                              dri2_surf);
+   } else {
+      assert(dri2_dpy->swrast);
+      dri2_surf->dri_drawable = 
+        (*dri2_dpy->swrast->createNewDrawable) (dri2_dpy->dri_screen,
+                                                dri2_conf->dri_double_config,
+                                                dri2_surf);
+   }
+
+   if (dri2_surf->dri_drawable == NULL) {
+      _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
+      goto cleanup_pixmap;
+   }
+   
+   if (dri2_dpy->dri2) {
+      xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable);
+   } else {
+      swrastCreateDrawable(dri2_dpy, dri2_surf, _eglGetConfigKey(conf, EGL_DEPTH_SIZE));
+   }
+
+   if (type != EGL_PBUFFER_BIT) {
+      cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
+      reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
+      if (reply == NULL || error != NULL) {
+        _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
+        free(error);
+        goto cleanup_dri_drawable;
+      }
+
+      dri2_surf->base.Width = reply->width;
+      dri2_surf->base.Height = reply->height;
+      free(reply);
+   }
+
+   return &dri2_surf->base;
+
+ cleanup_dri_drawable:
+   dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
+ cleanup_pixmap:
+   if (type == EGL_PBUFFER_BIT)
+      xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable);
+ cleanup_surf:
+   free(dri2_surf);
+
+   return NULL;
+}
+
+/**
+ * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
+ */
+static _EGLSurface *
+dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
+                          _EGLConfig *conf, EGLNativeWindowType window,
+                          const EGLint *attrib_list)
+{
+   return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
+                             window, attrib_list);
+}
+
+static _EGLSurface *
+dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
+                          _EGLConfig *conf, EGLNativePixmapType pixmap,
+                          const EGLint *attrib_list)
+{
+   return dri2_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
+                             pixmap, attrib_list);
+}
+
+static _EGLSurface *
+dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
+                           _EGLConfig *conf, const EGLint *attrib_list)
+{
+   return dri2_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
+                             XCB_WINDOW_NONE, attrib_list);
+}
+
+static EGLBoolean
+dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
+
+   (void) drv;
+
+   if (!_eglPutSurface(surf))
+      return EGL_TRUE;
+
+   (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
+   
+   if (dri2_dpy->dri2) {
+      xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable);
+   } else {
+      assert(dri2_dpy->swrast);
+      swrastDestroyDrawable(dri2_dpy, dri2_surf);
+   }
+
+   if (surf->Type == EGL_PBUFFER_BIT)
+      xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable);
+
+   free(surf);
+
+   return EGL_TRUE;
+}
+
+/**
+ * Process list of buffer received from the server
+ *
+ * Processes the list of buffers received in a reply from the server to either
+ * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
+ */
+static void
+dri2_process_buffers(struct dri2_egl_surface *dri2_surf,
+                    xcb_dri2_dri2_buffer_t *buffers, unsigned count)
+{
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+   xcb_rectangle_t rectangle;
+   unsigned i;
+
+   dri2_surf->buffer_count = count;
+   dri2_surf->have_fake_front = 0;
+
+   /* This assumes the DRI2 buffer attachment tokens matches the
+    * __DRIbuffer tokens. */
+   for (i = 0; i < count; i++) {
+      dri2_surf->buffers[i].attachment = buffers[i].attachment;
+      dri2_surf->buffers[i].name = buffers[i].name;
+      dri2_surf->buffers[i].pitch = buffers[i].pitch;
+      dri2_surf->buffers[i].cpp = buffers[i].cpp;
+      dri2_surf->buffers[i].flags = buffers[i].flags;
+
+      /* We only use the DRI drivers single buffer configs.  This
+       * means that if we try to render to a window, DRI2 will give us
+       * the fake front buffer, which we'll use as a back buffer.
+       * Note that EGL doesn't require that several clients rendering
+       * to the same window must see the same aux buffers. */
+      if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
+         dri2_surf->have_fake_front = 1;
+   }
+
+   if (dri2_surf->region != XCB_NONE)
+      xcb_xfixes_destroy_region(dri2_dpy->conn, dri2_surf->region);
+
+   rectangle.x = 0;
+   rectangle.y = 0;
+   rectangle.width = dri2_surf->base.Width;
+   rectangle.height = dri2_surf->base.Height;
+   dri2_surf->region = xcb_generate_id(dri2_dpy->conn);
+   xcb_xfixes_create_region(dri2_dpy->conn, dri2_surf->region, 1, &rectangle);
+}
+
+static __DRIbuffer *
+dri2_get_buffers(__DRIdrawable * driDrawable,
+               int *width, int *height,
+               unsigned int *attachments, int count,
+               int *out_count, void *loaderPrivate)
+{
+   struct dri2_egl_surface *dri2_surf = loaderPrivate;
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+   xcb_dri2_dri2_buffer_t *buffers;
+   xcb_dri2_get_buffers_reply_t *reply;
+   xcb_dri2_get_buffers_cookie_t cookie;
+
+   (void) driDrawable;
+
+   cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
+                                           dri2_surf->drawable,
+                                           count, count, attachments);
+   reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, cookie, NULL);
+   buffers = xcb_dri2_get_buffers_buffers (reply);
+   if (buffers == NULL)
+      return NULL;
+
+   *out_count = reply->count;
+   dri2_surf->base.Width = *width = reply->width;
+   dri2_surf->base.Height = *height = reply->height;
+   dri2_process_buffers(dri2_surf, buffers, *out_count);
+
+   free(reply);
+
+   return dri2_surf->buffers;
+}
+
+static __DRIbuffer *
+dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
+                            int *width, int *height,
+                            unsigned int *attachments, int count,
+                            int *out_count, void *loaderPrivate)
+{
+   struct dri2_egl_surface *dri2_surf = loaderPrivate;
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+   xcb_dri2_dri2_buffer_t *buffers;
+   xcb_dri2_get_buffers_with_format_reply_t *reply;
+   xcb_dri2_get_buffers_with_format_cookie_t cookie;
+   xcb_dri2_attach_format_t *format_attachments;
+
+   (void) driDrawable;
+
+   format_attachments = (xcb_dri2_attach_format_t *) attachments;
+   cookie = xcb_dri2_get_buffers_with_format_unchecked (dri2_dpy->conn,
+                                                       dri2_surf->drawable,
+                                                       count, count,
+                                                       format_attachments);
+
+   reply = xcb_dri2_get_buffers_with_format_reply (dri2_dpy->conn,
+                                                  cookie, NULL);
+   if (reply == NULL)
+      return NULL;
+
+   buffers = xcb_dri2_get_buffers_with_format_buffers (reply);
+   dri2_surf->base.Width = *width = reply->width;
+   dri2_surf->base.Height = *height = reply->height;
+   *out_count = reply->count;
+   dri2_process_buffers(dri2_surf, buffers, *out_count);
+
+   free(reply);
+
+   return dri2_surf->buffers;
+}
+
+static void
+dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
+{
+   (void) driDrawable;
+
+   /* FIXME: Does EGL support front buffer rendering at all? */
+
+#if 0
+   struct dri2_egl_surface *dri2_surf = loaderPrivate;
+
+   dri2WaitGL(dri2_surf);
+#else
+   (void) loaderPrivate;
+#endif
+}
+
+static char *
+dri2_strndup(const char *s, int length)
+{
+   char *d;
+
+   d = malloc(length + 1);
+   if (d == NULL)
+      return NULL;
+
+   memcpy(d, s, length);
+   d[length] = '\0';
+
+   return d;
+}
+
+static EGLBoolean
+dri2_connect(struct dri2_egl_display *dri2_dpy)
+{
+   xcb_xfixes_query_version_reply_t *xfixes_query;
+   xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
+   xcb_dri2_query_version_reply_t *dri2_query;
+   xcb_dri2_query_version_cookie_t dri2_query_cookie;
+   xcb_dri2_connect_reply_t *connect;
+   xcb_dri2_connect_cookie_t connect_cookie;
+   xcb_generic_error_t *error;
+   xcb_screen_iterator_t s;
+
+   xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id);
+   xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id);
+
+   xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn,
+                                                 XCB_XFIXES_MAJOR_VERSION,
+                                                 XCB_XFIXES_MINOR_VERSION);
+
+   dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->conn,
+                                              XCB_DRI2_MAJOR_VERSION,
+                                              XCB_DRI2_MINOR_VERSION);
+
+   s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
+   connect_cookie = xcb_dri2_connect_unchecked (dri2_dpy->conn,
+                                               s.data->root,
+                                               XCB_DRI2_DRIVER_TYPE_DRI);
+
+   xfixes_query =
+      xcb_xfixes_query_version_reply (dri2_dpy->conn,
+                                     xfixes_query_cookie, &error);
+   if (xfixes_query == NULL ||
+       error != NULL || xfixes_query->major_version < 2) {
+      _eglLog(_EGL_WARNING, "DRI2: failed to query xfixes version");
+      free(error);
+      return EGL_FALSE;
+   }
+   free(xfixes_query);
+
+   dri2_query =
+      xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error);
+   if (dri2_query == NULL || error != NULL) {
+      _eglLog(_EGL_WARNING, "DRI2: failed to query version");
+      free(error);
+      return EGL_FALSE;
+   }
+   dri2_dpy->dri2_major = dri2_query->major_version;
+   dri2_dpy->dri2_minor = dri2_query->minor_version;
+   free(dri2_query);
+
+   connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL);
+   if (connect == NULL ||
+       connect->driver_name_length + connect->device_name_length == 0) {
+      _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
+      return EGL_FALSE;
+   }
+
+   dri2_dpy->device_name =
+      dri2_strndup(xcb_dri2_connect_device_name (connect),
+                  xcb_dri2_connect_device_name_length (connect));
+
+   dri2_dpy->driver_name =
+      dri2_strndup(xcb_dri2_connect_driver_name (connect),
+                  xcb_dri2_connect_driver_name_length (connect));
+
+   if (dri2_dpy->device_name == NULL || dri2_dpy->driver_name == NULL) {
+      free(dri2_dpy->device_name);
+      free(dri2_dpy->driver_name);
+      free(connect);
+      return EGL_FALSE;
+   }
+   free(connect);
+
+   return EGL_TRUE;
+}
+
+static EGLBoolean
+dri2_authenticate(struct dri2_egl_display *dri2_dpy)
+{
+   xcb_dri2_authenticate_reply_t *authenticate;
+   xcb_dri2_authenticate_cookie_t authenticate_cookie;
+   xcb_screen_iterator_t s;
+   drm_magic_t magic;
+
+   if (drmGetMagic(dri2_dpy->fd, &magic)) {
+      _eglLog(_EGL_WARNING, "DRI2: failed to get drm magic");
+      return EGL_FALSE;
+   }
+
+   s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
+   authenticate_cookie =
+      xcb_dri2_authenticate_unchecked(dri2_dpy->conn, s.data->root, magic);
+   authenticate =
+      xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL);
+   if (authenticate == NULL || !authenticate->authenticated) {
+      _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
+      free(authenticate);
+      return EGL_FALSE;
+   }
+
+   free(authenticate);
+
+   return EGL_TRUE;
+}
+
+static EGLBoolean
+dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
+                            _EGLDisplay *disp)
+{
+   xcb_screen_iterator_t s;
+   xcb_depth_iterator_t d;
+   xcb_visualtype_t *visuals;
+   int i, j, id;
+   EGLint surface_type;
+   EGLint config_attrs[] = {
+          EGL_NATIVE_VISUAL_ID,   0,
+          EGL_NATIVE_VISUAL_TYPE, 0,
+          EGL_NONE
+   };
+
+   s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
+   d = xcb_screen_allowed_depths_iterator(s.data);
+   id = 1;
+
+   surface_type =
+      EGL_WINDOW_BIT |
+      EGL_PIXMAP_BIT |
+      EGL_PBUFFER_BIT |
+      EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+
+   while (d.rem > 0) {
+      EGLBoolean class_added[6] = { 0, };
+
+      visuals = xcb_depth_visuals(d.data);
+      for (i = 0; i < xcb_depth_visuals_length(d.data); i++) {
+        if (class_added[visuals[i]._class])
+           continue;
+
+        class_added[visuals[i]._class] = EGL_TRUE;
+        for (j = 0; dri2_dpy->driver_configs[j]; j++) {
+            config_attrs[1] = visuals[i].visual_id;
+            config_attrs[3] = visuals[i]._class;
+
+           dri2_add_config(disp, dri2_dpy->driver_configs[j], id++,
+                           d.data->depth, surface_type, config_attrs);
+        }
+      }
+
+      xcb_depth_next(&d);
+   }
+
+   if (!_eglGetArraySize(disp->Configs)) {
+      _eglLog(_EGL_WARNING, "DRI2: failed to create any config");
+      return EGL_FALSE;
+   }
+
+   return EGL_TRUE;
+}
+
+static EGLBoolean
+dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp,
+                _EGLSurface *draw, xcb_xfixes_region_t region)
+{
+   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
+   _EGLContext *ctx;
+   enum xcb_dri2_attachment_t render_attachment;
+   xcb_dri2_copy_region_cookie_t cookie;
+
+   if (dri2_drv->glFlush) {
+      ctx = _eglGetCurrentContext();
+      if (ctx && ctx->DrawSurface == &dri2_surf->base)
+         dri2_drv->glFlush();
+   }
+
+   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
+
+#if 0
+   /* FIXME: Add support for dri swapbuffers, that'll give us swap
+    * interval and page flipping (at least for fullscreen windows) as
+    * well as the page flip event.  Unless surface->SwapBehavior is
+    * EGL_BUFFER_PRESERVED. */
+#if __DRI2_FLUSH_VERSION >= 2
+   if (pdraw->psc->f)
+      (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable);
+#endif
+#endif
+
+   if (dri2_surf->have_fake_front)
+      render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT;
+   else
+      render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT;
+
+   cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->conn,
+                                          dri2_surf->drawable,
+                                          region,
+                                          XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
+                                          render_attachment);
+   free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL));
+
+   return EGL_TRUE;
+}
+
+static EGLBoolean
+dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
+
+   if (dri2_dpy->dri2) { 
+      return dri2_copy_region(drv, disp, draw, dri2_surf->region);
+   } else {
+      assert(dri2_dpy->swrast);
+     
+      dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable);
+      return EGL_TRUE;
+   }
+}
+
+static EGLBoolean
+dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
+                        EGLint numRects, const EGLint *rects)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
+   EGLBoolean ret;
+   xcb_xfixes_region_t region;
+   xcb_rectangle_t rectangles[16];
+   int i;
+
+   if (numRects > (int)ARRAY_SIZE(rectangles))
+      return dri2_copy_region(drv, disp, draw, dri2_surf->region);
+
+   /* FIXME: Invert y here? */
+   for (i = 0; i < numRects; i++) {
+      rectangles[i].x = rects[i * 4];
+      rectangles[i].y = rects[i * 4 + 1];
+      rectangles[i].width = rects[i * 4 + 2];
+      rectangles[i].height = rects[i * 4 + 3];
+   }
+
+   region = xcb_generate_id(dri2_dpy->conn);
+   xcb_xfixes_create_region(dri2_dpy->conn, region, numRects, rectangles);
+   ret = dri2_copy_region(drv, disp, draw, region);
+   xcb_xfixes_destroy_region(dri2_dpy->conn, region);
+
+   return ret;
+}
+
+static EGLBoolean
+dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
+                 EGLNativePixmapType target)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
+   xcb_gcontext_t gc;
+
+   (void) drv;
+
+   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
+
+   gc = xcb_generate_id(dri2_dpy->conn);
+   xcb_create_gc(dri2_dpy->conn, gc, target, 0, NULL);
+   xcb_copy_area(dri2_dpy->conn,
+                 dri2_surf->drawable,
+                 target,
+                 gc,
+                 0, 0,
+                 0, 0,
+                 dri2_surf->base.Width,
+                 dri2_surf->base.Height);
+   xcb_free_gc(dri2_dpy->conn, gc);
+
+   return EGL_TRUE;
+}
+
+static _EGLImage *
+dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
+                            EGLClientBuffer buffer, const EGLint *attr_list)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_image *dri2_img;
+   unsigned int attachments[1];
+   xcb_drawable_t drawable;
+   xcb_dri2_get_buffers_cookie_t buffers_cookie;
+   xcb_dri2_get_buffers_reply_t *buffers_reply;
+   xcb_dri2_dri2_buffer_t *buffers;
+   xcb_get_geometry_cookie_t geometry_cookie;
+   xcb_get_geometry_reply_t *geometry_reply;
+   xcb_generic_error_t *error;
+   int stride, format;
+
+   (void) ctx;
+
+   drawable = (xcb_drawable_t) buffer;
+   xcb_dri2_create_drawable (dri2_dpy->conn, drawable);
+   attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT;
+   buffers_cookie =
+      xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
+                                     drawable, 1, 1, attachments);
+   geometry_cookie = xcb_get_geometry (dri2_dpy->conn, drawable);
+   buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn,
+                                              buffers_cookie, NULL);
+   buffers = xcb_dri2_get_buffers_buffers (buffers_reply);
+   if (buffers == NULL) {
+      return NULL;
+   }
+
+   geometry_reply = xcb_get_geometry_reply (dri2_dpy->conn,
+                                           geometry_cookie, &error);
+   if (geometry_reply == NULL || error != NULL) {
+      _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
+      free(error);
+      free(buffers_reply);
+      return NULL;
+   }
+
+   switch (geometry_reply->depth) {
+   case 16:
+      format = __DRI_IMAGE_FORMAT_RGB565;
+      break;
+   case 24:
+      format = __DRI_IMAGE_FORMAT_XRGB8888;
+      break;
+   case 32:
+      format = __DRI_IMAGE_FORMAT_ARGB8888;
+      break;
+   default:
+      _eglError(EGL_BAD_PARAMETER,
+               "dri2_create_image_khr: unsupported pixmap depth");
+      free(buffers_reply);
+      free(geometry_reply);
+      return NULL;
+   }
+
+   dri2_img = malloc(sizeof *dri2_img);
+   if (!dri2_img) {
+      free(buffers_reply);
+      free(geometry_reply);
+      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
+      return EGL_NO_IMAGE_KHR;
+   }
+
+   if (!_eglInitImage(&dri2_img->base, disp)) {
+      free(buffers_reply);
+      free(geometry_reply);
+      return EGL_NO_IMAGE_KHR;
+   }
+
+   stride = buffers[0].pitch / buffers[0].cpp;
+   dri2_img->dri_image =
+      dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
+                                          buffers_reply->width,
+                                          buffers_reply->height,
+                                          format,
+                                          buffers[0].name,
+                                          stride,
+                                          dri2_img);
+
+   free(buffers_reply);
+   free(geometry_reply);
+
+   return &dri2_img->base;
+}
+
+static _EGLImage *
+dri2_x11_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
+                         _EGLContext *ctx, EGLenum target,
+                         EGLClientBuffer buffer, const EGLint *attr_list)
+{
+   (void) drv;
+
+   switch (target) {
+   case EGL_NATIVE_PIXMAP_KHR:
+      return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
+   default:
+      return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
+   }
+}
+
+static EGLBoolean
+dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp)
+{
+   struct dri2_egl_display *dri2_dpy;
+
+   drv->API.CreateWindowSurface = dri2_create_window_surface;
+   drv->API.CreatePixmapSurface = dri2_create_pixmap_surface;
+   drv->API.CreatePbufferSurface = dri2_create_pbuffer_surface;
+   drv->API.DestroySurface = dri2_destroy_surface;
+   drv->API.SwapBuffers = dri2_swap_buffers;
+   drv->API.CopyBuffers = dri2_copy_buffers;
+
+   drv->API.SwapBuffersRegionNOK = NULL;
+   drv->API.CreateImageKHR  = NULL;
+   drv->API.DestroyImageKHR = NULL;
+   drv->API.CreateDRMImageMESA = NULL;
+   drv->API.ExportDRMImageMESA = NULL;
+
+   dri2_dpy = malloc(sizeof *dri2_dpy);
+   if (!dri2_dpy)
+      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
+
+   memset(dri2_dpy, 0, sizeof *dri2_dpy);
+
+   disp->DriverData = (void *) dri2_dpy;
+   if (disp->PlatformDisplay == NULL) {
+      dri2_dpy->conn = xcb_connect(0, 0);
+   } else {
+      dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay);
+   }
+
+   if (xcb_connection_has_error(dri2_dpy->conn)) {
+      _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed");
+      goto cleanup_dpy;
+   }
+
+   dri2_dpy->driver_name = dri2_strndup("swrast", strlen("swrast"));
+
+   if (!dri2_load_driver(disp))
+      goto cleanup_conn;
+
+   dri2_dpy->swrast_loader_extension.base.name = __DRI_SWRAST_LOADER;
+   dri2_dpy->swrast_loader_extension.base.version = __DRI_SWRAST_LOADER_VERSION;
+   dri2_dpy->swrast_loader_extension.getDrawableInfo = swrastGetDrawableInfo;
+   dri2_dpy->swrast_loader_extension.putImage = swrastPutImage;
+   dri2_dpy->swrast_loader_extension.getImage = swrastGetImage;
+
+   dri2_dpy->extensions[0] = &dri2_dpy->swrast_loader_extension.base;
+   dri2_dpy->extensions[1] = NULL;
+   dri2_dpy->extensions[2] = NULL;
+
+   if (!dri2_create_screen(disp))
+      goto cleanup_driver;
+
+   if (dri2_dpy->conn) {
+      if (!dri2_add_configs_for_visuals(dri2_dpy, disp))
+         goto cleanup_configs;
+   }
+
+   /* we're supporting EGL 1.4 */
+   disp->VersionMajor = 1;
+   disp->VersionMinor = 4;
+
+   return EGL_TRUE;
+
+ cleanup_configs:
+   _eglCleanupDisplay(disp);
+   dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
+ cleanup_driver:
+   dlclose(dri2_dpy->driver);
+ cleanup_conn:
+   if (disp->PlatformDisplay == NULL)
+      xcb_disconnect(dri2_dpy->conn);
+ cleanup_dpy:
+   free(dri2_dpy);
+
+   return EGL_FALSE;
+}
+
+
+static EGLBoolean
+dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
+{
+   struct dri2_egl_display *dri2_dpy;
+
+   drv->API.CreateWindowSurface = dri2_create_window_surface;
+   drv->API.CreatePixmapSurface = dri2_create_pixmap_surface;
+   drv->API.CreatePbufferSurface = dri2_create_pbuffer_surface;
+   drv->API.DestroySurface = dri2_destroy_surface;
+   drv->API.SwapBuffers = dri2_swap_buffers;
+   drv->API.CopyBuffers = dri2_copy_buffers;
+   drv->API.CreateImageKHR = dri2_x11_create_image_khr;
+   drv->API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
+
+   dri2_dpy = malloc(sizeof *dri2_dpy);
+   if (!dri2_dpy)
+      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
+
+   memset(dri2_dpy, 0, sizeof *dri2_dpy);
+
+   disp->DriverData = (void *) dri2_dpy;
+   if (disp->PlatformDisplay == NULL) {
+      dri2_dpy->conn = xcb_connect(0, 0);
+   } else {
+      dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay);
+   }
+
+   if (xcb_connection_has_error(dri2_dpy->conn)) {
+      _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed");
+      goto cleanup_dpy;
+   }
+
+   if (dri2_dpy->conn) {
+      if (!dri2_connect(dri2_dpy))
+        goto cleanup_conn;
+   }
+
+   if (!dri2_load_driver(disp))
+      goto cleanup_conn;
+
+   dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR);
+   if (dri2_dpy->fd == -1) {
+      _eglLog(_EGL_WARNING,
+             "DRI2: could not open %s (%s)", dri2_dpy->device_name,
+              strerror(errno));
+      goto cleanup_driver;
+   }
+
+   if (dri2_dpy->conn) {
+      if (!dri2_authenticate(dri2_dpy))
+        goto cleanup_fd;
+   }
+
+   if (dri2_dpy->dri2_minor >= 1) {
+      dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
+      dri2_dpy->dri2_loader_extension.base.version = 3;
+      dri2_dpy->dri2_loader_extension.getBuffers = dri2_get_buffers;
+      dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_flush_front_buffer;
+      dri2_dpy->dri2_loader_extension.getBuffersWithFormat =
+        dri2_get_buffers_with_format;
+   } else {
+      dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
+      dri2_dpy->dri2_loader_extension.base.version = 2;
+      dri2_dpy->dri2_loader_extension.getBuffers = dri2_get_buffers;
+      dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_flush_front_buffer;
+      dri2_dpy->dri2_loader_extension.getBuffersWithFormat = NULL;
+   }
+      
+   dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base;
+   dri2_dpy->extensions[1] = &image_lookup_extension.base;
+   dri2_dpy->extensions[2] = NULL;
+
+   if (!dri2_create_screen(disp))
+      goto cleanup_fd;
+
+   if (dri2_dpy->conn) {
+      if (!dri2_add_configs_for_visuals(dri2_dpy, 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;
+   disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
+   disp->Extensions.NOK_swap_region = EGL_TRUE;
+   disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
+
+   /* we're supporting EGL 1.4 */
+   disp->VersionMajor = 1;
+   disp->VersionMinor = 4;
+
+   return EGL_TRUE;
+
+ cleanup_configs:
+   _eglCleanupDisplay(disp);
+   dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
+ cleanup_fd:
+   close(dri2_dpy->fd);
+ cleanup_driver:
+   dlclose(dri2_dpy->driver);
+ cleanup_conn:
+   if (disp->PlatformDisplay == NULL)
+      xcb_disconnect(dri2_dpy->conn);
+ cleanup_dpy:
+   free(dri2_dpy);
+
+   return EGL_FALSE;
+}
+
+EGLBoolean
+dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp)
+{
+   EGLBoolean initialized = EGL_TRUE;
+
+   int x11_dri2_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
+
+   if (x11_dri2_accel) {
+      if (!dri2_initialize_x11_dri2(drv, disp)) {
+         initialized = dri2_initialize_x11_swrast(drv, disp);
+      }
+   } else {
+      initialized = dri2_initialize_x11_swrast(drv, disp);
+   }
+
+   return initialized;
+}
+
index c710631688cbcadd549beb220315ec73b8d73bf7..a5b929950205beaf4df4b49a9311145f9afc44ab 100644 (file)
@@ -58,7 +58,7 @@ LOCAL_LIBS =
 ifeq ($(filter dri2, $(EGL_DRIVERS_DIRS)),dri2)
 LOCAL_CFLAGS += -D_EGL_BUILT_IN_DRIVER_DRI2
 LOCAL_LIBS += $(TOP)/src/egl/drivers/dri2/libegl_dri2.a
-EGL_LIB_DEPS += $(XCB_DRI2_LIBS) $(LIBUDEV_LIBS) $(DLOPEN_LIBS) $(LIBDRM_LIB)
+EGL_LIB_DEPS += $(XCB_DRI2_LIBS) $(LIBUDEV_LIBS) $(DLOPEN_LIBS) $(LIBDRM_LIB) $(WAYLAND_LIBS)
 endif
 ifeq ($(filter glx, $(EGL_DRIVERS_DIRS)),glx)
 LOCAL_CFLAGS += -D_EGL_BUILT_IN_DRIVER_GLX
@@ -71,6 +71,9 @@ EGL_NATIVE_PLATFORM=_EGL_INVALID_PLATFORM
 ifeq ($(firstword $(EGL_PLATFORMS)),x11)
 EGL_NATIVE_PLATFORM=_EGL_PLATFORM_X11
 endif
+ifeq ($(firstword $(EGL_PLATFORMS)),wayland)
+EGL_NATIVE_PLATFORM=_EGL_PLATFORM_WAYLAND
+endif
 ifeq ($(firstword $(EGL_PLATFORMS)),drm)
 EGL_NATIVE_PLATFORM=_EGL_PLATFORM_DRM
 endif
index 565e44d2d23c8fc98d292aaa77983772042d2bdb..305929472975b25de2abb6e766a73a6245e2388b 100644 (file)
@@ -27,6 +27,7 @@ _eglGetNativePlatformFromEnv(void)
    } egl_platforms[_EGL_NUM_PLATFORMS] = {
       { _EGL_PLATFORM_WINDOWS, "gdi" },
       { _EGL_PLATFORM_X11, "x11" },
+      { _EGL_PLATFORM_WAYLAND, "wayland" },
       { _EGL_PLATFORM_DRM, "drm" },
       { _EGL_PLATFORM_FBDEV, "fbdev" }
    };
index dbc5d32d910db654e1ecb46fa5eabbfd0c6b96ed..ce035eb2ef124255003bc3dc2af51ef0c878137a 100644 (file)
@@ -11,6 +11,7 @@
 enum _egl_platform_type {
    _EGL_PLATFORM_WINDOWS,
    _EGL_PLATFORM_X11,
+   _EGL_PLATFORM_WAYLAND,
    _EGL_PLATFORM_DRM,
    _EGL_PLATFORM_FBDEV,
 
index e133c220f5ca8a6edd6ba953d97003f33ce4dcfe..b75e8b6a2cb32e145c85c337677c7ed59385965e 100644 (file)
@@ -437,6 +437,7 @@ _eglAddUserDriver(void)
 {
    const char *search_path = _eglGetSearchPath();
    char *env;
+   size_t name_len = 0;
 
    env = getenv("EGL_DRIVER");
 #if defined(_EGL_OS_UNIX)
@@ -448,21 +449,39 @@ _eglAddUserDriver(void)
          env = NULL;
       }
    }
+   else if (env) {
+      char *suffix = strchr(env, '.');
+      name_len = (suffix) ? suffix - env : strlen(env);
+   }
+#else
+   if (env)
+      name_len = strlen(env);
 #endif /* _EGL_OS_UNIX */
-   if (env) {
+
+   /*
+    * Try built-in drivers first if we know the driver name.  This makes sure
+    * we do not load the outdated external driver that is still on the
+    * filesystem.
+    */
+   if (name_len) {
       _EGLModule *mod;
       EGLint i;
 
-      /* env can be a path */
-      _eglPreloadForEach(search_path, _eglLoaderFile, (void *) env);
-      /* or the name of a built-in driver */
       for (i = 0; _eglBuiltInDrivers[i].name; i++) {
-         if (!strcmp(_eglBuiltInDrivers[i].name, env)) {
+         if (strlen(_eglBuiltInDrivers[i].name) == name_len &&
+             !strncmp(_eglBuiltInDrivers[i].name, env, name_len)) {
             mod = _eglAddModule(env);
             if (mod)
                mod->BuiltIn = _eglBuiltInDrivers[i].main;
+
+            return EGL_TRUE;
          }
       }
+   }
+
+   /* otherwise, treat env as a path */
+   if (env) {
+      _eglPreloadForEach(search_path, _eglLoaderFile, (void *) env);
 
       return EGL_TRUE;
    }
diff --git a/src/egl/wayland/Makefile b/src/egl/wayland/Makefile
new file mode 100644 (file)
index 0000000..4cd0365
--- /dev/null
@@ -0,0 +1,67 @@
+# src/egl/main/Makefile
+
+TOP = ../../..
+include $(TOP)/configs/current
+
+INCLUDE_DIRS = -I$(TOP)/include
+
+HEADERS = wayland-egl-priv.h
+SOURCES = wayland-egl.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+LOCAL_CFLAGS = -I$(TOP)/include/EGL $(LIBDRM_CFLAGS) $(WAYLAND_CFLAGS)
+LOCAL_LIBS =
+
+.c.o:
+       $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(LOCAL_CFLAGS) $< -o $@
+
+
+default: depend library
+
+# wayland-egl Library
+library: $(TOP)/$(LIB_DIR)/$(WAYLAND_EGL_LIB_NAME)
+
+$(TOP)/$(LIB_DIR)/$(WAYLAND_EGL_LIB_NAME): $(OBJECTS) $(LOCAL_LIBS)
+       $(MKLIB) -o $(WAYLAND_EGL_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
+               -install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \
+               -L$(TOP)/$(LIB_DIR) $(WAYLAND_EGL_LIB_DEPS) \
+               $(OBJECTS) $(LOCAL_LIBS)
+
+PKG_CONFIG_DIR = $(INSTALL_LIB_DIR)/pkgconfig
+
+gl_pcedit = sed \
+       -e 's,@INSTALL_DIR@,$(INSTALL_DIR),' \
+       -e 's,@INSTALL_LIB_DIR@,$(INSTALL_LIB_DIR),' \
+       -e 's,@INSTALL_INC_DIR@,$(INSTALL_INC_DIR),' \
+       -e 's,@VERSION@,$(MESA_MAJOR).$(MESA_MINOR).$(MESA_TINY),' \
+       -e 's,@WAYLAND_EGL_PC_REQ_PRIV@,$(WAYLAND_EGL_PC_REQ_PRIV),' \
+       -e 's,@WAYLAND_EGL_PC_LIB_PRIV@,$(WAYLAND_EGL_PC_LIB_PRIV),' \
+       -e 's,@WAYLAND_EGL_PC_CFLAGS@,$(WAYLAND_EGL_PC_CFLAGS),' \
+       -e 's,@WAYLAND_EGL_LIB@,$(WAYLAND_EGL_LIB),'
+
+wayland-egl.pc: wayland-egl.pc.in
+       $(gl_pcedit) $< > $@
+
+install: default wayland-egl.pc
+       $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
+       $(MINSTALL) $(TOP)/$(LIB_DIR)/$(WAYLAND_EGL_LIB_GLOB) \
+               $(DESTDIR)$(INSTALL_LIB_DIR)
+       $(INSTALL) -d $(DESTDIR)$(PKG_CONFIG_DIR)
+       $(INSTALL) -m 644 wayland-egl.pc $(DESTDIR)$(PKG_CONFIG_DIR)
+
+clean:
+       -rm -f *.o
+       -rm -f depend depend.bak
+
+
+depend: $(SOURCES) $(HEADERS)
+       @ echo "running $(MKDEP)"
+       @ rm -f depend
+       @ touch depend
+       $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \
+               $(SOURCES) $(HEADERS) > /dev/null 2>/dev/null
+
+
+-include depend
+# DO NOT DELETE
diff --git a/src/egl/wayland/wayland-egl-priv.h b/src/egl/wayland/wayland-egl-priv.h
new file mode 100644 (file)
index 0000000..38b21c2
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef _WAYLAND_EGL_PRIV_H
+#define _WAYLAND_EGL_PRIV_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* GCC visibility */
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define WL_EGL_EXPORT __attribute__ ((visibility("default")))
+#else
+#define WL_EGL_EXPORT
+#endif
+
+#include <stdbool.h>
+#include <wayland-client.h>
+
+struct wl_egl_display {
+       struct wl_display *display;
+
+       struct wl_drm *drm;
+       int fd;
+       char *device_name;
+       bool authenticated;
+
+       void (*glFlush)(void);
+};
+
+struct wl_egl_window {
+       struct wl_surface *surface;
+       struct wl_visual *visual;
+
+       int width;
+       int height;
+       int dx;
+       int dy;
+
+       int attached_width;
+       int attached_height;
+};
+
+struct wl_egl_pixmap {
+       struct wl_egl_display *display;
+       struct wl_visual      *visual;
+
+       int name;
+       int width;
+       int height;
+       int stride;
+
+       void (*destroy) (struct wl_egl_pixmap *egl_pixmap);
+
+       void *driver_private;
+};
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/egl/wayland/wayland-egl.c b/src/egl/wayland/wayland-egl.c
new file mode 100644 (file)
index 0000000..12fbdfa
--- /dev/null
@@ -0,0 +1,226 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <dlfcn.h>
+
+#include <wayland-client.h>
+#include <xf86drm.h>
+
+#include "wayland-egl.h"
+#include "wayland-egl-priv.h"
+
+static void
+drm_handle_device(void *data, struct wl_drm *drm, const char *device)
+{
+       struct wl_egl_display *egl_display = data;
+       drm_magic_t magic;
+
+       egl_display->device_name = strdup(device);
+
+       egl_display->fd = open(egl_display->device_name, O_RDWR);
+
+       if (egl_display->fd == -1) {
+               fprintf(stderr, "wayland-egl: could not open %s (%s)",
+                       egl_display->device_name, strerror(errno));
+               return;
+       }
+       drmGetMagic(egl_display->fd, &magic);
+       wl_drm_authenticate(egl_display->drm, magic);
+}
+
+static void
+drm_handle_authenticated(void *data, struct wl_drm *drm)
+{
+       struct wl_egl_display *egl_display = data;
+
+       egl_display->authenticated = true;
+}
+
+static const struct wl_drm_listener drm_listener = {
+       drm_handle_device,
+       drm_handle_authenticated
+};
+
+static void
+wl_display_handle_global(struct wl_display *display, uint32_t id,
+                        const char *interface, uint32_t version, void *data)
+{
+       struct wl_egl_display *egl_display = data;
+
+       if (strcmp(interface, "drm") == 0) {
+               egl_display->drm = wl_drm_create(display, id);
+               wl_drm_add_listener(egl_display->drm, &drm_listener,
+                                   egl_display);
+       }
+}
+
+/* stolen from egl_dri2:dri2_load() */
+static void *
+get_flush_address() {
+       void *handle;
+       void *(*get_proc_address)(const char *procname);
+
+       handle = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
+       if (handle) {
+               get_proc_address = (void* (*)(const char *))
+                       dlsym(handle, "_glapi_get_proc_address");
+               /* no need to keep a reference */
+               dlclose(handle);
+       }
+
+       /*
+        * If glapi is not available, loading DRI drivers will fail.  Ideally, we
+        * should load one of libGL, libGLESv1_CM, or libGLESv2 and go on.  But if
+        * the app has loaded another one of them with RTLD_LOCAL, there may be
+        * unexpected behaviors later because there will be two copies of glapi
+        * (with global variables of the same names!) in the memory.
+        */
+       if (!get_proc_address) {
+               fprintf(stderr, "failed to find _glapi_get_proc_address");
+               return NULL;
+       }
+
+       return get_proc_address("glFlush");
+}
+
+WL_EGL_EXPORT struct wl_egl_display *
+wl_egl_display_create(struct wl_display *display)
+{
+       struct wl_egl_display *egl_display;
+
+       egl_display = malloc(sizeof *egl_display);
+       if (!egl_display)
+               return NULL;
+
+       egl_display->display = display;
+       egl_display->drm = NULL;
+       egl_display->fd = -1;
+       egl_display->device_name = NULL;
+       egl_display->authenticated = false;
+
+       egl_display->glFlush = (void (*)(void)) get_flush_address();
+
+       wl_display_add_global_listener(display, wl_display_handle_global,
+                                      egl_display);
+
+       return egl_display;
+}
+
+WL_EGL_EXPORT void
+wl_egl_display_destroy(struct wl_egl_display *egl_display)
+{
+
+       free(egl_display->device_name);
+       close(egl_display->fd);
+
+       wl_drm_destroy(egl_display->drm);
+
+       free(egl_display);
+}
+
+WL_EGL_EXPORT void
+wl_egl_window_resize(struct wl_egl_window *egl_window,
+                    int width, int height,
+                    int dx, int dy)
+{
+       egl_window->width  = width;
+       egl_window->height = height;
+       egl_window->dx     = dx;
+       egl_window->dy     = dy;
+}
+
+WL_EGL_EXPORT struct wl_egl_window *
+wl_egl_window_create(struct wl_egl_display *egl_display,
+                    struct wl_surface *surface,
+                    int width, int height,
+                    struct wl_visual *visual)
+{
+       struct wl_egl_window *egl_window;
+
+       egl_window = malloc(sizeof *egl_window);
+       if (!egl_window)
+               return NULL;
+
+       egl_window->surface = surface;
+       egl_window->visual  = visual;
+       wl_egl_window_resize(egl_window, width, height, 0, 0);
+       egl_window->attached_width  = 0;
+       egl_window->attached_height = 0;
+       
+       return egl_window;
+}
+
+WL_EGL_EXPORT void
+wl_egl_window_destroy(struct wl_egl_window *egl_window)
+{
+       free(egl_window);
+}
+
+WL_EGL_EXPORT void
+wl_egl_window_get_attached_size(struct wl_egl_window *egl_window,
+                               int *width, int *height)
+{
+       if (width)
+               *width = egl_window->attached_width;
+       if (height)
+               *height = egl_window->attached_height;
+}
+
+WL_EGL_EXPORT struct wl_egl_pixmap *
+wl_egl_pixmap_create(struct wl_egl_display *egl_display,
+                    int width, int height,
+                    struct wl_visual *visual, uint32_t flags)
+{
+       struct wl_egl_pixmap *egl_pixmap;
+
+       egl_pixmap = malloc(sizeof *egl_pixmap);
+       if (egl_pixmap == NULL)
+               return NULL;
+
+       egl_pixmap->display = egl_display;
+       egl_pixmap->width   = width;
+       egl_pixmap->height  = height;
+       egl_pixmap->visual  = visual;
+       egl_pixmap->name    = 0;
+       egl_pixmap->stride  = 0;
+
+       egl_pixmap->destroy = NULL;
+
+       return egl_pixmap;
+}
+
+WL_EGL_EXPORT void
+wl_egl_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap)
+{
+       if (egl_pixmap->destroy)
+               egl_pixmap->destroy(egl_pixmap);
+       free(egl_pixmap);
+}
+
+WL_EGL_EXPORT struct wl_buffer *
+wl_egl_pixmap_create_buffer(struct wl_egl_display *egl_display,
+                           struct wl_egl_pixmap *egl_pixmap)
+{
+       if (egl_pixmap->name == 0)
+               return NULL;
+
+       return wl_drm_create_buffer(egl_display->drm, egl_pixmap->name,
+                                   egl_pixmap->width, egl_pixmap->height,
+                                   egl_pixmap->stride, egl_pixmap->visual);
+}
+
+WL_EGL_EXPORT void
+wl_egl_pixmap_flush(struct wl_egl_display *egl_display,
+                   struct wl_egl_pixmap *egl_pixmap)
+{
+       if (egl_display->glFlush)
+               egl_display->glFlush();
+}
diff --git a/src/egl/wayland/wayland-egl.pc.in b/src/egl/wayland/wayland-egl.pc.in
new file mode 100644 (file)
index 0000000..3c2067c
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@INSTALL_DIR@
+exec_prefix=${prefix}
+libdir=@INSTALL_LIB_DIR@
+includedir=@INSTALL_INC_DIR@
+
+Name: wayland-egl
+Description: Mesa wayland-egl library
+Requires.private: @WAYLAND_EGL_PC_REQ_PRIV@
+Version: @VERSION@
+Libs: -L${libdir} -l@WAYLAND_EGL_LIB@
+Libs.private: @WAYLAND_EGL_PC_LIB_PRIV@
+Cflags: -I${includedir} @WAYLAND_EGL_PC_CFLAGS@
index 2265f1de46c44a3242ce8e8e83499e9a0dd1d705..31580556f031d0c3ecb3e166e9378bcba644ebdb 100644 (file)
@@ -42,6 +42,7 @@ if env['drm']:
     #     SConscript([
     #         'drivers/nouveau/SConscript', 
     #         'drivers/nv50/SConscript', 
+    #         'drivers/nvc0/SConscript', 
     #         'drivers/nvfx/SConscript',
     #     ])
 
index 6cf1ddd43fe7aaa9d7039892ad101fc8a0e85087..e40f546929df94c6124bab09c0abc7fdc855acf1 100644 (file)
@@ -143,6 +143,7 @@ C_SOURCES = \
        util/u_transfer.c \
        util/u_resource.c \
        util/u_upload_mgr.c \
+       util/u_vbuf_mgr.c \
        vl/vl_bitstream_parser.c \
        vl/vl_mpeg12_mc_renderer.c \
        vl/vl_compositor.c \
index e6806d9a723160138b81c9b0f58baacd1e0aeb5a..11024d4192356bbe260628a3c0d9b2fd64bc0877 100644 (file)
@@ -190,11 +190,11 @@ source = [
     'util/u_tile.c',
     'util/u_transfer.c',
     'util/u_upload_mgr.c',
+    'util/u_vbuf_mgr.c',
     'vl/vl_bitstream_parser.c',
     'vl/vl_mpeg12_mc_renderer.c',
     'vl/vl_compositor.c',
     'vl/vl_csc.c',
-    'target-helpers/wrap_screen.c',
 ]
 
 if env['llvm']:
index 58b022d531db97916aeb1948b9f638ba9c8cb9dc..fdd40fca126f2a8a1a3af3df6f96a6da02878a55 100644 (file)
 #include "cso_cache/cso_hash.h"
 #include "cso_context.h"
 
-struct cso_context {
-   struct pipe_context *pipe;
-   struct cso_cache *cache;
 
+/**
+ * Info related to samplers and sampler views.
+ * We have one of these for fragment samplers and another for vertex samplers.
+ */
+struct sampler_info
+{
    struct {
       void *samplers[PIPE_MAX_SAMPLERS];
       unsigned nr_samplers;
-
-      void *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS];
-      unsigned nr_vertex_samplers;
    } hw;
 
    void *samplers[PIPE_MAX_SAMPLERS];
    unsigned nr_samplers;
 
-   void *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS];
-   unsigned nr_vertex_samplers;
-
-   unsigned nr_samplers_saved;
    void *samplers_saved[PIPE_MAX_SAMPLERS];
+   unsigned nr_samplers_saved;
+
+   struct pipe_sampler_view *views[PIPE_MAX_SAMPLERS];
+   unsigned nr_views;
+
+   struct pipe_sampler_view *views_saved[PIPE_MAX_SAMPLERS];
+   unsigned nr_views_saved;
+};
+
 
-   unsigned nr_vertex_samplers_saved;
-   void *vertex_samplers_saved[PIPE_MAX_VERTEX_SAMPLERS];
 
-   uint nr_fragment_sampler_views;
-   struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS];
+struct cso_context {
+   struct pipe_context *pipe;
+   struct cso_cache *cache;
 
-   uint nr_vertex_sampler_views;
-   struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS];
+   struct sampler_info fragment_samplers;
+   struct sampler_info vertex_samplers;
 
-   uint nr_fragment_sampler_views_saved;
-   struct pipe_sampler_view *fragment_sampler_views_saved[PIPE_MAX_SAMPLERS];
+   uint nr_vertex_buffers;
+   struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
 
-   uint nr_vertex_sampler_views_saved;
-   struct pipe_sampler_view *vertex_sampler_views_saved[PIPE_MAX_VERTEX_SAMPLERS];
+   uint nr_vertex_buffers_saved;
+   struct pipe_vertex_buffer vertex_buffers_saved[PIPE_MAX_ATTRIBS];
 
    /** Current and saved state.
     * The saved state is used as a 1-deep stack.
@@ -252,6 +256,8 @@ struct cso_context *cso_create_context( struct pipe_context *pipe )
    if (ctx == NULL)
       goto out;
 
+   assert(PIPE_MAX_SAMPLERS == PIPE_MAX_VERTEX_SAMPLERS);
+
    ctx->cache = cso_cache_create();
    if (ctx->cache == NULL)
       goto out;
@@ -278,7 +284,8 @@ out:
 void cso_release_all( struct cso_context *ctx )
 {
    unsigned i;
-   
+   struct sampler_info *info;
+
    if (ctx->pipe) {
       ctx->pipe->bind_blend_state( ctx->pipe, NULL );
       ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL );
@@ -294,19 +301,30 @@ void cso_release_all( struct cso_context *ctx )
          ctx->pipe->set_vertex_sampler_views(ctx->pipe, 0, NULL);
    }
 
+   /* free fragment samplers, views */
+   info = &ctx->fragment_samplers;   
    for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
-      pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL);
-      pipe_sampler_view_reference(&ctx->fragment_sampler_views_saved[i], NULL);
+      pipe_sampler_view_reference(&info->views[i], NULL);
+      pipe_sampler_view_reference(&info->views_saved[i], NULL);
    }
 
-   for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
-      pipe_sampler_view_reference(&ctx->vertex_sampler_views[i], NULL);
-      pipe_sampler_view_reference(&ctx->vertex_sampler_views_saved[i], NULL);
+   /* free vertex samplers, views */
+   info = &ctx->vertex_samplers;   
+   for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+      pipe_sampler_view_reference(&info->views[i], NULL);
+      pipe_sampler_view_reference(&info->views_saved[i], NULL);
    }
 
    util_unreference_framebuffer_state(&ctx->fb);
    util_unreference_framebuffer_state(&ctx->fb_saved);
 
+   util_copy_vertex_buffers(ctx->vertex_buffers,
+                            &ctx->nr_vertex_buffers,
+                            NULL, 0);
+   util_copy_vertex_buffers(ctx->vertex_buffers_saved,
+                            &ctx->nr_vertex_buffers_saved,
+                            NULL, 0);
+
    if (ctx->cache) {
       cso_cache_delete( ctx->cache );
       ctx->cache = NULL;
@@ -395,233 +413,6 @@ void cso_restore_blend(struct cso_context *ctx)
 
 
 
-enum pipe_error cso_single_sampler(struct cso_context *ctx,
-                                   unsigned idx,
-                                   const struct pipe_sampler_state *templ)
-{
-   void *handle = NULL;
-
-   if (templ != NULL) {
-      unsigned key_size = sizeof(struct pipe_sampler_state);
-      unsigned hash_key = cso_construct_key((void*)templ, key_size);
-      struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
-                                                          hash_key, CSO_SAMPLER,
-                                                          (void*)templ, key_size);
-
-      if (cso_hash_iter_is_null(iter)) {
-         struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler));
-         if (!cso)
-            return PIPE_ERROR_OUT_OF_MEMORY;
-
-         memcpy(&cso->state, templ, sizeof(*templ));
-         cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state);
-         cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state;
-         cso->context = ctx->pipe;
-
-         iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso);
-         if (cso_hash_iter_is_null(iter)) {
-            FREE(cso);
-            return PIPE_ERROR_OUT_OF_MEMORY;
-         }
-
-         handle = cso->data;
-      }
-      else {
-         handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data;
-      }
-   }
-
-   ctx->samplers[idx] = handle;
-   return PIPE_OK;
-}
-
-enum pipe_error
-cso_single_vertex_sampler(struct cso_context *ctx,
-                          unsigned idx,
-                          const struct pipe_sampler_state *templ)
-{
-   void *handle = NULL;
-
-   if (templ != NULL) {
-      unsigned key_size = sizeof(struct pipe_sampler_state);
-      unsigned hash_key = cso_construct_key((void*)templ, key_size);
-      struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
-                                                          hash_key, CSO_SAMPLER,
-                                                          (void*)templ, key_size);
-
-      if (cso_hash_iter_is_null(iter)) {
-         struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler));
-         if (!cso)
-            return PIPE_ERROR_OUT_OF_MEMORY;
-
-         memcpy(&cso->state, templ, sizeof(*templ));
-         cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state);
-         cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state;
-         cso->context = ctx->pipe;
-
-         iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso);
-         if (cso_hash_iter_is_null(iter)) {
-            FREE(cso);
-            return PIPE_ERROR_OUT_OF_MEMORY;
-         }
-
-         handle = cso->data;
-      }
-      else {
-         handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data;
-      }
-   }
-
-   ctx->vertex_samplers[idx] = handle;
-   return PIPE_OK;
-}
-
-void cso_single_sampler_done( struct cso_context *ctx )
-{
-   unsigned i;
-
-   /* find highest non-null sampler */
-   for (i = PIPE_MAX_SAMPLERS; i > 0; i--) {
-      if (ctx->samplers[i - 1] != NULL)
-         break;
-   }
-
-   ctx->nr_samplers = i;
-
-   if (ctx->hw.nr_samplers != ctx->nr_samplers ||
-       memcmp(ctx->hw.samplers,
-              ctx->samplers,
-              ctx->nr_samplers * sizeof(void *)) != 0) 
-   {
-      memcpy(ctx->hw.samplers, ctx->samplers, ctx->nr_samplers * sizeof(void *));
-      ctx->hw.nr_samplers = ctx->nr_samplers;
-
-      ctx->pipe->bind_fragment_sampler_states(ctx->pipe, ctx->nr_samplers, ctx->samplers);
-   }
-}
-
-void
-cso_single_vertex_sampler_done(struct cso_context *ctx)
-{
-   unsigned i;
-
-   /* find highest non-null sampler */
-   for (i = PIPE_MAX_VERTEX_SAMPLERS; i > 0; i--) {
-      if (ctx->vertex_samplers[i - 1] != NULL)
-         break;
-   }
-
-   ctx->nr_vertex_samplers = i;
-
-   if (ctx->hw.nr_vertex_samplers != ctx->nr_vertex_samplers ||
-       memcmp(ctx->hw.vertex_samplers,
-              ctx->vertex_samplers,
-              ctx->nr_vertex_samplers * sizeof(void *)) != 0) 
-   {
-      memcpy(ctx->hw.vertex_samplers,
-             ctx->vertex_samplers,
-             ctx->nr_vertex_samplers * sizeof(void *));
-      ctx->hw.nr_vertex_samplers = ctx->nr_vertex_samplers;
-
-      ctx->pipe->bind_vertex_sampler_states(ctx->pipe,
-                                            ctx->nr_vertex_samplers,
-                                            ctx->vertex_samplers);
-   }
-}
-
-/*
- * If the function encouters any errors it will return the
- * last one. Done to always try to set as many samplers
- * as possible.
- */
-enum pipe_error cso_set_samplers( struct cso_context *ctx,
-                                  unsigned nr,
-                                  const struct pipe_sampler_state **templates )
-{
-   unsigned i;
-   enum pipe_error temp, error = PIPE_OK;
-
-   /* TODO: fastpath
-    */
-
-   for (i = 0; i < nr; i++) {
-      temp = cso_single_sampler( ctx, i, templates[i] );
-      if (temp != PIPE_OK)
-         error = temp;
-   }
-
-   for ( ; i < ctx->nr_samplers; i++) {
-      temp = cso_single_sampler( ctx, i, NULL );
-      if (temp != PIPE_OK)
-         error = temp;
-   }
-
-   cso_single_sampler_done( ctx );
-
-   return error;
-}
-
-void cso_save_samplers(struct cso_context *ctx)
-{
-   ctx->nr_samplers_saved = ctx->nr_samplers;
-   memcpy(ctx->samplers_saved, ctx->samplers, sizeof(ctx->samplers));
-}
-
-void cso_restore_samplers(struct cso_context *ctx)
-{
-   ctx->nr_samplers = ctx->nr_samplers_saved;
-   memcpy(ctx->samplers, ctx->samplers_saved, sizeof(ctx->samplers));
-   cso_single_sampler_done( ctx );
-}
-
-/*
- * If the function encouters any errors it will return the
- * last one. Done to always try to set as many samplers
- * as possible.
- */
-enum pipe_error cso_set_vertex_samplers(struct cso_context *ctx,
-                                        unsigned nr,
-                                        const struct pipe_sampler_state **templates)
-{
-   unsigned i;
-   enum pipe_error temp, error = PIPE_OK;
-
-   /* TODO: fastpath
-    */
-
-   for (i = 0; i < nr; i++) {
-      temp = cso_single_vertex_sampler( ctx, i, templates[i] );
-      if (temp != PIPE_OK)
-         error = temp;
-   }
-
-   for ( ; i < ctx->nr_samplers; i++) {
-      temp = cso_single_vertex_sampler( ctx, i, NULL );
-      if (temp != PIPE_OK)
-         error = temp;
-   }
-
-   cso_single_vertex_sampler_done( ctx );
-
-   return error;
-}
-
-void
-cso_save_vertex_samplers(struct cso_context *ctx)
-{
-   ctx->nr_vertex_samplers_saved = ctx->nr_vertex_samplers;
-   memcpy(ctx->vertex_samplers_saved, ctx->vertex_samplers, sizeof(ctx->vertex_samplers));
-}
-
-void
-cso_restore_vertex_samplers(struct cso_context *ctx)
-{
-   ctx->nr_vertex_samplers = ctx->nr_vertex_samplers_saved;
-   memcpy(ctx->vertex_samplers, ctx->vertex_samplers_saved, sizeof(ctx->vertex_samplers));
-   cso_single_vertex_sampler_done(ctx);
-}
-
-
 enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx,
                                             const struct pipe_depth_stencil_alpha_state *templ)
 {
@@ -1143,121 +934,361 @@ void cso_restore_vertex_elements(struct cso_context *ctx)
    ctx->velements_saved = NULL;
 }
 
-/* fragment sampler view state */
+/* vertex buffers */
 
-void
-cso_set_fragment_sampler_views(struct cso_context *cso,
-                               uint count,
-                               struct pipe_sampler_view **views)
+void cso_set_vertex_buffers(struct cso_context *ctx,
+                            unsigned count,
+                            const struct pipe_vertex_buffer *buffers)
 {
-   uint i;
-
-   for (i = 0; i < count; i++) {
-      pipe_sampler_view_reference(&cso->fragment_sampler_views[i], views[i]);
+   if (count != ctx->nr_vertex_buffers ||
+       memcmp(buffers, ctx->vertex_buffers,
+              sizeof(struct pipe_vertex_buffer) * count) != 0) {
+      util_copy_vertex_buffers(ctx->vertex_buffers, &ctx->nr_vertex_buffers,
+                               buffers, count);
+      ctx->pipe->set_vertex_buffers(ctx->pipe, count, buffers);
    }
-   for (; i < cso->nr_fragment_sampler_views; i++) {
-      pipe_sampler_view_reference(&cso->fragment_sampler_views[i], NULL);
+}
+
+void cso_save_vertex_buffers(struct cso_context *ctx)
+{
+   util_copy_vertex_buffers(ctx->vertex_buffers_saved,
+                            &ctx->nr_vertex_buffers_saved,
+                            ctx->vertex_buffers,
+                            ctx->nr_vertex_buffers);
+}
+
+void cso_restore_vertex_buffers(struct cso_context *ctx)
+{
+   util_copy_vertex_buffers(ctx->vertex_buffers,
+                            &ctx->nr_vertex_buffers,
+                            ctx->vertex_buffers_saved,
+                            ctx->nr_vertex_buffers_saved);
+   ctx->pipe->set_vertex_buffers(ctx->pipe, ctx->nr_vertex_buffers,
+                                 ctx->vertex_buffers);
+}
+
+
+/**************** fragment/vertex sampler view state *************************/
+
+static enum pipe_error
+single_sampler(struct cso_context *ctx,
+               struct sampler_info *info,
+               unsigned idx,
+               const struct pipe_sampler_state *templ)
+{
+   void *handle = NULL;
+
+   if (templ != NULL) {
+      unsigned key_size = sizeof(struct pipe_sampler_state);
+      unsigned hash_key = cso_construct_key((void*)templ, key_size);
+      struct cso_hash_iter iter =
+         cso_find_state_template(ctx->cache,
+                                 hash_key, CSO_SAMPLER,
+                                 (void *) templ, key_size);
+
+      if (cso_hash_iter_is_null(iter)) {
+         struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler));
+         if (!cso)
+            return PIPE_ERROR_OUT_OF_MEMORY;
+
+         memcpy(&cso->state, templ, sizeof(*templ));
+         cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state);
+         cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state;
+         cso->context = ctx->pipe;
+
+         iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso);
+         if (cso_hash_iter_is_null(iter)) {
+            FREE(cso);
+            return PIPE_ERROR_OUT_OF_MEMORY;
+         }
+
+         handle = cso->data;
+      }
+      else {
+         handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data;
+      }
    }
 
-   cso->pipe->set_fragment_sampler_views(cso->pipe,
-                                         MAX2(count, cso->nr_fragment_sampler_views),
-                                         cso->fragment_sampler_views);
+   info->samplers[idx] = handle;
 
-   cso->nr_fragment_sampler_views = count;
+   return PIPE_OK;
 }
 
-void
-cso_save_fragment_sampler_views(struct cso_context *cso)
+enum pipe_error
+cso_single_sampler(struct cso_context *ctx,
+                   unsigned idx,
+                   const struct pipe_sampler_state *templ)
 {
-   uint i;
+   return single_sampler(ctx, &ctx->fragment_samplers, idx, templ);
+}
+
+enum pipe_error
+cso_single_vertex_sampler(struct cso_context *ctx,
+                          unsigned idx,
+                          const struct pipe_sampler_state *templ)
+{
+   return single_sampler(ctx, &ctx->vertex_samplers, idx, templ);
+}
+
 
-   cso->nr_fragment_sampler_views_saved = cso->nr_fragment_sampler_views;
 
-   for (i = 0; i < cso->nr_fragment_sampler_views; i++) {
-      assert(!cso->fragment_sampler_views_saved[i]);
+static void
+single_sampler_done(struct cso_context *ctx,
+                    struct sampler_info *info)
+{
+   unsigned i;
 
-      pipe_sampler_view_reference(&cso->fragment_sampler_views_saved[i],
-                                  cso->fragment_sampler_views[i]);
+   /* find highest non-null sampler */
+   for (i = PIPE_MAX_SAMPLERS; i > 0; i--) {
+      if (info->samplers[i - 1] != NULL)
+         break;
+   }
+
+   info->nr_samplers = i;
+
+   if (info->hw.nr_samplers != info->nr_samplers ||
+       memcmp(info->hw.samplers,
+              info->samplers,
+              info->nr_samplers * sizeof(void *)) != 0) 
+   {
+      memcpy(info->hw.samplers,
+             info->samplers,
+             info->nr_samplers * sizeof(void *));
+      info->hw.nr_samplers = info->nr_samplers;
+
+      if (info == &ctx->fragment_samplers) {
+         ctx->pipe->bind_fragment_sampler_states(ctx->pipe,
+                                                 info->nr_samplers,
+                                                 info->samplers);
+      }
+      else if (info == &ctx->vertex_samplers) {
+         ctx->pipe->bind_vertex_sampler_states(ctx->pipe,
+                                               info->nr_samplers,
+                                               info->samplers);
+      }
+      else {
+         assert(0);
+      }
    }
 }
 
 void
-cso_restore_fragment_sampler_views(struct cso_context *cso)
+cso_single_sampler_done( struct cso_context *ctx )
 {
-   uint i;
+   single_sampler_done(ctx, &ctx->fragment_samplers);
+}
+
+void
+cso_single_vertex_sampler_done(struct cso_context *ctx)
+{
+   single_sampler_done(ctx, &ctx->vertex_samplers);
+}
 
-   for (i = 0; i < cso->nr_fragment_sampler_views_saved; i++) {
-      pipe_sampler_view_reference(&cso->fragment_sampler_views[i], cso->fragment_sampler_views_saved[i]);
-      pipe_sampler_view_reference(&cso->fragment_sampler_views_saved[i], NULL);
+
+/*
+ * If the function encouters any errors it will return the
+ * last one. Done to always try to set as many samplers
+ * as possible.
+ */
+static enum pipe_error
+set_samplers(struct cso_context *ctx,
+             struct sampler_info *info,
+             unsigned nr,
+             const struct pipe_sampler_state **templates)
+{
+   unsigned i;
+   enum pipe_error temp, error = PIPE_OK;
+
+   /* TODO: fastpath
+    */
+
+   for (i = 0; i < nr; i++) {
+      temp = single_sampler(ctx, info, i, templates[i]);
+      if (temp != PIPE_OK)
+         error = temp;
    }
-   for (; i < cso->nr_fragment_sampler_views; i++) {
-      pipe_sampler_view_reference(&cso->fragment_sampler_views[i], NULL);
+
+   for ( ; i < info->nr_samplers; i++) {
+      temp = single_sampler(ctx, info, i, NULL);
+      if (temp != PIPE_OK)
+         error = temp;
    }
 
-   cso->pipe->set_fragment_sampler_views(cso->pipe,
-                                         MAX2(cso->nr_fragment_sampler_views, cso->nr_fragment_sampler_views_saved),
-                                         cso->fragment_sampler_views);
+   single_sampler_done(ctx, info);
+
+   return error;
+}
+
+enum pipe_error
+cso_set_samplers(struct cso_context *ctx,
+                 unsigned nr,
+                 const struct pipe_sampler_state **templates)
+{
+   return set_samplers(ctx, &ctx->fragment_samplers, nr, templates);
+}
 
-   cso->nr_fragment_sampler_views = cso->nr_fragment_sampler_views_saved;
-   cso->nr_fragment_sampler_views_saved = 0;
+enum pipe_error
+cso_set_vertex_samplers(struct cso_context *ctx,
+                        unsigned nr,
+                        const struct pipe_sampler_state **templates)
+{
+   return set_samplers(ctx, &ctx->vertex_samplers, nr, templates);
 }
 
 
-/* vertex sampler view state */
+
+static void
+save_samplers(struct cso_context *ctx, struct sampler_info *info)
+{
+   info->nr_samplers_saved = info->nr_samplers;
+   memcpy(info->samplers_saved, info->samplers, sizeof(info->samplers));
+}
 
 void
-cso_set_vertex_sampler_views(struct cso_context *cso,
-                             uint count,
-                             struct pipe_sampler_view **views)
+cso_save_samplers(struct cso_context *ctx)
+{
+   save_samplers(ctx, &ctx->fragment_samplers);
+}
+
+void
+cso_save_vertex_samplers(struct cso_context *ctx)
+{
+   save_samplers(ctx, &ctx->vertex_samplers);
+}
+
+
+
+static void
+restore_samplers(struct cso_context *ctx, struct sampler_info *info)
+{
+   info->nr_samplers = info->nr_samplers_saved;
+   memcpy(info->samplers, info->samplers_saved, sizeof(info->samplers));
+   single_sampler_done(ctx, info);
+}
+
+void
+cso_restore_samplers(struct cso_context *ctx)
+{
+   restore_samplers(ctx, &ctx->fragment_samplers);
+}
+
+void
+cso_restore_vertex_samplers(struct cso_context *ctx)
+{
+   restore_samplers(ctx, &ctx->vertex_samplers);
+}
+
+
+
+static void
+set_sampler_views(struct cso_context *ctx,
+                  struct sampler_info *info,
+                  void (*set_views)(struct pipe_context *,
+                                    unsigned num_views,
+                                    struct pipe_sampler_view **),
+                  uint count,
+                  struct pipe_sampler_view **views)
 {
    uint i;
 
+   /* reference new views */
    for (i = 0; i < count; i++) {
-      pipe_sampler_view_reference(&cso->vertex_sampler_views[i], views[i]);
+      pipe_sampler_view_reference(&info->views[i], views[i]);
    }
-   for (; i < cso->nr_vertex_sampler_views; i++) {
-      pipe_sampler_view_reference(&cso->vertex_sampler_views[i], NULL);
+   /* unref extra old views, if any */
+   for (; i < info->nr_views; i++) {
+      pipe_sampler_view_reference(&info->views[i], NULL);
    }
 
-   cso->pipe->set_vertex_sampler_views(cso->pipe,
-                                       MAX2(count, cso->nr_vertex_sampler_views),
-                                       cso->vertex_sampler_views);
+   info->nr_views = count;
 
-   cso->nr_vertex_sampler_views = count;
+   /* bind the new sampler views */
+   set_views(ctx->pipe, count, info->views);
 }
 
 void
-cso_save_vertex_sampler_views(struct cso_context *cso)
+cso_set_fragment_sampler_views(struct cso_context *ctx,
+                               uint count,
+                               struct pipe_sampler_view **views)
 {
-   uint i;
+   set_sampler_views(ctx, &ctx->fragment_samplers,
+                     ctx->pipe->set_fragment_sampler_views,
+                     count, views);
+}
 
-   cso->nr_vertex_sampler_views_saved = cso->nr_vertex_sampler_views;
+void
+cso_set_vertex_sampler_views(struct cso_context *ctx,
+                             uint count,
+                             struct pipe_sampler_view **views)
+{
+   set_sampler_views(ctx, &ctx->vertex_samplers,
+                     ctx->pipe->set_vertex_sampler_views,
+                     count, views);
+}
 
-   for (i = 0; i < cso->nr_vertex_sampler_views; i++) {
-      assert(!cso->vertex_sampler_views_saved[i]);
 
-      pipe_sampler_view_reference(&cso->vertex_sampler_views_saved[i],
-                                  cso->vertex_sampler_views[i]);
+
+static void
+save_sampler_views(struct cso_context *ctx,
+                   struct sampler_info *info)
+{
+   uint i;
+
+   info->nr_views_saved = info->nr_views;
+
+   for (i = 0; i < info->nr_views; i++) {
+      assert(!info->views_saved[i]);
+      pipe_sampler_view_reference(&info->views_saved[i], info->views[i]);
    }
 }
 
 void
-cso_restore_vertex_sampler_views(struct cso_context *cso)
+cso_save_fragment_sampler_views(struct cso_context *ctx)
+{
+   save_sampler_views(ctx, &ctx->fragment_samplers);
+}
+
+void
+cso_save_vertex_sampler_views(struct cso_context *ctx)
+{
+   save_sampler_views(ctx, &ctx->vertex_samplers);
+}
+
+
+static void
+restore_sampler_views(struct cso_context *ctx,
+                      struct sampler_info *info,
+                      void (*set_views)(struct pipe_context *,
+                                        unsigned num_views,
+                                        struct pipe_sampler_view **))
 {
    uint i;
 
-   for (i = 0; i < cso->nr_vertex_sampler_views_saved; i++) {
-      pipe_sampler_view_reference(&cso->vertex_sampler_views[i], cso->vertex_sampler_views_saved[i]);
-      pipe_sampler_view_reference(&cso->vertex_sampler_views_saved[i], NULL);
+   for (i = 0; i < info->nr_views_saved; i++) {
+      pipe_sampler_view_reference(&info->views[i], info->views_saved[i]);
+      pipe_sampler_view_reference(&info->views_saved[i], NULL);
    }
-   for (; i < cso->nr_vertex_sampler_views; i++) {
-      pipe_sampler_view_reference(&cso->vertex_sampler_views[i], NULL);
+   for (; i < info->nr_views; i++) {
+      pipe_sampler_view_reference(&info->views[i], NULL);
    }
 
-   cso->pipe->set_vertex_sampler_views(cso->pipe,
-                                       MAX2(cso->nr_vertex_sampler_views, cso->nr_vertex_sampler_views_saved),
-                                       cso->vertex_sampler_views);
+   /* bind the old/saved sampler views */
+   set_views(ctx->pipe, info->nr_views_saved, info->views);
+
+   info->nr_views = info->nr_views_saved;
+   info->nr_views_saved = 0;
+}
+
+void
+cso_restore_fragment_sampler_views(struct cso_context *ctx)
+{
+   restore_sampler_views(ctx, &ctx->fragment_samplers,
+                         ctx->pipe->set_fragment_sampler_views);
+}
 
-   cso->nr_vertex_sampler_views = cso->nr_vertex_sampler_views_saved;
-   cso->nr_vertex_sampler_views_saved = 0;
+void
+cso_restore_vertex_sampler_views(struct cso_context *ctx)
+{
+   restore_sampler_views(ctx, &ctx->vertex_samplers,
+                         ctx->pipe->set_vertex_sampler_views);
 }
index f0b07f7376564451dfda2067660370f588e9f9e1..00edc9f8dd43a5882d249367a99db62810308536 100644 (file)
@@ -110,6 +110,13 @@ void cso_save_vertex_elements(struct cso_context *ctx);
 void cso_restore_vertex_elements(struct cso_context *ctx);
 
 
+void cso_set_vertex_buffers(struct cso_context *ctx,
+                            unsigned count,
+                            const struct pipe_vertex_buffer *buffers);
+void cso_save_vertex_buffers(struct cso_context *ctx);
+void cso_restore_vertex_buffers(struct cso_context *ctx);
+
+
 /* These aren't really sensible -- most of the time the api provides
  * object semantics for shaders anyway, and the cases where it doesn't
  * (eg mesa's internall-generated texenv programs), it will be up to
index e045313b94fe1d1992d3fdefd567e08b9f9568d4..95d96719873972590a21392b13bde2733e8ae018 100644 (file)
@@ -88,8 +88,14 @@ draw_create_gallivm(struct pipe_context *pipe, struct gallivm_state *gallivm)
       goto fail;
 
 #if HAVE_LLVM
-   if (draw_get_option_use_llvm() && gallivm) {
-      draw->llvm = draw_llvm_create(draw, gallivm);
+   if (draw_get_option_use_llvm()) {
+      if (!gallivm) {
+         gallivm = gallivm_create();
+         draw->own_gallivm = gallivm;
+      }
+
+      if (gallivm)
+         draw->llvm = draw_llvm_create(draw, gallivm);
    }
 #endif
 
@@ -180,8 +186,11 @@ void draw_destroy( struct draw_context *draw )
    draw_vs_destroy( draw );
    draw_gs_destroy( draw );
 #ifdef HAVE_LLVM
-   if(draw->llvm)
+   if (draw->llvm)
       draw_llvm_destroy( draw->llvm );
+
+   if (draw->own_gallivm)
+      gallivm_destroy(draw->own_gallivm);
 #endif
 
    FREE( draw );
@@ -401,7 +410,7 @@ void
 draw_wide_line_threshold(struct draw_context *draw, float threshold)
 {
    draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
-   draw->pipeline.wide_line_threshold = threshold;
+   draw->pipeline.wide_line_threshold = roundf(threshold);
 }
 
 
index 0c51aa85b3745b9987aed80488c5eb974f7f801c..a5217c1d4ec8c1bf3cc76b5f1bf618ff76e271da 100644 (file)
@@ -214,13 +214,12 @@ static LLVMTypeRef
 create_jit_vertex_buffer_type(struct gallivm_state *gallivm)
 {
    LLVMTargetDataRef target = gallivm->target;
-   LLVMTypeRef elem_types[4];
+   LLVMTypeRef elem_types[3];
    LLVMTypeRef vb_type;
 
    elem_types[0] =
-   elem_types[1] =
-   elem_types[2] = LLVMInt32TypeInContext(gallivm->context);
-   elem_types[3] = LLVMPointerType(LLVMOpaqueTypeInContext(gallivm->context), 0); /* vs_constants */
+   elem_types[1] = LLVMInt32TypeInContext(gallivm->context);
+   elem_types[2] = LLVMPointerType(LLVMInt8TypeInContext(gallivm->context), 0); /* vs_constants */
 
    vb_type = LLVMStructTypeInContext(gallivm->context, elem_types,
                                      Elements(elem_types), 0);
@@ -229,10 +228,8 @@ create_jit_vertex_buffer_type(struct gallivm_state *gallivm)
 
    LP_CHECK_MEMBER_OFFSET(struct pipe_vertex_buffer, stride,
                           target, vb_type, 0);
-   LP_CHECK_MEMBER_OFFSET(struct pipe_vertex_buffer, max_index,
-                          target, vb_type, 1);
    LP_CHECK_MEMBER_OFFSET(struct pipe_vertex_buffer, buffer_offset,
-                          target, vb_type, 2);
+                          target, vb_type, 1);
 
    LP_CHECK_STRUCT_SIZE(struct pipe_vertex_buffer, target, vb_type);
 
@@ -513,9 +510,7 @@ generate_fetch(struct gallivm_state *gallivm,
    LLVMValueRef vbuffer_ptr = LLVMBuildGEP(builder, vbuffers_ptr,
                                            &indices, 1, "");
    LLVMValueRef vb_stride = draw_jit_vbuffer_stride(gallivm, vbuf);
-   LLVMValueRef vb_max_index = draw_jit_vbuffer_max_index(gallivm, vbuf);
    LLVMValueRef vb_buffer_offset = draw_jit_vbuffer_offset(gallivm, vbuf);
-   LLVMValueRef cond;
    LLVMValueRef stride;
 
    if (velem->instance_divisor) {
@@ -525,10 +520,6 @@ generate_fetch(struct gallivm_state *gallivm,
                             "instance_divisor");
    }
 
-   /* limit index to min(index, vb_max_index) */
-   cond = LLVMBuildICmp(builder, LLVMIntULE, index, vb_max_index, "");
-   index = LLVMBuildSelect(builder, cond, index, vb_max_index, "");
-
    stride = LLVMBuildMul(builder, vb_stride, index, "");
 
    vbuffer_ptr = LLVMBuildLoad(builder, vbuffer_ptr, "vbuffer");
index 9f038f1f04d641f9e4d69f5ddbb154188eef20eb..e8623e7bcdc6c2c085054d08c94f672ddd977173 100644 (file)
@@ -133,11 +133,8 @@ struct draw_jit_context
 #define draw_jit_vbuffer_stride(_gallivm, _ptr)         \
    lp_build_struct_get(_gallivm, _ptr, 0, "stride")
 
-#define draw_jit_vbuffer_max_index(_gallivm, _ptr)      \
-   lp_build_struct_get(_gallivm, _ptr, 1, "max_index")
-
 #define draw_jit_vbuffer_offset(_gallivm, _ptr)         \
-   lp_build_struct_get(_gallivm, _ptr, 2, "buffer_offset")
+   lp_build_struct_get(_gallivm, _ptr, 1, "buffer_offset")
 
 
 typedef int
index 6206197dae97645ef742a5bad301e698bd49eb89..f1b0171f5200ec386b7285c7a7c52e07cd1058ee 100644 (file)
@@ -64,8 +64,8 @@ boolean draw_pipeline_init( struct draw_context *draw )
       return FALSE;
 
    /* these defaults are oriented toward the needs of softpipe */
-   draw->pipeline.wide_point_threshold = 1000000.0; /* infinity */
-   draw->pipeline.wide_line_threshold = 1.0;
+   draw->pipeline.wide_point_threshold = 1000000.0f; /* infinity */
+   draw->pipeline.wide_line_threshold = 1.0f;
    draw->pipeline.wide_point_sprites = FALSE;
    draw->pipeline.line_stipple = TRUE;
    draw->pipeline.point_sprite = TRUE;
index 0851b9acc0d4db457260fdcc14ba9095d1a589d0..32af29ae1444f7dffabe509c213274a083c71601 100644 (file)
 #define NUM_NEW_TOKENS 50
 
 
+/**
+ * Size for the alpha texture used for antialiasing
+ */
+#define TEXTURE_SIZE_LOG2  5   /* 32 x 32 */
+
 /**
  * Max texture level for the alpha texture used for antialiasing
+ *
+ * Don't use the 1x1 and 2x2 mipmap levels.
  */
-#define MAX_TEXTURE_LEVEL  5   /* 32 x 32 */
+#define MAX_TEXTURE_LEVEL  (TEXTURE_SIZE_LOG2 - 2)
 
 
 /**
@@ -403,8 +410,8 @@ aaline_create_texture(struct aaline_stage *aaline)
    texTemp.target = PIPE_TEXTURE_2D;
    texTemp.format = PIPE_FORMAT_A8_UNORM; /* XXX verify supported by driver! */
    texTemp.last_level = MAX_TEXTURE_LEVEL;
-   texTemp.width0 = 1 << MAX_TEXTURE_LEVEL;
-   texTemp.height0 = 1 << MAX_TEXTURE_LEVEL;
+   texTemp.width0 = 1 << TEXTURE_SIZE_LOG2;
+   texTemp.height0 = 1 << TEXTURE_SIZE_LOG2;
    texTemp.depth0 = 1;
    texTemp.array_size = 1;
    texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
@@ -461,7 +468,7 @@ aaline_create_texture(struct aaline_stage *aaline)
                d = 200; /* tuneable */
             }
             else if (i == 0 || j == 0 || i == size - 1 || j == size - 1) {
-               d = 0;
+               d = 35;  /* edge texel */
             }
             else {
                d = 255;
@@ -498,8 +505,7 @@ aaline_create_sampler(struct aaline_stage *aaline)
    sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
    sampler.normalized_coords = 1;
    sampler.min_lod = 0.0f;
-   /* avoid using the 1x1 and 2x2 mipmap levels */
-   sampler.max_lod = MAX_TEXTURE_LEVEL - 2;
+   sampler.max_lod = MAX_TEXTURE_LEVEL;
 
    aaline->sampler_cso = pipe->create_sampler_state(pipe, &sampler);
    if (aaline->sampler_cso == NULL)
index f5515c1df76c57161a7dc9cb6e5ce0b2010081e8..ea62c9739fd03de0d96b4ab2131b6b84f7ed3e42 100644 (file)
@@ -27,8 +27,9 @@
 
 /**
  * Polygon stipple stage:  implement polygon stipple with texture map and
- * fragment program.  The fragment program samples the texture and does
- * a fragment kill for the stipple-failing fragments.
+ * fragment program.  The fragment program samples the texture using the
+ * fragment window coordinate register and does a fragment kill for the
+ * stipple-failing fragments.
  *
  * Authors:  Brian Paul
  */
@@ -114,7 +115,8 @@ struct pstip_stage
 
 /**
  * Subclass of tgsi_transform_context, used for transforming the
- * user's fragment shader to add the special AA instructions.
+ * user's fragment shader to add the extra texture sample and fragment kill
+ * instructions.
  */
 struct pstip_transform_context {
    struct tgsi_transform_context base;
@@ -658,16 +660,16 @@ pstip_create_fs_state(struct pipe_context *pipe,
                        const struct pipe_shader_state *fs)
 {
    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
-   struct pstip_fragment_shader *aafs = CALLOC_STRUCT(pstip_fragment_shader);
+   struct pstip_fragment_shader *pstipfs = CALLOC_STRUCT(pstip_fragment_shader);
 
-   if (aafs) {
-      aafs->state = *fs;
+   if (pstipfs) {
+      pstipfs->state = *fs;
 
       /* pass-through */
-      aafs->driver_fs = pstip->driver_create_fs_state(pstip->pipe, fs);
+      pstipfs->driver_fs = pstip->driver_create_fs_state(pstip->pipe, fs);
    }
 
-   return aafs;
+   return pstipfs;
 }
 
 
@@ -675,12 +677,12 @@ static void
 pstip_bind_fs_state(struct pipe_context *pipe, void *fs)
 {
    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
-   struct pstip_fragment_shader *aafs = (struct pstip_fragment_shader *) fs;
+   struct pstip_fragment_shader *pstipfs = (struct pstip_fragment_shader *) fs;
    /* save current */
-   pstip->fs = aafs;
+   pstip->fs = pstipfs;
    /* pass-through */
    pstip->driver_bind_fs_state(pstip->pipe,
-                               (aafs ? aafs->driver_fs : NULL));
+                               (pstipfs ? pstipfs->driver_fs : NULL));
 }
 
 
@@ -688,14 +690,14 @@ static void
 pstip_delete_fs_state(struct pipe_context *pipe, void *fs)
 {
    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
-   struct pstip_fragment_shader *aafs = (struct pstip_fragment_shader *) fs;
+   struct pstip_fragment_shader *pstipfs = (struct pstip_fragment_shader *) fs;
    /* pass-through */
-   pstip->driver_delete_fs_state(pstip->pipe, aafs->driver_fs);
+   pstip->driver_delete_fs_state(pstip->pipe, pstipfs->driver_fs);
 
-   if (aafs->pstip_fs)
-      pstip->driver_delete_fs_state(pstip->pipe, aafs->pstip_fs);
+   if (pstipfs->pstip_fs)
+      pstip->driver_delete_fs_state(pstip->pipe, pstipfs->pstip_fs);
 
-   FREE(aafs);
+   FREE(pstipfs);
 }
 
 
index c575a8ac7caff68d5ffd3086adf3b218c61c5ee4..27afba5af3d8ae7e8b08ef270508b64f45934185 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 #include "util/u_memory.h"
+#include "util/u_math.h"
 #include "pipe/p_defines.h"
 #include "draw_private.h"
 #include "draw_pipe.h"
@@ -86,7 +87,7 @@ draw_need_pipeline(const struct draw_context *draw,
          return TRUE;
 
       /* wide lines */
-      if (rasterizer->line_width > draw->pipeline.wide_line_threshold)
+      if (roundf(rasterizer->line_width) > draw->pipeline.wide_line_threshold)
          return TRUE;
 
       /* AA lines */
@@ -169,7 +170,7 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage )
    stage->next = next;
 
    /* drawing wide lines? */
-   wide_lines = (rast->line_width > draw->pipeline.wide_line_threshold
+   wide_lines = (roundf(rast->line_width) > draw->pipeline.wide_line_threshold
                  && !rast->line_smooth);
 
    /* drawing large/sprite points (but not AA points)? */
index 06ed4d60ef287c34d2ae2a3ffd9660db0f80cabe..db2e3c5410d8c054151ae3c6ef665a2ec230a338 100644 (file)
@@ -286,6 +286,7 @@ struct draw_context
 
 #ifdef HAVE_LLVM
    struct draw_llvm *llvm;
+   struct gallivm_state *own_gallivm;
 #endif
 
    struct pipe_sampler_view *sampler_views[PIPE_MAX_VERTEX_SAMPLERS];
index 4078b2a07d035b1bda510dfaf0ab6949f8634f03..c3d7e871f7a3e54bb7a9db4fbbf7cd739ad76ab3 100644 (file)
@@ -459,10 +459,9 @@ draw_vbo(struct draw_context *draw,
       }
       debug_printf("Buffers:\n");
       for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
-         debug_printf("  %u: stride=%u maxindex=%u offset=%u ptr=%p\n",
+         debug_printf("  %u: stride=%u offset=%u ptr=%p\n",
                       i,
                       draw->pt.vertex_buffer[i].stride,
-                      draw->pt.vertex_buffer[i].max_index,
                       draw->pt.vertex_buffer[i].buffer_offset,
                       draw->pt.user.vbuffer[i]);
       }
index ae12ee24bdc36b2b7cfad30345a5712a4085e7a3..4fa3b265e10daf20876354614e5b9b6392fe7ed3 100644 (file)
@@ -139,7 +139,7 @@ void draw_pt_fetch_run( struct pt_fetch *fetch,
                            ((char *)draw->pt.user.vbuffer[i] + 
                             draw->pt.vertex_buffer[i].buffer_offset),
                            draw->pt.vertex_buffer[i].stride,
-                           draw->pt.vertex_buffer[i].max_index);
+                           draw->pt.user.max_index);
    }
 
    translate->run_elts( translate,
@@ -166,7 +166,7 @@ void draw_pt_fetch_run_linear( struct pt_fetch *fetch,
                            ((char *)draw->pt.user.vbuffer[i] +
                             draw->pt.vertex_buffer[i].buffer_offset),
                            draw->pt.vertex_buffer[i].stride,
-                           draw->pt.vertex_buffer[i].max_index);
+                           draw->pt.user.max_index);
    }
 
    translate->run( translate,
index e706b7796f82249e451196a61a5494ae208d03f4..51043102a6113e14f6169983dfee69cb9e5195d6 100644 (file)
@@ -186,7 +186,7 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
                                   ((char *)draw->pt.user.vbuffer[i] + 
                                    draw->pt.vertex_buffer[i].buffer_offset),
                                   draw->pt.vertex_buffer[i].stride,
-                                  draw->pt.vertex_buffer[i].max_index);
+                                  draw->pt.user.max_index);
    }
 
    *max_vertices = (draw->render->max_vertex_buffer_bytes / 
index c98fb3d5205a9dd4ed518e727ff416a9370287bc..1e926fb028ea069aacac2f2e560f7876f135b659 100644 (file)
@@ -169,7 +169,7 @@ static void fse_prepare( struct draw_pt_middle_end *middle,
                                ((const ubyte *) draw->pt.user.vbuffer[i] + 
                                 draw->pt.vertex_buffer[i].buffer_offset),
                               draw->pt.vertex_buffer[i].stride,
-                              draw->pt.vertex_buffer[i].max_index );
+                              draw->pt.user.max_index );
    }
 
    *max_vertices = (draw->render->max_vertex_buffer_bytes / 
index c43ee8ac6388d3b918cc33181f4c222c4e0561b4..c261d761161c2cea1bfeb99dc2d91d158b958839 100644 (file)
@@ -231,44 +231,53 @@ lp_build_unsigned_norm_to_float(struct gallivm_state *gallivm,
 
    assert(dst_type.floating);
 
-   /* Special-case int8->float, though most cases could be handled
-    * this way:
-    */
-   if (src_width == 8) {
-      scale = 1.0/255.0;
+   mantissa = lp_mantissa(dst_type);
+
+   if (src_width <= (mantissa + 1)) {
+      /*
+       * The source width matches fits what can be represented in floating
+       * point (i.e., mantissa + 1 bits). So do a straight multiplication
+       * followed by casting. No further rounding is necessary.
+       */
+
+      scale = 1.0/(double)((1ULL << src_width) - 1);
       res = LLVMBuildSIToFP(builder, src, vec_type, "");
       res = LLVMBuildFMul(builder, res,
                           lp_build_const_vec(gallivm, dst_type, scale), "");
       return res;
    }
+   else {
+      /*
+       * The source width exceeds what can be represented in floating
+       * point. So truncate the incoming values.
+       */
 
-   mantissa = lp_mantissa(dst_type);
-
-   n = MIN2(mantissa, src_width);
+      n = MIN2(mantissa, src_width);
 
-   ubound = ((unsigned long long)1 << n);
-   mask = ubound - 1;
-   scale = (double)ubound/mask;
-   bias = (double)((unsigned long long)1 << (mantissa - n));
+      ubound = ((unsigned long long)1 << n);
+      mask = ubound - 1;
+      scale = (double)ubound/mask;
+      bias = (double)((unsigned long long)1 << (mantissa - n));
 
-   res = src;
+      res = src;
 
-   if(src_width > mantissa) {
-      int shift = src_width - mantissa;
-      res = LLVMBuildLShr(builder, res,
-                          lp_build_const_int_vec(gallivm, dst_type, shift), "");
-   }
+      if (src_width > mantissa) {
+         int shift = src_width - mantissa;
+         res = LLVMBuildLShr(builder, res,
+                             lp_build_const_int_vec(gallivm, dst_type, shift), "");
+      }
 
-   bias_ = lp_build_const_vec(gallivm, dst_type, bias);
+      bias_ = lp_build_const_vec(gallivm, dst_type, bias);
 
-   res = LLVMBuildOr(builder,
-                     res,
-                     LLVMBuildBitCast(builder, bias_, int_vec_type, ""), "");
+      res = LLVMBuildOr(builder,
+                        res,
+                        LLVMBuildBitCast(builder, bias_, int_vec_type, ""), "");
 
-   res = LLVMBuildBitCast(builder, res, vec_type, "");
+      res = LLVMBuildBitCast(builder, res, vec_type, "");
 
-   res = LLVMBuildFSub(builder, res, bias_, "");
-   res = LLVMBuildFMul(builder, res, lp_build_const_vec(gallivm, dst_type, scale), "");
+      res = LLVMBuildFSub(builder, res, bias_, "");
+      res = LLVMBuildFMul(builder, res, lp_build_const_vec(gallivm, dst_type, scale), "");
+   }
 
    return res;
 }
index 7504cb5cf2fae17468568d30dc26401ec67809e6..45addee8fabb0db31334287ee8b4a3037ca6f396 100644 (file)
@@ -222,11 +222,12 @@ free_gallivm_state(struct gallivm_state *gallivm)
 static boolean
 init_gallivm_state(struct gallivm_state *gallivm)
 {
-   assert(gallivm_initialized);
    assert(!gallivm->context);
    assert(!gallivm->module);
    assert(!gallivm->provider);
 
+   lp_build_init();
+
    gallivm->context = LLVMContextCreate();
    if (!gallivm->context)
       goto fail;
@@ -387,6 +388,9 @@ gallivm_garbage_collect(struct gallivm_state *gallivm)
 void
 lp_build_init(void)
 {
+   if (gallivm_initialized)
+      return;
+
 #ifdef DEBUG
    gallivm_debug = debug_get_option_gallivm_debug();
 #endif
index 2ef02160f23ef606ce9b67dc7461678fa5b4398e..960068c494db584ae2a81bf0dc01236b91bcb70a 100644 (file)
@@ -82,6 +82,10 @@ struct pb_manager
     */
    void
    (*flush)( struct pb_manager *mgr );
+
+   boolean
+   (*is_buffer_busy)( struct pb_manager *mgr,
+                      struct pb_buffer *buf );
 };
 
 
index a6eb4039621f6fbfe047f62e337b0740c949b54f..25accefa8d6412807397fd087ac897b47620874d 100644 (file)
@@ -227,8 +227,6 @@ pb_cache_is_buffer_compat(struct pb_cache_buffer *buf,
                           pb_size size,
                           const struct pb_desc *desc)
 {
-   void *map;
-
    if(buf->base.base.size < size)
       return 0;
 
@@ -242,13 +240,18 @@ pb_cache_is_buffer_compat(struct pb_cache_buffer *buf,
    if(!pb_check_usage(desc->usage, buf->base.base.usage))
       return 0;
 
-   map = pb_map(buf->buffer, PB_USAGE_DONTBLOCK, NULL);
-   if (!map) {
-      return -1;
+   if (buf->mgr->provider->is_buffer_busy) {
+      if (buf->mgr->provider->is_buffer_busy(buf->mgr->provider, buf->buffer))
+         return -1;
+   } else {
+      void *ptr = pb_map(buf->buffer, PB_USAGE_DONTBLOCK, NULL);
+
+      if (!ptr)
+         return -1;
+
+      pb_unmap(buf->buffer);
    }
 
-   pb_unmap(buf->buffer);
-   
    return 1;
 }
 
index 75b0f6a68ea555da2cd6ca39539e4621e826e454..b03dd3a0cf88433bd58d8e4deae6b8e2c6d6a370 100644 (file)
@@ -2132,7 +2132,8 @@ struct x86_reg x86_fn_arg( struct x86_function *p,
       return x86_make_disp(x86_make_reg(file_REG32, reg_SP),
                        p->stack_offset + arg * 4);     /* ??? */
    default:
-      abort();
+      assert(0 && "Unexpected x86 target ABI in x86_fn_arg");
+      return x86_make_reg(file_REG32, reg_CX); /* not used / silence warning */
    }
 }
 
index 16a205f2068a869866221098cd1a4934d0bab119..d2cb98e84af00042c275cda09d414989f769c838 100644 (file)
@@ -26,6 +26,7 @@
  **************************************************************************/
 
 #include "util/u_debug.h"
+#include "pipe/p_format.h"
 #include "pipe/p_shader_tokens.h"
 #include "tgsi_build.h"
 #include "tgsi_parse.h"
@@ -226,6 +227,45 @@ tgsi_build_declaration_semantic(
    return ds;
 }
 
+
+static struct tgsi_declaration_resource
+tgsi_default_declaration_resource(void)
+{
+   struct tgsi_declaration_resource declaration_resource;
+
+   declaration_resource.Resource = TGSI_TEXTURE_UNKNOWN;
+   declaration_resource.ReturnTypeX = PIPE_TYPE_UNORM;
+   declaration_resource.ReturnTypeY = PIPE_TYPE_UNORM;
+   declaration_resource.ReturnTypeZ = PIPE_TYPE_UNORM;
+   declaration_resource.ReturnTypeW = PIPE_TYPE_UNORM;
+
+   return declaration_resource;
+}
+
+static struct tgsi_declaration_resource
+tgsi_build_declaration_resource(unsigned texture,
+                                unsigned return_type_x,
+                                unsigned return_type_y,
+                                unsigned return_type_z,
+                                unsigned return_type_w,
+                                struct tgsi_declaration *declaration,
+                                struct tgsi_header *header)
+{
+   struct tgsi_declaration_resource declaration_resource;
+
+   declaration_resource = tgsi_default_declaration_resource();
+   declaration_resource.Resource = texture;
+   declaration_resource.ReturnTypeX = return_type_x;
+   declaration_resource.ReturnTypeY = return_type_y;
+   declaration_resource.ReturnTypeZ = return_type_z;
+   declaration_resource.ReturnTypeW = return_type_w;
+
+   declaration_grow(declaration, header);
+
+   return declaration_resource;
+}
+
+
 struct tgsi_full_declaration
 tgsi_default_full_declaration( void )
 {
@@ -235,6 +275,7 @@ tgsi_default_full_declaration( void )
    full_declaration.Range = tgsi_default_declaration_range();
    full_declaration.Semantic = tgsi_default_declaration_semantic();
    full_declaration.ImmediateData.u = NULL;
+   full_declaration.Resource = tgsi_default_declaration_resource();
 
    return full_declaration;
 }
@@ -324,6 +365,24 @@ tgsi_build_full_declaration(
       }
    }
 
+   if (full_decl->Declaration.File == TGSI_FILE_RESOURCE) {
+      struct tgsi_declaration_resource *dr;
+
+      if (maxsize <= size) {
+         return  0;
+      }
+      dr = (struct tgsi_declaration_resource *)&tokens[size];
+      size++;
+
+      *dr = tgsi_build_declaration_resource(full_decl->Resource.Resource,
+                                            full_decl->Resource.ReturnTypeX,
+                                            full_decl->Resource.ReturnTypeY,
+                                            full_decl->Resource.ReturnTypeZ,
+                                            full_decl->Resource.ReturnTypeW,
+                                            declaration,
+                                            header);
+   }
+
    return size;
 }
 
index 82cd8eaa969b03f4236adf12aca127b0f23821df..c12662076b1bf069ad30a3ee25874e60a4276640 100644 (file)
@@ -104,7 +104,8 @@ tgsi_file_names[TGSI_FILE_COUNT] =
    "PRED",
    "SV",
    "IMMX",
-   "TEMPX"
+   "TEMPX",
+   "RES"
 };
 
 static const char *interpolate_names[] =
@@ -157,7 +158,9 @@ tgsi_texture_names[TGSI_TEXTURE_COUNT] =
    "RECT",
    "SHADOW1D",
    "SHADOW2D",
-   "SHADOWRECT"
+   "SHADOWRECT",
+   "1DARRAY",
+   "2DARRAY"
 };
 
 const char *tgsi_property_names[TGSI_PROPERTY_COUNT] =
@@ -170,6 +173,15 @@ const char *tgsi_property_names[TGSI_PROPERTY_COUNT] =
    "FS_COLOR0_WRITES_ALL_CBUFS",
 };
 
+static const char *tgsi_type_names[] =
+{
+   "UNORM",
+   "SNORM",
+   "SINT",
+   "UINT",
+   "FLOAT"
+};
+
 const char *tgsi_primitive_names[PIPE_PRIM_MAX] =
 {
    "POINTS",
@@ -393,6 +405,26 @@ iter_declaration(
       }
    }
 
+   if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
+      TXT(", ");
+      ENM(decl->Resource.Resource, tgsi_texture_names);
+      TXT(", ");
+      if ((decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeY) &&
+          (decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeZ) &&
+          (decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeW)) {
+         ENM(decl->Resource.ReturnTypeX, tgsi_type_names);
+      } else {
+         ENM(decl->Resource.ReturnTypeX, tgsi_type_names);
+         TXT(", ");
+         ENM(decl->Resource.ReturnTypeY, tgsi_type_names);
+         TXT(", ");
+         ENM(decl->Resource.ReturnTypeZ, tgsi_type_names);
+         TXT(", ");
+         ENM(decl->Resource.ReturnTypeW, tgsi_type_names);
+      }
+
+   }
+
    if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT &&
        decl->Declaration.File == TGSI_FILE_INPUT)
    {
index 35b2742351300e1c1ea7c15485f5bb4ddb2323bb..cbb090b2803c08849c2aa2a4d09f7f01f11686fa 100644 (file)
@@ -1750,6 +1750,36 @@ exec_tex(struct tgsi_exec_machine *mach,
                   &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       break;
 
+   case TGSI_TEXTURE_1D_ARRAY:
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+
+      if (modifier == TEX_MODIFIER_PROJECTED) {
+         micro_div(&r[0], &r[0], &r[3]);
+      }
+
+      fetch_texel(mach->Samplers[unit],
+                  &r[0], &r[1], &r[2], lod,     /* S, T, P, LOD */
+                  control,
+                  &r[0], &r[1], &r[2], &r[3]);  /* outputs */
+      break;
+
+   case TGSI_TEXTURE_2D_ARRAY:
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+      FETCH(&r[2], 0, CHAN_Z);
+
+      if (modifier == TEX_MODIFIER_PROJECTED) {
+         micro_div(&r[0], &r[0], &r[3]);
+         micro_div(&r[1], &r[1], &r[3]);
+      }
+
+      fetch_texel(mach->Samplers[unit],
+                  &r[0], &r[1], &r[2], lod,     /* S, T, P, LOD */
+                  control,
+                  &r[0], &r[1], &r[2], &r[3]);  /* outputs */
+      break;
+
    case TGSI_TEXTURE_3D:
    case TGSI_TEXTURE_CUBE:
       FETCH(&r[0], 0, CHAN_X);
@@ -1843,6 +1873,164 @@ exec_txd(struct tgsi_exec_machine *mach,
 }
 
 
+
+static void
+exec_sample(struct tgsi_exec_machine *mach,
+            const struct tgsi_full_instruction *inst,
+            uint modifier)
+{
+   const uint resource_unit = inst->Src[1].Register.Index;
+   const uint sampler_unit = inst->Src[2].Register.Index;
+   union tgsi_exec_channel r[4];
+   const union tgsi_exec_channel *lod = &ZeroVec;
+   enum tgsi_sampler_control control;
+   uint chan;
+
+   if (modifier != TEX_MODIFIER_NONE) {
+      if (modifier == TEX_MODIFIER_LOD_BIAS)
+         FETCH(&r[3], 3, CHAN_X);
+      else /*TEX_MODIFIER_LOD*/
+         FETCH(&r[3], 0, CHAN_W);
+
+      if (modifier != TEX_MODIFIER_PROJECTED) {
+         lod = &r[3];
+      }
+   }
+
+   if (modifier == TEX_MODIFIER_EXPLICIT_LOD) {
+      control = tgsi_sampler_lod_explicit;
+   } else {
+      control = tgsi_sampler_lod_bias;
+   }
+
+   switch (mach->Resources[resource_unit].Resource) {
+   case TGSI_TEXTURE_1D:
+   case TGSI_TEXTURE_SHADOW1D:
+      FETCH(&r[0], 0, CHAN_X);
+
+      if (modifier == TEX_MODIFIER_PROJECTED) {
+         micro_div(&r[0], &r[0], &r[3]);
+      }
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &ZeroVec, &ZeroVec, lod,  /* S, T, P, LOD */
+                  control,
+                  &r[0], &r[1], &r[2], &r[3]);     /* R, G, B, A */
+      break;
+
+   case TGSI_TEXTURE_2D:
+   case TGSI_TEXTURE_RECT:
+   case TGSI_TEXTURE_SHADOW2D:
+   case TGSI_TEXTURE_SHADOWRECT:
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+      FETCH(&r[2], 0, CHAN_Z);
+
+      if (modifier == TEX_MODIFIER_PROJECTED) {
+         micro_div(&r[0], &r[0], &r[3]);
+         micro_div(&r[1], &r[1], &r[3]);
+         micro_div(&r[2], &r[2], &r[3]);
+      }
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &r[1], &r[2], lod,     /* S, T, P, LOD */
+                  control,
+                  &r[0], &r[1], &r[2], &r[3]);  /* outputs */
+      break;
+
+   case TGSI_TEXTURE_3D:
+   case TGSI_TEXTURE_CUBE:
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+      FETCH(&r[2], 0, CHAN_Z);
+
+      if (modifier == TEX_MODIFIER_PROJECTED) {
+         micro_div(&r[0], &r[0], &r[3]);
+         micro_div(&r[1], &r[1], &r[3]);
+         micro_div(&r[2], &r[2], &r[3]);
+      }
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &r[1], &r[2], lod,
+                  control,
+                  &r[0], &r[1], &r[2], &r[3]);
+      break;
+
+   default:
+      assert(0);
+   }
+
+   for (chan = 0; chan < NUM_CHANNELS; chan++) {
+      if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
+         store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
+      }
+   }
+}
+
+static void
+exec_sample_d(struct tgsi_exec_machine *mach,
+              const struct tgsi_full_instruction *inst)
+{
+   const uint resource_unit = inst->Src[1].Register.Index;
+   const uint sampler_unit = inst->Src[2].Register.Index;
+   union tgsi_exec_channel r[4];
+   uint chan;
+   /*
+    * XXX: This is fake SAMPLE_D -- the derivatives are not taken into account, yet.
+    */
+
+   switch (mach->Resources[resource_unit].Resource) {
+   case TGSI_TEXTURE_1D:
+   case TGSI_TEXTURE_SHADOW1D:
+
+      FETCH(&r[0], 0, CHAN_X);
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &ZeroVec, &ZeroVec, &ZeroVec,   /* S, T, P, BIAS */
+                  tgsi_sampler_lod_bias,
+                  &r[0], &r[1], &r[2], &r[3]);           /* R, G, B, A */
+      break;
+
+   case TGSI_TEXTURE_2D:
+   case TGSI_TEXTURE_RECT:
+   case TGSI_TEXTURE_SHADOW2D:
+   case TGSI_TEXTURE_SHADOWRECT:
+
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+      FETCH(&r[2], 0, CHAN_Z);
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &r[1], &r[2], &ZeroVec,   /* inputs */
+                  tgsi_sampler_lod_bias,
+                  &r[0], &r[1], &r[2], &r[3]);     /* outputs */
+      break;
+
+   case TGSI_TEXTURE_3D:
+   case TGSI_TEXTURE_CUBE:
+
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+      FETCH(&r[2], 0, CHAN_Z);
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &r[1], &r[2], &ZeroVec,
+                  tgsi_sampler_lod_bias,
+                  &r[0], &r[1], &r[2], &r[3]);
+      break;
+
+   default:
+      assert(0);
+   }
+
+   for (chan = 0; chan < NUM_CHANNELS; chan++) {
+      if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
+         store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
+      }
+   }
+}
+
+
 /**
  * Evaluate a constant-valued coefficient at the position of the
  * current quad.
@@ -1914,6 +2102,11 @@ static void
 exec_declaration(struct tgsi_exec_machine *mach,
                  const struct tgsi_full_declaration *decl)
 {
+   if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
+      mach->Resources[decl->Range.First] = decl->Resource;
+      return;
+   }
+
    if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) {
       if (decl->Declaration.File == TGSI_FILE_INPUT) {
          uint first, last, mask;
@@ -3688,6 +3881,54 @@ exec_instruction(
       exec_endswitch(mach);
       break;
 
+   case TGSI_OPCODE_LOAD:
+      assert(0);
+      break;
+
+   case TGSI_OPCODE_LOAD_MS:
+      assert(0);
+      break;
+
+   case TGSI_OPCODE_SAMPLE:
+      exec_sample(mach, inst, TEX_MODIFIER_NONE);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_B:
+      exec_sample(mach, inst, TEX_MODIFIER_LOD_BIAS);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_C:
+      exec_sample(mach, inst, TEX_MODIFIER_NONE);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_C_LZ:
+      exec_sample(mach, inst, TEX_MODIFIER_LOD_BIAS);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_D:
+      exec_sample_d(mach, inst);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_L:
+      exec_sample(mach, inst, TEX_MODIFIER_EXPLICIT_LOD);
+      break;
+
+   case TGSI_OPCODE_GATHER4:
+      assert(0);
+      break;
+
+   case TGSI_OPCODE_RESINFO:
+      assert(0);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_POS:
+      assert(0);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_INFO:
+      assert(0);
+      break;
+
    default:
       assert( 0 );
    }
index 6c204c737144f953fc973d3c404a3738a8a2c13e..4a423b5bb4e27acc30b2fcb49c85c60cdad9a08d 100644 (file)
@@ -308,6 +308,7 @@ struct tgsi_exec_machine
    struct tgsi_full_declaration *Declarations;
    uint NumDeclarations;
 
+   struct tgsi_declaration_resource Resources[PIPE_MAX_SHADER_RESOURCES];
 };
 
 struct tgsi_exec_machine *
index e59e964ffa77a8d160605ea54bf6ba375a6d3afc..14ed56a1f6abd7fe13df9ddb25efb7b05b60c046 100644 (file)
@@ -175,7 +175,20 @@ static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] =
    { 0, 1, 0, 0, 0, 0, "SWITCH", TGSI_OPCODE_SWITCH },
    { 0, 1, 0, 0, 0, 0, "CASE", TGSI_OPCODE_CASE },
    { 0, 0, 0, 0, 0, 0, "DEFAULT", TGSI_OPCODE_DEFAULT },
-   { 0, 0, 0, 0, 0, 0, "ENDSWITCH", TGSI_OPCODE_ENDSWITCH }
+   { 0, 0, 0, 0, 0, 0, "ENDSWITCH", TGSI_OPCODE_ENDSWITCH },
+
+   { 1, 2, 0, 0, 0, 0, "LOAD",        TGSI_OPCODE_LOAD },
+   { 1, 2, 0, 0, 0, 0, "LOAD_MS",     TGSI_OPCODE_LOAD_MS },
+   { 1, 3, 0, 0, 0, 0, "SAMPLE",      TGSI_OPCODE_SAMPLE },
+   { 1, 4, 0, 0, 0, 0, "SAMPLE_B",    TGSI_OPCODE_SAMPLE_B },
+   { 1, 4, 0, 0, 0, 0, "SAMPLE_C",    TGSI_OPCODE_SAMPLE_C },
+   { 1, 4, 0, 0, 0, 0, "SAMPLE_C_LZ", TGSI_OPCODE_SAMPLE_C_LZ },
+   { 1, 5, 0, 0, 0, 0, "SAMPLE_D",    TGSI_OPCODE_SAMPLE_D },
+   { 1, 3, 0, 0, 0, 0, "SAMPLE_L",    TGSI_OPCODE_SAMPLE_L },
+   { 1, 3, 0, 0, 0, 0, "GATHER4",     TGSI_OPCODE_GATHER4 },
+   { 1, 2, 0, 0, 0, 0, "RESINFO",     TGSI_OPCODE_RESINFO },
+   { 1, 2, 0, 0, 0, 0, "SAMPLE_POS",  TGSI_OPCODE_SAMPLE_POS },
+   { 1, 2, 0, 0, 0, 0, "SAMPLE_INFO", TGSI_OPCODE_SAMPLE_INFO },
 };
 
 const struct tgsi_opcode_info *
index b3123ed016d606fbf1ba6651a3fb097a040281f4..b5d4504425ba9d64b9b67f98fa8f847ffb5072f3 100644 (file)
@@ -168,6 +168,19 @@ OP01(CASE)
 OP00(DEFAULT)
 OP00(ENDSWITCH)
 
+OP12(LOAD)
+OP12(LOAD_MS)
+OP13(SAMPLE)
+OP14(SAMPLE_B)
+OP14(SAMPLE_C)
+OP14(SAMPLE_C_LZ)
+OP15(SAMPLE_D)
+OP13(SAMPLE_L)
+OP13(GATHER4)
+OP12(RESINFO)
+OP13(SAMPLE_POS)
+OP12(SAMPLE_INFO)
+
 
 #undef OP00
 #undef OP01
@@ -180,6 +193,10 @@ OP00(ENDSWITCH)
 #undef OP14
 #endif
 
+#ifdef OP15
+#undef OP15
+#endif
+
 #undef OP00_LBL
 #undef OP01_LBL
 
index 1891203abe17acc2ce39151b52e15e4ac885abdd..fb36f9de32dcd06b0c883b41c78535dcf5796d10 100644 (file)
@@ -128,6 +128,10 @@ tgsi_parse_token(
          }
       }
 
+      if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
+         next_token(ctx, &decl->Resource);
+      }
+
       break;
    }
 
index 2aafa2a6e839a536f87569da924dbda812834e31..b7a3c9bc0e600132649085d50286bf894049ffe8 100644 (file)
@@ -69,6 +69,7 @@ struct tgsi_full_declaration
    struct tgsi_declaration_dimension Dim;
    struct tgsi_declaration_semantic Semantic;
    struct tgsi_immediate_array_data ImmediateData;
+   struct tgsi_declaration_resource Resource;
 };
 
 struct tgsi_full_immediate
@@ -84,7 +85,7 @@ struct tgsi_full_property
 };
 
 #define TGSI_FULL_MAX_DST_REGISTERS 2
-#define TGSI_FULL_MAX_SRC_REGISTERS 4 /* TXD has 4 */
+#define TGSI_FULL_MAX_SRC_REGISTERS 5 /* SAMPLE_D has 5 */
 
 struct tgsi_full_instruction
 {
index acbff103efe2d1ee9c43c7cb888e801119a6488d..509c534683789673c8ebd8ee5be65867af8131ac 100644 (file)
@@ -258,7 +258,8 @@ static const char *file_names[TGSI_FILE_COUNT] =
    "PRED",
    "SV",
    "IMMX",
-   "TEMPX"
+   "TEMPX",
+   "RES"
 };
 
 static boolean
index 3f2cda860e0790ea08281df97473cf4b20afcb66..92ba8b8f033225fa008c9c3b558acc4aec4bd894 100644 (file)
@@ -1514,6 +1514,7 @@ emit_tex( struct x86_function *func,
       break;
    case TGSI_TEXTURE_2D:
    case TGSI_TEXTURE_RECT:
+   case TGSI_TEXTURE_1D_ARRAY:
       count = 2;
       break;
    case TGSI_TEXTURE_SHADOW1D:
@@ -1521,6 +1522,7 @@ emit_tex( struct x86_function *func,
    case TGSI_TEXTURE_SHADOWRECT:
    case TGSI_TEXTURE_3D:
    case TGSI_TEXTURE_CUBE:
+   case TGSI_TEXTURE_2D_ARRAY:
       count = 3;
       break;
    default:
index 819b0725a1faaea9e9edd354ea2c76fbb18c93ad..1eac762e6e522a53f967322b6a29bd549a65fa82 100644 (file)
@@ -283,7 +283,8 @@ static const char *file_names[TGSI_FILE_COUNT] =
    "PRED",
    "SV",
    "IMMX",
-   "TEMPX"
+   "TEMPX",
+   "RES"
 };
 
 static boolean
@@ -828,6 +829,15 @@ static const char *texture_names[TGSI_TEXTURE_COUNT] =
    "SHADOWRECT"
 };
 
+static const char *type_names[] =
+{
+   "UNORM",
+   "SNORM",
+   "SINT",
+   "UINT",
+   "FLOAT"
+};
+
 static boolean
 match_inst_mnemonic(const char **pcur,
                     const struct tgsi_opcode_info *info)
@@ -1104,42 +1114,113 @@ static boolean parse_declaration( struct translate_ctx *ctx )
    cur = ctx->cur;
    eat_opt_white( &cur );
    if (*cur == ',' && !is_vs_input) {
-      uint i;
+      uint i, j;
 
       cur++;
       eat_opt_white( &cur );
-      for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
-         if (str_match_no_case( &cur, semantic_names[i] )) {
-            const char *cur2 = cur;
-            uint index;
-
-            if (is_digit_alpha_underscore( cur ))
-               continue;
-            eat_opt_white( &cur2 );
-            if (*cur2 == '[') {
-               cur2++;
-               eat_opt_white( &cur2 );
-               if (!parse_uint( &cur2, &index )) {
-                  report_error( ctx, "Expected literal integer" );
+      if (file == TGSI_FILE_RESOURCE) {
+         for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
+            if (str_match_no_case(&cur, texture_names[i])) {
+               if (!is_digit_alpha_underscore(cur)) {
+                  decl.Resource.Resource = i;
+                  break;
+               }
+            }
+         }
+         if (i == TGSI_TEXTURE_COUNT) {
+            report_error(ctx, "Expected texture target");
+            return FALSE;
+         }
+         eat_opt_white( &cur );
+         if (*cur != ',') {
+            report_error( ctx, "Expected `,'" );
+            return FALSE;
+         }
+         ++cur;
+         eat_opt_white( &cur );
+         for (j = 0; j < 4; ++j) {
+            for (i = 0; i < PIPE_TYPE_COUNT; ++i) {
+               if (str_match_no_case(&cur, type_names[i])) {
+                  if (!is_digit_alpha_underscore(cur)) {
+                     switch (j) {
+                     case 0:
+                        decl.Resource.ReturnTypeX = i;
+                        break;
+                     case 1:
+                        decl.Resource.ReturnTypeY = i;
+                        break;
+                     case 2:
+                        decl.Resource.ReturnTypeZ = i;
+                        break;
+                     case 3:
+                        decl.Resource.ReturnTypeW = i;
+                        break;
+                     default:
+                        assert(0);
+                     }
+                     break;
+                  }
+               }
+            }
+            if (i == PIPE_TYPE_COUNT) {
+               if (j == 0 || j >  2) {
+                  report_error(ctx, "Expected type name");
                   return FALSE;
                }
+               break;
+            } else {
+               const char *cur2 = cur;
                eat_opt_white( &cur2 );
-               if (*cur2 != ']') {
-                  report_error( ctx, "Expected `]'" );
-                  return FALSE;
+               if (*cur2 == ',') {
+                  cur2++;
+                  eat_opt_white( &cur2 );
+                  cur = cur2;
+                  continue;
+               } else
+                  break;
+            }
+         }
+         if (j < 4) {
+            decl.Resource.ReturnTypeY =
+               decl.Resource.ReturnTypeZ =
+               decl.Resource.ReturnTypeW =
+               decl.Resource.ReturnTypeX;
+         }
+         ctx->cur = cur;
+      } else {
+         for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
+            if (str_match_no_case( &cur, semantic_names[i] )) {
+               const char *cur2 = cur;
+               uint index;
+
+               if (is_digit_alpha_underscore( cur ))
+                  continue;
+               eat_opt_white( &cur2 );
+               if (*cur2 == '[') {
+                  cur2++;
+                  eat_opt_white( &cur2 );
+                  if (!parse_uint( &cur2, &index )) {
+                     report_error( ctx, "Expected literal integer" );
+                     return FALSE;
+                  }
+                  eat_opt_white( &cur2 );
+                  if (*cur2 != ']') {
+                     report_error( ctx, "Expected `]'" );
+                     return FALSE;
+                  }
+                  cur2++;
+
+                  decl.Semantic.Index = index;
+
+                  cur = cur2;
                }
-               cur2++;
 
-               decl.Semantic.Index = index;
+               decl.Declaration.Semantic = 1;
+               decl.Semantic.Name = i;
 
-               cur = cur2;
+               ctx->cur = cur;
+               break;
             }
-
-            decl.Declaration.Semantic = 1;
-            decl.Semantic.Name = i;
-
-            ctx->cur = cur;
-            break;
          }
       }
    } else if (is_imm_array) {
index 02de12d77d50d1bda18fed5b275b3c9a36818b57..4564ab81f99d51775b6ef9c9427b1eaaad5d1e4c 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  * 
- * Copyright 2009 VMware, Inc.
+ * Copyright 2009-2010 VMware, Inc.
  * All Rights Reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -47,6 +47,7 @@ union tgsi_any_token {
    struct tgsi_declaration_range decl_range;
    struct tgsi_declaration_dimension decl_dim;
    struct tgsi_declaration_semantic decl_semantic;
+   struct tgsi_declaration_resource decl_resource;
    struct tgsi_immediate imm;
    union  tgsi_immediate_data imm_data;
    struct tgsi_instruction insn;
@@ -137,6 +138,16 @@ struct ureg_program
    struct ureg_src sampler[PIPE_MAX_SAMPLERS];
    unsigned nr_samplers;
 
+   struct {
+      unsigned index;
+      unsigned target;
+      unsigned return_type_x;
+      unsigned return_type_y;
+      unsigned return_type_z;
+      unsigned return_type_w;
+   } resource[PIPE_MAX_SHADER_RESOURCES];
+   unsigned nr_resources;
+
    unsigned temps_active[UREG_MAX_TEMP / 32];
    unsigned nr_temps;
 
@@ -578,6 +589,41 @@ struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg,
    return ureg->sampler[0];
 }
 
+/*
+ * Allocate a new shader resource.
+ */
+struct ureg_src
+ureg_DECL_resource(struct ureg_program *ureg,
+                   unsigned index,
+                   unsigned target,
+                   unsigned return_type_x,
+                   unsigned return_type_y,
+                   unsigned return_type_z,
+                   unsigned return_type_w)
+{
+   struct ureg_src reg = ureg_src_register(TGSI_FILE_RESOURCE, index);
+   uint i;
+
+   for (i = 0; i < ureg->nr_resources; i++) {
+      if (ureg->resource[i].index == index) {
+         return reg;
+      }
+   }
+
+   if (i < PIPE_MAX_SHADER_RESOURCES) {
+      ureg->resource[i].index = index;
+      ureg->resource[i].target = target;
+      ureg->resource[i].return_type_x = return_type_x;
+      ureg->resource[i].return_type_y = return_type_y;
+      ureg->resource[i].return_type_z = return_type_z;
+      ureg->resource[i].return_type_w = return_type_w;
+      ureg->nr_resources++;
+      return reg;
+   }
+
+   assert(0);
+   return reg;
+}
 
 static int
 match_or_expand_immediate( const unsigned *v,
@@ -821,9 +867,10 @@ ureg_emit_dst( struct ureg_program *ureg,
    assert(dst.File != TGSI_FILE_CONSTANT);
    assert(dst.File != TGSI_FILE_INPUT);
    assert(dst.File != TGSI_FILE_SAMPLER);
+   assert(dst.File != TGSI_FILE_RESOURCE);
    assert(dst.File != TGSI_FILE_IMMEDIATE);
    assert(dst.File < TGSI_FILE_COUNT);
-   
+
    out[n].value = 0;
    out[n].dst.File = dst.File;
    out[n].dst.WriteMask = dst.WriteMask;
@@ -1205,6 +1252,36 @@ emit_decl_range2D(struct ureg_program *ureg,
    out[2].decl_dim.Index2D = index2D;
 }
 
+static void
+emit_decl_resource(struct ureg_program *ureg,
+                   unsigned index,
+                   unsigned target,
+                   unsigned return_type_x,
+                   unsigned return_type_y,
+                   unsigned return_type_z,
+                   unsigned return_type_w )
+{
+   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
+
+   out[0].value = 0;
+   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
+   out[0].decl.NrTokens = 3;
+   out[0].decl.File = TGSI_FILE_RESOURCE;
+   out[0].decl.UsageMask = 0xf;
+   out[0].decl.Interpolate = TGSI_INTERPOLATE_CONSTANT;
+
+   out[1].value = 0;
+   out[1].decl_range.First = index;
+   out[1].decl_range.Last = index;
+
+   out[2].value = 0;
+   out[2].decl_resource.Resource    = target;
+   out[2].decl_resource.ReturnTypeX = return_type_x;
+   out[2].decl_resource.ReturnTypeY = return_type_y;
+   out[2].decl_resource.ReturnTypeZ = return_type_z;
+   out[2].decl_resource.ReturnTypeW = return_type_w;
+}
+
 static void
 emit_immediate( struct ureg_program *ureg,
                 const unsigned *v,
@@ -1341,6 +1418,16 @@ static void emit_decls( struct ureg_program *ureg )
                        ureg->sampler[i].Index, 1 );
    }
 
+   for (i = 0; i < ureg->nr_resources; i++) {
+      emit_decl_resource(ureg,
+                         ureg->resource[i].index,
+                         ureg->resource[i].target,
+                         ureg->resource[i].return_type_x,
+                         ureg->resource[i].return_type_y,
+                         ureg->resource[i].return_type_z,
+                         ureg->resource[i].return_type_w);
+   }
+
    if (ureg->const_decls.nr_constant_ranges) {
       for (i = 0; i < ureg->const_decls.nr_constant_ranges; i++) {
          emit_decl_range(ureg,
index 807128a5e52d77fca870239f77575924b60ab9d5..b8d193f3f8962c7b18f91a19cc980cf104b01fc0 100644 (file)
@@ -270,6 +270,15 @@ struct ureg_src
 ureg_DECL_sampler( struct ureg_program *,
                    unsigned index );
 
+struct ureg_src
+ureg_DECL_resource(struct ureg_program *,
+                   unsigned index,
+                   unsigned target,
+                   unsigned return_type_x,
+                   unsigned return_type_y,
+                   unsigned return_type_z,
+                   unsigned return_type_w );
+
 
 static INLINE struct ureg_src
 ureg_imm4f( struct ureg_program *ureg,
@@ -733,6 +742,66 @@ static INLINE void ureg_##op( struct ureg_program *ureg,                \
 }
 
 
+#define OP14( op )                                                      \
+static INLINE void ureg_##op( struct ureg_program *ureg,                \
+                              struct ureg_dst dst,                      \
+                              struct ureg_src src0,                     \
+                              struct ureg_src src1,                     \
+                              struct ureg_src src2,                     \
+                              struct ureg_src src3 )                    \
+{                                                                       \
+   unsigned opcode = TGSI_OPCODE_##op;                                  \
+   unsigned insn = ureg_emit_insn(ureg,                                 \
+                                  opcode,                               \
+                                  dst.Saturate,                         \
+                                  dst.Predicate,                        \
+                                  dst.PredNegate,                       \
+                                  dst.PredSwizzleX,                     \
+                                  dst.PredSwizzleY,                     \
+                                  dst.PredSwizzleZ,                     \
+                                  dst.PredSwizzleW,                     \
+                                  1,                                    \
+                                  4).insn_token;                        \
+   ureg_emit_dst( ureg, dst );                                          \
+   ureg_emit_src( ureg, src0 );                                         \
+   ureg_emit_src( ureg, src1 );                                         \
+   ureg_emit_src( ureg, src2 );                                         \
+   ureg_emit_src( ureg, src3 );                                         \
+   ureg_fixup_insn_size( ureg, insn );                                  \
+}
+
+
+#define OP15( op )                                                      \
+static INLINE void ureg_##op( struct ureg_program *ureg,                \
+                              struct ureg_dst dst,                      \
+                              struct ureg_src src0,                     \
+                              struct ureg_src src1,                     \
+                              struct ureg_src src2,                     \
+                              struct ureg_src src3,                     \
+                              struct ureg_src src4 )                    \
+{                                                                       \
+   unsigned opcode = TGSI_OPCODE_##op;                                  \
+   unsigned insn = ureg_emit_insn(ureg,                                 \
+                                  opcode,                               \
+                                  dst.Saturate,                         \
+                                  dst.Predicate,                        \
+                                  dst.PredNegate,                       \
+                                  dst.PredSwizzleX,                     \
+                                  dst.PredSwizzleY,                     \
+                                  dst.PredSwizzleZ,                     \
+                                  dst.PredSwizzleW,                     \
+                                  1,                                    \
+                                  5).insn_token;                        \
+   ureg_emit_dst( ureg, dst );                                          \
+   ureg_emit_src( ureg, src0 );                                         \
+   ureg_emit_src( ureg, src1 );                                         \
+   ureg_emit_src( ureg, src2 );                                         \
+   ureg_emit_src( ureg, src3 );                                         \
+   ureg_emit_src( ureg, src4 );                                         \
+   ureg_fixup_insn_size( ureg, insn );                                  \
+}
+
+
 /* Use a template include to generate a correctly-typed ureg_OP()
  * function for each TGSI opcode:
  */
index 08e7e89bd670e42fcb0a7aadd9ef50c15956316c..aa9a886d4a98322e74d99c610d50aee4a370da19 100644 (file)
@@ -280,7 +280,12 @@ tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction *inst,
          case TGSI_TEXTURE_CUBE:
             read_mask = TGSI_WRITEMASK_XYZ;
             break;
-
+         case TGSI_TEXTURE_1D_ARRAY:
+            read_mask = TGSI_WRITEMASK_XY;
+            break;
+         case TGSI_TEXTURE_2D_ARRAY:
+            read_mask = TGSI_WRITEMASK_XYZ;
+            break;
          default:
             assert(0);
             read_mask = 0;
index d8069a149cfe94569cd2728754dcc9d3c5d9e924..3f1ecb630f2ab5c989f17b6c3cb6129e86997ea7 100644 (file)
@@ -40,6 +40,10 @@ struct translate_cache {
 struct translate_cache * translate_cache_create( void )
 {
    struct translate_cache *cache = MALLOC_STRUCT(translate_cache);
+   if (cache == NULL) {
+      return NULL;
+   }
+
    cache->hash = cso_hash_create();
    return cache;
 }
diff --git a/src/gallium/auxiliary/util/dbghelp.h b/src/gallium/auxiliary/util/dbghelp.h
new file mode 100644 (file)
index 0000000..bc7c53c
--- /dev/null
@@ -0,0 +1,1265 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the w64 mingw-runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+#ifndef _DBGHELP_
+#define _DBGHELP_
+
+#ifdef _WIN64
+#ifndef _IMAGEHLP64
+#define _IMAGEHLP64
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define IMAGEAPI DECLSPEC_IMPORT WINAPI
+#define DBHLP_DEPRECIATED __declspec(deprecated)
+
+#define DBHLPAPI IMAGEAPI
+
+#define IMAGE_SEPARATION (64*1024)
+
+  typedef struct _LOADED_IMAGE {
+    PSTR ModuleName;
+    HANDLE hFile;
+    PUCHAR MappedAddress;
+#ifdef _IMAGEHLP64
+    PIMAGE_NT_HEADERS64 FileHeader;
+#else
+    PIMAGE_NT_HEADERS32 FileHeader;
+#endif
+    PIMAGE_SECTION_HEADER LastRvaSection;
+    ULONG NumberOfSections;
+    PIMAGE_SECTION_HEADER Sections;
+    ULONG Characteristics;
+    BOOLEAN fSystemImage;
+    BOOLEAN fDOSImage;
+    LIST_ENTRY Links;
+    ULONG SizeOfImage;
+  } LOADED_IMAGE,*PLOADED_IMAGE;
+
+#define MAX_SYM_NAME 2000
+
+  typedef BOOL (CALLBACK *PFIND_DEBUG_FILE_CALLBACK)(HANDLE FileHandle,PSTR FileName,PVOID CallerData);
+  typedef BOOL (CALLBACK *PFINDFILEINPATHCALLBACK)(PSTR filename,PVOID context);
+  typedef BOOL (CALLBACK *PFIND_EXE_FILE_CALLBACK)(HANDLE FileHandle,PSTR FileName,PVOID CallerData);
+
+  typedef BOOL (WINAPI *PSYMBOLSERVERPROC)(LPCSTR,LPCSTR,PVOID,DWORD,DWORD,LPSTR);
+  typedef BOOL (WINAPI *PSYMBOLSERVEROPENPROC)(VOID);
+  typedef BOOL (WINAPI *PSYMBOLSERVERCLOSEPROC)(VOID);
+  typedef BOOL (WINAPI *PSYMBOLSERVERSETOPTIONSPROC)(UINT_PTR,ULONG64);
+  typedef BOOL (CALLBACK WINAPI *PSYMBOLSERVERCALLBACKPROC)(UINT_PTR action,ULONG64 data,ULONG64 context);
+  typedef UINT_PTR (WINAPI *PSYMBOLSERVERGETOPTIONSPROC)();
+  typedef BOOL (WINAPI *PSYMBOLSERVERPINGPROC)(LPCSTR);
+
+  HANDLE IMAGEAPI FindDebugInfoFile(PSTR FileName,PSTR SymbolPath,PSTR DebugFilePath);
+  HANDLE IMAGEAPI FindDebugInfoFileEx(PSTR FileName,PSTR SymbolPath,PSTR DebugFilePath,PFIND_DEBUG_FILE_CALLBACK Callback,PVOID CallerData);
+  BOOL IMAGEAPI SymFindFileInPath(HANDLE hprocess,LPSTR SearchPath,LPSTR FileName,PVOID id,DWORD two,DWORD three,DWORD flags,LPSTR FoundFile,PFINDFILEINPATHCALLBACK callback,PVOID context);
+  HANDLE IMAGEAPI FindExecutableImage(PSTR FileName,PSTR SymbolPath,PSTR ImageFilePath);
+  HANDLE IMAGEAPI FindExecutableImageEx(PSTR FileName,PSTR SymbolPath,PSTR ImageFilePath,PFIND_EXE_FILE_CALLBACK Callback,PVOID CallerData);
+  PIMAGE_NT_HEADERS IMAGEAPI ImageNtHeader(PVOID Base);
+  PVOID IMAGEAPI ImageDirectoryEntryToDataEx(PVOID Base,BOOLEAN MappedAsImage,USHORT DirectoryEntry,PULONG Size,PIMAGE_SECTION_HEADER *FoundHeader);
+  PVOID IMAGEAPI ImageDirectoryEntryToData(PVOID Base,BOOLEAN MappedAsImage,USHORT DirectoryEntry,PULONG Size);
+  PIMAGE_SECTION_HEADER IMAGEAPI ImageRvaToSection(PIMAGE_NT_HEADERS NtHeaders,PVOID Base,ULONG Rva);
+  PVOID IMAGEAPI ImageRvaToVa(PIMAGE_NT_HEADERS NtHeaders,PVOID Base,ULONG Rva,PIMAGE_SECTION_HEADER *LastRvaSection);
+
+#define SSRVOPT_CALLBACK 0x0001
+#define SSRVOPT_DWORD 0x0002
+#define SSRVOPT_DWORDPTR 0x0004
+#define SSRVOPT_GUIDPTR 0x0008
+#define SSRVOPT_OLDGUIDPTR 0x0010
+#define SSRVOPT_UNATTENDED 0x0020
+#define SSRVOPT_NOCOPY 0x0040
+#define SSRVOPT_PARENTWIN 0x0080
+#define SSRVOPT_PARAMTYPE 0x0100
+#define SSRVOPT_SECURE 0x0200
+#define SSRVOPT_TRACE 0x0400
+#define SSRVOPT_SETCONTEXT 0x0800
+#define SSRVOPT_PROXY 0x1000
+#define SSRVOPT_DOWNSTREAM_STORE 0x2000
+#define SSRVOPT_RESET ((ULONG_PTR)-1)
+
+#define SSRVACTION_TRACE 1
+#define SSRVACTION_QUERYCANCEL 2
+#define SSRVACTION_EVENT 3
+
+#ifndef _WIN64
+
+  typedef struct _IMAGE_DEBUG_INFORMATION {
+    LIST_ENTRY List;
+    DWORD ReservedSize;
+    PVOID ReservedMappedBase;
+    USHORT ReservedMachine;
+    USHORT ReservedCharacteristics;
+    DWORD ReservedCheckSum;
+    DWORD ImageBase;
+    DWORD SizeOfImage;
+    DWORD ReservedNumberOfSections;
+    PIMAGE_SECTION_HEADER ReservedSections;
+    DWORD ReservedExportedNamesSize;
+    PSTR ReservedExportedNames;
+    DWORD ReservedNumberOfFunctionTableEntries;
+    PIMAGE_FUNCTION_ENTRY ReservedFunctionTableEntries;
+    DWORD ReservedLowestFunctionStartingAddress;
+    DWORD ReservedHighestFunctionEndingAddress;
+    DWORD ReservedNumberOfFpoTableEntries;
+    PFPO_DATA ReservedFpoTableEntries;
+    DWORD SizeOfCoffSymbols;
+    PIMAGE_COFF_SYMBOLS_HEADER CoffSymbols;
+    DWORD ReservedSizeOfCodeViewSymbols;
+    PVOID ReservedCodeViewSymbols;
+    PSTR ImageFilePath;
+    PSTR ImageFileName;
+    PSTR ReservedDebugFilePath;
+    DWORD ReservedTimeDateStamp;
+    BOOL ReservedRomImage;
+    PIMAGE_DEBUG_DIRECTORY ReservedDebugDirectory;
+    DWORD ReservedNumberOfDebugDirectories;
+    DWORD ReservedOriginalFunctionTableBaseAddress;
+    DWORD Reserved[2 ];
+  } IMAGE_DEBUG_INFORMATION,*PIMAGE_DEBUG_INFORMATION;
+
+  PIMAGE_DEBUG_INFORMATION IMAGEAPI MapDebugInformation(HANDLE FileHandle,PSTR FileName,PSTR SymbolPath,DWORD ImageBase);
+  BOOL IMAGEAPI UnmapDebugInformation(PIMAGE_DEBUG_INFORMATION DebugInfo);
+#endif
+
+  typedef BOOL (CALLBACK *PENUMDIRTREE_CALLBACK)(LPCSTR FilePath,PVOID CallerData);
+
+  BOOL IMAGEAPI SearchTreeForFile(PSTR RootPath,PSTR InputPathName,PSTR OutputPathBuffer);
+  BOOL IMAGEAPI EnumDirTree(HANDLE hProcess,PSTR RootPath,PSTR InputPathName,PSTR OutputPathBuffer,PENUMDIRTREE_CALLBACK Callback,PVOID CallbackData);
+  BOOL IMAGEAPI MakeSureDirectoryPathExists(PCSTR DirPath);
+
+#define UNDNAME_COMPLETE (0x0000)
+#define UNDNAME_NO_LEADING_UNDERSCORES (0x0001)
+#define UNDNAME_NO_MS_KEYWORDS (0x0002)
+#define UNDNAME_NO_FUNCTION_RETURNS (0x0004)
+#define UNDNAME_NO_ALLOCATION_MODEL (0x0008)
+#define UNDNAME_NO_ALLOCATION_LANGUAGE (0x0010)
+#define UNDNAME_NO_MS_THISTYPE (0x0020)
+#define UNDNAME_NO_CV_THISTYPE (0x0040)
+#define UNDNAME_NO_THISTYPE (0x0060)
+#define UNDNAME_NO_ACCESS_SPECIFIERS (0x0080)
+#define UNDNAME_NO_THROW_SIGNATURES (0x0100)
+#define UNDNAME_NO_MEMBER_TYPE (0x0200)
+#define UNDNAME_NO_RETURN_UDT_MODEL (0x0400)
+#define UNDNAME_32_BIT_DECODE (0x0800)
+#define UNDNAME_NAME_ONLY (0x1000)
+#define UNDNAME_NO_ARGUMENTS (0x2000)
+#define UNDNAME_NO_SPECIAL_SYMS (0x4000)
+
+  DWORD IMAGEAPI WINAPI UnDecorateSymbolName(PCSTR DecoratedName,PSTR UnDecoratedName,DWORD UndecoratedLength,DWORD Flags);
+
+#define DBHHEADER_DEBUGDIRS 0x1
+
+  typedef struct _MODLOAD_DATA {
+    DWORD ssize;
+    DWORD ssig;
+    PVOID data;
+    DWORD size;
+    DWORD flags;
+  } MODLOAD_DATA,*PMODLOAD_DATA;
+
+  typedef enum {
+    AddrMode1616,AddrMode1632,AddrModeReal,AddrModeFlat
+  } ADDRESS_MODE;
+
+  typedef struct _tagADDRESS64 {
+    DWORD64 Offset;
+    WORD Segment;
+    ADDRESS_MODE Mode;
+  } ADDRESS64,*LPADDRESS64;
+
+#ifdef _IMAGEHLP64
+#define ADDRESS ADDRESS64
+#define LPADDRESS LPADDRESS64
+#else
+  typedef struct _tagADDRESS {
+    DWORD Offset;
+    WORD Segment;
+    ADDRESS_MODE Mode;
+  } ADDRESS,*LPADDRESS;
+
+  static __inline void Address32To64(LPADDRESS a32,LPADDRESS64 a64) {
+    a64->Offset = (ULONG64)(LONG64)(LONG)a32->Offset;
+    a64->Segment = a32->Segment;
+    a64->Mode = a32->Mode;
+  }
+
+  static __inline void Address64To32(LPADDRESS64 a64,LPADDRESS a32) {
+    a32->Offset = (ULONG)a64->Offset;
+    a32->Segment = a64->Segment;
+    a32->Mode = a64->Mode;
+  }
+#endif
+
+  typedef struct _KDHELP64 {
+    DWORD64 Thread;
+    DWORD ThCallbackStack;
+    DWORD ThCallbackBStore;
+    DWORD NextCallback;
+    DWORD FramePointer;
+    DWORD64 KiCallUserMode;
+    DWORD64 KeUserCallbackDispatcher;
+    DWORD64 SystemRangeStart;
+    DWORD64 Reserved[8];
+  } KDHELP64,*PKDHELP64;
+
+#ifdef _IMAGEHLP64
+#define KDHELP KDHELP64
+#define PKDHELP PKDHELP64
+#else
+  typedef struct _KDHELP {
+    DWORD Thread;
+    DWORD ThCallbackStack;
+    DWORD NextCallback;
+    DWORD FramePointer;
+    DWORD KiCallUserMode;
+    DWORD KeUserCallbackDispatcher;
+    DWORD SystemRangeStart;
+    DWORD ThCallbackBStore;
+    DWORD Reserved[8];
+  } KDHELP,*PKDHELP;
+
+  static __inline void KdHelp32To64(PKDHELP p32,PKDHELP64 p64) {
+    p64->Thread = p32->Thread;
+    p64->ThCallbackStack = p32->ThCallbackStack;
+    p64->NextCallback = p32->NextCallback;
+    p64->FramePointer = p32->FramePointer;
+    p64->KiCallUserMode = p32->KiCallUserMode;
+    p64->KeUserCallbackDispatcher = p32->KeUserCallbackDispatcher;
+    p64->SystemRangeStart = p32->SystemRangeStart;
+  }
+#endif
+
+  typedef struct _tagSTACKFRAME64 {
+    ADDRESS64 AddrPC;
+    ADDRESS64 AddrReturn;
+    ADDRESS64 AddrFrame;
+    ADDRESS64 AddrStack;
+    ADDRESS64 AddrBStore;
+    PVOID FuncTableEntry;
+    DWORD64 Params[4];
+    BOOL Far;
+    BOOL Virtual;
+    DWORD64 Reserved[3];
+    KDHELP64 KdHelp;
+  } STACKFRAME64,*LPSTACKFRAME64;
+
+#ifdef _IMAGEHLP64
+#define STACKFRAME STACKFRAME64
+#define LPSTACKFRAME LPSTACKFRAME64
+#else
+  typedef struct _tagSTACKFRAME {
+    ADDRESS AddrPC;
+    ADDRESS AddrReturn;
+    ADDRESS AddrFrame;
+    ADDRESS AddrStack;
+    PVOID FuncTableEntry;
+    DWORD Params[4];
+    BOOL Far;
+    BOOL Virtual;
+    DWORD Reserved[3];
+    KDHELP KdHelp;
+    ADDRESS AddrBStore;
+  } STACKFRAME,*LPSTACKFRAME;
+#endif
+
+  typedef BOOL (WINAPI *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess,DWORD64 qwBaseAddress,PVOID lpBuffer,DWORD nSize,LPDWORD lpNumberOfBytesRead);
+  typedef PVOID (WINAPI *PFUNCTION_TABLE_ACCESS_ROUTINE64)(HANDLE hProcess,DWORD64 AddrBase);
+  typedef DWORD64 (WINAPI *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess,DWORD64 Address);
+  typedef DWORD64 (WINAPI *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess,HANDLE hThread,LPADDRESS64 lpaddr);
+
+  BOOL IMAGEAPI StackWalk64(DWORD MachineType,HANDLE hProcess,HANDLE hThread,LPSTACKFRAME64 StackFrame,PVOID ContextRecord,PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
+
+#ifdef _IMAGEHLP64
+#define PREAD_PROCESS_MEMORY_ROUTINE PREAD_PROCESS_MEMORY_ROUTINE64
+#define PFUNCTION_TABLE_ACCESS_ROUTINE PFUNCTION_TABLE_ACCESS_ROUTINE64
+#define PGET_MODULE_BASE_ROUTINE PGET_MODULE_BASE_ROUTINE64
+#define PTRANSLATE_ADDRESS_ROUTINE PTRANSLATE_ADDRESS_ROUTINE64
+#define StackWalk StackWalk64
+#else
+  typedef BOOL (WINAPI *PREAD_PROCESS_MEMORY_ROUTINE)(HANDLE hProcess,DWORD lpBaseAddress,PVOID lpBuffer,DWORD nSize,PDWORD lpNumberOfBytesRead);
+  typedef PVOID (WINAPI *PFUNCTION_TABLE_ACCESS_ROUTINE)(HANDLE hProcess,DWORD AddrBase);
+  typedef DWORD (WINAPI *PGET_MODULE_BASE_ROUTINE)(HANDLE hProcess,DWORD Address);
+  typedef DWORD (WINAPI *PTRANSLATE_ADDRESS_ROUTINE)(HANDLE hProcess,HANDLE hThread,LPADDRESS lpaddr);
+
+  BOOL IMAGEAPI StackWalk(DWORD MachineType,HANDLE hProcess,HANDLE hThread,LPSTACKFRAME StackFrame,PVOID ContextRecord,PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,PTRANSLATE_ADDRESS_ROUTINE TranslateAddress);
+#endif
+
+#define API_VERSION_NUMBER 9
+
+  typedef struct API_VERSION {
+    USHORT MajorVersion;
+    USHORT MinorVersion;
+    USHORT Revision;
+    USHORT Reserved;
+  } API_VERSION,*LPAPI_VERSION;
+
+  LPAPI_VERSION IMAGEAPI ImagehlpApiVersion(VOID);
+  LPAPI_VERSION IMAGEAPI ImagehlpApiVersionEx(LPAPI_VERSION AppVersion);
+  DWORD IMAGEAPI GetTimestampForLoadedLibrary(HMODULE Module);
+
+  typedef BOOL (CALLBACK *PSYM_ENUMMODULES_CALLBACK64)(PSTR ModuleName,DWORD64 BaseOfDll,PVOID UserContext);
+  typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK64)(PSTR SymbolName,DWORD64 SymbolAddress,ULONG SymbolSize,PVOID UserContext);
+  typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK64W)(PWSTR SymbolName,DWORD64 SymbolAddress,ULONG SymbolSize,PVOID UserContext);
+  typedef BOOL (CALLBACK *PENUMLOADED_MODULES_CALLBACK64)(PSTR ModuleName,DWORD64 ModuleBase,ULONG ModuleSize,PVOID UserContext);
+  typedef BOOL (CALLBACK *PSYMBOL_REGISTERED_CALLBACK64)(HANDLE hProcess,ULONG ActionCode,ULONG64 CallbackData,ULONG64 UserContext);
+  typedef PVOID (CALLBACK *PSYMBOL_FUNCENTRY_CALLBACK)(HANDLE hProcess,DWORD AddrBase,PVOID UserContext);
+  typedef PVOID (CALLBACK *PSYMBOL_FUNCENTRY_CALLBACK64)(HANDLE hProcess,ULONG64 AddrBase,ULONG64 UserContext);
+
+#ifdef _IMAGEHLP64
+#define PSYM_ENUMMODULES_CALLBACK PSYM_ENUMMODULES_CALLBACK64
+#define PSYM_ENUMSYMBOLS_CALLBACK PSYM_ENUMSYMBOLS_CALLBACK64
+#define PSYM_ENUMSYMBOLS_CALLBACKW PSYM_ENUMSYMBOLS_CALLBACK64W
+#define PENUMLOADED_MODULES_CALLBACK PENUMLOADED_MODULES_CALLBACK64
+#define PSYMBOL_REGISTERED_CALLBACK PSYMBOL_REGISTERED_CALLBACK64
+#define PSYMBOL_FUNCENTRY_CALLBACK PSYMBOL_FUNCENTRY_CALLBACK64
+#else
+  typedef BOOL (CALLBACK *PSYM_ENUMMODULES_CALLBACK)(PSTR ModuleName,ULONG BaseOfDll,PVOID UserContext);
+  typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK)(PSTR SymbolName,ULONG SymbolAddress,ULONG SymbolSize,PVOID UserContext);
+  typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACKW)(PWSTR SymbolName,ULONG SymbolAddress,ULONG SymbolSize,PVOID UserContext);
+  typedef BOOL (CALLBACK *PENUMLOADED_MODULES_CALLBACK)(PSTR ModuleName,ULONG ModuleBase,ULONG ModuleSize,PVOID UserContext);
+  typedef BOOL (CALLBACK *PSYMBOL_REGISTERED_CALLBACK)(HANDLE hProcess,ULONG ActionCode,PVOID CallbackData,PVOID UserContext);
+#endif
+
+#define SYMFLAG_VALUEPRESENT 0x00000001
+#define SYMFLAG_REGISTER 0x00000008
+#define SYMFLAG_REGREL 0x00000010
+#define SYMFLAG_FRAMEREL 0x00000020
+#define SYMFLAG_PARAMETER 0x00000040
+#define SYMFLAG_LOCAL 0x00000080
+#define SYMFLAG_CONSTANT 0x00000100
+#define SYMFLAG_EXPORT 0x00000200
+#define SYMFLAG_FORWARDER 0x00000400
+#define SYMFLAG_FUNCTION 0x00000800
+#define SYMFLAG_VIRTUAL 0x00001000
+#define SYMFLAG_THUNK 0x00002000
+#define SYMFLAG_TLSREL 0x00004000
+
+  typedef enum {
+    SymNone = 0,SymCoff,SymCv,SymPdb,SymExport,SymDeferred,SymSym,SymDia,SymVirtual,NumSymTypes
+  } SYM_TYPE;
+
+  typedef struct _IMAGEHLP_SYMBOL64 {
+    DWORD SizeOfStruct;
+    DWORD64 Address;
+    DWORD Size;
+    DWORD Flags;
+    DWORD MaxNameLength;
+    CHAR Name[1];
+  } IMAGEHLP_SYMBOL64,*PIMAGEHLP_SYMBOL64;
+
+  typedef struct _IMAGEHLP_SYMBOL64_PACKAGE {
+    IMAGEHLP_SYMBOL64 sym;
+    CHAR name[MAX_SYM_NAME + 1];
+  } IMAGEHLP_SYMBOL64_PACKAGE,*PIMAGEHLP_SYMBOL64_PACKAGE;
+
+#ifdef _IMAGEHLP64
+
+#define IMAGEHLP_SYMBOL IMAGEHLP_SYMBOL64
+#define PIMAGEHLP_SYMBOL PIMAGEHLP_SYMBOL64
+#define IMAGEHLP_SYMBOL_PACKAGE IMAGEHLP_SYMBOL64_PACKAGE
+#define PIMAGEHLP_SYMBOL_PACKAGE PIMAGEHLP_SYMBOL64_PACKAGE
+#else
+
+  typedef struct _IMAGEHLP_SYMBOL {
+    DWORD SizeOfStruct;
+    DWORD Address;
+    DWORD Size;
+    DWORD Flags;
+    DWORD MaxNameLength;
+    CHAR Name[1];
+  } IMAGEHLP_SYMBOL,*PIMAGEHLP_SYMBOL;
+
+  typedef struct _IMAGEHLP_SYMBOL_PACKAGE {
+    IMAGEHLP_SYMBOL sym;
+    CHAR name[MAX_SYM_NAME + 1];
+  } IMAGEHLP_SYMBOL_PACKAGE,*PIMAGEHLP_SYMBOL_PACKAGE;
+#endif
+
+  typedef struct _IMAGEHLP_MODULE64 {
+    DWORD SizeOfStruct;
+    DWORD64 BaseOfImage;
+    DWORD ImageSize;
+    DWORD TimeDateStamp;
+    DWORD CheckSum;
+    DWORD NumSyms;
+    SYM_TYPE SymType;
+    CHAR ModuleName[32];
+    CHAR ImageName[256];
+    CHAR LoadedImageName[256];
+    CHAR LoadedPdbName[256];
+    DWORD CVSig;
+    CHAR CVData[MAX_PATH*3];
+    DWORD PdbSig;
+    GUID PdbSig70;
+    DWORD PdbAge;
+    BOOL PdbUnmatched;
+    BOOL DbgUnmatched;
+    BOOL LineNumbers;
+    BOOL GlobalSymbols;
+    BOOL TypeInfo;
+  } IMAGEHLP_MODULE64,*PIMAGEHLP_MODULE64;
+
+  typedef struct _IMAGEHLP_MODULE64W {
+    DWORD SizeOfStruct;
+    DWORD64 BaseOfImage;
+    DWORD ImageSize;
+    DWORD TimeDateStamp;
+    DWORD CheckSum;
+    DWORD NumSyms;
+    SYM_TYPE SymType;
+    WCHAR ModuleName[32];
+    WCHAR ImageName[256];
+    WCHAR LoadedImageName[256];
+    WCHAR LoadedPdbName[256];
+    DWORD CVSig;
+    WCHAR CVData[MAX_PATH*3];
+    DWORD PdbSig;
+    GUID PdbSig70;
+    DWORD PdbAge;
+    BOOL PdbUnmatched;
+    BOOL DbgUnmatched;
+    BOOL LineNumbers;
+    BOOL GlobalSymbols;
+    BOOL TypeInfo;
+  } IMAGEHLP_MODULEW64,*PIMAGEHLP_MODULEW64;
+
+#ifdef _IMAGEHLP64
+#define IMAGEHLP_MODULE IMAGEHLP_MODULE64
+#define PIMAGEHLP_MODULE PIMAGEHLP_MODULE64
+#define IMAGEHLP_MODULEW IMAGEHLP_MODULEW64
+#define PIMAGEHLP_MODULEW PIMAGEHLP_MODULEW64
+#else
+  typedef struct _IMAGEHLP_MODULE {
+    DWORD SizeOfStruct;
+    DWORD BaseOfImage;
+    DWORD ImageSize;
+    DWORD TimeDateStamp;
+    DWORD CheckSum;
+    DWORD NumSyms;
+    SYM_TYPE SymType;
+    CHAR ModuleName[32];
+    CHAR ImageName[256];
+    CHAR LoadedImageName[256];
+  } IMAGEHLP_MODULE,*PIMAGEHLP_MODULE;
+
+  typedef struct _IMAGEHLP_MODULEW {
+    DWORD SizeOfStruct;
+    DWORD BaseOfImage;
+    DWORD ImageSize;
+    DWORD TimeDateStamp;
+    DWORD CheckSum;
+    DWORD NumSyms;
+    SYM_TYPE SymType;
+    WCHAR ModuleName[32];
+    WCHAR ImageName[256];
+    WCHAR LoadedImageName[256];
+  } IMAGEHLP_MODULEW,*PIMAGEHLP_MODULEW;
+#endif
+
+  typedef struct _IMAGEHLP_LINE64 {
+    DWORD SizeOfStruct;
+    PVOID Key;
+    DWORD LineNumber;
+    PCHAR FileName;
+    DWORD64 Address;
+  } IMAGEHLP_LINE64,*PIMAGEHLP_LINE64;
+
+#ifdef _IMAGEHLP64
+#define IMAGEHLP_LINE IMAGEHLP_LINE64
+#define PIMAGEHLP_LINE PIMAGEHLP_LINE64
+#else
+  typedef struct _IMAGEHLP_LINE {
+    DWORD SizeOfStruct;
+    PVOID Key;
+    DWORD LineNumber;
+    PCHAR FileName;
+    DWORD Address;
+  } IMAGEHLP_LINE,*PIMAGEHLP_LINE;
+#endif
+
+  typedef struct _SOURCEFILE {
+    DWORD64 ModBase;
+    PCHAR FileName;
+  } SOURCEFILE,*PSOURCEFILE;
+
+#define CBA_DEFERRED_SYMBOL_LOAD_START 0x00000001
+#define CBA_DEFERRED_SYMBOL_LOAD_COMPLETE 0x00000002
+#define CBA_DEFERRED_SYMBOL_LOAD_FAILURE 0x00000003
+#define CBA_SYMBOLS_UNLOADED 0x00000004
+#define CBA_DUPLICATE_SYMBOL 0x00000005
+#define CBA_READ_MEMORY 0x00000006
+#define CBA_DEFERRED_SYMBOL_LOAD_CANCEL 0x00000007
+#define CBA_SET_OPTIONS 0x00000008
+#define CBA_EVENT 0x00000010
+#define CBA_DEFERRED_SYMBOL_LOAD_PARTIAL 0x00000020
+#define CBA_DEBUG_INFO 0x10000000
+
+  typedef struct _IMAGEHLP_CBA_READ_MEMORY {
+    DWORD64 addr;
+    PVOID buf;
+    DWORD bytes;
+    DWORD *bytesread;
+  } IMAGEHLP_CBA_READ_MEMORY,*PIMAGEHLP_CBA_READ_MEMORY;
+
+  enum {
+    sevInfo = 0,sevProblem,sevAttn,sevFatal,sevMax
+  };
+
+  typedef struct _IMAGEHLP_CBA_EVENT {
+    DWORD severity;
+    DWORD code;
+    PCHAR desc;
+    PVOID object;
+  } IMAGEHLP_CBA_EVENT,*PIMAGEHLP_CBA_EVENT;
+
+  typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOAD64 {
+    DWORD SizeOfStruct;
+    DWORD64 BaseOfImage;
+    DWORD CheckSum;
+    DWORD TimeDateStamp;
+    CHAR FileName[MAX_PATH];
+    BOOLEAN Reparse;
+    HANDLE hFile;
+    DWORD Flags;
+  } IMAGEHLP_DEFERRED_SYMBOL_LOAD64,*PIMAGEHLP_DEFERRED_SYMBOL_LOAD64;
+
+#define DSLFLAG_MISMATCHED_PDB 0x1
+#define DSLFLAG_MISMATCHED_DBG 0x2
+
+#ifdef _IMAGEHLP64
+#define IMAGEHLP_DEFERRED_SYMBOL_LOAD IMAGEHLP_DEFERRED_SYMBOL_LOAD64
+#define PIMAGEHLP_DEFERRED_SYMBOL_LOAD PIMAGEHLP_DEFERRED_SYMBOL_LOAD64
+#else
+  typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOAD {
+    DWORD SizeOfStruct;
+    DWORD BaseOfImage;
+    DWORD CheckSum;
+    DWORD TimeDateStamp;
+    CHAR FileName[MAX_PATH];
+    BOOLEAN Reparse;
+    HANDLE hFile;
+  } IMAGEHLP_DEFERRED_SYMBOL_LOAD,*PIMAGEHLP_DEFERRED_SYMBOL_LOAD;
+#endif
+
+  typedef struct _IMAGEHLP_DUPLICATE_SYMBOL64 {
+    DWORD SizeOfStruct;
+    DWORD NumberOfDups;
+    PIMAGEHLP_SYMBOL64 Symbol;
+    DWORD SelectedSymbol;
+  } IMAGEHLP_DUPLICATE_SYMBOL64,*PIMAGEHLP_DUPLICATE_SYMBOL64;
+
+#ifdef _IMAGEHLP64
+#define IMAGEHLP_DUPLICATE_SYMBOL IMAGEHLP_DUPLICATE_SYMBOL64
+#define PIMAGEHLP_DUPLICATE_SYMBOL PIMAGEHLP_DUPLICATE_SYMBOL64
+#else
+  typedef struct _IMAGEHLP_DUPLICATE_SYMBOL {
+    DWORD SizeOfStruct;
+    DWORD NumberOfDups;
+    PIMAGEHLP_SYMBOL Symbol;
+    DWORD SelectedSymbol;
+  } IMAGEHLP_DUPLICATE_SYMBOL,*PIMAGEHLP_DUPLICATE_SYMBOL;
+#endif
+
+  BOOL IMAGEAPI SymSetParentWindow(HWND hwnd);
+  PCHAR IMAGEAPI SymSetHomeDirectory(PCSTR dir);
+  PCHAR IMAGEAPI SymGetHomeDirectory(DWORD type,PSTR dir,size_t size);
+
+  enum {
+    hdBase = 0,hdSym,hdSrc,hdMax
+  };
+
+#define SYMOPT_CASE_INSENSITIVE 0x00000001
+#define SYMOPT_UNDNAME 0x00000002
+#define SYMOPT_DEFERRED_LOADS 0x00000004
+#define SYMOPT_NO_CPP 0x00000008
+#define SYMOPT_LOAD_LINES 0x00000010
+#define SYMOPT_OMAP_FIND_NEAREST 0x00000020
+#define SYMOPT_LOAD_ANYTHING 0x00000040
+#define SYMOPT_IGNORE_CVREC 0x00000080
+#define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100
+#define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200
+#define SYMOPT_EXACT_SYMBOLS 0x00000400
+#define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800
+#define SYMOPT_IGNORE_NT_SYMPATH 0x00001000
+#define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000
+#define SYMOPT_PUBLICS_ONLY 0x00004000
+#define SYMOPT_NO_PUBLICS 0x00008000
+#define SYMOPT_AUTO_PUBLICS 0x00010000
+#define SYMOPT_NO_IMAGE_SEARCH 0x00020000
+#define SYMOPT_SECURE 0x00040000
+#define SYMOPT_NO_PROMPTS 0x00080000
+
+#define SYMOPT_DEBUG 0x80000000
+
+  DWORD IMAGEAPI SymSetOptions(DWORD SymOptions);
+  DWORD IMAGEAPI SymGetOptions(VOID);
+  BOOL IMAGEAPI SymCleanup(HANDLE hProcess);
+  BOOL IMAGEAPI SymMatchString(LPSTR string,LPSTR expression,BOOL fCase);
+
+  typedef BOOL (CALLBACK *PSYM_ENUMSOURCFILES_CALLBACK)(PSOURCEFILE pSourceFile,PVOID UserContext);
+
+  BOOL IMAGEAPI SymEnumSourceFiles(HANDLE hProcess,ULONG64 ModBase,LPSTR Mask,PSYM_ENUMSOURCFILES_CALLBACK cbSrcFiles,PVOID UserContext);
+  BOOL IMAGEAPI SymEnumerateModules64(HANDLE hProcess,PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback,PVOID UserContext);
+
+#ifdef _IMAGEHLP64
+#define SymEnumerateModules SymEnumerateModules64
+#else
+  BOOL IMAGEAPI SymEnumerateModules(HANDLE hProcess,PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,PVOID UserContext);
+#endif
+
+  BOOL IMAGEAPI SymEnumerateSymbols64(HANDLE hProcess,DWORD64 BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback,PVOID UserContext);
+  BOOL IMAGEAPI SymEnumerateSymbolsW64(HANDLE hProcess,DWORD64 BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACK64W EnumSymbolsCallback,PVOID UserContext);
+
+#ifdef _IMAGEHLP64
+#define SymEnumerateSymbols SymEnumerateSymbols64
+#define SymEnumerateSymbolsW SymEnumerateSymbolsW64
+#else
+  BOOL IMAGEAPI SymEnumerateSymbols(HANDLE hProcess,DWORD BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext);
+  BOOL IMAGEAPI SymEnumerateSymbolsW(HANDLE hProcess,DWORD BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACKW EnumSymbolsCallback,PVOID UserContext);
+#endif
+
+  BOOL IMAGEAPI EnumerateLoadedModules64(HANDLE hProcess,PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback,PVOID UserContext);
+#ifdef _IMAGEHLP64
+#define EnumerateLoadedModules EnumerateLoadedModules64
+#else
+  BOOL IMAGEAPI EnumerateLoadedModules(HANDLE hProcess,PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,PVOID UserContext);
+#endif
+
+  PVOID IMAGEAPI SymFunctionTableAccess64(HANDLE hProcess,DWORD64 AddrBase);
+
+#ifdef _IMAGEHLP64
+#define SymFunctionTableAccess SymFunctionTableAccess64
+#else
+  PVOID IMAGEAPI SymFunctionTableAccess(HANDLE hProcess,DWORD AddrBase);
+#endif
+
+  BOOL IMAGEAPI SymGetModuleInfo64(HANDLE hProcess,DWORD64 qwAddr,PIMAGEHLP_MODULE64 ModuleInfo);
+  BOOL IMAGEAPI SymGetModuleInfoW64(HANDLE hProcess,DWORD64 qwAddr,PIMAGEHLP_MODULEW64 ModuleInfo);
+
+#ifdef _IMAGEHLP64
+#define SymGetModuleInfo SymGetModuleInfo64
+#define SymGetModuleInfoW SymGetModuleInfoW64
+#else
+  BOOL IMAGEAPI SymGetModuleInfo(HANDLE hProcess,DWORD dwAddr,PIMAGEHLP_MODULE ModuleInfo);
+  BOOL IMAGEAPI SymGetModuleInfoW(HANDLE hProcess,DWORD dwAddr,PIMAGEHLP_MODULEW ModuleInfo);
+#endif
+
+  DWORD64 IMAGEAPI SymGetModuleBase64(HANDLE hProcess,DWORD64 qwAddr);
+
+#ifdef _IMAGEHLP64
+#define SymGetModuleBase SymGetModuleBase64
+#else
+  DWORD IMAGEAPI SymGetModuleBase(HANDLE hProcess,DWORD dwAddr);
+#endif
+
+  BOOL IMAGEAPI SymGetSymNext64(HANDLE hProcess,PIMAGEHLP_SYMBOL64 Symbol);
+
+#ifdef _IMAGEHLP64
+#define SymGetSymNext SymGetSymNext64
+#else
+  BOOL IMAGEAPI SymGetSymNext(HANDLE hProcess,PIMAGEHLP_SYMBOL Symbol);
+#endif
+
+  BOOL IMAGEAPI SymGetSymPrev64(HANDLE hProcess,PIMAGEHLP_SYMBOL64 Symbol);
+
+#ifdef _IMAGEHLP64
+#define SymGetSymPrev SymGetSymPrev64
+#else
+  BOOL IMAGEAPI SymGetSymPrev(HANDLE hProcess,PIMAGEHLP_SYMBOL Symbol);
+#endif
+
+  typedef struct _SRCCODEINFO {
+    DWORD SizeOfStruct;
+    PVOID Key;
+    DWORD64 ModBase;
+    CHAR Obj[MAX_PATH + 1];
+    CHAR FileName[MAX_PATH + 1];
+    DWORD LineNumber;
+    DWORD64 Address;
+  } SRCCODEINFO,*PSRCCODEINFO;
+
+  typedef BOOL (CALLBACK *PSYM_ENUMLINES_CALLBACK)(PSRCCODEINFO LineInfo,PVOID UserContext);
+
+  BOOL IMAGEAPI SymEnumLines(HANDLE hProcess,ULONG64 Base,PCSTR Obj,PCSTR File,PSYM_ENUMLINES_CALLBACK EnumLinesCallback,PVOID UserContext);
+  BOOL IMAGEAPI SymGetLineFromAddr64(HANDLE hProcess,DWORD64 qwAddr,PDWORD pdwDisplacement,PIMAGEHLP_LINE64 Line64);
+
+#ifdef _IMAGEHLP64
+#define SymGetLineFromAddr SymGetLineFromAddr64
+#else
+  BOOL IMAGEAPI SymGetLineFromAddr(HANDLE hProcess,DWORD dwAddr,PDWORD pdwDisplacement,PIMAGEHLP_LINE Line);
+#endif
+
+  BOOL IMAGEAPI SymGetLineFromName64(HANDLE hProcess,PSTR ModuleName,PSTR FileName,DWORD dwLineNumber,PLONG plDisplacement,PIMAGEHLP_LINE64 Line);
+
+#ifdef _IMAGEHLP64
+#define SymGetLineFromName SymGetLineFromName64
+#else
+  BOOL IMAGEAPI SymGetLineFromName(HANDLE hProcess,PSTR ModuleName,PSTR FileName,DWORD dwLineNumber,PLONG plDisplacement,PIMAGEHLP_LINE Line);
+#endif
+
+  BOOL IMAGEAPI SymGetLineNext64(HANDLE hProcess,PIMAGEHLP_LINE64 Line);
+
+#ifdef _IMAGEHLP64
+#define SymGetLineNext SymGetLineNext64
+#else
+  BOOL IMAGEAPI SymGetLineNext(HANDLE hProcess,PIMAGEHLP_LINE Line);
+#endif
+
+  BOOL IMAGEAPI SymGetLinePrev64(HANDLE hProcess,PIMAGEHLP_LINE64 Line);
+
+#ifdef _IMAGEHLP64
+#define SymGetLinePrev SymGetLinePrev64
+#else
+  BOOL IMAGEAPI SymGetLinePrev(HANDLE hProcess,PIMAGEHLP_LINE Line);
+#endif
+
+  BOOL IMAGEAPI SymMatchFileName(PSTR FileName,PSTR Match,PSTR *FileNameStop,PSTR *MatchStop);
+  BOOL IMAGEAPI SymInitialize(HANDLE hProcess,PSTR UserSearchPath,BOOL fInvadeProcess);
+  BOOL IMAGEAPI SymGetSearchPath(HANDLE hProcess,PSTR SearchPath,DWORD SearchPathLength);
+  BOOL IMAGEAPI SymSetSearchPath(HANDLE hProcess,PSTR SearchPath);
+  DWORD64 IMAGEAPI SymLoadModule64(HANDLE hProcess,HANDLE hFile,PSTR ImageName,PSTR ModuleName,DWORD64 BaseOfDll,DWORD SizeOfDll);
+
+#define SLMFLAG_VIRTUAL 0x1
+
+  DWORD64 IMAGEAPI SymLoadModuleEx(HANDLE hProcess,HANDLE hFile,PSTR ImageName,PSTR ModuleName,DWORD64 BaseOfDll,DWORD DllSize,PMODLOAD_DATA Data,DWORD Flags);
+
+#ifdef _IMAGEHLP64
+#define SymLoadModule SymLoadModule64
+#else
+  DWORD IMAGEAPI SymLoadModule(HANDLE hProcess,HANDLE hFile,PSTR ImageName,PSTR ModuleName,DWORD BaseOfDll,DWORD SizeOfDll);
+#endif
+
+  BOOL IMAGEAPI SymUnloadModule64(HANDLE hProcess,DWORD64 BaseOfDll);
+
+#ifdef _IMAGEHLP64
+#define SymUnloadModule SymUnloadModule64
+#else
+  BOOL IMAGEAPI SymUnloadModule(HANDLE hProcess,DWORD BaseOfDll);
+#endif
+
+  BOOL IMAGEAPI SymUnDName64(PIMAGEHLP_SYMBOL64 sym,PSTR UnDecName,DWORD UnDecNameLength);
+
+#ifdef _IMAGEHLP64
+#define SymUnDName SymUnDName64
+#else
+  BOOL IMAGEAPI SymUnDName(PIMAGEHLP_SYMBOL sym,PSTR UnDecName,DWORD UnDecNameLength);
+#endif
+
+  BOOL IMAGEAPI SymRegisterCallback64(HANDLE hProcess,PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction,ULONG64 UserContext);
+
+  BOOL IMAGEAPI SymRegisterFunctionEntryCallback64(HANDLE hProcess,PSYMBOL_FUNCENTRY_CALLBACK64 CallbackFunction,ULONG64 UserContext);
+
+#ifdef _IMAGEHLP64
+#define SymRegisterCallback SymRegisterCallback64
+#define SymRegisterFunctionEntryCallback SymRegisterFunctionEntryCallback64
+#else
+  BOOL IMAGEAPI SymRegisterCallback(HANDLE hProcess,PSYMBOL_REGISTERED_CALLBACK CallbackFunction,PVOID UserContext);
+  BOOL IMAGEAPI SymRegisterFunctionEntryCallback(HANDLE hProcess,PSYMBOL_FUNCENTRY_CALLBACK CallbackFunction,PVOID UserContext);
+#endif
+
+  typedef struct _IMAGEHLP_SYMBOL_SRC {
+    DWORD sizeofstruct;
+    DWORD type;
+    char file[MAX_PATH];
+  } IMAGEHLP_SYMBOL_SRC,*PIMAGEHLP_SYMBOL_SRC;
+
+  typedef struct _MODULE_TYPE_INFO {
+    USHORT dataLength;
+    USHORT leaf;
+    BYTE data[1];
+  } MODULE_TYPE_INFO,*PMODULE_TYPE_INFO;
+
+  typedef struct _SYMBOL_INFO {
+    ULONG SizeOfStruct;
+    ULONG TypeIndex;
+    ULONG64 Reserved[2];
+    ULONG info;
+    ULONG Size;
+    ULONG64 ModBase;
+    ULONG Flags;
+    ULONG64 Value;
+    ULONG64 Address;
+    ULONG Register;
+    ULONG Scope;
+    ULONG Tag;
+    ULONG NameLen;
+    ULONG MaxNameLen;
+    CHAR Name[1];
+  } SYMBOL_INFO,*PSYMBOL_INFO;
+
+  typedef struct _SYMBOL_INFO_PACKAGE {
+    SYMBOL_INFO si;
+    CHAR name[MAX_SYM_NAME + 1];
+  } SYMBOL_INFO_PACKAGE,*PSYMBOL_INFO_PACKAGE;
+
+  typedef struct _IMAGEHLP_STACK_FRAME
+  {
+    ULONG64 InstructionOffset;
+    ULONG64 ReturnOffset;
+    ULONG64 FrameOffset;
+    ULONG64 StackOffset;
+    ULONG64 BackingStoreOffset;
+    ULONG64 FuncTableEntry;
+    ULONG64 Params[4];
+    ULONG64 Reserved[5];
+    BOOL Virtual;
+    ULONG Reserved2;
+  } IMAGEHLP_STACK_FRAME,*PIMAGEHLP_STACK_FRAME;
+
+  typedef VOID IMAGEHLP_CONTEXT,*PIMAGEHLP_CONTEXT;
+
+  BOOL IMAGEAPI SymSetContext(HANDLE hProcess,PIMAGEHLP_STACK_FRAME StackFrame,PIMAGEHLP_CONTEXT Context);
+  BOOL IMAGEAPI SymFromAddr(HANDLE hProcess,DWORD64 Address,PDWORD64 Displacement,PSYMBOL_INFO Symbol);
+  BOOL IMAGEAPI SymFromToken(HANDLE hProcess,DWORD64 Base,DWORD Token,PSYMBOL_INFO Symbol);
+  BOOL IMAGEAPI SymFromName(HANDLE hProcess,LPSTR Name,PSYMBOL_INFO Symbol);
+
+  typedef BOOL (CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACK)(PSYMBOL_INFO pSymInfo,ULONG SymbolSize,PVOID UserContext);
+
+  BOOL IMAGEAPI SymEnumSymbols(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Mask,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext);
+  BOOL IMAGEAPI SymEnumSymbolsForAddr(HANDLE hProcess,DWORD64 Address,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext);
+
+#define SYMENUMFLAG_FULLSRCH 1
+#define SYMENUMFLAG_SPEEDSRCH 2
+
+  typedef enum _IMAGEHLP_SYMBOL_TYPE_INFO {
+    TI_GET_SYMTAG,TI_GET_SYMNAME,TI_GET_LENGTH,TI_GET_TYPE,TI_GET_TYPEID,TI_GET_BASETYPE,TI_GET_ARRAYINDEXTYPEID,TI_FINDCHILDREN,
+    TI_GET_DATAKIND,TI_GET_ADDRESSOFFSET,TI_GET_OFFSET,TI_GET_VALUE,TI_GET_COUNT,TI_GET_CHILDRENCOUNT,TI_GET_BITPOSITION,TI_GET_VIRTUALBASECLASS,
+    TI_GET_VIRTUALTABLESHAPEID,TI_GET_VIRTUALBASEPOINTEROFFSET,TI_GET_CLASSPARENTID,TI_GET_NESTED,TI_GET_SYMINDEX,TI_GET_LEXICALPARENT,
+    TI_GET_ADDRESS,TI_GET_THISADJUST,TI_GET_UDTKIND,TI_IS_EQUIV_TO,TI_GET_CALLING_CONVENTION
+  } IMAGEHLP_SYMBOL_TYPE_INFO;
+
+  typedef struct _TI_FINDCHILDREN_PARAMS {
+    ULONG Count;
+    ULONG Start;
+    ULONG ChildId[1];
+  } TI_FINDCHILDREN_PARAMS;
+
+  BOOL IMAGEAPI SymGetTypeInfo(HANDLE hProcess,DWORD64 ModBase,ULONG TypeId,IMAGEHLP_SYMBOL_TYPE_INFO GetType,PVOID pInfo);
+  BOOL IMAGEAPI SymEnumTypes(HANDLE hProcess,ULONG64 BaseOfDll,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext);
+  BOOL IMAGEAPI SymGetTypeFromName(HANDLE hProcess,ULONG64 BaseOfDll,LPSTR Name,PSYMBOL_INFO Symbol);
+  BOOL IMAGEAPI SymAddSymbol(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Name,DWORD64 Address,DWORD Size,DWORD Flags);
+  BOOL IMAGEAPI SymDeleteSymbol(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Name,DWORD64 Address,DWORD Flags);
+
+  typedef BOOL (WINAPI *PDBGHELP_CREATE_USER_DUMP_CALLBACK)(DWORD DataType,PVOID *Data,LPDWORD DataLength,PVOID UserData);
+
+  BOOL WINAPI DbgHelpCreateUserDump(LPSTR FileName,PDBGHELP_CREATE_USER_DUMP_CALLBACK Callback,PVOID UserData);
+  BOOL WINAPI DbgHelpCreateUserDumpW(LPWSTR FileName,PDBGHELP_CREATE_USER_DUMP_CALLBACK Callback,PVOID UserData);
+  BOOL IMAGEAPI SymGetSymFromAddr64(HANDLE hProcess,DWORD64 qwAddr,PDWORD64 pdwDisplacement,PIMAGEHLP_SYMBOL64 Symbol);
+
+#ifdef _IMAGEHLP64
+#define SymGetSymFromAddr SymGetSymFromAddr64
+#else
+  BOOL IMAGEAPI SymGetSymFromAddr(HANDLE hProcess,DWORD dwAddr,PDWORD pdwDisplacement,PIMAGEHLP_SYMBOL Symbol);
+#endif
+
+  BOOL IMAGEAPI SymGetSymFromName64(HANDLE hProcess,PSTR Name,PIMAGEHLP_SYMBOL64 Symbol);
+
+#ifdef _IMAGEHLP64
+#define SymGetSymFromName SymGetSymFromName64
+#else
+  BOOL IMAGEAPI SymGetSymFromName(HANDLE hProcess,PSTR Name,PIMAGEHLP_SYMBOL Symbol);
+#endif
+
+  DBHLP_DEPRECIATED BOOL IMAGEAPI FindFileInPath(HANDLE hprocess,LPSTR SearchPath,LPSTR FileName,PVOID id,DWORD two,DWORD three,DWORD flags,LPSTR FilePath);
+  DBHLP_DEPRECIATED BOOL IMAGEAPI FindFileInSearchPath(HANDLE hprocess,LPSTR SearchPath,LPSTR FileName,DWORD one,DWORD two,DWORD three,LPSTR FilePath);
+  DBHLP_DEPRECIATED BOOL IMAGEAPI SymEnumSym(HANDLE hProcess,ULONG64 BaseOfDll,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext);
+
+#define SYMF_OMAP_GENERATED 0x00000001
+#define SYMF_OMAP_MODIFIED 0x00000002
+#define SYMF_REGISTER 0x00000008
+#define SYMF_REGREL 0x00000010
+#define SYMF_FRAMEREL 0x00000020
+#define SYMF_PARAMETER 0x00000040
+#define SYMF_LOCAL 0x00000080
+#define SYMF_CONSTANT 0x00000100
+#define SYMF_EXPORT 0x00000200
+#define SYMF_FORWARDER 0x00000400
+#define SYMF_FUNCTION 0x00000800
+#define SYMF_VIRTUAL 0x00001000
+#define SYMF_THUNK 0x00002000
+#define SYMF_TLSREL 0x00004000
+
+#define IMAGEHLP_SYMBOL_INFO_VALUEPRESENT 1
+#define IMAGEHLP_SYMBOL_INFO_REGISTER SYMF_REGISTER
+#define IMAGEHLP_SYMBOL_INFO_REGRELATIVE SYMF_REGREL
+#define IMAGEHLP_SYMBOL_INFO_FRAMERELATIVE SYMF_FRAMEREL
+#define IMAGEHLP_SYMBOL_INFO_PARAMETER SYMF_PARAMETER
+#define IMAGEHLP_SYMBOL_INFO_LOCAL SYMF_LOCAL
+#define IMAGEHLP_SYMBOL_INFO_CONSTANT SYMF_CONSTANT
+#define IMAGEHLP_SYMBOL_FUNCTION SYMF_FUNCTION
+#define IMAGEHLP_SYMBOL_VIRTUAL SYMF_VIRTUAL
+#define IMAGEHLP_SYMBOL_THUNK SYMF_THUNK
+#define IMAGEHLP_SYMBOL_INFO_TLSRELATIVE SYMF_TLSREL
+
+#include <pshpack4.h>
+
+#define MINIDUMP_SIGNATURE ('PMDM')
+#define MINIDUMP_VERSION (42899)
+  typedef DWORD RVA;
+  typedef ULONG64 RVA64;
+
+  typedef struct _MINIDUMP_LOCATION_DESCRIPTOR {
+    ULONG32 DataSize;
+    RVA Rva;
+  } MINIDUMP_LOCATION_DESCRIPTOR;
+
+  typedef struct _MINIDUMP_LOCATION_DESCRIPTOR64 {
+    ULONG64 DataSize;
+    RVA64 Rva;
+  } MINIDUMP_LOCATION_DESCRIPTOR64;
+
+  typedef struct _MINIDUMP_MEMORY_DESCRIPTOR {
+    ULONG64 StartOfMemoryRange;
+    MINIDUMP_LOCATION_DESCRIPTOR Memory;
+  } MINIDUMP_MEMORY_DESCRIPTOR,*PMINIDUMP_MEMORY_DESCRIPTOR;
+
+  typedef struct _MINIDUMP_MEMORY_DESCRIPTOR64 {
+    ULONG64 StartOfMemoryRange;
+    ULONG64 DataSize;
+  } MINIDUMP_MEMORY_DESCRIPTOR64,*PMINIDUMP_MEMORY_DESCRIPTOR64;
+
+  typedef struct _MINIDUMP_HEADER {
+    ULONG32 Signature;
+    ULONG32 Version;
+    ULONG32 NumberOfStreams;
+    RVA StreamDirectoryRva;
+    ULONG32 CheckSum;
+    union {
+      ULONG32 Reserved;
+      ULONG32 TimeDateStamp;
+    } DUMMYUNIONNAME;
+    ULONG64 Flags;
+  } MINIDUMP_HEADER,*PMINIDUMP_HEADER;
+
+  typedef struct _MINIDUMP_DIRECTORY {
+    ULONG32 StreamType;
+    MINIDUMP_LOCATION_DESCRIPTOR Location;
+  } MINIDUMP_DIRECTORY,*PMINIDUMP_DIRECTORY;
+
+  typedef struct _MINIDUMP_STRING {
+    ULONG32 Length;
+    WCHAR Buffer [0];
+  } MINIDUMP_STRING,*PMINIDUMP_STRING;
+
+  typedef enum _MINIDUMP_STREAM_TYPE {
+    UnusedStream = 0,ReservedStream0 = 1,ReservedStream1 = 2,ThreadListStream = 3,ModuleListStream = 4,MemoryListStream = 5,
+    ExceptionStream = 6,SystemInfoStream = 7,ThreadExListStream = 8,Memory64ListStream = 9,CommentStreamA = 10,CommentStreamW = 11,
+    HandleDataStream = 12,FunctionTableStream = 13,UnloadedModuleListStream = 14,MiscInfoStream = 15,LastReservedStream = 0xffff
+  } MINIDUMP_STREAM_TYPE;
+
+  typedef union _CPU_INFORMATION {
+    struct {
+      ULONG32 VendorId [3 ];
+      ULONG32 VersionInformation;
+      ULONG32 FeatureInformation;
+      ULONG32 AMDExtendedCpuFeatures;
+    } X86CpuInfo;
+    struct {
+      ULONG64 ProcessorFeatures [2 ];
+    } OtherCpuInfo;
+  } CPU_INFORMATION,*PCPU_INFORMATION;
+
+  typedef struct _MINIDUMP_SYSTEM_INFO {
+    USHORT ProcessorArchitecture;
+    USHORT ProcessorLevel;
+    USHORT ProcessorRevision;
+    union {
+      USHORT Reserved0;
+      struct {
+       UCHAR NumberOfProcessors;
+       UCHAR ProductType;
+      } DUMMYSTRUCTNAME;
+    } DUMMYUNIONNAME;
+    ULONG32 MajorVersion;
+    ULONG32 MinorVersion;
+    ULONG32 BuildNumber;
+    ULONG32 PlatformId;
+    RVA CSDVersionRva;
+    union {
+      ULONG32 Reserved1;
+      struct {
+       USHORT SuiteMask;
+       USHORT Reserved2;
+      } DUMMYSTRUCTNAME;
+    } DUMMYUNIONNAME1;
+    CPU_INFORMATION Cpu;
+  } MINIDUMP_SYSTEM_INFO,*PMINIDUMP_SYSTEM_INFO;
+
+  C_ASSERT (sizeof (((PPROCESS_INFORMATION)0)->dwThreadId)==4);
+
+  typedef struct _MINIDUMP_THREAD {
+    ULONG32 ThreadId;
+    ULONG32 SuspendCount;
+    ULONG32 PriorityClass;
+    ULONG32 Priority;
+    ULONG64 Teb;
+    MINIDUMP_MEMORY_DESCRIPTOR Stack;
+    MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
+  } MINIDUMP_THREAD,*PMINIDUMP_THREAD;
+
+  typedef struct _MINIDUMP_THREAD_LIST {
+    ULONG32 NumberOfThreads;
+    MINIDUMP_THREAD Threads [0];
+  } MINIDUMP_THREAD_LIST,*PMINIDUMP_THREAD_LIST;
+
+  typedef struct _MINIDUMP_THREAD_EX {
+    ULONG32 ThreadId;
+    ULONG32 SuspendCount;
+    ULONG32 PriorityClass;
+    ULONG32 Priority;
+    ULONG64 Teb;
+    MINIDUMP_MEMORY_DESCRIPTOR Stack;
+    MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
+    MINIDUMP_MEMORY_DESCRIPTOR BackingStore;
+  } MINIDUMP_THREAD_EX,*PMINIDUMP_THREAD_EX;
+
+  typedef struct _MINIDUMP_THREAD_EX_LIST {
+    ULONG32 NumberOfThreads;
+    MINIDUMP_THREAD_EX Threads [0];
+  } MINIDUMP_THREAD_EX_LIST,*PMINIDUMP_THREAD_EX_LIST;
+
+  typedef struct _MINIDUMP_EXCEPTION {
+    ULONG32 ExceptionCode;
+    ULONG32 ExceptionFlags;
+    ULONG64 ExceptionRecord;
+    ULONG64 ExceptionAddress;
+    ULONG32 NumberParameters;
+    ULONG32 __unusedAlignment;
+    ULONG64 ExceptionInformation [EXCEPTION_MAXIMUM_PARAMETERS ];
+  } MINIDUMP_EXCEPTION,*PMINIDUMP_EXCEPTION;
+
+  typedef struct MINIDUMP_EXCEPTION_STREAM {
+    ULONG32 ThreadId;
+    ULONG32 __alignment;
+    MINIDUMP_EXCEPTION ExceptionRecord;
+    MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
+  } MINIDUMP_EXCEPTION_STREAM,*PMINIDUMP_EXCEPTION_STREAM;
+
+  typedef struct _MINIDUMP_MODULE {
+    ULONG64 BaseOfImage;
+    ULONG32 SizeOfImage;
+    ULONG32 CheckSum;
+    ULONG32 TimeDateStamp;
+    RVA ModuleNameRva;
+    VS_FIXEDFILEINFO VersionInfo;
+    MINIDUMP_LOCATION_DESCRIPTOR CvRecord;
+    MINIDUMP_LOCATION_DESCRIPTOR MiscRecord;
+    ULONG64 Reserved0;
+    ULONG64 Reserved1;
+  } MINIDUMP_MODULE,*PMINIDUMP_MODULE;
+
+  typedef struct _MINIDUMP_MODULE_LIST {
+    ULONG32 NumberOfModules;
+    MINIDUMP_MODULE Modules [0 ];
+  } MINIDUMP_MODULE_LIST,*PMINIDUMP_MODULE_LIST;
+
+  typedef struct _MINIDUMP_MEMORY_LIST {
+    ULONG32 NumberOfMemoryRanges;
+    MINIDUMP_MEMORY_DESCRIPTOR MemoryRanges [0];
+  } MINIDUMP_MEMORY_LIST,*PMINIDUMP_MEMORY_LIST;
+
+  typedef struct _MINIDUMP_MEMORY64_LIST {
+    ULONG64 NumberOfMemoryRanges;
+    RVA64 BaseRva;
+    MINIDUMP_MEMORY_DESCRIPTOR64 MemoryRanges [0];
+  } MINIDUMP_MEMORY64_LIST,*PMINIDUMP_MEMORY64_LIST;
+
+  typedef struct _MINIDUMP_EXCEPTION_INFORMATION {
+    DWORD ThreadId;
+    PEXCEPTION_POINTERS ExceptionPointers;
+    BOOL ClientPointers;
+  } MINIDUMP_EXCEPTION_INFORMATION,*PMINIDUMP_EXCEPTION_INFORMATION;
+
+  typedef struct _MINIDUMP_EXCEPTION_INFORMATION64 {
+    DWORD ThreadId;
+    ULONG64 ExceptionRecord;
+    ULONG64 ContextRecord;
+    BOOL ClientPointers;
+  } MINIDUMP_EXCEPTION_INFORMATION64,*PMINIDUMP_EXCEPTION_INFORMATION64;
+
+  typedef struct _MINIDUMP_HANDLE_DESCRIPTOR {
+    ULONG64 Handle;
+    RVA TypeNameRva;
+    RVA ObjectNameRva;
+    ULONG32 Attributes;
+    ULONG32 GrantedAccess;
+    ULONG32 HandleCount;
+    ULONG32 PointerCount;
+  } MINIDUMP_HANDLE_DESCRIPTOR,*PMINIDUMP_HANDLE_DESCRIPTOR;
+
+  typedef struct _MINIDUMP_HANDLE_DATA_STREAM {
+    ULONG32 SizeOfHeader;
+    ULONG32 SizeOfDescriptor;
+    ULONG32 NumberOfDescriptors;
+    ULONG32 Reserved;
+  } MINIDUMP_HANDLE_DATA_STREAM,*PMINIDUMP_HANDLE_DATA_STREAM;
+
+  typedef struct _MINIDUMP_FUNCTION_TABLE_DESCRIPTOR {
+    ULONG64 MinimumAddress;
+    ULONG64 MaximumAddress;
+    ULONG64 BaseAddress;
+    ULONG32 EntryCount;
+    ULONG32 SizeOfAlignPad;
+  } MINIDUMP_FUNCTION_TABLE_DESCRIPTOR,*PMINIDUMP_FUNCTION_TABLE_DESCRIPTOR;
+
+  typedef struct _MINIDUMP_FUNCTION_TABLE_STREAM {
+    ULONG32 SizeOfHeader;
+    ULONG32 SizeOfDescriptor;
+    ULONG32 SizeOfNativeDescriptor;
+    ULONG32 SizeOfFunctionEntry;
+    ULONG32 NumberOfDescriptors;
+    ULONG32 SizeOfAlignPad;
+  } MINIDUMP_FUNCTION_TABLE_STREAM,*PMINIDUMP_FUNCTION_TABLE_STREAM;
+
+  typedef struct _MINIDUMP_UNLOADED_MODULE {
+    ULONG64 BaseOfImage;
+    ULONG32 SizeOfImage;
+    ULONG32 CheckSum;
+    ULONG32 TimeDateStamp;
+    RVA ModuleNameRva;
+  } MINIDUMP_UNLOADED_MODULE,*PMINIDUMP_UNLOADED_MODULE;
+
+  typedef struct _MINIDUMP_UNLOADED_MODULE_LIST {
+    ULONG32 SizeOfHeader;
+    ULONG32 SizeOfEntry;
+    ULONG32 NumberOfEntries;
+  } MINIDUMP_UNLOADED_MODULE_LIST,*PMINIDUMP_UNLOADED_MODULE_LIST;
+
+#define MINIDUMP_MISC1_PROCESS_ID 0x00000001
+#define MINIDUMP_MISC1_PROCESS_TIMES 0x00000002
+
+  typedef struct _MINIDUMP_MISC_INFO {
+    ULONG32 SizeOfInfo;
+    ULONG32 Flags1;
+    ULONG32 ProcessId;
+    ULONG32 ProcessCreateTime;
+    ULONG32 ProcessUserTime;
+    ULONG32 ProcessKernelTime;
+  } MINIDUMP_MISC_INFO,*PMINIDUMP_MISC_INFO;
+
+  typedef struct _MINIDUMP_USER_RECORD {
+    ULONG32 Type;
+    MINIDUMP_LOCATION_DESCRIPTOR Memory;
+  } MINIDUMP_USER_RECORD,*PMINIDUMP_USER_RECORD;
+
+  typedef struct _MINIDUMP_USER_STREAM {
+    ULONG32 Type;
+    ULONG BufferSize;
+    PVOID Buffer;
+  } MINIDUMP_USER_STREAM,*PMINIDUMP_USER_STREAM;
+
+  typedef struct _MINIDUMP_USER_STREAM_INFORMATION {
+    ULONG UserStreamCount;
+    PMINIDUMP_USER_STREAM UserStreamArray;
+  } MINIDUMP_USER_STREAM_INFORMATION,*PMINIDUMP_USER_STREAM_INFORMATION;
+
+  typedef enum _MINIDUMP_CALLBACK_TYPE {
+    ModuleCallback,ThreadCallback,ThreadExCallback,IncludeThreadCallback,IncludeModuleCallback,MemoryCallback
+  } MINIDUMP_CALLBACK_TYPE;
+
+  typedef struct _MINIDUMP_THREAD_CALLBACK {
+    ULONG ThreadId;
+    HANDLE ThreadHandle;
+    CONTEXT Context;
+    ULONG SizeOfContext;
+    ULONG64 StackBase;
+    ULONG64 StackEnd;
+  } MINIDUMP_THREAD_CALLBACK,*PMINIDUMP_THREAD_CALLBACK;
+
+  typedef struct _MINIDUMP_THREAD_EX_CALLBACK {
+    ULONG ThreadId;
+    HANDLE ThreadHandle;
+    CONTEXT Context;
+    ULONG SizeOfContext;
+    ULONG64 StackBase;
+    ULONG64 StackEnd;
+    ULONG64 BackingStoreBase;
+    ULONG64 BackingStoreEnd;
+  } MINIDUMP_THREAD_EX_CALLBACK,*PMINIDUMP_THREAD_EX_CALLBACK;
+
+  typedef struct _MINIDUMP_INCLUDE_THREAD_CALLBACK {
+    ULONG ThreadId;
+  } MINIDUMP_INCLUDE_THREAD_CALLBACK,*PMINIDUMP_INCLUDE_THREAD_CALLBACK;
+
+  typedef enum _THREAD_WRITE_FLAGS {
+    ThreadWriteThread = 0x0001,ThreadWriteStack = 0x0002,ThreadWriteContext = 0x0004,ThreadWriteBackingStore = 0x0008,
+    ThreadWriteInstructionWindow = 0x0010,ThreadWriteThreadData = 0x0020
+  } THREAD_WRITE_FLAGS;
+
+  typedef struct _MINIDUMP_MODULE_CALLBACK {
+    PWCHAR FullPath;
+    ULONG64 BaseOfImage;
+    ULONG SizeOfImage;
+    ULONG CheckSum;
+    ULONG TimeDateStamp;
+    VS_FIXEDFILEINFO VersionInfo;
+    PVOID CvRecord;
+    ULONG SizeOfCvRecord;
+    PVOID MiscRecord;
+    ULONG SizeOfMiscRecord;
+  } MINIDUMP_MODULE_CALLBACK,*PMINIDUMP_MODULE_CALLBACK;
+
+  typedef struct _MINIDUMP_INCLUDE_MODULE_CALLBACK {
+    ULONG64 BaseOfImage;
+  } MINIDUMP_INCLUDE_MODULE_CALLBACK,*PMINIDUMP_INCLUDE_MODULE_CALLBACK;
+
+  typedef enum _MODULE_WRITE_FLAGS {
+    ModuleWriteModule = 0x0001,ModuleWriteDataSeg = 0x0002,ModuleWriteMiscRecord = 0x0004,ModuleWriteCvRecord = 0x0008,
+    ModuleReferencedByMemory = 0x0010
+  } MODULE_WRITE_FLAGS;
+
+  typedef struct _MINIDUMP_CALLBACK_INPUT {
+    ULONG ProcessId;
+    HANDLE ProcessHandle;
+    ULONG CallbackType;
+    union {
+      MINIDUMP_THREAD_CALLBACK Thread;
+      MINIDUMP_THREAD_EX_CALLBACK ThreadEx;
+      MINIDUMP_MODULE_CALLBACK Module;
+      MINIDUMP_INCLUDE_THREAD_CALLBACK IncludeThread;
+      MINIDUMP_INCLUDE_MODULE_CALLBACK IncludeModule;
+    } DUMMYUNIONNAME;
+  } MINIDUMP_CALLBACK_INPUT,*PMINIDUMP_CALLBACK_INPUT;
+
+  typedef struct _MINIDUMP_CALLBACK_OUTPUT {
+    union {
+      ULONG ModuleWriteFlags;
+      ULONG ThreadWriteFlags;
+      struct {
+       ULONG64 MemoryBase;
+       ULONG MemorySize;
+      } DUMMYSTRUCTNAME;
+    } DUMMYUNIONNAME;
+  } MINIDUMP_CALLBACK_OUTPUT,*PMINIDUMP_CALLBACK_OUTPUT;
+
+  typedef enum _MINIDUMP_TYPE {
+    MiniDumpNormal = 0x0000,MiniDumpWithDataSegs = 0x0001,MiniDumpWithFullMemory = 0x0002,MiniDumpWithHandleData = 0x0004,
+    MiniDumpFilterMemory = 0x0008,MiniDumpScanMemory = 0x0010,MiniDumpWithUnloadedModules = 0x0020,MiniDumpWithIndirectlyReferencedMemory = 0x0040,
+    MiniDumpFilterModulePaths = 0x0080,MiniDumpWithProcessThreadData = 0x0100,MiniDumpWithPrivateReadWriteMemory = 0x0200,
+    MiniDumpWithoutOptionalData = 0x0400
+  } MINIDUMP_TYPE;
+
+  typedef BOOL (WINAPI *MINIDUMP_CALLBACK_ROUTINE)(PVOID CallbackParam,CONST PMINIDUMP_CALLBACK_INPUT CallbackInput,PMINIDUMP_CALLBACK_OUTPUT CallbackOutput);
+
+  typedef struct _MINIDUMP_CALLBACK_INFORMATION {
+    MINIDUMP_CALLBACK_ROUTINE CallbackRoutine;
+    PVOID CallbackParam;
+  } MINIDUMP_CALLBACK_INFORMATION,*PMINIDUMP_CALLBACK_INFORMATION;
+
+#define RVA_TO_ADDR(Mapping,Rva) ((PVOID)(((ULONG_PTR) (Mapping)) + (Rva)))
+
+  BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess,DWORD ProcessId,HANDLE hFile,MINIDUMP_TYPE DumpType,CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
+  BOOL WINAPI MiniDumpReadDumpStream(PVOID BaseOfDump,ULONG StreamNumber,PMINIDUMP_DIRECTORY *Dir,PVOID *StreamPointer,ULONG *StreamSize);
+
+#include <poppack.h>
+
+#ifdef __cplusplus
+}
+#endif
+#endif
index c11f7d383db7e62b2c2fb301e6fd6815113fdb40..76bd7ace52618dd5038ce17c263a91eb9cd03735 100644 (file)
@@ -199,6 +199,7 @@ get_next_slot( struct blit_state *ctx )
    if (!ctx->vbuf) {
       ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
                                      PIPE_BIND_VERTEX_BUFFER,
+                                     PIPE_USAGE_STREAM,
                                      max_slots * sizeof ctx->vertices);
    }
    
@@ -480,6 +481,7 @@ util_blit_pixels_writemask(struct blit_state *ctx,
    cso_save_vertex_shader(ctx->cso);
    cso_save_clip(ctx->cso);
    cso_save_vertex_elements(ctx->cso);
+   cso_save_vertex_buffers(ctx->cso);
 
    /* set misc state we care about */
    cso_set_blend(ctx->cso, &ctx->blend);
@@ -554,7 +556,7 @@ util_blit_pixels_writemask(struct blit_state *ctx,
                                   s1, t1,
                                   z);
 
-   util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, offset,
+   util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, offset,
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
                            2); /* attribs/vert */
@@ -571,6 +573,7 @@ util_blit_pixels_writemask(struct blit_state *ctx,
    cso_restore_vertex_shader(ctx->cso);
    cso_restore_clip(ctx->cso);
    cso_restore_vertex_elements(ctx->cso);
+   cso_restore_vertex_buffers(ctx->cso);
 
    pipe_sampler_view_reference(&sampler_view, NULL);
 }
@@ -672,6 +675,7 @@ util_blit_pixels_tex(struct blit_state *ctx,
    cso_save_vertex_shader(ctx->cso);
    cso_save_clip(ctx->cso);
    cso_save_vertex_elements(ctx->cso);
+   cso_save_vertex_buffers(ctx->cso);
 
    /* set misc state we care about */
    cso_set_blend(ctx->cso, &ctx->blend);
@@ -722,7 +726,7 @@ util_blit_pixels_tex(struct blit_state *ctx,
                                   s0, t0, s1, t1,
                                   z);
 
-   util_draw_vertex_buffer(ctx->pipe, 
+   util_draw_vertex_buffer(ctx->pipe, ctx->cso,
                            ctx->vbuf, offset,
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
@@ -740,4 +744,5 @@ util_blit_pixels_tex(struct blit_state *ctx,
    cso_restore_vertex_shader(ctx->cso);
    cso_restore_clip(ctx->cso);
    cso_restore_vertex_elements(ctx->cso);
+   cso_restore_vertex_buffers(ctx->cso);
 }
index 545021d2642bb319bbe2e8d6c127997bd1f9aed1..fd1c2b72d044df1d96f4d8c9385eb88d5b302a7a 100644 (file)
@@ -86,7 +86,6 @@ struct blitter_context_priv
    void *dsa_write_depth_keep_stencil;
    void *dsa_keep_depth_stencil;
    void *dsa_keep_depth_write_stencil;
-   void *dsa_flush_depth_stencil;
 
    void *velem_state;
 
@@ -156,10 +155,6 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
    ctx->dsa_keep_depth_stencil =
       pipe->create_depth_stencil_alpha_state(pipe, &dsa);
 
-   dsa.depth.writemask = 1;
-   ctx->dsa_flush_depth_stencil =
-      pipe->create_depth_stencil_alpha_state(pipe, &dsa);
-
    dsa.depth.enabled = 1;
    dsa.depth.writemask = 1;
    dsa.depth.func = PIPE_FUNC_ALWAYS;
@@ -225,9 +220,10 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
       ctx->vertices[i][0][3] = 1; /*v.w*/
 
    /* create the vertex buffer */
-   ctx->vbuf = pipe_buffer_create(ctx->base.pipe->screen,
-                                  PIPE_BIND_VERTEX_BUFFER,
-                                  sizeof(ctx->vertices));
+   ctx->vbuf = pipe_user_buffer_create(ctx->base.pipe->screen,
+                                       ctx->vertices,
+                                       sizeof(ctx->vertices),
+                                       PIPE_BIND_VERTEX_BUFFER);
 
    return &ctx->base;
 }
@@ -245,7 +241,6 @@ 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);
@@ -272,6 +267,12 @@ void util_blitter_destroy(struct blitter_context *blitter)
 
 static void blitter_check_saved_CSOs(struct blitter_context_priv *ctx)
 {
+   if (ctx->base.running) {
+      _debug_printf("u_blitter: Caught recursion on save. "
+                    "This is a driver bug.\n");
+   }
+   ctx->base.running = TRUE;
+
    /* make sure these CSOs have been saved */
    assert(ctx->base.saved_blend_state != INVALID_PTR &&
           ctx->base.saved_dsa_state != INVALID_PTR &&
@@ -302,7 +303,6 @@ static void blitter_restore_CSOs(struct blitter_context_priv *ctx)
    ctx->base.saved_velem_state = INVALID_PTR;
 
    pipe->set_stencil_ref(pipe, &ctx->base.saved_stencil_ref);
-
    pipe->set_viewport_state(pipe, &ctx->base.saved_viewport);
    pipe->set_clip_state(pipe, &ctx->base.saved_clip);
 
@@ -346,6 +346,12 @@ static void blitter_restore_CSOs(struct blitter_context_priv *ctx)
       }
       ctx->base.saved_num_vertex_buffers = ~0;
    }
+
+   if (!ctx->base.running) {
+      _debug_printf("u_blitter: Caught recursion on restore. "
+                    "This is a driver bug.\n");
+   }
+   ctx->base.running = FALSE;
 }
 
 static void blitter_set_rectangle(struct blitter_context_priv *ctx,
@@ -509,22 +515,6 @@ static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx,
    ctx->dst_height = height;
 }
 
-static void blitter_draw_quad(struct blitter_context_priv *ctx)
-{
-   struct pipe_context *pipe = ctx->base.pipe;
-   struct pipe_box box;
-
-   /* write vertices and draw them */
-   u_box_1d(0, sizeof(ctx->vertices), &box);
-   pipe->transfer_inline_write(pipe, ctx->vbuf, 0,
-                               PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
-                               &box, ctx->vertices, sizeof(ctx->vertices), 0);
-
-   util_draw_vertex_buffer(pipe, ctx->vbuf, 0, PIPE_PRIM_TRIANGLE_FAN,
-                           4,  /* verts */
-                           2); /* attribs/vert */
-}
-
 static INLINE
 void **blitter_get_sampler_state(struct blitter_context_priv *ctx,
                                  int miplevel, boolean normalized)
@@ -649,15 +639,19 @@ static void blitter_draw_rectangle(struct blitter_context *blitter,
    }
 
    blitter_set_rectangle(ctx, x1, y1, x2, y2, depth);
-   blitter_draw_quad(ctx);
+   ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf,
+                                        0, ctx->vbuf->width0);
+   util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0,
+                           PIPE_PRIM_TRIANGLE_FAN, 4, 2);
 }
 
-void util_blitter_clear(struct blitter_context *blitter,
-                        unsigned width, unsigned height,
-                        unsigned num_cbufs,
-                        unsigned clear_buffers,
-                        const float *rgba,
-                        double depth, unsigned stencil)
+static void util_blitter_clear_custom(struct blitter_context *blitter,
+                                      unsigned width, unsigned height,
+                                      unsigned num_cbufs,
+                                      unsigned clear_buffers,
+                                      const float *rgba,
+                                      double depth, unsigned stencil,
+                                      void *custom_blend, void *custom_dsa)
 {
    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
    struct pipe_context *pipe = ctx->base.pipe;
@@ -668,26 +662,28 @@ void util_blitter_clear(struct blitter_context *blitter,
    blitter_check_saved_CSOs(ctx);
 
    /* bind CSOs */
-   if (clear_buffers & PIPE_CLEAR_COLOR)
+   if (custom_blend) {
+      pipe->bind_blend_state(pipe, custom_blend);
+   } else if (clear_buffers & PIPE_CLEAR_COLOR) {
       pipe->bind_blend_state(pipe, ctx->blend_write_color);
-   else
+   } else {
       pipe->bind_blend_state(pipe, ctx->blend_keep_color);
+   }
 
-   if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
-      sr.ref_value[0] = stencil & 0xff;
+   if (custom_dsa) {
+      pipe->bind_depth_stencil_alpha_state(pipe, custom_dsa);
+   } else if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
-      pipe->set_stencil_ref(pipe, &sr);
-   }
-   else if (clear_buffers & PIPE_CLEAR_DEPTH) {
+   } else if (clear_buffers & PIPE_CLEAR_DEPTH) {
       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
-   }
-   else if (clear_buffers & PIPE_CLEAR_STENCIL) {
-      sr.ref_value[0] = stencil & 0xff;
+   } else if (clear_buffers & PIPE_CLEAR_STENCIL) {
       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
-      pipe->set_stencil_ref(pipe, &sr);
-   }
-   else
+   } else {
       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
+   }
+
+   sr.ref_value[0] = stencil & 0xff;
+   pipe->set_stencil_ref(pipe, &sr);
 
    pipe->bind_rasterizer_state(pipe, ctx->rs_state);
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
@@ -700,6 +696,27 @@ void util_blitter_clear(struct blitter_context *blitter,
    blitter_restore_CSOs(ctx);
 }
 
+void util_blitter_clear(struct blitter_context *blitter,
+                        unsigned width, unsigned height,
+                        unsigned num_cbufs,
+                        unsigned clear_buffers,
+                        const float *rgba,
+                        double depth, unsigned stencil)
+{
+   util_blitter_clear_custom(blitter, width, height, num_cbufs,
+                             clear_buffers, rgba, depth, stencil,
+                             NULL, NULL);
+}
+
+void util_blitter_clear_depth_custom(struct blitter_context *blitter,
+                                     unsigned width, unsigned height,
+                                     double depth, void *custom_dsa)
+{
+    const float rgba[4] = {0, 0, 0, 0};
+    util_blitter_clear_custom(blitter, width, height, 0,
+                              0, rgba, depth, 0, NULL, custom_dsa);
+}
+
 static
 boolean is_overlap(unsigned sx1, unsigned sx2, unsigned sy1, unsigned sy2,
                    unsigned dx1, unsigned dx2, unsigned dy1, unsigned dy2)
@@ -737,9 +754,6 @@ void util_blitter_copy_region(struct blitter_context *blitter,
    if (dst == src) {
       assert(!is_overlap(srcbox->x, srcbox->x + width, srcbox->y, srcbox->y + height,
                          dstx, dstx + width, dsty, dsty + height));
-   } else {
-      assert(util_is_format_compatible(util_format_description(src->format),
-                                       util_format_description(dst->format)));
    }
    assert(src->target < PIPE_MAX_TEXTURE_TYPES);
    /* XXX should handle 3d regions */
@@ -761,8 +775,10 @@ void util_blitter_copy_region(struct blitter_context *blitter,
                                     dst->nr_samples, bind, 0) ||
        !screen->is_format_supported(screen, src->format, src->target,
                                     src->nr_samples, PIPE_BIND_SAMPLER_VIEW, 0)) {
+      ctx->base.running = TRUE;
       util_resource_copy_region(pipe, dst, dstlevel, dstx, dsty, dstz,
                                 src, srclevel, srcbox);
+      ctx->base.running = FALSE;
       return;
    }
 
@@ -853,7 +869,10 @@ void util_blitter_copy_region(struct blitter_context *blitter,
 
          /* Draw. */
          blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0);
-         blitter_draw_quad(ctx);
+         ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf,
+                                              0, ctx->vbuf->width0);
+         util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0,
+                                 PIPE_PRIM_TRIANGLE_FAN, 4, 2);
          break;
 
       default:
@@ -1014,12 +1033,3 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
                            UTIL_BLITTER_ATTRIB_NONE, NULL);
    blitter_restore_CSOs(ctx);
 }
-
-/* flush a region of a depth stencil surface for r300g */
-void util_blitter_flush_depth_stencil(struct blitter_context *blitter,
-                                      struct pipe_surface *dstsurf)
-{
-       struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
-       util_blitter_custom_depth_stencil(blitter, dstsurf, NULL,
-                                         ctx->dsa_flush_depth_stencil, 0.0f);
-}
index 922a8580ac15a3e68562034d0a247b79a3af0eb0..41470d92bba344a972f30b53c3e35188543179ef 100644 (file)
@@ -55,13 +55,13 @@ struct blitter_context
     * \param y1      A Y coordinate of the top-left corner.
     * \param x2      An X coordinate of the bottom-right corner.
     * \param y2      A Y coordinate of the bottom-right corner.
-    * \param depth  A depth which the rectangle is rendered at.
+    * \param depth   A depth which the rectangle is rendered at.
     *
     * \param type   Semantics of the attributes "attrib".
     *               If type is UTIL_BLITTER_ATTRIB_NONE, ignore them.
     *               If type is UTIL_BLITTER_ATTRIB_COLOR, the attributes
-    *               make up a constant RGBA color, and should go to the COLOR0
-    *               varying slot of a fragment shader.
+    *               make up a constant RGBA color, and should go
+    *               to the GENERIC0 varying slot of a fragment shader.
     *               If type is UTIL_BLITTER_ATTRIB_TEXCOORD, {a1, a2} and
     *               {a3, a4} specify top-left and bottom-right texture
     *               coordinates of the rectangle, respectively, and should go
@@ -79,6 +79,9 @@ struct blitter_context
                           enum blitter_attrib_type type,
                           const float attrib[4]);
 
+   /* Whether the blitter is running. */
+   boolean running;
+
    /* Private members, really. */
    struct pipe_context *pipe; /**< pipe context */
 
@@ -141,6 +144,10 @@ void util_blitter_clear(struct blitter_context *blitter,
                         const float *rgba,
                         double depth, unsigned stencil);
 
+void util_blitter_clear_depth_custom(struct blitter_context *blitter,
+                                     unsigned width, unsigned height,
+                                     double depth, void *custom_dsa);
+
 /**
  * Copy a block of pixels from one surface to another.
  *
@@ -200,9 +207,6 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
                                       unsigned dstx, unsigned dsty,
                                       unsigned width, unsigned height);
 
-void util_blitter_flush_depth_stencil(struct blitter_context *blitter,
-                                      struct pipe_surface *dstsurf);
-
 void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
                                       struct pipe_surface *zsurf,
                                       struct pipe_surface *cbsurf,
index f4ad545bee73559b9db127ac31f5fd7b83346067..36ce4b577133741bd00be89cfbdcbf022acac63c 100644 (file)
@@ -44,6 +44,7 @@
 #include "util/u_surface.h"
 
 #include <limits.h> /* CHAR_BIT */
+#include <ctype.h> /* isalnum */
 
 void _debug_vprintf(const char *format, va_list ap)
 {
@@ -180,6 +181,48 @@ debug_get_num_option(const char *name, long dfault)
    return result;
 }
 
+static boolean str_has_option(const char *str, const char *name)
+{
+   /* Empty string. */
+   if (!*str) {
+      return FALSE;
+   }
+
+   /* OPTION=all */
+   if (!util_strcmp(str, "all")) {
+      return TRUE;
+   }
+
+   /* Find 'name' in 'str' surrounded by non-alphanumeric characters. */
+   {
+      const char *start = str;
+      unsigned name_len = strlen(name);
+
+      /* 'start' is the beginning of the currently-parsed word,
+       * we increment 'str' each iteration.
+       * if we find either the end of string or a non-alphanumeric character,
+       * we compare 'start' up to 'str-1' with 'name'. */
+
+      while (1) {
+         if (!*str || !isalnum(*str)) {
+            if (str-start == name_len &&
+                !memcmp(start, name, name_len)) {
+               return TRUE;
+            }
+
+            if (!*str) {
+               return FALSE;
+            }
+
+            start = str+1;
+         }
+
+         str++;
+      }
+   }
+
+   return FALSE;
+}
 
 unsigned long
 debug_get_flags_option(const char *name, 
@@ -207,7 +250,7 @@ debug_get_flags_option(const char *name,
    else {
       result = 0;
       while( flags->name ) {
-        if (!util_strcmp(str, "all") || util_strstr(str, flags->name ))
+        if (str_has_option(str, flags->name))
            result |= flags->value;
         ++flags;
       }
@@ -359,6 +402,41 @@ const char *u_prim_name( unsigned prim )
 
 
 
+#ifdef DEBUG
+int fl_indent = 0;
+const char* fl_function[1024];
+
+int debug_funclog_enter(const char* f, const int line, const char* file)
+{
+   int i;
+
+   for (i = 0; i < fl_indent; i++)
+      debug_printf("  ");
+   debug_printf("%s\n", f);
+
+   assert(fl_indent < 1023);
+   fl_function[fl_indent++] = f;
+
+   return 0;
+}
+
+void debug_funclog_exit(const char* f, const int line, const char* file)
+{
+   --fl_indent;
+   assert(fl_indent >= 0);
+   assert(fl_function[fl_indent] == f);
+}
+
+void debug_funclog_enter_exit(const char* f, const int line, const char* file)
+{
+   int i;
+   for (i = 0; i < fl_indent; i++)
+      debug_printf("  ");
+   debug_printf("%s\n", f);
+}
+#endif
+
+
 
 #ifdef DEBUG
 /**
index 1c9624ea3edb9d2881728f51572e47afc921f433..c47c13c64cf7303edc8f59edfecc62a17cd3033f 100644 (file)
@@ -279,6 +279,43 @@ debug_dump_flags(const struct debug_named_value *names,
                  unsigned long value);
 
 
+/**
+ * Function enter exit loggers
+ */
+#ifdef DEBUG
+int debug_funclog_enter(const char* f, const int line, const char* file);
+void debug_funclog_exit(const char* f, const int line, const char* file);
+void debug_funclog_enter_exit(const char* f, const int line, const char* file);
+
+#define DEBUG_FUNCLOG_ENTER() \
+   int __debug_decleration_work_around = \
+      debug_funclog_enter(__FUNCTION__, __LINE__, __FILE__)
+#define DEBUG_FUNCLOG_EXIT() \
+   do { \
+      (void)__debug_decleration_work_around; \
+      debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
+      return; \
+   } while(0)
+#define DEBUG_FUNCLOG_EXIT_RET(ret) \
+   do { \
+      (void)__debug_decleration_work_around; \
+      debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
+      return ret; \
+   } while(0)
+#define DEBUG_FUNCLOG_ENTER_EXIT() \
+   debug_funclog_enter_exit(__FUNCTION__, __LINE__, __FILE__)
+
+#else
+#define DEBUG_FUNCLOG_ENTER() \
+   int __debug_decleration_work_around
+#define DEBUG_FUNCLOG_EXIT() \
+   do { (void)__debug_decleration_work_around; return; } while(0)
+#define DEBUG_FUNCLOG_EXIT_RET(ret) \
+   do { (void)__debug_decleration_work_around; return ret; } while(0)
+#define DEBUG_FUNCLOG_ENTER_EXIT()
+#endif
+
+
 /**
  * Get option.
  * 
index 40a26c9c6974db6f678517b9bd8fab320960a1cb..6f706a35fda355232bd980c4518c619e408cd0b3 100644 (file)
@@ -43,7 +43,8 @@ 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;
+pipe_static_mutex(serials_mutex);
+
 static struct util_hash_table* serials_hash;
 static unsigned serials_last;
 
@@ -66,6 +67,15 @@ static boolean debug_serial(void* p, unsigned* pserial)
 {
    unsigned serial;
    boolean found = TRUE;
+#ifdef PIPE_SUBSYSTEM_WINDOWS_USER
+   static boolean first = TRUE;
+
+   if (first) {
+      pipe_mutex_init(serials_mutex);
+      first = FALSE;
+   }
+#endif
+
    pipe_mutex_lock(serials_mutex);
    if(!serials_hash)
       serials_hash = util_hash_table_create(hash_ptr, compare_ptr);
index 44d437747a1841c48c7dfefc46c594cb5405535a..bae9be87a26df06af274f30e7974a7da2eca3120 100644 (file)
 #include "u_debug_symbol.h"
 #include "u_hash_table.h"
 
-#if defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)
+#if defined(PIPE_OS_WINDOWS) && defined(PIPE_ARCH_X86)
    
 #include <windows.h>
 #include <stddef.h>
-#include <imagehlp.h>
 
-/*
- * TODO: Cleanup code.
- * TODO: Support x86_64 
- */
+#include "dbghelp.h"
+
 
 static BOOL bSymInitialized = FALSE;
 
-static HMODULE hModule_Imagehlp = NULL;
+static HMODULE hModule_Dbghelp = NULL;
+
+
+static
+FARPROC WINAPI __GetProcAddress(LPCSTR lpProcName)
+{
+#ifdef PIPE_CC_GCC
+   if (!hModule_Dbghelp) {
+      /*
+       * bfdhelp.dll is a dbghelp.dll look-alike replacement, which is able to
+       * understand MinGW symbols using BFD library.  It is available from
+       * http://people.freedesktop.org/~jrfonseca/bfdhelp/ for now.
+       */
+      hModule_Dbghelp = LoadLibraryA("bfdhelp.dll");
+   }
+#endif
+
+   if (!hModule_Dbghelp) {
+      hModule_Dbghelp = LoadLibraryA("dbghelp.dll");
+      if (!hModule_Dbghelp) {
+         return NULL;
+      }
+   }
+
+   return GetProcAddress(hModule_Dbghelp, lpProcName);
+}
+
 
 typedef BOOL (WINAPI *PFNSYMINITIALIZE)(HANDLE, LPSTR, BOOL);
 static PFNSYMINITIALIZE pfnSymInitialize = NULL;
@@ -62,8 +85,7 @@ static
 BOOL WINAPI j_SymInitialize(HANDLE hProcess, PSTR UserSearchPath, BOOL fInvadeProcess)
 {
    if(
-      (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
-      (pfnSymInitialize || (pfnSymInitialize = (PFNSYMINITIALIZE) GetProcAddress(hModule_Imagehlp, "SymInitialize")))
+      (pfnSymInitialize || (pfnSymInitialize = (PFNSYMINITIALIZE) __GetProcAddress("SymInitialize")))
    )
       return pfnSymInitialize(hProcess, UserSearchPath, fInvadeProcess);
    else
@@ -77,57 +99,41 @@ static
 DWORD WINAPI j_SymSetOptions(DWORD SymOptions)
 {
    if(
-      (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
-      (pfnSymSetOptions || (pfnSymSetOptions = (PFNSYMSETOPTIONS) GetProcAddress(hModule_Imagehlp, "SymSetOptions")))
+      (pfnSymSetOptions || (pfnSymSetOptions = (PFNSYMSETOPTIONS) __GetProcAddress("SymSetOptions")))
    )
       return pfnSymSetOptions(SymOptions);
    else
       return FALSE;
 }
 
-typedef PGET_MODULE_BASE_ROUTINE PFNSYMGETMODULEBASE;
-static PFNSYMGETMODULEBASE pfnSymGetModuleBase = NULL;
+typedef BOOL (WINAPI *PFNSYMGETSYMFROMADDR)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO);
+static PFNSYMGETSYMFROMADDR pfnSymFromAddr = NULL;
 
 static
-DWORD WINAPI j_SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
+BOOL WINAPI j_SymFromAddr(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol)
 {
    if(
-      (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
-      (pfnSymGetModuleBase || (pfnSymGetModuleBase = (PFNSYMGETMODULEBASE) GetProcAddress(hModule_Imagehlp, "SymGetModuleBase")))
+      (pfnSymFromAddr || (pfnSymFromAddr = (PFNSYMGETSYMFROMADDR) __GetProcAddress("SymFromAddr")))
    )
-      return pfnSymGetModuleBase(hProcess, dwAddr);
-   else
-      return 0;
-}
-
-typedef BOOL (WINAPI *PFNSYMGETSYMFROMADDR)(HANDLE, DWORD, LPDWORD, PIMAGEHLP_SYMBOL);
-static PFNSYMGETSYMFROMADDR pfnSymGetSymFromAddr = NULL;
-
-static
-BOOL WINAPI j_SymGetSymFromAddr(HANDLE hProcess, DWORD Address, PDWORD Displacement, PIMAGEHLP_SYMBOL Symbol)
-{
-   if(
-      (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
-      (pfnSymGetSymFromAddr || (pfnSymGetSymFromAddr = (PFNSYMGETSYMFROMADDR) GetProcAddress(hModule_Imagehlp, "SymGetSymFromAddr")))
-   )
-      return pfnSymGetSymFromAddr(hProcess, Address, Displacement, Symbol);
+      return pfnSymFromAddr(hProcess, Address, Displacement, Symbol);
    else
       return FALSE;
 }
 
 
 static INLINE void
-debug_symbol_name_imagehlp(const void *addr, char* buf, unsigned size)
+debug_symbol_name_dbghelp(const void *addr, char* buf, unsigned size)
 {
    HANDLE hProcess;
    BYTE symbolBuffer[1024];
-   PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL) symbolBuffer;
-   DWORD dwDisplacement = 0;  /* Displacement of the input address, relative to the start of the symbol */
+   PSYMBOL_INFO pSymbol = (PSYMBOL_INFO) symbolBuffer;
+   DWORD64 dwDisplacement = 0;  /* Displacement of the input address, relative to the start of the symbol */
 
    hProcess = GetCurrentProcess();
 
+   memset(pSymbol, 0, sizeof *pSymbol);
    pSymbol->SizeOfStruct = sizeof(symbolBuffer);
-   pSymbol->MaxNameLength = sizeof(symbolBuffer) - offsetof(IMAGEHLP_SYMBOL, Name);
+   pSymbol->MaxNameLen = sizeof(symbolBuffer) - offsetof(SYMBOL_INFO, Name);
 
    if(!bSymInitialized) {
       j_SymSetOptions(/* SYMOPT_UNDNAME | */ SYMOPT_LOAD_LINES);
@@ -135,7 +141,7 @@ debug_symbol_name_imagehlp(const void *addr, char* buf, unsigned size)
          bSymInitialized = TRUE;
    }
 
-   if(!j_SymGetSymFromAddr(hProcess, (DWORD)addr, &dwDisplacement, pSymbol))
+   if(!j_SymFromAddr(hProcess, (DWORD64)(uintptr_t)addr, &dwDisplacement, pSymbol))
       buf[0] = 0;
    else
    {
@@ -165,8 +171,8 @@ debug_symbol_name_glibc(const void *addr, char* buf, unsigned size)
 void
 debug_symbol_name(const void *addr, char* buf, unsigned size)
 {
-#if defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)
-   debug_symbol_name_imagehlp(addr, buf, size);
+#if defined(PIPE_OS_WINDOWS) && defined(PIPE_ARCH_X86)
+   debug_symbol_name_dbghelp(addr, buf, size);
    if(buf[0])
       return;
 #endif
@@ -190,7 +196,7 @@ debug_symbol_print(const void *addr)
 }
 
 struct util_hash_table* symbols_hash;
-pipe_mutex symbols_mutex;
+pipe_static_mutex(symbols_mutex);
 
 static unsigned hash_ptr(void* p)
 {
@@ -211,6 +217,15 @@ const char*
 debug_symbol_name_cached(const void *addr)
 {
    const char* name;
+#ifdef PIPE_SUBSYSTEM_WINDOWS_USER
+   static boolean first = TRUE;
+
+   if (first) {
+      pipe_mutex_init(symbols_mutex);
+      first = FALSE;
+   }
+#endif
+
    pipe_mutex_lock(symbols_mutex);
    if(!symbols_hash)
       symbols_hash = util_hash_table_create(hash_ptr, compare_ptr);
index 0b6dc5880f33fa39cae66f1cfb01348e9e55817b..0defd9199749fbee49ee70bef6da17c582d19ebf 100644 (file)
@@ -31,6 +31,7 @@
 #include "util/u_inlines.h"
 #include "util/u_draw_quad.h"
 #include "util/u_memory.h"
+#include "cso_cache/cso_context.h"
 
 
 /**
@@ -39,6 +40,7 @@
  */
 void 
 util_draw_vertex_buffer(struct pipe_context *pipe,
+                        struct cso_context *cso,
                         struct pipe_resource *vbuf,
                         uint offset,
                         uint prim_type,
@@ -54,8 +56,12 @@ util_draw_vertex_buffer(struct pipe_context *pipe,
    vbuffer.buffer = vbuf;
    vbuffer.stride = num_attribs * 4 * sizeof(float);  /* vertex size */
    vbuffer.buffer_offset = offset;
-   vbuffer.max_index = num_verts - 1;
-   pipe->set_vertex_buffers(pipe, 1, &vbuffer);
+
+   if (cso) {
+      cso_set_vertex_buffers(cso, 1, &vbuffer);
+   } else {
+      pipe->set_vertex_buffers(pipe, 1, &vbuffer);
+   }
 
    /* note: vertex elements already set by caller */
 
@@ -70,7 +76,7 @@ util_draw_vertex_buffer(struct pipe_context *pipe,
  * Note: this isn't especially efficient.
  */
 void 
-util_draw_texquad(struct pipe_context *pipe,
+util_draw_texquad(struct pipe_context *pipe, struct cso_context *cso,
                   float x0, float y0, float x1, float y1, float z)
 {
    uint numAttribs = 2, i, j;
@@ -118,7 +124,7 @@ util_draw_texquad(struct pipe_context *pipe,
    if (!vbuf) 
       goto out;
 
-   util_draw_vertex_buffer(pipe, vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, 2);
+   util_draw_vertex_buffer(pipe, cso, vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, 2);
 
 out:
    if (vbuf)
index 52994fe05c3ec4e224cd3b21f5f9e0b51c5253aa..f1167786f0efc4dfccf037587e2dc81866189c67 100644 (file)
@@ -38,17 +38,18 @@ extern "C" {
 #endif
 
 struct pipe_resource;
+struct cso_context;
 
 #include "util/u_draw.h"
 
 extern void 
-util_draw_vertex_buffer(struct pipe_context *pipe,
+util_draw_vertex_buffer(struct pipe_context *pipe, struct cso_context *cso,
                         struct pipe_resource *vbuf, uint offset,
                         uint num_attribs, uint num_verts, uint prim_type);
 
 
 extern void 
-util_draw_texquad(struct pipe_context *pipe,
+util_draw_texquad(struct pipe_context *pipe, struct cso_context *cso,
                   float x0, float y0, float x1, float y1, float z);
 
 
index b471d59eebf35295fd6fe39c65e7abc38c709d67..5ecf8cbb0674cc8ac598a2dcc0fce30c3057c1f4 100644 (file)
@@ -681,7 +681,6 @@ util_dump_vertex_buffer(struct os_stream *stream, const struct pipe_vertex_buffe
    util_dump_struct_begin(stream, "pipe_vertex_buffer");
 
    util_dump_member(stream, uint, state, stride);
-   util_dump_member(stream, uint, state, max_index);
    util_dump_member(stream, uint, state, buffer_offset);
    util_dump_member(stream, ptr, state, buffer);
 
index 03b73c0e98f5fa08adddfec177b3b6b329aa501a..7659a802a41605fdc1fed38cb8717db03750be8c 100644 (file)
@@ -673,7 +673,8 @@ util_format_has_alpha(enum pipe_format format)
 }
 
 /**
- * Return the matching SRGB format, or PIPE_FORMAT_NONE if none.
+ * Given a linear RGB colorspace format, return the corresponding SRGB
+ * format, or PIPE_FORMAT_NONE if none.
  */
 static INLINE enum pipe_format
 util_format_srgb(enum pipe_format format)
@@ -710,6 +711,45 @@ util_format_srgb(enum pipe_format format)
    }
 }
 
+/**
+ * Given an sRGB format, return the corresponding linear colorspace format.
+ * For non sRGB formats, return the format unchanged.
+ */
+static INLINE enum pipe_format
+util_format_linear(enum pipe_format format)
+{
+   switch (format) {
+   case PIPE_FORMAT_L8_SRGB:
+      return PIPE_FORMAT_L8_UNORM;
+   case PIPE_FORMAT_L8A8_SRGB:
+      return PIPE_FORMAT_L8A8_UNORM;
+   case PIPE_FORMAT_R8G8B8_SRGB:
+      return PIPE_FORMAT_R8G8B8_UNORM;
+   case PIPE_FORMAT_A8B8G8R8_SRGB:
+      return PIPE_FORMAT_A8B8G8R8_UNORM;
+   case PIPE_FORMAT_X8B8G8R8_SRGB:
+      return PIPE_FORMAT_X8B8G8R8_UNORM;
+   case PIPE_FORMAT_B8G8R8A8_SRGB:
+      return PIPE_FORMAT_B8G8R8A8_UNORM;
+   case PIPE_FORMAT_B8G8R8X8_SRGB:
+      return PIPE_FORMAT_B8G8R8X8_UNORM;
+   case PIPE_FORMAT_A8R8G8B8_SRGB:
+      return PIPE_FORMAT_A8R8G8B8_UNORM;
+   case PIPE_FORMAT_X8R8G8B8_SRGB:
+      return PIPE_FORMAT_X8R8G8B8_UNORM;
+   case PIPE_FORMAT_DXT1_SRGB:
+      return PIPE_FORMAT_DXT1_RGB;
+   case PIPE_FORMAT_DXT1_SRGBA:
+      return PIPE_FORMAT_DXT1_RGBA;
+   case PIPE_FORMAT_DXT3_SRGBA:
+      return PIPE_FORMAT_DXT3_RGBA;
+   case PIPE_FORMAT_DXT5_SRGBA:
+      return PIPE_FORMAT_DXT5_RGBA;
+   default:
+      return format;
+   }
+}
+
 /**
  * Return the number of components stored.
  * Formats with block size != 1x1 will always have 1 component (the block).
index d22ae8b375b8f828984f33391b52cb3c072831b5..3b6342ad8d19cc8c5705511fb0b7f8f6e91d8b7f 100644 (file)
@@ -1350,6 +1350,7 @@ get_next_slot(struct gen_mipmap_state *ctx)
    if (!ctx->vbuf) {
       ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
                                      PIPE_BIND_VERTEX_BUFFER,
+                                     PIPE_USAGE_STREAM,
                                      max_slots * sizeof ctx->vertices);
    }
    
@@ -1616,7 +1617,8 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
                                   face,
                                   rcoord);
 
-         util_draw_vertex_buffer(ctx->pipe, 
+         util_draw_vertex_buffer(ctx->pipe,
+                                 ctx->cso,
                                  ctx->vbuf,
                                  offset,
                                  PIPE_PRIM_TRIANGLE_FAN,
index f2c9db3caf1f8a830772a78f39dd5b48b87c3b1a..d0a28b5fdfadd5fdac6d5d35c978131db1b51ea3 100644 (file)
@@ -38,7 +38,10 @@ void util_shorten_ubyte_elts_to_userptr(struct pipe_context *context,
     unsigned short *out_map = out;
     unsigned i;
 
-    in_map = pipe_buffer_map(context, elts, PIPE_TRANSFER_READ, &src_transfer);
+    in_map = pipe_buffer_map(context, elts,
+                             PIPE_TRANSFER_READ |
+                             PIPE_TRANSFER_UNSYNCHRONIZED,
+                             &src_transfer);
     in_map += start;
 
     for (i = 0; i < count; i++) {
@@ -62,6 +65,7 @@ void util_shorten_ubyte_elts(struct pipe_context *context,
 
     new_elts = pipe_buffer_create(context->screen,
                                   PIPE_BIND_INDEX_BUFFER,
+                                  PIPE_USAGE_STATIC,
                                   2 * count);
 
     out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE,
@@ -87,7 +91,10 @@ void util_rebuild_ushort_elts_to_userptr(struct pipe_context *context,
     unsigned short *out_map = out;
     unsigned i;
 
-    in_map = pipe_buffer_map(context, elts, PIPE_TRANSFER_READ, &in_transfer);
+    in_map = pipe_buffer_map(context, elts,
+                             PIPE_TRANSFER_READ |
+                             PIPE_TRANSFER_UNSYNCHRONIZED,
+                             &in_transfer);
     in_map += start;
 
     for (i = 0; i < count; i++) {
@@ -110,6 +117,7 @@ void util_rebuild_ushort_elts(struct pipe_context *context,
 
     new_elts = pipe_buffer_create(context->screen,
                                   PIPE_BIND_INDEX_BUFFER,
+                                  PIPE_USAGE_STATIC,
                                   2 * count);
 
     out_map = pipe_buffer_map(context, new_elts,
@@ -135,7 +143,10 @@ void util_rebuild_uint_elts_to_userptr(struct pipe_context *context,
     unsigned int *out_map = out;
     unsigned i;
 
-    in_map = pipe_buffer_map(context, elts, PIPE_TRANSFER_READ, &in_transfer);
+    in_map = pipe_buffer_map(context, elts,
+                             PIPE_TRANSFER_READ |
+                             PIPE_TRANSFER_UNSYNCHRONIZED,
+                             &in_transfer);
     in_map += start;
 
     for (i = 0; i < count; i++) {
@@ -158,6 +169,7 @@ void util_rebuild_uint_elts(struct pipe_context *context,
 
     new_elts = pipe_buffer_create(context->screen,
                                   PIPE_BIND_INDEX_BUFFER,
+                                  PIPE_USAGE_STATIC,
                                   2 * count);
 
     out_map = pipe_buffer_map(context, new_elts,
index b4870bce9818e4347f83c396653daea9f00509d4..98889fb70ac16d1fa03817b17a1de9dd912310fb 100644 (file)
@@ -160,6 +160,21 @@ pipe_surface_init(struct pipe_context *ctx, struct pipe_surface* ps,
    pipe_surface_reset(ctx, ps, pt, level, layer, flags);
 }
 
+/* Return true if the surfaces are equal. */
+static INLINE boolean
+pipe_surface_equal(struct pipe_surface *s1, struct pipe_surface *s2)
+{
+   return s1->texture == s2->texture &&
+          s1->format == s2->format &&
+          (s1->texture->target != PIPE_BUFFER ||
+           (s1->u.buf.first_element == s2->u.buf.first_element &&
+            s1->u.buf.last_element == s2->u.buf.last_element)) &&
+          (s1->texture->target == PIPE_BUFFER ||
+           (s1->u.tex.level == s2->u.tex.level &&
+            s1->u.tex.first_layer == s2->u.tex.first_layer &&
+            s1->u.tex.last_layer == s2->u.tex.last_layer));
+}
+
 /*
  * Convenience wrappers for screen buffer functions.
  */
@@ -167,6 +182,7 @@ pipe_surface_init(struct pipe_context *ctx, struct pipe_surface* ps,
 static INLINE struct pipe_resource *
 pipe_buffer_create( struct pipe_screen *screen,
                    unsigned bind,
+                   unsigned usage,
                    unsigned size )
 {
    struct pipe_resource buffer;
@@ -174,7 +190,7 @@ pipe_buffer_create( struct pipe_screen *screen,
    buffer.target = PIPE_BUFFER;
    buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */
    buffer.bind = bind;
-   buffer.usage = PIPE_USAGE_DEFAULT;
+   buffer.usage = usage;
    buffer.flags = 0;
    buffer.width0 = size;
    buffer.height0 = 1;
@@ -220,6 +236,7 @@ pipe_buffer_map_range(struct pipe_context *pipe,
    map = pipe->transfer_map( pipe, *transfer );
    if (map == NULL) {
       pipe->transfer_destroy( pipe, *transfer );
+      *transfer = NULL;
       return NULL;
    }
 
index 37294b7203f1716df9f7bcdcfcfc026cbbd39efc..30555f92a6d021d9eede41b7e4204aacda1625a4 100644 (file)
@@ -176,7 +176,7 @@ static INLINE float logf( float f )
 
 #define isfinite(x) _finite((double)(x))
 #define isnan(x) _isnan((double)(x))
-#endif
+#endif /* _MSC_VER < 1400 && !defined(__cplusplus) */
 
 static INLINE double log2( double x )
 {
@@ -184,6 +184,18 @@ static INLINE double log2( double x )
    return log( x ) * invln2;
 }
 
+static INLINE double
+round(double x)
+{
+   return x >= 0.0 ? floor(x + 0.5) : ceil(x - 0.5);
+}
+
+static INLINE float
+roundf(float x)
+{
+   return x >= 0.0f ? floorf(x + 0.5f) : ceilf(x - 0.5f);
+}
+
 #endif /* _MSC_VER */
 
 
index 443c9f8067ef53643bfe28c8f557aa4bc99d4428..ea6896b430f91da19d0e6ecd93a7c33037897bb8 100644 (file)
@@ -35,7 +35,7 @@ unsigned u_is_resource_referenced_vtbl( struct pipe_context *pipe,
 struct pipe_transfer *u_get_transfer_vtbl(struct pipe_context *context,
                                           struct pipe_resource *resource,
                                           unsigned level,
-                                          enum pipe_transfer_usage usage,
+                                          unsigned usage,
                                           const struct pipe_box *box)
 {
    struct u_resource *ur = u_resource(resource);
index 44cadbfcdd0ce186a04c398b154b49ec2b3cf073..e3c7085ba9230219984d3c6e9865d726315fefe5 100644 (file)
@@ -367,47 +367,19 @@ pipe_get_tile_rgba(struct pipe_context *pipe,
                    uint x, uint y, uint w, uint h,
                    float *p)
 {
-   unsigned dst_stride = w * 4;
-   void *packed;
-   enum pipe_format format = pt->resource->format;
-
-   if (u_clip_tile(x, y, &w, &h, &pt->box))
-      return;
-
-   packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format));
-
-   if (!packed)
-      return;
-
-   if(format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV)
-      assert((x & 1) == 0);
-
-   pipe_get_tile_raw(pipe, pt, x, y, w, h, packed, 0);
-
-   pipe_tile_raw_to_rgba(format, packed, w, h, p, dst_stride);
-
-   FREE(packed);
+   pipe_get_tile_rgba_format(pipe, pt, x, y, w, h, pt->resource->format, p);
 }
 
 
 void
-pipe_get_tile_swizzle(struct pipe_context *pipe,
-                     struct pipe_transfer *pt,
-                      uint x,
-                      uint y,
-                      uint w,
-                      uint h,
-                      uint swizzle_r,
-                      uint swizzle_g,
-                      uint swizzle_b,
-                      uint swizzle_a,
-                      enum pipe_format format,
-                      float *p)
+pipe_get_tile_rgba_format(struct pipe_context *pipe,
+                          struct pipe_transfer *pt,
+                          uint x, uint y, uint w, uint h,
+                          enum pipe_format format,
+                          float *p)
 {
    unsigned dst_stride = w * 4;
    void *packed;
-   uint iy;
-   float rgba01[6];
 
    if (u_clip_tile(x, y, &w, &h, &pt->box)) {
       return;
@@ -427,35 +399,6 @@ pipe_get_tile_swizzle(struct pipe_context *pipe,
    pipe_tile_raw_to_rgba(format, packed, w, h, p, dst_stride);
 
    FREE(packed);
-
-   if (swizzle_r == PIPE_SWIZZLE_RED &&
-       swizzle_g == PIPE_SWIZZLE_GREEN &&
-       swizzle_b == PIPE_SWIZZLE_BLUE &&
-       swizzle_a == PIPE_SWIZZLE_ALPHA) {
-      /* no-op, skip */
-      return;
-   }
-
-   rgba01[PIPE_SWIZZLE_ZERO] = 0.0f;
-   rgba01[PIPE_SWIZZLE_ONE] = 1.0f;
-
-   for (iy = 0; iy < h; iy++) {
-      float *row = p;
-      uint ix;
-
-      for (ix = 0; ix < w; ix++) {
-         rgba01[PIPE_SWIZZLE_RED] = row[0];
-         rgba01[PIPE_SWIZZLE_GREEN] = row[1];
-         rgba01[PIPE_SWIZZLE_BLUE] = row[2];
-         rgba01[PIPE_SWIZZLE_ALPHA] = row[3];
-
-         *row++ = rgba01[swizzle_r];
-         *row++ = rgba01[swizzle_g];
-         *row++ = rgba01[swizzle_b];
-         *row++ = rgba01[swizzle_a];
-      }
-      p += dst_stride;
-   }
 }
 
 
@@ -464,10 +407,20 @@ pipe_put_tile_rgba(struct pipe_context *pipe,
                    struct pipe_transfer *pt,
                    uint x, uint y, uint w, uint h,
                    const float *p)
+{
+   pipe_put_tile_rgba_format(pipe, pt, x, y, w, h, pt->resource->format, p);
+}
+
+
+void
+pipe_put_tile_rgba_format(struct pipe_context *pipe,
+                          struct pipe_transfer *pt,
+                          uint x, uint y, uint w, uint h,
+                          enum pipe_format format,
+                          const float *p)
 {
    unsigned src_stride = w * 4;
    void *packed;
-   enum pipe_format format = pt->resource->format;
 
    if (u_clip_tile(x, y, &w, &h, &pt->box))
       return;
index 558351d0ce5866a150d5cb711cbb0bd9cc0ed723..0ba274308fe41ed3dace4e28d08072e0dd2de941 100644 (file)
@@ -80,18 +80,11 @@ pipe_get_tile_rgba(struct pipe_context *pipe,
                    float *p);
 
 void
-pipe_get_tile_swizzle(struct pipe_context *pipe,
-                     struct pipe_transfer *pt,
-                      uint x,
-                      uint y,
-                      uint w,
-                      uint h,
-                      uint swizzle_r,
-                      uint swizzle_g,
-                      uint swizzle_b,
-                      uint swizzle_a,
-                      enum pipe_format format,
-                      float *p);
+pipe_get_tile_rgba_format(struct pipe_context *pipe,
+                          struct pipe_transfer *pt,
+                          uint x, uint y, uint w, uint h,
+                          enum pipe_format format,
+                          float *p);
 
 void
 pipe_put_tile_rgba(struct pipe_context *pipe,
@@ -99,6 +92,13 @@ pipe_put_tile_rgba(struct pipe_context *pipe,
                    uint x, uint y, uint w, uint h,
                    const float *p);
 
+void
+pipe_put_tile_rgba_format(struct pipe_context *pipe,
+                          struct pipe_transfer *pt,
+                          uint x, uint y, uint w, uint h,
+                          enum pipe_format format,
+                          const float *p);
+
 
 void
 pipe_get_tile_z(struct pipe_context *pipe,
index e2828cfd99e8ef54330f777dadc199b9335b9884..b6c63d9642f9914d98832ceeb659b0c2503253a7 100644 (file)
@@ -112,3 +112,10 @@ void u_default_transfer_destroy(struct pipe_context *pipe,
    FREE(transfer);
 }
 
+void u_default_redefine_user_buffer(struct pipe_context *ctx,
+                                    struct pipe_resource *resource,
+                                    unsigned offset,
+                                    unsigned size)
+{
+   resource->width0 = MAX2(resource->width0, offset + size);
+}
index 3412e13c3ccc9641b6e9ab718f444e83d286915e..8cf9c418b040fdbe0b4bbc7b7458f0cb6efd8706 100644 (file)
@@ -93,7 +93,7 @@ struct u_resource_vtbl {
 
 struct u_resource {
    struct pipe_resource b;
-   struct u_resource_vtbl *vtbl;
+   const struct u_resource_vtbl *vtbl;
 };
 
 
@@ -136,11 +136,9 @@ void u_transfer_inline_write_vtbl( struct pipe_context *rm_ctx,
                                    unsigned stride,
                                    unsigned layer_stride);
 
-
-
-
-
-
-
+void u_default_redefine_user_buffer(struct pipe_context *ctx,
+                                    struct pipe_resource *resource,
+                                    unsigned offset,
+                                    unsigned size);
 
 #endif
index 3b3d5b418fe9227daf3ee4fc9d56443a6b94325d..dcf800a1e8e9e5733c361a42884b3324d7ab5a8b 100644 (file)
@@ -85,7 +85,12 @@ void u_upload_flush( struct u_upload_mgr *upload )
 {
    /* Unmap and unreference the upload buffer. */
    if (upload->transfer) {
+      if (upload->size) {
+         pipe_buffer_flush_mapped_range(upload->pipe, upload->transfer,
+                                        0, upload->size);
+      }
       pipe_transfer_unmap(upload->pipe, upload->transfer);
+      pipe_transfer_destroy(upload->pipe, upload->transfer);
       upload->transfer = NULL;
    }
    pipe_resource_reference( &upload->buffer, NULL );
@@ -116,13 +121,17 @@ u_upload_alloc_buffer( struct u_upload_mgr *upload,
 
    upload->buffer = pipe_buffer_create( upload->pipe->screen,
                                         upload->bind,
+                                        PIPE_USAGE_STREAM,
                                         size );
    if (upload->buffer == NULL) 
       goto fail;
 
    /* Map the new buffer. */
-   upload->map = pipe_buffer_map(upload->pipe, upload->buffer,
-                                 PIPE_TRANSFER_WRITE, &upload->transfer);
+   upload->map = pipe_buffer_map_range(upload->pipe, upload->buffer,
+                                       0, size,
+                                       PIPE_TRANSFER_WRITE |
+                                       PIPE_TRANSFER_FLUSH_EXPLICIT,
+                                       &upload->transfer);
    
    upload->size = size;
 
diff --git a/src/gallium/auxiliary/util/u_vbuf_mgr.c b/src/gallium/auxiliary/util/u_vbuf_mgr.c
new file mode 100644 (file)
index 0000000..dec8dd7
--- /dev/null
@@ -0,0 +1,601 @@
+/**************************************************************************
+ *
+ * Copyright 2011 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, 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 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_vbuf_mgr.h"
+
+#include "util/u_format.h"
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
+#include "util/u_upload_mgr.h"
+#include "translate/translate.h"
+#include "translate/translate_cache.h"
+
+/* Hardware vertex fetcher limitations can be described by this structure. */
+struct u_vbuf_caps {
+   /* Vertex format CAPs. */
+   /* TRUE if hardware supports it. */
+   unsigned format_fixed32:1;    /* PIPE_FORMAT_*32*_FIXED */
+   unsigned format_float16:1;    /* PIPE_FORMAT_*16*_FLOAT */
+   unsigned format_float64:1;    /* PIPE_FORMAT_*64*_FLOAT */
+   unsigned format_norm32:1;     /* PIPE_FORMAT_*32*NORM */
+   unsigned format_scaled32:1;   /* PIPE_FORMAT_*32*SCALED */
+
+   /* Whether vertex fetches don't have to be dword-aligned. */
+   /* TRUE if hardware supports it. */
+   unsigned fetch_dword_unaligned:1;
+};
+
+struct u_vbuf_mgr_elements {
+   unsigned count;
+   struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS];
+
+   /* If (velem[i].src_format != real_format[i]), the vertex buffer
+    * referenced by the vertex element cannot be used for rendering and
+    * its vertex data must be translated to real_format[i]. */
+   enum pipe_format native_format[PIPE_MAX_ATTRIBS];
+   unsigned native_format_size[PIPE_MAX_ATTRIBS];
+
+   /* This might mean two things:
+    * - src_format != native_format, as discussed above.
+    * - src_offset % 4 != 0 (if the caps don't allow such an offset). */
+   boolean incompatible_layout;
+};
+
+struct u_vbuf_mgr_priv {
+   struct u_vbuf_mgr b;
+   struct u_vbuf_caps caps;
+   struct pipe_context *pipe;
+
+   struct translate_cache *translate_cache;
+   unsigned translate_vb_slot;
+
+   struct u_vbuf_mgr_elements *ve;
+   void *saved_ve, *fallback_ve;
+   boolean ve_binding_lock;
+
+   boolean any_user_vbs;
+   boolean incompatible_vb_layout;
+};
+
+static void u_vbuf_mgr_init_format_caps(struct u_vbuf_mgr_priv *mgr)
+{
+   struct pipe_screen *screen = mgr->pipe->screen;
+
+   mgr->caps.format_fixed32 =
+      screen->is_format_supported(screen, PIPE_FORMAT_R32_FIXED, PIPE_BUFFER,
+                                  0, PIPE_BIND_VERTEX_BUFFER, 0);
+
+   mgr->caps.format_float16 =
+      screen->is_format_supported(screen, PIPE_FORMAT_R16_FLOAT, PIPE_BUFFER,
+                                  0, PIPE_BIND_VERTEX_BUFFER, 0);
+
+   mgr->caps.format_float64 =
+      screen->is_format_supported(screen, PIPE_FORMAT_R64_FLOAT, PIPE_BUFFER,
+                                  0, PIPE_BIND_VERTEX_BUFFER, 0);
+
+   mgr->caps.format_norm32 =
+      screen->is_format_supported(screen, PIPE_FORMAT_R32_UNORM, PIPE_BUFFER,
+                                  0, PIPE_BIND_VERTEX_BUFFER, 0) &&
+      screen->is_format_supported(screen, PIPE_FORMAT_R32_SNORM, PIPE_BUFFER,
+                                  0, PIPE_BIND_VERTEX_BUFFER, 0);
+
+   mgr->caps.format_scaled32 =
+      screen->is_format_supported(screen, PIPE_FORMAT_R32_USCALED, PIPE_BUFFER,
+                                  0, PIPE_BIND_VERTEX_BUFFER, 0) &&
+      screen->is_format_supported(screen, PIPE_FORMAT_R32_SSCALED, PIPE_BUFFER,
+                                  0, PIPE_BIND_VERTEX_BUFFER, 0);
+}
+
+struct u_vbuf_mgr *
+u_vbuf_mgr_create(struct pipe_context *pipe,
+                  unsigned upload_buffer_size,
+                  unsigned upload_buffer_alignment,
+                  unsigned upload_buffer_bind,
+                  enum u_fetch_alignment fetch_alignment)
+{
+   struct u_vbuf_mgr_priv *mgr = CALLOC_STRUCT(u_vbuf_mgr_priv);
+
+   mgr->pipe = pipe;
+   mgr->translate_cache = translate_cache_create();
+
+   mgr->b.uploader = u_upload_create(pipe, upload_buffer_size,
+                                     upload_buffer_alignment,
+                                     upload_buffer_bind);
+
+   mgr->caps.fetch_dword_unaligned =
+         fetch_alignment == U_VERTEX_FETCH_BYTE_ALIGNED;
+
+   u_vbuf_mgr_init_format_caps(mgr);
+
+   return &mgr->b;
+}
+
+void u_vbuf_mgr_destroy(struct u_vbuf_mgr *mgrb)
+{
+   struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
+   unsigned i;
+
+   for (i = 0; i < mgr->b.nr_real_vertex_buffers; i++) {
+      pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, NULL);
+      pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL);
+   }
+
+   translate_cache_destroy(mgr->translate_cache);
+   u_upload_destroy(mgr->b.uploader);
+   FREE(mgr);
+}
+
+
+static void u_vbuf_translate_begin(struct u_vbuf_mgr_priv *mgr,
+                                   int min_index, int max_index,
+                                   boolean *upload_flushed)
+{
+   struct translate_key key;
+   struct translate_element *te;
+   unsigned tr_elem_index[PIPE_MAX_ATTRIBS];
+   struct translate *tr;
+   boolean vb_translated[PIPE_MAX_ATTRIBS] = {0};
+   uint8_t *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map;
+   struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0};
+   struct pipe_resource *out_buffer = NULL;
+   unsigned i, num_verts, out_offset;
+   struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS];
+
+   memset(&key, 0, sizeof(key));
+   memset(tr_elem_index, 0xff, sizeof(tr_elem_index));
+
+   /* Initialize the translate key, i.e. the recipe how vertices should be
+     * translated. */
+   for (i = 0; i < mgr->ve->count; i++) {
+      struct pipe_vertex_buffer *vb =
+            &mgr->b.vertex_buffer[mgr->ve->ve[i].vertex_buffer_index];
+      enum pipe_format output_format = mgr->ve->native_format[i];
+      unsigned output_format_size = mgr->ve->native_format_size[i];
+
+      /* Check for support. */
+      if (mgr->ve->ve[i].src_format == mgr->ve->native_format[i] &&
+          (mgr->caps.fetch_dword_unaligned ||
+           (vb->buffer_offset % 4 == 0 &&
+            vb->stride % 4 == 0 &&
+            mgr->ve->ve[i].src_offset % 4 == 0))) {
+         continue;
+      }
+
+      /* Workaround for translate: output floats instead of halfs. */
+      switch (output_format) {
+      case PIPE_FORMAT_R16_FLOAT:
+         output_format = PIPE_FORMAT_R32_FLOAT;
+         output_format_size = 4;
+         break;
+      case PIPE_FORMAT_R16G16_FLOAT:
+         output_format = PIPE_FORMAT_R32G32_FLOAT;
+         output_format_size = 8;
+         break;
+      case PIPE_FORMAT_R16G16B16_FLOAT:
+         output_format = PIPE_FORMAT_R32G32B32_FLOAT;
+         output_format_size = 12;
+         break;
+      case PIPE_FORMAT_R16G16B16A16_FLOAT:
+         output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+         output_format_size = 16;
+         break;
+      default:;
+      }
+
+      /* Add this vertex element. */
+      te = &key.element[key.nr_elements];
+      /*te->type;
+        te->instance_divisor;*/
+      te->input_buffer = mgr->ve->ve[i].vertex_buffer_index;
+      te->input_format = mgr->ve->ve[i].src_format;
+      te->input_offset = mgr->ve->ve[i].src_offset;
+      te->output_format = output_format;
+      te->output_offset = key.output_stride;
+
+      key.output_stride += output_format_size;
+      vb_translated[mgr->ve->ve[i].vertex_buffer_index] = TRUE;
+      tr_elem_index[i] = key.nr_elements;
+      key.nr_elements++;
+   }
+
+   /* Get a translate object. */
+   tr = translate_cache_find(mgr->translate_cache, &key);
+
+   /* Map buffers we want to translate. */
+   for (i = 0; i < mgr->b.nr_vertex_buffers; i++) {
+      if (vb_translated[i]) {
+         struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[i];
+
+         vb_map[i] = pipe_buffer_map(mgr->pipe, vb->buffer,
+                                     PIPE_TRANSFER_READ, &vb_transfer[i]);
+
+         tr->set_buffer(tr, i,
+                        vb_map[i] + vb->buffer_offset + vb->stride * min_index,
+                        vb->stride, ~0);
+      }
+   }
+
+   /* Create and map the output buffer. */
+   num_verts = max_index + 1 - min_index;
+
+   u_upload_alloc(mgr->b.uploader,
+                  key.output_stride * min_index,
+                  key.output_stride * num_verts,
+                  &out_offset, &out_buffer, upload_flushed,
+                  (void**)&out_map);
+
+   out_offset -= key.output_stride * min_index;
+
+   /* Translate. */
+   tr->run(tr, 0, num_verts, 0, out_map);
+
+   /* Unmap all buffers. */
+   for (i = 0; i < mgr->b.nr_vertex_buffers; i++) {
+      if (vb_translated[i]) {
+         pipe_buffer_unmap(mgr->pipe, vb_transfer[i]);
+      }
+   }
+
+   /* Setup the new vertex buffer in the first free slot. */
+   mgr->translate_vb_slot = ~0;
+   for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+      if (!mgr->b.vertex_buffer[i].buffer) {
+         mgr->translate_vb_slot = i;
+
+         if (i >= mgr->b.nr_vertex_buffers) {
+            mgr->b.nr_real_vertex_buffers = i+1;
+         }
+         break;
+      }
+   }
+
+   if (mgr->translate_vb_slot != ~0) {
+      /* Setup the new vertex buffer. */
+      pipe_resource_reference(
+            &mgr->b.real_vertex_buffer[mgr->translate_vb_slot], out_buffer);
+      mgr->b.vertex_buffer[mgr->translate_vb_slot].buffer_offset = out_offset;
+      mgr->b.vertex_buffer[mgr->translate_vb_slot].stride = key.output_stride;
+
+      /* Setup new vertex elements. */
+      for (i = 0; i < mgr->ve->count; i++) {
+         if (tr_elem_index[i] < key.nr_elements) {
+            te = &key.element[tr_elem_index[i]];
+            new_velems[i].instance_divisor = mgr->ve->ve[i].instance_divisor;
+            new_velems[i].src_format = te->output_format;
+            new_velems[i].src_offset = te->output_offset;
+            new_velems[i].vertex_buffer_index = mgr->translate_vb_slot;
+         } else {
+            memcpy(&new_velems[i], &mgr->ve->ve[i],
+                   sizeof(struct pipe_vertex_element));
+         }
+      }
+
+      mgr->fallback_ve =
+            mgr->pipe->create_vertex_elements_state(mgr->pipe, mgr->ve->count,
+                                                    new_velems);
+
+      /* Preserve saved_ve. */
+      mgr->ve_binding_lock = TRUE;
+      mgr->pipe->bind_vertex_elements_state(mgr->pipe, mgr->fallback_ve);
+      mgr->ve_binding_lock = FALSE;
+   }
+
+   pipe_resource_reference(&out_buffer, NULL);
+}
+
+static void u_vbuf_translate_end(struct u_vbuf_mgr_priv *mgr)
+{
+   if (mgr->fallback_ve == NULL) {
+      return;
+   }
+
+   /* Restore vertex elements. */
+   /* Note that saved_ve will be overwritten in bind_vertex_elements_state. */
+   mgr->pipe->bind_vertex_elements_state(mgr->pipe, mgr->saved_ve);
+   mgr->pipe->delete_vertex_elements_state(mgr->pipe, mgr->fallback_ve);
+   mgr->fallback_ve = NULL;
+
+   /* Delete the now-unused VBO. */
+   pipe_resource_reference(&mgr->b.real_vertex_buffer[mgr->translate_vb_slot],
+                           NULL);
+   mgr->b.nr_real_vertex_buffers = mgr->b.nr_vertex_buffers;
+}
+
+#define FORMAT_REPLACE(what, withwhat) \
+    case PIPE_FORMAT_##what: format = PIPE_FORMAT_##withwhat; break
+
+struct u_vbuf_mgr_elements *
+u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgrb,
+                                  unsigned count,
+                                  const struct pipe_vertex_element *attribs,
+                                  struct pipe_vertex_element *native_attribs)
+{
+   struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
+   unsigned i;
+   struct u_vbuf_mgr_elements *ve = CALLOC_STRUCT(u_vbuf_mgr_elements);
+
+   ve->count = count;
+
+   if (!count) {
+      return ve;
+   }
+
+   memcpy(ve->ve, attribs, sizeof(struct pipe_vertex_element) * count);
+   memcpy(native_attribs, attribs, sizeof(struct pipe_vertex_element) * count);
+
+   /* Set the best native format in case the original format is not
+    * supported. */
+   for (i = 0; i < count; i++) {
+      enum pipe_format format = ve->ve[i].src_format;
+
+      /* Choose a native format.
+       * For now we don't care about the alignment, that's going to
+       * be sorted out later. */
+      if (!mgr->caps.format_fixed32) {
+         switch (format) {
+            FORMAT_REPLACE(R32_FIXED,           R32_FLOAT);
+            FORMAT_REPLACE(R32G32_FIXED,        R32G32_FLOAT);
+            FORMAT_REPLACE(R32G32B32_FIXED,     R32G32B32_FLOAT);
+            FORMAT_REPLACE(R32G32B32A32_FIXED,  R32G32B32A32_FLOAT);
+            default:;
+         }
+      }
+      if (!mgr->caps.format_float16) {
+         switch (format) {
+            FORMAT_REPLACE(R16_FLOAT,           R32_FLOAT);
+            FORMAT_REPLACE(R16G16_FLOAT,        R32G32_FLOAT);
+            FORMAT_REPLACE(R16G16B16_FLOAT,     R32G32B32_FLOAT);
+            FORMAT_REPLACE(R16G16B16A16_FLOAT,  R32G32B32A32_FLOAT);
+            default:;
+         }
+      }
+      if (!mgr->caps.format_float64) {
+         switch (format) {
+            FORMAT_REPLACE(R64_FLOAT,           R32_FLOAT);
+            FORMAT_REPLACE(R64G64_FLOAT,        R32G32_FLOAT);
+            FORMAT_REPLACE(R64G64B64_FLOAT,     R32G32B32_FLOAT);
+            FORMAT_REPLACE(R64G64B64A64_FLOAT,  R32G32B32A32_FLOAT);
+            default:;
+         }
+      }
+      if (!mgr->caps.format_norm32) {
+         switch (format) {
+            FORMAT_REPLACE(R32_UNORM,           R32_FLOAT);
+            FORMAT_REPLACE(R32G32_UNORM,        R32G32_FLOAT);
+            FORMAT_REPLACE(R32G32B32_UNORM,     R32G32B32_FLOAT);
+            FORMAT_REPLACE(R32G32B32A32_UNORM,  R32G32B32A32_FLOAT);
+            FORMAT_REPLACE(R32_SNORM,           R32_FLOAT);
+            FORMAT_REPLACE(R32G32_SNORM,        R32G32_FLOAT);
+            FORMAT_REPLACE(R32G32B32_SNORM,     R32G32B32_FLOAT);
+            FORMAT_REPLACE(R32G32B32A32_SNORM,  R32G32B32A32_FLOAT);
+            default:;
+         }
+      }
+      if (!mgr->caps.format_scaled32) {
+         switch (format) {
+            FORMAT_REPLACE(R32_USCALED,         R32_FLOAT);
+            FORMAT_REPLACE(R32G32_USCALED,      R32G32_FLOAT);
+            FORMAT_REPLACE(R32G32B32_USCALED,   R32G32B32_FLOAT);
+            FORMAT_REPLACE(R32G32B32A32_USCALED,R32G32B32A32_FLOAT);
+            FORMAT_REPLACE(R32_SSCALED,         R32_FLOAT);
+            FORMAT_REPLACE(R32G32_SSCALED,      R32G32_FLOAT);
+            FORMAT_REPLACE(R32G32B32_SSCALED,   R32G32B32_FLOAT);
+            FORMAT_REPLACE(R32G32B32A32_SSCALED,R32G32B32A32_FLOAT);
+            default:;
+         }
+      }
+
+      native_attribs[i].src_format = format;
+      ve->native_format[i] = format;
+      ve->native_format_size[i] =
+            util_format_get_blocksize(ve->native_format[i]);
+
+      ve->incompatible_layout =
+            ve->incompatible_layout ||
+            ve->ve[i].src_format != ve->native_format[i] ||
+            (!mgr->caps.fetch_dword_unaligned && ve->ve[i].src_offset % 4 != 0);
+   }
+
+   /* Align the formats to the size of DWORD if needed. */
+   if (!mgr->caps.fetch_dword_unaligned) {
+      for (i = 0; i < count; i++) {
+         ve->native_format_size[i] = align(ve->native_format_size[i], 4);
+      }
+   }
+
+   return ve;
+}
+
+void u_vbuf_mgr_bind_vertex_elements(struct u_vbuf_mgr *mgrb,
+                                     void *cso,
+                                     struct u_vbuf_mgr_elements *ve)
+{
+   struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
+
+   if (!cso) {
+      return;
+   }
+
+   if (!mgr->ve_binding_lock) {
+      mgr->saved_ve = cso;
+      mgr->ve = ve;
+   }
+}
+
+void u_vbuf_mgr_destroy_vertex_elements(struct u_vbuf_mgr *mgr,
+                                        struct u_vbuf_mgr_elements *ve)
+{
+   FREE(ve);
+}
+
+void u_vbuf_mgr_set_vertex_buffers(struct u_vbuf_mgr *mgrb,
+                                   unsigned count,
+                                   const struct pipe_vertex_buffer *bufs)
+{
+   struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
+   unsigned i;
+
+   mgr->b.max_index = ~0;
+   mgr->any_user_vbs = FALSE;
+   mgr->incompatible_vb_layout = FALSE;
+
+   if (!mgr->caps.fetch_dword_unaligned) {
+      /* Check if the strides and offsets are aligned to the size of DWORD. */
+      for (i = 0; i < count; i++) {
+         if (bufs[i].buffer) {
+            if (bufs[i].stride % 4 != 0 ||
+                bufs[i].buffer_offset % 4 != 0) {
+               mgr->incompatible_vb_layout = TRUE;
+               break;
+            }
+         }
+      }
+   }
+
+   for (i = 0; i < count; i++) {
+      const struct pipe_vertex_buffer *vb = &bufs[i];
+
+      pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, vb->buffer);
+      pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL);
+
+      if (u_vbuf_resource(vb->buffer)->user_ptr) {
+         mgr->any_user_vbs = TRUE;
+         continue;
+      }
+
+      pipe_resource_reference(&mgr->b.real_vertex_buffer[i], vb->buffer);
+
+      /* The stride of zero means we will be fetching only the first
+       * vertex, so don't care about max_index. */
+      if (!vb->stride) {
+         continue;
+      }
+
+      /* Update the maximum index. */
+      mgr->b.max_index =
+            MIN2(mgr->b.max_index,
+                 (vb->buffer->width0 - vb->buffer_offset) / vb->stride);
+   }
+
+   for (; i < mgr->b.nr_real_vertex_buffers; i++) {
+      pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, NULL);
+      pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL);
+   }
+
+   memcpy(mgr->b.vertex_buffer, bufs,
+          sizeof(struct pipe_vertex_buffer) * count);
+
+   mgr->b.nr_vertex_buffers = count;
+   mgr->b.nr_real_vertex_buffers = count;
+}
+
+static void u_vbuf_upload_buffers(struct u_vbuf_mgr_priv *mgr,
+                                  int min_index, int max_index,
+                                  boolean *upload_flushed)
+{
+   int i, nr = mgr->ve->count;
+   unsigned count = max_index + 1 - min_index;
+   boolean uploaded[PIPE_MAX_ATTRIBS] = {0};
+
+   for (i = 0; i < nr; i++) {
+      unsigned index = mgr->ve->ve[i].vertex_buffer_index;
+      struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[index];
+
+      if (vb->buffer &&
+          u_vbuf_resource(vb->buffer)->user_ptr &&
+          !uploaded[index]) {
+         unsigned first, size;
+         boolean flushed;
+
+         if (vb->stride) {
+            first = vb->stride * min_index;
+            size = vb->stride * count;
+         } else {
+            first = 0;
+            size = mgr->ve->native_format_size[i];
+         }
+
+         u_upload_data(mgr->b.uploader, first, size,
+                       u_vbuf_resource(vb->buffer)->user_ptr + first,
+                       &vb->buffer_offset,
+                       &mgr->b.real_vertex_buffer[index],
+                       &flushed);
+
+         vb->buffer_offset -= first;
+
+         uploaded[index] = TRUE;
+         *upload_flushed = *upload_flushed || flushed;
+      } else {
+         assert(mgr->b.real_vertex_buffer[index]);
+      }
+   }
+}
+
+void u_vbuf_mgr_draw_begin(struct u_vbuf_mgr *mgrb,
+                           const struct pipe_draw_info *info,
+                           boolean *buffers_updated,
+                           boolean *uploader_flushed)
+{
+   struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
+   boolean bufs_updated = FALSE, upload_flushed = FALSE;
+   int min_index, max_index;
+
+   min_index = info->min_index - info->index_bias;
+   max_index = info->max_index - info->index_bias;
+
+   /* Translate vertices with non-native layouts or formats. */
+   if (mgr->incompatible_vb_layout || mgr->ve->incompatible_layout) {
+      u_vbuf_translate_begin(mgr, min_index, max_index, &upload_flushed);
+
+      if (mgr->fallback_ve) {
+         bufs_updated = TRUE;
+      }
+   }
+
+   /* Upload user buffers. */
+   if (mgr->any_user_vbs) {
+      u_vbuf_upload_buffers(mgr, min_index, max_index, &upload_flushed);
+      bufs_updated = TRUE;
+   }
+
+   /* Set the return values. */
+   if (buffers_updated) {
+      *buffers_updated = bufs_updated;
+   }
+   if (uploader_flushed) {
+      *uploader_flushed = upload_flushed;
+   }
+}
+
+void u_vbuf_mgr_draw_end(struct u_vbuf_mgr *mgrb)
+{
+   struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
+
+   if (mgr->fallback_ve) {
+      u_vbuf_translate_end(mgr);
+   }
+}
diff --git a/src/gallium/auxiliary/util/u_vbuf_mgr.h b/src/gallium/auxiliary/util/u_vbuf_mgr.h
new file mode 100644 (file)
index 0000000..8b24185
--- /dev/null
@@ -0,0 +1,121 @@
+/**************************************************************************
+ *
+ * Copyright 2011 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, 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 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_VBUF_MGR_H
+#define U_VBUF_MGR_H
+
+/* This module builds upon u_upload_mgr and translate_cache and takes care of
+ * user buffer uploads and vertex format fallbacks. It's designed
+ * for the drivers which don't always use the Draw module. (e.g. for HWTCL)
+ */
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "util/u_transfer.h"
+
+/* The manager.
+ * This structure should also be used to access vertex buffers
+ * from a driver. */
+struct u_vbuf_mgr {
+   /* This is what was set in set_vertex_buffers.
+    * May contain user buffers. */
+   struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
+   unsigned nr_vertex_buffers;
+
+   /* Contains only real vertex buffers.
+    * Hardware drivers should use real_vertex_buffers[i]
+    * instead of vertex_buffers[i].buffer. */
+   struct pipe_resource *real_vertex_buffer[PIPE_MAX_ATTRIBS];
+   int nr_real_vertex_buffers;
+
+   /* Precomputed max_index for hardware vertex buffers. */
+   int max_index;
+
+   /* This uploader can optionally be used by the driver.
+    *
+    * Allowed functions:
+    * - u_upload_alloc
+    * - u_upload_data
+    * - u_upload_buffer
+    * - u_upload_flush */
+   struct u_upload_mgr *uploader;
+};
+
+struct u_vbuf_resource {
+   struct u_resource b;
+   uint8_t *user_ptr;
+};
+
+/* Opaque type containing information about vertex elements for the manager. */
+struct u_vbuf_mgr_elements;
+
+enum u_fetch_alignment {
+   U_VERTEX_FETCH_BYTE_ALIGNED,
+   U_VERTEX_FETCH_DWORD_ALIGNED
+};
+
+
+struct u_vbuf_mgr *
+u_vbuf_mgr_create(struct pipe_context *pipe,
+                  unsigned upload_buffer_size,
+                  unsigned upload_buffer_alignment,
+                  unsigned upload_buffer_bind,
+                  enum u_fetch_alignment fetch_alignment);
+
+void u_vbuf_mgr_destroy(struct u_vbuf_mgr *mgr);
+
+struct u_vbuf_mgr_elements *
+u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgr,
+                                  unsigned count,
+                                  const struct pipe_vertex_element *attrs,
+                                  struct pipe_vertex_element *native_attrs);
+
+void u_vbuf_mgr_bind_vertex_elements(struct u_vbuf_mgr *mgr,
+                                     void *cso,
+                                     struct u_vbuf_mgr_elements *ve);
+
+void u_vbuf_mgr_destroy_vertex_elements(struct u_vbuf_mgr *mgr,
+                                        struct u_vbuf_mgr_elements *ve);
+
+void u_vbuf_mgr_set_vertex_buffers(struct u_vbuf_mgr *mgr,
+                                   unsigned count,
+                                   const struct pipe_vertex_buffer *bufs);
+
+void u_vbuf_mgr_draw_begin(struct u_vbuf_mgr *mgr,
+                           const struct pipe_draw_info *info,
+                           boolean *buffers_updated,
+                           boolean *uploader_flushed);
+
+void u_vbuf_mgr_draw_end(struct u_vbuf_mgr *mgr);
+
+
+static INLINE struct u_vbuf_resource *u_vbuf_resource(struct pipe_resource *r)
+{
+   return (struct u_vbuf_resource*)r;
+}
+
+#endif
index d7b29497ace9a56dcfe626f05f3a8bd54435996e..d1ba5faf7881afcb895b0f46056624ad4be5379c 100644 (file)
@@ -247,13 +247,13 @@ init_buffers(struct vl_compositor *c)
     * Create our vertex buffer and vertex buffer elements
     */
    c->vertex_buf.stride = sizeof(struct vertex4f);
-   c->vertex_buf.max_index = (VL_COMPOSITOR_MAX_LAYERS + 2) * 6 - 1;
    c->vertex_buf.buffer_offset = 0;
    /* XXX: Create with DYNAMIC or STREAM */
    c->vertex_buf.buffer = pipe_buffer_create
    (
       c->pipe->screen,
       PIPE_BIND_VERTEX_BUFFER,
+      PIPE_USAGE_STATIC,
       sizeof(struct vertex4f) * (VL_COMPOSITOR_MAX_LAYERS + 2) * 6
    );
 
@@ -276,6 +276,7 @@ init_buffers(struct vl_compositor *c)
    (
       c->pipe->screen,
       PIPE_BIND_CONSTANT_BUFFER,
+      PIPE_USAGE_STATIC,
       sizeof(struct fragment_shader_consts)
    );
 
index 5d472f93481822fe32ecea0236a80b39718393b8..89463a5c75c448a04c3abdc83e663e34ede8cea8 100644 (file)
@@ -428,7 +428,6 @@ init_textures(struct vl_idct *idct, struct vl_idct_buffer *buffer)
    /* create textures */
    memset(&template, 0, sizeof(struct pipe_resource));
    template.last_level = 0;
-   template.depth0 = 1;
    template.bind = PIPE_BIND_SAMPLER_VIEW;
    template.flags = 0;
 
@@ -437,6 +436,7 @@ init_textures(struct vl_idct *idct, struct vl_idct_buffer *buffer)
    template.width0 = idct->buffer_width / 4;
    template.height0 = idct->buffer_height;
    template.depth0 = 1;
+   template.array_size = 1;
    template.usage = PIPE_USAGE_STREAM;
    buffer->textures.individual.source = idct->pipe->screen->resource_create(idct->pipe->screen, &template);
 
@@ -478,7 +478,6 @@ init_vertex_buffers(struct vl_idct *idct, struct vl_idct_buffer *buffer)
    assert(idct && buffer);
 
    buffer->vertex_bufs.individual.quad.stride = idct->quad.stride;
-   buffer->vertex_bufs.individual.quad.max_index = idct->quad.max_index;
    buffer->vertex_bufs.individual.quad.buffer_offset = idct->quad.buffer_offset;
    pipe_resource_reference(&buffer->vertex_bufs.individual.quad.buffer, idct->quad.buffer);
 
@@ -526,6 +525,7 @@ vl_idct_upload_matrix(struct pipe_context *pipe)
    template.width0 = 2;
    template.height0 = 8;
    template.depth0 = 1;
+   template.array_size = 1;
    template.usage = PIPE_USAGE_IMMUTABLE;
    template.bind = PIPE_BIND_SAMPLER_VIEW;
    template.flags = 0;
index de83b6a5338b0b363991b5e9a31b2cae5d3cc9dd..484e781f0cb89d3976c300d917a45becaced0efb 100644 (file)
@@ -888,6 +888,7 @@ vl_mpeg12_mc_init_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg1
    template.width0 = renderer->buffer_width;
    template.height0 = renderer->buffer_height;
    template.depth0 = 1;
+   template.array_size = 1;
    template.usage = PIPE_USAGE_STATIC;
    template.bind = PIPE_BIND_SAMPLER_VIEW;
    template.flags = 0;
@@ -928,7 +929,6 @@ vl_mpeg12_mc_init_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg1
    }
 
    buffer->vertex_bufs.individual.quad.stride = renderer->quad.stride;
-   buffer->vertex_bufs.individual.quad.max_index = renderer->quad.max_index;
    buffer->vertex_bufs.individual.quad.buffer_offset = renderer->quad.buffer_offset;
    pipe_resource_reference(&buffer->vertex_bufs.individual.quad.buffer, renderer->quad.buffer);
 
index 8599ed3533dc64fb1cc7895487c8cbca848d2117..552a0451fef084e3f0e6e330765937b3776efdc4 100644 (file)
@@ -53,12 +53,12 @@ vl_vb_upload_quads(struct pipe_context *pipe, unsigned max_blocks)
 
    /* create buffer */
    quad.stride = sizeof(struct vertex2f);
-   quad.max_index = 4 * max_blocks - 1;
    quad.buffer_offset = 0;
    quad.buffer = pipe_buffer_create
    (
       pipe->screen,
       PIPE_BIND_VERTEX_BUFFER,
+      PIPE_USAGE_STATIC,
       sizeof(struct vertex2f) * 4 * max_blocks
    );
 
@@ -100,7 +100,7 @@ unsigned
 vl_vb_element_helper(struct pipe_vertex_element* elements, unsigned num_elements,
                               unsigned vertex_buffer_index)
 {
-   unsigned i, size, offset = 0;
+   unsigned i, offset = 0;
 
    assert(elements && num_elements);
 
@@ -126,12 +126,12 @@ vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe,
    buffer->stride = stride;
 
    buf.stride = stride;
-   buf.max_index = 4 * max_blocks - 1;
    buf.buffer_offset = 0;
    buf.buffer = pipe_buffer_create
    (
       pipe->screen,
       PIPE_BIND_VERTEX_BUFFER,
+      PIPE_USAGE_STREAM,
       stride * 4 * max_blocks
    );
 
index 11e77190895672e66fd429d03e17df8158057524..0a9e7e50f1d7af08cd4587e4736b2d5c41c6ac32 100644 (file)
@@ -337,7 +337,6 @@ IaSetTopology
        + Gallium supports line loops, triangle fans, quads, quad strips and polygons
 
 IaSetVertexBuffers -> set_vertex_buffers
-       + Gallium allows to specify a max_index here
        - Gallium only allows setting all vertex buffers at once, while D3D11 supports setting a subset
 
 OpenResource -> texture_from_handle
index 6760e7be4b90cdb44fac4dbe87d3fdd5eb091a16..c6812cd309e31be4857307808d77d007093ba452 100644 (file)
@@ -3,8 +3,12 @@
 Context
 =======
 
-The context object represents the purest, most directly accessible, abilities
-of the device's 3D rendering pipeline.
+A Gallium rendering context encapsulates the state which effects 3D
+rendering such as blend state, depth/stencil state, texture samplers,
+etc.
+
+Note that resource/texture allocation is not per-context but per-screen.
+
 
 Methods
 -------
@@ -12,20 +16,23 @@ Methods
 CSO State
 ^^^^^^^^^
 
-All CSO state is created, bound, and destroyed, with triplets of methods that
-all follow a specific naming scheme. For example, ``create_blend_state``,
-``bind_blend_state``, and ``destroy_blend_state``.
+All Constant State Object (CSO) state is created, bound, and destroyed,
+with triplets of methods that all follow a specific naming scheme.
+For example, ``create_blend_state``, ``bind_blend_state``, and
+``destroy_blend_state``.
 
 CSO objects handled by the context object:
 
 * :ref:`Blend`: ``*_blend_state``
-* :ref:`Sampler`: These are special; they can be bound to either vertex or
-  fragment samplers, and they are bound in groups.
-  ``bind_fragment_sampler_states``, ``bind_vertex_sampler_states``
+* :ref:`Sampler`: Texture sampler states are bound separately for fragment,
+  vertex and geometry samplers.  Note that sampler states are set en masse.
+  If M is the max number of sampler units supported by the driver and N
+  samplers are bound with ``bind_fragment_sampler_states`` then sampler
+  units N..M-1 are considered disabled/NULL.
 * :ref:`Rasterizer`: ``*_rasterizer_state``
 * :ref:`Depth, Stencil, & Alpha`: ``*_depth_stencil_alpha_state``
-* :ref:`Shader`: These have two sets of methods. ``*_fs_state`` is for
-  fragment shaders, and ``*_vs_state`` is for vertex shaders.
+* :ref:`Shader`: These are create, bind and destroy methods for vertex,
+  fragment and geometry shaders.
 * :ref:`Vertex Elements`: ``*_vertex_elements_state``
 
 
@@ -47,6 +54,9 @@ buffers, surfaces) are bound to the driver.
 
 * ``set_index_buffer``
 
+* ``set_stream_output_buffers``
+
+
 Non-CSO State
 ^^^^^^^^^^^^^
 
@@ -96,7 +106,9 @@ to the array index which is used for sampling.
 * ``set_fragment_sampler_views`` binds an array of sampler views to
   fragment shader stage. Every binding point acquires a reference
   to a respective sampler view and releases a reference to the previous
-  sampler view.
+  sampler view.  If M is the maximum number of sampler units and N units
+  is passed to set_fragment_sampler_views, the driver should unbind the
+  sampler views for units N..M-1.
 
 * ``set_vertex_sampler_views`` binds an array of sampler views to vertex
   shader stage. Every binding point acquires a reference to a respective
@@ -233,6 +245,11 @@ The most common type of query is the occlusion query,
 are written to the framebuffer without being culled by
 :ref:`Depth, Stencil, & Alpha` testing or shader KILL instructions.
 The result is an unsigned 64-bit integer.
+In cases where a boolean result of an occlusion query is enough,
+``PIPE_QUERY_OCCLUSION_PREDICATE`` should be used. It is just like
+``PIPE_QUERY_OCCLUSION_COUNTER`` except that the result is a boolean
+value of FALSE for cases where COUNTER would result in 0 and TRUE
+for all other cases.
 
 Another type of query, ``PIPE_QUERY_TIME_ELAPSED``, returns the amount of
 time, in nanoseconds, the context takes to perform operations.
@@ -349,6 +366,22 @@ Any pointers into the map should be considered invalid and discarded.
 Basically get_transfer, transfer_map, data write, transfer_unmap, and
 transfer_destroy all in one.
 
+
+The box parameter to some of these functions defines a 1D, 2D or 3D
+region of pixels.  This is self-explanatory for 1D, 2D and 3D texture
+targets.
+
+For PIPE_TEXTURE_1D_ARRAY, the box::y and box::height fields refer to the
+array dimension of the texture.
+
+For PIPE_TEXTURE_2D_ARRAY, the box::z and box::depth fields refer to the
+array dimension of the texture.
+
+For PIPE_TEXTURE_CUBE, the box:z and box::depth fields refer to the
+faces of the cube map (z + depth <= 6).
+
+
+
 .. _transfer_flush_region:
 
 transfer_flush_region
@@ -359,6 +392,22 @@ be flushed on write or unmap. Flushes must be requested with
 ``transfer_flush_region``. Flush ranges are relative to the mapped range, not
 the beginning of the resource.
 
+
+
+.. _redefine_user_buffer:
+
+redefine_user_buffer
+%%%%%%%%%%%%%%%%%%%%
+
+This function notifies a driver that the user buffer content has been changed.
+The updated region starts at ``offset`` and is ``size`` bytes large.
+The ``offset`` is relative to the pointer specified in ``user_buffer_create``.
+While uploading the user buffer, the driver is allowed not to upload
+the memory outside of this region.
+The width0 is redefined to ``MAX2(width0, offset+size)``.
+
+
+
 .. _pipe_transfer:
 
 PIPE_TRANSFER
@@ -366,16 +415,32 @@ PIPE_TRANSFER
 
 These flags control the behavior of a transfer object.
 
-* ``READ``: resource contents are read at transfer create time.
-* ``WRITE``: resource contents will be written back at transfer destroy time.
-* ``MAP_DIRECTLY``: a transfer should directly map the resource. May return
-  NULL if not supported.
-* ``DISCARD``: The memory within the mapped region is discarded.
-  Cannot be used with ``READ``.
-* ``DONTBLOCK``: Fail if the resource cannot be mapped immediately.
-* ``UNSYNCHRONIZED``: Do not synchronize pending operations on the resource
-  when mapping. The interaction of any writes to the map and any
-  operations pending on the resource are undefined. Cannot be used with
-  ``READ``.
-* ``FLUSH_EXPLICIT``: Written ranges will be notified later with
-  :ref:`transfer_flush_region`. Cannot be used with ``READ``.
+``PIPE_TRANSFER_READ``
+  Resource contents read back (or accessed directly) at transfer create time.
+
+``PIPE_TRANSFER_WRITE``
+  Resource contents will be written back at transfer_destroy time (or modified
+  as a result of being accessed directly).
+
+``PIPE_TRANSFER_MAP_DIRECTLY``
+  a transfer should directly map the resource. May return NULL if not supported.
+
+``PIPE_TRANSFER_DISCARD_RANGE``
+  The memory within the mapped region is discarded.  Cannot be used with
+  ``PIPE_TRANSFER_READ``.
+
+``PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE``
+  Discards all memory backing the resource.  It should not be used with
+  ``PIPE_TRANSFER_READ``.
+
+``PIPE_TRANSFER_DONTBLOCK``
+  Fail if the resource cannot be mapped immediately.
+
+``PIPE_TRANSFER_UNSYNCHRONIZED``
+  Do not synchronize pending operations on the resource when mapping. The
+  interaction of any writes to the map and any operations pending on the
+  resource are undefined. Cannot be used with ``PIPE_TRANSFER_READ``.
+
+``PIPE_TRANSFER_FLUSH_EXPLICIT``
+  Written ranges will be notified later with :ref:`transfer_flush_region`.
+  Cannot be used with ``PIPE_TRANSFER_READ``.
index ab90097add63e8a708602d9d56636f8779e387a0..976e75bed042a0c140a1a50b87b0d7171a192a99 100644 (file)
@@ -273,7 +273,7 @@ Modern APIs allow using buffers as shader resources.
 **depth0** the depth of the base mip level of the texture
 (1 for everything else).
 
-**array_size the array size for 1D and 2D array textures.
+**array_size** the array size for 1D and 2D array textures.
 For cube maps this must be 6, for other textures 1.
 
 **last_level** the last mip map level present.
index d986e6601e63c7095aba4caeb4cb202767ee4eb6..4debcc6ecc4921d00603882cc72c44a003af2b8d 100644 (file)
@@ -1250,6 +1250,157 @@ This opcode is the inverse of :opcode:`DFRACEXP`.
    dst.zw = \sqrt{src.zw}
 
 
+.. _resourceopcodes:
+
+Resource Access Opcodes
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Those opcodes follow very closely semantics of the respective Direct3D
+instructions. If in doubt double check Direct3D documentation.
+
+.. opcode:: LOAD - Simplified alternative to the "SAMPLE" instruction.
+               Using the provided integer address, LOAD fetches data
+               from the specified buffer/texture without any filtering.
+               The source data may come from any resource type other
+               than CUBE.
+               LOAD dst, address, resource
+               e.g.
+               LOAD TEMP[0], TEMP[1], RES[0]
+               The 'address' is specified as unsigned integers. If the
+               'address' is out of range [0...(# texels - 1)] the
+               result of the fetch is always 0 in all components.
+               As such the instruction doesn't honor address wrap
+               modes, in cases where that behavior is desirable
+               'sample' instruction should be used.
+               address.w always provides an unsigned integer mipmap
+               level. If the value is out of the range then the
+               instruction always returns 0 in all components.
+               address.yz are ignored for buffers and 1d textures.
+               address.z is ignored for 1d texture arrays and 2d
+               textures.
+               For 1D texture arrays address.y provides the array
+               index (also as unsigned integer). If the value is
+               out of the range of available array indices
+               [0... (array size - 1)] then the opcode always returns
+               0 in all components.
+               For 2D texture arrays address.z provides the array
+               index, otherwise it exhibits the same behavior as in
+               the case for 1D texture arrays.
+               The exeact semantics of the source address are presented
+               in the table below:
+               resource type         X     Y     Z       W
+               -------------         ------------------------
+               PIPE_BUFFER           x                ignored
+               PIPE_TEXTURE_1D       x                  mpl
+               PIPE_TEXTURE_2D       x     y            mpl
+               PIPE_TEXTURE_3D       x     y     z      mpl
+               PIPE_TEXTURE_RECT     x     y            mpl
+               PIPE_TEXTURE_CUBE     not allowed as source
+               PIPE_TEXTURE_1D_ARRAY x    idx           mpl
+               PIPE_TEXTURE_2D_ARRAY x     y    idx     mpl
+
+               Where 'mpl' is a mipmap level and 'idx' is the
+               array index.
+
+
+.. opcode:: LOAD_MS - Just like LOAD but allows fetch data from
+               multi-sampled surfaces.
+
+.. opcode:: SAMPLE - Using provided address, sample data from the
+               specified texture using the filtering mode identified
+               by the gven sampler. The source data may come from
+               any resource type other than buffers.
+               SAMPLE dst, address, resource, sampler
+               e.g.
+               SAMPLE TEMP[0], TEMP[1], RES[0], SAMP[0]
+
+.. opcode:: SAMPLE_B - Just like the SAMPLE instruction with the
+               exception that an additiona bias is applied to the
+               level of detail computed as part of the instruction
+               execution.
+               SAMPLE_B dst, address, resource, sampler, lod_bias
+               e.g.
+               SAMPLE_B TEMP[0], TEMP[1], RES[0], SAMP[0], TEMP[2].x
+
+.. opcode:: SAMPLE_C - Similar to the SAMPLE instruction but it
+               performs a comparison filter. The operands to SAMPLE_C
+               are identical to SAMPLE, except that tere is an additional
+               float32 operand, reference value, which must be a register
+               with single-component, or a scalar literal.
+               SAMPLE_C makes the hardware use the current samplers
+               compare_func (in pipe_sampler_state) to compare
+               reference value against the red component value for the
+               surce resource at each texel that the currently configured
+               texture filter covers based on the provided coordinates.
+               SAMPLE_C dst, address, resource.r, sampler, ref_value
+               e.g.
+               SAMPLE_C TEMP[0], TEMP[1], RES[0].r, SAMP[0], TEMP[2].x
+
+.. opcode:: SAMPLE_C_LZ - Same as SAMPLE_C, but LOD is 0 and derivatives
+               are ignored. The LZ stands for level-zero.
+               SAMPLE_C_LZ dst, address, resource.r, sampler, ref_value
+               e.g.
+               SAMPLE_C_LZ TEMP[0], TEMP[1], RES[0].r, SAMP[0], TEMP[2].x
+
+
+.. opcode:: SAMPLE_D - SAMPLE_D is identical to the SAMPLE opcode except
+               that the derivatives for the source address in the x
+               direction and the y direction are provided by extra
+               parameters.
+               SAMPLE_D dst, address, resource, sampler, der_x, der_y
+               e.g.
+               SAMPLE_D TEMP[0], TEMP[1], RES[0], SAMP[0], TEMP[2], TEMP[3]
+
+.. opcode:: SAMPLE_L - SAMPLE_L is identical to the SAMPLE opcode except
+               that the LOD is provided directly as a scalar value,
+               representing no anisotropy. Source addresses A channel
+               is used as the LOD.
+               SAMPLE_L dst, address, resource, sampler
+               e.g.
+               SAMPLE_L TEMP[0], TEMP[1], RES[0], SAMP[0]
+
+
+.. opcode:: GATHER4 - Gathers the four texels to be used in a bi-linear
+               filtering operation and packs them into a single register.
+               Only woth with 2D, 2D array, cubemaps, and cubemaps arrays.
+               For 2D textures, only the addressing modes of the sampler and
+               the top level of any mip pyramid are used. Set W to zero.
+               It behaves like the SAMPLE instruction, but a filtered
+               sample is not generated. The four samples that contribute
+               to filtering are places into xyzw in cunter-clockwise order,
+               starting with the (u,v) texture coordinate delta at the
+               following locations (-, +), (+, +), (+, -), (-, -), where
+               the magnitude of the deltas are half a texel.
+
+
+.. opcode:: RESINFO - query the dimensions of a given input buffer.
+               dst receives width, height, depth or array size and
+               number of mipmap levels. The dst can have a writemask
+               which will specify what info is the caller interested
+               in.
+               RESINFO dst, src_mip_level, resource
+               e.g.
+               RESINFO TEMP[0], TEMP[1].x, RES[0]
+               src_mip_level is an unsigned integer scalar. If it's
+               out of range then returns 0 for width, height and
+               depth/array size but the total number of mipmap is
+               still returned correctly for the given resource.
+               The returned width, height and depth values are for
+               the mipmap level selected by the src_mip_level and
+               are in the number of texels.
+               For 1d texture array width is in dst.x, array size
+               is in dst.y and dst.zw are always 0.
+
+.. opcode:: SAMPLE_POS - query the position of a given sample.
+               dst receives float4 (x, y, 0, 0) indicated where the
+               sample is located. If the resource is not a multi-sample
+               resource and not a render target, the result is 0.
+
+.. opcode:: SAMPLE_INFO - dst receives number of samples in x.
+               If the resource is not a multi-sample resource and
+               not a render target, the result is 0.
+
+
 Explanation of symbols used
 ------------------------------
 
@@ -1332,6 +1483,8 @@ wrapping when interpolating by the rasteriser. If TGSI_CYLINDRICAL_WRAP_X
 is set to 1, the X component should be interpolated according to cylindrical
 wrapping rules.
 
+If file is TGSI_FILE_RESOURCE, a Declaration Resource token follows.
+
 
 Declaration Semantic
 ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1475,6 +1628,23 @@ is a writable stencil reference value. Only the Y component is writable.
 This allows the fragment shader to change the fragments stencilref value.
 
 
+Declaration Resource
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+   Follows Declaration token if file is TGSI_FILE_RESOURCE.
+
+   DCL RES[#], resource, type(s)
+
+   Declares a shader input resource and assigns it to a RES[#]
+   register.
+
+   resource can be one of BUFFER, 1D, 2D, 3D, CUBE, 1DArray and
+   2DArray.
+
+   type must be 1 or 4 entries (if specifying on a per-component
+   level) out of UNORM, SNORM, SINT, UINT and FLOAT.
+
+
 Properties
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
index eb22a09a913b85182b1c469efebc097e07e1f055..7f65b82619eb7d5ddcec6f1b70b69057839cf619 100644 (file)
@@ -33,6 +33,7 @@
 #include "cell_state.h"
 
 #include "util/u_memory.h"
+#include "util/u_transfer.h"
 #include "draw/draw_context.h"
 
 
@@ -115,4 +116,5 @@ cell_init_vertex_functions(struct cell_context *cell)
    cell->pipe.create_vertex_elements_state = cell_create_vertex_elements_state;
    cell->pipe.bind_vertex_elements_state = cell_bind_vertex_elements_state;
    cell->pipe.delete_vertex_elements_state = cell_delete_vertex_elements_state;
+   cell->pipe.redefine_user_buffer = u_default_redefine_user_buffer;
 }
index af1fd953aaf0b89c44973e88492449526cdc6967..b4da1b8b9016c00087a2f3265f6482522ec30516 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "util/u_inlines.h"
 #include "util/u_memory.h"
+#include "util/u_transfer.h"
 
 #include "fo_context.h"
 
@@ -656,4 +657,5 @@ failover_init_state_functions( struct failover_context *failover )
    failover->pipe.set_constant_buffer = failover_set_constant_buffer;
    failover->pipe.create_sampler_view = failover_create_sampler_view;
    failover->pipe.sampler_view_destroy = failover_sampler_view_destroy;
+   failover->pipe.redefine_user_buffer = u_default_redefine_user_buffer;
 }
index 8cbf0b1de4a6507517d99cabbe329c77ab9c4bb5..75e4c253dd98ab1f6115089518965b8573275835 100644 (file)
@@ -962,6 +962,19 @@ galahad_context_transfer_inline_write(struct pipe_context *_context,
 }
 
 
+static void galahad_redefine_user_buffer(struct pipe_context *_context,
+                                         struct pipe_resource *_resource,
+                                         unsigned offset, unsigned size)
+{
+   struct galahad_context *glhd_context = galahad_context(_context);
+   struct galahad_resource *glhd_resource = galahad_resource(_resource);
+   struct pipe_context *context = glhd_context->pipe;
+   struct pipe_resource *resource = glhd_resource->resource;
+
+   context->redefine_user_buffer(context, resource, offset, size);
+}
+
+
 struct pipe_context *
 galahad_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
 {
@@ -1036,6 +1049,7 @@ galahad_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
    glhd_pipe->base.transfer_unmap = galahad_context_transfer_unmap;
    glhd_pipe->base.transfer_flush_region = galahad_context_transfer_flush_region;
    glhd_pipe->base.transfer_inline_write = galahad_context_transfer_inline_write;
+   glhd_pipe->base.redefine_user_buffer = galahad_redefine_user_buffer;
 
    glhd_pipe->pipe = pipe;
 
index 94c428bebf84dbfcb17a4099afe7120cf34ea7b1..f4e1423fa59806c7ac24ae391f42a2b9bd7b128e 100644 (file)
@@ -1,5 +1,13 @@
 Random list of problems with i915g:
 
+- Check if PIPE_CAP_BLEND_EQUATION_SEPARATE work, the code is there.
+  If not fix it! A simple task, good for beginners.
+
+- Add support for PIPE_CAP_POINT_SPRITE either via the draw module or directly
+  via the hardware, look at the classic driver, more advanced.
+
+- What does this button do? Figure out LIS7 with regards to depth offset.
+
 - Dies with BadDrawable on GLXFBconfig changes/destruction. Makes piglit totally
   unusable :( Upgrading xserver helped here, it doesn't crash anymore. Still
   broken, it doesn't update the viewport/get new buffers.
index ea3c10b5e7822b679facbf7c5e37eb12bbbd28e8..707b2e9f95640c81494797a7c3d927ef48a1aa81 100644 (file)
@@ -39,6 +39,9 @@
 #include "pipe/p_screen.h"
 
 
+DEBUG_GET_ONCE_BOOL_OPTION(i915_no_vbuf, "I915_NO_VBUF", FALSE);
+
+
 /*
  * Draw functions
  */
@@ -50,7 +53,6 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
    struct i915_context *i915 = i915_context(pipe);
    struct draw_context *draw = i915->draw;
    void *mapped_indices = NULL;
-   unsigned i;
    unsigned cbuf_dirty;
 
 
@@ -63,14 +65,6 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
    if (i915->dirty)
       i915_update_derived(i915);
 
-   /*
-    * Map vertex buffers
-    */
-   for (i = 0; i < i915->num_vertex_buffers; i++) {
-      void *buf = i915_buffer(i915->vertex_buffer[i].buffer)->data;
-      draw_set_mapped_vertex_buffer(draw, i, buf);
-   }
-
    /*
     * Map index buffer, if present
     */
@@ -90,13 +84,6 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
     */
    draw_vbo(i915->draw, info);
 
-   /*
-    * unmap vertex/index buffers
-    */
-   for (i = 0; i < i915->num_vertex_buffers; i++) {
-      draw_set_mapped_vertex_buffer(draw, i, NULL);
-   }
-
    if (mapped_indices)
       draw_set_mapped_index_buffer(draw, NULL);
 }
@@ -117,10 +104,6 @@ static void i915_destroy(struct pipe_context *pipe)
    if(i915->batch)
       i915->iws->batchbuffer_destroy(i915->batch);
 
-   for (i = 0; i < i915->num_vertex_buffers; i++) {
-      pipe_resource_reference(&i915->vertex_buffer[i].buffer, NULL);
-   }
-
    /* unbind framebuffer */
    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
       pipe_surface_reference(&i915->framebuffer.cbufs[i], NULL);
@@ -164,7 +147,7 @@ i915_create_context(struct pipe_screen *screen, void *priv)
     */
    i915->draw = draw_create(&i915->base);
    assert(i915->draw);
-   if (!debug_get_bool_option("I915_NO_VBUF", FALSE)) {
+   if (!debug_get_option_i915_no_vbuf()) {
       draw_set_rasterize_stage(i915->draw, i915_draw_vbuf_stage(i915));
    } else {
       draw_set_rasterize_stage(i915->draw, i915_draw_render_stage(i915));
@@ -180,6 +163,8 @@ i915_create_context(struct pipe_screen *screen, void *priv)
 
    i915->dirty = ~0;
    i915->hardware_dirty = ~0;
+   i915->immediate_dirty = ~0;
+   i915->dynamic_dirty = ~0;
 
    /* Batch stream debugging is a bit hacked up at the moment:
     */
index b7f1fb22221f1eb100f229eaace698cd1e318f8f..2cf53424f06c1128331ce668c45c464eeefe6f4f 100644 (file)
@@ -219,14 +219,12 @@ struct i915_context {
    struct pipe_scissor_state scissor;
    struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS];
    struct pipe_viewport_state viewport;
-   struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
    struct pipe_index_buffer index_buffer;
 
    unsigned dirty;
 
    unsigned num_samplers;
    unsigned num_fragment_sampler_views;
-   unsigned num_vertex_buffers;
 
    struct i915_winsys_batchbuffer *batch;
 
@@ -237,6 +235,8 @@ struct i915_context {
 
    struct i915_state current;
    unsigned hardware_dirty;
+   unsigned immediate_dirty;
+   unsigned dynamic_dirty;
 
    struct util_slab_mempool transfer_pool;
 };
index 845e92cf5c60194d562393b58c9b27424ca7902b..1713bf131f2e99c0443e1b0ba7035b438ee148a5 100644 (file)
@@ -48,10 +48,15 @@ static const struct debug_named_value debug_options[] = {
 unsigned i915_debug = 0;
 boolean i915_tiling = TRUE;
 
-void i915_debug_init(struct i915_screen *screen)
+DEBUG_GET_ONCE_FLAGS_OPTION(i915_debug, "I915_DEBUG", debug_options, 0)
+DEBUG_GET_ONCE_BOOL_OPTION(i915_no_tiling, "I915_NO_TILING", FALSE)
+DEBUG_GET_ONCE_BOOL_OPTION(i915_lie, "I915_LIE", FALSE)
+
+void i915_debug_init(struct i915_screen *is)
 {
-   i915_debug = debug_get_flags_option("I915_DEBUG", debug_options, 0);
-   i915_tiling = !debug_get_bool_option("I915_NO_TILING", FALSE);
+   i915_debug = debug_get_option_i915_debug();
+   is->debug.tiling = !debug_get_option_i915_no_tiling();
+   is->debug.lie = debug_get_option_i915_lie();
 }
 
 
index 11af7662f0a614e75f7f9d52ae27bc336460b011..fa60799d0c55669253ae9ab3ae4327764a96a54a 100644 (file)
@@ -46,7 +46,6 @@ struct i915_winsys_batchbuffer;
 #define DBG_CONSTANTS 0x20
 
 extern unsigned i915_debug;
-extern boolean i915_tiling;
 
 #ifdef DEBUG
 static INLINE boolean
index a2c70b11991724e5021ee0c0e8c66592ba78c6da..911c051d1f22e4c6a692942eb2246d0b0e9f7148 100644 (file)
@@ -74,7 +74,6 @@ static void i915_flush_pipe( struct pipe_context *pipe,
    /* If there are no flags, just flush pending commands to hardware:
     */
    FLUSH_BATCH(fence);
-   i915->vbo_flushed = 1;
 
    I915_DBG(DBG_FLUSH, "%s: #####\n", __FUNCTION__);
 }
@@ -93,5 +92,8 @@ void i915_flush(struct i915_context *i915, struct pipe_fence_handle **fence)
    struct i915_winsys_batchbuffer *batch = i915->batch;
 
    batch->iws->batchbuffer_flush(batch, fence);
+   i915->vbo_flushed = 1;
    i915->hardware_dirty = ~0;
+   i915->immediate_dirty = ~0;
+   i915->dynamic_dirty = ~0;
 }
index e793d126ade8b02a0631cb4f2a0b68e282010814..aad5235a6ad3c2bb26632f627bde0f525f5d62f7 100644 (file)
@@ -172,15 +172,15 @@ i915_texture_set_image_offset(struct i915_texture *tex,
 }
 
 static enum i915_winsys_buffer_tile
-i915_texture_tiling(struct pipe_resource *pt)
+i915_texture_tiling(struct i915_screen *is, struct i915_texture *tex)
 {
-   if (!i915_tiling)
+   if (!is->debug.tiling)
       return I915_TILE_NONE;
 
-   if (pt->target == PIPE_TEXTURE_1D)
+   if (tex->b.b.target == PIPE_TEXTURE_1D)
       return I915_TILE_NONE;
 
-   if (util_format_is_s3tc(pt->format))
+   if (util_format_is_s3tc(tex->b.b.format))
       /* XXX X-tiling might make sense */
       return I915_TILE_NONE;
 
@@ -401,11 +401,7 @@ i915_texture_layout_3d(struct i915_texture *tex)
 static boolean
 i915_texture_layout(struct i915_texture * tex)
 {
-   struct pipe_resource *pt = &tex->b.b;
-
-   tex->tiling = i915_texture_tiling(pt);
-
-   switch (pt->target) {
+   switch (tex->b.b.target) {
    case PIPE_TEXTURE_1D:
    case PIPE_TEXTURE_2D:
    case PIPE_TEXTURE_RECT:
@@ -649,11 +645,7 @@ i945_texture_layout_cube(struct i915_texture *tex)
 static boolean
 i945_texture_layout(struct i915_texture * tex)
 {
-   struct pipe_resource *pt = &tex->b.b;
-
-   tex->tiling = i915_texture_tiling(pt);
-
-   switch (pt->target) {
+   switch (tex->b.b.target) {
    case PIPE_TEXTURE_1D:
    case PIPE_TEXTURE_2D:
    case PIPE_TEXTURE_RECT:
@@ -664,7 +656,7 @@ i945_texture_layout(struct i915_texture * tex)
       i945_texture_layout_3d(tex);
       break;
    case PIPE_TEXTURE_CUBE:
-      if (!util_format_is_s3tc(pt->format))
+      if (!util_format_is_s3tc(tex->b.b.format))
          i9x5_texture_layout_cube(tex);
       else
          i945_texture_layout_cube(tex);
@@ -818,6 +810,8 @@ i915_texture_create(struct pipe_screen *screen,
    pipe_reference_init(&tex->b.b.reference, 1);
    tex->b.b.screen = screen;
 
+   tex->tiling = i915_texture_tiling(is, tex);
+
    if (is->is_i945) {
       if (!i945_texture_layout(tex))
          goto fail;
index bdbc08e808653d0d82b94b75cfb283c79097e9f0..77febbf5012aa8e0754e33882f9b63de9b0b279e 100644 (file)
@@ -98,59 +98,81 @@ i915_get_name(struct pipe_screen *screen)
 }
 
 static int
-i915_get_param(struct pipe_screen *screen, enum pipe_cap param)
+i915_get_param(struct pipe_screen *screen, enum pipe_cap cap)
 {
-   switch (param) {
-   case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
-      return 8;
-   case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
-      return 0;
-   case PIPE_CAP_MAX_COMBINED_SAMPLERS:
-      return 8;
+   struct i915_screen *is = i915_screen(screen);
+
+   switch (cap) {
+   /* Supported features (boolean caps). */
+   case PIPE_CAP_ANISOTROPIC_FILTER:
    case PIPE_CAP_NPOT_TEXTURES:
-      return 1;
+   case PIPE_CAP_PRIMITIVE_RESTART: /* draw module */
+   case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
+   case PIPE_CAP_TEXTURE_SHADOW_MAP:
    case PIPE_CAP_TWO_SIDED_STENCIL:
       return 1;
-   case PIPE_CAP_GLSL:
-      return 0;
-   case PIPE_CAP_ANISOTROPIC_FILTER:
+
+   /* Features that should be supported (boolean caps). */
+   /* XXX: Just test the code */
+   case PIPE_CAP_BLEND_EQUATION_SEPARATE:
       return 0;
+
+   /* Unsupported features (boolean caps). */
+   case PIPE_CAP_ARRAY_TEXTURES:
+   case PIPE_CAP_DEPTH_CLAMP:
+   case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: /* disable for now */
+   case PIPE_CAP_GLSL:
+   case PIPE_CAP_INDEP_BLEND_ENABLE:
+   case PIPE_CAP_INDEP_BLEND_FUNC:
+   case PIPE_CAP_INSTANCED_DRAWING: /* draw module? */
    case PIPE_CAP_POINT_SPRITE:
+   case PIPE_CAP_SHADER_STENCIL_EXPORT:
+   case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+   case PIPE_CAP_TEXTURE_SWIZZLE:
+   case PIPE_CAP_TIMER_QUERY:
       return 0;
-   case PIPE_CAP_MAX_RENDER_TARGETS:
-      return 1;
+
+   /* Features we can lie about (boolean caps). */
    case PIPE_CAP_OCCLUSION_QUERY:
+      return is->debug.lie ? 1 : 0;
+
+   /* Texturing. */
+   case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+   case PIPE_CAP_MAX_COMBINED_SAMPLERS:
+      return 8;
+   case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
       return 0;
-   case PIPE_CAP_TIMER_QUERY:
-      return 0;
-   case PIPE_CAP_TEXTURE_SHADOW_MAP:
-      return 1;
    case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
       return I915_MAX_TEXTURE_2D_LEVELS;
    case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
       return I915_MAX_TEXTURE_3D_LEVELS;
    case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
       return I915_MAX_TEXTURE_2D_LEVELS;
+
+   /* Render targets. */
+   case PIPE_CAP_MAX_RENDER_TARGETS:
+      return 1;
+
+   /* Fragment coordinate conventions. */
    case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
    case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
       return 1;
    case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
    case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
       return 0;
-   case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
-      /* disable for now */
-      return 0;
+
    default:
+      debug_printf("%s: Unkown cap %u.\n", __FUNCTION__, cap);
       return 0;
    }
 }
 
 static int
-i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap param)
+i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap cap)
 {
    switch(shader) {
    case PIPE_SHADER_VERTEX:
-      return draw_get_shader_param(shader, param);
+      return draw_get_shader_param(shader, cap);
    case PIPE_SHADER_FRAGMENT:
       break;
    default:
@@ -158,7 +180,7 @@ i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_sha
    }
 
    /* XXX: these are just shader model 2.0 values, fix this! */
-   switch(param) {
+   switch(cap) {
       case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
          return 96;
       case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
@@ -191,15 +213,15 @@ i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_sha
       case PIPE_SHADER_CAP_SUBROUTINES:
          return 0;
       default:
-         assert(0);
+         debug_printf("%s: Unkown cap %u.\n", __FUNCTION__, cap);
          return 0;
    }
 }
 
 static float
-i915_get_paramf(struct pipe_screen *screen, enum pipe_cap param)
+i915_get_paramf(struct pipe_screen *screen, enum pipe_cap cap)
 {
-   switch (param) {
+   switch(cap) {
    case PIPE_CAP_MAX_LINE_WIDTH:
       /* fall-through */
    case PIPE_CAP_MAX_LINE_WIDTH_AA:
@@ -217,6 +239,7 @@ i915_get_paramf(struct pipe_screen *screen, enum pipe_cap param)
       return 16.0;
 
    default:
+      debug_printf("%s: Unkown cap %u.\n", __FUNCTION__, cap);
       return 0;
    }
 }
@@ -320,6 +343,20 @@ i915_fence_finish(struct pipe_screen *screen,
  */
 
 
+static void
+i915_flush_frontbuffer(struct pipe_screen *screen,
+                       struct pipe_resource *resource,
+                       unsigned level, unsigned layer,
+                       void *winsys_drawable_handle)
+{
+   /* XXX: Dummy right now. */
+   (void)screen;
+   (void)resource;
+   (void)level;
+   (void)layer;
+   (void)winsys_drawable_handle;
+}
+
 static void
 i915_destroy_screen(struct pipe_screen *screen)
 {
@@ -371,6 +408,7 @@ i915_screen_create(struct i915_winsys *iws)
    is->base.winsys = NULL;
 
    is->base.destroy = i915_destroy_screen;
+   is->base.flush_frontbuffer = i915_flush_frontbuffer;
 
    is->base.get_name = i915_get_name;
    is->base.get_vendor = i915_get_vendor;
index bb4d255a3b39942060ff06171a08f50458776329..60f0e2971e0cb17a06cc50cc47ae315564be9843 100644 (file)
@@ -45,6 +45,11 @@ struct i915_screen
    struct i915_winsys *iws;
 
    boolean is_i945;
+
+   struct {
+      boolean tiling;
+      boolean lie;
+   } debug;
 };
 
 
index 4a1a4a04f6d6873fa41d18bf04b59e1317dc10a7..58bbbd1de2ce452944934b57fbd2ba47ba3cd6f2 100644 (file)
@@ -33,6 +33,7 @@
 #include "util/u_inlines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
+#include "util/u_transfer.h"
 #include "tgsi/tgsi_parse.h"
 
 #include "i915_context.h"
@@ -57,10 +58,8 @@ translate_wrap_mode(unsigned wrap)
       return TEXCOORDMODE_CLAMP_EDGE;
    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
       return TEXCOORDMODE_CLAMP_BORDER;
-   /*         
-   case PIPE_TEX_WRAP_MIRRORED_REPEAT:
+   case PIPE_TEX_WRAP_MIRROR_REPEAT:
       return TEXCOORDMODE_MIRROR;
-    */
    default:
       return TEXCOORDMODE_WRAP;
    }
@@ -535,21 +534,31 @@ static void i915_set_constant_buffer(struct pipe_context *pipe,
 
    /* if we have a new buffer compare it with the old one */
    if (buf) {
-      struct i915_buffer *ir = i915_buffer(buf);
+      struct i915_buffer *ibuf = i915_buffer(buf);
       struct pipe_resource *old_buf = i915->constants[shader];
       struct i915_buffer *old = old_buf ? i915_buffer(old_buf) : NULL;
-
-      new_num = ir->b.b.width0 / 4 * sizeof(float);
-
-      if (old && new_num != i915->current.num_user_constants[shader])
-         diff = memcmp(old->data, ir->data, ir->b.b.width0);
+      unsigned old_num = i915->current.num_user_constants[shader];
+
+      new_num = ibuf->b.b.width0 / 4 * sizeof(float);
+
+      if (old_num == new_num) {
+         if (old_num == 0)
+            diff = FALSE;
+#if 0
+         /* XXX no point in running this code since st/mesa only uses user buffers */
+         /* Can't compare the buffer data since they are userbuffers */
+         else if (old && old->free_on_destroy)
+            diff = memcmp(old->data, ibuf->data, ibuf->b.b.width0);
+#else
+         (void)old;
+#endif
+      }
    } else {
       diff = i915->current.num_user_constants[shader] != 0;
    }
 
    /*
     * flush before updateing the state.
-    * XXX: looks like its okay to skip the flush for vertex cbufs
     */
    if (diff && shader == PIPE_SHADER_FRAGMENT)
       draw_flush(i915->draw);
@@ -766,17 +775,25 @@ static void i915_set_vertex_buffers(struct pipe_context *pipe,
                                     const struct pipe_vertex_buffer *buffers)
 {
    struct i915_context *i915 = i915_context(pipe);
-   /* Because we change state before the draw_set_vertex_buffers call
-    * we need a flush here, just to be sure.
-    */
-   draw_flush(i915->draw);
+   struct draw_context *draw = i915->draw;
+   int i;
 
-   util_copy_vertex_buffers(i915->vertex_buffer,
-                            &i915->num_vertex_buffers,
-                            buffers, count);
+#if 0
+   /* XXX doesn't look like this is needed */
+   /* unmap old */
+   for (i = 0; i < i915->num_vertex_buffers; i++) {
+      draw_set_mapped_vertex_buffer(draw, i, NULL);
+   }
+#endif
 
    /* pass-through to draw module */
-   draw_set_vertex_buffers(i915->draw, count, buffers);
+   draw_set_vertex_buffers(draw, count, buffers);
+
+   /* map new */
+   for (i = 0; i < count; i++) {
+      void *buf = i915_buffer(buffers[i].buffer)->data;
+      draw_set_mapped_vertex_buffer(draw, i, buf);
+   }
 }
 
 static void *
@@ -801,11 +818,6 @@ i915_bind_vertex_elements_state(struct pipe_context *pipe,
    struct i915_context *i915 = i915_context(pipe);
    struct i915_velems_state *i915_velems = (struct i915_velems_state *) velems;
 
-   /* Because we change state before the draw_set_vertex_buffers call
-    * we need a flush here, just to be sure.
-    */
-   draw_flush(i915->draw);
-
    /* pass-through to draw module */
    if (i915_velems) {
       draw_set_vertex_elements(i915->draw,
@@ -882,4 +894,5 @@ i915_init_state_functions( struct i915_context *i915 )
    i915->base.set_viewport_state = i915_set_viewport_state;
    i915->base.set_vertex_buffers = i915_set_vertex_buffers;
    i915->base.set_index_buffer = i915_set_index_buffer;
+   i915->base.redefine_user_buffer = u_default_redefine_user_buffer;
 }
index d61a8c3407f31500ffefbcee06ba0d3e5dd57b2b..204cee6fe9ebe5c3d3dfc09902bcdcd753568c3b 100644 (file)
  * (active) state every time a 4kb boundary is crossed.
  */
 
-static INLINE void set_dynamic_indirect(struct i915_context *i915,
-                                        unsigned offset,
-                                        const unsigned *src,
-                                        unsigned dwords)
+static INLINE void set_dynamic(struct i915_context *i915,
+                               unsigned offset,
+                               const unsigned state)
+{
+   if (i915->current.dynamic[offset] == state)
+      return;
+
+   i915->current.dynamic[offset] = state;
+   i915->dynamic_dirty |= 1 << offset;
+   i915->hardware_dirty |= I915_HW_DYNAMIC;
+}
+
+
+
+static INLINE void set_dynamic_array(struct i915_context *i915,
+                                     unsigned offset,
+                                     const unsigned *src,
+                                     unsigned dwords)
 {
    unsigned i;
 
    if (!memcmp(src, &i915->current.dynamic[offset], dwords * 4))
       return;
 
-   for (i = 0; i < dwords; i++)
+   for (i = 0; i < dwords; i++) {
       i915->current.dynamic[offset + i] = src[i];
+      i915->dynamic_dirty |= 1 << (offset + i);
+   }
 
    i915->hardware_dirty |= I915_HW_DYNAMIC;
 }
@@ -79,12 +95,7 @@ static void upload_MODES4(struct i915_context *i915)
      */
    modes4 |= i915->blend->modes4;
 
-   /* Always, so that we know when state is in-active:
-    */
-   set_dynamic_indirect(i915,
-                        I915_DYNAMIC_MODES4,
-                        &modes4,
-                        1);
+   set_dynamic(i915, I915_DYNAMIC_MODES4, modes4);
 }
 
 const struct i915_tracked_state i915_upload_MODES4 = {
@@ -107,10 +118,7 @@ static void upload_BFO(struct i915_context *i915)
       bfo[0] |= i915->stencil_ref.ref_value[1] << BFO_STENCIL_REF_SHIFT;
    }
 
-   set_dynamic_indirect(i915,
-                        I915_DYNAMIC_BFO_0,
-                        &(bfo[0]),
-                        2);
+   set_dynamic_array(i915, I915_DYNAMIC_BFO_0, bfo, 2);
 }
 
 const struct i915_tracked_state i915_upload_BFO = {
@@ -141,10 +149,7 @@ static void upload_BLENDCOLOR(struct i915_context *i915)
                                color[3]);
    }
 
-   set_dynamic_indirect(i915,
-                        I915_DYNAMIC_BC_0,
-                        bc,
-                        2);
+   set_dynamic_array(i915, I915_DYNAMIC_BC_0, bc, 2);
 }
 
 const struct i915_tracked_state i915_upload_BLENDCOLOR = {
@@ -161,10 +166,7 @@ static void upload_IAB(struct i915_context *i915)
 {
    unsigned iab = i915->blend->iab;
 
-   set_dynamic_indirect(i915,
-                        I915_DYNAMIC_IAB,
-                        &iab,
-                        1);
+   set_dynamic(i915, I915_DYNAMIC_IAB, iab);
 }
 
 const struct i915_tracked_state i915_upload_IAB = {
@@ -179,10 +181,8 @@ const struct i915_tracked_state i915_upload_IAB = {
  */
 static void upload_DEPTHSCALE(struct i915_context *i915)
 {
-   set_dynamic_indirect(i915,
-                        I915_DYNAMIC_DEPTHSCALE_0,
-                        &(i915->rasterizer->ds[0].u),
-                        2);
+   set_dynamic_array(i915, I915_DYNAMIC_DEPTHSCALE_0,
+                     &i915->rasterizer->ds[0].u, 2);
 }
 
 const struct i915_tracked_state i915_upload_DEPTHSCALE = {
@@ -234,10 +234,7 @@ static void upload_STIPPLE(struct i915_context *i915)
                 (p[3] << 12));
    }
 
-   set_dynamic_indirect(i915,
-                        I915_DYNAMIC_STP_0,
-                        &st[0],
-                        2);
+   set_dynamic_array(i915, I915_DYNAMIC_STP_0, st, 2);
 }
 
 const struct i915_tracked_state i915_upload_STIPPLE = {
@@ -253,10 +250,7 @@ const struct i915_tracked_state i915_upload_STIPPLE = {
  */
 static void upload_SCISSOR_ENABLE( struct i915_context *i915 )
 {
-   set_dynamic_indirect(i915,
-                        I915_DYNAMIC_SC_ENA_0,
-                        &(i915->rasterizer->sc[0]),
-                        1);
+   set_dynamic(i915, I915_DYNAMIC_SC_ENA_0, i915->rasterizer->sc[0]);
 }
 
 const struct i915_tracked_state i915_upload_SCISSOR_ENABLE = {
@@ -282,10 +276,7 @@ static void upload_SCISSOR_RECT(struct i915_context *i915)
    sc[1] = (y1 << 16) | (x1 & 0xffff);
    sc[2] = (y2 << 16) | (x2 & 0xffff);
 
-   set_dynamic_indirect(i915,
-                        I915_DYNAMIC_SC_RECT_0,
-                        &sc[0],
-                        3);
+   set_dynamic_array(i915, I915_DYNAMIC_SC_RECT_0, sc, 3);
 }
 
 const struct i915_tracked_state i915_upload_SCISSOR_RECT = {
index 5a89977c26c6f6897352b187b23ece17d36241a1..509d487b4988a8ff6a76c04da297209557fcfc08 100644 (file)
@@ -35,6 +35,8 @@
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
 
+#include "util/u_math.h"
+
 static unsigned translate_format( enum pipe_format format )
 {
    switch (format) {
@@ -178,11 +180,6 @@ i915_emit_hardware_state(struct i915_context *i915 )
                 ENABLE_TEXKILL_3D_4D | 
                 TEXKILL_4D);
 
-      /* Need to initialize this to zero.
-       */
-      OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | (0));
-      OUT_BATCH(0);
-
       OUT_BATCH(_3DSTATE_DEPTH_SUBRECT_DISABLE);
 
       /* disable indirect state for now
@@ -194,27 +191,30 @@ i915_emit_hardware_state(struct i915_context *i915 )
    /* 7 dwords, 1 relocs */
    if (i915->hardware_dirty & I915_HW_IMMEDIATE)
    {
-      OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 
-                I1_LOAD_S(0) |
-                I1_LOAD_S(1) |
-                I1_LOAD_S(2) |
-                I1_LOAD_S(4) |
-                I1_LOAD_S(5) |
-                I1_LOAD_S(6) | 
-                (5));
-      
-      if(i915->vbo)
-         OUT_RELOC(i915->vbo,
-                   I915_USAGE_VERTEX,
-                   i915->current.immediate[I915_IMMEDIATE_S0]);
-      else
-         /* FIXME: we should not do this */
-         OUT_BATCH(0);
-      OUT_BATCH(i915->current.immediate[I915_IMMEDIATE_S1]);
-      OUT_BATCH(i915->current.immediate[I915_IMMEDIATE_S2]);
-      OUT_BATCH(i915->current.immediate[I915_IMMEDIATE_S4]);
-      OUT_BATCH(i915->current.immediate[I915_IMMEDIATE_S5]);
-      OUT_BATCH(i915->current.immediate[I915_IMMEDIATE_S6]);
+      /* remove unwatned bits and S7 */
+      unsigned dirty = (1 << I915_IMMEDIATE_S0 | 1 << I915_IMMEDIATE_S1 |
+                        1 << I915_IMMEDIATE_S2 | 1 << I915_IMMEDIATE_S3 |
+                        1 << I915_IMMEDIATE_S3 | 1 << I915_IMMEDIATE_S4 |
+                        1 << I915_IMMEDIATE_S5 | 1 << I915_IMMEDIATE_S6) &
+                       i915->immediate_dirty;
+      int i, num = util_bitcount(dirty);
+      assert(num && num <= I915_MAX_IMMEDIATE);
+
+      OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
+                dirty << 4 | (num - 1));
+
+      if (i915->immediate_dirty & (1 << I915_IMMEDIATE_S0)) {
+         if (i915->vbo)
+            OUT_RELOC(i915->vbo, I915_USAGE_VERTEX,
+                      i915->current.immediate[I915_IMMEDIATE_S0]);
+         else
+            OUT_BATCH(0);
+      }
+
+      for (i = 1; i < I915_MAX_IMMEDIATE; i++) {
+         if (dirty & (1 << i))
+            OUT_BATCH(i915->current.immediate[i]);
+      }
    } 
 
 #if 01
@@ -223,7 +223,8 @@ i915_emit_hardware_state(struct i915_context *i915 )
    {
       int i;
       for (i = 0; i < I915_MAX_DYNAMIC; i++) {
-         OUT_BATCH(i915->current.dynamic[i]);
+         if (i915->dynamic_dirty & (1 << i));
+            OUT_BATCH(i915->current.dynamic[i]);
       }
    }
 #endif
@@ -443,4 +444,6 @@ i915_emit_hardware_state(struct i915_context *i915 )
             i915->batch->relocs - save_relocs);
 
    i915->hardware_dirty = 0;
+   i915->immediate_dirty = 0;
+   i915->dynamic_dirty = 0;
 }
index f9ade7077f245a1a9493758168803dbee778702a..813486473997d7b76fb54dfd7ef4d3b378412394 100644 (file)
 #include "util/u_memory.h"
 
 
-/* All state expressable with the LOAD_STATE_IMMEDIATE_1 packet.
- * Would like to opportunistically recombine all these fragments into
- * a single packet containing only what has changed, but for now emit
- * as multiple packets.
+/* Convinience function to check immediate state.
  */
 
+static INLINE void set_immediate(struct i915_context *i915,
+                                 unsigned offset,
+                                 const unsigned state)
+{
+   if (i915->current.immediate[offset] == state)
+      return;
+
+   i915->current.immediate[offset] = state;
+   i915->immediate_dirty |= 1 << offset;
+   i915->hardware_dirty |= I915_HW_IMMEDIATE;
+}
 
 
 
@@ -56,9 +64,14 @@ static void upload_S0S1(struct i915_context *i915)
     */
    LIS0 = i915->vbo_offset;
 
+   /* Need to force this */
+   if (i915->dirty & I915_NEW_VBO) {
+      i915->immediate_dirty |= 1 << I915_IMMEDIATE_S0;
+      i915->hardware_dirty |= I915_HW_IMMEDIATE;
+   }
+
    /* I915_NEW_VERTEX_SIZE
     */
-   /* XXX do this where the vertex size is calculated! */
    {
       unsigned vertex_size = i915->current.vertex_info.size;
 
@@ -66,16 +79,8 @@ static void upload_S0S1(struct i915_context *i915)
               (vertex_size << 16));
    }
 
-   /* I915_NEW_VBO
-    */
-   if (1 ||
-       i915->current.immediate[I915_IMMEDIATE_S0] != LIS0 ||
-       i915->current.immediate[I915_IMMEDIATE_S1] != LIS1)
-   {
-      i915->current.immediate[I915_IMMEDIATE_S0] = LIS0;
-      i915->current.immediate[I915_IMMEDIATE_S1] = LIS1;
-      i915->hardware_dirty |= I915_HW_IMMEDIATE;
-   }
+   set_immediate(i915, I915_IMMEDIATE_S0, LIS0);
+   set_immediate(i915, I915_IMMEDIATE_S1, LIS1);
 }
 
 const struct i915_tracked_state i915_upload_S0S1 = {
@@ -98,21 +103,13 @@ static void upload_S2S4(struct i915_context *i915)
    {
       LIS2 = i915->current.vertex_info.hwfmt[1];
       LIS4 = i915->current.vertex_info.hwfmt[0];
-      /*
-      debug_printf("LIS2: 0x%x  LIS4: 0x%x\n", LIS2, LIS4);
-      */
       assert(LIS4); /* should never be zero? */
    }
 
    LIS4 |= i915->rasterizer->LIS4;
 
-   if (LIS2 != i915->current.immediate[I915_IMMEDIATE_S2] ||
-       LIS4 != i915->current.immediate[I915_IMMEDIATE_S4]) {
-
-      i915->current.immediate[I915_IMMEDIATE_S2] = LIS2;
-      i915->current.immediate[I915_IMMEDIATE_S4] = LIS4;
-      i915->hardware_dirty |= I915_HW_IMMEDIATE;
-   }
+   set_immediate(i915, I915_IMMEDIATE_S2, LIS2);
+   set_immediate(i915, I915_IMMEDIATE_S4, LIS4);
 }
 
 const struct i915_tracked_state i915_upload_S2S4 = {
@@ -142,15 +139,12 @@ static void upload_S5(struct i915_context *i915)
 #if 0
    /* I915_NEW_RASTERIZER
     */
-   if (i915->state.Polygon->OffsetFill) {
+   if (i915->rasterizer->LIS7) {
       LIS5 |= S5_GLOBAL_DEPTH_OFFSET_ENABLE;
    }
 #endif
 
-   if (LIS5 != i915->current.immediate[I915_IMMEDIATE_S5]) {
-      i915->current.immediate[I915_IMMEDIATE_S5] = LIS5;
-      i915->hardware_dirty |= I915_HW_IMMEDIATE;
-   }
+   set_immediate(i915, I915_IMMEDIATE_S5, LIS5);
 }
 
 const struct i915_tracked_state i915_upload_S5 = {
@@ -180,14 +174,11 @@ static void upload_S6(struct i915_context *i915)
     */
    LIS6 |= i915->depth_stencil->depth_LIS6;
 
-   if (LIS6 != i915->current.immediate[I915_IMMEDIATE_S6]) {
-      i915->current.immediate[I915_IMMEDIATE_S6] = LIS6;
-      i915->hardware_dirty |= I915_HW_IMMEDIATE;
-   }
+   set_immediate(i915, I915_IMMEDIATE_S6, LIS6);
 }
 
 const struct i915_tracked_state i915_upload_S6 = {
-   "imm s6",
+   "imm S6",
    upload_S6,
    I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL | I915_NEW_FRAMEBUFFER
 };
@@ -204,10 +195,9 @@ static void upload_S7(struct i915_context *i915)
     */
    LIS7 = i915->rasterizer->LIS7;
 
-   if (LIS7 != i915->current.immediate[I915_IMMEDIATE_S7]) {
-      i915->current.immediate[I915_IMMEDIATE_S7] = LIS7;
-      i915->hardware_dirty |= I915_HW_IMMEDIATE;
-   }
+#if 0
+   set_immediate(i915, I915_IMMEDIATE_S7, LIS7);
+#endif
 }
 
 const struct i915_tracked_state i915_upload_S7 = {
index 24ea416f015469b84215dba63bd9f2ca1b19e624..e915a886c9b7196adcbf58a659ae3e683a39cf8a 100644 (file)
@@ -103,11 +103,12 @@ struct i915_winsys {
     * @usage how is the hardware going to use the buffer.
     * @offset add this to the reloc buffers address
     * @target buffer where to write the address, null for batchbuffer.
+    * @fenced relocation needs a fence.
     */
    int (*batchbuffer_reloc)(struct i915_winsys_batchbuffer *batch,
                             struct i915_winsys_buffer *reloc,
                             enum i915_winsys_buffer_usage usage,
-                            unsigned offset, bool fenced);
+                            unsigned offset, boolean fenced);
 
    /**
     * Flush a bufferbatch.
index b23454b5808c7f191003a30d08aa1c9f16f2109a..570ea23ff458ff83c50a3e44af5bd1d6b91eb673 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "util/u_memory.h"
 #include "util/u_format.h"
+#include "util/u_transfer.h"
 
 
 static unsigned brw_translate_surface_format( unsigned id )
@@ -302,6 +303,7 @@ brw_pipe_vertex_init( struct brw_context *brw )
    brw->base.create_vertex_elements_state = brw_create_vertex_elements_state;
    brw->base.bind_vertex_elements_state = brw_bind_vertex_elements_state;
    brw->base.delete_vertex_elements_state = brw_delete_vertex_elements_state;
+   brw->base.redefine_user_buffer = u_default_redefine_user_buffer;
 }
 
 
index 3efbd6a246d577d1c9d302a223ce8dade86e4c88..b533abe24c6145df45e783d190bdaa69e56ac441 100644 (file)
@@ -855,6 +855,19 @@ identity_context_transfer_inline_write(struct pipe_context *_context,
 }
 
 
+static void identity_redefine_user_buffer(struct pipe_context *_context,
+                                          struct pipe_resource *_resource,
+                                          unsigned offset, unsigned size)
+{
+   struct identity_context *id_context = identity_context(_context);
+   struct identity_resource *id_resource = identity_resource(_resource);
+   struct pipe_context *context = id_context->pipe;
+   struct pipe_resource *resource = id_resource->resource;
+
+   context->redefine_user_buffer(context, resource, offset, size);
+}
+
+
 struct pipe_context *
 identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
 {
@@ -929,6 +942,7 @@ identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
    id_pipe->base.transfer_unmap = identity_context_transfer_unmap;
    id_pipe->base.transfer_flush_region = identity_context_transfer_flush_region;
    id_pipe->base.transfer_inline_write = identity_context_transfer_inline_write;
+   id_pipe->base.redefine_user_buffer = identity_redefine_user_buffer;
 
    id_pipe->pipe = pipe;
 
index 26b258b956957cac81a0f71788980928461f4850..c10a8cbc12c8e406fbb22323fec2d6a996bf0cd4 100644 (file)
@@ -96,10 +96,15 @@ if env['platform'] != 'embedded':
         tests.append('round')
 
     for test in tests:
+        testname = 'lp_test_' + test
         target = env.Program(
-            target = 'lp_test_' + test,
-            source = ['lp_test_' + test + '.c', 'lp_test_main.c'],
+            target = testname,
+            source = [testname + '.c', 'lp_test_main.c'],
         )
         env.InstallProgram(target)
+        
+        # http://www.scons.org/wiki/UnitTests
+        alias = env.Alias(testname, [target], target[0].abspath)
+        AlwaysBuild(alias)
 
 Export('llvmpipe')
index 85e3cdec82c0b244240eb4691fa49a5ad6025599..849db06acdf3f5402ec454f0584f8ab3e3496071 100644 (file)
@@ -72,7 +72,7 @@ llvmpipe_flush( struct pipe_context *pipe,
 
          for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) {
             util_snprintf(filename, sizeof(filename), "cbuf%u_%u", i, frame_no);
-            debug_dump_surface_bmp(&llvmpipe->pipe, filename, llvmpipe->framebuffer.cbufs[0]);
+            debug_dump_surface_bmp(&llvmpipe->pipe, filename, llvmpipe->framebuffer.cbufs[i]);
          }
 
          if (0) {
index fffdeb6ccde615cb7c16390d7d44c5b0a9fec2e1..be86f66de91aea20287b57e197be06d18501b90f 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "draw/draw_context.h"
 #include "util/u_inlines.h"
+#include "util/u_transfer.h"
 
 
 static void *
@@ -114,4 +115,6 @@ llvmpipe_init_vertex_funcs(struct llvmpipe_context *llvmpipe)
 
    llvmpipe->pipe.set_vertex_buffers = llvmpipe_set_vertex_buffers;
    llvmpipe->pipe.set_index_buffer = llvmpipe_set_index_buffer;
+
+   llvmpipe->pipe.redefine_user_buffer = u_default_redefine_user_buffer;
 }
index 149ee6f1256a4e9dca3c4144d8361fabeab0c8d7..d229c6203109f39214b7a6a3f92105a060c1ed08 100644 (file)
 
 
 #include "util/u_cpu_detect.h"
+#include "util/u_math.h"
 
 #include "gallivm/lp_bld_const.h"
 #include "gallivm/lp_bld_init.h"
 #include "lp_test.h"
 
 
-#ifdef PIPE_CC_MSVC
-static INLINE double
-round(double x)
-{
-   if (x >= 0.0)
-      return floor(x + 0.5);
-   else
-      return ceil(x - 0.5);
-}
-#endif
-
-
 void
 dump_type(FILE *fp,
           struct lp_type type)
index ad324774c0347de38f50260accf28e2f0786dd13..00a4c1eb01ede7bc9e7d8723964f8163cd4949a7 100644 (file)
@@ -28,6 +28,7 @@
 #include <pipe/p_screen.h>
 #include <util/u_memory.h>
 #include <util/u_inlines.h>
+#include "util/u_transfer.h"
 
 static void noop_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
 {
@@ -287,4 +288,5 @@ void noop_init_state_functions(struct pipe_context *ctx)
        ctx->sampler_view_destroy = noop_sampler_view_destroy;
        ctx->surface_destroy = noop_surface_destroy;
        ctx->draw_vbo = noop_draw_vbo;
+       ctx->redefine_user_buffer = u_default_redefine_user_buffer;
 }
index 27eb3817bf107b0f34fbbd581f977612f8801ac1..679e5ea14856ffdaae8299e220c80657f6555de3 100644 (file)
@@ -299,7 +299,7 @@ check_swap_src_0_1(struct nv_instruction *nvi)
    }
 
    if (nvi->opcode == NV_OP_SET && nvi->src[0] != src0)
-      nvi->set_cond = cc_swapped[nvi->set_cond];
+      nvi->set_cond = (nvi->set_cond & ~7) | cc_swapped[nvi->set_cond & 7];
 }
 
 static int
index 53f94820ce09479c66e15d466df122d1e065daff..f3418df83817b22a2d41762e99c6600e43d9ea60 100644 (file)
@@ -45,7 +45,7 @@ nv50_query_create(struct pipe_context *pipe, unsigned type)
        struct nv50_query *q = CALLOC_STRUCT(nv50_query);
        int ret;
 
-       assert (q->type == PIPE_QUERY_OCCLUSION_COUNTER);
+       assert (type == PIPE_QUERY_OCCLUSION_COUNTER);
        q->type = type;
 
        ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 256,
index b4eda0f617d55b276beaeb8e92a44bb2f73d6004..ba2c3e8c2815e38bc0204eaa6b9aa53e09f001b9 100644 (file)
@@ -23,6 +23,7 @@
 #include "pipe/p_state.h"
 #include "pipe/p_defines.h"
 #include "util/u_inlines.h"
+#include "util/u_transfer.h"
 
 #include "tgsi/tgsi_parse.h"
 
@@ -886,5 +887,6 @@ nv50_init_state_functions(struct nv50_context *nv50)
 
        nv50->pipe.set_vertex_buffers = nv50_set_vertex_buffers;
        nv50->pipe.set_index_buffer = nv50_set_index_buffer;
+       nv50->pipe.redefine_user_buffer = u_default_redefine_user_buffer;
 }
 
index d6b80c3ea791eaed7ed334bc9f3ab476e56e5022..ce9300ad8fd1328304a106be0b78f03331534756 100644 (file)
@@ -1130,7 +1130,7 @@ emit_fetch(struct bld_context *bld, const struct tgsi_full_instruction *insn,
    case TGSI_FILE_INPUT:
       res = bld_saved_input(bld, idx, swz);
       if (res && (insn->Instruction.Opcode != TGSI_OPCODE_TXP))
-         return res;
+         break;
 
       res = new_value(bld->pc, bld->ti->input_file, type);
       res->reg.id = bld->ti->input_map[idx][swz];
index 61932ff2b6a2ccfce1ba159d077a84e278306423..73a605f94e182cf704eaef9e3d810069ed578273 100644 (file)
@@ -84,6 +84,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define NVC0_3D_EARLY_FRAGMENT_TESTS                           0x00000210
 
+#define NVC0_3D_MEM_BARRIER                                    0x0000021c
+#define NVC0_3D_MEM_BARRIER_UNK0                               0x00000001
+#define NVC0_3D_MEM_BARRIER_UNK1                               0x00000002
+#define NVC0_3D_MEM_BARRIER_UNK2                               0x00000004
+#define NVC0_3D_MEM_BARRIER_UNK4                               0x00000010
+#define NVC0_3D_MEM_BARRIER_UNK8                               0x00000100
+#define NVC0_3D_MEM_BARRIER_UNK12                              0x00001000
+
 #define NVC0_3D_TESS_MODE                                      0x00000320
 #define NVC0_3D_TESS_MODE_PRIM__MASK                           0x0000000f
 #define NVC0_3D_TESS_MODE_PRIM__SHIFT                          0
@@ -122,11 +130,17 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define NVC0_3D_TFB_PRIMITIVE_ID(i0)                          (0x00000390 + 0x20*(i0))
 
-#define NVC0_3D_TFB_UNK0700(i0)                                       (0x00000700 + 0x10*(i0))
+#define NVC0_3D_TFB_UNK07X0(i0)                                       (0x00000700 + 0x10*(i0))
+#define NVC0_3D_TFB_UNK07X0__ESIZE                             0x00000010
+#define NVC0_3D_TFB_UNK07X0__LEN                               0x00000004
 
 #define NVC0_3D_TFB_VARYING_COUNT(i0)                         (0x00000704 + 0x10*(i0))
+#define NVC0_3D_TFB_VARYING_COUNT__ESIZE                       0x00000010
+#define NVC0_3D_TFB_VARYING_COUNT__LEN                         0x00000004
 
 #define NVC0_3D_TFB_BUFFER_STRIDE(i0)                         (0x00000708 + 0x10*(i0))
+#define NVC0_3D_TFB_BUFFER_STRIDE__ESIZE                       0x00000010
+#define NVC0_3D_TFB_BUFFER_STRIDE__LEN                         0x00000004
 
 #define NVC0_3D_TFB_ENABLE                                     0x00000744
 
@@ -144,29 +158,29 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define NVC0_3D_RT__ESIZE                                      0x00000020
 #define NVC0_3D_RT__LEN                                                0x00000008
 
-#define NVC0_3D_RT_ADDRESS_HIGH(i0)                           (0x00000800 + 0x20*(i0))
+#define NVC0_3D_RT_ADDRESS_HIGH(i0)                           (0x00000800 + 0x40*(i0))
 
-#define NVC0_3D_RT_ADDRESS_LOW(i0)                            (0x00000804 + 0x20*(i0))
+#define NVC0_3D_RT_ADDRESS_LOW(i0)                            (0x00000804 + 0x40*(i0))
 
-#define NVC0_3D_RT_HORIZ(i0)                                  (0x00000808 + 0x20*(i0))
+#define NVC0_3D_RT_HORIZ(i0)                                  (0x00000808 + 0x40*(i0))
 
-#define NVC0_3D_RT_VERT(i0)                                   (0x0000080c + 0x20*(i0))
+#define NVC0_3D_RT_VERT(i0)                                   (0x0000080c + 0x40*(i0))
 
-#define NVC0_3D_RT_FORMAT(i0)                                 (0x00000810 + 0x20*(i0))
+#define NVC0_3D_RT_FORMAT(i0)                                 (0x00000810 + 0x40*(i0))
 
-#define NVC0_3D_RT_TILE_MODE(i0)                              (0x00000814 + 0x20*(i0))
+#define NVC0_3D_RT_TILE_MODE(i0)                              (0x00000814 + 0x40*(i0))
 #define NVC0_3D_RT_TILE_MODE_UNK0                              0x00000001
 #define NVC0_3D_RT_TILE_MODE_Y__MASK                           0x00000070
 #define NVC0_3D_RT_TILE_MODE_Y__SHIFT                          4
 #define NVC0_3D_RT_TILE_MODE_Z__MASK                           0x00000700
 #define NVC0_3D_RT_TILE_MODE_Z__SHIFT                          8
 
-#define NVC0_3D_RT_ARRAY_MODE(i0)                             (0x00000818 + 0x20*(i0))
+#define NVC0_3D_RT_ARRAY_MODE(i0)                             (0x00000818 + 0x40*(i0))
 #define NVC0_3D_RT_ARRAY_MODE_LAYERS__MASK                     0x0000ffff
 #define NVC0_3D_RT_ARRAY_MODE_LAYERS__SHIFT                    0
 #define NVC0_3D_RT_ARRAY_MODE_VOLUME                           0x00010000
 
-#define NVC0_3D_RT_LAYER_STRIDE(i0)                           (0x0000081c + 0x20*(i0))
+#define NVC0_3D_RT_LAYER_STRIDE(i0)                           (0x0000081c + 0x40*(i0))
 
 #define NVC0_3D_VIEWPORT_SCALE_X(i0)                          (0x00000a00 + 0x20*(i0))
 #define NVC0_3D_VIEWPORT_SCALE_X__ESIZE                                0x00000020
@@ -216,21 +230,21 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define NVC0_3D_DEPTH_RANGE_FAR__ESIZE                         0x00000010
 #define NVC0_3D_DEPTH_RANGE_FAR__LEN                           0x00000010
 
-#define NVC0_3D_VIEWPORT_CLIP_HORIZ(i0)                               (0x00000d00 + 0x8*(i0))
-#define NVC0_3D_VIEWPORT_CLIP_HORIZ__ESIZE                     0x00000008
-#define NVC0_3D_VIEWPORT_CLIP_HORIZ__LEN                       0x00000008
-#define NVC0_3D_VIEWPORT_CLIP_HORIZ_MIN__MASK                  0x0000ffff
-#define NVC0_3D_VIEWPORT_CLIP_HORIZ_MIN__SHIFT                 0
-#define NVC0_3D_VIEWPORT_CLIP_HORIZ_MAX__MASK                  0xffff0000
-#define NVC0_3D_VIEWPORT_CLIP_HORIZ_MAX__SHIFT                 16
-
-#define NVC0_3D_VIEWPORT_CLIP_VERT(i0)                        (0x00000d04 + 0x8*(i0))
-#define NVC0_3D_VIEWPORT_CLIP_VERT__ESIZE                      0x00000008
-#define NVC0_3D_VIEWPORT_CLIP_VERT__LEN                                0x00000008
-#define NVC0_3D_VIEWPORT_CLIP_VERT_MIN__MASK                   0x0000ffff
-#define NVC0_3D_VIEWPORT_CLIP_VERT_MIN__SHIFT                  0
-#define NVC0_3D_VIEWPORT_CLIP_VERT_MAX__MASK                   0xffff0000
-#define NVC0_3D_VIEWPORT_CLIP_VERT_MAX__SHIFT                  16
+#define NVC0_3D_CLIP_RECT_HORIZ(i0)                           (0x00000d00 + 0x8*(i0))
+#define NVC0_3D_CLIP_RECT_HORIZ__ESIZE                         0x00000008
+#define NVC0_3D_CLIP_RECT_HORIZ__LEN                           0x00000008
+#define NVC0_3D_CLIP_RECT_HORIZ_MIN__MASK                      0x0000ffff
+#define NVC0_3D_CLIP_RECT_HORIZ_MIN__SHIFT                     0
+#define NVC0_3D_CLIP_RECT_HORIZ_MAX__MASK                      0xffff0000
+#define NVC0_3D_CLIP_RECT_HORIZ_MAX__SHIFT                     16
+
+#define NVC0_3D_CLIP_RECT_VERT(i0)                            (0x00000d04 + 0x8*(i0))
+#define NVC0_3D_CLIP_RECT_VERT__ESIZE                          0x00000008
+#define NVC0_3D_CLIP_RECT_VERT__LEN                            0x00000008
+#define NVC0_3D_CLIP_RECT_VERT_MIN__MASK                       0x0000ffff
+#define NVC0_3D_CLIP_RECT_VERT_MIN__SHIFT                      0
+#define NVC0_3D_CLIP_RECT_VERT_MAX__MASK                       0xffff0000
+#define NVC0_3D_CLIP_RECT_VERT_MAX__SHIFT                      16
 
 #define NVC0_3D_CLIPID_REGION_HORIZ(i0)                               (0x00000d40 + 0x8*(i0))
 #define NVC0_3D_CLIPID_REGION_HORIZ__ESIZE                     0x00000008
@@ -356,6 +370,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define NVC0_3D_SCREEN_SCISSOR_VERT_Y__MASK                    0x0000ffff
 #define NVC0_3D_SCREEN_SCISSOR_VERT_Y__SHIFT                   0
 
+#define NVC0_3D_CLEAR_FLAGS                                    0x000010f8
+#define NVC0_3D_CLEAR_FLAGS_STENCIL_MASK                       0x00000001
+#define NVC0_3D_CLEAR_FLAGS_UNK4                               0x00000010
+#define NVC0_3D_CLEAR_FLAGS_SCISSOR                            0x00000100
+#define NVC0_3D_CLEAR_FLAGS_VIEWPORT                           0x00001000
+
 #define NVC0_3D_VERTEX_ID                                      0x00001118
 
 #define NVC0_3D_VTX_ATTR_DEFINE                                        0x0000114c
@@ -561,7 +581,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define NVC0_3D_BLEND_ENABLE__ESIZE                            0x00000004
 #define NVC0_3D_BLEND_ENABLE__LEN                              0x00000008
 
-#define NVC0_3D_STENCIL_FRONT_ENABLE                           0x00001380
+#define NVC0_3D_STENCIL_ENABLE                                 0x00001380
 
 #define NVC0_3D_STENCIL_FRONT_OP_FAIL                          0x00001384
 #define NVC0_3D_STENCIL_FRONT_OP_FAIL_ZERO                     0x00000000
@@ -605,9 +625,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define NVC0_3D_STENCIL_FRONT_FUNC_REF                         0x00001394
 
-#define NVC0_3D_STENCIL_FRONT_MASK                             0x00001398
+#define NVC0_3D_STENCIL_FRONT_FUNC_MASK                                0x00001398
 
-#define NVC0_3D_STENCIL_FRONT_FUNC_MASK                                0x0000139c
+#define NVC0_3D_STENCIL_FRONT_MASK                             0x0000139c
 
 #define NVC0_3D_DRAW_TFB_BASE                                  0x000013a4
 
@@ -642,6 +662,18 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define NVC0_3D_CLIPID_HEIGHT                                  0x00001504
 #define NVC0_3D_CLIPID_HEIGHT__MAX                             0x00002000
 
+#define NVC0_3D_CLIPID_FILL_RECT_HORIZ                         0x00001508
+#define NVC0_3D_CLIPID_FILL_RECT_HORIZ_LOW__MASK               0x0000ffff
+#define NVC0_3D_CLIPID_FILL_RECT_HORIZ_LOW__SHIFT              0
+#define NVC0_3D_CLIPID_FILL_RECT_HORIZ_HIGH__MASK              0xffff0000
+#define NVC0_3D_CLIPID_FILL_RECT_HORIZ_HIGH__SHIFT             16
+
+#define NVC0_3D_CLIPID_FILL_RECT_VERT                          0x0000150c
+#define NVC0_3D_CLIPID_FILL_RECT_VERT_LOW__MASK                        0x0000ffff
+#define NVC0_3D_CLIPID_FILL_RECT_VERT_LOW__SHIFT               0
+#define NVC0_3D_CLIPID_FILL_RECT_VERT_HIGH__MASK               0xffff0000
+#define NVC0_3D_CLIPID_FILL_RECT_VERT_HIGH__SHIFT              16
+
 #define NVC0_3D_VP_CLIP_DISTANCE_ENABLE                                0x00001510
 #define NVC0_3D_VP_CLIP_DISTANCE_ENABLE_0                      0x00000001
 #define NVC0_3D_VP_CLIP_DISTANCE_ENABLE_1                      0x00000002
@@ -814,8 +846,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define NVC0_3D_VERTEX_BASE_LOW                                        0x000015f8
 
 #define NVC0_3D_POINT_COORD_REPLACE                            0x00001604
-#define NVC0_3D_POINT_COORD_REPLACE_BITS__MASK                 0x00001fff
-#define NVC0_3D_POINT_COORD_REPLACE_BITS__SHIFT                        0
+#define NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN__MASK         0x00000004
+#define NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN__SHIFT                2
+#define NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_LOWER_LEFT    0x00000000
+#define NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_UPPER_LEFT    0x00000004
+#define NVC0_3D_POINT_COORD_REPLACE_ENABLE__MASK               0x000007f8
+#define NVC0_3D_POINT_COORD_REPLACE_ENABLE__SHIFT              3
 
 #define NVC0_3D_CODE_ADDRESS_HIGH                              0x00001608
 
@@ -864,8 +900,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define NVC0_3D_POINT_RASTER_RULES_OGL                         0x00000000
 #define NVC0_3D_POINT_RASTER_RULES_D3D                         0x00000001
 
-#define NVC0_3D_POINT_SPRITE_CTRL                              0x00001660
-
 #define NVC0_3D_TEX_MISC                                       0x00001664
 #define NVC0_3D_TEX_MISC_SEAMLESS_CUBE_MAP                     0x00000004
 
@@ -928,22 +962,28 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define NVC0_3D_VIEW_VOLUME_CLIP_CTRL                          0x0000193c
 #define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK0                     0x00000001
-#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1                     0x00000002
-#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK2                     0x00000004
-#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK3                     0x00000008
-#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK4                     0x00000010
+#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1__MASK               0x00000006
+#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1__SHIFT              1
+#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK0                        0x00000000
+#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1                        0x00000002
+#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK2                        0x00000004
+#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR         0x00000008
+#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR          0x00000010
 #define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK7                     0x00000080
 #define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK10                    0x00000400
 #define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK11                    0x00000800
-#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12                    0x00001000
-#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK13                    0x00002000
+#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12__MASK              0x00003000
+#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12__SHIFT             12
+#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK0               0x00000000
+#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK1               0x00001000
+#define NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK2               0x00002000
 
-#define NVC0_3D_VIEWPORT_CLIP_RECTS_EN                         0x0000194c
+#define NVC0_3D_CLIP_RECTS_EN                                  0x0000194c
 
-#define NVC0_3D_VIEWPORT_CLIP_MODE                             0x00001950
-#define NVC0_3D_VIEWPORT_CLIP_MODE_INSIDE_ANY                  0x00000000
-#define NVC0_3D_VIEWPORT_CLIP_MODE_OUTSIDE_ALL                 0x00000001
-#define NVC0_3D_VIEWPORT_CLIP_MODE_NEVER                       0x00000002
+#define NVC0_3D_CLIP_RECTS_MODE                                        0x00001950
+#define NVC0_3D_CLIP_RECTS_MODE_INSIDE_ANY                     0x00000000
+#define NVC0_3D_CLIP_RECTS_MODE_OUTSIDE_ALL                    0x00000001
+#define NVC0_3D_CLIP_RECTS_MODE_NEVER                          0x00000002
 
 #define NVC0_3D_FP_ZORDER_CTRL                                 0x0000196c
 #define NVC0_3D_FP_ZORDER_CTRL_0                               0x00000001
@@ -996,6 +1036,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define NVC0_3D_CLEAR_BUFFERS_LAYER__MASK                      0x001ffc00
 #define NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT                     10
 
+#define NVC0_3D_CLIPID_FILL                                    0x000019d4
+
 #define NVC0_3D_COLOR_MASK(i0)                                (0x00001a00 + 0x4*(i0))
 #define NVC0_3D_COLOR_MASK__ESIZE                              0x00000004
 #define NVC0_3D_COLOR_MASK__LEN                                        0x00000008
@@ -1155,9 +1197,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define NVC0_3D_VERT_COLOR_CLAMP_EN                            0x00002600
 
-#define NVC0_3D_TFB_VARYING_LOCS(i0)                          (0x00002800 + 0x4*(i0))
+#define NVC0_3D_TFB_VARYING_LOCS(i0, i1)                      (0x00002800 + 0x80*(i0) + 0x4*(i1))
 #define NVC0_3D_TFB_VARYING_LOCS__ESIZE                                0x00000004
-#define NVC0_3D_TFB_VARYING_LOCS__LEN                          0x00000080
+#define NVC0_3D_TFB_VARYING_LOCS__LEN                          0x00000020
 
 #define NVC0_3D_COLOR_MASK_BROADCAST                           0x00003808
 
index ea3e642a4483cfedf3572de0ae478c008ed33650..aa949bdfa36018d15f983028e8216638b87ca07e 100644 (file)
@@ -59,15 +59,23 @@ release_allocation(struct nvc0_mm_allocation **mm, struct nvc0_fence *fence)
    (*mm) = NULL;
 }
 
-static INLINE boolean
-nvc0_buffer_reallocate(struct nvc0_screen *screen, struct nvc0_resource *buf,
-                       unsigned domain)
+INLINE void
+nvc0_buffer_release_gpu_storage(struct nvc0_resource *buf)
 {
    nouveau_bo_ref(NULL, &buf->bo);
 
    if (buf->mm)
       release_allocation(&buf->mm, buf->fence);
 
+   buf->domain = 0;
+}
+
+static INLINE boolean
+nvc0_buffer_reallocate(struct nvc0_screen *screen, struct nvc0_resource *buf,
+                       unsigned domain)
+{
+   nvc0_buffer_release_gpu_storage(buf);
+
    return nvc0_buffer_allocate(screen, buf, domain);
 }
 
@@ -77,10 +85,7 @@ nvc0_buffer_destroy(struct pipe_screen *pscreen,
 {
    struct nvc0_resource *res = nvc0_resource(presource);
 
-   nouveau_bo_ref(NULL, &res->bo);
-
-   if (res->mm)
-      release_allocation(&res->mm, res->fence);
+   nvc0_buffer_release_gpu_storage(res);
 
    if (res->data && !(res->status & NVC0_BUFFER_STATUS_USER_MEMORY))
       FREE(res->data);
@@ -112,7 +117,7 @@ nvc0_buffer_download(struct nvc0_context *nvc0, struct nvc0_resource *buf,
    memcpy(buf->data + start, bounce->map, size);
    nouveau_bo_unmap(bounce);
 
-   buf->status &= ~NVC0_BUFFER_STATUS_DIRTY;
+   buf->status &= ~NVC0_BUFFER_STATUS_GPU_WRITING;
 
    nouveau_bo_ref(NULL, &bounce);
    if (mm)
@@ -151,7 +156,7 @@ nvc0_buffer_upload(struct nvc0_context *nvc0, struct nvc0_resource *buf,
       release_allocation(&mm, nvc0->screen->fence.current);
 
    if (start == 0 && size == buf->base.width0)
-      buf->status &= ~NVC0_BUFFER_STATUS_DIRTY;
+      buf->status &= ~NVC0_BUFFER_STATUS_GPU_WRITING;
    return TRUE;
 }
 
@@ -174,7 +179,7 @@ nvc0_buffer_transfer_get(struct pipe_context *pipe,
 
    if (buf->domain == NOUVEAU_BO_VRAM) {
       if (usage & PIPE_TRANSFER_READ) {
-         if (buf->status & NVC0_BUFFER_STATUS_DIRTY)
+         if (buf->status & NVC0_BUFFER_STATUS_GPU_WRITING)
             nvc0_buffer_download(nvc0_context(pipe), buf, 0, buf->base.width0);
       }
    }
index 2118abb5d5d60acd6682165320afb6e034cf67d3..f02de4d044a8e0b267ef7798d80177c78d32ac4e 100644 (file)
@@ -41,17 +41,18 @@ nvc0_flush(struct pipe_context *pipe, unsigned flags,
       OUT_RING  (chan, 0);
       BEGIN_RING(chan, RING_3D(TEX_CACHE_CTL), 1);
       OUT_RING  (chan, 0x00);
+   } else
+   if ((flags & PIPE_FLUSH_RENDER_CACHE) && !(flags & PIPE_FLUSH_FRAME)) {
+      BEGIN_RING(chan, RING_3D(SERIALIZE), 1);
+      OUT_RING  (chan, 0);
    }
 
-   if (fence) {
-      nvc0_screen_fence_new(nvc0->screen, (struct nvc0_fence **)fence, TRUE);
-   }
+   if (fence)
+      nvc0_fence_reference((struct nvc0_fence **)fence,
+                           nvc0->screen->fence.current);
 
-   if (flags & (PIPE_FLUSH_SWAPBUFFERS | PIPE_FLUSH_FRAME)) {
+   if (flags & (PIPE_FLUSH_SWAPBUFFERS | PIPE_FLUSH_FRAME))
       FIRE_RING(chan);
-
-      nvc0_screen_fence_next(nvc0->screen);
-   }
 }
 
 static void
@@ -67,6 +68,16 @@ nvc0_destroy(struct pipe_context *pipe)
    FREE(nvc0);
 }
 
+void
+nvc0_default_flush_notify(struct nouveau_channel *chan)
+{
+   struct nvc0_context *nvc0 = chan->user_private;
+
+   nvc0_screen_fence_update(nvc0->screen, TRUE);
+
+   nvc0_screen_fence_next(nvc0->screen);
+}
+
 struct pipe_context *
 nvc0_create(struct pipe_screen *pscreen, void *priv)
 {
@@ -91,6 +102,7 @@ nvc0_create(struct pipe_screen *pscreen, void *priv)
    nvc0->pipe.flush = nvc0_flush;
 
    screen->base.channel->user_private = nvc0;
+   screen->base.channel->flush_notify = nvc0_default_flush_notify;
 
    nvc0_init_query_functions(nvc0);
    nvc0_init_surface_functions(nvc0);
@@ -148,12 +160,14 @@ nvc0_bufctx_emit_relocs(struct nvc0_context *nvc0)
 {
    struct resident *rsd;
    struct util_dynarray *array;
-   unsigned ctx, i;
+   unsigned ctx, i, n;
 
    for (ctx = 0; ctx < NVC0_BUFCTX_COUNT; ++ctx) {
       array = &nvc0->residents[ctx];
 
-      for (i = 0; i < array->size / sizeof(struct resident); ++i) {
+      n = array->size / sizeof(struct resident);
+      MARK_RING(nvc0->screen->base.channel, n, n);
+      for (i = 0; i < n; ++i) {
          rsd = util_dynarray_element(array, struct resident, i);
 
          nvc0_resource_validate(rsd->res, rsd->flags);
index 94117988e5081dfc09e386e06eaf17d19ef03f9e..1ce5554f7b784742251c6bba0b72445c7c3ef25f 100644 (file)
@@ -54,6 +54,8 @@
 #define NVC0_NEW_CONSTBUF     (1 << 18)
 #define NVC0_NEW_TEXTURES     (1 << 19)
 #define NVC0_NEW_SAMPLERS     (1 << 20)
+#define NVC0_NEW_TFB          (1 << 21)
+#define NVC0_NEW_TFB_BUFFERS  (1 << 22)
 
 #define NVC0_BUFCTX_CONSTANT 0
 #define NVC0_BUFCTX_FRAME    1
@@ -79,6 +81,7 @@ struct nvc0_context {
       uint8_t num_vtxelts;
       uint8_t num_textures[5];
       uint8_t num_samplers[5];
+      uint8_t tls_required; /* bitmask of shader types using l[] */
       uint16_t scissor;
       uint32_t uniform_buffer_bound[5];
    } state;
@@ -123,6 +126,11 @@ struct nvc0_context {
    boolean vbo_dirty;
    boolean vbo_push_hint;
 
+   struct nvc0_transform_feedback_state *tfb;
+   struct pipe_resource *tfbbuf[4];
+   unsigned num_tfbbufs;
+   unsigned tfb_offset[4];
+
    struct draw_context *draw;
 };
 
@@ -149,6 +157,8 @@ nvc0_surface(struct pipe_surface *ps)
 /* nvc0_context.c */
 struct pipe_context *nvc0_create(struct pipe_screen *, void *);
 
+void nvc0_default_flush_notify(struct nouveau_channel *);
+
 void nvc0_bufctx_emit_relocs(struct nvc0_context *);
 void nvc0_bufctx_add_resident(struct nvc0_context *, int ctx,
                               struct nvc0_resource *, uint32_t flags);
@@ -177,6 +187,8 @@ void nvc0_tevlprog_validate(struct nvc0_context *);
 void nvc0_gmtyprog_validate(struct nvc0_context *);
 void nvc0_fragprog_validate(struct nvc0_context *);
 
+void nvc0_tfb_validate(struct nvc0_context *);
+
 /* nvc0_state.c */
 extern void nvc0_init_state_functions(struct nvc0_context *);
 
index 9d2c48cf14d4a11433eb32d771c136bef712a910..f2d4b1451bf1f54b57d0eb08f3ba32ae95f8a2da 100644 (file)
@@ -55,6 +55,7 @@ nvc0_fence_emit(struct nvc0_fence *fence)
 
    assert(fence->state == NVC0_FENCE_STATE_AVAILABLE);
 
+   MARK_RING (chan, 5, 2);
    BEGIN_RING(chan, RING_3D(QUERY_ADDRESS_HIGH), 4);
    OUT_RELOCh(chan, screen->fence.bo, 0, NOUVEAU_BO_WR);
    OUT_RELOCl(chan, screen->fence.bo, 0, NOUVEAU_BO_WR);
@@ -83,7 +84,8 @@ nvc0_fence_del(struct nvc0_fence *fence)
    struct nvc0_fence *it;
    struct nvc0_screen *screen = fence->screen;
 
-   if (fence->state == NVC0_FENCE_STATE_EMITTED) {
+   if (fence->state == NVC0_FENCE_STATE_EMITTED ||
+       fence->state == NVC0_FENCE_STATE_FLUSHED) {
       if (fence == screen->fence.head) {
          screen->fence.head = fence->next;
          if (!screen->fence.head)
@@ -118,8 +120,8 @@ nvc0_fence_trigger_release_buffers(struct nvc0_fence *fence)
    fence->buffers = NULL;
 }
 
-static void
-nvc0_screen_fence_update(struct nvc0_screen *screen)
+void
+nvc0_screen_fence_update(struct nvc0_screen *screen, boolean flushed)
 {
    struct nvc0_fence *fence;
    struct nvc0_fence *next = NULL;
@@ -146,38 +148,43 @@ nvc0_screen_fence_update(struct nvc0_screen *screen)
    screen->fence.head = next;
    if (!next)
       screen->fence.tail = NULL;
-}
 
-#define NVC0_FENCE_MAX_SPINS (1 << 17)
+   if (flushed) {
+      for (fence = next; fence; fence = fence->next)
+         fence->state = NVC0_FENCE_STATE_FLUSHED;
+   }
+}
 
 boolean
 nvc0_fence_signalled(struct nvc0_fence *fence)
 {
    struct nvc0_screen *screen = fence->screen;
 
-   if (fence->state == NVC0_FENCE_STATE_EMITTED)
-      nvc0_screen_fence_update(screen);
+   if (fence->state >= NVC0_FENCE_STATE_EMITTED)
+      nvc0_screen_fence_update(screen, FALSE);
 
    return fence->state == NVC0_FENCE_STATE_SIGNALLED;
 }
 
+#define NVC0_FENCE_MAX_SPINS (1 << 31)
+
 boolean
 nvc0_fence_wait(struct nvc0_fence *fence)
 {
    struct nvc0_screen *screen = fence->screen;
-   int spins = 0;
+   uint32_t spins = 0;
 
-   if (fence->state == NVC0_FENCE_STATE_AVAILABLE) {
+   if (fence->state < NVC0_FENCE_STATE_EMITTED) {
       nvc0_fence_emit(fence);
 
-      FIRE_RING(screen->base.channel);
-
       if (fence == screen->fence.current)
          nvc0_screen_fence_new(screen, &screen->fence.current, FALSE);
    }
+   if (fence->state < NVC0_FENCE_STATE_FLUSHED)
+      FIRE_RING(screen->base.channel);
 
    do {
-      nvc0_screen_fence_update(screen);
+      nvc0_screen_fence_update(screen, FALSE);
 
       if (fence->state == NVC0_FENCE_STATE_SIGNALLED)
          return TRUE;
@@ -188,8 +195,9 @@ nvc0_fence_wait(struct nvc0_fence *fence)
 #endif
    } while (spins < NVC0_FENCE_MAX_SPINS);
 
-   if (spins > 9000)
-      NOUVEAU_ERR("fence %x: been spinning too long\n", fence->sequence);
+   debug_printf("Wait on fence %u (ack = %u, next = %u) timed out !\n",
+                fence->sequence,
+                screen->fence.sequence_ack, screen->fence.sequence);
 
    return FALSE;
 }
@@ -199,5 +207,4 @@ nvc0_screen_fence_next(struct nvc0_screen *screen)
 {
    nvc0_fence_emit(screen->fence.current);
    nvc0_screen_fence_new(screen, &screen->fence.current, FALSE);
-   nvc0_screen_fence_update(screen);
 }
index e63c164bda42638c1b64f94cd3757c91d1305139..3d8c3f8ba604083fd812b0f51cda3cf570859c9f 100644 (file)
@@ -7,7 +7,8 @@
 
 #define NVC0_FENCE_STATE_AVAILABLE 0
 #define NVC0_FENCE_STATE_EMITTED   1
-#define NVC0_FENCE_STATE_SIGNALLED 2
+#define NVC0_FENCE_STATE_FLUSHED   2
+#define NVC0_FENCE_STATE_SIGNALLED 3
 
 struct nvc0_mm_allocation;
 
index 7c7e134146ea5e26a963e6f4205425fa2951d5a6..ea3ed9e02251884188d2a6d21466a7c04a862d20 100644 (file)
@@ -143,8 +143,7 @@ nvc0_miptree_create(struct pipe_screen *pscreen,
    switch (pt->format) {
    case PIPE_FORMAT_Z16_UNORM:
       tile_flags = 0x0700; /* COMPRESSED */
-      tile_flags = 0x0200; /* NORMAL ? */
-      tile_flags = 0x0100; /* NORMAL ? */
+      tile_flags = 0x0100; /* NORMAL */
       break;
    case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
       tile_flags = 0x5300; /* MSAA 4, COMPRESSED */
@@ -170,6 +169,7 @@ nvc0_miptree_create(struct pipe_screen *pscreen,
       break;
    case PIPE_FORMAT_R16G16B16A16_UNORM:
       tile_flags = 0xe900; /* COMPRESSED */
+      tile_flags = 0xfe00; /* NORMAL */
       break;
    default:
       tile_flags = 0xe000; /* MSAA 4, COMPRESSED 32 BIT */
@@ -283,7 +283,7 @@ nvc0_miptree_surface_new(struct pipe_context *pipe,
    pipe_reference_init(&ps->reference, 1);
    pipe_resource_reference(&ps->texture, pt);
    ps->context = pipe;
-   ps->format = pt->format;
+   ps->format = templ->format;
    ps->usage = templ->usage;
    ps->u.tex.level = templ->u.tex.level;
    ps->u.tex.first_layer = templ->u.tex.first_layer;
index 0629dad19c9726bd493ce6cc0e2386aede4ee09c..516d2e31b55db819e4222bc8befe1b62c20767c6 100644 (file)
@@ -96,13 +96,13 @@ mm_bucket_by_size(struct nvc0_mman *cache, unsigned size)
 static INLINE uint32_t
 mm_default_slab_size(unsigned chunk_order)
 {
-   assert(chunk_order <= MM_MAX_ORDER && chunk_order >= MM_MIN_ORDER);
-
    static const int8_t slab_order[MM_MAX_ORDER - MM_MIN_ORDER + 1] =
    {
       12, 12, 13, 14, 14, 17, 17, 17, 17, 19, 19, 20, 21, 22
    };
 
+   assert(chunk_order <= MM_MAX_ORDER && chunk_order >= MM_MIN_ORDER);
+
    return 1 << slab_order[chunk_order - MM_MIN_ORDER];
 }
 
index 304a1919768e22f61398ba65b5550616509bdc9e..f51d289e8cdf3662477fd906bcfe3085870c0af2 100644 (file)
@@ -44,6 +44,11 @@ nvc0_insn_can_load(struct nv_instruction *nvi, int s,
    if (ld->indirect >= 0)
       return FALSE;
 
+   /* a few ops can use g[] sources directly, but we don't support g[] yet */
+   if (ld->src[0]->value->reg.file == NV_FILE_MEM_L ||
+       ld->src[0]->value->reg.file == NV_FILE_MEM_G)
+      return FALSE;
+
    for (i = 0; i < 3 && nvi->src[i]; ++i)
       if (nvi->src[i]->value->reg.file == NV_FILE_IMM)
          return FALSE;
@@ -55,15 +60,11 @@ nvc0_insn_can_load(struct nv_instruction *nvi, int s,
 boolean
 nvc0_insn_is_predicateable(struct nv_instruction *nvi)
 {
-   int s;
-
-   if (!nv_op_predicateable(nvi->opcode))
+   if (nvi->predicate >= 0) /* already predicated */
       return FALSE;
-   if (nvi->predicate >= 0)
+   if (!nvc0_op_info_table[nvi->opcode].predicate &&
+       !nvc0_op_info_table[nvi->opcode].pseudo)
       return FALSE;
-   for (s = 0; s < 4 && nvi->src[s]; ++s)
-      if (nvi->src[s]->value->reg.file == NV_FILE_IMM)
-         return FALSE;
    return TRUE;
 }
 
@@ -103,6 +104,12 @@ nvc0_pc_replace_value(struct nv_pc *pc,
    return n;
 }
 
+static INLINE boolean
+is_gpr63(struct nv_value *val)
+{
+   return (val->reg.file == NV_FILE_GPR && val->reg.id == 63);
+}
+
 struct nv_value *
 nvc0_pc_find_constant(struct nv_ref *ref)
 {
@@ -116,7 +123,7 @@ nvc0_pc_find_constant(struct nv_ref *ref)
       assert(!src->insn->src[0]->mod);
       src = src->insn->src[0]->value;
    }
-   if ((src->reg.file == NV_FILE_IMM) ||
+   if ((src->reg.file == NV_FILE_IMM) || is_gpr63(src) ||
        (src->insn &&
         src->insn->opcode == NV_OP_LD &&
         src->insn->src[0]->value->reg.file >= NV_FILE_MEM_C(0) &&
@@ -130,7 +137,7 @@ nvc0_pc_find_immediate(struct nv_ref *ref)
 {
    struct nv_value *src = nvc0_pc_find_constant(ref);
 
-   return (src && src->reg.file == NV_FILE_IMM) ? src : NULL;
+   return (src && (src->reg.file == NV_FILE_IMM || is_gpr63(src))) ? src : NULL;
 }
 
 static void
@@ -187,7 +194,10 @@ nvc0_pc_pass_in_order(struct nv_basic_block *root, nv_pc_pass_func f,
             bb[p++] = b->out[j];
             break;
          case CFG_EDGE_LOOP_LEAVE:
-            bbb[pp++] = b->out[j];
+            if (!b->out[j]->priv) {
+               bbb[pp++] = b->out[j];
+               b->out[j]->priv = 1;
+            }
             break;
          default:
             assert(0);
@@ -499,6 +509,9 @@ nvc0_insn_append(struct nv_basic_block *b, struct nv_instruction *i)
 
    i->bb = b;
    b->num_instructions++;
+
+   if (i->prev && i->prev->terminator)
+      nvc0_insns_permute(i->prev, i);
 }
 
 void
@@ -512,6 +525,8 @@ nvc0_insn_insert_after(struct nv_instruction *at, struct nv_instruction *ni)
    ni->prev = at;
    ni->next->prev = ni;
    ni->prev->next = ni;
+   ni->bb = at->bb;
+   ni->bb->num_instructions++;
 }
 
 void
index 969cc68c596157deb7b3075148cec5ac5e2a08cd..efa073a92016c170e7859f53b225de9499cac577 100644 (file)
@@ -53,7 +53,8 @@
 
 /**
  * BIND forces source operand i into the same register as destination operand i,
- *  and the operands will be assigned consecutive registers (needed for TEX)
+ *  and the operands will be assigned consecutive registers (needed for TEX).
+ *  Beware conflicts !
  * SELECT forces its multiple source operands and its destination operand into
  *  one and the same register.
  */
 #define NV_CC_C  0x11
 #define NV_CC_A  0x12
 #define NV_CC_S  0x13
+#define NV_CC_INVERSE(cc) ((cc) ^ 0x7)
+/* for 1 bit predicates: */
+#define NV_CC_P     0
+#define NV_CC_NOT_P 1
 
 #define NV_PC_MAX_INSTRUCTIONS 2048
 #define NV_PC_MAX_VALUES (NV_PC_MAX_INSTRUCTIONS * 4)
@@ -259,12 +264,6 @@ nv_op_supported_src_mods(uint opcode)
    return nvc0_op_info_table[opcode].mods;
 }
 
-static INLINE boolean
-nv_op_predicateable(uint opcode)
-{
-   return nvc0_op_info_table[opcode].predicate ? TRUE : FALSE;
-}
-
 static INLINE uint
 nv_type_order(ubyte type)
 {
@@ -310,7 +309,7 @@ struct nv_reg {
       int32_t s32;
       int64_t s64;
       uint64_t u64;
-      uint32_t u32;
+      uint32_t u32; /* expected to be 0 for $r63 */
       float f32;
       double f64;
    } imm;
@@ -344,6 +343,8 @@ struct nv_ref {
    uint8_t flags;
 };
 
+#define NV_REF_FLAG_REGALLOC_PRIV (1 << 0)
+
 struct nv_basic_block;
 
 struct nv_instruction {
@@ -485,7 +486,7 @@ nv_alloc_instruction(struct nv_pc *pc, uint opcode)
    assert(pc->num_instructions < NV_PC_MAX_INSTRUCTIONS);
 
    insn->opcode = opcode;
-   insn->cc = 0;
+   insn->cc = NV_CC_P;
    insn->indirect = -1;
    insn->predicate = -1;
 
index db8055d91cd74aa8c4461ba97ada8f3dbb5758ec..c10f920e6f1084ad2c431dee11d5f9860e70d5ae 100644 (file)
@@ -236,7 +236,7 @@ emit_flow(struct nv_pc *pc, struct nv_instruction *i, uint8_t op)
       */
 
       pc->emit[0] |= (pcrel & 0x3f) << 26;
-      pc->emit[1] |= (pcrel >> 6) & 0x1ffff;
+      pc->emit[1] |= (pcrel >> 6) & 0x3ffff;
    }
 }
 
@@ -393,6 +393,8 @@ emit_tex(struct nv_pc *pc, struct nv_instruction *i)
 {
    int src1 = i->tex_array + i->tex_dim + i->tex_cube;
 
+   assert(src1 < 6);
+
    pc->emit[0] = 0x00000086;
    pc->emit[1] = 0x80000000;
 
@@ -446,7 +448,7 @@ emit_flop(struct nv_pc *pc, struct nv_instruction *i, ubyte op)
 
    pc->emit[0] |= op << 26;
 
-   if (op >= 4) {
+   if (op >= 3) {
       if (i->src[0]->mod & NV_MOD_NEG) pc->emit[0] |= 1 << 9;
       if (i->src[0]->mod & NV_MOD_ABS) pc->emit[0] |= 1 << 7;
    } else {
@@ -477,6 +479,7 @@ emit_ddx(struct nv_pc *pc, struct nv_instruction *i)
 {
    i->quadop = 0x99;
    i->lanes = 4;
+   i->src[1] = i->src[0];
    emit_quadop(pc, i);
 }
 
@@ -485,6 +488,7 @@ emit_ddy(struct nv_pc *pc, struct nv_instruction *i)
 {
    i->quadop = 0xa5;
    i->lanes = 5;
+   i->src[1] = i->src[0];
    emit_quadop(pc, i);
 }
 
@@ -629,25 +633,28 @@ emit_slct(struct nv_pc *pc, struct nv_instruction *i)
 static void
 emit_cvt(struct nv_pc *pc, struct nv_instruction *i)
 {
+   uint32_t rint;
+
    pc->emit[0] = 0x00000004;
    pc->emit[1] = 0x10000000;
 
-   if (i->opcode != NV_OP_CVT)
+   /* if no type conversion specified, get type from opcode */
+   if (i->opcode != NV_OP_CVT && i->ext.cvt.d == i->ext.cvt.s)
       i->ext.cvt.d = i->ext.cvt.s = NV_OPTYPE(i->opcode);
 
    switch (i->ext.cvt.d) {
    case NV_TYPE_F32:
       switch (i->ext.cvt.s) {
       case NV_TYPE_F32: pc->emit[1] = 0x10000000; break;
-      case NV_TYPE_S32: pc->emit[0] |= 0x200;
+      case NV_TYPE_S32: pc->emit[0] |= 0x200; /* fall through */
       case NV_TYPE_U32: pc->emit[1] = 0x18000000; break;
       }
       break;
-   case NV_TYPE_S32: pc->emit[0] |= 0x80;
+   case NV_TYPE_S32: pc->emit[0] |= 0x80; /* fall through */
    case NV_TYPE_U32:
       switch (i->ext.cvt.s) {
       case NV_TYPE_F32: pc->emit[1] = 0x14000000; break;
-      case NV_TYPE_S32: pc->emit[0] |= 0x200;
+      case NV_TYPE_S32: pc->emit[0] |= 0x200; /* fall through */
       case NV_TYPE_U32: pc->emit[1] = 0x1c000000; break;
       }
       break;
@@ -656,14 +663,20 @@ emit_cvt(struct nv_pc *pc, struct nv_instruction *i)
       break;
    }
 
-   if (i->opcode == NV_OP_FLOOR)
-      pc->emit[1] |= 0x00020000;
-   else
-   if (i->opcode == NV_OP_CEIL)
-      pc->emit[1] |= 0x00040000;
-   else
-   if (i->opcode == NV_OP_TRUNC)
-      pc->emit[1] |= 0x00060000;
+   rint = (i->ext.cvt.d == NV_TYPE_F32) ? 1 << 7 : 0;
+
+   if (i->opcode == NV_OP_FLOOR) {
+      pc->emit[0] |= rint;
+      pc->emit[1] |= 2 << 16;
+   } else
+   if (i->opcode == NV_OP_CEIL) {
+      pc->emit[0] |= rint;
+      pc->emit[1] |= 4 << 16;
+   } else
+   if (i->opcode == NV_OP_TRUNC) {
+      pc->emit[0] |= rint;
+      pc->emit[1] |= 6 << 16;
+   }
 
    if (i->saturate || i->opcode == NV_OP_SAT)
       pc->emit[0] |= 0x20;
@@ -793,11 +806,8 @@ emit_ldst_size(struct nv_pc *pc, struct nv_instruction *i)
 }
 
 static void
-emit_ld_const(struct nv_pc *pc, struct nv_instruction *i)
+emit_ld_common(struct nv_pc *pc, struct nv_instruction *i)
 {
-   pc->emit[0] = 0x00000006;
-   pc->emit[1] = 0x14000000 | (const_space_index(i, 0) << 10);
-
    emit_ldst_size(pc, i);
 
    set_pred(pc, i);
@@ -807,6 +817,15 @@ emit_ld_const(struct nv_pc *pc, struct nv_instruction *i)
    DID(pc, i->def[0], 14);
 }
 
+static void
+emit_ld_const(struct nv_pc *pc, struct nv_instruction *i)
+{
+   pc->emit[0] = 0x00000006;
+   pc->emit[1] = 0x14000000 | (const_space_index(i, 0) << 10);
+
+   emit_ld_common(pc, i);
+}
+
 static void
 emit_ld(struct nv_pc *pc, struct nv_instruction *i)
 {
@@ -818,6 +837,12 @@ emit_ld(struct nv_pc *pc, struct nv_instruction *i)
       } else {
          emit_ld_const(pc, i);
       }
+   } else
+   if (SFILE(i, 0) == NV_FILE_MEM_L) {
+      pc->emit[0] = 0x00000005;
+      pc->emit[1] = 0xc0000000;
+
+      emit_ld_common(pc, i);
    } else {
       NOUVEAU_ERR("emit_ld(%u): not handled yet\n", SFILE(i, 0));
       abort();
@@ -827,8 +852,19 @@ emit_ld(struct nv_pc *pc, struct nv_instruction *i)
 static void
 emit_st(struct nv_pc *pc, struct nv_instruction *i)
 {
-   NOUVEAU_ERR("emit_st: not handled yet\n");
-   abort();
+   if (SFILE(i, 0) != NV_FILE_MEM_L)
+      NOUVEAU_ERR("emit_st(%u): file not handled yet\n", SFILE(i, 0));
+
+   pc->emit[0] = 0x00000005 | (0 << 8); /* write-back caching */
+   pc->emit[1] = 0xc8000000;
+
+   emit_ldst_size(pc, i);
+
+   set_pred(pc, i);
+   set_address_16(pc, i->src[0]);
+
+   SID(pc, (i->indirect >= 0) ? i->src[i->indirect] : NULL, 20);
+   DID(pc, i->src[1]->value, 14);
 }
 
 void
index acc72bff14cb5fc675e87f3e41f164ce95767cc3..c5a7367a5fd34107166c39837bd5bd2b4e57aa20 100644 (file)
@@ -99,6 +99,7 @@ inst_removable(struct nv_instruction *nvi)
              nvc0_insn_refcount(nvi)));
 }
 
+/* Check if we do not actually have to emit this instruction. */
 static INLINE boolean
 inst_is_noop(struct nv_instruction *nvi)
 {
@@ -141,9 +142,10 @@ nv_pc_pass_pre_emission(void *priv, struct nv_basic_block *b)
    struct nv_instruction *nvi, *next;
    int j;
 
+   /* find first non-empty block emitted before b */
    for (j = pc->num_blocks - 1; j >= 0 && !pc->bb_list[j]->emit_size; --j);
 
-   if (j >= 0) {
+   for (; j >= 0; --j) {
       in = pc->bb_list[j];
 
       /* check for no-op branches (BRA $PC+8) */
@@ -157,6 +159,9 @@ nv_pc_pass_pre_emission(void *priv, struct nv_basic_block *b)
          nvc0_insn_delete(in->exit);
       }
       b->emit_pos = in->emit_pos + in->emit_size;
+
+      if (in->emit_size) /* no more no-op branches to b */
+         break;
    }
 
    pc->bb_list[pc->num_blocks++] = b;
@@ -240,10 +245,15 @@ check_swap_src_0_1(struct nv_instruction *nvi)
    struct nv_ref *src0 = nvi->src[0];
    struct nv_ref *src1 = nvi->src[1];
 
-   if (!nv_op_commutative(nvi->opcode))
+   if (!nv_op_commutative(nvi->opcode) &&
+       NV_BASEOP(nvi->opcode) != NV_OP_SET &&
+       NV_BASEOP(nvi->opcode) != NV_OP_SLCT)
       return;
    assert(src0 && src1 && src0->value && src1->value);
 
+   if (src1->value->reg.file != NV_FILE_GPR)
+      return;
+
    if (is_cspace_load(src0->value->insn)) {
       if (!is_cspace_load(src1->value->insn)) {
          nvi->src[0] = src1;
@@ -258,8 +268,13 @@ check_swap_src_0_1(struct nv_instruction *nvi)
       }
    }
 
-   if (nvi->src[0] != src0 && nvi->opcode == NV_OP_SET)
-      nvi->set_cond = cc_swapped[nvi->set_cond];
+   if (nvi->src[0] != src0) {
+      if (NV_BASEOP(nvi->opcode) == NV_OP_SET)
+         nvi->set_cond = (nvi->set_cond & ~7) | cc_swapped[nvi->set_cond & 7];
+      else
+      if (NV_BASEOP(nvi->opcode) == NV_OP_SLCT)
+         nvi->set_cond = NV_CC_INVERSE(nvi->set_cond);
+   }
 }
 
 static void
@@ -543,6 +558,7 @@ constant_operand(struct nv_pc *pc,
          nv_reference(pc, nvi, s, nvi->src[t]->value);
          nvi->src[s]->mod = nvi->src[t]->mod;
       }
+      break;
    case NV_OP_ADD_F32:
       if (u.u32 == 0) {
          switch (nvi->src[t]->mod) {
@@ -562,6 +578,7 @@ constant_operand(struct nv_pc *pc,
          if (nvi->opcode != NV_OP_CVT)
             nvi->src[0]->mod = 0;
       }
+      break;
    case NV_OP_ADD_B32:
       if (u.u32 == 0) {
          assert(nvi->src[t]->mod == 0);
@@ -582,7 +599,7 @@ constant_operand(struct nv_pc *pc,
       } else
       if (u.s32 > 0 && u.s32 == (1 << shift)) {
          nvi->opcode = NV_OP_SHL;
-         (val = new_value(pc, NV_FILE_IMM, NV_TYPE_U32))->reg.imm.s32 = shift;
+         (val = new_value(pc, NV_FILE_IMM, 4))->reg.imm.s32 = shift;
          nv_reference(pc, nvi, 0, nvi->src[t]->value);
          nv_reference(pc, nvi, 1, val);
          break;
@@ -590,14 +607,14 @@ constant_operand(struct nv_pc *pc,
       break;
    case NV_OP_RCP:
       u.f32 = 1.0f / u.f32;
-      (val = new_value(pc, NV_FILE_IMM, NV_TYPE_F32))->reg.imm.f32 = u.f32;
+      (val = new_value(pc, NV_FILE_IMM, 4))->reg.imm.f32 = u.f32;
       nvi->opcode = NV_OP_MOV;
       assert(s == 0);
       nv_reference(pc, nvi, 0, val);
       break;
    case NV_OP_RSQ:
       u.f32 = 1.0f / sqrtf(u.f32);
-      (val = new_value(pc, NV_FILE_IMM, NV_TYPE_F32))->reg.imm.f32 = u.f32;
+      (val = new_value(pc, NV_FILE_IMM, 4))->reg.imm.f32 = u.f32;
       nvi->opcode = NV_OP_MOV;
       assert(s == 0);
       nv_reference(pc, nvi, 0, val);
@@ -607,25 +624,83 @@ constant_operand(struct nv_pc *pc,
    }
 }
 
+static void
+handle_min_max(struct nv_pass *ctx, struct nv_instruction *nvi)
+{
+   struct nv_value *src0 = nvi->src[0]->value;
+   struct nv_value *src1 = nvi->src[1]->value;
+
+   if (src0 != src1 || (nvi->src[0]->mod | nvi->src[1]->mod))
+      return;
+   if (src0->reg.file != NV_FILE_GPR)
+      return;
+   nvc0_pc_replace_value(ctx->pc, nvi->def[0], src0);
+   nvc0_insn_delete(nvi);
+}
+
+/* check if we can MUL + ADD -> MAD/FMA */
+static void
+handle_add_mul(struct nv_pass *ctx, struct nv_instruction *nvi)
+{
+   struct nv_value *src0 = nvi->src[0]->value;
+   struct nv_value *src1 = nvi->src[1]->value;
+   struct nv_value *src;
+   int s;
+   uint8_t mod[4];
+
+   if (SRC_IS_MUL(src0) && src0->refc == 1) s = 0;
+   else
+   if (SRC_IS_MUL(src1) && src1->refc == 1) s = 1;
+   else
+      return;
+
+   if ((src0->insn && src0->insn->bb != nvi->bb) ||
+       (src1->insn && src1->insn->bb != nvi->bb))
+      return;
+
+   /* check for immediates from prior constant folding */
+   if (src0->reg.file != NV_FILE_GPR || src1->reg.file != NV_FILE_GPR)
+      return;
+   src = nvi->src[s]->value;
+
+   mod[0] = nvi->src[0]->mod;
+   mod[1] = nvi->src[1]->mod;
+   mod[2] = src->insn->src[0]->mod;
+   mod[3] = src->insn->src[1]->mod;
+
+   if ((mod[0] | mod[1] | mod[2] | mod[3]) & ~NV_MOD_NEG)
+      return;
+
+   nvi->opcode = NV_OP_MAD_F32;
+
+   nv_reference(ctx->pc, nvi, s, NULL);
+   nvi->src[2] = nvi->src[!s];
+   nvi->src[!s] = NULL;
+
+   nv_reference(ctx->pc, nvi, 0, src->insn->src[0]->value);
+   nvi->src[0]->mod = mod[2] ^ mod[s];
+   nv_reference(ctx->pc, nvi, 1, src->insn->src[1]->value);
+   nvi->src[1]->mod = mod[3];
+}
+
 static int
-nv_pass_lower_arith(struct nv_pass *ctx, struct nv_basic_block *b)
+nv_pass_algebraic_opt(struct nv_pass *ctx, struct nv_basic_block *b)
 {
    struct nv_instruction *nvi, *next;
    int j;
 
    for (nvi = b->entry; nvi; nvi = next) {
-      struct nv_value *src0, *src1, *src;
-      int s;
-      uint8_t mod[4];
+      struct nv_value *src0, *src1;
+      uint baseop = NV_BASEOP(nvi->opcode);
 
       next = nvi->next;
 
       src0 = nvc0_pc_find_immediate(nvi->src[0]);
       src1 = nvc0_pc_find_immediate(nvi->src[1]);
 
-      if (src0 && src1)
+      if (src0 && src1) {
          constant_expression(ctx->pc, nvi, src0, src1);
-      else {
+      else {
          if (src0)
             constant_operand(ctx->pc, nvi, src0, 0);
          else
@@ -633,44 +708,13 @@ nv_pass_lower_arith(struct nv_pass *ctx, struct nv_basic_block *b)
             constant_operand(ctx->pc, nvi, src1, 1);
       }
 
-      /* check if we can MUL + ADD -> MAD/FMA */
-      if (nvi->opcode != NV_OP_ADD)
-         continue;
-
-      src0 = nvi->src[0]->value;
-      src1 = nvi->src[1]->value;
-
-      if (SRC_IS_MUL(src0) && src0->refc == 1)
-         src = src0;
+      if (baseop == NV_OP_MIN || baseop == NV_OP_MAX)
+         handle_min_max(ctx, nvi);
       else
-      if (SRC_IS_MUL(src1) && src1->refc == 1)
-         src = src1;
-      else
-         continue;
-
-      /* could have an immediate from above constant_*  */
-      if (src0->reg.file != NV_FILE_GPR || src1->reg.file != NV_FILE_GPR)
-         continue;
-      s = (src == src0) ? 0 : 1;
-
-      mod[0] = nvi->src[0]->mod;
-      mod[1] = nvi->src[1]->mod;
-      mod[2] = src->insn->src[0]->mod;
-      mod[3] = src->insn->src[0]->mod;
-
-      if ((mod[0] | mod[1] | mod[2] | mod[3]) & ~NV_MOD_NEG)
-         continue;
-
-      nvi->opcode = NV_OP_MAD;
-      nv_reference(ctx->pc, nvi, s, NULL);
-      nvi->src[2] = nvi->src[!s];
-
-      nvi->src[0] = new_ref(ctx->pc, src->insn->src[0]->value);
-      nvi->src[1] = new_ref(ctx->pc, src->insn->src[1]->value);
-      nvi->src[0]->mod = mod[2] ^ mod[s];
-      nvi->src[1]->mod = mod[3];
+      if (nvi->opcode == NV_OP_ADD_F32)
+         handle_add_mul(ctx, nvi);
    }
-   DESCEND_ARBITRARY(j, nv_pass_lower_arith);
+   DESCEND_ARBITRARY(j, nv_pass_algebraic_opt);
 
    return 0;
 }
@@ -700,8 +744,12 @@ struct pass_reld_elim {
    int alloc;
 };
 
+/* Extend the load operation in @rec to also cover the data loaded by @ld.
+ * The two loads may not overlap but reference adjacent memory locations.
+ */
 static void
-combine_load(struct mem_record *rec, struct nv_instruction *ld)
+combine_load(struct nv_pc *pc, struct mem_record *rec,
+             struct nv_instruction *ld)
 {
    struct nv_instruction *fv = rec->insn;
    struct nv_value *mem = ld->src[0]->value;
@@ -716,7 +764,7 @@ combine_load(struct mem_record *rec, struct nv_instruction *ld)
          return;
       rec->ofst = mem->reg.address;
       for (j = 0; j < d; ++j)
-         fv->def[d + j] = fv->def[j];
+         fv->def[mem->reg.size / 4 + j] = fv->def[j];
       d = 0;
    } else
    if ((size == 8 && rec->ofst & 3) ||
@@ -729,6 +777,9 @@ combine_load(struct mem_record *rec, struct nv_instruction *ld)
       fv->def[d++]->insn = fv;
    }
 
+   if (fv->src[0]->value->refc > 1)
+      nv_reference(pc, fv, 0, new_value_like(pc, fv->src[0]->value));
+   fv->src[0]->value->reg.address = rec->ofst;
    fv->src[0]->value->reg.size = rec->size = size;
 
    nvc0_insn_delete(ld);
@@ -793,6 +844,7 @@ nv_pass_mem_opt(struct pass_reld_elim *ctx, struct nv_basic_block *b)
              ((it->ofst >> 4) == (ofst >> 4)) &&
              ((it->ofst + it->size == ofst) ||
               (it->ofst - mem->reg.size == ofst))) {
+            /* only NV_OP_VFETCH can load exactly 12 bytes */
             if (ld->opcode == NV_OP_LD && it->size + mem->reg.size == 12)
                continue;
             if (it->ofst < ofst) {
@@ -808,7 +860,7 @@ nv_pass_mem_opt(struct pass_reld_elim *ctx, struct nv_basic_block *b)
          switch (ld->opcode) {
          case NV_OP_EXPORT: combine_export(it, ld); break;
          default:
-            combine_load(it, ld);
+            combine_load(ctx->pc, it, ld);
             break;
          }
       } else
@@ -817,6 +869,11 @@ nv_pass_mem_opt(struct pass_reld_elim *ctx, struct nv_basic_block *b)
       }
    }
 
+   ctx->alloc = 0;
+   ctx->mem_a = ctx->mem_v = ctx->mem_l = NULL;
+   for (s = 0; s < 16; ++s)
+      ctx->mem_c[s] = NULL;
+
    DESCEND_ARBITRARY(s, nv_pass_mem_opt);
    return 0;
 }
@@ -1006,7 +1063,6 @@ nv_pass_dce(struct nv_pass_dce *ctx, struct nv_basic_block *b)
    return 0;
 }
 
-#if 0
 /* Register allocation inserted ELSE blocks for all IF/ENDIF without ELSE.
  * Returns TRUE if @bb initiates an IF/ELSE/ENDIF clause, or is an IF with
  * BREAK and dummy ELSE block.
@@ -1027,61 +1083,187 @@ bb_is_if_else_endif(struct nv_basic_block *bb)
    }
 }
 
-/* predicate instructions and remove branch at the end */
+/* Predicate instructions and delete any branch at the end if it is
+ * not a break from a loop.
+ */
 static void
 predicate_instructions(struct nv_pc *pc, struct nv_basic_block *b,
-                       struct nv_value *p, ubyte cc)
+                       struct nv_value *pred, uint8_t cc)
 {
+   struct nv_instruction *nvi, *prev;
+   int s;
 
+   if (!b->entry)
+      return;
+   for (nvi = b->entry; nvi; nvi = nvi->next) {
+      prev = nvi;
+      if (inst_is_noop(nvi))
+         continue;
+      for (s = 0; nvi->src[s]; ++s);
+      assert(s < 6);
+      nvi->predicate = s;
+      nvi->cc = cc;
+      nv_reference(pc, nvi, nvi->predicate, pred);
+   }
+   if (prev->opcode == NV_OP_BRA &&
+       b->out_kind[0] != CFG_EDGE_LOOP_LEAVE &&
+       b->out_kind[1] != CFG_EDGE_LOOP_LEAVE)
+      nvc0_insn_delete(prev);
 }
-#endif
 
-/* NOTE: Run this after register allocation, we can just cut out the cflow
- * instructions and hook the predicates to the conditional OPs if they are
- * not using immediates; better than inserting SELECT to join definitions.
- *
- * NOTE: Should adapt prior optimization to make this possible more often.
+static INLINE boolean
+may_predicate_insn(struct nv_instruction *nvi, struct nv_value *pred)
+{
+   if (nvi->def[0] && values_equal(nvi->def[0], pred))
+      return FALSE;
+   return nvc0_insn_is_predicateable(nvi);
+}
+
+/* Transform IF/ELSE/ENDIF constructs into predicated instructions
+ * where feasible.
  */
 static int
 nv_pass_flatten(struct nv_pass *ctx, struct nv_basic_block *b)
 {
+   struct nv_instruction *nvi;
+   struct nv_value *pred;
+   int k;
+   int n0, n1; /* instruction counts of outgoing blocks */
+
+   if (bb_is_if_else_endif(b)) {
+      assert(b->exit && b->exit->opcode == NV_OP_BRA);
+
+      assert(b->exit->predicate >= 0);
+      pred = b->exit->src[b->exit->predicate]->value;
+
+      n1 = n0 = 0;
+      for (nvi = b->out[0]->entry; nvi; nvi = nvi->next, ++n0)
+         if (!may_predicate_insn(nvi, pred))
+            break;
+      if (!nvi) {
+         /* we're after register allocation, so there always is an ELSE block */
+         for (nvi = b->out[1]->entry; nvi; nvi = nvi->next, ++n1)
+            if (!may_predicate_insn(nvi, pred))
+               break;
+      }
+
+      /* 12 is an arbitrary limit */
+      if (!nvi && n0 < 12 && n1 < 12) {
+         predicate_instructions(ctx->pc, b->out[0], pred, !b->exit->cc);
+         predicate_instructions(ctx->pc, b->out[1], pred, b->exit->cc);
+
+         nvc0_insn_delete(b->exit); /* delete the branch */
+
+         /* and a potential joinat before it */
+         if (b->exit && b->exit->opcode == NV_OP_JOINAT)
+            nvc0_insn_delete(b->exit);
+
+         /* remove join operations at the end of the conditional */
+         k = (b->out[0]->out_kind[0] == CFG_EDGE_LOOP_LEAVE) ? 1 : 0;
+         if ((nvi = b->out[0]->out[k]->entry)) {
+            nvi->join = 0;
+            if (nvi->opcode == NV_OP_JOIN)
+               nvc0_insn_delete(nvi);
+         }
+      }
+   }
+   DESCEND_ARBITRARY(k, nv_pass_flatten);
+
    return 0;
 }
 
+/* Tests instructions for equality, but independently of sources. */
+static boolean
+is_operation_equal(struct nv_instruction *a, struct nv_instruction *b)
+{
+   if (a->opcode != b->opcode)
+      return FALSE;
+   if (nv_is_texture_op(a->opcode)) {
+      if (a->ext.tex.t != b->ext.tex.t ||
+          a->ext.tex.s != b->ext.tex.s)
+         return FALSE;
+      if (a->tex_dim != b->tex_dim ||
+          a->tex_array != b->tex_array ||
+          a->tex_cube != b->tex_cube ||
+          a->tex_shadow != b->tex_shadow ||
+          a->tex_live != b->tex_live)
+         return FALSE;
+   } else
+   if (a->opcode == NV_OP_CVT) {
+      if (a->ext.cvt.s != b->ext.cvt.s ||
+          a->ext.cvt.d != b->ext.cvt.d)
+         return FALSE;
+   } else
+   if (NV_BASEOP(a->opcode) == NV_OP_SET ||
+       NV_BASEOP(a->opcode) == NV_OP_SLCT) {
+      if (a->set_cond != b->set_cond)
+         return FALSE;
+   } else
+   if (a->opcode == NV_OP_LINTERP ||
+       a->opcode == NV_OP_PINTERP) {
+      if (a->centroid != b->centroid ||
+          a->flat != b->flat)
+         return FALSE;
+   }
+   if (a->cc != b->cc)
+      return FALSE;
+   if (a->lanes != b->lanes ||
+       a->patch != b->patch ||
+       a->saturate != b->saturate)
+      return FALSE;
+   if (a->opcode == NV_OP_QUADOP) /* beware quadon ! */
+      return FALSE;
+   return TRUE;
+}
+
 /* local common subexpression elimination, stupid O(n^2) implementation */
 static int
 nv_pass_cse(struct nv_pass *ctx, struct nv_basic_block *b)
 {
    struct nv_instruction *ir, *ik, *next;
    struct nv_instruction *entry = b->phi ? b->phi : b->entry;
-   int s;
+   int s, d;
    unsigned int reps;
 
    do {
       reps = 0;
       for (ir = entry; ir; ir = next) {
          next = ir->next;
+         if (ir->fixed)
+            continue;
          for (ik = entry; ik != ir; ik = ik->next) {
-            if (ir->opcode != ik->opcode || ir->fixed)
+            if (!is_operation_equal(ir, ik))
                continue;
-
-            if (!ir->def[0] || !ik->def[0] || ir->def[1] || ik->def[1])
+            if (!ir->def[0] || !ik->def[0])
                continue;
 
             if (ik->indirect != ir->indirect || ik->predicate != ir->predicate)
                continue;
 
-            if (!values_equal(ik->def[0], ir->def[0]))
+            for (d = 0; d < 4; ++d) {
+               if ((ir->def[d] ? 1 : 0) != (ik->def[d] ? 1 : 0))
+                  break;
+               if (ir->def[d]) {
+                  if (!values_equal(ik->def[0], ir->def[0]))
+                     break;
+               } else {
+                  d = 4;
+                  break;
+               }
+            }
+            if (d != 4)
                continue;
 
-            for (s = 0; s < 3; ++s) {
+            for (s = 0; s < 5; ++s) {
                struct nv_value *a, *b;
 
-               if (!ik->src[s]) {
-                  if (ir->src[s])
-                     break;
-                  continue;
+               if ((ir->src[s] ? 1 : 0) != (ik->src[s] ? 1 : 0))
+                  break;
+               if (!ir->src[s]) {
+                  s = 5;
+                  break;
                }
+
                if (ik->src[s]->mod != ir->src[s]->mod)
                   break;
                a = ik->src[s]->value;
@@ -1089,14 +1271,15 @@ nv_pass_cse(struct nv_pass *ctx, struct nv_basic_block *b)
                if (a == b)
                   continue;
                if (a->reg.file != b->reg.file ||
-                   a->reg.id < 0 ||
+                   a->reg.id < 0 || /* this excludes memory loads/stores */
                    a->reg.id != b->reg.id)
                   break;
             }
-            if (s == 3) {
+            if (s == 5) {
                nvc0_insn_delete(ir);
+               for (d = 0; d < 4 && ir->def[d]; ++d)
+                  nvc0_pc_replace_value(ctx->pc, ir->def[d], ik->def[d]);
                ++reps;
-               nvc0_pc_replace_value(ctx->pc, ir->def[0], ik->def[0]);
                break;
             }
          }
@@ -1110,13 +1293,15 @@ nv_pass_cse(struct nv_pass *ctx, struct nv_basic_block *b)
 
 /* Make sure all sources of an NV_OP_BIND are distinct, they need to occupy
  * neighbouring registers. CSE might have messed this up.
+ * Just generate a MOV for each source to avoid conflicts if they're used in
+ * multiple NV_OP_BIND at different positions.
  */
 static int
 nv_pass_fix_bind(struct nv_pass *ctx, struct nv_basic_block *b)
 {
    struct nv_value *val;
    struct nv_instruction *bnd, *nvi, *next;
-   int s, t;
+   int s;
 
    for (bnd = b->entry; bnd; bnd = next) {
       next = bnd->next;
@@ -1124,20 +1309,17 @@ nv_pass_fix_bind(struct nv_pass *ctx, struct nv_basic_block *b)
          continue;
       for (s = 0; s < 4 && bnd->src[s]; ++s) {
          val = bnd->src[s]->value;
-         for (t = s + 1; t < 4 && bnd->src[t]; ++t) {
-            if (bnd->src[t]->value != val)
-               continue;
-            nvi = nv_alloc_instruction(ctx->pc, NV_OP_MOV);
-            nvi->def[0] = new_value_like(ctx->pc, val);
-            nvi->def[0]->insn = nvi;
-            nv_reference(ctx->pc, nvi, 0, val);
-            nvc0_insn_insert_before(bnd, nvi);
 
-            nv_reference(ctx->pc, bnd, t, nvi->def[0]);
-         }
+         nvi = nv_alloc_instruction(ctx->pc, NV_OP_MOV);
+         nvi->def[0] = new_value_like(ctx->pc, val);
+         nvi->def[0]->insn = nvi;
+         nv_reference(ctx->pc, nvi, 0, val);
+         nv_reference(ctx->pc, bnd, s, nvi->def[0]);
+
+         nvc0_insn_insert_before(bnd, nvi);
       }
    }
-   DESCEND_ARBITRARY(t, nv_pass_fix_bind);
+   DESCEND_ARBITRARY(s, nv_pass_fix_bind);
 
    return 0;
 }
@@ -1153,11 +1335,17 @@ nv_pc_pass0(struct nv_pc *pc, struct nv_basic_block *root)
    pass.n = 0;
    pass.pc = pc;
 
+   /* Do CSE so we can just compare values by pointer in subsequent passes. */
+   pc->pass_seq++;
+   ret = nv_pass_cse(&pass, root);
+   if (ret)
+      return ret;
+
    /* Do this first, so we don't have to pay attention
     * to whether sources are supported memory loads.
     */
    pc->pass_seq++;
-   ret = nv_pass_lower_arith(&pass, root);
+   ret = nv_pass_algebraic_opt(&pass, root);
    if (ret)
       return ret;
 
@@ -1185,11 +1373,9 @@ nv_pc_pass0(struct nv_pc *pc, struct nv_basic_block *root)
       reldelim->pc = pc;
    }
 
-   pc->pass_seq++;
-   ret = nv_pass_cse(&pass, root);
-   if (ret)
-      return ret;
-
+   /* May run DCE before load-combining since that pass will clean up
+    * after itself.
+    */
    dce.pc = pc;
    do {
       dce.removed = 0;
index b03826484e4f20f62566c5b75f741fdef4096f45..90c669cc4b832c85b8fe4d92be5854cd6e1ded43 100644 (file)
@@ -225,7 +225,7 @@ nvc0_print_instruction(struct nv_instruction *i)
 
    PRINT("%s", gree);
    if (NV_BASEOP(i->opcode) == NV_OP_SET)
-      PRINT("set %s", nv_cond_name(i->set_cond));
+      PRINT("%s %s", nvc0_opcode_name(i->opcode), nv_cond_name(i->set_cond));
    else
    if (i->saturate)
       PRINT("sat %s", nvc0_opcode_name(i->opcode));
@@ -278,10 +278,10 @@ struct nv_op_info nvc0_op_info_table[NV_OP_COUNT + 1] =
    { NV_OP_MERGE,  "merge",  NV_TYPE_ANY, 0, /* fcvpoi */ 0, 0, 1, 0, 1, 0, 0 },
    { NV_OP_PHI,    "phi",    NV_TYPE_ANY, 0, /* fcvpoi */ 0, 0, 0, 0, 1, 0, 0 },
    { NV_OP_SELECT, "select", NV_TYPE_ANY, 0, /* fcvpoi */ 0, 0, 0, 0, 1, 0, 0 },
-   { NV_OP_NOP,    "nop",    NV_TYPE_ANY, 0, /* fcvpoi */ 0, 0, 0, 0, 0, 0, 0 },
+   { NV_OP_NOP,    "nop",    NV_TYPE_ANY, 0, /* fcvpoi */ 0, 0, 0, 1, 0, 0, 0 },
 
-   { NV_OP_LD,  "ld",  NV_TYPE_ANY, 0, 0, 0, 0, 0, 0, 0, 0 },
-   { NV_OP_ST,  "st",  NV_TYPE_ANY, 0, 0, 0, 0, 0, 0, 0, 0 },
+   { NV_OP_LD,  "ld",  NV_TYPE_ANY, 0, 0, 0, 0, 1, 0, 0, 0 },
+   { NV_OP_ST,  "st",  NV_TYPE_ANY, 0, 0, 0, 0, 1, 0, 0, 0 },
    { NV_OP_MOV, "mov", NV_TYPE_ANY, 0, 0, 0, 0, 1, 0, 1, 0 },
    { NV_OP_AND, "and", NV_TYPE_U32, NV_MOD_NOT, 0, 1, 0, 1, 0, 6, 0 },
    { NV_OP_OR,  "or",  NV_TYPE_U32, NV_MOD_NOT, 0, 1, 0, 1, 0, 6, 0 },
@@ -302,7 +302,7 @@ struct nv_op_info nvc0_op_info_table[NV_OP_COUNT + 1] =
 
    { NV_OP_CEIL,  "ceil",  NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 0 },
    { NV_OP_FLOOR, "floor", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 0 },
-   { NV_OP_TRUNC, "floor", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 0 },
+   { NV_OP_TRUNC, "trunc", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 0 },
 
    { NV_OP_SAD, "sad", NV_TYPE_S32, 0, 0, 1, 0, 1, 0, 0, 0 },
 
@@ -343,18 +343,18 @@ struct nv_op_info nvc0_op_info_table[NV_OP_COUNT + 1] =
    { NV_OP_MIN, "max", NV_TYPE_U32, 0, 0, 1, 0, 1, 0, 0, 0 },
    { NV_OP_MAX, "min", NV_TYPE_S32, 0, 0, 1, 0, 1, 0, 0, 0 },
    { NV_OP_MIN, "min", NV_TYPE_U32, 0, 0, 1, 0, 1, 0, 0, 0 },
-   { NV_OP_SET, "set", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 2 },
-   { NV_OP_SET, "set", NV_TYPE_S32, 0, 0, 0, 0, 1, 0, 0, 0 },
-   { NV_OP_SET, "set", NV_TYPE_U32, 0, 0, 0, 0, 1, 0, 0, 0 },
+   { NV_OP_SET, "set", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 2, 2 },
+   { NV_OP_SET, "set", NV_TYPE_S32, 0, 0, 0, 0, 1, 0, 2, 2 },
+   { NV_OP_SET, "set", NV_TYPE_U32, 0, 0, 0, 0, 1, 0, 2, 2 },
    { NV_OP_SHR, "sar", NV_TYPE_S32, 0, 0, 0, 0, 1, 0, 1, 0 },
-   { NV_OP_RCP, "rcp", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 0, 0, 0, 0 },
-   { NV_OP_RSQ, "rsqrt", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 0, 0, 0, 0 },
-   { NV_OP_LG2, "lg2", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 0, 0, 0, 0 },
-   { NV_OP_SIN, "sin", NV_TYPE_F32, 0, 0, 0, 0, 0, 0, 0, 0 },
-   { NV_OP_COS, "cos", NV_TYPE_F32, 0, 0, 0, 0, 0, 0, 0, 0 },
-   { NV_OP_EX2, "ex2", NV_TYPE_F32, 0, 0, 0, 0, 0, 0, 0, 0 },
-   { NV_OP_PRESIN, "presin", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 0, 0, 0, 0 },
-   { NV_OP_PREEX2, "preex2", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 0, 0, 0, 0 },
+   { NV_OP_RCP, "rcp", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 0 },
+   { NV_OP_RSQ, "rsqrt", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 0 },
+   { NV_OP_LG2, "lg2", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 0 },
+   { NV_OP_SIN, "sin", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 0, 0 },
+   { NV_OP_COS, "cos", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 0, 0 },
+   { NV_OP_EX2, "ex2", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 0, 0 },
+   { NV_OP_PRESIN, "presin", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 1 },
+   { NV_OP_PREEX2, "preex2", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 1 },
    { NV_OP_SAT, "sat", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 0, 0 },
 
    { NV_OP_SET_F32_AND, "and set", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 0, 0 },
@@ -363,13 +363,13 @@ struct nv_op_info nvc0_op_info_table[NV_OP_COUNT + 1] =
 
    { NV_OP_SELP, "selp", NV_TYPE_U32, 0, 0, 0, 0, 1, 0, 0, 0 },
 
-   { NV_OP_SLCT_F32, "slct", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 0, 0 },
-   { NV_OP_SLCT_F32, "slct", NV_TYPE_S32, 0, 0, 0, 0, 1, 0, 0, 0 },
-   { NV_OP_SLCT_F32, "slct", NV_TYPE_U32, 0, 0, 0, 0, 1, 0, 0, 0 },
+   { NV_OP_SLCT, "slct", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 2, 2 },
+   { NV_OP_SLCT, "slct", NV_TYPE_S32, 0, 0, 0, 0, 1, 0, 2, 2 },
+   { NV_OP_SLCT, "slct", NV_TYPE_U32, 0, 0, 0, 0, 1, 0, 2, 2 },
 
    { NV_OP_ADD, "sub", NV_TYPE_F32, 0, 0, 0, 0, 1, 0, 1, 0 },
 
-   { NV_OP_FSET_F32, "fset", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 0, 2 },
+   { NV_OP_SET, "fset", NV_TYPE_F32, NV_MOD_SGN, 0, 0, 0, 1, 0, 2, 2 },
 
    { NV_OP_TXG, "texgrad", NV_TYPE_F32, 0, 0, 0, 1, 1, 0, 0, 0 },
 
index d24f09a1507f5af94445f8cfbfec6be8674fd275..f4afe083e2dde92a32e1a79a21d9837c9b81c9fe 100644 (file)
@@ -39,6 +39,30 @@ struct register_set {
    struct nv_pc *pc;
 };
 
+/* aliasing is allowed */
+static void
+intersect_register_sets(struct register_set *dst,
+                        struct register_set *src1, struct register_set *src2)
+{
+   int i;
+
+   for (i = 0; i < NVC0_NUM_REGISTER_FILES; ++i) {
+      dst->bits[i][0] = src1->bits[i][0] | src2->bits[i][0];
+      dst->bits[i][1] = src1->bits[i][1] | src2->bits[i][1];
+   }
+}
+
+static void
+mask_register_set(struct register_set *set, uint32_t mask, uint32_t umask)
+{
+   int i;
+
+   for (i = 0; i < NVC0_NUM_REGISTER_FILES; ++i) {
+      set->bits[i][0] = (set->bits[i][0] | mask) & umask;
+      set->bits[i][1] = (set->bits[i][1] | mask) & umask;
+   }
+}
+
 struct nv_pc_pass {
    struct nv_pc *pc;
    struct nv_instruction **insns;
@@ -63,6 +87,9 @@ add_range_ex(struct nv_value *val, int bgn, int end, struct nv_range *new_range)
 {
    struct nv_range *range, **nextp = &val->livei;
 
+   if (bgn == end) /* [a, a) is invalid / empty */
+      return TRUE;
+
    for (range = val->livei; range; range = range->next) {
       if (end < range->bgn)
          break; /* insert before */
@@ -327,14 +354,14 @@ do_join_values(struct nv_pc_pass *ctx, struct nv_value *a, struct nv_value *b)
    assert(b->join == a->join);
 }
 
-static INLINE void
+static INLINE boolean
 try_join_values(struct nv_pc_pass *ctx, struct nv_value *a, struct nv_value *b)
 {
    if (!join_allowed(ctx, a, b)) {
 #ifdef NVC0_RA_DEBUG_JOIN
       debug_printf("cannot join %i to %i: not allowed\n", b->n, a->n);
 #endif
-      return;
+      return FALSE;
    }
    if (livei_have_overlap(a->join, b->join)) {
 #ifdef NVC0_RA_DEBUG_JOIN
@@ -342,10 +369,27 @@ try_join_values(struct nv_pc_pass *ctx, struct nv_value *a, struct nv_value *b)
       livei_print(a);
       livei_print(b);
 #endif
-      return;
+      return FALSE;
    }
 
    do_join_values(ctx, a, b);
+
+   return TRUE;
+}
+
+static void
+join_values_nofail(struct nv_pc_pass *ctx,
+                   struct nv_value *a, struct nv_value *b, boolean type_only)
+{
+   if (type_only) {
+      assert(join_allowed(ctx, a, b));
+      do_join_values(ctx, a, b);
+   } else {
+      boolean ok = try_join_values(ctx, a, b);
+      if (!ok) {
+         NOUVEAU_ERR("failed to coalesce values\n");
+      }
+   }
 }
 
 static INLINE boolean
@@ -360,20 +404,32 @@ need_new_else_block(struct nv_basic_block *b, struct nv_basic_block *p)
    return (b->num_in > 1) && (n == 2);
 }
 
+/* Look for the @phi's operand whose definition reaches @b. */
 static int
 phi_opnd_for_bb(struct nv_instruction *phi, struct nv_basic_block *b,
                 struct nv_basic_block *tb)
 {
+   struct nv_ref *srci, *srcj;
    int i, j;
 
    for (j = -1, i = 0; i < 6 && phi->src[i]; ++i) {
-      if (!nvc0_bblock_reachable_by(b, phi->src[i]->value->insn->bb, tb))
+      srci = phi->src[i];
+      /* if already replaced, check with original source first */
+      if (srci->flags & NV_REF_FLAG_REGALLOC_PRIV)
+         srci = srci->value->insn->src[0];
+      if (!nvc0_bblock_reachable_by(b, srci->value->insn->bb, NULL))
          continue;
       /* NOTE: back-edges are ignored by the reachable-by check */
-      if (j < 0 || !nvc0_bblock_reachable_by(phi->src[j]->value->insn->bb,
-                                             phi->src[i]->value->insn->bb, tb))
+      if (j < 0 || !nvc0_bblock_reachable_by(srcj->value->insn->bb,
+                                             srci->value->insn->bb, NULL)) {
          j = i;
+         srcj = srci;
+      }
    }
+   if (j >= 0 && nvc0_bblock_reachable_by(b, phi->def[0]->insn->bb, NULL))
+      if (!nvc0_bblock_reachable_by(srcj->value->insn->bb,
+                                    phi->def[0]->insn->bb, NULL))
+         j = -1;
    return j;
 }
 
@@ -420,21 +476,23 @@ pass_generate_phi_movs(struct nv_pc_pass *ctx, struct nv_basic_block *b)
       ctx->pc->current_block = pn;
 
       for (i = b->phi; i && i->opcode == NV_OP_PHI; i = i->next) {
-         if ((j = phi_opnd_for_bb(i, p, b)) < 0)
-            continue;
-         val = i->src[j]->value;
-
-         if (i->src[j]->flags) {
-            /* value already encountered from a different in-block */
-            val = val->insn->src[0]->value;
-            while (j < 6 && i->src[j])
-               ++j;
-            assert(j < 6);
+         j = phi_opnd_for_bb(i, p, b);
+
+         if (j < 0) {
+            val = i->def[0];
+         } else {
+            val = i->src[j]->value;
+            if (i->src[j]->flags & NV_REF_FLAG_REGALLOC_PRIV) {
+               j = -1;
+               /* use original value, we already encountered & replaced it */
+               val = val->insn->src[0]->value;
+            }
          }
+         if (j < 0) /* need an additional source ? */
+            for (j = 0; j < 6 && i->src[j] && i->src[j]->value != val; ++j);
+         assert(j < 6); /* XXX: really ugly shaders */
 
          ni = new_instruction(ctx->pc, NV_OP_MOV);
-
-         /* TODO: insert instruction at correct position in the first place */
          if (ni->prev && ni->prev->target)
             nvc0_insns_permute(ni->prev, ni);
 
@@ -442,7 +500,7 @@ pass_generate_phi_movs(struct nv_pc_pass *ctx, struct nv_basic_block *b)
          ni->def[0]->insn = ni;
          nv_reference(ctx->pc, ni, 0, val);
          nv_reference(ctx->pc, i, j, ni->def[0]); /* new phi source = MOV def */
-         i->src[j]->flags = 1;
+         i->src[j]->flags |= NV_REF_FLAG_REGALLOC_PRIV;
       }
 
       if (pn != p && pn->exit) {
@@ -460,8 +518,13 @@ pass_generate_phi_movs(struct nv_pc_pass *ctx, struct nv_basic_block *b)
    return 0;
 }
 
+#define JOIN_MASK_PHI    (1 << 0)
+#define JOIN_MASK_SELECT (1 << 1)
+#define JOIN_MASK_MOV    (1 << 2)
+#define JOIN_MASK_BIND   (1 << 3)
+
 static int
-pass_join_values(struct nv_pc_pass *ctx, int iter)
+pass_join_values(struct nv_pc_pass *ctx, unsigned mask)
 {
    int c, n;
 
@@ -470,36 +533,33 @@ pass_join_values(struct nv_pc_pass *ctx, int iter)
 
       switch (i->opcode) {
       case NV_OP_PHI:
-         if (iter != 2)
+         if (!(mask & JOIN_MASK_PHI))
             break;
          for (c = 0; c < 6 && i->src[c]; ++c)
-            try_join_values(ctx, i->def[0], i->src[c]->value);
+            join_values_nofail(ctx, i->def[0], i->src[c]->value, FALSE);
          break;
       case NV_OP_MOV:
-         if ((iter == 2) && i->src[0]->value->insn &&
-             !nv_is_texture_op(i->src[0]->value->join->insn->opcode))
+         if (!(mask & JOIN_MASK_MOV))
+            break;
+         if (i->src[0]->value->insn && !i->src[0]->value->insn->def[1])
             try_join_values(ctx, i->def[0], i->src[0]->value);
          break;
       case NV_OP_SELECT:
-         if (iter != 1)
+         if (!(mask & JOIN_MASK_SELECT))
             break;
-         for (c = 0; c < 6 && i->src[c]; ++c) {
-            assert(join_allowed(ctx, i->def[0], i->src[c]->value));
-            do_join_values(ctx, i->def[0], i->src[c]->value);
-         }
-         break;
-      case NV_OP_TEX:
-      case NV_OP_TXB:
-      case NV_OP_TXL:
-      case NV_OP_TXQ:
-         /* on nvc0, TEX src and dst can differ */
+         for (c = 0; c < 6 && i->src[c]; ++c)
+            join_values_nofail(ctx, i->def[0], i->src[c]->value, TRUE);
          break;
       case NV_OP_BIND:
-         if (iter)
+         if (!(mask & JOIN_MASK_BIND))
             break;
-         for (c = 0; c < 6 && i->src[c]; ++c)
-            do_join_values(ctx, i->def[c], i->src[c]->value);
+         for (c = 0; c < 4 && i->src[c]; ++c)
+            join_values_nofail(ctx, i->def[c], i->src[c]->value, TRUE);
          break;
+      case NV_OP_TEX:
+      case NV_OP_TXB:
+      case NV_OP_TXL:
+      case NV_OP_TXQ: /* on nvc0, TEX src and dst can differ */
       default:
          break;
       }
@@ -621,15 +681,16 @@ static void collect_live_values(struct nv_basic_block *b, const int n)
 {
    int i;
 
-   if (b->out[0]) {
-      if (b->out[1]) { /* what to do about back-edges ? */
+   /* XXX: what to do about back/fake-edges (used to include both here) ? */
+   if (b->out[0] && b->out_kind[0] != CFG_EDGE_FAKE) {
+      if (b->out[1] && b->out_kind[1] != CFG_EDGE_FAKE) {
          for (i = 0; i < n; ++i)
             b->live_set[i] = b->out[0]->live_set[i] | b->out[1]->live_set[i];
       } else {
          memcpy(b->live_set, b->out[0]->live_set, n * sizeof(uint32_t));
       }
    } else
-   if (b->out[1]) {
+   if (b->out[1] && b->out_kind[1] != CFG_EDGE_FAKE) {
       memcpy(b->live_set, b->out[1]->live_set, n * sizeof(uint32_t));
    } else {
       memset(b->live_set, 0, n * sizeof(uint32_t));
@@ -746,42 +807,46 @@ insert_ordered_tail(struct nv_value *list, struct nv_value *nval)
    elem->next = nval;
 }
 
-static int
-pass_linear_scan(struct nv_pc_pass *ctx, int iter)
+static void
+collect_register_values(struct nv_pc_pass *ctx, struct nv_value *head,
+                        boolean assigned_only)
 {
-   struct nv_instruction *i;
-   struct register_set f, free;
+   struct nv_value *val;
    int k, n;
-   struct nv_value *cur, *val, *tmp[2];
-   struct nv_value active, inactive, handled, unhandled;
 
-   make_empty_list(&active);
-   make_empty_list(&inactive);
-   make_empty_list(&handled);
-   make_empty_list(&unhandled);
+   make_empty_list(head);
 
-   nvc0_ctor_register_set(ctx->pc, &free);
-
-   /* joined values should have range = NULL and thus not be added;
-    * also, fixed memory values won't be added because they're not
-    * def'd, just used
-    */
    for (n = 0; n < ctx->num_insns; ++n) {
-      i = ctx->insns[n];
+      struct nv_instruction *i = ctx->insns[n];
 
+      /* for joined values, only the representative will have livei != NULL */
       for (k = 0; k < 5; ++k) {
          if (i->def[k] && i->def[k]->livei)
-            insert_ordered_tail(&unhandled, i->def[k]);
-         else
-         if (0 && i->def[k])
-            debug_printf("skipping def'd value %i: no livei\n", i->def[k]->n);
+            if (!assigned_only || i->def[k]->reg.id >= 0)
+               insert_ordered_tail(head, i->def[k]);
       }
    }
 
-   for (val = unhandled.next; val != unhandled.prev; val = val->next) {
+   for (val = head->next; val != head->prev; val = val->next) {
       assert(val->join == val);
       assert(val->livei->bgn <= val->next->livei->bgn);
    }
+}
+
+static int
+pass_linear_scan(struct nv_pc_pass *ctx)
+{
+   struct register_set f, free;
+   struct nv_value *cur, *val, *tmp[2];
+   struct nv_value active, inactive, handled, unhandled;
+
+   make_empty_list(&active);
+   make_empty_list(&inactive);
+   make_empty_list(&handled);
+
+   nvc0_ctor_register_set(ctx->pc, &free);
+
+   collect_register_values(ctx, &unhandled, FALSE);
 
    foreach_s(cur, tmp[0], &unhandled) {
       remove_from_list(cur);
@@ -818,14 +883,7 @@ pass_linear_scan(struct nv_pc_pass *ctx, int iter)
             reg_occupy(&f, val);
 
       if (cur->reg.id < 0) {
-         boolean mem = FALSE;
-         int v = nvi_vector_size(cur->insn);
-
-         if (v > 1)
-            mem = !reg_assign(&f, &cur->insn->def[0], v);
-         else
-         if (iter)
-            mem = !reg_assign(&f, &cur, 1);
+         boolean mem = !reg_assign(&f, &cur, 1);
 
          if (mem) {
             NOUVEAU_ERR("out of registers\n");
@@ -839,6 +897,68 @@ pass_linear_scan(struct nv_pc_pass *ctx, int iter)
    return 0;
 }
 
+/* Allocate values defined by instructions such as TEX, which have to be
+ * assigned to consecutive registers.
+ * Linear scan doesn't really work here since the values can have different
+ * live intervals.
+ */
+static int
+pass_allocate_constrained_values(struct nv_pc_pass *ctx)
+{
+   struct nv_value regvals, *val;
+   struct nv_instruction *i;
+   struct nv_value *defs[4];
+   struct register_set regs[4];
+   int n, vsize, c;
+   uint32_t mask;
+   boolean mem;
+
+   collect_register_values(ctx, &regvals, TRUE);
+
+   for (n = 0; n < ctx->num_insns; ++n) {
+      i = ctx->insns[n];
+      vsize = nvi_vector_size(i);
+      if (!(vsize > 1))
+         continue;
+      assert(vsize <= 4);
+
+      for (c = 0; c < vsize; ++c)
+         defs[c] = i->def[c]->join;
+
+      if (defs[0]->reg.id >= 0) {
+         for (c = 1; c < vsize; ++c)
+            assert(defs[c]->reg.id >= 0);
+         continue;
+      }
+
+      for (c = 0; c < vsize; ++c) {
+         nvc0_ctor_register_set(ctx->pc, &regs[c]);
+
+         foreach(val, &regvals) {
+            if (val->reg.id >= 0 && livei_have_overlap(val, defs[c]))
+               reg_occupy(&regs[c], val);
+         }
+         mask = 0x11111111;
+         if (vsize == 2) /* granularity is 2 and not 4 */
+            mask |= 0x11111111 << 2;
+         mask_register_set(&regs[c], 0, mask << c);
+
+         if (defs[c]->livei)
+            insert_ordered_tail(&regvals, defs[c]);
+      }
+      for (c = 1; c < vsize; ++c)
+         intersect_register_sets(&regs[0], &regs[0], &regs[c]);
+
+      mem = !reg_assign(&regs[0], &defs[0], vsize);
+
+      if (mem) {
+         NOUVEAU_ERR("out of registers\n");
+         abort();
+      }
+   }
+   return 0;
+}
+
 static int
 nv_pc_pass1(struct nv_pc *pc, struct nv_basic_block *root)
 {
@@ -862,6 +982,10 @@ nv_pc_pass1(struct nv_pc *pc, struct nv_basic_block *root)
    ret = pass_generate_phi_movs(ctx, root);
    assert(!ret);
 
+#ifdef NVC0_RA_DEBUG_LIVEI
+   nvc0_print_function(root);
+#endif
+
    for (i = 0; i < pc->loop_nesting_bound; ++i) {
       pc->pass_seq++;
       ret = pass_build_live_sets(ctx, root);
@@ -888,19 +1012,19 @@ nv_pc_pass1(struct nv_pc *pc, struct nv_basic_block *root)
       livei_print(&pc->values[i]);
 #endif
 
-   ret = pass_join_values(ctx, 0);
+   ret = pass_join_values(ctx, JOIN_MASK_PHI);
    if (ret)
       goto out;
-   ret = pass_linear_scan(ctx, 0);
+   ret = pass_join_values(ctx, JOIN_MASK_SELECT | JOIN_MASK_BIND);
    if (ret)
       goto out;
-   ret = pass_join_values(ctx, 1);
+   ret = pass_join_values(ctx, JOIN_MASK_MOV);
    if (ret)
       goto out;
-   ret = pass_join_values(ctx, 2);
+   ret = pass_allocate_constrained_values(ctx);
    if (ret)
       goto out;
-   ret = pass_linear_scan(ctx, 1);
+   ret = pass_linear_scan(ctx);
    if (ret)
       goto out;
 
index aefaf7b98ad026862ba13c916f5e3aad8077cb4d..899fe147c6a3c82d90634aeaefad724533b22244 100644 (file)
@@ -185,8 +185,17 @@ nvc0_varying_location(unsigned sn, unsigned si)
       return 0x2e0;
       */
    case TGSI_SEMANTIC_GENERIC:
+      /* We'd really like to distinguish between TEXCOORD and GENERIC here,
+       * since only 0x300 to 0x37c can be replaced by sprite coordinates.
+       * Also, gl_PointCoord should be a system value and must be assigned to
+       * address 0x2e0. For now, let's cheat:
+       */
       assert(si < 31);
-      return 0x80 + (si * 16);
+      if (si <= 7)
+         return 0x300 + si * 16;
+      if (si == 9)
+         return 0x2e0;
+      return 0x80 + ((si - 8) * 16);
    case TGSI_SEMANTIC_NORMAL:
       return 0x360;
    case TGSI_SEMANTIC_PRIMID:
@@ -256,12 +265,14 @@ prog_decl(struct nvc0_translation_info *ti,
    case TGSI_FILE_INPUT:
       for (i = first; i <= last; ++i) {
          if (ti->prog->type == PIPE_SHADER_VERTEX) {
-            sn = TGSI_SEMANTIC_GENERIC;
-            si = i;
+            for (c = 0; c < 4; ++c)
+               ti->input_loc[i][c] = 0x80 + i * 16 + c * 4;
+         } else {
+            for (c = 0; c < 4; ++c)
+               ti->input_loc[i][c] = nvc0_varying_location(sn, si) + c * 4;
+            /* for sprite coordinates: */
+            ti->prog->fp.in_pos[i] = ti->input_loc[i][0] / 4;
          }
-         for (c = 0; c < 4; ++c)
-            ti->input_loc[i][c] = nvc0_varying_location(sn, si) + c * 4;
-
          if (ti->prog->type == PIPE_SHADER_FRAGMENT)
             ti->interp_mode[i] = nvc0_interp_mode(decl);
       }
@@ -281,6 +292,8 @@ prog_decl(struct nvc0_translation_info *ti,
          } else {
             for (c = 0; c < 4; ++c)
                ti->output_loc[i][c] = nvc0_varying_location(sn, si) + c * 4;
+            /* for TFB_VARYING_LOCS: */
+            ti->prog->vp.out_pos[i] = ti->output_loc[i][0] / 4;
          }
       }
       break;
@@ -288,9 +301,11 @@ prog_decl(struct nvc0_translation_info *ti,
       ti->sysval_loc[i] = nvc0_system_value_location(sn, si, &ti->sysval_in[i]);
       assert(first == last);
       break;
+   case TGSI_FILE_TEMPORARY:
+      ti->temp128_nr = MAX2(ti->temp128_nr, last + 1);
+      break;
    case TGSI_FILE_NULL:
    case TGSI_FILE_CONSTANT:
-   case TGSI_FILE_TEMPORARY:
    case TGSI_FILE_SAMPLER:
    case TGSI_FILE_ADDRESS:
    case TGSI_FILE_IMMEDIATE:
@@ -518,8 +533,13 @@ nvc0_fp_gen_header(struct nvc0_program *fp, struct nvc0_translation_info *ti)
          if (!ti->input_access[i][c])
             continue;
          a = ti->input_loc[i][c] / 2;
-         if ((a & ~7) == 0x70/2)
-            fp->hdr[5] |= 1 << (28 + (a & 7) / 2); /* FRAG_COORD_UMASK */
+         if (ti->input_loc[i][c] >= 0x2c0)
+            a -= 32;
+         if (ti->input_loc[i][0] == 0x70)
+            fp->hdr[5] |= 1 << (28 + c); /* FRAG_COORD_UMASK */
+         else
+         if (ti->input_loc[i][0] == 0x2e0)
+            fp->hdr[14] |= 1 << (24 + c); /* POINT_COORD */
          else
             fp->hdr[4 + a / 32] |= m << (a % 32);
       }
@@ -618,7 +638,7 @@ nvc0_prog_scan(struct nvc0_translation_info *ti)
       if (ti->scan.writes_z)
          prog->flags[0] = 0x11; /* ? */
       else
-      if (!ti->global_stores)
+      if (!ti->scan.uses_kill && !ti->global_stores)
          prog->fp.early_z = 1;
 
       ret = nvc0_fp_gen_header(prog, ti);
@@ -629,6 +649,11 @@ nvc0_prog_scan(struct nvc0_translation_info *ti)
       break;
    }
 
+   if (ti->require_stores) {
+      prog->hdr[0] |= 1 << 26;
+      prog->hdr[1] |= ti->temp128_nr * 16; /* l[] size */
+   }
+
    assert(!ret);
    return ret;
 }
index e6b210d135522e6a4839d89a516fc97b114aacd5..f6fea29780ba221df944b66486a9d0c4b79432ad 100644 (file)
@@ -21,16 +21,18 @@ struct nvc0_program {
    unsigned code_size;
    unsigned parm_size;
 
-   uint32_t hdr[20];
+   uint32_t hdr[20]; /* TODO: move this into code to save space */
 
    uint32_t flags[2];
 
    struct {
       uint8_t edgeflag;
       uint8_t num_ucps;
+      uint8_t out_pos[PIPE_MAX_SHADER_OUTPUTS];
    } vp;
    struct {
       uint8_t early_z;
+      uint8_t in_pos[PIPE_MAX_SHADER_INPUTS];
    } fp;
 
    void *relocs;
@@ -74,6 +76,7 @@ struct nvc0_translation_info {
    uint32_t *immd32;
    ubyte *immd32_ty;
    unsigned immd32_nr;
+   unsigned temp128_nr;
    ubyte edgeflag_out;
    struct nvc0_subroutine *subr;
    unsigned num_subrs;
index 74c3451c19a05ea41382a58446be50c9af186534..fcbb7da41a368313a717d60dd79ae36f17dec5a3 100644 (file)
@@ -217,6 +217,7 @@ nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info)
    struct push_context ctx;
    unsigned i, index_size;
    unsigned inst = info->instance_count;
+   boolean apply_bias = info->indexed && info->index_bias;
 
    ctx.chan = nvc0->screen->base.channel;
    ctx.translate = nvc0->vertex->translate;
@@ -230,7 +231,8 @@ nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info)
 
       data = nvc0_resource_map_offset(nvc0, res,
                                       vb->buffer_offset, NOUVEAU_BO_RD);
-      if (info->indexed)
+
+      if (apply_bias && likely(!(nvc0->vertex->instance_bufs & (1 << i))))
          data += info->index_bias * vb->stride;
 
       ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);
index cc83fbe771c1b71e95b8dee7fa2790930fcd882b..e5e43c0e7a5e604ee1d6a28fbde13ec19ac7f82a 100644 (file)
@@ -312,6 +312,7 @@ nvc0_render_condition(struct pipe_context *pipe,
 
    if (mode == PIPE_RENDER_COND_WAIT ||
        mode == PIPE_RENDER_COND_BY_REGION_WAIT) {
+      MARK_RING (chan, 5, 2);
       BEGIN_RING(chan, RING_3D_(NV84_SUBCHAN_QUERY_ADDRESS_HIGH), 4);
       OUT_RELOCh(chan, q->bo, q->offset, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
       OUT_RELOCl(chan, q->bo, q->offset, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
@@ -319,6 +320,7 @@ nvc0_render_condition(struct pipe_context *pipe,
       OUT_RING  (chan, 0x00001001);
    }
 
+   MARK_RING (chan, 4, 2);
    BEGIN_RING(chan, RING_3D(COND_ADDRESS_HIGH), 3);
    OUT_RELOCh(chan, q->bo, q->offset, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
    OUT_RELOCl(chan, q->bo, q->offset, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
index 17e79642a6d3003f5d6982065061cc2a77018c73..599823c0dc9b69b057943df44317a05910d81f67 100644 (file)
@@ -24,7 +24,8 @@ struct nvc0_context;
  * USER_MEMORY: resource->data is a pointer to client memory and may change
  *  between GL calls
  */
-#define NVC0_BUFFER_STATUS_DIRTY       (1 << 0)
+#define NVC0_BUFFER_STATUS_GPU_READING (1 << 0)
+#define NVC0_BUFFER_STATUS_GPU_WRITING (1 << 1)
 #define NVC0_BUFFER_STATUS_USER_MEMORY (1 << 7)
 
 /* Resources, if mapped into the GPU's address space, are guaranteed to
@@ -51,6 +52,9 @@ struct nvc0_resource {
    struct nvc0_mm_allocation *mm;
 };
 
+void
+nvc0_buffer_release_gpu_storage(struct nvc0_resource *);
+
 boolean
 nvc0_buffer_download(struct nvc0_context *, struct nvc0_resource *,
                      unsigned start, unsigned size);
@@ -87,7 +91,7 @@ nvc0_resource_map_offset(struct nvc0_context *nvc0,
    nvc0_buffer_adjust_score(nvc0, res, -250);
 
    if ((res->domain == NOUVEAU_BO_VRAM) &&
-       (res->status & NVC0_BUFFER_STATUS_DIRTY))
+       (res->status & NVC0_BUFFER_STATUS_GPU_WRITING))
       nvc0_buffer_download(nvc0, res, 0, res->base.width0);
 
    if ((res->domain != NOUVEAU_BO_GART) ||
index f608b32e1cb24f8b17539fe5cd903cdddb648805..f7f1fd09a12d4ea3113af328a2c822f5e8c22e8e 100644 (file)
@@ -75,6 +75,8 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
       return 10;
    case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
       return 13;
+   case PIPE_CAP_ARRAY_TEXTURES:
+      return 1;
    case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
    case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
    case PIPE_CAP_TEXTURE_SWIZZLE:
@@ -281,9 +283,6 @@ nvc0_magic_3d_init(struct nouveau_channel *chan)
    BEGIN_RING(chan, RING_3D_(0x074c), 1);
    OUT_RING  (chan, 0x3f);
 
-   BEGIN_RING(chan, RING_3D_(0x10f8), 1);
-   OUT_RING  (chan, 0x0101);
-
    BEGIN_RING(chan, RING_3D_(0x16a8), 1);
    OUT_RING  (chan, (3 << 16) | 3);
    BEGIN_RING(chan, RING_3D_(0x1794), 1);
@@ -476,7 +475,7 @@ nvc0_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
       OUT_RING  (chan, (15 << 4) | 1);
    }
 
-   screen->tls_size = 4 * 4 * 32 * 128 * 4;
+   screen->tls_size = (16 * 32) * (NVC0_CAP_MAX_PROGRAM_TEMPS * 16);
    ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17,
                         screen->tls_size, &screen->tls);
    if (ret)
@@ -490,6 +489,8 @@ nvc0_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
    OUT_RELOCl(chan, screen->tls, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
    OUT_RING  (chan, screen->tls_size >> 32);
    OUT_RING  (chan, screen->tls_size);
+   BEGIN_RING(chan, RING_3D_(0x07a0), 1);
+   OUT_RING  (chan, 0);
    BEGIN_RING(chan, RING_3D(LOCAL_BASE), 1);
    OUT_RING  (chan, 0);
 
@@ -532,16 +533,27 @@ nvc0_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
    BEGIN_RING(chan, RING_3D_(0x1590), 1); /* deactivate ZCULL */
    OUT_RING  (chan, 0x3f);
 
-   BEGIN_RING(chan, RING_3D(VIEWPORT_CLIP_RECTS_EN), 1);
+   BEGIN_RING(chan, RING_3D(CLIP_RECTS_MODE), 1);
+   OUT_RING  (chan, NVC0_3D_CLIP_RECTS_MODE_INSIDE_ANY);
+   BEGIN_RING(chan, RING_3D(CLIP_RECT_HORIZ(0)), 8 * 2);
+   for (i = 0; i < 8 * 2; ++i)
+      OUT_RING(chan, 0);
+   BEGIN_RING(chan, RING_3D(CLIP_RECTS_EN), 1);
    OUT_RING  (chan, 0);
    BEGIN_RING(chan, RING_3D(CLIPID_ENABLE), 1);
    OUT_RING  (chan, 0);
 
+   /* neither scissors, viewport nor stencil mask should affect clears */
+   BEGIN_RING(chan, RING_3D(CLEAR_FLAGS), 1);
+   OUT_RING  (chan, 0);
+
    BEGIN_RING(chan, RING_3D(VIEWPORT_TRANSFORM_EN), 1);
    OUT_RING  (chan, 1);
    BEGIN_RING(chan, RING_3D(DEPTH_RANGE_NEAR(0)), 2);
    OUT_RINGf (chan, 0.0f);
    OUT_RINGf (chan, 1.0f);
+   BEGIN_RING(chan, RING_3D(VIEW_VOLUME_CLIP_CTRL), 1);
+   OUT_RING  (chan, NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1);
 
    /* We use scissors instead of exact view volume clipping,
     * so they're always enabled.
@@ -628,11 +640,14 @@ nvc0_screen_make_buffers_resident(struct nvc0_screen *screen)
 
    const unsigned flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;
 
+   MARK_RING(chan, 5, 5);
    nouveau_bo_validate(chan, screen->text, flags);
    nouveau_bo_validate(chan, screen->uniforms, flags);
    nouveau_bo_validate(chan, screen->txc, flags);
-   nouveau_bo_validate(chan, screen->tls, flags);
    nouveau_bo_validate(chan, screen->mp_stack_bo, flags);
+
+   if (screen->cur_ctx && screen->cur_ctx->state.tls_required)
+      nouveau_bo_validate(chan, screen->tls, flags);
 }
 
 int
index 1fac142e2be588888f5db7ab2ba5a604570f7f31..d952ff1f9b13894ecc36fe046b01e389aff2c3a7 100644 (file)
@@ -128,17 +128,25 @@ nvc0_resource_validate(struct nvc0_resource *res, uint32_t flags)
 {
    struct nvc0_screen *screen = nvc0_screen(res->base.screen);
 
-   nouveau_bo_validate(screen->base.channel, res->bo, flags);
+   if (likely(res->bo)) {
+      nouveau_bo_validate(screen->base.channel, res->bo, flags);
 
-   nvc0_resource_fence(res, flags);
+      if (flags & NOUVEAU_BO_WR)
+         res->status |= NVC0_BUFFER_STATUS_GPU_WRITING;
+      if (flags & NOUVEAU_BO_RD)
+         res->status |= NVC0_BUFFER_STATUS_GPU_READING;
+
+      nvc0_resource_fence(res, flags);
+   }
 }
 
 
 boolean
 nvc0_screen_fence_new(struct nvc0_screen *, struct nvc0_fence **, boolean emit);
-
 void
 nvc0_screen_fence_next(struct nvc0_screen *);
+void
+nvc0_screen_fence_update(struct nvc0_screen *, boolean flushed);
 
 static INLINE boolean
 nvc0_screen_fence_emit(struct nvc0_screen *screen)
index 981b5488d088be36110265a5990c9d0403fb3859..357f8b80debb37647d8d9f60d86f680d0c3b50c5 100644 (file)
 
 #include "nvc0_context.h"
 
+static INLINE void
+nvc0_program_update_context_state(struct nvc0_context *nvc0,
+                                  struct nvc0_program *prog, int stage)
+{
+   if (prog->hdr[1])
+      nvc0->state.tls_required |= 1 << stage;
+   else
+      nvc0->state.tls_required &= ~(1 << stage);
+}
+
 static boolean
 nvc0_program_validate(struct nvc0_context *nvc0, struct nvc0_program *prog)
 {
@@ -55,7 +65,7 @@ nvc0_program_validate(struct nvc0_context *nvc0, struct nvc0_program *prog)
                          prog->code_base + NVC0_SHADER_HEADER_SIZE,
                          prog->code_size, prog->code);
 
-   BEGIN_RING(nvc0->screen->base.channel, RING_3D_(0x021c), 1);
+   BEGIN_RING(nvc0->screen->base.channel, RING_3D(MEM_BARRIER), 1);
    OUT_RING  (nvc0->screen->base.channel, 0x1111);
 
    return TRUE;
@@ -77,6 +87,7 @@ nvc0_vertprog_validate(struct nvc0_context *nvc0)
 
    if (!nvc0_program_validate(nvc0, vp))
          return;
+   nvc0_program_update_context_state(nvc0, vp, 0);
 
    BEGIN_RING(chan, RING_3D(SP_SELECT(1)), 2);
    OUT_RING  (chan, 0x11);
@@ -98,6 +109,7 @@ nvc0_fragprog_validate(struct nvc0_context *nvc0)
 
    if (!nvc0_program_validate(nvc0, fp))
          return;
+   nvc0_program_update_context_state(nvc0, fp, 4);
 
    BEGIN_RING(chan, RING_3D(EARLY_FRAGMENT_TESTS), 1);
    OUT_RING  (chan, fp->fp.early_z);
@@ -127,6 +139,7 @@ nvc0_tctlprog_validate(struct nvc0_context *nvc0)
    }
    if (!nvc0_program_validate(nvc0, tp))
          return;
+   nvc0_program_update_context_state(nvc0, tp, 1);
 
    BEGIN_RING(chan, RING_3D(SP_SELECT(2)), 2);
    OUT_RING  (chan, 0x21);
@@ -148,6 +161,7 @@ nvc0_tevlprog_validate(struct nvc0_context *nvc0)
    }
    if (!nvc0_program_validate(nvc0, tp))
          return;
+   nvc0_program_update_context_state(nvc0, tp, 2);
 
    BEGIN_RING(chan, RING_3D(TEP_SELECT), 1);
    OUT_RING  (chan, 0x31);
@@ -170,6 +184,7 @@ nvc0_gmtyprog_validate(struct nvc0_context *nvc0)
    }
    if (!nvc0_program_validate(nvc0, gp))
          return;
+   nvc0_program_update_context_state(nvc0, gp, 3);
 
    BEGIN_RING(chan, RING_3D(GP_SELECT), 1);
    OUT_RING  (chan, 0x41);
@@ -178,3 +193,59 @@ nvc0_gmtyprog_validate(struct nvc0_context *nvc0)
    BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(4)), 1);
    OUT_RING  (chan, gp->max_gpr);   
 }
+
+/* It's *is* kind of shader related. We need to inspect the program
+ * to get the output locations right.
+ */
+void
+nvc0_tfb_validate(struct nvc0_context *nvc0)
+{
+   struct nouveau_channel *chan = nvc0->screen->base.channel;
+   struct nvc0_program *vp;
+   struct nvc0_transform_feedback_state *tfb = nvc0->tfb;
+   int b;
+
+   BEGIN_RING(chan, RING_3D(TFB_ENABLE), 1);
+   if (!tfb) {
+      OUT_RING(chan, 0);
+      return;
+   }
+   OUT_RING(chan, 1);
+
+   vp = nvc0->vertprog ? nvc0->vertprog : nvc0->gmtyprog;
+
+   for (b = 0; b < nvc0->num_tfbbufs; ++b) {
+      uint8_t idx, var[128];
+      int i, n;
+      struct nvc0_resource *buf = nvc0_resource(nvc0->tfbbuf[b]);
+
+      BEGIN_RING(chan, RING_3D(TFB_BUFFER_ENABLE(b)), 5);
+      OUT_RING  (chan, 1);
+      OUT_RESRCh(chan, buf, nvc0->tfb_offset[b], NOUVEAU_BO_WR);
+      OUT_RESRCl(chan, buf, nvc0->tfb_offset[b], NOUVEAU_BO_WR);
+      OUT_RING  (chan, buf->base.width0 - nvc0->tfb_offset[b]);
+      OUT_RING  (chan, 0); /* TFB_PRIMITIVE_ID <- offset ? */
+
+      if (!(nvc0->dirty & NVC0_NEW_TFB))
+         continue;
+
+      BEGIN_RING(chan, RING_3D(TFB_UNK07X0(b)), 3);
+      OUT_RING  (chan, 0);
+      OUT_RING  (chan, tfb->varying_count[b]);
+      OUT_RING  (chan, tfb->stride[b]);
+
+      n = b ? tfb->varying_count[b - 1] : 0;
+      i = 0;
+      for (; i < tfb->varying_count[b]; ++i) {
+         idx = tfb->varying_index[n + i];
+         var[i] = vp->vp.out_pos[idx >> 2] + (idx & 3);
+      }
+      for (; i & 3; ++i)
+         var[i] = 0;
+
+      BEGIN_RING(chan, RING_3D(TFB_VARYING_LOCS(b, 0)), i / 4);
+      OUT_RINGp (chan, var, i / 4);
+   }
+   for (; b < 4; ++b)
+      IMMED_RING(chan, RING_3D(TFB_BUFFER_ENABLE(b)), 0);
+}
index c08f3693f5ea45c6b57a0c0e98712e7bb8929f9d..aa437195764dd8a37f51cad5d768c1345618fa91 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "pipe/p_defines.h"
 #include "util/u_inlines.h"
+#include "util/u_transfer.h"
 
 #include "tgsi/tgsi_parse.h"
 
@@ -50,40 +51,35 @@ nvc0_colormask(unsigned mask)
     return ret;
 }
 
+#define NVC0_BLEND_FACTOR_CASE(a, b) \
+   case PIPE_BLENDFACTOR_##a: return NV50_3D_BLEND_FACTOR_##b
+
 static INLINE uint32_t
 nvc0_blend_fac(unsigned factor)
 {
-    static const uint16_t bf[] = {
-        NV50_3D_BLEND_FACTOR_ZERO, /* 0x00 */
-        NV50_3D_BLEND_FACTOR_ONE,
-        NV50_3D_BLEND_FACTOR_SRC_COLOR,
-        NV50_3D_BLEND_FACTOR_SRC_ALPHA,
-        NV50_3D_BLEND_FACTOR_DST_ALPHA,
-        NV50_3D_BLEND_FACTOR_DST_COLOR,
-        NV50_3D_BLEND_FACTOR_SRC_ALPHA_SATURATE,
-        NV50_3D_BLEND_FACTOR_CONSTANT_COLOR,
-        NV50_3D_BLEND_FACTOR_CONSTANT_ALPHA,
-        NV50_3D_BLEND_FACTOR_SRC1_COLOR,
-        NV50_3D_BLEND_FACTOR_SRC1_ALPHA,
-        NV50_3D_BLEND_FACTOR_ZERO, /* 0x0b */
-        NV50_3D_BLEND_FACTOR_ZERO, /* 0x0c */
-        NV50_3D_BLEND_FACTOR_ZERO, /* 0x0d */
-        NV50_3D_BLEND_FACTOR_ZERO, /* 0x0e */
-        NV50_3D_BLEND_FACTOR_ZERO, /* 0x0f */
-        NV50_3D_BLEND_FACTOR_ZERO, /* 0x10 */
-        NV50_3D_BLEND_FACTOR_ZERO, /* 0x11 */
-        NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
-        NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
-        NV50_3D_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
-        NV50_3D_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
-        NV50_3D_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
-        NV50_3D_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA,
-        NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR,
-        NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA
-    };
-
-    assert(factor < (sizeof(bf) / sizeof(bf[0])));
-    return bf[factor];
+   switch (factor) {
+   NVC0_BLEND_FACTOR_CASE(ONE, ONE);
+   NVC0_BLEND_FACTOR_CASE(SRC_COLOR, SRC_COLOR);
+   NVC0_BLEND_FACTOR_CASE(SRC_ALPHA, SRC_ALPHA);
+   NVC0_BLEND_FACTOR_CASE(DST_ALPHA, DST_ALPHA);
+   NVC0_BLEND_FACTOR_CASE(DST_COLOR, DST_COLOR);
+   NVC0_BLEND_FACTOR_CASE(SRC_ALPHA_SATURATE, SRC_ALPHA_SATURATE);
+   NVC0_BLEND_FACTOR_CASE(CONST_COLOR, CONSTANT_COLOR);
+   NVC0_BLEND_FACTOR_CASE(CONST_ALPHA, CONSTANT_ALPHA);
+   NVC0_BLEND_FACTOR_CASE(SRC1_COLOR, SRC1_COLOR);
+   NVC0_BLEND_FACTOR_CASE(SRC1_ALPHA, SRC1_ALPHA);
+   NVC0_BLEND_FACTOR_CASE(ZERO, ZERO);
+   NVC0_BLEND_FACTOR_CASE(INV_SRC_COLOR, ONE_MINUS_SRC_COLOR);
+   NVC0_BLEND_FACTOR_CASE(INV_SRC_ALPHA, ONE_MINUS_SRC_ALPHA);
+   NVC0_BLEND_FACTOR_CASE(INV_DST_ALPHA, ONE_MINUS_DST_ALPHA);
+   NVC0_BLEND_FACTOR_CASE(INV_DST_COLOR, ONE_MINUS_DST_COLOR);
+   NVC0_BLEND_FACTOR_CASE(INV_CONST_COLOR, ONE_MINUS_CONSTANT_COLOR);
+   NVC0_BLEND_FACTOR_CASE(INV_CONST_ALPHA, ONE_MINUS_CONSTANT_ALPHA);
+   NVC0_BLEND_FACTOR_CASE(INV_SRC1_COLOR, ONE_MINUS_SRC1_COLOR);
+   NVC0_BLEND_FACTOR_CASE(INV_SRC1_ALPHA, ONE_MINUS_SRC1_ALPHA);
+   default:
+      return NV50_3D_BLEND_FACTOR_ZERO;
+   }
 }
 
 static void *
@@ -176,9 +172,9 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe,
         return NULL;
     so->pipe = *cso;
 
-#ifndef NVC0_SCISSORS_CLIPPING
-    SB_IMMED_3D(so, SCISSOR_ENABLE(0), cso->scissor);
-#endif
+    /* Scissor enables are handled in scissor state, we will not want to
+     * always emit 16 commands, one for each scissor rectangle, here.
+     */
     
     SB_BEGIN_3D(so, SHADE_MODEL, 1);
     SB_DATA    (so, cso->flatshade ? NVC0_3D_SHADE_MODEL_FLAT :
@@ -242,7 +238,7 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe,
         SB_BEGIN_3D(so, POLYGON_OFFSET_FACTOR, 1);
         SB_DATA    (so, fui(cso->offset_scale));
         SB_BEGIN_3D(so, POLYGON_OFFSET_UNITS, 1);
-        SB_DATA    (so, fui(cso->offset_units)); /* XXX: multiply by 2 ? */
+        SB_DATA    (so, fui(cso->offset_units * 2.0f));
     }
 
     assert(so->size < (sizeof(so->state) / sizeof(so->state[0])));
@@ -283,20 +279,21 @@ nvc0_zsa_state_create(struct pipe_context *pipe,
    }
 
    if (cso->stencil[0].enabled) {
-      SB_BEGIN_3D(so, STENCIL_FRONT_ENABLE, 5);
+      SB_BEGIN_3D(so, STENCIL_ENABLE, 5);
       SB_DATA    (so, 1);
       SB_DATA    (so, nvgl_stencil_op(cso->stencil[0].fail_op));
       SB_DATA    (so, nvgl_stencil_op(cso->stencil[0].zfail_op));
       SB_DATA    (so, nvgl_stencil_op(cso->stencil[0].zpass_op));
       SB_DATA    (so, nvgl_comparison_op(cso->stencil[0].func));
-      SB_BEGIN_3D(so, STENCIL_FRONT_MASK, 2);
-      SB_DATA    (so, cso->stencil[0].writemask);
+      SB_BEGIN_3D(so, STENCIL_FRONT_FUNC_MASK, 2);
       SB_DATA    (so, cso->stencil[0].valuemask);
+      SB_DATA    (so, cso->stencil[0].writemask);
    } else {
-      SB_IMMED_3D(so, STENCIL_FRONT_ENABLE, 0);
+      SB_IMMED_3D(so, STENCIL_ENABLE, 0);
    }
 
    if (cso->stencil[1].enabled) {
+      assert(cso->stencil[0].enabled);
       SB_BEGIN_3D(so, STENCIL_TWO_SIDE_ENABLE, 5);
       SB_DATA    (so, 1);
       SB_DATA    (so, nvgl_stencil_op(cso->stencil[1].fail_op));
@@ -306,7 +303,8 @@ nvc0_zsa_state_create(struct pipe_context *pipe,
       SB_BEGIN_3D(so, STENCIL_BACK_MASK, 2);
       SB_DATA    (so, cso->stencil[1].writemask);
       SB_DATA    (so, cso->stencil[1].valuemask);
-   } else {
+   } else
+   if (cso->stencil[0].enabled) {
       SB_IMMED_3D(so, STENCIL_TWO_SIDE_ENABLE, 0);
    }
     
@@ -808,6 +806,74 @@ nvc0_vertex_state_bind(struct pipe_context *pipe, void *hwcso)
     nvc0->dirty |= NVC0_NEW_VERTEX;
 }
 
+static void *
+nvc0_tfb_state_create(struct pipe_context *pipe,
+                      const struct pipe_stream_output_state *pso)
+{
+   struct nvc0_transform_feedback_state *so;
+   int n = 0;
+   int i, c, b;
+
+   so = MALLOC(sizeof(*so) + pso->num_outputs * 4 * sizeof(uint8_t));
+   if (!so)
+      return NULL;
+
+   for (b = 0; b < 4; ++b) {
+      for (i = 0; i < pso->num_outputs; ++i) {
+         if (pso->output_buffer[i] != b)
+            continue;
+         for (c = 0; c < 4; ++c) {
+            if (!(pso->register_mask[i] & (1 << c)))
+               continue;
+            so->varying_count[b]++;
+            so->varying_index[n++] = (pso->register_index[i] << 2) | c;
+         }
+      }
+      so->stride[b] = so->varying_count[b] * 4;
+   }
+   if (pso->stride)
+      so->stride[0] = pso->stride;
+
+   return so;
+}
+
+static void
+nvc0_tfb_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+   FREE(hwcso);
+}
+
+static void
+nvc0_tfb_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+   nvc0_context(pipe)->tfb = hwcso;
+   nvc0_context(pipe)->dirty |= NVC0_NEW_TFB;
+}
+
+static void
+nvc0_set_transform_feedback_buffers(struct pipe_context *pipe,
+                                    struct pipe_resource **buffers,
+                                    int *offsets,
+                                    int num_buffers)
+{
+   struct nvc0_context *nvc0 = nvc0_context(pipe);
+   int i;
+
+   assert(num_buffers >= 0 && num_buffers <= 4); /* why signed ? */
+
+   for (i = 0; i < num_buffers; ++i) {
+       assert(offsets[i] >= 0);
+       nvc0->tfb_offset[i] = offsets[i];
+       pipe_resource_reference(&nvc0->tfbbuf[i], buffers[i]);
+   }
+   for (; i < nvc0->num_tfbbufs; ++i)
+      pipe_resource_reference(&nvc0->tfbbuf[i], NULL);
+
+   nvc0->num_tfbbufs = num_buffers;
+
+   nvc0->dirty |= NVC0_NEW_TFB_BUFFERS;
+}
+
 void
 nvc0_init_state_functions(struct nvc0_context *nvc0)
 {
@@ -861,5 +927,12 @@ nvc0_init_state_functions(struct nvc0_context *nvc0)
 
     nvc0->pipe.set_vertex_buffers = nvc0_set_vertex_buffers;
     nvc0->pipe.set_index_buffer = nvc0_set_index_buffer;
+
+    nvc0->pipe.create_stream_output_state = nvc0_tfb_state_create;
+    nvc0->pipe.delete_stream_output_state = nvc0_tfb_state_delete;
+    nvc0->pipe.bind_stream_output_state = nvc0_tfb_state_bind;
+    nvc0->pipe.set_stream_output_buffers = nvc0_set_transform_feedback_buffers;
+
+    nvc0->pipe.redefine_user_buffer = u_default_redefine_user_buffer;
 }
 
index 25aec0244db5270134574562229965c53c517d87..70c418fad9b6706f1f6eaa2a4c96201578929f72 100644 (file)
@@ -25,6 +25,7 @@ nvc0_validate_zcull(struct nvc0_context *nvc0)
     else
        width = fb->width;
 
+    MARK_RING (chan, 23, 4);
     BEGIN_RING(chan, RING_3D_(0x1590), 1); /* ZCULL_REGION_INDEX (bits 0x3f) */
     OUT_RING  (chan, 0);
     BEGIN_RING(chan, RING_3D_(0x07e8), 2); /* ZCULL_ADDRESS_A_HIGH */
@@ -57,6 +58,7 @@ nvc0_validate_fb(struct nvc0_context *nvc0)
     struct nouveau_channel *chan = nvc0->screen->base.channel;
     struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
     unsigned i;
+    boolean serialize = FALSE;
 
     nvc0_bufctx_reset(nvc0, NVC0_BUFCTX_FRAME);
 
@@ -66,12 +68,14 @@ nvc0_validate_fb(struct nvc0_context *nvc0)
     OUT_RING  (chan, fb->width << 16);
     OUT_RING  (chan, fb->height << 16);
 
+    MARK_RING(chan, 9 * fb->nr_cbufs, 2 * fb->nr_cbufs);
+
     for (i = 0; i < fb->nr_cbufs; ++i) {
         struct nvc0_miptree *mt = nvc0_miptree(fb->cbufs[i]->texture);
         struct nvc0_surface *sf = nvc0_surface(fb->cbufs[i]);
         struct nouveau_bo *bo = mt->base.bo;
         uint32_t offset = sf->offset;
-        
+
         BEGIN_RING(chan, RING_3D(RT_ADDRESS_HIGH(i)), 8);
         OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
         OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
@@ -83,6 +87,11 @@ nvc0_validate_fb(struct nvc0_context *nvc0)
         OUT_RING  (chan, sf->depth);
         OUT_RING  (chan, mt->layer_stride >> 2);
 
+        if (mt->base.status & NVC0_BUFFER_STATUS_GPU_READING)
+           serialize = TRUE;
+        mt->base.status |=  NVC0_BUFFER_STATUS_GPU_WRITING;
+        mt->base.status &= ~NVC0_BUFFER_STATUS_GPU_READING;
+
         nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_FRAME, &mt->base,
                                  NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
     }
@@ -93,7 +102,8 @@ nvc0_validate_fb(struct nvc0_context *nvc0)
         struct nouveau_bo *bo = mt->base.bo;
         int unk = mt->base.base.target == PIPE_TEXTURE_2D;
         uint32_t offset = sf->offset;
-        
+
+        MARK_RING (chan, 12, 2);
         BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5);
         OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
         OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
@@ -107,6 +117,11 @@ nvc0_validate_fb(struct nvc0_context *nvc0)
         OUT_RING  (chan, sf->height);
         OUT_RING  (chan, (unk << 16) | sf->depth);
 
+        if (mt->base.status & NVC0_BUFFER_STATUS_GPU_READING)
+           serialize = TRUE;
+        mt->base.status |=  NVC0_BUFFER_STATUS_GPU_WRITING;
+        mt->base.status &= ~NVC0_BUFFER_STATUS_GPU_READING;
+
         nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_FRAME, &mt->base,
                                  NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
     } else {
@@ -114,11 +129,10 @@ nvc0_validate_fb(struct nvc0_context *nvc0)
         OUT_RING  (chan, 0);
     }
 
-#ifndef NVC0_SCISSORS_CLIPPING
-    BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
-    OUT_RING  (chan, fb->width << 16);
-    OUT_RING  (chan, fb->height << 16);
-#endif
+    if (serialize) {
+       BEGIN_RING(chan, RING_3D(SERIALIZE), 1);
+       OUT_RING  (chan, 0);
+    }
 }
 
 static void
@@ -160,65 +174,54 @@ nvc0_validate_scissor(struct nvc0_context *nvc0)
 {
     struct nouveau_channel *chan = nvc0->screen->base.channel;
     struct pipe_scissor_state *s = &nvc0->scissor;
-#ifdef NVC0_SCISSORS_CLIPPING
-    struct pipe_viewport_state *vp = &nvc0->viewport;
-    int minx, maxx, miny, maxy;
 
-    if (!(nvc0->dirty &
-          (NVC0_NEW_SCISSOR | NVC0_NEW_VIEWPORT | NVC0_NEW_FRAMEBUFFER)) &&
-        nvc0->state.scissor == nvc0->rast->pipe.scissor)
+    if (!(nvc0->dirty & NVC0_NEW_SCISSOR) &&
+        nvc0->rast->pipe.scissor == nvc0->state.scissor)
        return;
     nvc0->state.scissor = nvc0->rast->pipe.scissor;
 
-    if (nvc0->state.scissor) {
-       minx = s->minx;
-       maxx = s->maxx;
-       miny = s->miny;
-       maxy = s->maxy;
+    BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2);
+    if (nvc0->rast->pipe.scissor) {
+       OUT_RING(chan, (s->maxx << 16) | s->minx);
+       OUT_RING(chan, (s->maxy << 16) | s->miny);
     } else {
-       minx = 0;
-       maxx = nvc0->framebuffer.width;
-       miny = 0;
-       maxy = nvc0->framebuffer.height;
+       OUT_RING(chan, (0xffff << 16) | 0);
+       OUT_RING(chan, (0xffff << 16) | 0);
     }
-
-    minx = MAX2(minx, (int)(vp->translate[0] - fabsf(vp->scale[0])));
-    maxx = MIN2(maxx, (int)(vp->translate[0] + fabsf(vp->scale[0])));
-    miny = MAX2(miny, (int)(vp->translate[1] - fabsf(vp->scale[1])));
-    maxy = MIN2(maxy, (int)(vp->translate[1] + fabsf(vp->scale[1])));
-
-    BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2);
-    OUT_RING  (chan, (maxx << 16) | minx);
-    OUT_RING  (chan, (maxy << 16) | miny);
-    BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
-    OUT_RING  (chan, ((maxx - minx) << 16) | minx);
-    OUT_RING  (chan, ((maxy - miny) << 16) | miny);
-#else
-    BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2);
-    OUT_RING  (chan, (s->maxx << 16) | s->minx);
-    OUT_RING  (chan, (s->maxy << 16) | s->miny);
-#endif
 }
 
 static void
 nvc0_validate_viewport(struct nvc0_context *nvc0)
 {
     struct nouveau_channel *chan = nvc0->screen->base.channel;
+    struct pipe_viewport_state *vp = &nvc0->viewport;
+    int x, y, w, h;
+    float zmin, zmax;
 
     BEGIN_RING(chan, RING_3D(VIEWPORT_TRANSLATE_X(0)), 3);
-    OUT_RINGf (chan, nvc0->viewport.translate[0]);
-    OUT_RINGf (chan, nvc0->viewport.translate[1]);
-    OUT_RINGf (chan, nvc0->viewport.translate[2]);
+    OUT_RINGf (chan, vp->translate[0]);
+    OUT_RINGf (chan, vp->translate[1]);
+    OUT_RINGf (chan, vp->translate[2]);
     BEGIN_RING(chan, RING_3D(VIEWPORT_SCALE_X(0)), 3);
-    OUT_RINGf (chan, nvc0->viewport.scale[0]);
-    OUT_RINGf (chan, nvc0->viewport.scale[1]);
-    OUT_RINGf (chan, nvc0->viewport.scale[2]);
+    OUT_RINGf (chan, vp->scale[0]);
+    OUT_RINGf (chan, vp->scale[1]);
+    OUT_RINGf (chan, vp->scale[2]);
 
-#ifdef NVC0_SCISSORS_CLIPPING
+    /* now set the viewport rectangle to viewport dimensions for clipping */
+
+    x = (int)(vp->translate[0] - fabsf(vp->scale[0]));
+    y = (int)(vp->translate[1] - fabsf(vp->scale[1]));
+    w = (int)fabsf(2.0f * vp->scale[0]);
+    h = (int)fabsf(2.0f * vp->scale[1]);
+    zmin = vp->translate[2] - fabsf(vp->scale[2]);
+    zmax = vp->translate[2] + fabsf(vp->scale[2]);
+
+    BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
+    OUT_RING  (chan, (w << 16) | x);
+    OUT_RING  (chan, (h << 16) | y);
     BEGIN_RING(chan, RING_3D(DEPTH_RANGE_NEAR(0)), 2);
-    OUT_RINGf (chan, nvc0->viewport.translate[2] - nvc0->viewport.scale[2]);
-    OUT_RINGf (chan, nvc0->viewport.translate[2] + nvc0->viewport.scale[2]);
-#endif
+    OUT_RINGf (chan, zmin);
+    OUT_RINGf (chan, zmax);
 }
 
 static void
@@ -227,10 +230,15 @@ nvc0_validate_clip(struct nvc0_context *nvc0)
    struct nouveau_channel *chan = nvc0->screen->base.channel;
    uint32_t clip;
 
-   clip = nvc0->clip.depth_clamp ? 0x201a : 0x0002;
-#ifndef NVC0_SCISSORS_CLIPPING
-   clip |= 0x1080;
-#endif
+   if (nvc0->clip.depth_clamp) {
+      clip =
+         NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1 |
+         NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR |
+         NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR |
+         NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK2;
+   } else {
+      clip = NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1;
+   }
 
    BEGIN_RING(chan, RING_3D(VIEW_VOLUME_CLIP_CTRL), 1);
    OUT_RING  (chan, clip);
@@ -238,6 +246,7 @@ nvc0_validate_clip(struct nvc0_context *nvc0)
    if (nvc0->clip.nr) {
       struct nouveau_bo *bo = nvc0->screen->uniforms;
 
+      MARK_RING (chan, 6 + nvc0->clip.nr * 4, 2);
       BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
       OUT_RING  (chan, 256);
       OUT_RELOCh(chan, bo, 5 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
@@ -280,6 +289,32 @@ nvc0_validate_rasterizer(struct nvc0_context *nvc0)
    OUT_RINGp(chan, nvc0->rast->state, nvc0->rast->size);
 }
 
+static void
+nvc0_validate_sprite_coords(struct nvc0_context *nvc0)
+{
+   struct nouveau_channel *chan = nvc0->screen->base.channel;
+   uint32_t reg;
+
+   if (nvc0->rast->pipe.sprite_coord_mode == PIPE_SPRITE_COORD_UPPER_LEFT)
+      reg = NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_UPPER_LEFT;
+   else
+      reg = NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_LOWER_LEFT;
+
+   if (nvc0->rast->pipe.point_quad_rasterization) {
+      uint32_t en = nvc0->rast->pipe.sprite_coord_enable;
+
+      while (en) {
+         int i = ffs(en) - 1;
+         en &= ~(1 << i);
+         if (i >= 0 && i < 8)
+            reg |= 8 << i;
+      }
+   }
+
+   BEGIN_RING(chan, RING_3D(POINT_COORD_REPLACE), 1);
+   OUT_RING  (chan, reg);
+}
+
 static void
 nvc0_constbufs_validate(struct nvc0_context *nvc0)
 {
@@ -340,6 +375,7 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0)
                                      NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
 
          if (rebind) {
+            MARK_RING (chan, 4, 2);
             BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
             OUT_RING  (chan, align(res->base.width0, 0x100));
             OUT_RELOCh(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
@@ -357,6 +393,7 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0)
             }
             nr = MIN2(MIN2(nr - 6, words), NV04_PFIFO_MAX_PACKET_LEN - 1);
 
+            MARK_RING (chan, nr + 5, 2);
             BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
             OUT_RING  (chan, align(res->base.width0, 0x100));
             OUT_RELOCh(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
@@ -383,13 +420,7 @@ static struct state_validate {
     { nvc0_validate_blend_colour,  NVC0_NEW_BLEND_COLOUR },
     { nvc0_validate_stencil_ref,   NVC0_NEW_STENCIL_REF },
     { nvc0_validate_stipple,       NVC0_NEW_STIPPLE },
-#ifdef NVC0_SCISSORS_CLIPPING
-    { nvc0_validate_scissor,       NVC0_NEW_SCISSOR | NVC0_NEW_VIEWPORT |
-                                   NVC0_NEW_RASTERIZER |
-                                   NVC0_NEW_FRAMEBUFFER },
-#else
-    { nvc0_validate_scissor,       NVC0_NEW_SCISSOR },
-#endif
+    { nvc0_validate_scissor,       NVC0_NEW_SCISSOR | NVC0_NEW_RASTERIZER },
     { nvc0_validate_viewport,      NVC0_NEW_VIEWPORT },
     { nvc0_validate_clip,          NVC0_NEW_CLIP },
     { nvc0_vertprog_validate,      NVC0_NEW_VERTPROG },
@@ -397,10 +428,12 @@ static struct state_validate {
     { nvc0_tevlprog_validate,      NVC0_NEW_TEVLPROG },
     { nvc0_gmtyprog_validate,      NVC0_NEW_GMTYPROG },
     { nvc0_fragprog_validate,      NVC0_NEW_FRAGPROG },
+    { nvc0_validate_sprite_coords, NVC0_NEW_RASTERIZER | NVC0_NEW_FRAGPROG },
     { nvc0_constbufs_validate,     NVC0_NEW_CONSTBUF },
     { nvc0_validate_textures,      NVC0_NEW_TEXTURES },
     { nvc0_validate_samplers,      NVC0_NEW_SAMPLERS },
-    { nvc0_vertex_arrays_validate, NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS }
+    { nvc0_vertex_arrays_validate, NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS },
+    { nvc0_tfb_validate,           NVC0_NEW_TFB | NVC0_NEW_TFB_BUFFERS }
 };
 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
 
index 6c8028aba13a0d5c3cf6b542ffc53ceccec32ded..57566128ab5ab8fbe423bb336b119e80cf119a52 100644 (file)
@@ -4,8 +4,6 @@
 
 #include "pipe/p_state.h"
 
-#define NVC0_SCISSORS_CLIPPING
-
 #define SB_BEGIN_3D(so, m, s)                                                  \
    (so)->state[(so)->size++] =                                                 \
       (0x2 << 28) | ((s) << 16) | (NVC0_SUBCH_3D << 13) | ((NVC0_3D_##m) >> 2)
@@ -67,16 +65,17 @@ struct nvc0_vertex_stateobj {
    unsigned num_elements;
    uint32_t instance_elts;
    uint32_t instance_bufs;
+   boolean need_conversion; /* e.g. VFETCH cannot convert f64 to f32 */
    unsigned vtx_size;
    unsigned vtx_per_packet_max;
-   struct nvc0_vertex_element element[1];
+   struct nvc0_vertex_element element[0];
 };
 
 /* will have to lookup index -> location qualifier from nvc0_program */
-struct nvc0_tfb_state {
-   uint8_t varying_count[4];
+struct nvc0_transform_feedback_state {
    uint32_t stride[4];
-   uint8_t varying_indices[1];
+   uint8_t varying_count[4];
+   uint8_t varying_index[0];
 };
 
 #endif
index cc0a65687dc3b2214c1635e3f7b3605e06518ee0..8898bc733a36a3c6ac4826e206bd5c679c179533 100644 (file)
 
 #include "nv50_defs.xml.h"
 
+#define NVC0_ENG2D_SUPPORTED_FORMATS 0xff9ccfe1cce3ccc9ULL
+
 /* return TRUE for formats that can be converted among each other by NVC0_2D */
 static INLINE boolean
 nvc0_2d_format_faithful(enum pipe_format format)
 {
-   switch (format) {
-   case PIPE_FORMAT_B8G8R8A8_UNORM:
-   case PIPE_FORMAT_B8G8R8X8_UNORM:
-   case PIPE_FORMAT_B8G8R8A8_SRGB:
-   case PIPE_FORMAT_B8G8R8X8_SRGB:
-   case PIPE_FORMAT_B5G6R5_UNORM:
-   case PIPE_FORMAT_B5G5R5A1_UNORM:
-   case PIPE_FORMAT_B10G10R10A2_UNORM:
-   case PIPE_FORMAT_R8_UNORM:
-   case PIPE_FORMAT_R32G32B32A32_FLOAT:
-   case PIPE_FORMAT_R32G32B32_FLOAT:
-      return TRUE;
-   default:
-      return FALSE;
-   }
+   uint8_t id = nvc0_format_table[format].rt;
+
+   return (id >= 0xc0) && (NVC0_ENG2D_SUPPORTED_FORMATS & (1ULL << (id - 0xc0)));
 }
 
 static INLINE uint8_t
@@ -62,7 +52,7 @@ nvc0_2d_format(enum pipe_format format)
    /* Hardware values for color formats range from 0xc0 to 0xff,
     * but the 2D engine doesn't support all of them.
     */
-   if ((id >= 0xc0) && (0xff0843e080608409ULL & (1ULL << (id - 0xc0))))
+   if (nvc0_2d_format_faithful(format))
       return id;
 
    switch (util_format_get_blocksize(format)) {
@@ -72,6 +62,10 @@ nvc0_2d_format(enum pipe_format format)
       return NV50_SURFACE_FORMAT_R16_UNORM;
    case 4:
       return NV50_SURFACE_FORMAT_A8R8G8B8_UNORM;
+   case 8:
+      return NV50_SURFACE_FORMAT_R16G16B16A16_UNORM;
+   case 16:
+      return NV50_SURFACE_FORMAT_R32G32B32A32_FLOAT;
    default:
       return 0;
    }
@@ -249,15 +243,16 @@ nvc0_clear_render_target(struct pipe_context *pipe,
        OUT_RING  (chan, 1);
        OUT_RING  (chan, 0);
 
-       /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */
-
-       BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
-       OUT_RING  (chan, (width << 16) | dstx);
-       OUT_RING  (chan, (height << 16) | dsty);
+       BEGIN_RING(chan, RING_3D(CLIP_RECT_HORIZ(0)), 2);
+       OUT_RING  (chan, ((dstx + width) << 16) | dstx);
+       OUT_RING  (chan, ((dsty + height) << 16) | dsty);
+       IMMED_RING(chan, RING_3D(CLIP_RECTS_EN), 1);
 
        BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
        OUT_RING  (chan, 0x3c);
 
+       IMMED_RING(chan, RING_3D(CLIP_RECTS_EN), 0);
+
        nv50->dirty |= NVC0_NEW_FRAMEBUFFER;
 }
 
@@ -306,13 +301,16 @@ nvc0_clear_depth_stencil(struct pipe_context *pipe,
        OUT_RING  (chan, sf->height);
        OUT_RING  (chan, (1 << 16) | 1);
 
-       BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
-       OUT_RING  (chan, (width << 16) | dstx);
-       OUT_RING  (chan, (height << 16) | dsty);
+       BEGIN_RING(chan, RING_3D(CLIP_RECT_HORIZ(0)), 2);
+       OUT_RING  (chan, ((dstx + width) << 16) | dstx);
+       OUT_RING  (chan, ((dsty + height) << 16) | dsty);
+       IMMED_RING(chan, RING_3D(CLIP_RECTS_EN), 1);
 
        BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
        OUT_RING  (chan, mode);
 
+       IMMED_RING(chan, RING_3D(CLIP_RECTS_EN), 0);
+
        nv50->dirty |= NVC0_NEW_FRAMEBUFFER;
 }
 
index b219f82c903cf504e54e1d723b1154a3c862a57f..968558a5869d12ac27f922af40aeb28e5a931655 100644 (file)
@@ -196,9 +196,16 @@ nvc0_validate_tic(struct nvc0_context *nvc0, int s)
          OUT_RINGp (chan, &tic->tic[3], 5);
 
          need_flush = TRUE;
+      } else
+      if (res->status & NVC0_BUFFER_STATUS_GPU_WRITING) {
+         BEGIN_RING(chan, RING_3D(TEX_CACHE_CTL), 1);
+         OUT_RING  (chan, (tic->id << 4) | 1);
       }
       nvc0->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32);
 
+      res->status &= ~NVC0_BUFFER_STATUS_GPU_WRITING;
+      res->status |=  NVC0_BUFFER_STATUS_GPU_READING;
+
       nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_TEXTURES, res,
                                NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
 
index 950bee2eda46c49812e67d2cd0f9290c95fd093e..a44d330c7319d106d85609afdde2c377c3dfb991 100644 (file)
@@ -63,7 +63,13 @@ bld_register_access(struct bld_register *reg, unsigned i)
 static INLINE void
 bld_register_add_val(struct bld_register *reg, struct nv_value *val)
 {
-   util_dynarray_append(&reg->vals, struct nv_value *, val);
+   struct nv_basic_block *bb = val->insn->bb;
+
+   if (reg->vals.size &&
+       (util_dynarray_top(&reg->vals, struct nv_value *))->insn->bb == bb)
+      *(util_dynarray_top_ptr(&reg->vals, struct nv_value *)) = val;
+   else
+      util_dynarray_append(&reg->vals, struct nv_value *, val);
 }
 
 static INLINE boolean
@@ -127,13 +133,10 @@ struct bld_context {
 static INLINE ubyte
 bld_register_file(struct bld_context *bld, struct bld_register *reg)
 {
-   if (reg < &bld->avs[0][0]) return NV_FILE_GPR;
-   else
-   if (reg < &bld->pvs[0][0]) return NV_FILE_GPR;
-   else
-   if (reg < &bld->ovs[0][0]) return NV_FILE_PRED;
-   else
-      return NV_FILE_MEM_V;
+   if (reg >= &bld->pvs[0][0] &&
+       reg <  &bld->ovs[0][0])
+      return NV_FILE_PRED;
+   return NV_FILE_GPR;
 }
 
 static INLINE struct nv_value *
@@ -361,6 +364,9 @@ bld_loop_phi(struct bld_context *bld, struct bld_register *reg,
    struct nv_basic_block *bb = bld->pc->current_block;
    struct nv_value *val = NULL;
 
+   if (bld->ti->require_stores) /* XXX: actually only for INDEXABLE_TEMP */
+      return NULL;
+
    if (bld->loop_lvl > 1) {
       --bld->loop_lvl;
       if (!((reg->loop_def | reg->loop_use) & (1 << bld->loop_lvl)))
@@ -459,6 +465,7 @@ bld_loop_end(struct bld_context *bld, struct nv_basic_block *bb)
       reg = (struct bld_register *)phi->target;
       phi->target = NULL;
 
+      /* start with s == 1, src[0] is from outside the loop */
       for (s = 1, n = 0; n < bb->num_in; ++n) {
          if (bb->in_kind[n] != CFG_EDGE_BACK)
             continue;
@@ -470,8 +477,11 @@ bld_loop_end(struct bld_context *bld, struct nv_basic_block *bb)
          for (i = 0; i < 4; ++i)
             if (phi->src[i] && phi->src[i]->value == val)
                break;
-         if (i == 4)
+         if (i == 4) {
+            /* skip values we do not want to replace */
+            for (; phi->src[s] && phi->src[s]->value != phi->def[0]; ++s);
             nv_reference(bld->pc, phi, s++, val);
+         }
       }
       bld->pc->current_block = save;
 
@@ -563,11 +573,12 @@ bld_lmem_store(struct bld_context *bld, struct nv_value *ptr, int ofst,
 
    loc = new_value(bld->pc, NV_FILE_MEM_L, nv_type_sizeof(NV_TYPE_U32));
 
-   loc->reg.id = ofst * 4;
+   loc->reg.address = ofst * 4;
 
    nv_reference(bld->pc, insn, 0, loc);
-   nv_reference(bld->pc, insn, 1, ptr);
-   nv_reference(bld->pc, insn, 2, val);
+   nv_reference(bld->pc, insn, 1, val);
+   if (ptr)
+      bld_src_pointer(bld, insn, 2, ptr);
 }
 
 static struct nv_value *
@@ -579,7 +590,9 @@ bld_lmem_load(struct bld_context *bld, struct nv_value *ptr, int ofst)
 
    loc->reg.address = ofst * 4;
 
-   val = bld_insn_2(bld, NV_OP_LD, loc, ptr);
+   val = bld_insn_1(bld, NV_OP_LD, loc);
+   if (ptr)
+      bld_src_pointer(bld, val->insn, 1, ptr);
 
    return val;
 }
@@ -650,7 +663,7 @@ bld_kil(struct bld_context *bld, struct nv_value *src)
 
 static void
 bld_flow(struct bld_context *bld, uint opcode,
-         struct nv_value *src, struct nv_basic_block *target,
+         struct nv_value *pred, uint8_t cc, struct nv_basic_block *target,
          boolean reconverge)
 {
    struct nv_instruction *nvi;
@@ -661,8 +674,10 @@ bld_flow(struct bld_context *bld, uint opcode,
    nvi = new_instruction(bld->pc, opcode);
    nvi->target = target;
    nvi->terminator = 1;
-   if (src)
-      bld_src_predicate(bld, nvi, 0, src);
+   if (pred) {
+      nvi->cc = cc;
+      bld_src_predicate(bld, nvi, 0, pred);
+   }
 }
 
 static ubyte
@@ -878,11 +893,10 @@ emit_store(struct bld_context *bld, const struct tgsi_full_instruction *inst,
       break;
    case TGSI_FILE_TEMPORARY:
       assert(idx < BLD_MAX_TEMPS);
-      if (!res->insn)
+      if (!res->insn || res->insn->bb != bld->pc->current_block)
          res = bld_insn_1(bld, NV_OP_MOV, res);
 
       assert(res->reg.file == NV_FILE_GPR);
-      assert(res->insn->bb = bld->pc->current_block);
 
       if (bld->ti->require_stores)
          bld_lmem_store(bld, ptr, idx * 4 + chan, res);
@@ -978,14 +992,6 @@ bld_new_block(struct bld_context *bld, struct nv_basic_block *b)
    bld->out_kind = CFG_EDGE_FORWARD;
 }
 
-static struct nv_value *
-bld_get_saved_input(struct bld_context *bld, unsigned i, unsigned c)
-{
-   if (bld->saved_inputs[i][c])
-      return bld->saved_inputs[i][c];
-   return NULL;
-}
-
 static struct nv_value *
 bld_interp(struct bld_context *bld, unsigned mode, struct nv_value *val)
 {
@@ -1053,9 +1059,9 @@ emit_fetch(struct bld_context *bld, const struct tgsi_full_instruction *insn,
    case TGSI_FILE_INPUT:
       assert(!src->Register.Dimension);
       if (!ptr) {
-         res = bld_get_saved_input(bld, idx, swz);
+         res = bld->saved_inputs[idx][swz];
          if (res)
-            return res;
+            break;
       }
       res = new_value(bld->pc, bld->ti->input_file, 4);
       if (ptr)
@@ -1173,7 +1179,7 @@ static INLINE void
 describe_texture_target(unsigned target, int *dim,
                         int *array, int *cube, int *shadow)
 {
-   *array = *cube = *shadow = 0;
+   *dim = *array = *cube = *shadow = 0;
 
    switch (target) {
    case TGSI_TEXTURE_1D:
@@ -1199,11 +1205,6 @@ describe_texture_target(unsigned target, int *dim,
       *dim = 2;
       *cube = 1;
       break;
-      /*
-   case TGSI_TEXTURE_CUBE_ARRAY:
-      *dim = 2;
-      *cube = *array = 1;
-      break;
    case TGSI_TEXTURE_1D_ARRAY:
       *dim = *array = 1;
       break;
@@ -1211,6 +1212,7 @@ describe_texture_target(unsigned target, int *dim,
       *dim = 2;
       *array = 1;
       break;
+      /*
    case TGSI_TEXTURE_SHADOW1D_ARRAY:
       *dim = *array = *shadow = 1;
       break;
@@ -1220,7 +1222,7 @@ describe_texture_target(unsigned target, int *dim,
       break;
    case TGSI_TEXTURE_CUBE_ARRAY:
       *dim = 2;
-      *array = *cube = 1;
+      *cube = *array = 1;
       break;
       */
    default:
@@ -1338,10 +1340,6 @@ emit_tex(struct bld_context *bld, uint opcode, int tic, int tsc,
    if (array)
       arg[dim] = bld_cvt(bld, NV_TYPE_U32, NV_TYPE_F32, arg[dim]);
 
-   /* ensure that all inputs reside in a GPR */
-   for (c = 0; c < dim + array + cube + shadow; ++c)
-      (src[c] = bld_insn_1(bld, NV_OP_MOV, arg[c]))->insn->fixed = 1;
-
    /* bind { layer x y z } and { lod/bias shadow } to adjacent regs */
 
    bnd = new_instruction(bld->pc, NV_OP_BIND);
@@ -1383,21 +1381,12 @@ emit_tex(struct bld_context *bld, uint opcode, int tic, int tsc,
    nvi->tex_dim = dim;
    nvi->tex_cube = cube;
    nvi->tex_shadow = shadow;
+   nvi->tex_array = array;
    nvi->tex_live = 0;
 
    return nvi;
 }
 
-/*
-static boolean
-bld_is_constant(struct nv_value *val)
-{
-   if (val->reg.file == NV_FILE_IMM)
-      return TRUE;
-   return val->insn && nvCG_find_constant(val->insn->src[0]);
-}
-*/
-
 static void
 bld_tex(struct bld_context *bld, struct nv_value *dst0[4],
         const struct tgsi_full_instruction *insn)
@@ -1413,7 +1402,7 @@ bld_tex(struct bld_context *bld, struct nv_value *dst0[4],
 
    assert(dim + array + shadow + lodbias <= 5);
 
-   if (!cube && insn->Instruction.Opcode == TGSI_OPCODE_TXP)
+   if (!cube && !array && insn->Instruction.Opcode == TGSI_OPCODE_TXP)
       load_proj_tex_coords(bld, t, dim, shadow, insn);
    else {
       for (c = 0; c < dim + cube + array; ++c)
@@ -1504,10 +1493,10 @@ bld_instruction(struct bld_context *bld,
    case TGSI_OPCODE_CMP:
       FOR_EACH_DST0_ENABLED_CHANNEL(c, insn) {
          src0 = emit_fetch(bld, insn, 0, c);
-         src0 = bld_setp(bld, NV_OP_SET_F32, NV_CC_LT, src0, bld->zero);
          src1 = emit_fetch(bld, insn, 1, c);
          src2 = emit_fetch(bld, insn, 2, c);
-         dst0[c] = bld_insn_3(bld, NV_OP_SELP, src1, src2, src0);
+         dst0[c] = bld_insn_3(bld, NV_OP_SLCT_F32, src1, src2, src0);
+         dst0[c]->insn->set_cond = NV_CC_LT;
       }
       break;
    case TGSI_OPCODE_COS:
@@ -1601,6 +1590,7 @@ bld_instruction(struct bld_context *bld,
    case TGSI_OPCODE_IF:
    {
       struct nv_basic_block *b = new_basic_block(bld->pc);
+      struct nv_value *pred = emit_fetch(bld, insn, 0, 0);
 
       assert(bld->cond_lvl < BLD_MAX_COND_NESTING);
 
@@ -1609,10 +1599,19 @@ bld_instruction(struct bld_context *bld,
       bld->join_bb[bld->cond_lvl] = bld->pc->current_block;
       bld->cond_bb[bld->cond_lvl] = bld->pc->current_block;
 
-      src1 = bld_setp(bld, NV_OP_SET_U32, NV_CC_EQ,
-                      emit_fetch(bld, insn, 0, 0), bld->zero);
+      if (pred->insn && NV_BASEOP(pred->insn->opcode) == NV_OP_SET) {
+         pred = bld_clone(bld, pred->insn);
+         pred->reg.size = 1;
+         pred->reg.file = NV_FILE_PRED;
+         if (pred->insn->opcode == NV_OP_FSET_F32)
+            pred->insn->opcode = NV_OP_SET_F32;
+      } else {
+         pred = bld_setp(bld, NV_OP_SET_U32, NV_CC_NE | NV_CC_U,
+                         pred, bld->zero);
+      }
+      assert(!mask);
 
-      bld_flow(bld, NV_OP_BRA, src1, NULL, (bld->cond_lvl == 0));
+      bld_flow(bld, NV_OP_BRA, pred, NV_CC_NOT_P, NULL, (bld->cond_lvl == 0));
 
       ++bld->cond_lvl;
       bld_new_block(bld, b);
@@ -1638,6 +1637,10 @@ bld_instruction(struct bld_context *bld,
    {
       struct nv_basic_block *b = new_basic_block(bld->pc);
 
+      if (bld->pc->current_block->exit &&
+          !bld->pc->current_block->exit->terminator)
+         bld_flow(bld, NV_OP_BRA, NULL, NV_CC_P, b, FALSE);
+
       --bld->cond_lvl;
       nvc0_bblock_attach(bld->pc->current_block, b, bld->out_kind);
       nvc0_bblock_attach(bld->cond_bb[bld->cond_lvl], b, CFG_EDGE_FORWARD);
@@ -1678,7 +1681,7 @@ bld_instruction(struct bld_context *bld,
    {
       struct nv_basic_block *bb = bld->brkt_bb[bld->loop_lvl - 1];
 
-      bld_flow(bld, NV_OP_BRA, NULL, bb, FALSE);
+      bld_flow(bld, NV_OP_BRA, NULL, NV_CC_P, bb, FALSE);
 
       if (bld->out_kind == CFG_EDGE_FORWARD) /* else we already had BRK/CONT */
          nvc0_bblock_attach(bld->pc->current_block, bb, CFG_EDGE_LOOP_LEAVE);
@@ -1690,7 +1693,7 @@ bld_instruction(struct bld_context *bld,
    {
       struct nv_basic_block *bb = bld->loop_bb[bld->loop_lvl - 1];
 
-      bld_flow(bld, NV_OP_BRA, NULL, bb, FALSE);
+      bld_flow(bld, NV_OP_BRA, NULL, NV_CC_P, bb, FALSE);
 
       nvc0_bblock_attach(bld->pc->current_block, bb, CFG_EDGE_BACK);
 
@@ -1705,9 +1708,11 @@ bld_instruction(struct bld_context *bld,
    {
       struct nv_basic_block *bb = bld->loop_bb[bld->loop_lvl - 1];
 
-      bld_flow(bld, NV_OP_BRA, NULL, bb, FALSE);
+      if (bld->out_kind != CFG_EDGE_FAKE) { /* else we already had BRK/CONT */
+         bld_flow(bld, NV_OP_BRA, NULL, NV_CC_P, bb, FALSE);
 
-      nvc0_bblock_attach(bld->pc->current_block, bb, CFG_EDGE_BACK);
+         nvc0_bblock_attach(bld->pc->current_block, bb, CFG_EDGE_BACK);
+      }
 
       bld_loop_end(bld, bb); /* replace loop-side operand of the phis */
 
@@ -1824,11 +1829,11 @@ bld_instruction(struct bld_context *bld,
    case TGSI_OPCODE_SSG:
       FOR_EACH_DST0_ENABLED_CHANNEL(c, insn) { /* XXX: set lt, set gt, sub */
          src0 = emit_fetch(bld, insn, 0, c);
-         src1 = bld_setp(bld, NV_OP_SET_F32, NV_CC_EQ, src0, bld->zero);
-         temp = bld_insn_2(bld, NV_OP_AND, src0, bld_imm_u32(bld, 0x80000000));
-         temp = bld_insn_2(bld, NV_OP_OR,  temp, bld_imm_f32(bld, 1.0f));
-         dst0[c] = bld_insn_1(bld, NV_OP_MOV, temp);
-         bld_src_predicate(bld, dst0[c]->insn, 1, src1);
+         src1 = bld_insn_2(bld, NV_OP_FSET_F32, src0, bld->zero);
+         src2 = bld_insn_2(bld, NV_OP_FSET_F32, src0, bld->zero);
+         src1->insn->set_cond = NV_CC_GT;
+         src2->insn->set_cond = NV_CC_LT;
+         dst0[c] = bld_insn_2(bld, NV_OP_SUB_F32, src1, src2);
       }
       break;
    case TGSI_OPCODE_SUB:
@@ -1892,10 +1897,10 @@ bld_instruction(struct bld_context *bld,
       }
 
       for (c = 0; c < 4; ++c)
-         if ((mask & (1 << c)) &&
-             ((dst0[c]->reg.file == NV_FILE_IMM) ||
-              (dst0[c]->reg.id == 63 && dst0[c]->reg.file == NV_FILE_GPR)))
-            dst0[c] = bld_insn_1(bld, NV_OP_MOV, dst0[c]);
+         if (mask & (1 << c))
+            if ((dst0[c]->reg.file == NV_FILE_IMM) ||
+                (dst0[c]->reg.file == NV_FILE_GPR && dst0[c]->reg.id == 63))
+               dst0[c] = bld_insn_1(bld, NV_OP_MOV, dst0[c]);
 
       c = 0;
       if ((mask & 0x3) == 0x3) {
index 286b382f58e85f2530e69b5ef3ec1f18c0b56b33..b279bdc6e7d8cba02092ccc45c8a1e8fd1813358 100644 (file)
@@ -10,7 +10,8 @@ struct nvc0_transfer {
    struct pipe_transfer base;
    struct nvc0_m2mf_rect rect[2];
    uint32_t nblocksx;
-   uint32_t nblocksy;
+   uint16_t nblocksy;
+   uint16_t nlayers;
 };
 
 static void
@@ -242,23 +243,36 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx,
    struct nvc0_miptree_level *lvl = &mt->level[level];
    struct nvc0_transfer *tx;
    uint32_t size;
-   uint32_t w, h, d, z, layer;
+   uint32_t w, h, d, z, layer, box_h, box_y;
    int ret;
 
+   tx = CALLOC_STRUCT(nvc0_transfer);
+   if (!tx)
+      return NULL;
+
+   box_y = box->y;
+   box_h = box->height;
+
    if (mt->layout_3d) {
       z = box->z;
       d = u_minify(res->depth0, level);
       layer = 0;
+      tx->nlayers = box->depth;
    } else {
       z = 0;
       d = 1;
-      layer = box->z;
+      if (res->target == PIPE_TEXTURE_1D ||
+          res->target == PIPE_TEXTURE_1D_ARRAY) {
+         box_y = 0;
+         box_h = 1;
+         layer = box->y;
+         tx->nlayers = box->height;
+      } else {
+         layer = box->z;
+         tx->nlayers = box->depth;
+      }
    }
 
-   tx = CALLOC_STRUCT(nvc0_transfer);
-   if (!tx)
-      return NULL;
-
    pipe_resource_reference(&tx->base.resource, res);
 
    tx->base.level = level;
@@ -266,7 +280,7 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx,
    tx->base.box = *box;
 
    tx->nblocksx = util_format_get_nblocksx(res->format, box->width);
-   tx->nblocksy = util_format_get_nblocksy(res->format, box->height);
+   tx->nblocksy = util_format_get_nblocksy(res->format, box_h);
 
    tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format);
    tx->base.layer_stride = tx->nblocksy * tx->base.stride;
@@ -280,7 +294,7 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx,
    tx->rect[0].base = lvl->offset + layer * mt->layer_stride;
    tx->rect[0].tile_mode = lvl->tile_mode;
    tx->rect[0].x = util_format_get_nblocksx(res->format, box->x);
-   tx->rect[0].y = util_format_get_nblocksy(res->format, box->y);
+   tx->rect[0].y = util_format_get_nblocksy(res->format, box_y);
    tx->rect[0].z = z;
    tx->rect[0].width = util_format_get_nblocksx(res->format, w);
    tx->rect[0].height = util_format_get_nblocksy(res->format, h);
@@ -291,7 +305,7 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx,
    size = tx->base.layer_stride;
 
    ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
-                        size * tx->base.box.depth, &tx->rect[1].bo);
+                        size * tx->nlayers, &tx->rect[1].bo);
    if (ret) {
       FREE(tx);
       return NULL;
@@ -304,8 +318,9 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx,
    tx->rect[1].domain = NOUVEAU_BO_GART;
 
    if (usage & PIPE_TRANSFER_READ) {
+      unsigned base = tx->rect[0].base;
       unsigned i;
-      for (i = 0; i < box->depth; ++i) {
+      for (i = 0; i < tx->nlayers; ++i) {
          nvc0_m2mf_transfer_rect(pscreen, &tx->rect[1], &tx->rect[0],
                                  tx->nblocksx, tx->nblocksy);
          if (mt->layout_3d)
@@ -314,9 +329,10 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx,
             tx->rect[0].base += mt->layer_stride;
          tx->rect[1].base += size;
       }
+      tx->rect[0].z = z;
+      tx->rect[0].base = base;
+      tx->rect[1].base = 0;
    }
-   tx->rect[0].z = z;
-   tx->rect[1].base = 0;
 
    return &tx->base;
 }
@@ -331,7 +347,7 @@ nvc0_miptree_transfer_del(struct pipe_context *pctx,
    unsigned i;
 
    if (tx->base.usage & PIPE_TRANSFER_WRITE) {
-      for (i = 0; i < tx->base.box.depth; ++i) {
+      for (i = 0; i < tx->nlayers; ++i) {
          nvc0_m2mf_transfer_rect(pscreen, &tx->rect[0], &tx->rect[1],
                                  tx->nblocksx, tx->nblocksy);
          if (mt->layout_3d)
index a51a887ed89b7360c058bb92b322d02f48851925..2db43d8704bc99e10cf6b11a5ff27db6ee41dc5d 100644 (file)
@@ -54,12 +54,13 @@ nvc0_vertex_state_create(struct pipe_context *pipe,
     assert(num_elements);
 
     so = MALLOC(sizeof(*so) +
-                (num_elements - 1) * sizeof(struct nvc0_vertex_element));
+                num_elements * sizeof(struct nvc0_vertex_element));
     if (!so)
         return NULL;
     so->num_elements = num_elements;
     so->instance_elts = 0;
     so->instance_bufs = 0;
+    so->need_conversion = FALSE;
 
     transkey.nr_elements = 0;
     transkey.output_stride = 0;
@@ -83,6 +84,7 @@ nvc0_vertex_state_create(struct pipe_context *pipe,
                 return NULL;
             }
             so->element[i].state = nvc0_format_table[fmt].vtx;
+            so->need_conversion = TRUE;
         }
         so->element[i].state |= i;
 
@@ -152,7 +154,7 @@ nvc0_vbuf_range(struct nvc0_context *nvc0, int vbi,
    if (unlikely(nvc0->vertex->instance_bufs & (1 << vbi))) {
       /* TODO: use min and max instance divisor to get a proper range */
       *base = 0;
-      *size = (nvc0->vtxbuf[vbi].max_index + 1) * nvc0->vtxbuf[vbi].stride;
+      *size = nvc0->vtxbuf[vbi].buffer->width0;
    } else {
       assert(nvc0->vbo_max_index != ~0);
       *base = nvc0->vbo_min_index * nvc0->vtxbuf[vbi].stride;
@@ -171,12 +173,15 @@ nvc0_prevalidate_vbufs(struct nvc0_context *nvc0)
 
    nvc0->vbo_fifo = nvc0->vbo_user = 0;
 
+   nvc0_bufctx_reset(nvc0, NVC0_BUFCTX_VERTEX);
+
    for (i = 0; i < nvc0->num_vtxbufs; ++i) {
       vb = &nvc0->vtxbuf[i];
       if (!vb->stride)
          continue;
       buf = nvc0_resource(vb->buffer);
 
+      /* NOTE: user buffers with temporary storage count as mapped by GPU */
       if (!nvc0_resource_mapped_by_gpu(vb->buffer)) {
          if (nvc0->vbo_push_hint) {
             nvc0->vbo_fifo = ~0;
@@ -227,16 +232,30 @@ nvc0_update_user_vbufs(struct nvc0_context *nvc0)
       }
       offset = vb->buffer_offset + ve->src_offset;
 
+      MARK_RING (chan, 6, 4);
       BEGIN_RING_1I(chan, RING_3D(VERTEX_ARRAY_SELECT), 5);
       OUT_RING  (chan, i);
-      OUT_RESRCh(chan, buf, size - 1, NOUVEAU_BO_RD);
-      OUT_RESRCl(chan, buf, size - 1, NOUVEAU_BO_RD);
+      OUT_RESRCh(chan, buf, base + size - 1, NOUVEAU_BO_RD);
+      OUT_RESRCl(chan, buf, base + size - 1, NOUVEAU_BO_RD);
       OUT_RESRCh(chan, buf, offset, NOUVEAU_BO_RD);
       OUT_RESRCl(chan, buf, offset, NOUVEAU_BO_RD);
    }
    nvc0->vbo_dirty = TRUE;
 }
 
+static INLINE void
+nvc0_release_user_vbufs(struct nvc0_context *nvc0)
+{
+   uint32_t vbo_user = nvc0->vbo_user;
+
+   while (vbo_user) {
+      int i = ffs(vbo_user) - 1;
+      vbo_user &= ~(1 << i);
+
+      nvc0_buffer_release_gpu_storage(nvc0_resource(nvc0->vtxbuf[i].buffer));
+   }
+}
+
 void
 nvc0_vertex_arrays_validate(struct nvc0_context *nvc0)
 {
@@ -246,7 +265,12 @@ nvc0_vertex_arrays_validate(struct nvc0_context *nvc0)
    struct nvc0_vertex_element *ve;
    unsigned i;
 
-   nvc0_prevalidate_vbufs(nvc0);
+   if (unlikely(vertex->need_conversion)) {
+      nvc0->vbo_fifo = ~0;
+      nvc0->vbo_user = 0;
+   } else {
+      nvc0_prevalidate_vbufs(nvc0);
+   }
 
    BEGIN_RING(chan, RING_3D(VERTEX_ATTRIB_FORMAT(0)), vertex->num_elements);
    for (i = 0; i < vertex->num_elements; ++i) {
@@ -292,6 +316,7 @@ nvc0_vertex_arrays_validate(struct nvc0_context *nvc0)
       size = vb->buffer->width0;
       offset = ve->pipe.src_offset + vb->buffer_offset;
 
+      MARK_RING (chan, 8, 4);
       BEGIN_RING(chan, RING_3D(VERTEX_ARRAY_FETCH(i)), 1);
       OUT_RING  (chan, (1 << 12) | vb->stride);
       BEGIN_RING_1I(chan, RING_3D(VERTEX_ARRAY_SELECT), 5);
@@ -346,57 +371,10 @@ nvc0_draw_vbo_flush_notify(struct nouveau_channel *chan)
 {
    struct nvc0_context *nvc0 = chan->user_private;
 
-   nvc0_bufctx_emit_relocs(nvc0);
-}
+   nvc0_screen_fence_update(nvc0->screen, TRUE);
 
-#if 0
-static struct nouveau_bo *
-nvc0_tfb_setup(struct nvc0_context *nvc0)
-{
-   struct nouveau_channel *chan = nvc0->screen->base.channel;
-   struct nouveau_bo *tfb = NULL;
-   int ret, i;
-
-   ret = nouveau_bo_new(nvc0->screen->base.device,
-                        NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, 4096, &tfb);
-   if (ret)
-      return NULL;
-
-   ret = nouveau_bo_map(tfb, NOUVEAU_BO_WR);
-   if (ret)
-      return NULL;
-   memset(tfb->map, 0xee, 8 * 4 * 3);
-   nouveau_bo_unmap(tfb);
-
-   BEGIN_RING(chan, RING_3D(TFB_ENABLE), 1);
-   OUT_RING  (chan, 1);
-   BEGIN_RING(chan, RING_3D(TFB_BUFFER_ENABLE(0)), 5);
-   OUT_RING  (chan, 1);
-   OUT_RELOCh(chan, tfb, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR);
-   OUT_RELOCl(chan, tfb, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR);
-   OUT_RING  (chan, tfb->size);
-   OUT_RING  (chan, 0); /* TFB_PRIMITIVE_ID(0) */
-   BEGIN_RING(chan, RING_3D(TFB_UNK0700(0)), 3);
-   OUT_RING  (chan, 0);
-   OUT_RING  (chan, 8); /* TFB_VARYING_COUNT(0) */
-   OUT_RING  (chan, 32); /* TFB_BUFFER_STRIDE(0) */
-   BEGIN_RING(chan, RING_3D(TFB_VARYING_LOCS(0)), 2);
-   OUT_RING  (chan, 0x1f1e1d1c);
-   OUT_RING  (chan, 0xa3a2a1a0);
-   for (i = 1; i < 4; ++i) {
-      BEGIN_RING(chan, RING_3D(TFB_BUFFER_ENABLE(i)), 1);
-      OUT_RING  (chan, 0);
-   }
-   BEGIN_RING(chan, RING_3D(TFB_ENABLE), 1);
-   OUT_RING  (chan, 1);
-   BEGIN_RING(chan, RING_3D_(0x135c), 1);
-   OUT_RING  (chan, 1);
-   BEGIN_RING(chan, RING_3D_(0x135c), 1);
-   OUT_RING  (chan, 0);
-
-   return tfb;
+   nvc0_bufctx_emit_relocs(nvc0);
 }
-#endif
 
 static void
 nvc0_draw_arrays(struct nvc0_context *nvc0,
@@ -422,7 +400,7 @@ nvc0_draw_arrays(struct nvc0_context *nvc0,
       prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
    }
 
-   chan->flush_notify = NULL;
+   chan->flush_notify = nvc0_default_flush_notify;
 }
 
 static void
@@ -592,7 +570,7 @@ nvc0_draw_elements(struct nvc0_context *nvc0, boolean shorten,
       }
    }
 
-   chan->flush_notify = NULL;
+   chan->flush_notify = nvc0_default_flush_notify;
 }
 
 void
@@ -611,6 +589,9 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
    nvc0->vbo_min_index = info->min_index;
    nvc0->vbo_max_index = info->max_index;
 
+   if (nvc0->vbo_push_hint != !!nvc0->vbo_fifo)
+      nvc0->dirty |= NVC0_NEW_ARRAYS;
+
    if (nvc0->vbo_user && !(nvc0->dirty & (NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS)))
       nvc0_update_user_vbufs(nvc0);
 
@@ -668,4 +649,6 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
                          info->mode, info->start, info->count,
                          info->instance_count, info->index_bias);
    }
+
+   nvc0_release_user_vbufs(nvc0);
 }
index 1544fb7a1de20a6bd87b8bbff9dc0d7653cee02e..45f71967eff9b573ee6894d066654b49808c6e57 100644 (file)
@@ -95,7 +95,7 @@ OUT_RESRCl(struct nouveau_channel *chan, struct nvc0_resource *res,
            unsigned delta, unsigned flags)
 {
    if (flags & NOUVEAU_BO_WR)
-      res->status |= NVC0_BUFFER_STATUS_DIRTY;
+      res->status |= NVC0_BUFFER_STATUS_GPU_WRITING;
    return OUT_RELOCl(chan, res->bo, res->offset + delta, res->domain | flags);
 }
 
index 01dacb43dad1155b77d350e72c3e4da2c7a78456..b72379d653694d6a920ad768dafaa91b528fbd78 100644 (file)
@@ -2,6 +2,7 @@
 #include "pipe/p_state.h"
 #include "util/u_inlines.h"
 #include "util/u_format.h"
+#include "util/u_transfer.h"
 #include "translate/translate.h"
 
 #include "nvfx_context.h"
@@ -631,4 +632,6 @@ nvfx_init_vbo_functions(struct nvfx_context *nvfx)
        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.redefine_user_buffer = u_default_redefine_user_buffer;
 }
index a43e83c0d363c11db33a984b700b8fa3d84809e0..4f86db399265fc274881c2670b25780212bc4ac4 100644 (file)
@@ -55,11 +55,12 @@ static void r300_blitter_begin(struct r300_context* r300, enum r300_blitter_op o
     util_blitter_save_viewport(r300->blitter, &r300->viewport);
     util_blitter_save_clip(r300->blitter, (struct pipe_clip_state*)r300->clip_state.state);
     util_blitter_save_vertex_elements(r300->blitter, r300->velems);
-    util_blitter_save_vertex_buffers(r300->blitter, r300->vertex_buffer_count,
-                                     r300->vertex_buffer);
+    util_blitter_save_vertex_buffers(r300->blitter, r300->vbuf_mgr->nr_vertex_buffers,
+                                     r300->vbuf_mgr->vertex_buffer);
 
-    if (op & (R300_CLEAR_SURFACE | R300_COPY))
+    if (op & (R300_CLEAR_SURFACE | R300_COPY)) {
         util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
+    }
 
     if (op & R300_COPY) {
         struct r300_textures_state* state =
@@ -108,6 +109,14 @@ static boolean r300_cbzb_clear_allowed(struct r300_context *r300,
     return r300_surface(fb->cbufs[0])->cbzb_allowed;
 }
 
+static boolean r300_fast_zclear_allowed(struct r300_context *r300)
+{
+    struct pipe_framebuffer_state *fb =
+        (struct pipe_framebuffer_state*)r300->fb_state.state;
+
+    return r300_resource(fb->zsbuf->texture)->tex.zmask_dwords[fb->zsbuf->u.tex.level];
+}
+
 static uint32_t r300_depth_clear_value(enum pipe_format format,
                                        double depth, unsigned stencil)
 {
@@ -132,37 +141,46 @@ static void r300_clear(struct pipe_context* pipe,
                        double depth,
                        unsigned stencil)
 {
-    /* My notes about fastfill:
+    /* My notes about Zbuffer compression:
      *
-     * 1) Only the zbuffer is cleared.
+     * 1) The zbuffer must be micro-tiled and whole microtiles must be
+     *    written if compression is enabled. If microtiling is disabled,
+     *    it locks up.
      *
-     * 2) The zbuffer must be micro-tiled and whole microtiles must be
-     *    written. If microtiling is disabled, it locks up.
+     * 2) There is ZMASK RAM which contains a compressed zbuffer.
+     *    Each dword of the Z Mask contains compression information
+     *    for 16 4x4 pixel tiles, that is 2 bits for each tile.
+     *    On chips with 2 Z pipes, every other dword maps to a different
+     *    pipe. On newer chipsets, there is a new compression mode
+     *    with 8x8 pixel tiles per 2 bits.
      *
-     * 3) There is Z Mask RAM which contains a compressed zbuffer and
-     *    it interacts with fastfill. We should figure out how to use it
-     *    to get more performance.
-     *    This is what we know about the Z Mask:
+     * 3) The FASTFILL bit has nothing to do with filling. It only tells hw
+     *    it should look in the ZMASK RAM first before fetching from a real
+     *    zbuffer.
      *
-     *       Each dword of the Z Mask contains compression information
-     *       for 16 4x4 pixel blocks, that is 2 bits for each block.
-     *       On chips with 2 Z pipes, every other dword maps to a different
-     *       pipe.
+     * 4) If a pixel is in a cleared state, ZB_DEPTHCLEARVALUE is returned
+     *    during zbuffer reads instead of the value that is actually stored
+     *    in the zbuffer memory. A pixel is in a cleared state when its ZMASK
+     *    is equal to 0. Therefore, if you clear ZMASK with zeros, you may
+     *    leave the zbuffer memory uninitialized, but then you must enable
+     *    compression, so that the ZMASK RAM is actually used.
      *
-     * 4) ZB_DEPTHCLEARVALUE is used to clear the zbuffer and the Z Mask must
-     *    be equal to 0. (clear the Z Mask RAM with zeros)
+     * 5) Each 4x4 (or 8x8) tile is automatically decompressed and recompressed
+     *    during zbuffer updates. A special decompressing operation should be
+     *    used to fully decompress a zbuffer, which basically just stores all
+     *    compressed tiles in ZMASK to the zbuffer memory.
      *
-     * 5) For 16-bit zbuffer, compression causes a hung with one or
+     * 6) For a 16-bit zbuffer, compression causes a hung with one or
      *    two samples and should not be used.
      *
-     * 6) FORCE_COMPRESSED_STENCIL_VALUE should be enabled for stencil clears
+     * 7) FORCE_COMPRESSED_STENCIL_VALUE should be enabled for stencil clears
      *    to avoid needless decompression.
      *
-     * 7) Fastfill must not be used if reading of compressed Z data is disabled
+     * 8) Fastfill must not be used if reading of compressed Z data is disabled
      *    and writing of compressed Z data is enabled (RD/WR_COMP_ENABLE),
      *    i.e. it cannot be used to compress the zbuffer.
      *
-     * 8) ZB_CB_CLEAR does not interact with fastfill in any way.
+     * 9) ZB_CB_CLEAR does not interact with zbuffer compression in any way.
      *
      * - Marek
      */
@@ -172,32 +190,30 @@ static void r300_clear(struct pipe_context* pipe,
         (struct pipe_framebuffer_state*)r300->fb_state.state;
     struct r300_hyperz_state *hyperz =
         (struct r300_hyperz_state*)r300->hyperz_state.state;
-    struct r300_texture *zstex =
-            fb->zsbuf ? r300_texture(fb->zsbuf->texture) : NULL;
+    struct r300_resource *zstex =
+            fb->zsbuf ? r300_resource(fb->zsbuf->texture) : NULL;
     uint32_t width = fb->width;
     uint32_t height = fb->height;
     boolean can_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ);
     uint32_t hyperz_dcv = hyperz->zb_depthclearvalue;
 
-    /* Decompress zbuffers that are bound as textures. If we didn't flush here,
-     * it would happen inside the blitter when updating derived state,
-     * causing a blitter operation to be called from inside the blitter,
-     * which would overwrite saved states and they would never get restored. */
-    r300_flush_depth_textures(r300);
-
     /* Enable fast Z clear.
      * The zbuffer must be in micro-tiled mode, otherwise it locks up. */
     if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && can_hyperz) {
         hyperz_dcv = hyperz->zb_depthclearvalue =
             r300_depth_clear_value(fb->zsbuf->format, depth, stencil);
 
-        r300_mark_fb_state_dirty(r300, R300_CHANGED_ZCLEAR_FLAG);
-        if (zstex->zmask_mem[fb->zsbuf->u.tex.level]) {
+        if (r300_fast_zclear_allowed(r300)) {
             r300_mark_atom_dirty(r300, &r300->zmask_clear);
             buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
         }
+
         if (zstex->hiz_mem[fb->zsbuf->u.tex.level])
             r300_mark_atom_dirty(r300, &r300->hiz_clear);
+
+        /* XXX Change this to r300_mark_atom_dirty(r300, &r300->hyperz_state);
+         * once hiz offset is constant. */
+        r300_mark_fb_state_dirty(r300, R300_CHANGED_HYPERZ_FLAG);
     }
 
     /* Enable CBZB clear. */
@@ -211,7 +227,7 @@ static void r300_clear(struct pipe_context* pipe,
         height = surf->cbzb_height;
 
         r300->cbzb_clear = TRUE;
-        r300_mark_fb_state_dirty(r300, R300_CHANGED_CBZB_FLAG);
+        r300_mark_fb_state_dirty(r300, R300_CHANGED_HYPERZ_FLAG);
     }
 
     /* Clear. */
@@ -225,7 +241,7 @@ static void r300_clear(struct pipe_context* pipe,
                            buffers, rgba, depth, stencil);
         r300_blitter_end(r300);
     } else if (r300->zmask_clear.dirty) {
-        /* Just clear zmask and hiz now, this does not use a standard draw
+        /* Just clear zmask and hiz now, this does not use the standard draw
          * procedure. */
         unsigned dwords;
 
@@ -257,16 +273,15 @@ static void r300_clear(struct pipe_context* pipe,
     if (r300->cbzb_clear) {
         r300->cbzb_clear = FALSE;
         hyperz->zb_depthclearvalue = hyperz_dcv;
-        r300_mark_fb_state_dirty(r300, R300_CHANGED_CBZB_FLAG);
+        r300_mark_fb_state_dirty(r300, R300_CHANGED_HYPERZ_FLAG);
     }
 
     /* Enable fastfill and/or hiz.
      *
      * If we cleared zmask/hiz, it's in use now. The Hyper-Z state update
      * looks if zmask/hiz is in use and enables fastfill accordingly. */
-    if (zstex &&
-        (zstex->zmask_in_use[fb->zsbuf->u.tex.level] ||
-         zstex->hiz_in_use[fb->zsbuf->u.tex.level])) {
+    if (r300->zmask_in_use ||
+        (zstex && zstex->hiz_in_use[fb->zsbuf->u.tex.level])) {
         r300_mark_atom_dirty(r300, &r300->hyperz_state);
     }
 }
@@ -280,16 +295,16 @@ static void r300_clear_render_target(struct pipe_context *pipe,
 {
     struct r300_context *r300 = r300_context(pipe);
 
-    /* Decompress zbuffers that are bound as textures. If we didn't flush here,
-     * it would happen inside the blitter when updating derived state,
-     * causing a blitter operation to be called from inside the blitter,
-     * which would overwrite saved states and they would never get restored. */
-    r300_flush_depth_textures(r300);
+    r300->zmask_locked = TRUE;
+    r300_mark_atom_dirty(r300, &r300->hyperz_state);
 
     r300_blitter_begin(r300, R300_CLEAR_SURFACE);
     util_blitter_clear_render_target(r300->blitter, dst, rgba,
                                      dstx, dsty, width, height);
     r300_blitter_end(r300);
+
+    r300->zmask_locked = FALSE;
+    r300_mark_atom_dirty(r300, &r300->hyperz_state);
 }
 
 /* Clear a region of a depth stencil surface. */
@@ -302,83 +317,70 @@ static void r300_clear_depth_stencil(struct pipe_context *pipe,
                                      unsigned width, unsigned height)
 {
     struct r300_context *r300 = r300_context(pipe);
+    struct pipe_framebuffer_state *fb =
+        (struct pipe_framebuffer_state*)r300->fb_state.state;
 
-    /* Decompress zbuffers that are bound as textures. If we didn't flush here,
-     * it would happen inside the blitter when updating derived state,
-     * causing a blitter operation to be called from inside the blitter,
-     * which would overwrite saved states and they would never get restored. */
-    r300_flush_depth_textures(r300);
+    if (r300->zmask_in_use && !r300->zmask_locked) {
+        if (fb->zsbuf->texture == dst->texture) {
+            r300_decompress_zmask(r300);
+        } else {
+            r300->zmask_locked = TRUE;
+            r300_mark_atom_dirty(r300, &r300->hyperz_state);
+        }
+    }
 
     r300_blitter_begin(r300, R300_CLEAR_SURFACE);
     util_blitter_clear_depth_stencil(r300->blitter, dst, clear_flags, depth, stencil,
                                      dstx, dsty, width, height);
     r300_blitter_end(r300);
+
+    if (r300->zmask_locked) {
+        r300->zmask_locked = FALSE;
+        r300_mark_atom_dirty(r300, &r300->hyperz_state);
+    }
 }
 
-/* Flush a depth stencil buffer. */
-static void r300_flush_depth_stencil(struct pipe_context *pipe,
-                                     struct pipe_resource *dst,
-                                     unsigned level,
-                                     unsigned layer)
+void r300_decompress_zmask(struct r300_context *r300)
 {
-    struct r300_context *r300 = r300_context(pipe);
-    struct pipe_surface *dstsurf, surf_tmpl;
-    struct r300_texture *tex = r300_texture(dst);
+    struct pipe_framebuffer_state *fb =
+        (struct pipe_framebuffer_state*)r300->fb_state.state;
 
-    if (!tex->zmask_mem[level])
-        return;
-    if (!tex->zmask_in_use[level])
+    if (!r300->zmask_in_use || r300->zmask_locked)
         return;
 
-    surf_tmpl.format = dst->format;
-    surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL;
-    surf_tmpl.u.tex.level = level;
-    surf_tmpl.u.tex.first_layer = layer;
-    surf_tmpl.u.tex.last_layer = layer;
-    dstsurf = pipe->create_surface(pipe, dst, &surf_tmpl);
+    r300->zmask_decompress = TRUE;
+    r300_mark_atom_dirty(r300, &r300->hyperz_state);
 
-    r300->z_decomp_rd = TRUE;
-
-    r300_blitter_begin(r300, R300_CLEAR_SURFACE);
-    util_blitter_flush_depth_stencil(r300->blitter, dstsurf);
+    r300_blitter_begin(r300, R300_CLEAR);
+    util_blitter_clear_depth_custom(r300->blitter, fb->width, fb->height, 0,
+                                    r300->dsa_decompress_zmask);
     r300_blitter_end(r300);
-    r300->z_decomp_rd = FALSE;
 
-    tex->zmask_in_use[level] = FALSE;
-    pipe_surface_reference(&dstsurf, NULL);
+    r300->zmask_decompress = FALSE;
+    r300->zmask_in_use = FALSE;
+    r300_mark_atom_dirty(r300, &r300->hyperz_state);
 }
 
-/* We can't use compressed zbuffers as samplers. */
-void r300_flush_depth_textures(struct r300_context *r300)
+void r300_decompress_zmask_locked_unsafe(struct r300_context *r300)
 {
-    struct r300_textures_state *state =
-        (struct r300_textures_state*)r300->textures_state.state;
-    unsigned i, level;
-    unsigned count = MIN2(state->sampler_view_count,
-                          state->sampler_state_count);
-
-    if (r300->z_decomp_rd)
-        return;
-
-    for (i = 0; i < count; i++)
-        if (state->sampler_views[i] && state->sampler_states[i]) {
-            struct pipe_resource *tex = state->sampler_views[i]->base.texture;
-
-            if (tex->target == PIPE_TEXTURE_3D ||
-                tex->target == PIPE_TEXTURE_CUBE)
-                continue;
+    struct pipe_framebuffer_state fb = {0};
+    fb.width = r300->locked_zbuffer->width;
+    fb.height = r300->locked_zbuffer->height;
+    fb.nr_cbufs = 0;
+    fb.zsbuf = r300->locked_zbuffer;
+
+    r300->context.set_framebuffer_state(&r300->context, &fb);
+    r300_decompress_zmask(r300);
+}
 
-            /* Ignore non-depth textures.
-             * Also ignore reinterpreted depth textures, e.g. resource_copy. */
-            if (!util_format_is_depth_or_stencil(tex->format))
-                continue;
+void r300_decompress_zmask_locked(struct r300_context *r300)
+{
+    struct pipe_framebuffer_state saved_fb = {0};
 
-            for (level = 0; level <= tex->last_level; level++)
-                if (r300_texture(tex)->zmask_in_use[level]) {
-                    /* We don't handle 3D textures and cubemaps yet. */
-                    r300_flush_depth_stencil(&r300->context, tex, level, 0);
-                 }
-        }
+    util_copy_framebuffer_state(&saved_fb, r300->fb_state.state);
+    r300_decompress_zmask_locked_unsafe(r300);
+    r300->context.set_framebuffer_state(&r300->context, &saved_fb);
+    util_unreference_framebuffer_state(&saved_fb);
 }
 
 /* Copy a block of pixels from one surface to another using HW. */
@@ -393,8 +395,6 @@ static void r300_hw_copy_region(struct pipe_context* pipe,
     struct r300_context* r300 = r300_context(pipe);
 
     r300_blitter_begin(r300, R300_COPY);
-
-    /* Do a copy */
     util_blitter_copy_region(r300->blitter, dst, dst_level, dstx, dsty, dstz,
                              src, src_level, src_box, TRUE);
     r300_blitter_end(r300);
@@ -409,56 +409,102 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
                                       unsigned src_level,
                                       const struct pipe_box *src_box)
 {
-    enum pipe_format old_format = dst->format;
-    enum pipe_format new_format = old_format;
-    boolean is_depth;
-
-    if (!pipe->screen->is_format_supported(pipe->screen,
-                                           old_format, src->target,
-                                           src->nr_samples,
-                                           PIPE_BIND_RENDER_TARGET |
-                                           PIPE_BIND_SAMPLER_VIEW, 0) &&
-        util_format_is_plain(old_format)) {
-        switch (util_format_get_blocksize(old_format)) {
+    struct r300_context *r300 = r300_context(pipe);
+    struct pipe_framebuffer_state *fb =
+        (struct pipe_framebuffer_state*)r300->fb_state.state;
+    struct pipe_resource old_src = *src;
+    struct pipe_resource old_dst = *dst;
+    struct pipe_resource new_src = old_src;
+    struct pipe_resource new_dst = old_dst;
+    const struct util_format_description *desc =
+            util_format_description(dst->format);
+    struct pipe_box box;
+
+    if (r300->zmask_in_use && !r300->zmask_locked) {
+        if (fb->zsbuf->texture == src ||
+            fb->zsbuf->texture == dst) {
+            r300_decompress_zmask(r300);
+        } else {
+            r300->zmask_locked = TRUE;
+            r300_mark_atom_dirty(r300, &r300->hyperz_state);
+        }
+    }
+
+    /* Handle non-renderable plain formats. */
+    if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
+        (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB ||
+         !pipe->screen->is_format_supported(pipe->screen,
+                                            src->format, src->target,
+                                            src->nr_samples,
+                                            PIPE_BIND_SAMPLER_VIEW, 0) ||
+         !pipe->screen->is_format_supported(pipe->screen,
+                                            dst->format, dst->target,
+                                            dst->nr_samples,
+                                            PIPE_BIND_RENDER_TARGET, 0))) {
+        switch (util_format_get_blocksize(old_dst.format)) {
             case 1:
-                new_format = PIPE_FORMAT_I8_UNORM;
+                new_dst.format = PIPE_FORMAT_I8_UNORM;
                 break;
             case 2:
-                new_format = PIPE_FORMAT_B4G4R4A4_UNORM;
+                new_dst.format = PIPE_FORMAT_B4G4R4A4_UNORM;
                 break;
             case 4:
-                new_format = PIPE_FORMAT_B8G8R8A8_UNORM;
+                new_dst.format = PIPE_FORMAT_B8G8R8A8_UNORM;
                 break;
             case 8:
-                new_format = PIPE_FORMAT_R16G16B16A16_UNORM;
+                new_dst.format = PIPE_FORMAT_R16G16B16A16_UNORM;
                 break;
             default:
                 debug_printf("r300: surface_copy: Unhandled format: %s. Falling back to software.\n"
                              "r300: surface_copy: Software fallback doesn't work for tiled textures.\n",
-                             util_format_short_name(old_format));
+                             util_format_short_name(dst->format));
         }
+        new_src.format = new_dst.format;
     }
 
-    is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
-    if (is_depth) {
-        r300_flush_depth_stencil(pipe, src, src_level, src_box->z);
-    }
+    /* Handle compressed formats. */
+    if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
+        switch (util_format_get_blocksize(old_dst.format)) {
+        case 8:
+            /* 1 pixel = 4 bits,
+             * we set 1 pixel = 2 bytes ===> 4 times larger pixels. */
+            new_dst.format = PIPE_FORMAT_B4G4R4A4_UNORM;
+            break;
+        case 16:
+            /* 1 pixel = 8 bits,
+             * we set 1 pixel = 4 bytes ===> 4 times larger pixels. */
+            new_dst.format = PIPE_FORMAT_B8G8R8A8_UNORM;
+            break;
+        }
 
-    if (old_format != new_format) {
-        r300_texture_reinterpret_format(pipe->screen,
-                                        dst, new_format);
-        r300_texture_reinterpret_format(pipe->screen,
-                                        src, new_format);
+        /* Since the pixels are 4 times larger, we must decrease
+         * the image size and the coordinates 4 times. */
+        new_src.format = new_dst.format;
+        new_dst.height0 = (new_dst.height0 + 3) / 4;
+        new_src.height0 = (new_src.height0 + 3) / 4;
+        dsty /= 4;
+        box = *src_box;
+        box.y /= 4;
+        box.height = (box.height + 3) / 4;
+        src_box = &box;
     }
 
+    if (old_src.format != new_src.format)
+        r300_resource_set_properties(pipe->screen, src, 0, &new_src);
+    if (old_dst.format != new_dst.format)
+        r300_resource_set_properties(pipe->screen, dst, 0, &new_dst);
+
     r300_hw_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
                         src, src_level, src_box);
 
-    if (old_format != new_format) {
-        r300_texture_reinterpret_format(pipe->screen,
-                                        dst, old_format);
-        r300_texture_reinterpret_format(pipe->screen,
-                                        src, old_format);
+    if (old_src.format != new_src.format)
+        r300_resource_set_properties(pipe->screen, src, 0, &old_src);
+    if (old_dst.format != new_dst.format)
+        r300_resource_set_properties(pipe->screen, dst, 0, &old_dst);
+
+    if (r300->zmask_locked) {
+        r300->zmask_locked = FALSE;
+        r300_mark_atom_dirty(r300, &r300->hyperz_state);
     }
 }
 
index 9d3d4fc1b19843a2028d404f1d3843a66d439cd0..b373937a1f933b838a12eb41824dfcd5caf1b1a3 100644 (file)
  * that they neatly hide away, and don't have the cost of function setup, so
  * we're going to use them. */
 
-#ifdef DEBUG
-#define CB_DEBUG(x) x
-#else
-#define CB_DEBUG(x)
-#endif
-
-
 /**
  * Command buffer setup.
  */
 
+#ifdef DEBUG
+
 #define CB_LOCALS \
-    CB_DEBUG(int cs_count = 0;) \
+    int cs_count = 0; \
     uint32_t *cs_ptr = NULL; \
-    CB_DEBUG((void) cs_count;) (void) cs_ptr;
+    (void) cs_count; (void) cs_ptr
 
-#define NEW_CB(ptr, size) do { \
-    assert(sizeof(*ptr) == sizeof(uint32_t)); \
-    cs_ptr = (ptr) = (uint32_t*)malloc((size) * sizeof(uint32_t)); \
-    CB_DEBUG(cs_count = size;) \
+#define BEGIN_CB(ptr, size) do { \
+    assert(sizeof(*(ptr)) == sizeof(uint32_t)); \
+    cs_count = (size); \
+    cs_ptr = (ptr); \
 } while (0)
 
-#define BEGIN_CB(ptr, size) do { \
-    assert(sizeof(*ptr) == sizeof(uint32_t)); \
-    cs_ptr = ptr; \
-    CB_DEBUG(cs_count = size;) \
+#define NEW_CB(ptr, size) \
+    do { \
+    assert(sizeof(*(ptr)) == sizeof(uint32_t)); \
+    cs_count = (size); \
+    cs_ptr = (ptr) = (uint32_t*)malloc((size) * sizeof(uint32_t)); \
 } while (0)
 
 #define END_CB do { \
-    CB_DEBUG(if (cs_count != 0) \
+    if (cs_count != 0) \
         debug_printf("r300: Warning: cs_count off by %d at (%s, %s:%i)\n", \
-                     cs_count, __FUNCTION__, __FILE__, __LINE__);) \
+                     cs_count, __FUNCTION__, __FILE__, __LINE__); \
 } while (0)
 
+#define CB_USED_DW(x) cs_count -= x
+
+#else
+
+#define CB_LOCALS \
+    uint32_t *cs_ptr = NULL; (void) cs_ptr
+
+#define NEW_CB(ptr, size) \
+    cs_ptr = (ptr) = (uint32_t*)malloc((size) * sizeof(uint32_t))
+
+#define BEGIN_CB(ptr, size) cs_ptr = (ptr)
+#define END_CB
+#define CB_USED_DW(x)
+
+#endif
+
 
 /**
  * Storing pure DWORDs.
 #define OUT_CB(value) do { \
     *cs_ptr = (value); \
     cs_ptr++; \
-    CB_DEBUG(cs_count--;) \
+    CB_USED_DW(1); \
 } while (0)
 
 #define OUT_CB_TABLE(values, count) do { \
     memcpy(cs_ptr, values, count * sizeof(uint32_t)); \
     cs_ptr += count; \
-    CB_DEBUG(cs_count -= count;) \
+    CB_USED_DW(count); \
 } while (0)
 
 #define OUT_CB_32F(value) \
index 2b183f62c56e3284683c86c151d8ba62b9af2fe3..1968d0feb35d1aec733e67a562e8c3e13d09095f 100644 (file)
@@ -241,7 +241,6 @@ void r300_parse_chipset(struct r300_capabilities* caps)
         case 0x5A42:
             caps->family = CHIP_FAMILY_RS400;
             caps->has_tcl = FALSE;
-            caps->zmask_ram = RV3xx_ZMASK_SIZE;
             break;
 
         case 0x5A61:
@@ -424,5 +423,6 @@ void r300_parse_chipset(struct r300_capabilities* caps)
     }
 
     caps->is_rv350 = caps->family >= CHIP_FAMILY_RV350;
+    caps->z_compress = caps->is_rv350 ? R300_ZCOMP_8X8 : R300_ZCOMP_4X4;
     caps->dxtc_swizzle = caps->is_r400 || caps->is_r500;
 }
index f2035d2009243733f58548bcf1b153e3d65682c6..0be161fa07a84545113e9d5914090df6a9125bf9 100644 (file)
 #define PIPE_ZMASK_SIZE 4096
 #define RV3xx_ZMASK_SIZE 5120
 
+/* The size of a compressed tile. Each compressed tile takes 2 bits
+ * in the ZMASK RAM, so there is always 16 tiles per one dword. */
+enum r300_zmask_compression {
+   R300_ZCOMP_4X4 = 4,
+   R300_ZCOMP_8X8 = 8
+};
+
 /* Structure containing all the possible information about a specific Radeon
  * in the R3xx, R4xx, and R5xx families. */
 struct r300_capabilities {
@@ -50,10 +57,12 @@ struct r300_capabilities {
     unsigned num_tex_units;
     /* Whether or not TCL is physically present */
     boolean has_tcl;
-    /* Some chipsets do not have HiZ RAM - other have varying amounts . */
+    /* Some chipsets do not have HiZ RAM - other have varying amounts. */
     int hiz_ram;
-    /*  some chipsets have zmask ram per pipe some don't */
+    /* Some chipsets have zmask ram per pipe some don't. */
     int zmask_ram;
+    /* Compression mode for ZMASK. */
+    enum r300_zmask_compression z_compress;
     /* Whether or not this is RV350 or newer, including all r400 and r500
      * chipsets. The differences compared to the oldest r300 chips are:
      * - Blend LTE/GTE thresholds
index 91263ad7bcdb1c2c78922e33fd1f586051aa3ab0..9f85bd4ce5f0886d4060dc9fc2478ca73d761e1c 100644 (file)
 #include "r300_screen_buffer.h"
 #include "r300_winsys.h"
 
-#ifdef HAVE_LLVM
-#include "gallivm/lp_bld_init.h"
-#endif
-
 static void r300_update_num_contexts(struct r300_screen *r300screen,
                                      int diff)
 {
+    pipe_mutex_lock(r300screen->num_contexts_mutex);
     if (diff > 0) {
-        p_atomic_inc(&r300screen->num_contexts);
+        r300screen->num_contexts++;
 
         if (r300screen->num_contexts > 1)
             util_slab_set_thread_safety(&r300screen->pool_buffers,
                                         UTIL_SLAB_MULTITHREADED);
     } else {
-        p_atomic_dec(&r300screen->num_contexts);
+        r300screen->num_contexts--;
 
         if (r300screen->num_contexts <= 1)
             util_slab_set_thread_safety(&r300screen->pool_buffers,
                                         UTIL_SLAB_SINGLETHREADED);
     }
+    pipe_mutex_unlock(r300screen->num_contexts_mutex);
 }
 
 static void r300_release_referenced_objects(struct r300_context *r300)
@@ -87,17 +85,14 @@ static void r300_release_referenced_objects(struct r300_context *r300)
     /* The SWTCL VBO. */
     pipe_resource_reference(&r300->vbo, NULL);
 
-    /* Vertex buffers. */
-    for (i = 0; i < r300->vertex_buffer_count; i++) {
-        pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL);
-        pipe_resource_reference(&r300->valid_vertex_buffer[i], NULL);
-    }
-
     /* If there are any queries pending or not destroyed, remove them now. */
     foreach_s(query, temp, &r300->query_list) {
         remove_from_list(query);
         FREE(query);
     }
+
+    r300->context.delete_depth_stencil_alpha_state(&r300->context,
+                                                   r300->dsa_decompress_zmask);
 }
 
 static void r300_destroy_context(struct pipe_context* context)
@@ -106,28 +101,15 @@ static void r300_destroy_context(struct pipe_context* context)
 
     if (r300->blitter)
         util_blitter_destroy(r300->blitter);
-    if (r300->draw) {
+    if (r300->draw)
         draw_destroy(r300->draw);
 
-#ifdef HAVE_LLVM
-        gallivm_destroy(r300->gallivm);
-#endif
-    }
-
-    if (r300->upload_vb)
-        u_upload_destroy(r300->upload_vb);
-    if (r300->upload_ib)
-        u_upload_destroy(r300->upload_ib);
-
-    if (r300->tran.translate_cache)
-        translate_cache_destroy(r300->tran.translate_cache);
+    if (r300->vbuf_mgr)
+        u_vbuf_mgr_destroy(r300->vbuf_mgr);
 
     /* XXX: This function assumes r300->query_list was initialized */
     r300_release_referenced_objects(r300);
 
-    if (r300->zmask_mm)
-        r300_hyperz_destroy_mm(r300);
-
     if (r300->cs)
         r300->rws->cs_destroy(r300->cs);
 
@@ -247,7 +229,7 @@ static boolean r300_setup_atoms(struct r300_context* r300)
         if (has_hiz_ram)
             R300_INIT_ATOM(hiz_clear, 0);
         /* zmask clear */
-        R300_INIT_ATOM(zmask_clear, 0);
+        R300_INIT_ATOM(zmask_clear, 4);
     }
     /* ZB (unpipelined), SU. */
     R300_INIT_ATOM(query_start, 4);
@@ -432,12 +414,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
 
     if (!r300screen->caps.has_tcl) {
         /* Create a Draw. This is used for SW TCL. */
-#ifdef HAVE_LLVM
-        r300->gallivm = gallivm_create();
-        r300->draw = draw_create_gallivm(&r300->context, r300->gallivm);
-#else
         r300->draw = draw_create(&r300->context);
-#endif
         if (r300->draw == NULL)
             goto fail;
         /* Enable our renderer. */
@@ -456,6 +433,13 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
     r300_init_state_functions(r300);
     r300_init_resource_functions(r300);
 
+    r300->vbuf_mgr = u_vbuf_mgr_create(&r300->context, 1024 * 1024, 16,
+                                       PIPE_BIND_VERTEX_BUFFER |
+                                       PIPE_BIND_INDEX_BUFFER,
+                                       U_VERTEX_FETCH_DWORD_ALIGNED);
+    if (!r300->vbuf_mgr)
+        goto fail;
+
     r300->blitter = util_blitter_create(&r300->context);
     if (r300->blitter == NULL)
         goto fail;
@@ -470,23 +454,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
         if (!r300_hyperz_init_mm(r300))
             goto fail;
 
-    r300->upload_ib = u_upload_create(&r300->context,
-                                     64 * 1024, 16,
-                                     PIPE_BIND_INDEX_BUFFER);
-
-    if (r300->upload_ib == NULL)
-        goto fail;
-
-    r300->upload_vb = u_upload_create(&r300->context,
-                                     1024 * 1024, 16,
-                                     PIPE_BIND_VERTEX_BUFFER);
-    if (r300->upload_vb == NULL)
-        goto fail;
-
-    r300->tran.translate_cache = translate_cache_create();
-    if (r300->tran.translate_cache == NULL)
-        goto fail;
-
     r300_init_states(&r300->context);
 
     /* The KIL opcode needs the first texture unit to be enabled
@@ -515,7 +482,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
     }
 
     {
-        struct pipe_resource vb = {};
+        struct pipe_resource vb;
+        memset(&vb, 0, sizeof(vb));
         vb.target = PIPE_BUFFER;
         vb.format = PIPE_FORMAT_R8_UNORM;
         vb.bind = PIPE_BIND_VERTEX_BUFFER;
@@ -527,36 +495,44 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
         r300->dummy_vb = screen->resource_create(screen, &vb);
     }
 
+    {
+        struct pipe_depth_stencil_alpha_state dsa;
+        memset(&dsa, 0, sizeof(dsa));
+        dsa.depth.writemask = 1;
+
+        r300->dsa_decompress_zmask =
+            r300->context.create_depth_stencil_alpha_state(&r300->context,
+                                                           &dsa);
+    }
+
+    /* Print driver info. */
+#ifdef NDEBUG
+    if (DBG_ON(r300, DBG_INFO)) {
+#else
+    {
+#endif
+        fprintf(stderr,
+                "r300: DRM version: %d.%d.%d, Name: %s, ID: 0x%04x, GB: %d, Z: %d\n"
+                "r300: GART size: %d MB, VRAM size: %d MB\n"
+                "r300: AA compression: %s, Z compression: %s, HiZ: %s\n",
+                rws->get_value(rws, R300_VID_DRM_MAJOR),
+                rws->get_value(rws, R300_VID_DRM_MINOR),
+                rws->get_value(rws, R300_VID_DRM_PATCHLEVEL),
+                screen->get_name(screen),
+                rws->get_value(rws, R300_VID_PCI_ID),
+                rws->get_value(rws, R300_VID_GB_PIPES),
+                rws->get_value(rws, R300_VID_Z_PIPES),
+                rws->get_value(rws, R300_VID_GART_SIZE) >> 20,
+                rws->get_value(rws, R300_VID_VRAM_SIZE) >> 20,
+                rws->get_value(rws, R300_CAN_AACOMPRESS) ? "YES" : "NO",
+                rws->get_value(rws, R300_CAN_HYPERZ) ? "YES" : "NO",
+                rws->get_value(rws, R300_CAN_HYPERZ) &&
+                r300->screen->caps.hiz_ram ? "YES" : "NO");
+    }
+
     return &r300->context;
 
- fail:
+fail:
     r300_destroy_context(&r300->context);
     return NULL;
 }
-
-void r300_finish(struct r300_context *r300)
-{
-    struct pipe_framebuffer_state *fb;
-    unsigned i;
-
-    /* This is a preliminary implementation of glFinish.
-     *
-     * The ideal implementation should use something like EmitIrqLocked and
-     * WaitIrq, or better, real fences.
-     */
-    if (r300->fb_state.state) {
-        fb = r300->fb_state.state;
-
-        for (i = 0; i < fb->nr_cbufs; i++) {
-            if (fb->cbufs[i]->texture) {
-                r300->rws->buffer_wait(r300->rws,
-                    r300_texture(fb->cbufs[i]->texture)->buffer);
-                return;
-            }
-        }
-        if (fb->zsbuf && fb->zsbuf->texture) {
-            r300->rws->buffer_wait(r300->rws,
-                r300_texture(fb->zsbuf->texture)->buffer);
-        }
-    }
-}
index e09cf87f733eac04572145cfa2f7a6c3f9e68475..300737594768447e5268081cc5c48e0fbce88aa8 100644 (file)
 #include "pipe/p_context.h"
 #include "util/u_inlines.h"
 #include "util/u_transfer.h"
-
-#include "translate/translate_cache.h"
+#include "util/u_vbuf_mgr.h"
 
 #include "r300_defines.h"
 #include "r300_screen.h"
+#include "r300_winsys.h"
 
 struct u_upload_mgr;
 struct r300_context;
@@ -189,11 +189,6 @@ struct r300_sampler_view {
     uint32_t texcache_region;
 };
 
-struct r300_texture_fb_state {
-    uint32_t pitch[R300_MAX_TEXTURE_LEVELS]; /* COLORPITCH or DEPTHPITCH. */
-    uint32_t format; /* US_OUT_FMT or R300_ZB_FORMAT */
-};
-
 struct r300_texture_sampler_state {
     struct r300_texture_format_state format;
     uint32_t filter0;      /* R300_TX_FILTER0: 0x4400 */
@@ -273,14 +268,12 @@ struct r300_query {
     /* 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;
     /* if begin has been emitted */
     boolean begin_emitted;
 
     /* The buffer where query results are stored. */
-    struct r300_winsys_buffer *buffer;
-    struct r300_winsys_cs_buffer *cs_buffer;
+    struct r300_winsys_bo *buf;
+    struct r300_winsys_cs_handle *cs_buf;
     /* The size of the buffer. */
     unsigned buffer_size;
     /* The domain of the buffer. */
@@ -291,28 +284,12 @@ struct r300_query {
     struct r300_query* next;
 };
 
-/* Fence object.
- *
- * This is a fake fence. Instead of syncing with the fence, we sync
- * with the context, which is inefficient but compliant.
- *
- * This is not a subclass of pipe_fence_handle because pipe_fence_handle is
- * never actually fully defined. So, rather than have it as a member, and do
- * subclass-style casting, we treat pipe_fence_handle as an opaque, and just
- * trust that our state tracker does not ever mess up fence objects.
- */
-struct r300_fence {
-    struct pipe_reference reference;
-    struct r300_context *ctx;
-    boolean signalled;
-};
-
 struct r300_surface {
     struct pipe_surface base;
 
     /* Winsys buffer backing the texture. */
-    struct r300_winsys_buffer *buffer;
-    struct r300_winsys_cs_buffer *cs_buffer;
+    struct r300_winsys_bo *buf;
+    struct r300_winsys_cs_handle *cs_buf;
 
     enum r300_buffer_domain domain;
 
@@ -329,13 +306,9 @@ struct r300_surface {
 
     /* Whether the CBZB clear is allowed on the surface. */
     boolean cbzb_allowed;
-
 };
 
 struct r300_texture_desc {
-    /* Parent class. */
-    struct u_resource b;
-
     /* Width, height, and depth.
      * Most of the time, these are equal to pipe_texture::width0, height0,
      * and depth0. However, NPOT 3D textures must have dimensions aligned
@@ -387,27 +360,38 @@ struct r300_texture_desc {
 
     /* Whether CBZB fast color clear is allowed on the miplevel. */
     boolean cbzb_allowed[R300_MAX_TEXTURE_LEVELS];
+
+    /* Zbuffer compression info for each miplevel. */
+    boolean zcomp8x8[R300_MAX_TEXTURE_LEVELS];
+    /* If zero, then disable compression. */
+    unsigned zmask_dwords[R300_MAX_TEXTURE_LEVELS];
 };
 
-struct r300_texture {
-    struct r300_texture_desc desc;
+struct r300_resource
+{
+    struct u_vbuf_resource b;
 
+    /* Winsys buffer backing this resource. */
+    struct r300_winsys_bo *buf;
+    struct r300_winsys_cs_handle *cs_buf;
     enum r300_buffer_domain domain;
+    unsigned buf_size;
+
+    /* Constant buffers are in user memory. */
+    uint8_t *constant_buffer;
 
-    /* Pipe buffer backing this texture. */
-    struct r300_winsys_buffer *buffer;
-    struct r300_winsys_cs_buffer *cs_buffer;
+    /* Texture description (addressing, layout, special features). */
+    struct r300_texture_desc tex;
 
     /* Registers carrying texture format data. */
     /* Only format-independent bits should be filled in. */
     struct r300_texture_format_state tx_format;
-    /* All bits should be filled in. */
-    struct r300_texture_fb_state fb_state;
 
-    /* hyper-z memory allocs */
+    /* Where the texture starts in the buffer. */
+    unsigned tex_offset;
+
+    /* HiZ memory allocations. */
     struct mem_block *hiz_mem[R300_MAX_TEXTURE_LEVELS];
-    struct mem_block *zmask_mem[R300_MAX_TEXTURE_LEVELS];
-    boolean zmask_in_use[R300_MAX_TEXTURE_LEVELS];
     boolean hiz_in_use[R300_MAX_TEXTURE_LEVELS];
 
     /* This is the level tiling flags were last time set for.
@@ -418,32 +402,16 @@ struct r300_texture {
 struct r300_vertex_element_state {
     unsigned count;
     struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS];
+    unsigned format_size[PIPE_MAX_ATTRIBS];
 
-    /* If (velem[i].src_format != hw_format[i]), the vertex buffer
-     * referenced by this vertex element cannot be used for rendering and
-     * its vertex data must be translated to hw_format[i]. */
-    enum pipe_format hw_format[PIPE_MAX_ATTRIBS];
-    unsigned hw_format_size[PIPE_MAX_ATTRIBS];
+    struct u_vbuf_mgr_elements *vmgr_elements;
 
     /* The size of the vertex, in dwords. */
     unsigned vertex_size_dwords;
 
-    /* This might mean two things:
-     * - src_format != hw_format, as discussed above.
-     * - src_offset % 4 != 0. */
-    boolean incompatible_layout;
-
     struct r300_vertex_stream_state vertex_stream;
 };
 
-struct r300_translate_context {
-    /* Translate cache for incompatible vertex offset/stride/format fallback. */
-    struct translate_cache *translate_cache;
-
-    /* Saved and new vertex element state. */
-    void *saved_velems, *new_velems;
-};
-
 struct r300_context {
     /* Parent class */
     struct pipe_context context;
@@ -456,7 +424,6 @@ struct r300_context {
     struct r300_screen *screen;
 
     /* Draw module. Used mostly for SW TCL. */
-    struct gallivm_state *gallivm;
     struct draw_context* draw;
     /* Vertex buffer for SW TCL. */
     struct pipe_resource* vbo;
@@ -471,8 +438,6 @@ struct r300_context {
     struct blitter_context* blitter;
     /* Stencil two-sided reference value fallback. */
     struct r300_stencilref_context *stencilref_fallback;
-    /* For translating vertex buffers having incompatible vertex layout. */
-    struct r300_translate_context tran;
 
     /* The KIL opcode needs the first texture unit to be enabled
      * on r3xx-r4xx. In order to calm down the CS checker, we bind this
@@ -554,14 +519,6 @@ struct r300_context {
     /* The pointers to the first and the last atom. */
     struct r300_atom *first_dirty, *last_dirty;
 
-    /* Vertex buffers for Gallium. */
-    /* May contain user buffers. */
-    struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
-    /* Contains only non-user buffers. */
-    struct pipe_resource *valid_vertex_buffer[PIPE_MAX_ATTRIBS];
-    int vertex_buffer_count;
-    int vertex_buffer_max_index;
-    boolean any_user_vbs;
     /* Vertex elements for Gallium. */
     struct r300_vertex_element_state *velems;
 
@@ -588,21 +545,23 @@ struct r300_context {
     int sprite_coord_enable;
     /* Whether two-sided color selection is enabled (AKA light_twoside). */
     boolean two_sided_color;
-    /* Incompatible vertex buffer layout? (misaligned stride or buffer_offset) */
-    boolean incompatible_vb_layout;
-#define R300_Z_COMPRESS_44 1
-#define RV350_Z_COMPRESS_88 2
-    int z_compression;
+
     boolean cbzb_clear;
-    boolean z_decomp_rd;
+    /* Whether ZMASK is enabled. */
+    boolean zmask_in_use;
+    /* Whether ZMASK is being decompressed. */
+    boolean zmask_decompress;
+    /* Whether ZMASK is locked, i.e. should be disabled and cannot be taken over. */
+    boolean zmask_locked;
+    /* The zbuffer the ZMASK of which is locked. */
+    struct pipe_surface *locked_zbuffer;
+
+    void *dsa_decompress_zmask;
 
     /* two mem block managers for hiz/zmask ram space */
     struct mem_block *hiz_mm;
-    struct mem_block *zmask_mm;
 
-    /* upload managers */
-    struct u_upload_mgr *upload_vb;
-    struct u_upload_mgr *upload_ib;
+    struct u_vbuf_mgr *vbuf_mgr;
 
     struct util_slab_mempool pool_transfers;
 
@@ -612,16 +571,10 @@ struct r300_context {
     /* const tracking for VS */
     int vs_const_base;
 
-    /* AOS (PACKET3_3D_LOAD_VBPNTR) command buffer for the case offset=0. */
-    uint32_t vertex_arrays_cb[(16 * 3 + 1) / 2];
+    /* Vertex array state info */
     boolean vertex_arrays_dirty;
-
-    /* Whether any buffer (FB, textures, VBOs) has been set, but buffers
-     * haven't been validated yet. */
-    boolean validate_buffers;
-    /* Whether user buffers have been validated. */
-    boolean upload_vb_validated;
-    boolean upload_ib_validated;
+    boolean vertex_arrays_indexed;
+    int vertex_arrays_offset;
 };
 
 #define foreach_atom(r300, atom) \
@@ -641,9 +594,9 @@ static INLINE struct r300_surface* r300_surface(struct pipe_surface* surf)
     return (struct r300_surface*)surf;
 }
 
-static INLINE struct r300_texture* r300_texture(struct pipe_resource* tex)
+static INLINE struct r300_resource* r300_resource(struct pipe_resource* tex)
 {
-    return (struct r300_texture*)tex;
+    return (struct r300_resource*)tex;
 }
 
 static INLINE struct r300_context* r300_context(struct pipe_context* context)
@@ -675,7 +628,6 @@ static INLINE void r300_mark_atom_dirty(struct r300_context *r300,
 struct pipe_context* r300_create_context(struct pipe_screen* screen,
                                          void *priv);
 
-void r300_finish(struct r300_context *r300);
 void r300_flush_cb(void *data);
 
 /* Context initialization. */
@@ -688,7 +640,9 @@ void r300_init_state_functions(struct r300_context* r300);
 void r300_init_resource_functions(struct r300_context* r300);
 
 /* r300_blit.c */
-void r300_flush_depth_textures(struct r300_context *r300);
+void r300_decompress_zmask(struct r300_context *r300);
+void r300_decompress_zmask_locked_unsafe(struct r300_context *r300);
+void r300_decompress_zmask_locked(struct r300_context *r300);
 
 /* r300_query.c */
 void r300_resume_query(struct r300_context *r300,
@@ -696,9 +650,6 @@ void r300_resume_query(struct r300_context *r300,
 void r300_stop_query(struct r300_context *r300);
 
 /* r300_render_translate.c */
-void r300_begin_vertex_translate(struct r300_context *r300,
-                                 int min_index, int max_index);
-void r300_end_vertex_translate(struct r300_context *r300);
 void r300_translate_index_buffer(struct r300_context *r300,
                                  struct pipe_resource **index_buffer,
                                  unsigned *index_size, unsigned index_offset,
@@ -714,8 +665,7 @@ 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,
-    R300_CHANGED_CBZB_FLAG,
-    R300_CHANGED_ZCLEAR_FLAG,
+    R300_CHANGED_HYPERZ_FLAG,
     R300_CHANGED_MULTIWRITE
 };
 
index 6726f100e1b9ae562123e78582d29b487d60f047..2e52dfa43c6a17e36e1c6ec040f712f2407b141c 100644 (file)
  * that they neatly hide away, and don't have the cost of function setup,so
  * we're going to use them. */
 
-#ifdef DEBUG
-#define CS_DEBUG(x) x
-#else
-#define CS_DEBUG(x)
-#endif
-
 /**
  * Command submission setup.
  */
     struct r300_winsys_screen *cs_winsys = (context)->rws; \
     int cs_count = 0; (void) cs_count; (void) cs_winsys;
 
+#ifdef DEBUG
+
 #define BEGIN_CS(size) do { \
     assert(size <= (R300_MAX_CMDBUF_DWORDS - cs_copy->cdw)); \
-    CS_DEBUG(cs_count = size;) \
+    cs_count = size; \
 } while (0)
 
-#ifdef DEBUG
 #define END_CS do { \
     if (cs_count != 0) \
         debug_printf("r300: Warning: cs_count off by %d at (%s, %s:%i)\n", \
                      cs_count, __FUNCTION__, __FILE__, __LINE__); \
     cs_count = 0; \
 } while (0)
+
+#define CS_USED_DW(x) cs_count -= (x)
+
 #else
+
+#define BEGIN_CS(size)
 #define END_CS
-#endif
+#define CS_USED_DW(x)
 
+#endif
 
 /**
  * Writing pure DWORDs.
@@ -73,7 +74,7 @@
 
 #define OUT_CS(value) do { \
     cs_copy->buf[cs_copy->cdw++] = (value); \
-    CS_DEBUG(cs_count--;) \
+    CS_USED_DW(1); \
 } while (0)
 
 #define OUT_CS_32F(value) \
@@ -98,7 +99,7 @@
 #define OUT_CS_TABLE(values, count) do { \
     memcpy(cs_copy->buf + cs_copy->cdw, values, count * 4); \
     cs_copy->cdw += count; \
-    CS_DEBUG(cs_count -= count;) \
+    CS_USED_DW(count); \
 } while (0)
 
 
  * Writing relocations.
  */
 
-#define OUT_CS_RELOC(bo, offset) do { \
-    assert(bo); \
-    OUT_CS(offset); \
-    cs_winsys->cs_write_reloc(cs_copy, bo); \
-    CS_DEBUG(cs_count -= 2;) \
-} while (0)
-
-#define OUT_CS_BUF_RELOC(bo, offset) do { \
-    assert(bo); \
-    OUT_CS_RELOC(r300_buffer(bo)->cs_buf, offset); \
-} while (0)
-
-#define OUT_CS_TEX_RELOC(tex, offset) do { \
-    assert(tex); \
-    OUT_CS_RELOC(tex->cs_buffer, offset); \
-} while (0)
-
-#define OUT_CS_BUF_RELOC_NO_OFFSET(bo) do { \
-    assert(bo); \
-    cs_winsys->cs_write_reloc(cs_copy, r300_buffer(bo)->cs_buf); \
-    CS_DEBUG(cs_count -= 2;) \
+#define OUT_CS_RELOC(r) do { \
+    assert((r)); \
+    assert((r)->cs_buf); \
+    cs_winsys->cs_write_reloc(cs_copy, (r)->cs_buf); \
+    CS_USED_DW(2); \
 } while (0)
 
 
  */
 
 #define WRITE_CS_TABLE(values, count) do { \
-    CS_DEBUG(assert(cs_count == 0);) \
+    assert(cs_count == 0); \
     memcpy(cs_copy->buf + cs_copy->cdw, (values), (count) * 4); \
     cs_copy->cdw += (count); \
 } while (0)
index d6aa90bd0530d38190806acff463694732e174fa..b60cfd1f248084d74852f3594eb63721a7b8dfb6 100644 (file)
@@ -27,6 +27,7 @@
 #include <stdio.h>
 
 static const struct debug_named_value debug_options[] = {
+    { "info", DBG_INFO, "Print hardware info"},
     { "fp", DBG_FP, "Log fragment program compilation" },
     { "vp", DBG_VP, "Log vertex program compilation" },
     { "pstat", DBG_P_STAT, "Log vertex/fragment program stats" },
@@ -49,6 +50,8 @@ static const struct debug_named_value debug_options[] = {
     { "noimmd", DBG_NO_IMMD, "Disable immediate mode" },
     { "noopt", DBG_NO_OPT, "Disable shader optimizations" },
     { "nocbzb", DBG_NO_CBZB, "Disable fast color clear" },
+    { "nozmask", DBG_NO_ZMASK, "Disable zbuffer compression" },
+    { "nohiz", DBG_NO_HIZ, "Disable hierarchical zbuffer" },
 
     /* must be last */
     DEBUG_NAMED_VALUE_END
index d14cdcbbaf0629a9a59411e5191a31ec1efaedd5..e2e4719ec82113ffcf7b80cbc6e1839b23fad28c 100644 (file)
@@ -89,7 +89,7 @@ static void get_rc_constant_state(
     struct rc_constant * constant)
 {
     struct r300_textures_state* texstate = r300->textures_state.state;
-    struct r300_texture *tex;
+    struct r300_resource *tex;
 
     assert(constant->Type == RC_CONSTANT_STATE);
 
@@ -101,19 +101,19 @@ static void get_rc_constant_state(
         /* Factor for converting rectangle coords to
          * normalized coords. Should only show up on non-r500. */
         case RC_STATE_R300_TEXRECT_FACTOR:
-            tex = r300_texture(texstate->sampler_views[constant->u.State[1]]->base.texture);
-            vec[0] = 1.0 / tex->desc.width0;
-            vec[1] = 1.0 / tex->desc.height0;
+            tex = r300_resource(texstate->sampler_views[constant->u.State[1]]->base.texture);
+            vec[0] = 1.0 / tex->tex.width0;
+            vec[1] = 1.0 / tex->tex.height0;
             vec[2] = 0;
             vec[3] = 1;
             break;
 
         case RC_STATE_R300_TEXSCALE_FACTOR:
-            tex = r300_texture(texstate->sampler_views[constant->u.State[1]]->base.texture);
+            tex = r300_resource(texstate->sampler_views[constant->u.State[1]]->base.texture);
             /* Add a small number to the texture size to work around rounding errors in hw. */
-            vec[0] = tex->desc.b.b.width0  / (tex->desc.width0  + 0.001f);
-            vec[1] = tex->desc.b.b.height0 / (tex->desc.height0 + 0.001f);
-            vec[2] = tex->desc.b.b.depth0  / (tex->desc.depth0  + 0.001f);
+            vec[0] = tex->b.b.b.width0  / (tex->tex.width0  + 0.001f);
+            vec[1] = tex->b.b.b.height0 / (tex->tex.height0 + 0.001f);
+            vec[2] = tex->b.b.b.depth0  / (tex->tex.depth0  + 0.001f);
             vec[3] = 1;
             break;
 
@@ -352,11 +352,9 @@ void r300_emit_aa_state(struct r300_context *r300, unsigned size, void *state)
     OUT_CS_REG(R300_GB_AA_CONFIG, aa->aa_config);
 
     if (aa->dest) {
-        OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_OFFSET, 1);
-        OUT_CS_RELOC(aa->dest->cs_buffer, aa->dest->offset);
-
-        OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_PITCH, 1);
-        OUT_CS_RELOC(aa->dest->cs_buffer, aa->dest->pitch);
+        OUT_CS_REG(R300_RB3D_AARESOLVE_OFFSET, aa->dest->offset);
+        OUT_CS_RELOC(aa->dest);
+        OUT_CS_REG(R300_RB3D_AARESOLVE_PITCH, aa->dest->pitch);
     }
 
     OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, aa->aaresolve_ctl);
@@ -391,11 +389,11 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
     for (i = 0; i < fb->nr_cbufs; i++) {
         surf = r300_surface(fb->cbufs[i]);
 
-        OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1);
-        OUT_CS_RELOC(surf->cs_buffer, surf->offset);
+        OUT_CS_REG(R300_RB3D_COLOROFFSET0 + (4 * i), surf->offset);
+        OUT_CS_RELOC(surf);
 
-        OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1);
-        OUT_CS_RELOC(surf->cs_buffer, surf->pitch);
+        OUT_CS_REG(R300_RB3D_COLORPITCH0 + (4 * i), surf->pitch);
+        OUT_CS_RELOC(surf);
     }
 
     /* Set up the ZB part of the CBZB clear. */
@@ -404,11 +402,11 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
 
         OUT_CS_REG(R300_ZB_FORMAT, surf->cbzb_format);
 
-        OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1);
-        OUT_CS_RELOC(surf->cs_buffer, surf->cbzb_midpoint_offset);
+        OUT_CS_REG(R300_ZB_DEPTHOFFSET, surf->cbzb_midpoint_offset);
+        OUT_CS_RELOC(surf);
 
-        OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1);
-        OUT_CS_RELOC(surf->cs_buffer, surf->cbzb_pitch);
+        OUT_CS_REG(R300_ZB_DEPTHPITCH, surf->cbzb_pitch);
+        OUT_CS_RELOC(surf);
 
         DBG(r300, DBG_CBZB,
             "CBZB clearing cbuf %08x %08x\n", surf->cbzb_format,
@@ -420,19 +418,20 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
 
         OUT_CS_REG(R300_ZB_FORMAT, surf->format);
 
-        OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1);
-        OUT_CS_RELOC(surf->cs_buffer, surf->offset);
+        OUT_CS_REG(R300_ZB_DEPTHOFFSET, surf->offset);
+        OUT_CS_RELOC(surf);
 
-        OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1);
-        OUT_CS_RELOC(surf->cs_buffer, surf->pitch);
+        OUT_CS_REG(R300_ZB_DEPTHPITCH, surf->pitch);
+        OUT_CS_RELOC(surf);
 
         if (can_hyperz) {
             uint32_t surf_pitch;
-            struct r300_texture *tex;
+            struct r300_resource *tex;
             int level = surf->base.u.tex.level;
-            tex = r300_texture(surf->base.texture);
+            tex = r300_resource(surf->base.texture);
 
             surf_pitch = surf->pitch & R300_DEPTHPITCH_MASK;
+
             /* HiZ RAM. */
             if (r300->screen->caps.hiz_ram) {
                 if (tex->hiz_mem[level]) {
@@ -443,14 +442,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
                     OUT_CS_REG(R300_ZB_HIZ_PITCH, 0);
                 }
             }
+
             /* Z Mask RAM. (compressed zbuffer) */
-            if (tex->zmask_mem[level]) {
-                OUT_CS_REG(R300_ZB_ZMASK_OFFSET, tex->zmask_mem[level]->ofs << 2);
-                OUT_CS_REG(R300_ZB_ZMASK_PITCH, surf_pitch);
-            } else {
-                OUT_CS_REG(R300_ZB_ZMASK_OFFSET, 0);
-                OUT_CS_REG(R300_ZB_ZMASK_PITCH, 0);
-            }
+            OUT_CS_REG(R300_ZB_ZMASK_OFFSET, 0);
+            OUT_CS_REG(R300_ZB_ZMASK_PITCH, surf_pitch);
         }
     }
 
@@ -462,6 +457,7 @@ void r300_emit_hyperz_state(struct r300_context *r300,
 {
     struct r300_hyperz_state *z = state;
     CS_LOCALS(r300);
+
     if (z->flush)
         WRITE_CS_TABLE(&z->cb_flush_begin, size);
     else
@@ -563,14 +559,12 @@ void r300_emit_query_start(struct r300_context *r300, unsigned size, void*state)
     OUT_CS_REG(R300_ZB_ZPASS_DATA, 0);
     END_CS;
     query->begin_emitted = TRUE;
-    query->flushed = FALSE;
 }
 
 static void r300_emit_query_end_frag_pipes(struct r300_context *r300,
                                            struct r300_query *query)
 {
     struct r300_capabilities* caps = &r300->screen->caps;
-    struct r300_winsys_cs_buffer *buf = r300->query_current->cs_buffer;
     CS_LOCALS(r300);
 
     assert(caps->num_frag_pipes);
@@ -588,25 +582,25 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300,
         case 4:
             /* pipe 3 only */
             OUT_CS_REG(R300_SU_REG_DEST, 1 << 3);
-            OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
-            OUT_CS_RELOC(buf, (query->num_results + 3) * 4);
+            OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 3) * 4);
+            OUT_CS_RELOC(r300->query_current);
         case 3:
             /* pipe 2 only */
             OUT_CS_REG(R300_SU_REG_DEST, 1 << 2);
-            OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
-            OUT_CS_RELOC(buf, (query->num_results + 2) * 4);
+            OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 2) * 4);
+            OUT_CS_RELOC(r300->query_current);
         case 2:
             /* pipe 1 only */
             /* As mentioned above, accomodate RV380 and older. */
             OUT_CS_REG(R300_SU_REG_DEST,
                     1 << (caps->high_second_pipe ? 3 : 1));
-            OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
-            OUT_CS_RELOC(buf, (query->num_results + 1) * 4);
+            OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 1) * 4);
+            OUT_CS_RELOC(r300->query_current);
         case 1:
             /* pipe 0 only */
             OUT_CS_REG(R300_SU_REG_DEST, 1 << 0);
-            OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
-            OUT_CS_RELOC(buf, (query->num_results + 0) * 4);
+            OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 0) * 4);
+            OUT_CS_RELOC(r300->query_current);
             break;
         default:
             fprintf(stderr, "r300: Implementation error: Chipset reports %d"
@@ -622,13 +616,12 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300,
 static void rv530_emit_query_end_single_z(struct r300_context *r300,
                                           struct r300_query *query)
 {
-    struct r300_winsys_cs_buffer *buf = r300->query_current->cs_buffer;
     CS_LOCALS(r300);
 
     BEGIN_CS(8);
     OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
-    OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
-    OUT_CS_RELOC(buf, query->num_results * 4);
+    OUT_CS_REG(R300_ZB_ZPASS_ADDR, query->num_results * 4);
+    OUT_CS_RELOC(r300->query_current);
     OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
     END_CS;
 }
@@ -636,16 +629,15 @@ static void rv530_emit_query_end_single_z(struct r300_context *r300,
 static void rv530_emit_query_end_double_z(struct r300_context *r300,
                                           struct r300_query *query)
 {
-    struct r300_winsys_cs_buffer *buf = r300->query_current->cs_buffer;
     CS_LOCALS(r300);
 
     BEGIN_CS(14);
     OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
-    OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
-    OUT_CS_RELOC(buf, (query->num_results + 0) * 4);
+    OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 0) * 4);
+    OUT_CS_RELOC(r300->query_current);
     OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1);
-    OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
-    OUT_CS_RELOC(buf, (query->num_results + 1) * 4);
+    OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 1) * 4);
+    OUT_CS_RELOC(r300->query_current);
     OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
     END_CS;
 }
@@ -784,7 +776,7 @@ void r300_emit_textures_state(struct r300_context *r300,
 {
     struct r300_textures_state *allstate = (struct r300_textures_state*)state;
     struct r300_texture_sampler_state *texstate;
-    struct r300_texture *tex;
+    struct r300_resource *tex;
     unsigned i;
     CS_LOCALS(r300);
 
@@ -794,7 +786,7 @@ void r300_emit_textures_state(struct r300_context *r300,
     for (i = 0; i < allstate->count; i++) {
         if ((1 << i) & allstate->tx_enable) {
             texstate = &allstate->regs[i];
-            tex = r300_texture(allstate->sampler_views[i]->base.texture);
+            tex = r300_resource(allstate->sampler_views[i]->base.texture);
 
             OUT_CS_REG(R300_TX_FILTER0_0 + (i * 4), texstate->filter0);
             OUT_CS_REG(R300_TX_FILTER1_0 + (i * 4), texstate->filter1);
@@ -805,96 +797,56 @@ void r300_emit_textures_state(struct r300_context *r300,
             OUT_CS_REG(R300_TX_FORMAT1_0 + (i * 4), texstate->format.format1);
             OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format.format2);
 
-            OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (i * 4), 1);
-            OUT_CS_TEX_RELOC(tex, texstate->format.tile_config);
+            OUT_CS_REG(R300_TX_OFFSET_0 + (i * 4), texstate->format.tile_config);
+            OUT_CS_RELOC(tex);
         }
     }
     END_CS;
 }
 
-static void r300_update_vertex_arrays_cb(struct r300_context *r300, unsigned packet_size)
+void r300_emit_vertex_arrays(struct r300_context* r300, int offset, boolean indexed)
 {
-    struct pipe_vertex_buffer *vb1, *vb2, *vbuf = r300->vertex_buffer;
+    struct pipe_vertex_buffer *vbuf = r300->vbuf_mgr->vertex_buffer;
+    struct pipe_resource **valid_vbuf = r300->vbuf_mgr->real_vertex_buffer;
     struct pipe_vertex_element *velem = r300->velems->velem;
-    unsigned *hw_format_size = r300->velems->hw_format_size;
-    unsigned size1, size2, vertex_array_count = r300->velems->count;
+    struct r300_resource *buf;
     int i;
-    CB_LOCALS;
+    unsigned vertex_array_count = r300->velems->count;
+    unsigned packet_size = (vertex_array_count * 3 + 1) / 2;
+    struct pipe_vertex_buffer *vb1, *vb2;
+    unsigned *hw_format_size;
+    unsigned size1, size2;
+    CS_LOCALS(r300);
+
+    BEGIN_CS(2 + packet_size + vertex_array_count * 2);
+    OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size);
+    OUT_CS(vertex_array_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0));
+
+    hw_format_size = r300->velems->format_size;
 
-    BEGIN_CB(r300->vertex_arrays_cb, packet_size);
     for (i = 0; i < vertex_array_count - 1; i += 2) {
         vb1 = &vbuf[velem[i].vertex_buffer_index];
         vb2 = &vbuf[velem[i+1].vertex_buffer_index];
         size1 = hw_format_size[i];
         size2 = hw_format_size[i+1];
 
-        OUT_CB(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) |
+        OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) |
                R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride));
-        OUT_CB(vb1->buffer_offset + velem[i].src_offset);
-        OUT_CB(vb2->buffer_offset + velem[i+1].src_offset);
+        OUT_CS(vb1->buffer_offset + velem[i].src_offset   + offset * vb1->stride);
+        OUT_CS(vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride);
     }
 
     if (vertex_array_count & 1) {
         vb1 = &vbuf[velem[i].vertex_buffer_index];
         size1 = hw_format_size[i];
 
-        OUT_CB(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride));
-        OUT_CB(vb1->buffer_offset + velem[i].src_offset);
-    }
-    END_CB;
-
-    r300->vertex_arrays_dirty = FALSE;
-}
-
-void r300_emit_vertex_arrays(struct r300_context* r300, int offset, boolean indexed)
-{
-    struct pipe_vertex_buffer *vbuf = r300->vertex_buffer;
-    struct pipe_resource **valid_vbuf = r300->valid_vertex_buffer;
-    struct pipe_vertex_element *velem = r300->velems->velem;
-    struct r300_buffer *buf;
-    int i;
-    unsigned vertex_array_count = r300->velems->count;
-    unsigned packet_size = (vertex_array_count * 3 + 1) / 2;
-    CS_LOCALS(r300);
-
-    BEGIN_CS(2 + packet_size + vertex_array_count * 2);
-    OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size);
-    OUT_CS(vertex_array_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0));
-
-    if (!offset) {
-        if (r300->vertex_arrays_dirty) {
-            r300_update_vertex_arrays_cb(r300, packet_size);
-        }
-        OUT_CS_TABLE(r300->vertex_arrays_cb, packet_size);
-    } else {
-        struct pipe_vertex_buffer *vb1, *vb2;
-        unsigned *hw_format_size = r300->velems->hw_format_size;
-        unsigned size1, size2;
-
-        for (i = 0; i < vertex_array_count - 1; i += 2) {
-            vb1 = &vbuf[velem[i].vertex_buffer_index];
-            vb2 = &vbuf[velem[i+1].vertex_buffer_index];
-            size1 = hw_format_size[i];
-            size2 = hw_format_size[i+1];
-
-            OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) |
-                   R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride));
-            OUT_CS(vb1->buffer_offset + velem[i].src_offset   + offset * vb1->stride);
-            OUT_CS(vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride);
-        }
-
-        if (vertex_array_count & 1) {
-            vb1 = &vbuf[velem[i].vertex_buffer_index];
-            size1 = hw_format_size[i];
-
-            OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride));
-            OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride);
-        }
+        OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride));
+        OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride);
     }
 
     for (i = 0; i < vertex_array_count; i++) {
-        buf = r300_buffer(valid_vbuf[velem[i].vertex_buffer_index]);
-        OUT_CS_BUF_RELOC_NO_OFFSET(&buf->b.b);
+        buf = r300_resource(valid_vbuf[velem[i].vertex_buffer_index]);
+        OUT_CS_RELOC(buf);
     }
     END_CS;
 }
@@ -919,7 +871,8 @@ void r300_emit_vertex_arrays_swtcl(struct r300_context *r300, boolean indexed)
     OUT_CS(r300->vertex_info.size |
             (r300->vertex_info.size << 8));
     OUT_CS(r300->draw_vbo_offset);
-    OUT_CS_BUF_RELOC(r300->vbo, 0);
+    OUT_CS(0);
+    OUT_CS_RELOC(r300_resource(r300->vbo));
     END_CS;
 }
 
@@ -1097,17 +1050,6 @@ static void r300_emit_hiz_line_clear(struct r300_context *r300, int start, uint1
     END_CS;
 }
 
-static void r300_emit_zmask_line_clear(struct r300_context *r300, int start, uint16_t count, uint32_t val)
-{
-    CS_LOCALS(r300);
-    BEGIN_CS(4);
-    OUT_CS_PKT3(R300_PACKET3_3D_CLEAR_ZMASK, 2);
-    OUT_CS(start);
-    OUT_CS(count);
-    OUT_CS(val);
-    END_CS;
-}
-
 #define ALIGN_DIVUP(x, y) (((x) + (y) - 1) / (y))
 
 void r300_emit_hiz_clear(struct r300_context *r300, unsigned size, void *state)
@@ -1118,13 +1060,13 @@ void r300_emit_hiz_clear(struct r300_context *r300, unsigned size, void *state)
         (struct r300_hyperz_state*)r300->hyperz_state.state;
     struct r300_screen* r300screen = r300->screen;
     uint32_t stride, offset = 0, height, offset_shift;
-    struct r300_texture* tex;
+    struct r300_resource* tex;
     int i;
 
-    tex = r300_texture(fb->zsbuf->texture);
+    tex = r300_resource(fb->zsbuf->texture);
 
     offset = tex->hiz_mem[fb->zsbuf->u.tex.level]->ofs;
-    stride = tex->desc.stride_in_pixels[fb->zsbuf->u.tex.level];
+    stride = tex->tex.stride_in_pixels[fb->zsbuf->u.tex.level];
 
     /* convert from pixels to 4x4 blocks */
     stride = ALIGN_DIVUP(stride, 4);
@@ -1153,42 +1095,21 @@ void r300_emit_zmask_clear(struct r300_context *r300, unsigned size, void *state
 {
     struct pipe_framebuffer_state *fb =
         (struct pipe_framebuffer_state*)r300->fb_state.state;
-    struct r300_screen* r300screen = r300->screen;
-    uint32_t stride, offset = 0;
-    struct r300_texture* tex;
-    uint32_t i, height;
-    int mult, offset_shift;
-
-    tex = r300_texture(fb->zsbuf->texture);
-    stride = tex->desc.stride_in_pixels[fb->zsbuf->u.tex.level];
-
-    offset = tex->zmask_mem[fb->zsbuf->u.tex.level]->ofs;
-
-    if (r300->z_compression == RV350_Z_COMPRESS_88)
-        mult = 8;
-    else
-        mult = 4;
-
-    height = ALIGN_DIVUP(fb->zsbuf->height, mult);
-
-    offset_shift = 4;
-    offset_shift += (r300screen->caps.num_frag_pipes / 2);
-    stride = ALIGN_DIVUP(stride, r300screen->caps.num_frag_pipes);
+    struct r300_resource *tex;
+    CS_LOCALS(r300);
 
-    /* okay have width in pixels - divide by block width */
-    stride = ALIGN_DIVUP(stride, mult);
-    /* have width in blocks - divide by number of fragment pipes screen width */
-    /* 16 blocks per dword */
-    stride = ALIGN_DIVUP(stride, 16);
+    tex = r300_resource(fb->zsbuf->texture);
 
-    for (i = 0; i < height; i++) {
-        offset = i * stride;
-        offset <<= offset_shift;
-        r300_emit_zmask_line_clear(r300, offset, stride, 0x0);//0xffffffff);
-    }
+    BEGIN_CS(size);
+    OUT_CS_PKT3(R300_PACKET3_3D_CLEAR_ZMASK, 2);
+    OUT_CS(0);
+    OUT_CS(tex->tex.zmask_dwords[fb->zsbuf->u.tex.level]);
+    OUT_CS(0);
+    END_CS;
 
     /* Mark the current zbuffer's zmask as in use. */
-    tex->zmask_in_use[fb->zsbuf->u.tex.level] = TRUE;
+    r300->zmask_in_use = TRUE;
+    r300_mark_atom_dirty(r300, &r300->hyperz_state);
 }
 
 void r300_emit_ztop_state(struct r300_context* r300,
@@ -1219,7 +1140,7 @@ boolean r300_emit_buffer_validate(struct r300_context *r300,
         (struct pipe_framebuffer_state*)r300->fb_state.state;
     struct r300_textures_state *texstate =
         (struct r300_textures_state*)r300->textures_state.state;
-    struct r300_texture *tex;
+    struct r300_resource *tex;
     unsigned i;
     boolean flushed = FALSE;
 
@@ -1227,16 +1148,16 @@ validate:
     if (r300->fb_state.dirty) {
         /* Color buffers... */
         for (i = 0; i < fb->nr_cbufs; i++) {
-            tex = r300_texture(fb->cbufs[i]->texture);
-            assert(tex && tex->buffer && "cbuf is marked, but NULL!");
-            r300->rws->cs_add_reloc(r300->cs, tex->cs_buffer, 0,
+            tex = r300_resource(fb->cbufs[i]->texture);
+            assert(tex && tex->buf && "cbuf is marked, but NULL!");
+            r300->rws->cs_add_reloc(r300->cs, tex->cs_buf, 0,
                                     r300_surface(fb->cbufs[i])->domain);
         }
         /* ...depth buffer... */
         if (fb->zsbuf) {
-            tex = r300_texture(fb->zsbuf->texture);
-            assert(tex && tex->buffer && "zsbuf is marked, but NULL!");
-            r300->rws->cs_add_reloc(r300->cs, tex->cs_buffer, 0,
+            tex = r300_resource(fb->zsbuf->texture);
+            assert(tex && tex->buf && "zsbuf is marked, but NULL!");
+            r300->rws->cs_add_reloc(r300->cs, tex->cs_buf, 0,
                                     r300_surface(fb->zsbuf)->domain);
         }
     }
@@ -1247,35 +1168,35 @@ validate:
                 continue;
             }
 
-            tex = r300_texture(texstate->sampler_views[i]->base.texture);
-            r300->rws->cs_add_reloc(r300->cs, tex->cs_buffer, tex->domain, 0);
+            tex = r300_resource(texstate->sampler_views[i]->base.texture);
+            r300->rws->cs_add_reloc(r300->cs, tex->cs_buf, tex->domain, 0);
         }
     }
     /* ...occlusion query buffer... */
     if (r300->query_current)
-        r300->rws->cs_add_reloc(r300->cs, r300->query_current->cs_buffer,
+        r300->rws->cs_add_reloc(r300->cs, r300->query_current->cs_buf,
                                 0, r300->query_current->domain);
     /* ...vertex buffer for SWTCL path... */
     if (r300->vbo)
-        r300->rws->cs_add_reloc(r300->cs, r300_buffer(r300->vbo)->cs_buf,
-                                r300_buffer(r300->vbo)->domain, 0);
+        r300->rws->cs_add_reloc(r300->cs, r300_resource(r300->vbo)->cs_buf,
+                                r300_resource(r300->vbo)->domain, 0);
     /* ...vertex buffers for HWTCL path... */
-    if (do_validate_vertex_buffers) {
-        struct pipe_resource **buf = r300->valid_vertex_buffer;
-        struct pipe_resource **last = r300->valid_vertex_buffer +
-                                      r300->vertex_buffer_count;
+    if (do_validate_vertex_buffers && r300->vertex_arrays_dirty) {
+        struct pipe_resource **buf = r300->vbuf_mgr->real_vertex_buffer;
+        struct pipe_resource **last = r300->vbuf_mgr->real_vertex_buffer +
+                                      r300->vbuf_mgr->nr_real_vertex_buffers;
         for (; buf != last; buf++) {
             if (!*buf)
                 continue;
 
-            r300->rws->cs_add_reloc(r300->cs, r300_buffer(*buf)->cs_buf,
-                                    r300_buffer(*buf)->domain, 0);
+            r300->rws->cs_add_reloc(r300->cs, r300_resource(*buf)->cs_buf,
+                                    r300_resource(*buf)->domain, 0);
         }
     }
     /* ...and index buffer for HWTCL path. */
     if (index_buffer)
-        r300->rws->cs_add_reloc(r300->cs, r300_buffer(index_buffer)->cs_buf,
-                                r300_buffer(index_buffer)->domain, 0);
+        r300->rws->cs_add_reloc(r300->cs, r300_resource(index_buffer)->cs_buf,
+                                r300_resource(index_buffer)->domain, 0);
 
     /* Now do the validation. */
     if (!r300->rws->cs_validate(r300->cs)) {
index b250532ba92c581b1818b9d2ca0504375f876369..c77cc08539d7fd01b2064006e897aa01941a2138 100644 (file)
@@ -36,16 +36,24 @@ static void r300_flush(struct pipe_context* pipe,
                        struct pipe_fence_handle** fence)
 {
     struct r300_context *r300 = r300_context(pipe);
-    struct r300_query *query;
     struct r300_atom *atom;
-    struct r300_fence **rfence = (struct r300_fence**)fence;
-
-    u_upload_flush(r300->upload_vb);
-    u_upload_flush(r300->upload_ib);
+    struct r300_winsys_bo **rfence = (struct r300_winsys_bo**)fence;
 
     if (r300->draw && !r300->draw_vbo_locked)
        r300_draw_flush_vbuf(r300);
 
+    if (rfence) {
+        /* Create a fence, which is a dummy BO. */
+        *rfence = r300->rws->buffer_create(r300->rws, 1, 1,
+                                           PIPE_BIND_VERTEX_BUFFER,
+                                           PIPE_USAGE_STATIC,
+                                           R300_DOMAIN_GTT);
+        /* Add the fence as a dummy relocation. */
+        r300->rws->cs_add_reloc(r300->cs,
+                                r300->rws->buffer_get_cs_handle(*rfence),
+                                R300_DOMAIN_GTT, R300_DOMAIN_GTT);
+    }
+
     if (r300->dirty_hw) {
         r300_emit_hyperz_end(r300);
         r300_emit_query_end(r300);
@@ -62,32 +70,29 @@ static void r300_flush(struct pipe_context* pipe,
                 r300_mark_atom_dirty(r300, atom);
             }
         }
+        r300->vertex_arrays_dirty = TRUE;
 
         /* Unmark HWTCL state for SWTCL. */
         if (!r300->screen->caps.has_tcl) {
             r300->vs_state.dirty = FALSE;
             r300->vs_constants.dirty = FALSE;
         }
-
-        r300->validate_buffers = TRUE;
-        r300->upload_vb_validated = FALSE;
-        r300->upload_ib_validated = FALSE;
     } else {
-        /* Even if hw is not dirty, we should at least reset the CS in case
-         * the space checking failed for the first draw operation. */
-        r300->rws->cs_flush(r300->cs);
-    }
-
-    /* reset flushed query */
-    foreach(query, &r300->query_list) {
-        query->flushed = TRUE;
+        if (rfence) {
+            /* We have to create a fence object, but the command stream is empty
+             * and we cannot emit an empty CS. We must write some regs then. */
+            CS_LOCALS(r300);
+            OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0);
+            r300->rws->cs_flush(r300->cs);
+        } else {
+            /* Even if hw is not dirty, we should at least reset the CS in case
+             * the space checking failed for the first draw operation. */
+            r300->rws->cs_flush(r300->cs);
+        }
     }
 
-    /* Create a new fence. */
-    if (rfence) {
-        *rfence = CALLOC_STRUCT(r300_fence);
-        pipe_reference_init(&(*rfence)->reference, 1);
-        (*rfence)->ctx = r300;
+    if (flags & PIPE_FLUSH_FRAME) {
+        r300->rws->cs_sync_flush(r300->cs);
     }
 }
 
index 6d4091dc87da2180f4c1de8fa56d962a6ff718ef..cec7473009a6e03f359b7e5457c4c3ceeefa71ae 100644 (file)
@@ -152,13 +152,13 @@ static void get_external_state(
     for (i = 0; i < texstate->sampler_state_count; i++) {
         struct r300_sampler_state *s = texstate->sampler_states[i];
         struct r300_sampler_view *v = texstate->sampler_views[i];
-        struct r300_texture *t;
+        struct r300_resource *t;
 
         if (!s || !v) {
             continue;
         }
 
-        t = r300_texture(texstate->sampler_views[i]->base.texture);
+        t = r300_resource(texstate->sampler_views[i]->base.texture);
 
         if (s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
             state->unit[i].compare_mode_enabled = 1;
@@ -181,7 +181,7 @@ static void get_external_state(
         state->unit[i].non_normalized_coords = !s->state.normalized_coords;
 
         /* XXX this should probably take into account STR, not just S. */
-        if (t->desc.is_npot) {
+        if (t->tex.is_npot) {
             switch (s->state.wrap_s) {
             case PIPE_TEX_WRAP_REPEAT:
                 state->unit[i].wrap_mode = RC_WRAP_REPEAT;
@@ -201,7 +201,7 @@ static void get_external_state(
                 state->unit[i].wrap_mode = RC_WRAP_NONE;
             }
 
-            if (t->desc.b.b.target == PIPE_TEXTURE_3D)
+            if (t->b.b.b.target == PIPE_TEXTURE_3D)
                 state->unit[i].clamp_and_scale_before_fetch = TRUE;
         }
     }
@@ -298,44 +298,98 @@ static void r300_emit_fs_code_to_buffer(
         }
     } else { /* r300 */
         struct r300_fragment_program_code *code = &generic_code->code.r300;
-
-        shader->cb_code_size = 19 +
-                               (r300->screen->caps.is_r400 ? 2 : 0) +
-                               code->alu.length * 4 +
-                               (code->tex.length ? (1 + code->tex.length) : 0) +
-                               imm_count * 5;
+        unsigned int alu_length = code->alu.length;
+        unsigned int alu_iterations = ((alu_length - 1) / 64) + 1;
+        unsigned int tex_length = code->tex.length;
+        unsigned int tex_iterations =
+            tex_length > 0 ? ((tex_length - 1) / 32) + 1 : 0;
+        unsigned int iterations =
+            alu_iterations > tex_iterations ? alu_iterations : tex_iterations;
+        unsigned int bank = 0;
+
+        shader->cb_code_size = 15 +
+            /* R400_US_CODE_BANK */
+            (r300->screen->caps.is_r400 ? 2 * (iterations + 1): 0) +
+            /* R400_US_CODE_EXT */
+            (r300->screen->caps.is_r400 ? 2 : 0) +
+            /* R300_US_ALU_{RGB,ALPHA}_{INST,ADDR}_0, R400_US_ALU_EXT_ADDR_0 */
+            (code->r390_mode ? (5 * alu_iterations) : 4) +
+            /* R400_US_ALU_EXT_ADDR_[0-63] */
+            (code->r390_mode ? (code->alu.length) : 0) +
+            /* R300_US_ALU_{RGB,ALPHA}_{INST,ADDR}_0 */
+            code->alu.length * 4 +
+            /* R300_US_TEX_INST_0, R300_US_TEX_INST_[0-31] */
+            (code->tex.length > 0 ? code->tex.length + tex_iterations : 0) +
+            imm_count * 5;
 
         NEW_CB(shader->cb_code, shader->cb_code_size);
 
-        if (r300->screen->caps.is_r400)
-            OUT_CB_REG(R400_US_CODE_BANK, 0);
-
         OUT_CB_REG(R300_US_CONFIG, code->config);
         OUT_CB_REG(R300_US_PIXSIZE, code->pixsize);
         OUT_CB_REG(R300_US_CODE_OFFSET, code->code_offset);
 
+        if (code->r390_mode) {
+            OUT_CB_REG(R400_US_CODE_EXT, code->r400_code_offset_ext);
+        } else if (r300->screen->caps.is_r400) {
+            /* This register appears to affect shaders even if r390_mode is
+             * disabled, so it needs to be set to 0 for shaders that
+             * don't use r390_mode. */
+            OUT_CB_REG(R400_US_CODE_EXT, 0);
+        }
+
         OUT_CB_REG_SEQ(R300_US_CODE_ADDR_0, 4);
         OUT_CB_TABLE(code->code_addr, 4);
 
-        OUT_CB_REG_SEQ(R300_US_ALU_RGB_INST_0, code->alu.length);
-        for (i = 0; i < code->alu.length; i++)
-            OUT_CB(code->alu.inst[i].rgb_inst);
+        do {
+            unsigned int bank_alu_length = (alu_length < 64 ? alu_length : 64);
+            unsigned int bank_alu_offset = bank * 64;
+            unsigned int bank_tex_length = (tex_length < 32 ? tex_length : 32);
+            unsigned int bank_tex_offset = bank * 32;
+
+            if (r300->screen->caps.is_r400) {
+                OUT_CB_REG(R400_US_CODE_BANK, code->r390_mode ?
+                                (bank << R400_BANK_SHIFT) | R400_R390_MODE_ENABLE : 0);//2
+            }
+
+            if (bank_alu_length > 0) {
+                OUT_CB_REG_SEQ(R300_US_ALU_RGB_INST_0, bank_alu_length);
+                for (i = 0; i < bank_alu_length; i++)
+                    OUT_CB(code->alu.inst[i + bank_alu_offset].rgb_inst);
+
+                OUT_CB_REG_SEQ(R300_US_ALU_RGB_ADDR_0, bank_alu_length);
+                for (i = 0; i < bank_alu_length; i++)
+                    OUT_CB(code->alu.inst[i + bank_alu_offset].rgb_addr);
 
-        OUT_CB_REG_SEQ(R300_US_ALU_RGB_ADDR_0, code->alu.length);
-        for (i = 0; i < code->alu.length; i++)
-            OUT_CB(code->alu.inst[i].rgb_addr);
+                OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_INST_0, bank_alu_length);
+                for (i = 0; i < bank_alu_length; i++)
+                    OUT_CB(code->alu.inst[i + bank_alu_offset].alpha_inst);
 
-        OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_INST_0, code->alu.length);
-        for (i = 0; i < code->alu.length; i++)
-            OUT_CB(code->alu.inst[i].alpha_inst);
+                OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_ADDR_0, bank_alu_length);
+                for (i = 0; i < bank_alu_length; i++)
+                    OUT_CB(code->alu.inst[i + bank_alu_offset].alpha_addr);
 
-        OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_ADDR_0, code->alu.length);
-        for (i = 0; i < code->alu.length; i++)
-            OUT_CB(code->alu.inst[i].alpha_addr);
+                if (code->r390_mode) {
+                    OUT_CB_REG_SEQ(R400_US_ALU_EXT_ADDR_0, bank_alu_length);
+                    for (i = 0; i < bank_alu_length; i++)
+                        OUT_CB(code->alu.inst[i + bank_alu_offset].r400_ext_addr);
+                }
+            }
+
+            if (bank_tex_length > 0) {
+                OUT_CB_REG_SEQ(R300_US_TEX_INST_0, bank_tex_length);
+                OUT_CB_TABLE(code->tex.inst + bank_tex_offset, bank_tex_length);
+            }
+
+            alu_length -= bank_alu_length;
+            tex_length -= bank_tex_length;
+            bank++;
+        } while(code->r390_mode && (alu_length > 0 || tex_length > 0));
 
-        if (code->tex.length) {
-            OUT_CB_REG_SEQ(R300_US_TEX_INST_0, code->tex.length);
-            OUT_CB_TABLE(code->tex.inst, code->tex.length);
+        /* R400_US_CODE_BANK needs to be reset to 0, otherwise some shaders
+         * will be rendered incorrectly. */
+        if (r300->screen->caps.is_r400) {
+            OUT_CB_REG(R400_US_CODE_BANK,
+                code->r390_mode ? R400_R390_MODE_ENABLE : 0);
         }
 
         /* Emit immediates. */
@@ -384,12 +438,17 @@ static void r300_translate_fragment_shader(
     compiler.code = &shader->code;
     compiler.state = shader->compare_state;
     compiler.Base.is_r500 = r300->screen->caps.is_r500;
+    compiler.Base.is_r400 = r300->screen->caps.is_r400;
     compiler.Base.disable_optimizations = DBG_ON(r300, DBG_NO_OPT);
     compiler.Base.has_half_swizzles = TRUE;
     compiler.Base.has_presub = TRUE;
-    compiler.Base.max_temp_regs = compiler.Base.is_r500 ? 128 : 32;
+    compiler.Base.max_temp_regs =
+        compiler.Base.is_r500 ? 128 : (compiler.Base.is_r400 ? 64 : 32);
     compiler.Base.max_constants = compiler.Base.is_r500 ? 256 : 32;
-    compiler.Base.max_alu_insts = compiler.Base.is_r500 ? 512 : 64;
+    compiler.Base.max_alu_insts =
+        (compiler.Base.is_r500 || compiler.Base.is_r400) ? 512 : 64;
+    compiler.Base.max_tex_insts =
+        (compiler.Base.is_r500 || compiler.Base.is_r400) ? 512 : 32;
     compiler.AllocateHwInputs = &allocate_hardware_inputs;
     compiler.UserData = &shader->inputs;
 
@@ -414,6 +473,13 @@ static void r300_translate_fragment_shader(
 
     r300_tgsi_to_rc(&ttr, tokens);
 
+    if (ttr.error) {
+        fprintf(stderr, "r300 FP: Cannot translate a shader. "
+                "Using a dummy shader instead.\n");
+        r300_dummy_fragment_shader(r300, shader);
+        return;
+    }
+
     if (!r300->screen->caps.is_r500 ||
         compiler.Base.Program.Constants.Count > 200) {
         compiler.Base.remove_unused_constants = TRUE;
index c22e307c679a11c251d9131902d5379faff7c6e3..873e0209d42f0dea6dbd5d5263fdb1c2ab8fe522 100644 (file)
@@ -127,7 +127,7 @@ static boolean r300_can_hiz(struct r300_context *r300)
                 z->current_func, dsa_state->z_stencil_control);
             return FALSE;
         }
-    }    
+    }
     return TRUE;
 }
 
@@ -137,9 +137,8 @@ static void r300_update_hyperz(struct r300_context* r300)
         (struct r300_hyperz_state*)r300->hyperz_state.state;
     struct pipe_framebuffer_state *fb =
         (struct pipe_framebuffer_state*)r300->fb_state.state;
-    struct r300_texture *zstex =
-            fb->zsbuf ? r300_texture(fb->zsbuf->texture) : NULL;
-    boolean zmask_in_use = FALSE;
+    struct r300_resource *zstex =
+            fb->zsbuf ? r300_resource(fb->zsbuf->texture) : NULL;
     boolean hiz_in_use = FALSE;
 
     z->gb_z_peq_config = 0;
@@ -158,42 +157,40 @@ static void r300_update_hyperz(struct r300_context* r300)
     if (!r300->rws->get_value(r300->rws, R300_CAN_HYPERZ))
         return;
 
-    zmask_in_use = zstex->zmask_in_use[fb->zsbuf->u.tex.level];
     hiz_in_use = zstex->hiz_in_use[fb->zsbuf->u.tex.level];
 
-    /* Z fastfill. */
-    if (zmask_in_use) {
-        z->zb_bw_cntl |= R300_FAST_FILL_ENABLE; /*  | R300_FORCE_COMPRESSED_STENCIL_VALUE_ENABLE;*/
-    }
-
     /* Zbuffer compression. */
-    if (zmask_in_use && r300->z_compression) {
-        z->zb_bw_cntl |= R300_RD_COMP_ENABLE;
-        if (r300->z_decomp_rd == false)
+    if (r300->zmask_in_use && !r300->zmask_locked) {
+        z->zb_bw_cntl |= R300_FAST_FILL_ENABLE |
+                         /*R300_FORCE_COMPRESSED_STENCIL_VALUE_ENABLE |*/
+                         R300_RD_COMP_ENABLE;
+
+        if (!r300->zmask_decompress) {
             z->zb_bw_cntl |= R300_WR_COMP_ENABLE;
+        }
     }
-    /* RV350 and up optimizations. */
-    /* The section 10.4.9 in the docs is a lie. */
-    if (r300->z_compression == RV350_Z_COMPRESS_88)
+
+    if (zstex->tex.zcomp8x8[fb->zsbuf->u.tex.level]) {
         z->gb_z_peq_config |= R300_GB_Z_PEQ_CONFIG_Z_PEQ_SIZE_8_8;
+    }
+
+    if (hiz_in_use && r300_can_hiz(r300)) {
+        z->zb_bw_cntl |= R300_HIZ_ENABLE |
+                         r300_get_hiz_min(r300);
 
-    if (hiz_in_use) {
-        bool can_hiz = r300_can_hiz(r300);
-        if (can_hiz) {
-            z->zb_bw_cntl |= R300_HIZ_ENABLE;
-            z->sc_hyperz |= R300_SC_HYPERZ_ENABLE;
-            z->sc_hyperz |= r300_get_sc_hz_max(r300);
-            z->zb_bw_cntl |= r300_get_hiz_min(r300);
+        z->sc_hyperz |= R300_SC_HYPERZ_ENABLE |
+                        r300_get_sc_hz_max(r300);
+
+        if (r300->screen->caps.is_r500) {
+            z->zb_bw_cntl |= R500_HIZ_FP_EXP_BITS_3 |
+                             R500_HIZ_EQUAL_REJECT_ENABLE;
         }
     }
 
     /* R500-specific features and optimizations. */
     if (r300->screen->caps.is_r500) {
-        z->zb_bw_cntl |= R500_HIZ_FP_EXP_BITS_3;
-        z->zb_bw_cntl |=
-                R500_HIZ_EQUAL_REJECT_ENABLE |
-                R500_PEQ_PACKING_ENABLE |
-                R500_COVERED_PTR_MASKING_ENABLE;
+        z->zb_bw_cntl |= R500_PEQ_PACKING_ENABLE |
+                         R500_COVERED_PTR_MASKING_ENABLE;
     }
 }
 
@@ -297,26 +294,10 @@ static void r300_update_hiz_clear(struct r300_context *r300)
     r300->hiz_clear.size = height * 4;
 }
 
-static void r300_update_zmask_clear(struct r300_context *r300)
-{
-    struct pipe_framebuffer_state *fb =
-        (struct pipe_framebuffer_state*)r300->fb_state.state;
-    uint32_t height;
-    int mult;
-
-    if (r300->z_compression == RV350_Z_COMPRESS_88)
-        mult = 8;
-    else
-        mult = 4;
-
-    height = ALIGN_DIVUP(fb->zsbuf->height, mult);
-
-    r300->zmask_clear.size = height * 4;
-}
-
 void r300_update_hyperz_state(struct r300_context* r300)
 {
     r300_update_ztop(r300);
+
     if (r300->hyperz_state.dirty) {
         r300_update_hyperz(r300);
     }
@@ -324,64 +305,24 @@ void r300_update_hyperz_state(struct r300_context* r300)
     if (r300->hiz_clear.dirty) {
        r300_update_hiz_clear(r300);
     }
-    if (r300->zmask_clear.dirty) {
-       r300_update_zmask_clear(r300);
-    }
 }
 
 void r300_hiz_alloc_block(struct r300_context *r300, struct r300_surface *surf)
 {
-    struct r300_texture *tex;
+    struct r300_resource *tex;
     uint32_t zsize, ndw;
     int level = surf->base.u.tex.level;
 
-    tex = r300_texture(surf->base.texture);
+    tex = r300_resource(surf->base.texture);
 
     if (tex->hiz_mem[level])
         return;
 
-    zsize = tex->desc.layer_size_in_bytes[level];
-    zsize /= util_format_get_blocksize(tex->desc.b.b.format);
+    zsize = tex->tex.layer_size_in_bytes[level];
+    zsize /= util_format_get_blocksize(tex->b.b.b.format);
     ndw = ALIGN_DIVUP(zsize, 64);
 
     tex->hiz_mem[level] = u_mmAllocMem(r300->hiz_mm, ndw, 0, 0);
-    return;
-}
-
-void r300_zmask_alloc_block(struct r300_context *r300, struct r300_surface *surf, int compress)
-{
-    int bsize = 256;
-    uint32_t zsize, ndw;
-    int level = surf->base.u.tex.level;
-    struct r300_texture *tex;
-
-    tex = r300_texture(surf->base.texture);
-
-    /* We currently don't handle decompression for 3D textures and cubemaps
-     * correctly. */
-    if (tex->desc.b.b.target != PIPE_TEXTURE_1D &&
-        tex->desc.b.b.target != PIPE_TEXTURE_2D &&
-        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])
-        return;
-
-    zsize = tex->desc.layer_size_in_bytes[level];
-    zsize /= util_format_get_blocksize(tex->desc.b.b.format);
-
-    /* each zmask dword represents 16 4x4 blocks - which is 256 pixels
-       or 16 8x8 depending on the gb peq flag = 1024 pixels */
-    if (compress == RV350_Z_COMPRESS_88)
-        bsize = 1024;
-
-    ndw = ALIGN_DIVUP(zsize, bsize);
-    tex->zmask_mem[level] = u_mmAllocMem(r300->zmask_mm, ndw, 0, 0);
-    return;
 }
 
 boolean r300_hyperz_init_mm(struct r300_context *r300)
@@ -389,15 +330,9 @@ boolean r300_hyperz_init_mm(struct r300_context *r300)
     struct r300_screen* r300screen = r300->screen;
     int frag_pipes = r300screen->caps.num_frag_pipes;
 
-    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;
       }
     }
@@ -413,7 +348,4 @@ void r300_hyperz_destroy_mm(struct r300_context *r300)
       u_mmDestroy(r300->hiz_mm);
       r300->hiz_mm = NULL;
     }
-
-    u_mmDestroy(r300->zmask_mm);
-    r300->zmask_mm = NULL;
 }
index 30a23ec6493686bfebe961968e4a08be1b48c5e4..d4c8e7c60a95cdab21de392bd84f00e05ca1af84 100644 (file)
@@ -28,8 +28,8 @@ struct r300_context;
 void r300_update_hyperz_state(struct r300_context* r300);
 
 void r300_hiz_alloc_block(struct r300_context *r300, struct r300_surface *surf);
-void r300_zmask_alloc_block(struct r300_context *r300, struct r300_surface *surf, int compress);
 
 boolean r300_hyperz_init_mm(struct r300_context *r300);
 void r300_hyperz_destroy_mm(struct r300_context *r300);
+
 #endif
index 6223e043210b92c94abee375f4b5c6974de582c9..717485f43cbb140728fbec23ec7cbdf56095bf30 100644 (file)
@@ -57,10 +57,10 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe,
     insert_at_tail(&r300->query_list, q);
 
     /* Open up the occlusion query buffer. */
-    q->buffer = r300->rws->buffer_create(r300->rws, q->buffer_size, 4096,
+    q->buf = r300->rws->buffer_create(r300->rws, q->buffer_size, 4096,
                                          PIPE_BIND_CUSTOM, PIPE_USAGE_STREAM,
                                          q->domain);
-    q->cs_buffer = r300->rws->buffer_get_cs_handle(r300->rws, q->buffer);
+    q->cs_buf = r300->rws->buffer_get_cs_handle(q->buf);
 
     return (struct pipe_query*)q;
 }
@@ -68,10 +68,9 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe,
 static void r300_destroy_query(struct pipe_context* pipe,
                                struct pipe_query* query)
 {
-    struct r300_context *r300 = r300_context(pipe);
     struct r300_query* q = r300_query(query);
 
-    r300->rws->buffer_reference(r300->rws, &q->buffer, NULL);
+    r300_winsys_bo_reference(&q->buf, NULL);
     remove_from_list(q);
     FREE(query);
 }
@@ -128,16 +127,12 @@ static boolean r300_get_query_result(struct pipe_context* pipe,
 {
     struct r300_context* r300 = r300_context(pipe);
     struct r300_query *q = r300_query(query);
-    unsigned flags, i;
+    unsigned i;
     uint32_t temp, *map;
-    uint64_t *result = (uint64_t*)vresult;
-
-    if (!q->flushed)
-        pipe->flush(pipe, 0, NULL);
-
-    flags = PIPE_TRANSFER_READ | (!wait ? PIPE_TRANSFER_DONTBLOCK : 0);
 
-    map = r300->rws->buffer_map(r300->rws, q->buffer, r300->cs, flags);
+    map = r300->rws->buffer_map(q->buf, r300->cs,
+                                PIPE_TRANSFER_READ |
+                                (!wait ? PIPE_TRANSFER_DONTBLOCK : 0));
     if (!map)
         return FALSE;
 
@@ -148,9 +143,9 @@ static boolean r300_get_query_result(struct pipe_context* pipe,
         map++;
     }
 
-    r300->rws->buffer_unmap(r300->rws, q->buffer);
+    r300->rws->buffer_unmap(q->buf);
 
-    *result = temp;
+    *((uint64_t*)vresult) = temp;
     return TRUE;
 }
 
index d1154dee40a16297682965b520cf788a290e5ae7..1d93dab2ca256e262fa102f1fc43584537e314a9 100644 (file)
@@ -2162,14 +2162,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 /* R4xx extended fragment shader registers. */
 #define R400_US_ALU_EXT_ADDR_0              0x4ac0 /* up to 63 (0x4bbc) */
-#   define R400_ADDR0_EXT_RGB_MSB_BIT       0x01
-#   define R400_ADDR1_EXT_RGB_MSB_BIT       0x02
-#   define R400_ADDR2_EXT_RGB_MSB_BIT       0x04
+#   define R400_ADDR_EXT_RGB_MSB_BIT(x)     (1 << (x))
 #   define R400_ADDRD_EXT_RGB_MSB_BIT       0x08
-#   define R400_ADDR0_EXT_A_MSB_BIT         0x10
-#   define R400_ADDR1_EXT_A_MSB_BIT         0x20
-#   define R400_ADDR2_EXT_A_MSB_BIT         0x40
+#   define R400_ADDR_EXT_A_MSB_BIT(x)       (1 << ((x) + 4))
 #   define R400_ADDRD_EXT_A_MSB_BIT         0x80
+
 #define R400_US_CODE_BANK                   0x46b8
 #   define R400_BANK_SHIFT                  0
 #   define R400_BANK_MASK                   0xf
index b35822c82f83e37e785ffd34f95f9cbae8f95f31..2ead8667bda276e5613a84f0d8919512d1e0e815 100644 (file)
@@ -127,6 +127,20 @@ void r500_emit_index_bias(struct r300_context *r300, int index_bias)
     END_CS;
 }
 
+static void r300_emit_draw_init(struct r300_context *r300, unsigned mode,
+                                unsigned min_index, unsigned max_index)
+{
+    CS_LOCALS(r300);
+
+    BEGIN_CS(5);
+    OUT_CS_REG(R300_GA_COLOR_CONTROL,
+            r300_provoking_vertex_fixes(r300, mode));
+    OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
+    OUT_CS(max_index);
+    OUT_CS(min_index);
+    END_CS;
+}
+
 /* This function splits the index bias value into two parts:
  * - buffer_offset: the value that can be safely added to buffer offsets
  *   in r300_emit_vertex_arrays (it must yield a positive offset when added to
@@ -136,7 +150,7 @@ void r500_emit_index_bias(struct r300_context *r300, int index_bias)
 static void r300_split_index_bias(struct r300_context *r300, int index_bias,
                                   int *buffer_offset, int *index_offset)
 {
-    struct pipe_vertex_buffer *vb, *vbufs = r300->vertex_buffer;
+    struct pipe_vertex_buffer *vb, *vbufs = r300->vbuf_mgr->vertex_buffer;
     struct pipe_vertex_element *velem = r300->velems->velem;
     unsigned i, size;
     int max_neg_bias;
@@ -235,24 +249,11 @@ static boolean r300_emit_states(struct r300_context *r300,
 
     /* Validate buffers and emit dirty state if needed. */
     if (first_draw) {
-        if (r300->validate_buffers) {
-            if (!r300_emit_buffer_validate(r300, validate_vbos,
-                                           index_buffer)) {
-                fprintf(stderr, "r300: CS space validation failed. "
-                        "(not enough memory?) Skipping rendering.\n");
-                return FALSE;
-            }
-
-            /* Consider the validation done only if everything was validated. */
-            if (validate_vbos) {
-                r300->validate_buffers = FALSE;
-                if (r300->any_user_vbs)
-                    r300->upload_vb_validated = TRUE;
-                if (r300->index_buffer.buffer &&
-                    r300_is_user_buffer(r300->index_buffer.buffer)) {
-                    r300->upload_ib_validated = TRUE;
-                }
-            }
+        if (!r300_emit_buffer_validate(r300, validate_vbos,
+                                       index_buffer)) {
+           fprintf(stderr, "r300: CS space validation failed. "
+                   "(not enough memory?) Skipping rendering.\n");
+           return FALSE;
         }
 
         r300_emit_dirty_state(r300);
@@ -263,9 +264,17 @@ static boolean r300_emit_states(struct r300_context *r300,
                 r500_emit_index_bias(r300, 0);
         }
 
-        if (emit_vertex_arrays)
+        if (emit_vertex_arrays &&
+            (r300->vertex_arrays_dirty ||
+             r300->vertex_arrays_indexed != indexed ||
+             r300->vertex_arrays_offset != buffer_offset)) {
             r300_emit_vertex_arrays(r300, buffer_offset, indexed);
 
+            r300->vertex_arrays_dirty = FALSE;
+            r300->vertex_arrays_indexed = indexed;
+            r300->vertex_arrays_offset = buffer_offset;
+        }
+
         if (emit_vertex_arrays_swtcl)
             r300_emit_vertex_arrays_swtcl(r300, indexed);
     }
@@ -294,7 +303,8 @@ static boolean r300_prepare_for_rendering(struct r300_context *r300,
     if (r300_reserve_cs_dwords(r300, flags, cs_dwords))
         flags |= PREP_FIRST_DRAW;
 
-    return r300_emit_states(r300, flags, index_buffer, buffer_offset, index_bias);
+    return r300_emit_states(r300, flags, index_buffer, buffer_offset,
+                            index_bias);
 }
 
 static boolean immd_is_good_idea(struct r300_context *r300,
@@ -325,17 +335,12 @@ static boolean immd_is_good_idea(struct r300_context *r300,
         vbi = velem->vertex_buffer_index;
 
         if (!checked[vbi]) {
-            buf = r300->valid_vertex_buffer[vbi];
+            buf = r300->vbuf_mgr->real_vertex_buffer[vbi];
 
-            if (!(r300_buffer(buf)->domain & R300_DOMAIN_GTT)) {
+            if ((r300_resource(buf)->domain != R300_DOMAIN_GTT)) {
                 return FALSE;
             }
 
-            if (r300_buffer_is_referenced(&r300->context, buf,
-                                          R300_REF_CS | R300_REF_HW)) {
-                /* It's a very bad idea to map it... */
-                return FALSE;
-            }
             checked[vbi] = TRUE;
         }
     }
@@ -346,10 +351,9 @@ static boolean immd_is_good_idea(struct r300_context *r300,
  * The HWTCL draw functions.                                                 *
  ****************************************************************************/
 
-static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
-                                            unsigned mode,
-                                            unsigned start,
-                                            unsigned count)
+static void r300_draw_arrays_immediate(struct r300_context *r300,
+                                       unsigned mode, unsigned start,
+                                       unsigned count)
 {
     struct pipe_vertex_element* velem;
     struct pipe_vertex_buffer* vbuf;
@@ -360,7 +364,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
     unsigned vertex_size = r300->velems->vertex_size_dwords;
 
     /* The number of dwords for this draw operation. */
-    unsigned dwords = 9 + count * vertex_size;
+    unsigned dwords = 4 + count * vertex_size;
 
     /* Size of the vertex element, in dwords. */
     unsigned size[PIPE_MAX_ATTRIBS];
@@ -370,9 +374,8 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
     unsigned stride[PIPE_MAX_ATTRIBS];
 
     /* Mapped vertex buffers. */
-    uint32_t* map[PIPE_MAX_ATTRIBS];
+    uint32_t* map[PIPE_MAX_ATTRIBS] = {0};
     uint32_t* mapelem[PIPE_MAX_ATTRIBS];
-    struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {0};
 
     CS_LOCALS(r300);
 
@@ -382,29 +385,25 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
     /* Calculate the vertex size, offsets, strides etc. and map the buffers. */
     for (i = 0; i < vertex_element_count; i++) {
         velem = &r300->velems->velem[i];
-        size[i] = r300->velems->hw_format_size[i] / 4;
+        size[i] = r300->velems->format_size[i] / 4;
         vbi = velem->vertex_buffer_index;
-        vbuf = &r300->vertex_buffer[vbi];
+        vbuf = &r300->vbuf_mgr->vertex_buffer[vbi];
         stride[i] = vbuf->stride / 4;
 
         /* Map the buffer. */
-        if (!transfer[vbi]) {
-            map[vbi] = (uint32_t*)pipe_buffer_map(&r300->context,
-                                                  r300->valid_vertex_buffer[vbi],
-                                                  PIPE_TRANSFER_READ,
-                                                 &transfer[vbi]);
+        if (!map[vbi]) {
+            map[vbi] = (uint32_t*)r300->rws->buffer_map(
+                r300_resource(r300->vbuf_mgr->real_vertex_buffer[vbi])->buf,
+                r300->cs, PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED);
             map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * start;
         }
         mapelem[i] = map[vbi] + (velem->src_offset / 4);
     }
 
+    r300_emit_draw_init(r300, mode, 0, count-1);
+
     BEGIN_CS(dwords);
-    OUT_CS_REG(R300_GA_COLOR_CONTROL,
-            r300_provoking_vertex_fixes(r300, mode));
     OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size);
-    OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
-    OUT_CS(count - 1);
-    OUT_CS(0);
     OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size);
     OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) |
             r300_translate_primitive(mode));
@@ -421,9 +420,9 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
     for (i = 0; i < vertex_element_count; i++) {
         vbi = r300->velems->velem[i].vertex_buffer_index;
 
-        if (transfer[vbi]) {
-            pipe_buffer_unmap(&r300->context, transfer[vbi]);
-            transfer[vbi] = NULL;
+        if (map[vbi]) {
+            r300->rws->buffer_unmap(r300_resource(r300->vbuf_mgr->real_vertex_buffer[vbi])->buf);
+            map[vbi] = NULL;
         }
     }
 }
@@ -441,15 +440,12 @@ static void r300_emit_draw_arrays(struct r300_context *r300,
         return;
     }
 
-    BEGIN_CS(7 + (alt_num_verts ? 2 : 0));
+    r300_emit_draw_init(r300, mode, 0, count-1);
+
+    BEGIN_CS(2 + (alt_num_verts ? 2 : 0));
     if (alt_num_verts) {
         OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count);
     }
-    OUT_CS_REG(R300_GA_COLOR_CONTROL,
-            r300_provoking_vertex_fixes(r300, mode));
-    OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
-    OUT_CS(count - 1);
-    OUT_CS(0);
     OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0);
     OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) |
            r300_translate_primitive(mode) |
@@ -471,22 +467,16 @@ static void r300_emit_draw_elements(struct r300_context *r300,
     boolean alt_num_verts = count > 65535;
     CS_LOCALS(r300);
 
-    if (count >= (1 << 24)) {
+    if (count >= (1 << 24) || maxIndex >= (1 << 24)) {
         fprintf(stderr, "r300: Got a huge number of vertices: %i, "
-                "refusing to render.\n", count);
+                "refusing to render (maxIndex: %i).\n", count, maxIndex);
         return;
     }
 
     DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n",
         count, minIndex, maxIndex);
 
-    BEGIN_CS(5);
-    OUT_CS_REG(R300_GA_COLOR_CONTROL,
-            r300_provoking_vertex_fixes(r300, mode));
-    OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
-    OUT_CS(maxIndex);
-    OUT_CS(minIndex);
-    END_CS;
+    r300_emit_draw_init(r300, mode, minIndex, maxIndex);
 
     /* If start is odd, render the first triangle with indices embedded
      * in the command stream. This will increase start by 3 and make it
@@ -527,30 +517,105 @@ static void r300_emit_draw_elements(struct r300_context *r300,
                (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0));
     }
 
-    /* INDX_BUFFER is a truly special packet3.
-     * Unlike most other packet3, where the offset is after the count,
-     * the order is reversed, so the relocation ends up carrying the
-     * size of the indexbuf instead of the offset.
-     */
     OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2);
     OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) |
            (0 << R300_INDX_BUFFER_SKIP_SHIFT));
     OUT_CS(offset_dwords << 2);
-    OUT_CS_BUF_RELOC(indexBuffer, count_dwords);
+    OUT_CS(count_dwords);
+    OUT_CS_RELOC(r300_resource(indexBuffer));
+    END_CS;
+}
+
+static void r300_draw_elements_immediate(struct r300_context *r300,
+                                         int indexBias, unsigned minIndex,
+                                         unsigned maxIndex, unsigned mode,
+                                         unsigned start, unsigned count)
+{
+    uint8_t *ptr1;
+    uint16_t *ptr2;
+    uint32_t *ptr4;
+    unsigned index_size = r300->index_buffer.index_size;
+    unsigned i, count_dwords = index_size == 4 ? count : (count + 1) / 2;
+    CS_LOCALS(r300);
+
+    /* 19 dwords for r300_draw_elements_immediate. Give up if the function fails. */
+    if (!r300_prepare_for_rendering(r300,
+            PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS |
+            PREP_INDEXED, NULL, 2+count_dwords, 0, indexBias))
+        return;
 
+    r300_emit_draw_init(r300, mode, minIndex, maxIndex);
+
+    BEGIN_CS(2 + count_dwords);
+    OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, count_dwords);
+
+    switch (index_size) {
+    case 1:
+        ptr1 = r300_resource(r300->index_buffer.buffer)->b.user_ptr;
+        ptr1 += start;
+
+        OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) |
+               r300_translate_primitive(mode));
+
+        if (indexBias && !r300->screen->caps.index_bias_supported) {
+            for (i = 0; i < count-1; i += 2)
+                OUT_CS(((ptr1[i+1] + indexBias) << 16) |
+                        (ptr1[i]   + indexBias));
+
+            if (count & 1)
+                OUT_CS(ptr1[i] + indexBias);
+        } else {
+            for (i = 0; i < count-1; i += 2)
+                OUT_CS(((ptr1[i+1]) << 16) |
+                        (ptr1[i]  ));
+
+            if (count & 1)
+                OUT_CS(ptr1[i]);
+        }
+        break;
+
+    case 2:
+        ptr2 = (uint16_t*)r300_resource(r300->index_buffer.buffer)->b.user_ptr;
+        ptr2 += start;
+
+        OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) |
+               r300_translate_primitive(mode));
+
+        if (indexBias && !r300->screen->caps.index_bias_supported) {
+            for (i = 0; i < count-1; i += 2)
+                OUT_CS(((ptr2[i+1] + indexBias) << 16) |
+                        (ptr2[i]   + indexBias));
+
+            if (count & 1)
+                OUT_CS(ptr2[i] + indexBias);
+        } else {
+            OUT_CS_TABLE(ptr2, count_dwords);
+        }
+        break;
+
+    case 4:
+        ptr4 = (uint32_t*)r300_resource(r300->index_buffer.buffer)->b.user_ptr;
+        ptr4 += start;
+
+        OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) |
+               R300_VAP_VF_CNTL__INDEX_SIZE_32bit |
+               r300_translate_primitive(mode));
+
+        if (indexBias && !r300->screen->caps.index_bias_supported) {
+            for (i = 0; i < count; i++)
+                OUT_CS(ptr4[i] + indexBias);
+        } else {
+            OUT_CS_TABLE(ptr4, count_dwords);
+        }
+        break;
+    }
     END_CS;
 }
 
-/* This is the fast-path drawing & emission for HW TCL. */
-static void r300_draw_range_elements(struct pipe_context* pipe,
-                                     int indexBias,
-                                     unsigned minIndex,
-                                     unsigned maxIndex,
-                                     unsigned mode,
-                                     unsigned start,
-                                     unsigned count)
+static void r300_draw_elements(struct r300_context *r300, int indexBias,
+                               unsigned minIndex, unsigned maxIndex,
+                               unsigned mode, unsigned start, unsigned count)
 {
-    struct r300_context* r300 = r300_context(pipe);
     struct pipe_resource *indexBuffer = r300->index_buffer.buffer;
     unsigned indexSize = r300->index_buffer.index_size;
     struct pipe_resource* orgIndexBuffer = indexBuffer;
@@ -570,30 +635,28 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
 
     /* Fallback for misaligned ushort indices. */
     if (indexSize == 2 && (start & 1) &&
-        !r300_is_user_buffer(indexBuffer)) {
-        struct pipe_transfer *transfer;
-        struct pipe_resource *userbuf;
-
-        uint16_t *ptr = pipe_buffer_map(pipe, indexBuffer,
-                                        PIPE_TRANSFER_READ, &transfer);
+        !r300_resource(indexBuffer)->b.user_ptr) {
+        /* If we got here, then orgIndexBuffer == indexBuffer. */
+        uint16_t *ptr = r300->rws->buffer_map(r300_resource(orgIndexBuffer)->buf,
+                                              r300->cs,
+                                              PIPE_TRANSFER_READ |
+                                              PIPE_TRANSFER_UNSYNCHRONIZED);
 
         if (mode == PIPE_PRIM_TRIANGLES) {
            memcpy(indices3, ptr + start, 6);
         } else {
             /* Copy the mapped index buffer directly to the upload buffer.
              * The start index will be aligned simply from the fact that
-             * every sub-buffer in u_upload_mgr is aligned. */
-            userbuf = pipe->screen->user_buffer_create(pipe->screen,
-                                                       ptr, 0,
-                                                       PIPE_BIND_INDEX_BUFFER);
-            indexBuffer = userbuf;
-            r300_upload_index_buffer(r300, &indexBuffer, indexSize, &start, count);
-            pipe_resource_reference(&userbuf, NULL);
+             * every sub-buffer in the upload buffer is aligned. */
+            r300_upload_index_buffer(r300, &indexBuffer, indexSize, &start,
+                                     count, (uint8_t*)ptr);
         }
-        pipe_buffer_unmap(pipe, transfer);
+        r300->rws->buffer_unmap(r300_resource(orgIndexBuffer)->buf);
     } else {
-        if (r300_is_user_buffer(indexBuffer))
-            r300_upload_index_buffer(r300, &indexBuffer, indexSize, &start, count);
+        if (r300_resource(indexBuffer)->b.user_ptr)
+            r300_upload_index_buffer(r300, &indexBuffer, indexSize,
+                                     &start, count,
+                                     r300_resource(indexBuffer)->b.user_ptr);
     }
 
     /* 19 dwords for emit_draw_elements. Give up if the function fails. */
@@ -607,7 +670,11 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
                                minIndex, maxIndex, mode, start, count, indices3);
     } else {
         do {
-            short_count = MIN2(count, 65534);
+            if (indexSize == 2 && (start & 1))
+                short_count = MIN2(count, 65535);
+            else
+                short_count = MIN2(count, 65534);
+
             r300_emit_draw_elements(r300, indexBuffer, indexSize,
                                      minIndex, maxIndex,
                                      mode, start, short_count, indices3);
@@ -631,43 +698,38 @@ done:
     }
 }
 
-static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
+static void r300_draw_arrays(struct r300_context *r300, unsigned mode,
                              unsigned start, unsigned count)
 {
-    struct r300_context* r300 = r300_context(pipe);
     boolean alt_num_verts = r300->screen->caps.is_r500 &&
                             count > 65536 &&
                             r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0);
     unsigned short_count;
 
-    if (immd_is_good_idea(r300, count)) {
-        r300_emit_draw_arrays_immediate(r300, mode, start, count);
+    /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */
+    if (!r300_prepare_for_rendering(r300,
+                                    PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS,
+                                    NULL, 9, start, 0))
+        return;
+
+    if (alt_num_verts || count <= 65535) {
+        r300_emit_draw_arrays(r300, mode, count);
     } else {
-        /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */
-        if (!r300_prepare_for_rendering(r300,
-                PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS,
-                NULL, 9, start, 0))
-            return;
+        do {
+            short_count = MIN2(count, 65535);
+            r300_emit_draw_arrays(r300, mode, short_count);
 
-        if (alt_num_verts || count <= 65535) {
-            r300_emit_draw_arrays(r300, mode, count);
-        } else {
-            do {
-                short_count = MIN2(count, 65535);
-                r300_emit_draw_arrays(r300, mode, short_count);
-
-                start += short_count;
-                count -= short_count;
-
-                /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */
-                if (count) {
-                    if (!r300_prepare_for_rendering(r300,
-                            PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9,
-                            start, 0))
-                        return;
-                }
-            } while (count);
-        }
+            start += short_count;
+            count -= short_count;
+
+            /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */
+            if (count) {
+                if (!r300_prepare_for_rendering(r300,
+                                                PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9,
+                                                start, 0))
+                    return;
+            }
+        } while (count);
     }
 }
 
@@ -676,83 +738,45 @@ static void r300_draw_vbo(struct pipe_context* pipe,
 {
     struct r300_context* r300 = r300_context(pipe);
     unsigned count = info->count;
-    boolean translate = FALSE;
+    boolean buffers_updated, uploader_flushed;
     boolean indexed = info->indexed && r300->index_buffer.buffer;
-    unsigned min_index = 0;
-    unsigned max_index = r300->vertex_buffer_max_index;
+    unsigned start_indexed = info->start + r300->index_buffer.offset;
+    int max_index = MIN2(r300->vbuf_mgr->max_index, info->max_index);
 
-    if (r300->skip_rendering) {
+    if (r300->skip_rendering ||
+        !u_trim_pipe_prim(info->mode, &count)) {
         return;
     }
 
-    if (!u_trim_pipe_prim(info->mode, &count)) {
-        return;
+    /* Start the vbuf manager and update buffers if needed. */
+    u_vbuf_mgr_draw_begin(r300->vbuf_mgr, info,
+                          &buffers_updated, &uploader_flushed);
+    if (buffers_updated) {
+        r300->vertex_arrays_dirty = TRUE;
     }
 
-    if (indexed) {
-        int real_min_index, real_max_index;
-        /* Compute the start for draw_elements, taking the offset into account. */
-        unsigned start_indexed =
-            info->start +
-            (r300->index_buffer.offset / r300->index_buffer.index_size);
-
-        assert(r300->index_buffer.offset % r300->index_buffer.index_size == 0);
-
-        /* Index buffer range checking. */
-        if ((start_indexed + count) * r300->index_buffer.index_size >
-            r300->index_buffer.buffer->width0) {
-            fprintf(stderr, "r300: Invalid index buffer range. Skipping rendering.\n");
-            return;
-        }
-
-        min_index = MAX2(min_index, info->min_index);
-        max_index = MIN2(max_index, info->max_index);
-        real_min_index = (int)min_index - info->index_bias;
-        real_max_index = (int)max_index - info->index_bias;
-
-        if (max_index >= (1 << 24) - 1) {
-            fprintf(stderr, "r300: Invalid max_index: %i. Skipping rendering...\n", max_index);
-            return;
-        }
-
-        r300_update_derived_state(r300);
-
-        /* Set up the fallback for an incompatible vertex layout if needed. */
-        if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) {
-            r300_begin_vertex_translate(r300, real_min_index, real_max_index);
-            translate = TRUE;
-        }
+    /* Draw. */
+    r300_update_derived_state(r300);
 
-        /* Upload vertex buffers. */
-        if (r300->any_user_vbs) {
-            r300_upload_user_buffers(r300, real_min_index, real_max_index);
+    if (indexed) {
+        if (count <= 8 &&
+            r300_resource(r300->index_buffer.buffer)->b.user_ptr) {
+            r300_draw_elements_immediate(r300, info->index_bias,
+                                         info->min_index, max_index,
+                                         info->mode, start_indexed, count);
+        } else {
+            r300_draw_elements(r300, info->index_bias, info->min_index,
+                               max_index, info->mode, start_indexed, count);
         }
-
-        r300_draw_range_elements(pipe, info->index_bias, min_index, max_index,
-                                 info->mode, start_indexed, count);
     } else {
-        min_index = MAX2(min_index, info->start);
-        max_index = MIN2(max_index, info->start + count - 1);
-
-        r300_update_derived_state(r300);
-
-        /* Set up the fallback for an incompatible vertex layout if needed. */
-        if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) {
-            r300_begin_vertex_translate(r300, min_index, max_index);
-            translate = TRUE;
-        }
-
-        /* Upload vertex buffers. */
-        if (r300->any_user_vbs) {
-            r300_upload_user_buffers(r300, min_index, max_index);
+        if (immd_is_good_idea(r300, count)) {
+            r300_draw_arrays_immediate(r300, info->mode, info->start, count);
+        } else {
+            r300_draw_arrays(r300, info->mode, info->start, count);
         }
-
-        r300_draw_arrays(pipe, info->mode, info->start, count);
     }
 
-    if (translate) {
-        r300_end_vertex_translate(r300);
-    }
+    u_vbuf_mgr_draw_end(r300->vbuf_mgr);
 }
 
 /****************************************************************************
@@ -787,11 +811,12 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe,
             (indexed ? PREP_INDEXED : 0),
             indexed ? 256 : 6);
 
-    for (i = 0; i < r300->vertex_buffer_count; i++) {
-        if (r300->vertex_buffer[i].buffer) {
+    for (i = 0; i < r300->vbuf_mgr->nr_vertex_buffers; i++) {
+        if (r300->vbuf_mgr->vertex_buffer[i].buffer) {
             void *buf = pipe_buffer_map(pipe,
-                                  r300->vertex_buffer[i].buffer,
-                                  PIPE_TRANSFER_READ,
+                                  r300->vbuf_mgr->vertex_buffer[i].buffer,
+                                  PIPE_TRANSFER_READ |
+                                  PIPE_TRANSFER_UNSYNCHRONIZED,
                                   &vb_transfer[i]);
             draw_set_mapped_vertex_buffer(r300->draw, i, buf);
         }
@@ -799,7 +824,8 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe,
 
     if (indexed) {
         indices = pipe_buffer_map(pipe, r300->index_buffer.buffer,
-                                  PIPE_TRANSFER_READ, &ib_transfer);
+                                  PIPE_TRANSFER_READ |
+                                  PIPE_TRANSFER_UNSYNCHRONIZED, &ib_transfer);
     }
 
     draw_set_mapped_index_buffer(r300->draw, indices);
@@ -810,8 +836,8 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe,
     draw_flush(r300->draw);
     r300->draw_vbo_locked = FALSE;
 
-    for (i = 0; i < r300->vertex_buffer_count; i++) {
-        if (r300->vertex_buffer[i].buffer) {
+    for (i = 0; i < r300->vbuf_mgr->nr_vertex_buffers; i++) {
+        if (r300->vbuf_mgr->vertex_buffer[i].buffer) {
             pipe_buffer_unmap(pipe, vb_transfer[i]);
             draw_set_mapped_vertex_buffer(r300->draw, i, NULL);
         }
@@ -874,10 +900,10 @@ static boolean r300_render_allocate_vertices(struct vbuf_render* render,
        pipe_resource_reference(&r300->vbo, NULL);
         r300->vbo = pipe_buffer_create(screen,
                                       PIPE_BIND_VERTEX_BUFFER,
+                                      PIPE_USAGE_STREAM,
                                       R300_MAX_DRAW_VBO_SIZE);
         r300->draw_vbo_offset = 0;
         r300->draw_vbo_size = R300_MAX_DRAW_VBO_SIZE;
-        r300->validate_buffers = TRUE;
     }
 
     r300render->vertex_size = vertex_size;
@@ -896,7 +922,8 @@ static void* r300_render_map_vertices(struct vbuf_render* render)
 
     r300render->vbo_ptr = pipe_buffer_map(&r300render->r300->context,
                                          r300->vbo,
-                                          PIPE_TRANSFER_WRITE,
+                                          PIPE_TRANSFER_WRITE |
+                                          PIPE_TRANSFER_UNSYNCHRONIZED,
                                          &r300render->vbo_transfer);
 
     assert(r300render->vbo_ptr);
@@ -963,7 +990,7 @@ static void r300_render_draw_arrays(struct vbuf_render* render,
     if (r300->draw_first_emitted) {
         if (!r300_prepare_for_rendering(r300,
                 PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL,
-                NULL, 6, 0, 0))
+                NULL, dwords, 0, 0))
             return;
     } else {
         if (!r300_emit_states(r300,
@@ -972,23 +999,6 @@ static void r300_render_draw_arrays(struct vbuf_render* render,
             return;
     }
 
-    /* Uncomment to dump all VBOs rendered through this interface.
-     * Slow and noisy!
-    ptr = pipe_buffer_map(&r300render->r300->context,
-                          r300render->vbo, PIPE_TRANSFER_READ,
-                          &r300render->vbo_transfer);
-
-    for (i = 0; i < count; i++) {
-        printf("r300: Vertex %d\n", i);
-        draw_dump_emitted_vertex(&r300->vertex_info, ptr);
-        ptr += r300->vertex_info.size * 4;
-        printf("\n");
-    }
-
-    pipe_buffer_unmap(&r300render->r300->context, r300render->vbo,
-        r300render->vbo_transfer);
-    */
-
     BEGIN_CS(dwords);
     OUT_CS_REG(R300_GA_COLOR_CONTROL,
             r300_provoking_vertex_fixes(r300, r300render->prim));
@@ -1250,7 +1260,7 @@ static void r300_resource_resolve(struct pipe_context* pipe,
     aa->aaresolve_ctl =
         R300_RB3D_AARESOLVE_CTL_AARESOLVE_MODE_RESOLVE |
         R300_RB3D_AARESOLVE_CTL_AARESOLVE_ALPHA_AVERAGE;
-    r300->aa_state.size = 12;
+    r300->aa_state.size = 10;
     r300_mark_atom_dirty(r300, &r300->aa_state);
 
     /* Resolve the surface. */
index c48062c80845392b8ff0d02105abd8dad588b082..f8c7558f4b4ef8795b8c4f810ee305b0a2bb147b 100644 (file)
  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
 
-/**
- * The functions below translate vertex and index buffers to the layout
- * compatible with the hardware, so that all vertex and index fetches are
- * DWORD-aligned and all used vertex and index formats are supported.
- * For indices, an optional index offset is added to each index.
- */
-
 #include "r300_context.h"
-#include "translate/translate.h"
 #include "util/u_index_modify.h"
+#include "util/u_upload_mgr.h"
 
-/* XXX Optimization: use min_index and translate only that range. */
-/* XXX Use the uploader. */
-void r300_begin_vertex_translate(struct r300_context *r300,
-                                 int min_index, int max_index)
-{
-    struct pipe_context *pipe = &r300->context;
-    struct translate_key key = {0};
-    struct translate_element *te;
-    unsigned tr_elem_index[PIPE_MAX_ATTRIBS] = {0};
-    struct translate *tr;
-    struct r300_vertex_element_state *ve = r300->velems;
-    boolean vb_translated[PIPE_MAX_ATTRIBS] = {0};
-    void *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map;
-    struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}, *out_transfer;
-    struct pipe_resource *out_buffer;
-    unsigned i, num_verts;
-    unsigned slot;
-
-    /* Initialize the translate key, i.e. the recipe how vertices should be
-     * translated. */
-    for (i = 0; i < ve->count; i++) {
-        struct pipe_vertex_buffer *vb =
-                &r300->vertex_buffer[ve->velem[i].vertex_buffer_index];
-        enum pipe_format output_format = ve->hw_format[i];
-        unsigned output_format_size = ve->hw_format_size[i];
-
-        /* Check for support. */
-        if (ve->velem[i].src_format == ve->hw_format[i] &&
-            (vb->buffer_offset + ve->velem[i].src_offset) % 4 == 0 &&
-            vb->stride % 4 == 0) {
-            continue;
-        }
-
-        /* Workaround for translate: output floats instead of halfs. */
-        switch (output_format) {
-            case PIPE_FORMAT_R16_FLOAT:
-                output_format = PIPE_FORMAT_R32_FLOAT;
-                output_format_size = 4;
-                break;
-            case PIPE_FORMAT_R16G16_FLOAT:
-                output_format = PIPE_FORMAT_R32G32_FLOAT;
-                output_format_size = 8;
-                break;
-            case PIPE_FORMAT_R16G16B16_FLOAT:
-                output_format = PIPE_FORMAT_R32G32B32_FLOAT;
-                output_format_size = 12;
-                break;
-            case PIPE_FORMAT_R16G16B16A16_FLOAT:
-                output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
-                output_format_size = 16;
-                break;
-            default:;
-        }
-
-        /* Add this vertex element. */
-        te = &key.element[key.nr_elements];
-        /*te->type;
-        te->instance_divisor;*/
-        te->input_buffer = ve->velem[i].vertex_buffer_index;
-        te->input_format = ve->velem[i].src_format;
-        te->input_offset = vb->buffer_offset + ve->velem[i].src_offset;
-        te->output_format = output_format;
-        te->output_offset = key.output_stride;
-
-        key.output_stride += output_format_size;
-        vb_translated[ve->velem[i].vertex_buffer_index] = TRUE;
-        tr_elem_index[i] = key.nr_elements;
-        key.nr_elements++;
-    }
-
-    /* Get a translate object. */
-    tr = translate_cache_find(r300->tran.translate_cache, &key);
-
-    /* Map buffers we want to translate. */
-    for (i = 0; i < r300->vertex_buffer_count; i++) {
-        if (vb_translated[i]) {
-            struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i];
-
-            vb_map[i] = pipe_buffer_map(pipe, vb->buffer,
-                                        PIPE_TRANSFER_READ, &vb_transfer[i]);
-
-            tr->set_buffer(tr, i, vb_map[i], vb->stride, max_index);
-        }
-    }
-
-    /* Create and map the output buffer. */
-    num_verts = max_index + 1;
-
-    out_buffer = pipe_buffer_create(&r300->screen->screen,
-                                    PIPE_BIND_VERTEX_BUFFER,
-                                    key.output_stride * num_verts);
-
-    out_map = pipe_buffer_map(pipe, out_buffer, PIPE_TRANSFER_WRITE,
-                              &out_transfer);
-
-    /* Translate. */
-    tr->run(tr, 0, num_verts, 0, out_map);
-
-    /* Unmap all buffers. */
-    for (i = 0; i < r300->vertex_buffer_count; i++) {
-        if (vb_translated[i]) {
-            pipe_buffer_unmap(pipe, vb_transfer[i]);
-        }
-    }
-
-    pipe_buffer_unmap(pipe, out_transfer);
-
-    /* Setup the new vertex buffer in the first free slot. */
-    slot = ~0;
-    for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
-        struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i];
-
-        if (!vb->buffer) {
-            pipe_resource_reference(&r300->valid_vertex_buffer[i], out_buffer);
-            vb->buffer_offset = 0;
-            vb->stride = key.output_stride;
-            slot = i;
-            /* XXX probably need to preserve the real count for u_blitter_save_*. */
-            r300->vertex_buffer_count = MAX2(r300->vertex_buffer_count, i+1);
-            r300->validate_buffers = TRUE;
-            break;
-        }
-    }
-    /* XXX This may fail. */
-    assert(slot != ~0);
-
-    /* Save and replace vertex elements. */
-    {
-        struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS];
-
-        r300->tran.saved_velems = r300->velems;
-
-        for (i = 0; i < ve->count; i++) {
-            if (vb_translated[ve->velem[i].vertex_buffer_index]) {
-                te = &key.element[tr_elem_index[i]];
-                new_velems[i].instance_divisor = ve->velem[i].instance_divisor;
-                new_velems[i].src_format = te->output_format;
-                new_velems[i].src_offset = te->output_offset;
-                new_velems[i].vertex_buffer_index = slot;
-            } else {
-                memcpy(&new_velems[i], &ve->velem[i],
-                       sizeof(struct pipe_vertex_element));
-            }
-        }
-
-        r300->tran.new_velems =
-            pipe->create_vertex_elements_state(pipe, ve->count, new_velems);
-        pipe->bind_vertex_elements_state(pipe, r300->tran.new_velems);
-    }
-
-    pipe_resource_reference(&out_buffer, NULL);
-}
 
-void r300_end_vertex_translate(struct r300_context *r300)
-{
-    struct pipe_context *pipe = &r300->context;
-
-    /* Restore vertex elements. */
-    pipe->bind_vertex_elements_state(pipe, r300->tran.saved_velems);
-    pipe->delete_vertex_elements_state(pipe, r300->tran.new_velems);
-}
-
-/* XXX Use the uploader. */
 void r300_translate_index_buffer(struct r300_context *r300,
                                  struct pipe_resource **index_buffer,
                                  unsigned *index_size, unsigned index_offset,
                                  unsigned *start, unsigned count)
 {
+    struct pipe_resource *out_buffer = NULL;
+    unsigned out_offset;
+    void *ptr;
+    boolean flushed;
+
     switch (*index_size) {
-        case 1:
-            util_shorten_ubyte_elts(&r300->context, index_buffer, index_offset, *start, count);
-            *index_size = 2;
-            *start = 0;
-            r300->validate_buffers = TRUE;
-            break;
+    case 1:
+        u_upload_alloc(r300->vbuf_mgr->uploader, 0, count * 2,
+                       &out_offset, &out_buffer, &flushed, &ptr);
+
+        util_shorten_ubyte_elts_to_userptr(
+                &r300->context, *index_buffer, index_offset,
+                *start, count, ptr);
+
+       *index_buffer = NULL;
+        pipe_resource_reference(index_buffer, out_buffer);
+        *index_size = 2;
+        *start = out_offset / 2;
+        break;
+
+    case 2:
+        if (index_offset) {
+            u_upload_alloc(r300->vbuf_mgr->uploader, 0, count * 2,
+                           &out_offset, &out_buffer, &flushed, &ptr);
+
+            util_rebuild_ushort_elts_to_userptr(&r300->context, *index_buffer,
+                                                index_offset, *start,
+                                                count, ptr);
+
+           *index_buffer = NULL;
+            pipe_resource_reference(index_buffer, out_buffer);
+            *start = out_offset / 2;
+        }
+        break;
 
-        case 2:
-            if (index_offset) {
-                util_rebuild_ushort_elts(&r300->context, index_buffer, index_offset, *start, count);
-                *start = 0;
-                r300->validate_buffers = TRUE;
-            }
-            break;
+    case 4:
+        if (index_offset) {
+            u_upload_alloc(r300->vbuf_mgr->uploader, 0, count * 4,
+                           &out_offset, &out_buffer, &flushed, &ptr);
 
-        case 4:
-            if (index_offset) {
-                util_rebuild_uint_elts(&r300->context, index_buffer, index_offset, *start, count);
-                *start = 0;
-                r300->validate_buffers = TRUE;
-            }
-            break;
+            util_rebuild_uint_elts_to_userptr(&r300->context, *index_buffer,
+                                              index_offset, *start,
+                                              count, ptr);
+
+           *index_buffer = NULL;
+            pipe_resource_reference(index_buffer, out_buffer);
+            *start = out_offset / 4;
+        }
+        break;
     }
 }
index dd1df970594c00c1ec3b25970b56a08e2c230eb4..f3d8c5b889f5c51d199c114a92991fe8e308a15a 100644 (file)
@@ -38,26 +38,22 @@ r300_resource_create(struct pipe_screen *screen,
 
 }
 
-static struct pipe_resource *
-r300_resource_from_handle(struct pipe_screen * screen,
-                        const struct pipe_resource *templ,
-                        struct winsys_handle *whandle)
+static unsigned r300_resource_is_referenced_by_cs(struct pipe_context *context,
+                                                  struct pipe_resource *buf,
+                                                  unsigned level, int layer)
 {
-   if (templ->target == PIPE_BUFFER)
-      return NULL;
-   else
-      return r300_texture_from_handle(screen, templ, whandle);
+    return r300_buffer_is_referenced(context, buf);
 }
 
 void r300_init_resource_functions(struct r300_context *r300)
 {
    r300->context.get_transfer = u_get_transfer_vtbl;
    r300->context.transfer_map = u_transfer_map_vtbl;
-   r300->context.transfer_flush_region = u_transfer_flush_region_vtbl;
+   r300->context.transfer_flush_region = u_default_transfer_flush_region;
    r300->context.transfer_unmap = u_transfer_unmap_vtbl;
    r300->context.transfer_destroy = u_transfer_destroy_vtbl;
    r300->context.transfer_inline_write = u_transfer_inline_write_vtbl;
-   r300->context.is_resource_referenced = u_is_resource_referenced_vtbl;
+   r300->context.is_resource_referenced = r300_resource_is_referenced_by_cs;
    r300->context.create_surface = r300_create_surface;
    r300->context.surface_destroy = r300_surface_destroy;
 }
@@ -65,8 +61,8 @@ void r300_init_resource_functions(struct r300_context *r300)
 void r300_init_screen_resource_functions(struct r300_screen *r300screen)
 {
    r300screen->screen.resource_create = r300_resource_create;
-   r300screen->screen.resource_from_handle = r300_resource_from_handle;
-   r300screen->screen.resource_get_handle = u_resource_get_handle_vtbl;
+   r300screen->screen.resource_from_handle = r300_texture_from_handle;
+   r300screen->screen.resource_get_handle = r300_resource_get_handle;
    r300screen->screen.resource_destroy = u_resource_destroy_vtbl;
    r300screen->screen.user_buffer_create = r300_user_buffer_create;
 }
index c75aeaa10a7f2155ff15ed8c5cb1f4f87fdff4b7..77a9c6ad86f88db92a8cbecf77b1db5329b469a4 100644 (file)
 
 #include "draw/draw_context.h"
 
-#ifdef HAVE_LLVM
-#include "gallivm/lp_bld_init.h"
-#endif
-
 /* Return the identifier behind whom the brave coders responsible for this
  * amalgamation of code, sweat, and duct tape, routinely obscure their names.
  *
@@ -87,12 +83,8 @@ static const char* r300_get_name(struct pipe_screen* pscreen)
 static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
 {
     struct r300_screen* r300screen = r300_screen(pscreen);
-    boolean is_r400 = r300screen->caps.is_r400;
     boolean is_r500 = r300screen->caps.is_r500;
 
-    /* XXX extended shader capabilities of r400 unimplemented */
-    is_r400 = FALSE;
-
     switch (param) {
         /* Supported features (boolean caps). */
         case PIPE_CAP_NPOT_TEXTURES:
@@ -129,11 +121,13 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
         case PIPE_CAP_DUAL_SOURCE_BLEND:
         case PIPE_CAP_INDEP_BLEND_ENABLE:
         case PIPE_CAP_INDEP_BLEND_FUNC:
-        case PIPE_CAP_DEPTH_CLAMP: /* XXX implemented, but breaks Regnum Online */
+        case PIPE_CAP_DEPTH_CLAMP:
         case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
         case PIPE_CAP_SHADER_STENCIL_EXPORT:
         case PIPE_CAP_STREAM_OUTPUT:
         case PIPE_CAP_PRIMITIVE_RESTART:
+        case PIPE_CAP_INSTANCED_DRAWING:
+        case PIPE_CAP_ARRAY_TEXTURES:
             return 0;
 
         /* Texturing. */
@@ -175,9 +169,6 @@ static int r300_get_shader_param(struct pipe_screen *pscreen, unsigned shader, e
    boolean is_r400 = r300screen->caps.is_r400;
    boolean is_r500 = r300screen->caps.is_r500;
 
-   /* XXX extended shader capabilities of r400 unimplemented */
-   is_r400 = FALSE;
-
    switch (shader)
     {
     case PIPE_SHADER_FRAGMENT:
@@ -407,6 +398,7 @@ static void r300_destroy_screen(struct pipe_screen* pscreen)
     struct r300_winsys_screen *rws = r300_winsys_screen(pscreen);
 
     util_slab_destroy(&r300screen->pool_buffers);
+    pipe_mutex_destroy(r300screen->num_contexts_mutex);
 
     if (rws)
       rws->destroy(rws);
@@ -418,32 +410,28 @@ static void r300_fence_reference(struct pipe_screen *screen,
                                  struct pipe_fence_handle **ptr,
                                  struct pipe_fence_handle *fence)
 {
-    struct r300_fence **oldf = (struct r300_fence**)ptr;
-    struct r300_fence *newf = (struct r300_fence*)fence;
-
-    if (pipe_reference(&(*oldf)->reference, &newf->reference))
-        FREE(*oldf);
-
-    *ptr = fence;
+    r300_winsys_bo_reference((struct r300_winsys_bo**)ptr,
+                             (struct r300_winsys_bo*)fence);
 }
 
 static int r300_fence_signalled(struct pipe_screen *screen,
                                 struct pipe_fence_handle *fence,
                                 unsigned flags)
 {
-    struct r300_fence *rfence = (struct r300_fence*)fence;
+    struct r300_winsys_screen *rws = r300_screen(screen)->rws;
+    struct r300_winsys_bo *rfence = (struct r300_winsys_bo*)fence;
 
-    return rfence->signalled ? 0 : 1; /* 0 == success */
+    return !rws->buffer_is_busy(rfence) ? 0 : 1; /* 0 == success */
 }
 
 static int r300_fence_finish(struct pipe_screen *screen,
                              struct pipe_fence_handle *fence,
                              unsigned flags)
 {
-    struct r300_fence *rfence = (struct r300_fence*)fence;
+    struct r300_winsys_screen *rws = r300_screen(screen)->rws;
+    struct r300_winsys_bo *rfence = (struct r300_winsys_bo*)fence;
 
-    r300_finish(rfence->ctx);
-    rfence->signalled = TRUE;
+    rws->buffer_wait(rfence);
     return 0; /* 0 == success */
 }
 
@@ -463,12 +451,19 @@ struct pipe_screen* r300_screen_create(struct r300_winsys_screen *rws)
     r300_init_debug(r300screen);
     r300_parse_chipset(&r300screen->caps);
 
+    if (SCREEN_DBG_ON(r300screen, DBG_NO_ZMASK))
+        r300screen->caps.zmask_ram = 0;
+    if (SCREEN_DBG_ON(r300screen, DBG_NO_HIZ))
+        r300screen->caps.hiz_ram = 0;
+
     r300screen->caps.index_bias_supported =
             r300screen->caps.is_r500 &&
             rws->get_value(rws, R300_VID_DRM_2_3_0);
 
+    pipe_mutex_init(r300screen->num_contexts_mutex);
+
     util_slab_create(&r300screen->pool_buffers,
-                     sizeof(struct r300_buffer), 64,
+                     sizeof(struct r300_resource), 64,
                      UTIL_SLAB_SINGLETHREADED);
 
     r300screen->rws = rws;
@@ -490,9 +485,5 @@ struct pipe_screen* r300_screen_create(struct r300_winsys_screen *rws)
 
     util_format_s3tc_init();
 
-#ifdef HAVE_LLVM
-    lp_build_init();
-#endif
-
     return &r300screen->screen;
 }
index 752f53b7579842a43faeca29c43848e4c2843176..576f9c1f4a96e65595b3ba35048b21fee03bb2d9 100644 (file)
@@ -52,6 +52,7 @@ struct r300_screen {
     /* The number of created contexts to know whether we have multiple
      * contexts or not. */
     int num_contexts;
+    pipe_mutex num_contexts_mutex;
 };
 
 
@@ -94,6 +95,7 @@ r300_winsys_screen(struct pipe_screen *screen) {
 #define DBG_HYPERZ      (1 << 12)
 #define DBG_SCISSOR     (1 << 13)
 #define DBG_UPLOAD      (1 << 14)
+#define DBG_INFO        (1 << 15)
 /* Features. */
 #define DBG_ANISOHQ     (1 << 16)
 #define DBG_NO_TILING   (1 << 17)
@@ -101,6 +103,8 @@ r300_winsys_screen(struct pipe_screen *screen) {
 #define DBG_FAKE_OCC    (1 << 19)
 #define DBG_NO_OPT      (1 << 20)
 #define DBG_NO_CBZB     (1 << 21)
+#define DBG_NO_ZMASK    (1 << 22)
+#define DBG_NO_HIZ      (1 << 23)
 /* Statistics. */
 #define DBG_P_STAT      (1 << 25)
 /*@}*/
index cc3c1d7687edebb807036cbfdc1e31a823f783f5..1045911f3ae8f52c75de50c096c8dab29e4f7136 100644 (file)
 #include "r300_winsys.h"
 
 unsigned r300_buffer_is_referenced(struct pipe_context *context,
-                                  struct pipe_resource *buf,
-                                   enum r300_reference_domain domain)
+                                  struct pipe_resource *buf)
 {
     struct r300_context *r300 = r300_context(context);
-    struct r300_buffer *rbuf = r300_buffer(buf);
+    struct r300_resource *rbuf = r300_resource(buf);
 
-    if (r300_is_user_buffer(buf))
+    if (rbuf->b.user_ptr || rbuf->constant_buffer)
        return PIPE_UNREFERENCED;
 
-    if (r300->rws->cs_is_buffer_referenced(r300->cs, rbuf->cs_buf, domain))
+    if (r300->rws->cs_is_buffer_referenced(r300->cs, rbuf->cs_buf))
         return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
 
     return PIPE_UNREFERENCED;
 }
 
-static unsigned r300_buffer_is_referenced_by_cs(struct pipe_context *context,
-                                                struct pipe_resource *buf,
-                                                unsigned level, int layer)
-{
-    return r300_buffer_is_referenced(context, buf, R300_REF_CS);
-}
-
 void r300_upload_index_buffer(struct r300_context *r300,
                              struct pipe_resource **index_buffer,
                              unsigned index_size, unsigned *start,
-                             unsigned count)
+                             unsigned count, uint8_t *ptr)
 {
     unsigned index_offset;
-    uint8_t *ptr = r300_buffer(*index_buffer)->user_buffer;
     boolean flushed;
 
     *index_buffer = NULL;
 
-    u_upload_data(r300->upload_ib,
+    u_upload_data(r300->vbuf_mgr->uploader,
                   0, count * index_size,
                   ptr + (*start * index_size),
                   &index_offset,
                   index_buffer, &flushed);
 
     *start = index_offset / index_size;
-
-    if (flushed || !r300->upload_ib_validated) {
-        r300->upload_ib_validated = FALSE;
-        r300->validate_buffers = TRUE;
-    }
-}
-
-void r300_upload_user_buffers(struct r300_context *r300,
-                              int min_index, int max_index)
-{
-    int i, nr = r300->velems->count;
-    unsigned count = max_index + 1 - min_index;
-    boolean flushed;
-    boolean uploaded[16] = {0};
-
-    for (i = 0; i < nr; i++) {
-        unsigned index = r300->velems->velem[i].vertex_buffer_index;
-        struct pipe_vertex_buffer *vb = &r300->vertex_buffer[index];
-        struct r300_buffer *userbuf = r300_buffer(vb->buffer);
-
-        if (userbuf && userbuf->user_buffer && !uploaded[index]) {
-            unsigned first, size;
-
-            if (vb->stride) {
-                first = vb->stride * min_index;
-                size = vb->stride * count;
-            } else {
-                first = 0;
-                size = r300->velems->hw_format_size[i];
-            }
-
-            DBG(r300, DBG_UPLOAD,
-                "Uploading %i bytes, index: %i, buffer: %p, userptr: %p "
-                "offset: %i, stride: %i.\n",
-                size, index, userbuf, userbuf->user_buffer,
-                vb->buffer_offset, vb->stride);
-
-            u_upload_data(r300->upload_vb, first, size,
-                          userbuf->user_buffer + first,
-                          &vb->buffer_offset,
-                          &r300->valid_vertex_buffer[index],
-                          &flushed);
-
-            vb->buffer_offset -= first;
-
-            r300->vertex_arrays_dirty = TRUE;
-
-            if (flushed || !r300->upload_vb_validated) {
-                r300->upload_vb_validated = FALSE;
-                r300->validate_buffers = TRUE;
-            }
-            uploaded[index] = TRUE;
-        } else {
-            assert(r300->valid_vertex_buffer[index]);
-        }
-    }
-    DBG(r300, DBG_UPLOAD, "-------\n");
 }
 
 static void r300_buffer_destroy(struct pipe_screen *screen,
                                struct pipe_resource *buf)
 {
     struct r300_screen *r300screen = r300_screen(screen);
-    struct r300_buffer *rbuf = r300_buffer(buf);
-    struct r300_winsys_screen *rws = r300screen->rws;
+    struct r300_resource *rbuf = r300_resource(buf);
 
     if (rbuf->constant_buffer)
         FREE(rbuf->constant_buffer);
 
     if (rbuf->buf)
-        rws->buffer_reference(rws, &rbuf->buf, NULL);
+        r300_winsys_bo_reference(&rbuf->buf, NULL);
 
     util_slab_free(&r300screen->pool_buffers, rbuf);
 }
@@ -188,15 +121,15 @@ r300_buffer_transfer_map( struct pipe_context *pipe,
     struct r300_context *r300 = r300_context(pipe);
     struct r300_screen *r300screen = r300_screen(pipe->screen);
     struct r300_winsys_screen *rws = r300screen->rws;
-    struct r300_buffer *rbuf = r300_buffer(transfer->resource);
+    struct r300_resource *rbuf = r300_resource(transfer->resource);
     uint8_t *map;
 
-    if (rbuf->user_buffer)
-        return (uint8_t *) rbuf->user_buffer + transfer->box.x;
+    if (rbuf->b.user_ptr)
+        return (uint8_t *) rbuf->b.user_ptr + transfer->box.x;
     if (rbuf->constant_buffer)
         return (uint8_t *) rbuf->constant_buffer + transfer->box.x;
 
-    map = rws->buffer_map(rws, rbuf->buf, r300->cs, transfer->usage);
+    map = rws->buffer_map(rbuf->buf, r300->cs, transfer->usage);
 
     if (map == NULL)
         return NULL;
@@ -204,22 +137,15 @@ r300_buffer_transfer_map( struct pipe_context *pipe,
     return map + transfer->box.x;
 }
 
-static void r300_buffer_transfer_flush_region( struct pipe_context *pipe,
-                                              struct pipe_transfer *transfer,
-                                              const struct pipe_box *box)
-{
-    /* no-op */
-}
-
 static void r300_buffer_transfer_unmap( struct pipe_context *pipe,
                            struct pipe_transfer *transfer )
 {
     struct r300_screen *r300screen = r300_screen(pipe->screen);
     struct r300_winsys_screen *rws = r300screen->rws;
-    struct r300_buffer *rbuf = r300_buffer(transfer->resource);
+    struct r300_resource *rbuf = r300_resource(transfer->resource);
 
     if (rbuf->buf) {
-        rws->buffer_unmap(rws, rbuf->buf);
+        rws->buffer_unmap(rbuf->buf);
     }
 }
 
@@ -234,32 +160,32 @@ static void r300_buffer_transfer_inline_write(struct pipe_context *pipe,
 {
     struct r300_context *r300 = r300_context(pipe);
     struct r300_winsys_screen *rws = r300->screen->rws;
-    struct r300_buffer *rbuf = r300_buffer(resource);
+    struct r300_resource *rbuf = r300_resource(resource);
     uint8_t *map = NULL;
 
     if (rbuf->constant_buffer) {
         memcpy(rbuf->constant_buffer + box->x, data, box->width);
         return;
     }
-    assert(rbuf->user_buffer == NULL);
+    assert(rbuf->b.user_ptr == NULL);
 
-    map = rws->buffer_map(rws, rbuf->buf, r300->cs,
+    map = rws->buffer_map(rbuf->buf, r300->cs,
                           PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | usage);
 
     memcpy(map + box->x, data, box->width);
 
-    rws->buffer_unmap(rws, rbuf->buf);
+    rws->buffer_unmap(rbuf->buf);
 }
 
-struct u_resource_vtbl r300_buffer_vtbl =
+static const struct u_resource_vtbl r300_buffer_vtbl =
 {
-   u_default_resource_get_handle,      /* get_handle */
+   NULL,                               /* get_handle */
    r300_buffer_destroy,                /* resource_destroy */
-   r300_buffer_is_referenced_by_cs,    /* is_buffer_referenced */
+   NULL,                               /* is_buffer_referenced */
    r300_buffer_get_transfer,           /* get_transfer */
    r300_buffer_transfer_destroy,       /* transfer_destroy */
    r300_buffer_transfer_map,           /* transfer_map */
-   r300_buffer_transfer_flush_region,  /* transfer_flush_region */
+   NULL,                               /* transfer_flush_region */
    r300_buffer_transfer_unmap,         /* transfer_unmap */
    r300_buffer_transfer_inline_write   /* transfer_inline_write */
 };
@@ -268,42 +194,41 @@ struct pipe_resource *r300_buffer_create(struct pipe_screen *screen,
                                         const struct pipe_resource *templ)
 {
     struct r300_screen *r300screen = r300_screen(screen);
-    struct r300_buffer *rbuf;
+    struct r300_resource *rbuf;
     unsigned alignment = 16;
 
     rbuf = util_slab_alloc(&r300screen->pool_buffers);
 
-    rbuf->magic = R300_BUFFER_MAGIC;
-
-    rbuf->b.b = *templ;
-    rbuf->b.vtbl = &r300_buffer_vtbl;
-    pipe_reference_init(&rbuf->b.b.reference, 1);
-    rbuf->b.b.screen = screen;
+    rbuf->b.b.b = *templ;
+    rbuf->b.b.vtbl = &r300_buffer_vtbl;
+    pipe_reference_init(&rbuf->b.b.b.reference, 1);
+    rbuf->b.b.b.screen = screen;
+    rbuf->b.user_ptr = NULL;
     rbuf->domain = R300_DOMAIN_GTT;
     rbuf->buf = NULL;
+    rbuf->buf_size = templ->width0;
     rbuf->constant_buffer = NULL;
-    rbuf->user_buffer = NULL;
 
     /* Alloc constant buffers in RAM. */
     if (templ->bind & PIPE_BIND_CONSTANT_BUFFER) {
         rbuf->constant_buffer = MALLOC(templ->width0);
-        return &rbuf->b.b;
+        return &rbuf->b.b.b;
     }
 
     rbuf->buf =
         r300screen->rws->buffer_create(r300screen->rws,
-                                       rbuf->b.b.width0, alignment,
-                                       rbuf->b.b.bind, rbuf->b.b.usage,
+                                       rbuf->b.b.b.width0, alignment,
+                                       rbuf->b.b.b.bind, rbuf->b.b.b.usage,
                                        rbuf->domain);
-    rbuf->cs_buf =
-        r300screen->rws->buffer_get_cs_handle(r300screen->rws, rbuf->buf);
-
     if (!rbuf->buf) {
         util_slab_free(&r300screen->pool_buffers, rbuf);
         return NULL;
     }
 
-    return &rbuf->b.b;
+    rbuf->cs_buf =
+        r300screen->rws->buffer_get_cs_handle(rbuf->buf);
+
+    return &rbuf->b.b.b;
 }
 
 struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen,
@@ -311,27 +236,26 @@ struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen,
                                              unsigned bind)
 {
     struct r300_screen *r300screen = r300_screen(screen);
-    struct r300_buffer *rbuf;
+    struct r300_resource *rbuf;
 
     rbuf = util_slab_alloc(&r300screen->pool_buffers);
 
-    rbuf->magic = R300_BUFFER_MAGIC;
-
-    pipe_reference_init(&rbuf->b.b.reference, 1);
-    rbuf->b.vtbl = &r300_buffer_vtbl;
-    rbuf->b.b.screen = screen;
-    rbuf->b.b.target = PIPE_BUFFER;
-    rbuf->b.b.format = PIPE_FORMAT_R8_UNORM;
-    rbuf->b.b.usage = PIPE_USAGE_IMMUTABLE;
-    rbuf->b.b.bind = bind;
-    rbuf->b.b.width0 = ~0;
-    rbuf->b.b.height0 = 1;
-    rbuf->b.b.depth0 = 1;
-    rbuf->b.b.array_size = 1;
-    rbuf->b.b.flags = 0;
+    pipe_reference_init(&rbuf->b.b.b.reference, 1);
+    rbuf->b.b.b.screen = screen;
+    rbuf->b.b.b.target = PIPE_BUFFER;
+    rbuf->b.b.b.format = PIPE_FORMAT_R8_UNORM;
+    rbuf->b.b.b.usage = PIPE_USAGE_IMMUTABLE;
+    rbuf->b.b.b.bind = bind;
+    rbuf->b.b.b.width0 = ~0;
+    rbuf->b.b.b.height0 = 1;
+    rbuf->b.b.b.depth0 = 1;
+    rbuf->b.b.b.array_size = 1;
+    rbuf->b.b.b.flags = 0;
+    rbuf->b.b.vtbl = &r300_buffer_vtbl;
+    rbuf->b.user_ptr = ptr;
     rbuf->domain = R300_DOMAIN_GTT;
     rbuf->buf = NULL;
+    rbuf->buf_size = size;
     rbuf->constant_buffer = NULL;
-    rbuf->user_buffer = ptr;
-    return &rbuf->b.b;
+    return &rbuf->b.b.b;
 }
index 58dec8539b668e390ca58518edbf75019fc3ce49..14bee460d5b0602ad9d8dfc50d05518346324849 100644 (file)
 #include "r300_winsys.h"
 #include "r300_context.h"
 
-#define R300_BUFFER_MAGIC 0xabcd1234
-#define R300_BUFFER_MAX_RANGES 32
-
-struct r300_buffer_range {
-    uint32_t start;
-    uint32_t end;
-};
-
-/* Vertex buffer. */
-struct r300_buffer
-{
-    struct u_resource b;
-
-    uint32_t magic;
-
-    struct r300_winsys_buffer *buf;
-    struct r300_winsys_cs_buffer *cs_buf;
-
-    enum r300_buffer_domain domain;
-
-    uint8_t *user_buffer;
-    uint8_t *constant_buffer;
-};
-
 /* Functions. */
 
-void r300_upload_user_buffers(struct r300_context *r300,
-                             int min_index, int max_index);
-
 void r300_upload_index_buffer(struct r300_context *r300,
                              struct pipe_resource **index_buffer,
                              unsigned index_size, unsigned *start,
-                             unsigned count);
+                             unsigned count, uint8_t *ptr);
 
 struct pipe_resource *r300_buffer_create(struct pipe_screen *screen,
                                         const struct pipe_resource *templ);
@@ -77,8 +50,7 @@ struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen,
                                              unsigned bind);
 
 unsigned r300_buffer_is_referenced(struct pipe_context *context,
-                                  struct pipe_resource *buf,
-                                   enum r300_reference_domain domain);
+                                  struct pipe_resource *buf);
 
 /* Inline functions. */
 
@@ -87,9 +59,4 @@ static INLINE struct r300_buffer *r300_buffer(struct pipe_resource *buffer)
     return (struct r300_buffer *)buffer;
 }
 
-static INLINE boolean r300_is_user_buffer(struct pipe_resource *buffer)
-{
-    return r300_buffer(buffer)->user_buffer ? true : false;
-}
-
 #endif
index 3a97b76a4c8187bb1532757972c5f22e468c4474..09f18b3e6246cde10dbf0499aa752e7b40f6e4d3 100644 (file)
@@ -28,6 +28,7 @@
 #include "util/u_mm.h"
 #include "util/u_memory.h"
 #include "util/u_pack_color.h"
+#include "util/u_transfer.h"
 
 #include "tgsi/tgsi_parse.h"
 
@@ -442,8 +443,7 @@ static void r300_set_clip_state(struct pipe_context* pipe,
            OUT_CB_TABLE(state->ucp, state->nr * 4);
         }
         OUT_CB_REG(R300_VAP_CLIP_CNTL, ((1 << state->nr) - 1) |
-                R300_PS_UCP_MODE_CLIP_AS_TRIFAN |
-                (state->depth_clamp ? R300_CLIP_DISABLE : 0));
+                   R300_PS_UCP_MODE_CLIP_AS_TRIFAN);
         END_CB;
 
         r300_mark_atom_dirty(r300, &r300->clip_state);
@@ -617,21 +617,16 @@ static void r300_set_stencil_ref(struct pipe_context* pipe,
 }
 
 static void r300_tex_set_tiling_flags(struct r300_context *r300,
-                                      struct r300_texture *tex, unsigned level)
+                                      struct r300_resource *tex,
+                                      unsigned level)
 {
     /* Check if the macrotile flag needs to be changed.
      * Skip changing the flags otherwise. */
-    if (tex->desc.macrotile[tex->surface_level] !=
-        tex->desc.macrotile[level]) {
-        /* Tiling determines how DRM treats the buffer data.
-         * We must flush CS when changing it if the buffer is referenced. */
-        if (r300->rws->cs_is_buffer_referenced(r300->cs,
-                                               tex->cs_buffer, R300_REF_CS))
-            r300->context.flush(&r300->context, 0, NULL);
-
-        r300->rws->buffer_set_tiling(r300->rws, tex->buffer,
-                tex->desc.microtile, tex->desc.macrotile[level],
-                tex->desc.stride_in_bytes[0]);
+    if (tex->tex.macrotile[tex->surface_level] !=
+        tex->tex.macrotile[level]) {
+        r300->rws->buffer_set_tiling(tex->buf, r300->cs,
+                tex->tex.microtile, tex->tex.macrotile[level],
+                tex->tex.stride_in_bytes[0]);
 
         tex->surface_level = level;
     }
@@ -646,12 +641,12 @@ static void r300_fb_set_tiling_flags(struct r300_context *r300,
     /* Set tiling flags for new surfaces. */
     for (i = 0; i < state->nr_cbufs; i++) {
         r300_tex_set_tiling_flags(r300,
-                                  r300_texture(state->cbufs[i]->texture),
+                                  r300_resource(state->cbufs[i]->texture),
                                   state->cbufs[i]->u.tex.level);
     }
     if (state->zsbuf) {
         r300_tex_set_tiling_flags(r300,
-                                  r300_texture(state->zsbuf->texture),
+                                  r300_resource(state->zsbuf->texture),
                                   state->zsbuf->u.tex.level);
     }
 }
@@ -660,7 +655,7 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index,
                                     const char *binding)
 {
     struct pipe_resource *tex = surf->texture;
-    struct r300_texture *rtex = r300_texture(tex);
+    struct r300_resource *rtex = r300_resource(tex);
 
     fprintf(stderr,
             "r300:   %s[%i] Dim: %ix%i, Firstlayer: %i, "
@@ -673,9 +668,9 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index,
             surf->u.tex.first_layer, surf->u.tex.last_layer, surf->u.tex.level,
             util_format_short_name(surf->format),
 
-            rtex->desc.macrotile[0] ? "YES" : " NO",
-            rtex->desc.microtile ? "YES" : " NO",
-            rtex->desc.stride_in_pixels[0],
+            rtex->tex.macrotile[0] ? "YES" : " NO",
+            rtex->tex.microtile ? "YES" : " NO",
+            rtex->tex.stride_in_pixels[0],
             tex->width0, tex->height0, tex->depth0,
             tex->last_level, util_format_short_name(tex->format));
 }
@@ -695,8 +690,7 @@ void r300_mark_fb_state_dirty(struct r300_context *r300,
     }
 
     if (change == R300_CHANGED_FB_STATE ||
-        change == R300_CHANGED_CBZB_FLAG ||
-        change == R300_CHANGED_ZCLEAR_FLAG) {
+        change == R300_CHANGED_HYPERZ_FLAG) {
         r300_mark_atom_dirty(r300, &r300->hyperz_state);
     }
 
@@ -720,8 +714,8 @@ void r300_mark_fb_state_dirty(struct r300_context *r300,
 }
 
 static void
-    r300_set_framebuffer_state(struct pipe_context* pipe,
-                               const struct pipe_framebuffer_state* state)
+r300_set_framebuffer_state(struct pipe_context* pipe,
+                           const struct pipe_framebuffer_state* state)
 {
     struct r300_context* r300 = r300_context(pipe);
     struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state;
@@ -729,7 +723,6 @@ static void
     boolean can_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ);
     unsigned max_width, max_height, i;
     uint32_t zbuffer_bpp = 0;
-    int blocksize;
 
     if (r300->screen->caps.is_r500) {
         max_width = max_height = 4096;
@@ -745,6 +738,32 @@ static void
         return;
     }
 
+    if (old_state->zsbuf && r300->zmask_in_use && !r300->zmask_locked) {
+        /* There is a zmask in use, what are we gonna do? */
+        if (state->zsbuf) {
+            if (!pipe_surface_equal(old_state->zsbuf, state->zsbuf)) {
+                /* Decompress the currently bound zbuffer before we bind another one. */
+                r300_decompress_zmask(r300);
+            }
+        } else {
+            /* We don't bind another zbuffer, so lock the current one. */
+            r300->zmask_locked = TRUE;
+            pipe_surface_reference(&r300->locked_zbuffer, old_state->zsbuf);
+        }
+    } else if (r300->zmask_locked && r300->locked_zbuffer) {
+        /* We have a locked zbuffer now, what are we gonna do? */
+        if (state->zsbuf) {
+            if (!pipe_surface_equal(r300->locked_zbuffer, state->zsbuf)) {
+                /* We are binding some other zbuffer, so decompress the locked one,
+                 * it gets unlocked automatically. */
+                r300_decompress_zmask_locked_unsafe(r300);
+            } else {
+                /* We are binding the locked zbuffer again, so unlock it. */
+                r300->zmask_locked = FALSE;
+            }
+        }
+    }
+
     /* If nr_cbufs is changed from zero to non-zero or vice versa... */
     if (!!old_state->nr_cbufs != !!state->nr_cbufs) {
         r300_mark_atom_dirty(r300, &r300->blend_state);
@@ -759,14 +778,14 @@ static void
 
     util_copy_framebuffer_state(r300->fb_state.state, state);
 
+    if (!r300->zmask_locked) {
+        pipe_surface_reference(&r300->locked_zbuffer, NULL);
+    }
+
     r300_mark_fb_state_dirty(r300, R300_CHANGED_FB_STATE);
-    r300->validate_buffers = TRUE;
 
-    r300->z_compression = false;
-    
     if (state->zsbuf) {
-        blocksize = util_format_get_blocksize(state->zsbuf->texture->format);
-        switch (blocksize) {
+        switch (util_format_get_blocksize(state->zsbuf->texture->format)) {
         case 2:
             zbuffer_bpp = 16;
             break;
@@ -774,30 +793,19 @@ static void
             zbuffer_bpp = 24;
             break;
         }
+
+        /* Setup Hyper-Z. */
         if (can_hyperz) {
             struct r300_surface *zs_surf = r300_surface(state->zsbuf);
-            struct r300_texture *tex;
-            int compress = r300->screen->caps.is_rv350 ? RV350_Z_COMPRESS_88 : R300_Z_COMPRESS_44;
+            struct r300_resource *tex = r300_resource(zs_surf->base.texture);
             int level = zs_surf->base.u.tex.level;
 
-            tex = r300_texture(zs_surf->base.texture);
-
             /* work out whether we can support hiz on this buffer */
             r300_hiz_alloc_block(r300, zs_surf);
-        
-            /* work out whether we can support zmask features on this buffer */
-            r300_zmask_alloc_block(r300, zs_surf, compress);
-
-            if (tex->zmask_mem[level]) {
-                /* compression causes hangs on 16-bit */
-                if (zbuffer_bpp == 24)
-                    r300->z_compression = compress;
-            }
+
             DBG(r300, DBG_HYPERZ,
-                "hyper-z features: hiz: %d @ %08x z-compression: %d z-fastfill: %d @ %08x\n", tex->hiz_mem[level] ? 1 : 0,
-                tex->hiz_mem[level] ? tex->hiz_mem[level]->ofs : 0xdeadbeef,
-                r300->z_compression, tex->zmask_mem[level] ? 1 : 0,
-                tex->zmask_mem[level] ? tex->zmask_mem[level]->ofs : 0xdeadbeef);
+                "hyper-z features: hiz: %d @ %08x\n", tex->hiz_mem[level] ? 1 : 0,
+                tex->hiz_mem[level] ? tex->hiz_mem[level]->ofs : 0xdeadbeef);
         }
 
         /* Polygon offset depends on the zbuffer bit depth. */
@@ -1300,7 +1308,7 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
     struct r300_context* r300 = r300_context(pipe);
     struct r300_textures_state* state =
         (struct r300_textures_state*)r300->textures_state.state;
-    struct r300_texture *texture;
+    struct r300_resource *texture;
     unsigned i, real_num_views = 0, view_index = 0;
     unsigned tex_units = r300->screen->caps.num_tex_units;
     boolean dirty_tex = FALSE;
@@ -1329,8 +1337,8 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
 
         /* Set the texrect factor in the fragment shader.
              * Needed for RECT and NPOT fallback. */
-        texture = r300_texture(views[i]->texture);
-        if (texture->desc.is_npot) {
+        texture = r300_resource(views[i]->texture);
+        if (texture->tex.is_npot) {
             r300_mark_atom_dirty(r300, &r300->fs_rc_constant_state);
         }
 
@@ -1350,7 +1358,6 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
     state->sampler_view_count = count;
 
     r300_mark_atom_dirty(r300, &r300->textures_state);
-    r300->validate_buffers = TRUE;
 
     if (dirty_tex) {
         r300_mark_atom_dirty(r300, &r300->texture_cache_inval);
@@ -1363,7 +1370,7 @@ r300_create_sampler_view(struct pipe_context *pipe,
                          const struct pipe_sampler_view *templ)
 {
     struct r300_sampler_view *view = CALLOC_STRUCT(r300_sampler_view);
-    struct r300_texture *tex = r300_texture(texture);
+    struct r300_resource *tex = r300_resource(texture);
     boolean is_r500 = r300_screen(pipe->screen)->caps.is_r500;
     boolean dxtc_swizzle = r300_screen(pipe->screen)->caps.dxtc_swizzle;
 
@@ -1465,10 +1472,7 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
                                     const struct pipe_vertex_buffer* buffers)
 {
     struct r300_context* r300 = r300_context(pipe);
-    const struct pipe_vertex_buffer *vbo;
-    unsigned i, max_index = (1 << 24) - 1;
-    boolean any_user_buffer = FALSE;
-    boolean any_nonuser_buffer = FALSE;
+    unsigned i;
     struct pipe_vertex_buffer dummy_vb = {0};
 
     /* There must be at least one vertex buffer set, otherwise it locks up. */
@@ -1478,90 +1482,20 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
         count = 1;
     }
 
-    if (count == r300->vertex_buffer_count &&
-        memcmp(r300->vertex_buffer, buffers,
-            sizeof(struct pipe_vertex_buffer) * count) == 0) {
-        return;
-    }
+    u_vbuf_mgr_set_vertex_buffers(r300->vbuf_mgr, count, buffers);
 
     if (r300->screen->caps.has_tcl) {
         /* HW TCL. */
-        r300->incompatible_vb_layout = FALSE;
-
-        /* Check if the strides and offsets are aligned to the size of DWORD. */
-        for (i = 0; i < count; i++) {
-            if (buffers[i].buffer) {
-                if (buffers[i].stride % 4 != 0 ||
-                    buffers[i].buffer_offset % 4 != 0) {
-                    r300->incompatible_vb_layout = TRUE;
-                    break;
-                }
-            }
-        }
-
         for (i = 0; i < count; i++) {
-            vbo = &buffers[i];
-
-            /* Skip NULL buffers */
-            if (!vbo->buffer) {
-                continue;
-            }
-
-            /* User buffers have no info about maximum index,
-             * we will have to compute it in draw_vbo. */
-            if (r300_is_user_buffer(vbo->buffer)) {
-                any_user_buffer = TRUE;
-                continue;
-            }
-            any_nonuser_buffer = TRUE;
-
-            /* The stride of zero means we will be fetching only the first
-             * vertex, so don't care about max_index. */
-            if (!vbo->stride)
-                continue;
-
-            /* Update the maximum index. */
-            {
-                unsigned vbo_max_index =
-                      (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride;
-                max_index = MIN2(max_index, vbo_max_index);
+            if (buffers[i].buffer &&
+               !r300_resource(buffers[i].buffer)->b.user_ptr) {
             }
         }
-
-        r300->any_user_vbs = any_user_buffer;
-        r300->vertex_buffer_max_index = max_index;
         r300->vertex_arrays_dirty = TRUE;
-        if (any_nonuser_buffer)
-            r300->validate_buffers = TRUE;
-        if (!any_user_buffer)
-            r300->upload_vb_validated = FALSE;
     } else {
         /* SW TCL. */
         draw_set_vertex_buffers(r300->draw, count, buffers);
     }
-
-    /* Common code. */
-    for (i = 0; i < count; i++) {
-        vbo = &buffers[i];
-
-        /* Reference our buffer. */
-        pipe_resource_reference(&r300->vertex_buffer[i].buffer, vbo->buffer);
-        if (vbo->buffer && r300_is_user_buffer(vbo->buffer)) {
-            pipe_resource_reference(&r300->valid_vertex_buffer[i], NULL);
-        } else {
-            pipe_resource_reference(&r300->valid_vertex_buffer[i], vbo->buffer);
-        }
-    }
-    for (; i < r300->vertex_buffer_count; i++) {
-        /* Dereference any old buffers. */
-        pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL);
-        pipe_resource_reference(&r300->valid_vertex_buffer[i], NULL);
-    }
-
-    memcpy(r300->vertex_buffer, buffers,
-           sizeof(struct pipe_vertex_buffer) * count);
-
-    r300->vertex_buffer_count = count;
 }
 
 static void r300_set_index_buffer(struct pipe_context* pipe,
@@ -1570,14 +1504,11 @@ static void r300_set_index_buffer(struct pipe_context* pipe,
     struct r300_context* r300 = r300_context(pipe);
 
     if (ib && ib->buffer) {
+        assert(ib->offset % ib->index_size == 0);
+
         pipe_resource_reference(&r300->index_buffer.buffer, ib->buffer);
         memcpy(&r300->index_buffer, ib, sizeof(r300->index_buffer));
-
-        if (r300->screen->caps.has_tcl &&
-            !r300_is_user_buffer(ib->buffer)) {
-            r300->validate_buffers = TRUE;
-            r300->upload_ib_validated = FALSE;
-        }
+        r300->index_buffer.offset /= r300->index_buffer.index_size;
     }
     else {
         pipe_resource_reference(&r300->index_buffer.buffer, NULL);
@@ -1607,7 +1538,7 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems)
      * so PSC should just route stuff based on the vertex elements,
      * and not on attrib information. */
     for (i = 0; i < velems->count; i++) {
-        format = velems->hw_format[i];
+        format = velems->velem[i].src_format;
 
         type = r300_translate_vertex_data_type(format);
         if (type == R300_INVALID_FORMAT) {
@@ -1639,16 +1570,13 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems)
     vstream->count = (i >> 1) + 1;
 }
 
-#define FORMAT_REPLACE(what, withwhat) \
-    case PIPE_FORMAT_##what: *format = PIPE_FORMAT_##withwhat; break
-
 static void* r300_create_vertex_elements_state(struct pipe_context* pipe,
                                                unsigned count,
                                                const struct pipe_vertex_element* attribs)
 {
+    struct r300_context *r300 = r300_context(pipe);
     struct r300_vertex_element_state *velems;
     unsigned i;
-    enum pipe_format *format;
     struct pipe_vertex_element dummy_attrib = {0};
 
     /* R300 Programmable Stream Control (PSC) doesn't support 0 vertex elements. */
@@ -1660,77 +1588,26 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe,
 
     assert(count <= PIPE_MAX_ATTRIBS);
     velems = CALLOC_STRUCT(r300_vertex_element_state);
-    if (velems != NULL) {
-        velems->count = count;
-        memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count);
-
-        if (r300_screen(pipe->screen)->caps.has_tcl) {
-            /* Set the best hw format in case the original format is not
-             * supported by hw. */
-            for (i = 0; i < count; i++) {
-                velems->hw_format[i] = velems->velem[i].src_format;
-                format = &velems->hw_format[i];
-
-                /* This is basically the list of unsupported formats.
-                 * For now we don't care about the alignment, that's going to
-                 * be sorted out after the PSC setup. */
-                switch (*format) {
-                    FORMAT_REPLACE(R64_FLOAT,           R32_FLOAT);
-                    FORMAT_REPLACE(R64G64_FLOAT,        R32G32_FLOAT);
-                    FORMAT_REPLACE(R64G64B64_FLOAT,     R32G32B32_FLOAT);
-                    FORMAT_REPLACE(R64G64B64A64_FLOAT,  R32G32B32A32_FLOAT);
-
-                    FORMAT_REPLACE(R32_UNORM,           R32_FLOAT);
-                    FORMAT_REPLACE(R32G32_UNORM,        R32G32_FLOAT);
-                    FORMAT_REPLACE(R32G32B32_UNORM,     R32G32B32_FLOAT);
-                    FORMAT_REPLACE(R32G32B32A32_UNORM,  R32G32B32A32_FLOAT);
-
-                    FORMAT_REPLACE(R32_USCALED,         R32_FLOAT);
-                    FORMAT_REPLACE(R32G32_USCALED,      R32G32_FLOAT);
-                    FORMAT_REPLACE(R32G32B32_USCALED,   R32G32B32_FLOAT);
-                    FORMAT_REPLACE(R32G32B32A32_USCALED,R32G32B32A32_FLOAT);
-
-                    FORMAT_REPLACE(R32_SNORM,           R32_FLOAT);
-                    FORMAT_REPLACE(R32G32_SNORM,        R32G32_FLOAT);
-                    FORMAT_REPLACE(R32G32B32_SNORM,     R32G32B32_FLOAT);
-                    FORMAT_REPLACE(R32G32B32A32_SNORM,  R32G32B32A32_FLOAT);
-
-                    FORMAT_REPLACE(R32_SSCALED,         R32_FLOAT);
-                    FORMAT_REPLACE(R32G32_SSCALED,      R32G32_FLOAT);
-                    FORMAT_REPLACE(R32G32B32_SSCALED,   R32G32B32_FLOAT);
-                    FORMAT_REPLACE(R32G32B32A32_SSCALED,R32G32B32A32_FLOAT);
-
-                    FORMAT_REPLACE(R32_FIXED,           R32_FLOAT);
-                    FORMAT_REPLACE(R32G32_FIXED,        R32G32_FLOAT);
-                    FORMAT_REPLACE(R32G32B32_FIXED,     R32G32B32_FLOAT);
-                    FORMAT_REPLACE(R32G32B32A32_FIXED,  R32G32B32A32_FLOAT);
-
-                    default:;
-                }
+    if (!velems)
+        return NULL;
 
-                velems->incompatible_layout =
-                        velems->incompatible_layout ||
-                        velems->velem[i].src_format != velems->hw_format[i] ||
-                        velems->velem[i].src_offset % 4 != 0;
-            }
+    velems->count = count;
+    velems->vmgr_elements =
+        u_vbuf_mgr_create_vertex_elements(r300->vbuf_mgr, count, attribs,
+                                          velems->velem);
 
-            /* Now setup PSC.
-             * The unused components will be replaced by (..., 0, 1). */
-            r300_vertex_psc(velems);
-
-            /* Align the formats to the size of DWORD.
-             * We only care about the blocksizes of the formats since
-             * swizzles are already set up.
-             * Also compute the vertex size. */
-            for (i = 0; i < count; i++) {
-                /* This is OK because we check for aligned strides too
-                 * elsewhere. */
-                velems->hw_format_size[i] =
-                    align(util_format_get_blocksize(velems->hw_format[i]), 4);
-                velems->vertex_size_dwords += velems->hw_format_size[i] / 4;
-            }
+    if (r300_screen(pipe->screen)->caps.has_tcl) {
+        /* Setup PSC.
+         * The unused components will be replaced by (..., 0, 1). */
+        r300_vertex_psc(velems);
+
+        for (i = 0; i < count; i++) {
+            velems->format_size[i] =
+                align(util_format_get_blocksize(velems->velem[i].src_format), 4);
+            velems->vertex_size_dwords += velems->format_size[i] / 4;
         }
     }
+
     return velems;
 }
 
@@ -1746,6 +1623,8 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe,
 
     r300->velems = velems;
 
+    u_vbuf_mgr_bind_vertex_elements(r300->vbuf_mgr, state, velems->vmgr_elements);
+
     if (r300->draw) {
         draw_set_vertex_elements(r300->draw, velems->count, velems->velem);
         return;
@@ -1758,7 +1637,11 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe,
 
 static void r300_delete_vertex_elements_state(struct pipe_context *pipe, void *state)
 {
-   FREE(state);
+    struct r300_context *r300 = r300_context(pipe);
+    struct r300_vertex_element_state *velems = state;
+
+    u_vbuf_mgr_destroy_vertex_elements(r300->vbuf_mgr, velems->vmgr_elements);
+    FREE(state);
 }
 
 static void* r300_create_vs_state(struct pipe_context* pipe,
@@ -1845,7 +1728,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
 {
     struct r300_context* r300 = r300_context(pipe);
     struct r300_constant_buffer *cbuf;
-    struct r300_buffer *rbuf = r300_buffer(buf);
+    struct r300_resource *rbuf = r300_resource(buf);
     uint32_t *mapped;
 
     switch (shader) {
@@ -1862,8 +1745,8 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
     if (buf == NULL || buf->width0 == 0)
         return;
 
-    if (rbuf->user_buffer)
-        mapped = (uint32_t*)rbuf->user_buffer;
+    if (rbuf->b.user_ptr)
+        mapped = (uint32_t*)rbuf->b.user_ptr;
     else if (rbuf->constant_buffer)
         mapped = (uint32_t*)rbuf->constant_buffer;
     else
@@ -1947,6 +1830,7 @@ void r300_init_state_functions(struct r300_context* r300)
 
     r300->context.set_vertex_buffers = r300_set_vertex_buffers;
     r300->context.set_index_buffer = r300_set_index_buffer;
+    r300->context.redefine_user_buffer = u_default_redefine_user_buffer;
 
     r300->context.create_vertex_elements_state = r300_create_vertex_elements_state;
     r300->context.bind_vertex_elements_state = r300_bind_vertex_elements_state;
index 95be7849f8f976380a366d5e105e5b99519a9288..003fe9a58cd3db889ab97a4c6ad5ceef12cc974c 100644 (file)
@@ -489,7 +489,8 @@ static void r300_update_rs_block(struct r300_context *r300)
     for (; i < ATTR_GENERIC_COUNT; i++) {
         if (fs_inputs->generic[i] != ATTR_UNUSED) {
             fprintf(stderr, "r300: ERROR: FS input generic %i unassigned, "
-                    "not enough hardware slots.\n", i);
+                    "not enough hardware slots (it's not a bug, do not "
+                    "report it).\n", i);
         }
     }
 
@@ -524,7 +525,8 @@ static void r300_update_rs_block(struct r300_context *r300)
                 DBG(r300, DBG_RS, "r300: FS input fog unassigned.\n");
             } else {
                 fprintf(stderr, "r300: ERROR: FS input fog unassigned, "
-                        "not enough hardware slots.\n");
+                        "not enough hardware slots. (it's not a bug, "
+                        "do not report it)\n");
             }
         }
     }
@@ -551,7 +553,8 @@ static void r300_update_rs_block(struct r300_context *r300)
     } else {
         if (fs_inputs->wpos != ATTR_UNUSED && tex_count >= 8) {
             fprintf(stderr, "r300: ERROR: FS input WPOS unassigned, "
-                    "not enough hardware slots.\n");
+                    "not enough hardware slots. (it's not a bug, do not "
+                    "report it)\n");
         }
     }
 
@@ -674,7 +677,20 @@ static uint32_t r300_get_border_color(enum pipe_format format,
         case 16:
             if (desc->nr_channels <= 2) {
                 border_swizzled[0] = border_swizzled[2];
-                util_pack_color(border_swizzled, PIPE_FORMAT_R16G16_UNORM, &uc);
+                if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) {
+                    util_pack_color(border_swizzled, PIPE_FORMAT_R16G16_FLOAT, &uc);
+                } else {
+                    util_pack_color(border_swizzled, PIPE_FORMAT_R16G16_UNORM, &uc);
+                }
+            } else {
+                util_pack_color(border_swizzled, PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
+            }
+            break;
+
+        case 32:
+            if (desc->nr_channels == 1) {
+                border_swizzled[0] = border_swizzled[2];
+                util_pack_color(border_swizzled, PIPE_FORMAT_R32_FLOAT, &uc);
             } else {
                 util_pack_color(border_swizzled, PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
             }
@@ -684,6 +700,25 @@ static uint32_t r300_get_border_color(enum pipe_format format,
     return uc.ui;
 }
 
+static boolean util_format_is_float(enum pipe_format format)
+{
+    const struct util_format_description *desc = util_format_description(format);
+    unsigned i;
+
+    if (!format)
+       return FALSE;
+
+    /* Find the first non-void channel. */
+    for (i = 0; i < 4; i++)
+        if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID)
+            break;
+
+    if (i == 4)
+        return FALSE;
+
+    return desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT ? TRUE : FALSE;
+}
+
 static void r300_merge_textures_and_samplers(struct r300_context* r300)
 {
     struct r300_textures_state *state =
@@ -691,7 +726,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
     struct r300_texture_sampler_state *texstate;
     struct r300_sampler_state *sampler;
     struct r300_sampler_view *view;
-    struct r300_texture *tex;
+    struct r300_resource *tex;
     unsigned min_level, max_level, i, j, size;
     unsigned count = MIN2(state->sampler_view_count,
                           state->sampler_state_count);
@@ -709,7 +744,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
             state->tx_enable |= 1 << i;
 
             view = state->sampler_views[i];
-            tex = r300_texture(view->base.texture);
+            tex = r300_resource(view->base.texture);
             sampler = state->sampler_states[i];
 
             texstate = &state->regs[i];
@@ -725,32 +760,37 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
 
             /* determine min/max levels */
             max_level = MIN3(sampler->max_lod + view->base.u.tex.first_level,
-                             tex->desc.b.b.last_level, view->base.u.tex.last_level);
+                             tex->b.b.b.last_level, view->base.u.tex.last_level);
             min_level = MIN2(sampler->min_lod + view->base.u.tex.first_level,
                              max_level);
 
-            if (tex->desc.is_npot && min_level > 0) {
+            if (tex->tex.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,
+                 * the i-th mipmap level as the zero level. */
+                unsigned offset = tex->tex_offset +
+                                  tex->tex.offset_in_bytes[min_level];
+
+                r300_texture_setup_format_state(r300->screen, tex,
                                                 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);
+                texstate->format.tile_config |= offset & 0xffffffe0;
+                assert((offset & 0x1f) == 0);
+            } else {
+                texstate->format.tile_config |= tex->tex_offset & 0xffffffe0;
+                assert((tex->tex_offset & 0x1f) == 0);
             }
 
             /* Assign a texture cache region. */
             texstate->format.format1 |= view->texcache_region;
 
             /* Depth textures are kinda special. */
-            if (util_format_is_depth_or_stencil(tex->desc.b.b.format)) {
+            if (util_format_is_depth_or_stencil(tex->b.b.b.format)) {
                 unsigned char depth_swizzle[4];
 
                 if (!r300->screen->caps.is_r500 &&
-                    util_format_get_blocksizebits(tex->desc.b.b.format) == 32) {
+                    util_format_get_blocksizebits(tex->b.b.b.format) == 32) {
                     /* X24x8 is sampled as Y16X16 on r3xx-r4xx.
                      * The depth here is at the Y component. */
                     for (j = 0; j < 4; j++)
@@ -775,17 +815,17 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
             }
 
             if (r300->screen->caps.dxtc_swizzle &&
-                util_format_is_compressed(tex->desc.b.b.format)) {
+                util_format_is_compressed(tex->b.b.b.format)) {
                 texstate->filter1 |= R400_DXTC_SWIZZLE_ENABLE;
             }
 
             /* to emulate 1D textures through 2D ones correctly */
-            if (tex->desc.b.b.target == PIPE_TEXTURE_1D) {
+            if (tex->b.b.b.target == PIPE_TEXTURE_1D) {
                 texstate->filter0 &= ~R300_TX_WRAP_T_MASK;
                 texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE);
             }
 
-            if (tex->desc.is_npot) {
+            if (tex->tex.is_npot) {
                 /* NPOT textures don't support mip filter, unfortunately.
                  * This prevents incorrect rendering. */
                 texstate->filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK;
@@ -814,6 +854,32 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
                 texstate->filter0 |= R300_TX_MAX_MIP_LEVEL(min_level);
             }
 
+            /* Float textures only support nearest and mip-nearest filtering. */
+            if (util_format_is_float(tex->b.b.b.format)) {
+                /* No MAG linear filtering. */
+                if ((texstate->filter0 & R300_TX_MAG_FILTER_MASK) ==
+                    R300_TX_MAG_FILTER_LINEAR) {
+                    texstate->filter0 &= ~R300_TX_MAG_FILTER_MASK;
+                    texstate->filter0 |= R300_TX_MAG_FILTER_NEAREST;
+                }
+                /* No MIN linear filtering. */
+                if ((texstate->filter0 & R300_TX_MIN_FILTER_MASK) ==
+                    R300_TX_MIN_FILTER_LINEAR) {
+                    texstate->filter0 &= ~R300_TX_MIN_FILTER_MASK;
+                    texstate->filter0 |= R300_TX_MIN_FILTER_NEAREST;
+                }
+                /* No mipmap linear filtering. */
+                if ((texstate->filter0 & R300_TX_MIN_FILTER_MIP_MASK) ==
+                    R300_TX_MIN_FILTER_MIP_LINEAR) {
+                    texstate->filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK;
+                    texstate->filter0 |= R300_TX_MIN_FILTER_MIP_NEAREST;
+                }
+                /* No anisotropic filtering. */
+                texstate->filter0 &= ~R300_TX_MAX_ANISO_MASK;
+                texstate->filter1 &= ~R500_TX_MAX_ANISO_MASK;
+                texstate->filter1 &= ~R500_TX_ANISO_HIGH_QUALITY;
+            }
+
             texstate->filter0 |= i << 28;
 
             size += 16;
@@ -862,11 +928,35 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
     }
 }
 
-void r300_update_derived_state(struct r300_context* r300)
+static void r300_decompress_depth_textures(struct r300_context *r300)
 {
-    r300_flush_depth_textures(r300);
+    struct r300_textures_state *state =
+        (struct r300_textures_state*)r300->textures_state.state;
+    struct pipe_resource *tex;
+    unsigned count = MIN2(state->sampler_view_count,
+                          state->sampler_state_count);
+    unsigned i;
+
+    if (!r300->zmask_locked || !r300->locked_zbuffer) {
+        return;
+    }
 
+    for (i = 0; i < count; i++) {
+        if (state->sampler_views[i] && state->sampler_states[i]) {
+            tex = state->sampler_views[i]->base.texture;
+
+            if (tex == r300->locked_zbuffer->texture) {
+                r300_decompress_zmask_locked(r300);
+                return;
+            }
+        }
+    }
+}
+
+void r300_update_derived_state(struct r300_context* r300)
+{
     if (r300->textures_state.dirty) {
+        r300_decompress_depth_textures(r300);
         r300_merge_textures_and_samplers(r300);
     }
 
index 7e501221b1f525040d421a8095d36c4b5dda5978..06da04c7ad7ea04c2c63785395d6975dfe26903c 100644 (file)
 #define R300_STATE_INLINES_H
 
 #include "draw/draw_vertex.h"
-
 #include "pipe/p_format.h"
-
 #include "util/u_format.h"
-
 #include "r300_reg.h"
-
 #include <stdio.h>
 
 /* Some maths. These should probably find their way to u_math, if needed. */
@@ -341,24 +337,6 @@ static INLINE uint32_t r500_anisotropy(unsigned max_aniso)
            R500_TX_ANISO_HIGH_QUALITY;
 }
 
-/* Non-CSO state. (For now.) */
-
-static INLINE uint32_t r300_translate_gb_pipes(int pipe_count)
-{
-    switch (pipe_count) {
-        case 1:
-            return R300_GB_TILE_PIPE_COUNT_RV300;
-        case 2:
-            return R300_GB_TILE_PIPE_COUNT_R300;
-        case 3:
-            return R300_GB_TILE_PIPE_COUNT_R420_3P;
-        case 4:
-            return R300_GB_TILE_PIPE_COUNT_R420;
-    }
-    return 0;
-}
-
-
 /* Translate pipe_formats into PSC vertex types. */
 static INLINE uint16_t
 r300_translate_vertex_data_type(enum pipe_format format) {
index 6fdc504ed5401b8f48176f962b6a95cb351f79c5..354144cac79948673b4a0221f0062c8aeadc2e42 100644 (file)
@@ -370,14 +370,18 @@ static uint32_t r300_translate_colorformat(enum pipe_format format)
     switch (format) {
         /* 8-bit buffers. */
         case PIPE_FORMAT_A8_UNORM:
+        /*case PIPE_FORMAT_A8_SNORM:*/
         case PIPE_FORMAT_I8_UNORM:
+        /*case PIPE_FORMAT_I8_SNORM:*/
         case PIPE_FORMAT_L8_UNORM:
+        /*case PIPE_FORMAT_L8_SNORM:*/
         case PIPE_FORMAT_R8_UNORM:
         case PIPE_FORMAT_R8_SNORM:
             return R300_COLOR_FORMAT_I8;
 
         /* 16-bit buffers. */
         case PIPE_FORMAT_L8A8_UNORM:
+        /*case PIPE_FORMAT_L8A8_SNORM:*/
         case PIPE_FORMAT_R8G8_UNORM:
         case PIPE_FORMAT_R8G8_SNORM:
             return R300_COLOR_FORMAT_UV88;
@@ -395,13 +399,21 @@ static uint32_t r300_translate_colorformat(enum pipe_format format)
 
         /* 32-bit buffers. */
         case PIPE_FORMAT_B8G8R8A8_UNORM:
+        /*case PIPE_FORMAT_B8G8R8A8_SNORM:*/
         case PIPE_FORMAT_B8G8R8X8_UNORM:
+        /*case PIPE_FORMAT_B8G8R8X8_SNORM:*/
         case PIPE_FORMAT_A8R8G8B8_UNORM:
+        /*case PIPE_FORMAT_A8R8G8B8_SNORM:*/
         case PIPE_FORMAT_X8R8G8B8_UNORM:
+        /*case PIPE_FORMAT_X8R8G8B8_SNORM:*/
         case PIPE_FORMAT_A8B8G8R8_UNORM:
+        /*case PIPE_FORMAT_A8B8G8R8_SNORM:*/
+        case PIPE_FORMAT_R8G8B8A8_UNORM:
         case PIPE_FORMAT_R8G8B8A8_SNORM:
         case PIPE_FORMAT_X8B8G8R8_UNORM:
+        /*case PIPE_FORMAT_X8B8G8R8_SNORM:*/
         case PIPE_FORMAT_R8G8B8X8_UNORM:
+        /*case PIPE_FORMAT_R8G8B8X8_SNORM:*/
         case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
             return R300_COLOR_FORMAT_ARGB8888;
 
@@ -506,9 +518,12 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format)
         /* 8-bit outputs, one channel.
          * COLORFORMAT_I8 stores the C2 component. */
         case PIPE_FORMAT_A8_UNORM:
+        /*case PIPE_FORMAT_A8_SNORM:*/
             return modifier | R300_C2_SEL_A;
         case PIPE_FORMAT_I8_UNORM:
+        /*case PIPE_FORMAT_I8_SNORM:*/
         case PIPE_FORMAT_L8_UNORM:
+        /*case PIPE_FORMAT_L8_SNORM:*/
         case PIPE_FORMAT_R8_UNORM:
         case PIPE_FORMAT_R8_SNORM:
             return modifier | R300_C2_SEL_R;
@@ -516,6 +531,7 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format)
         /* 16-bit outputs, two channels.
          * COLORFORMAT_UV88 stores C2 and C0. */
         case PIPE_FORMAT_L8A8_UNORM:
+        /*case PIPE_FORMAT_L8A8_SNORM:*/
             return modifier | R300_C0_SEL_A | R300_C2_SEL_R;
         case PIPE_FORMAT_R8G8_UNORM:
         case PIPE_FORMAT_R8G8_SNORM:
@@ -528,7 +544,9 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format)
         case PIPE_FORMAT_B4G4R4A4_UNORM:
         case PIPE_FORMAT_B4G4R4X4_UNORM:
         case PIPE_FORMAT_B8G8R8A8_UNORM:
+        /*case PIPE_FORMAT_B8G8R8A8_SNORM:*/
         case PIPE_FORMAT_B8G8R8X8_UNORM:
+        /*case PIPE_FORMAT_B8G8R8X8_SNORM:*/
         case PIPE_FORMAT_B10G10R10A2_UNORM:
             return modifier |
                 R300_C0_SEL_B | R300_C1_SEL_G |
@@ -536,20 +554,26 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format)
 
         /* ARGB outputs. */
         case PIPE_FORMAT_A8R8G8B8_UNORM:
+        /*case PIPE_FORMAT_A8R8G8B8_SNORM:*/
         case PIPE_FORMAT_X8R8G8B8_UNORM:
+        /*case PIPE_FORMAT_X8R8G8B8_SNORM:*/
             return modifier |
                 R300_C0_SEL_A | R300_C1_SEL_R |
                 R300_C2_SEL_G | R300_C3_SEL_B;
 
         /* ABGR outputs. */
         case PIPE_FORMAT_A8B8G8R8_UNORM:
+        /*case PIPE_FORMAT_A8B8G8R8_SNORM:*/
         case PIPE_FORMAT_X8B8G8R8_UNORM:
+        /*case PIPE_FORMAT_X8B8G8R8_SNORM:*/
             return modifier |
                 R300_C0_SEL_A | R300_C1_SEL_B |
                 R300_C2_SEL_G | R300_C3_SEL_R;
 
         /* RGBA outputs. */
         case PIPE_FORMAT_R8G8B8X8_UNORM:
+        /*case PIPE_FORMAT_R8G8B8X8_SNORM:*/
+        case PIPE_FORMAT_R8G8B8A8_UNORM:
         case PIPE_FORMAT_R8G8B8A8_SNORM:
         case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
         case PIPE_FORMAT_R10G10B10A2_UNORM:
@@ -585,11 +609,12 @@ 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,
+                                     struct r300_resource *tex,
                                      unsigned level,
                                      struct r300_texture_format_state *out)
 {
-    struct pipe_resource *pt = &desc->b.b;
+    struct pipe_resource *pt = &tex->b.b.b;
+    struct r300_texture_desc *desc = &tex->tex;
     boolean is_r500 = screen->caps.is_r500;
 
     /* Mask out all the fields we change. */
@@ -632,163 +657,152 @@ void r300_texture_setup_format_state(struct r300_screen *screen,
                        R300_TXO_MICRO_TILE(desc->microtile);
 }
 
-static void r300_texture_setup_fb_state(struct r300_screen* screen,
-                                        struct r300_texture* tex)
+static void r300_texture_setup_fb_state(struct r300_surface *surf)
 {
-    unsigned i;
+    struct r300_resource *tex = r300_resource(surf->base.texture);
+    unsigned level = surf->base.u.tex.level;
 
     /* Set framebuffer state. */
-    if (util_format_is_depth_or_stencil(tex->desc.b.b.format)) {
-        for (i = 0; i <= tex->desc.b.b.last_level; i++) {
-            tex->fb_state.pitch[i] =
-                tex->desc.stride_in_pixels[i] |
-                R300_DEPTHMACROTILE(tex->desc.macrotile[i]) |
-                R300_DEPTHMICROTILE(tex->desc.microtile);
-        }
-        tex->fb_state.format = r300_translate_zsformat(tex->desc.b.b.format);
+    if (util_format_is_depth_or_stencil(surf->base.format)) {
+        surf->pitch =
+                tex->tex.stride_in_pixels[level] |
+                R300_DEPTHMACROTILE(tex->tex.macrotile[level]) |
+                R300_DEPTHMICROTILE(tex->tex.microtile);
+        surf->format = r300_translate_zsformat(surf->base.format);
     } else {
-        for (i = 0; i <= tex->desc.b.b.last_level; i++) {
-            tex->fb_state.pitch[i] =
-                tex->desc.stride_in_pixels[i] |
-                r300_translate_colorformat(tex->desc.b.b.format) |
-                R300_COLOR_TILE(tex->desc.macrotile[i]) |
-                R300_COLOR_MICROTILE(tex->desc.microtile);
-        }
-        tex->fb_state.format = r300_translate_out_fmt(tex->desc.b.b.format);
+        surf->pitch =
+                tex->tex.stride_in_pixels[level] |
+                r300_translate_colorformat(surf->base.format) |
+                R300_COLOR_TILE(tex->tex.macrotile[level]) |
+                R300_COLOR_MICROTILE(tex->tex.microtile);
+        surf->format = r300_translate_out_fmt(surf->base.format);
     }
 }
 
-void r300_texture_reinterpret_format(struct pipe_screen *screen,
+boolean r300_resource_set_properties(struct pipe_screen *screen,
                                      struct pipe_resource *tex,
-                                     enum pipe_format new_format)
+                                     unsigned offset,
+                                     const struct pipe_resource *new_properties)
 {
-    struct r300_screen *r300screen = r300_screen(screen);
+    struct r300_screen *rscreen = r300_screen(screen);
+    struct r300_resource *res = r300_resource(tex);
 
-    SCREEN_DBG(r300screen, DBG_TEX,
-        "r300: texture_reinterpret_format: %s -> %s\n",
+    SCREEN_DBG(rscreen, DBG_TEX,
+        "r300: texture_set_properties: %s -> %s\n",
         util_format_short_name(tex->format),
-        util_format_short_name(new_format));
-
-    tex->format = new_format;
+        util_format_short_name(new_properties->format));
 
-    r300_texture_setup_fb_state(r300_screen(screen), r300_texture(tex));
-}
-
-static unsigned r300_texture_is_referenced(struct pipe_context *context,
-                                           struct pipe_resource *texture,
-                                           unsigned level, int layer)
-{
-    struct r300_context *r300 = r300_context(context);
-    struct r300_texture *rtex = (struct r300_texture *)texture;
-
-    if (r300->rws->cs_is_buffer_referenced(r300->cs,
-                                           rtex->cs_buffer, R300_REF_CS))
-        return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+    if (!r300_texture_desc_init(rscreen, res, new_properties)) {
+        fprintf(stderr, "r300: ERROR: Cannot set texture properties.\n");
+        return FALSE;
+    }
+    res->tex_offset = offset;
+    r300_texture_setup_format_state(rscreen, res, 0, &res->tx_format);
 
-    return PIPE_UNREFERENCED;
+    return TRUE;
 }
 
 static void r300_texture_destroy(struct pipe_screen *screen,
                                  struct pipe_resource* texture)
 {
-    struct r300_texture* tex = (struct r300_texture*)texture;
-    struct r300_winsys_screen *rws = (struct r300_winsys_screen *)texture->screen->winsys;
+    struct r300_resource* tex = (struct r300_resource*)texture;
     int i;
 
-    rws->buffer_reference(rws, &tex->buffer, NULL);
+    r300_winsys_bo_reference(&tex->buf, NULL);
     for (i = 0; i < R300_MAX_TEXTURE_LEVELS; i++) {
         if (tex->hiz_mem[i])
             u_mmFreeMem(tex->hiz_mem[i]);
-        if (tex->zmask_mem[i])
-            u_mmFreeMem(tex->zmask_mem[i]);
     }
 
     FREE(tex);
 }
 
-static boolean r300_texture_get_handle(struct pipe_screen* screen,
-                                       struct pipe_resource *texture,
-                                       struct winsys_handle *whandle)
+boolean r300_resource_get_handle(struct pipe_screen* screen,
+                                 struct pipe_resource *texture,
+                                 struct winsys_handle *whandle)
 {
     struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys;
-    struct r300_texture* tex = (struct r300_texture*)texture;
+    struct r300_resource* tex = (struct r300_resource*)texture;
 
     if (!tex) {
         return FALSE;
     }
 
-    return rws->buffer_get_handle(rws, tex->buffer,
-                                  tex->desc.stride_in_bytes[0], whandle);
+    return rws->buffer_get_handle(tex->buf,
+                                  tex->tex.stride_in_bytes[0], whandle);
 }
 
-struct u_resource_vtbl r300_texture_vtbl =
+static const struct u_resource_vtbl r300_texture_vtbl =
 {
-   r300_texture_get_handle,          /* get_handle */
-   r300_texture_destroy,             /* resource_destroy */
-   r300_texture_is_referenced,       /* is_resource_referenced */
-   r300_texture_get_transfer,        /* get_transfer */
-   r300_texture_transfer_destroy,     /* transfer_destroy */
-   r300_texture_transfer_map,        /* transfer_map */
-   u_default_transfer_flush_region,   /* transfer_flush_region */
-   r300_texture_transfer_unmap,              /* transfer_unmap */
-   u_default_transfer_inline_write    /* transfer_inline_write */
+    NULL,                           /* get_handle */
+    r300_texture_destroy,           /* resource_destroy */
+    NULL,                           /* is_resource_referenced */
+    r300_texture_get_transfer,      /* get_transfer */
+    r300_texture_transfer_destroy,  /* transfer_destroy */
+    r300_texture_transfer_map,      /* transfer_map */
+    NULL,                           /* transfer_flush_region */
+    r300_texture_transfer_unmap,    /* transfer_unmap */
+    u_default_transfer_inline_write /* transfer_inline_write */
 };
 
 /* The common texture constructor. */
-static struct r300_texture*
+static struct r300_resource*
 r300_texture_create_object(struct r300_screen *rscreen,
                            const struct pipe_resource *base,
                            enum r300_buffer_tiling microtile,
                            enum r300_buffer_tiling macrotile,
                            unsigned stride_in_bytes_override,
                            unsigned max_buffer_size,
-                           struct r300_winsys_buffer *buffer)
+                           struct r300_winsys_bo *buffer)
 {
     struct r300_winsys_screen *rws = rscreen->rws;
-    struct r300_texture *tex = CALLOC_STRUCT(r300_texture);
+    struct r300_resource *tex = CALLOC_STRUCT(r300_resource);
     if (!tex) {
         if (buffer)
-            rws->buffer_reference(rws, &buffer, NULL);
+            r300_winsys_bo_reference(&buffer, NULL);
         return NULL;
     }
 
-    /* Initialize the descriptor. */
-    if (!r300_texture_desc_init(rscreen, &tex->desc, base,
-                                microtile, macrotile,
-                                stride_in_bytes_override,
-                                max_buffer_size)) {
+    pipe_reference_init(&tex->b.b.b.reference, 1);
+    tex->b.b.b.screen = &rscreen->screen;
+    tex->b.b.b.usage = base->usage;
+    tex->b.b.b.bind = base->bind;
+    tex->b.b.b.flags = base->flags;
+    tex->b.b.vtbl = &r300_texture_vtbl;
+    tex->tex.microtile = microtile;
+    tex->tex.macrotile[0] = macrotile;
+    tex->tex.stride_in_bytes_override = stride_in_bytes_override;
+    tex->domain = base->flags & R300_RESOURCE_FLAG_TRANSFER ?
+                  R300_DOMAIN_GTT :
+                  R300_DOMAIN_VRAM | R300_DOMAIN_GTT;
+    tex->buf_size = max_buffer_size;
+
+    if (!r300_resource_set_properties(&rscreen->screen, &tex->b.b.b, 0, base)) {
         if (buffer)
-            rws->buffer_reference(rws, &buffer, NULL);
+            r300_winsys_bo_reference(&buffer, NULL);
         FREE(tex);
         return NULL;
     }
-    /* Initialize the hardware state. */
-    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;
-    pipe_reference_init(&tex->desc.b.b.reference, 1);
-    tex->domain = base->flags & R300_RESOURCE_FLAG_TRANSFER ?
-                  R300_DOMAIN_GTT :
-                  R300_DOMAIN_VRAM | R300_DOMAIN_GTT;
-    tex->buffer = buffer;
 
     /* Create the backing buffer if needed. */
-    if (!tex->buffer) {
-        tex->buffer = rws->buffer_create(rws, tex->desc.size_in_bytes, 2048,
+    if (!buffer) {
+        tex->buf_size = tex->tex.size_in_bytes;
+        tex->buf = rws->buffer_create(rws, tex->tex.size_in_bytes, 2048,
                                          base->bind, base->usage, tex->domain);
 
-        if (!tex->buffer) {
+        if (!tex->buf) {
             FREE(tex);
             return NULL;
         }
+    } else {
+        tex->buf = buffer;
     }
 
-    tex->cs_buffer = rws->buffer_get_cs_handle(rws, tex->buffer);
+    tex->cs_buf = rws->buffer_get_cs_handle(tex->buf);
 
-    rws->buffer_set_tiling(rws, tex->buffer,
-            tex->desc.microtile, tex->desc.macrotile[0],
-            tex->desc.stride_in_bytes[0]);
+    rws->buffer_set_tiling(tex->buf, NULL,
+            tex->tex.microtile, tex->tex.macrotile[0],
+            tex->tex.stride_in_bytes[0]);
 
     return tex;
 }
@@ -820,7 +834,7 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen,
 {
     struct r300_winsys_screen *rws = (struct r300_winsys_screen*)screen->winsys;
     struct r300_screen *rscreen = r300_screen(screen);
-    struct r300_winsys_buffer *buffer;
+    struct r300_winsys_bo *buffer;
     enum r300_buffer_tiling microtile, macrotile;
     unsigned stride, size;
 
@@ -836,7 +850,7 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen,
     if (!buffer)
         return NULL;
 
-    rws->buffer_get_tiling(rws, buffer, &microtile, &macrotile);
+    rws->buffer_get_tiling(buffer, &microtile, &macrotile);
 
     /* Enforce a microtiled zbuffer. */
     if (util_format_is_depth_or_stencil(base->format) &&
@@ -847,7 +861,7 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen,
                 break;
 
             case 2:
-                if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT))
+                if (rws->get_value(rws, R300_VID_DRM_2_1_0))
                     microtile = R300_BUFFER_SQUARETILED;
                 break;
         }
@@ -864,7 +878,7 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx,
                                          struct pipe_resource* texture,
                                          const struct pipe_surface *surf_tmpl)
 {
-    struct r300_texture* tex = r300_texture(texture);
+    struct r300_resource* tex = r300_resource(texture);
     struct r300_surface* surface = CALLOC_STRUCT(r300_surface);
     unsigned level = surf_tmpl->u.tex.level;
 
@@ -884,28 +898,27 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx,
         surface->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
         surface->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
 
-        surface->buffer = tex->buffer;
-        surface->cs_buffer = tex->cs_buffer;
+        surface->buf = tex->buf;
+        surface->cs_buf = tex->cs_buf;
 
         /* Prefer VRAM if there are multiple domains to choose from. */
         surface->domain = tex->domain;
         if (surface->domain & R300_DOMAIN_VRAM)
             surface->domain &= ~R300_DOMAIN_GTT;
 
-        surface->offset = r300_texture_get_offset(&tex->desc, level,
+        surface->offset = r300_texture_get_offset(tex, level,
                                                   surf_tmpl->u.tex.first_layer);
-        surface->pitch = tex->fb_state.pitch[level];
-        surface->format = tex->fb_state.format;
+        r300_texture_setup_fb_state(surface);
 
         /* Parameters for the CBZB clear. */
-        surface->cbzb_allowed = tex->desc.cbzb_allowed[level];
+        surface->cbzb_allowed = tex->tex.cbzb_allowed[level];
         surface->cbzb_width = align(surface->base.width, 64);
 
         /* Height must be aligned to the size of a tile. */
-        tile_height = r300_get_pixel_alignment(tex->desc.b.b.format,
-                                               tex->desc.b.b.nr_samples,
-                                               tex->desc.microtile,
-                                               tex->desc.macrotile[level],
+        tile_height = r300_get_pixel_alignment(tex->b.b.b.format,
+                                               tex->b.b.b.nr_samples,
+                                               tex->tex.microtile,
+                                               tex->tex.macrotile[level],
                                                DIM_HEIGHT, 0);
 
         surface->cbzb_height = align((surface->base.height + 1) / 2,
@@ -914,7 +927,7 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx,
         /* Offset must be aligned to 2K and must point at the beginning
          * of a scanline. */
         offset = surface->offset +
-                 tex->desc.stride_in_bytes[level] * surface->cbzb_height;
+                 tex->tex.stride_in_bytes[level] * surface->cbzb_height;
         surface->cbzb_midpoint_offset = offset & ~2047;
 
         surface->cbzb_pitch = surface->pitch & 0x1ffffc;
@@ -929,8 +942,8 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx,
             surface->cbzb_allowed ? "YES" : " NO",
             surface->cbzb_width, surface->cbzb_height,
             offset & 2047,
-            tex->desc.microtile ? "YES" : " NO",
-            tex->desc.macrotile[level] ? "YES" : " NO");
+            tex->tex.microtile ? "YES" : " NO",
+            tex->tex.macrotile[level] ? "YES" : " NO");
     }
 
     return &surface->base;
index 0ab22f747e4c8814ce3395ad4acfc4133844ccdf..158a387478ff377379174b8f64f75dd7f5a2d34d 100644 (file)
@@ -32,7 +32,7 @@ struct pipe_resource;
 struct winsys_handle;
 struct r300_texture_format_state;
 struct r300_texture_desc;
-struct r300_texture;
+struct r300_resource;
 struct r300_screen;
 
 unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format,
@@ -46,9 +46,10 @@ uint32_t r300_translate_texformat(enum pipe_format format,
 
 uint32_t r500_tx_format_msb_bit(enum pipe_format format);
 
-void r300_texture_reinterpret_format(struct pipe_screen *screen,
+boolean r300_resource_set_properties(struct pipe_screen *screen,
                                      struct pipe_resource *tex,
-                                     enum pipe_format new_format);
+                                     unsigned offset,
+                                     const struct pipe_resource *new_properties);
 
 boolean r300_is_colorbuffer_format_supported(enum pipe_format format);
 
@@ -57,10 +58,14 @@ 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,
+                                     struct r300_resource *tex,
                                      unsigned level,
                                      struct r300_texture_format_state *out);
 
+boolean r300_resource_get_handle(struct pipe_screen* screen,
+                                struct pipe_resource *texture,
+                                struct winsys_handle *whandle);
+
 struct pipe_resource*
 r300_texture_from_handle(struct pipe_screen* screen,
                         const struct pipe_resource* base,
index 7b1739142d49083f97f88b7734fe70feb3c21317..2cfeec7d7516e7b723beae364f159aabc2e0f499 100644 (file)
@@ -90,19 +90,19 @@ unsigned r300_get_pixel_alignment(enum pipe_format format,
 }
 
 /* Return true if macrotiling should be enabled on the miplevel. */
-static boolean r300_texture_macro_switch(struct r300_texture_desc *desc,
+static boolean r300_texture_macro_switch(struct r300_resource *tex,
                                          unsigned level,
                                          boolean rv350_mode,
                                          enum r300_dim dim)
 {
     unsigned tile, texdim;
 
-    tile = r300_get_pixel_alignment(desc->b.b.format, desc->b.b.nr_samples,
-                                    desc->microtile, R300_BUFFER_TILED, dim, 0);
+    tile = r300_get_pixel_alignment(tex->b.b.b.format, tex->b.b.b.nr_samples,
+                                    tex->tex.microtile, R300_BUFFER_TILED, dim, 0);
     if (dim == DIM_WIDTH) {
-        texdim = u_minify(desc->width0, level);
+        texdim = u_minify(tex->tex.width0, level);
     } else {
-        texdim = u_minify(desc->height0, level);
+        texdim = u_minify(tex->tex.height0, level);
     }
 
     /* See TX_FILTER1_n.MACRO_SWITCH. */
@@ -118,7 +118,7 @@ static boolean r300_texture_macro_switch(struct r300_texture_desc *desc,
  * at the given level.
  */
 static unsigned r300_texture_get_stride(struct r300_screen *screen,
-                                        struct r300_texture_desc *desc,
+                                        struct r300_resource *tex,
                                         unsigned level)
 {
     unsigned tile_width, width, stride;
@@ -126,62 +126,62 @@ static unsigned r300_texture_get_stride(struct r300_screen *screen,
                         screen->caps.family == CHIP_FAMILY_RS690 ||
                         screen->caps.family == CHIP_FAMILY_RS740);
 
-    if (desc->stride_in_bytes_override)
-        return desc->stride_in_bytes_override;
+    if (tex->tex.stride_in_bytes_override)
+        return tex->tex.stride_in_bytes_override;
 
     /* Check the level. */
-    if (level > desc->b.b.last_level) {
+    if (level > tex->b.b.b.last_level) {
         SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n",
-                   __FUNCTION__, level, desc->b.b.last_level);
+                   __FUNCTION__, level, tex->b.b.b.last_level);
         return 0;
     }
 
-    width = u_minify(desc->width0, level);
+    width = u_minify(tex->tex.width0, level);
 
-    if (util_format_is_plain(desc->b.b.format)) {
-        tile_width = r300_get_pixel_alignment(desc->b.b.format,
-                                              desc->b.b.nr_samples,
-                                              desc->microtile,
-                                              desc->macrotile[level],
+    if (util_format_is_plain(tex->b.b.b.format)) {
+        tile_width = r300_get_pixel_alignment(tex->b.b.b.format,
+                                              tex->b.b.b.nr_samples,
+                                              tex->tex.microtile,
+                                              tex->tex.macrotile[level],
                                               DIM_WIDTH, is_rs690);
         width = align(width, tile_width);
 
-        stride = util_format_get_stride(desc->b.b.format, width);
+        stride = util_format_get_stride(tex->b.b.b.format, width);
         /* The alignment to 32 bytes is sort of implied by the layout... */
         return stride;
     } else {
-        return align(util_format_get_stride(desc->b.b.format, width), is_rs690 ? 64 : 32);
+        return align(util_format_get_stride(tex->b.b.b.format, width), is_rs690 ? 64 : 32);
     }
 }
 
-static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc,
+static unsigned r300_texture_get_nblocksy(struct r300_resource *tex,
                                           unsigned level,
                                           boolean *out_aligned_for_cbzb)
 {
     unsigned height, tile_height;
 
-    height = u_minify(desc->height0, level);
+    height = u_minify(tex->tex.height0, level);
 
-    if (util_format_is_plain(desc->b.b.format)) {
-        tile_height = r300_get_pixel_alignment(desc->b.b.format,
-                                               desc->b.b.nr_samples,
-                                               desc->microtile,
-                                               desc->macrotile[level],
+    /* Mipmapped and 3D textures must have their height aligned to POT. */
+    if ((tex->b.b.b.target != PIPE_TEXTURE_1D &&
+         tex->b.b.b.target != PIPE_TEXTURE_2D &&
+         tex->b.b.b.target != PIPE_TEXTURE_RECT) ||
+        tex->b.b.b.last_level != 0) {
+        height = util_next_power_of_two(height);
+    }
+
+    if (util_format_is_plain(tex->b.b.b.format)) {
+        tile_height = r300_get_pixel_alignment(tex->b.b.b.format,
+                                               tex->b.b.b.nr_samples,
+                                               tex->tex.microtile,
+                                               tex->tex.macrotile[level],
                                                DIM_HEIGHT, 0);
         height = align(height, tile_height);
 
-        /* This is needed for the kernel checker, unfortunately. */
-        if ((desc->b.b.target != PIPE_TEXTURE_1D &&
-             desc->b.b.target != PIPE_TEXTURE_2D &&
-             desc->b.b.target != PIPE_TEXTURE_RECT) ||
-            desc->b.b.last_level != 0) {
-            height = util_next_power_of_two(height);
-        }
-
         /* See if the CBZB clear can be used on the buffer,
          * taking the texture size into account. */
         if (out_aligned_for_cbzb) {
-            if (desc->macrotile[level]) {
+            if (tex->tex.macrotile[level]) {
                 /* When clearing, the layer (width*height) is horizontally split
                  * into two, and the upper and lower halves are cleared by the CB
                  * and ZB units, respectively. Therefore, the number of macrotiles
@@ -189,10 +189,10 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc,
 
                 /* Align the height so that there is an even number of macrotiles.
                  * Do so for 3 or more macrotiles in the Y direction. */
-                if (level == 0 && desc->b.b.last_level == 0 &&
-                    (desc->b.b.target == PIPE_TEXTURE_1D ||
-                     desc->b.b.target == PIPE_TEXTURE_2D ||
-                     desc->b.b.target == PIPE_TEXTURE_RECT) &&
+                if (level == 0 && tex->b.b.b.last_level == 0 &&
+                    (tex->b.b.b.target == PIPE_TEXTURE_1D ||
+                     tex->b.b.b.target == PIPE_TEXTURE_2D ||
+                     tex->b.b.b.target == PIPE_TEXTURE_RECT) &&
                     height >= tile_height * 3) {
                     height = align(height, tile_height * 2);
                 }
@@ -204,11 +204,11 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc,
         }
     }
 
-    return util_format_get_nblocksy(desc->b.b.format, height);
+    return util_format_get_nblocksy(tex->b.b.b.format, height);
 }
 
 static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen,
-                                           struct r300_texture_desc *desc)
+                                           struct r300_resource *tex)
 {
     /* The kernels <= 2.6.34-rc4 compute the size of mipmapped 3D textures
      * incorrectly. This is a workaround to prevent CS from being rejected. */
@@ -216,17 +216,17 @@ static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen,
     unsigned i, size;
 
     if (!screen->rws->get_value(screen->rws, R300_VID_DRM_2_3_0) &&
-        desc->b.b.target == PIPE_TEXTURE_3D &&
-        desc->b.b.last_level > 0) {
+        tex->b.b.b.target == PIPE_TEXTURE_3D &&
+        tex->b.b.b.last_level > 0) {
         size = 0;
 
-        for (i = 0; i <= desc->b.b.last_level; i++) {
-            size += desc->stride_in_bytes[i] *
-                    r300_texture_get_nblocksy(desc, i, FALSE);
+        for (i = 0; i <= tex->b.b.b.last_level; i++) {
+            size += tex->tex.stride_in_bytes[i] *
+                    r300_texture_get_nblocksy(tex, i, FALSE);
         }
 
-        size *= desc->depth0;
-        desc->size_in_bytes = size;
+        size *= tex->tex.depth0;
+        tex->tex.size_in_bytes = size;
     }
 }
 
@@ -239,15 +239,15 @@ static unsigned stride_to_width(enum pipe_format format,
 }
 
 static void r300_setup_miptree(struct r300_screen *screen,
-                               struct r300_texture_desc *desc,
+                               struct r300_resource *tex,
                                boolean align_for_cbzb)
 {
-    struct pipe_resource *base = &desc->b.b;
+    struct pipe_resource *base = &tex->b.b.b;
     unsigned stride, size, layer_size, nblocksy, i;
     boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350;
     boolean aligned_for_cbzb;
 
-    desc->size_in_bytes = 0;
+    tex->tex.size_in_bytes = 0;
 
     SCREEN_DBG(screen, DBG_TEXALLOC,
         "r300: Making miptree for texture, format %s\n",
@@ -255,21 +255,21 @@ static void r300_setup_miptree(struct r300_screen *screen,
 
     for (i = 0; i <= base->last_level; i++) {
         /* Let's see if this miplevel can be macrotiled. */
-        desc->macrotile[i] =
-            (desc->macrotile[0] == R300_BUFFER_TILED &&
-             r300_texture_macro_switch(desc, i, rv350_mode, DIM_WIDTH) &&
-             r300_texture_macro_switch(desc, i, rv350_mode, DIM_HEIGHT)) ?
+        tex->tex.macrotile[i] =
+            (tex->tex.macrotile[0] == R300_BUFFER_TILED &&
+             r300_texture_macro_switch(tex, i, rv350_mode, DIM_WIDTH) &&
+             r300_texture_macro_switch(tex, i, rv350_mode, DIM_HEIGHT)) ?
              R300_BUFFER_TILED : R300_BUFFER_LINEAR;
 
-        stride = r300_texture_get_stride(screen, desc, i);
+        stride = r300_texture_get_stride(screen, tex, i);
 
         /* Compute the number of blocks in Y, see if the CBZB clear can be
          * used on the texture. */
         aligned_for_cbzb = FALSE;
-        if (align_for_cbzb && desc->cbzb_allowed[i])
-            nblocksy = r300_texture_get_nblocksy(desc, i, &aligned_for_cbzb);
+        if (align_for_cbzb && tex->tex.cbzb_allowed[i])
+            nblocksy = r300_texture_get_nblocksy(tex, i, &aligned_for_cbzb);
         else
-            nblocksy = r300_texture_get_nblocksy(desc, i, NULL);
+            nblocksy = r300_texture_get_nblocksy(tex, i, NULL);
 
         layer_size = stride * nblocksy;
 
@@ -280,75 +280,136 @@ static void r300_setup_miptree(struct r300_screen *screen,
         if (base->target == PIPE_TEXTURE_CUBE)
             size = layer_size * 6;
         else
-            size = layer_size * u_minify(desc->depth0, i);
+            size = layer_size * u_minify(tex->tex.depth0, i);
 
-        desc->offset_in_bytes[i] = desc->size_in_bytes;
-        desc->size_in_bytes = desc->offset_in_bytes[i] + size;
-        desc->layer_size_in_bytes[i] = layer_size;
-        desc->stride_in_bytes[i] = stride;
-        desc->stride_in_pixels[i] = stride_to_width(desc->b.b.format, stride);
-        desc->cbzb_allowed[i] = desc->cbzb_allowed[i] && aligned_for_cbzb;
+        tex->tex.offset_in_bytes[i] = tex->tex.size_in_bytes;
+        tex->tex.size_in_bytes = tex->tex.offset_in_bytes[i] + size;
+        tex->tex.layer_size_in_bytes[i] = layer_size;
+        tex->tex.stride_in_bytes[i] = stride;
+        tex->tex.stride_in_pixels[i] = stride_to_width(tex->b.b.b.format, stride);
+        tex->tex.cbzb_allowed[i] = tex->tex.cbzb_allowed[i] && aligned_for_cbzb;
 
         SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Texture miptree: Level %d "
                 "(%dx%dx%d px, pitch %d bytes) %d bytes total, macrotiled %s\n",
-                i, u_minify(desc->width0, i), u_minify(desc->height0, i),
-                u_minify(desc->depth0, i), stride, desc->size_in_bytes,
-                desc->macrotile[i] ? "TRUE" : "FALSE");
+                i, u_minify(tex->tex.width0, i), u_minify(tex->tex.height0, i),
+                u_minify(tex->tex.depth0, i), stride, tex->tex.size_in_bytes,
+                tex->tex.macrotile[i] ? "TRUE" : "FALSE");
     }
 }
 
-static void r300_setup_flags(struct r300_texture_desc *desc)
+static void r300_setup_flags(struct r300_resource *tex)
 {
-    desc->uses_stride_addressing =
-        !util_is_power_of_two(desc->b.b.width0) ||
-        (desc->stride_in_bytes_override &&
-         stride_to_width(desc->b.b.format,
-                         desc->stride_in_bytes_override) != desc->b.b.width0);
-
-    desc->is_npot =
-        desc->uses_stride_addressing ||
-        !util_is_power_of_two(desc->b.b.height0) ||
-        !util_is_power_of_two(desc->b.b.depth0);
+    tex->tex.uses_stride_addressing =
+        !util_is_power_of_two(tex->b.b.b.width0) ||
+        (tex->tex.stride_in_bytes_override &&
+         stride_to_width(tex->b.b.b.format,
+                         tex->tex.stride_in_bytes_override) != tex->b.b.b.width0);
+
+    tex->tex.is_npot =
+        tex->tex.uses_stride_addressing ||
+        !util_is_power_of_two(tex->b.b.b.height0) ||
+        !util_is_power_of_two(tex->b.b.b.depth0);
 }
 
 static void r300_setup_cbzb_flags(struct r300_screen *rscreen,
-                                  struct r300_texture_desc *desc)
+                                  struct r300_resource *tex)
 {
     unsigned i, bpp;
     boolean first_level_valid;
 
-    bpp = util_format_get_blocksizebits(desc->b.b.format);
+    bpp = util_format_get_blocksizebits(tex->b.b.b.format);
 
     /* 1) The texture must be point-sampled,
      * 2) The depth must be 16 or 32 bits.
      * 3) If the midpoint ZB offset is not aligned to 2048, it returns garbage
      *    with certain texture sizes. Macrotiling ensures the alignment. */
-    first_level_valid = desc->b.b.nr_samples <= 1 &&
+    first_level_valid = tex->b.b.b.nr_samples <= 1 &&
                        (bpp == 16 || bpp == 32) &&
-                       desc->macrotile[0];
+                       tex->tex.macrotile[0];
 
     if (SCREEN_DBG_ON(rscreen, DBG_NO_CBZB))
         first_level_valid = FALSE;
 
-    for (i = 0; i <= desc->b.b.last_level; i++)
-        desc->cbzb_allowed[i] = first_level_valid && desc->macrotile[i];
+    for (i = 0; i <= tex->b.b.b.last_level; i++)
+        tex->tex.cbzb_allowed[i] = first_level_valid && tex->tex.macrotile[i];
+}
+
+#define ALIGN_DIVUP(x, y) (((x) + (y) - 1) / (y))
+
+static void r300_setup_zmask_flags(struct r300_screen *screen,
+                                   struct r300_resource *tex)
+{
+    /* The tile size of 1 DWORD is:
+     *
+     * GPU    Pipes    4x4 mode   8x8 mode
+     * ------------------------------------------
+     * R580   4P/1Z    32x32      64x64
+     * RV570  3P/1Z    48x16      96x32
+     * RV530  1P/2Z    32x16      64x32
+     *        1P/1Z    16x16      32x32
+     */
+    static unsigned num_blocks_x_per_dw[4] = {4, 8, 12, 8};
+    static unsigned num_blocks_y_per_dw[4] = {4, 4,  4, 8};
+
+    if (util_format_is_depth_or_stencil(tex->b.b.b.format) &&
+        util_format_get_blocksizebits(tex->b.b.b.format) == 32 &&
+        tex->tex.microtile) {
+        unsigned i, pipes;
+
+        if (screen->caps.family == CHIP_FAMILY_RV530) {
+            pipes = screen->caps.num_z_pipes;
+        } else {
+            pipes = screen->caps.num_frag_pipes;
+        }
+
+        for (i = 0; i <= tex->b.b.b.last_level; i++) {
+            unsigned numdw, compsize;
+
+            /* The 8x8 compression mode needs macrotiling. */
+            compsize = screen->caps.z_compress == R300_ZCOMP_8X8 &&
+                       tex->tex.macrotile[i] &&
+                       tex->b.b.b.nr_samples <= 1 ? 8 : 4;
+
+            /* Get the zbuffer size (with the aligned width and height). */
+            numdw = align(tex->tex.stride_in_pixels[i],
+                          num_blocks_x_per_dw[pipes-1] * compsize) *
+                    align(u_minify(tex->b.b.b.height0, i),
+                          num_blocks_y_per_dw[pipes-1] * compsize);
+
+            /* Convert pixels -> dwords. */
+            numdw = ALIGN_DIVUP(numdw, num_blocks_x_per_dw[pipes-1] * compsize *
+                                       num_blocks_y_per_dw[pipes-1] * compsize);
+
+            /* Check that we have enough ZMASK memory. */
+            if (numdw <= screen->caps.zmask_ram * pipes) {
+                tex->tex.zmask_dwords[i] = numdw;
+                tex->tex.zcomp8x8[i] = compsize == 8;
+            } else {
+                tex->tex.zmask_dwords[i] = 0;
+                tex->tex.zcomp8x8[i] = FALSE;
+            }
+        }
+    }
 }
 
 static void r300_setup_tiling(struct r300_screen *screen,
-                              struct r300_texture_desc *desc)
+                              struct r300_resource *tex)
 {
     struct r300_winsys_screen *rws = screen->rws;
-    enum pipe_format format = desc->b.b.format;
+    enum pipe_format format = tex->b.b.b.format;
     boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350;
     boolean is_zb = util_format_is_depth_or_stencil(format);
     boolean dbg_no_tiling = SCREEN_DBG_ON(screen, DBG_NO_TILING);
 
+    tex->tex.microtile = R300_BUFFER_LINEAR;
+    tex->tex.macrotile[0] = R300_BUFFER_LINEAR;
+
     if (!util_format_is_plain(format)) {
         return;
     }
 
     /* If height == 1, disable microtiling except for zbuffer. */
-    if (!is_zb && (desc->b.b.height0 == 1 || dbg_no_tiling)) {
+    if (!is_zb && (tex->b.b.b.height0 == 1 || dbg_no_tiling)) {
         return;
     }
 
@@ -357,12 +418,12 @@ static void r300_setup_tiling(struct r300_screen *screen,
         case 1:
         case 4:
         case 8:
-            desc->microtile = R300_BUFFER_TILED;
+            tex->tex.microtile = R300_BUFFER_TILED;
             break;
 
         case 2:
-            if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) {
-                desc->microtile = R300_BUFFER_SQUARETILED;
+            if (rws->get_value(rws, R300_VID_DRM_2_1_0)) {
+                tex->tex.microtile = R300_BUFFER_SQUARETILED;
             }
             break;
     }
@@ -372,104 +433,100 @@ static void r300_setup_tiling(struct r300_screen *screen,
     }
 
     /* Set macrotiling. */
-    if (r300_texture_macro_switch(desc, 0, rv350_mode, DIM_WIDTH) &&
-        r300_texture_macro_switch(desc, 0, rv350_mode, DIM_HEIGHT)) {
-        desc->macrotile[0] = R300_BUFFER_TILED;
+    if (r300_texture_macro_switch(tex, 0, rv350_mode, DIM_WIDTH) &&
+        r300_texture_macro_switch(tex, 0, rv350_mode, DIM_HEIGHT)) {
+        tex->tex.macrotile[0] = R300_BUFFER_TILED;
     }
 }
 
-static void r300_tex_print_info(struct r300_screen *rscreen,
-                                struct r300_texture_desc *desc,
+static void r300_tex_print_info(struct r300_resource *tex,
                                 const char *func)
 {
     fprintf(stderr,
             "r300: %s: Macro: %s, Micro: %s, Pitch: %i, Dim: %ix%ix%i, "
             "LastLevel: %i, Size: %i, Format: %s\n",
             func,
-            desc->macrotile[0] ? "YES" : " NO",
-            desc->microtile ? "YES" : " NO",
-            desc->stride_in_pixels[0],
-            desc->b.b.width0, desc->b.b.height0, desc->b.b.depth0,
-            desc->b.b.last_level, desc->size_in_bytes,
-            util_format_short_name(desc->b.b.format));
+            tex->tex.macrotile[0] ? "YES" : " NO",
+            tex->tex.microtile ? "YES" : " NO",
+            tex->tex.stride_in_pixels[0],
+            tex->b.b.b.width0, tex->b.b.b.height0, tex->b.b.b.depth0,
+            tex->b.b.b.last_level, tex->tex.size_in_bytes,
+            util_format_short_name(tex->b.b.b.format));
 }
 
 boolean r300_texture_desc_init(struct r300_screen *rscreen,
-                               struct r300_texture_desc *desc,
-                               const struct pipe_resource *base,
-                               enum r300_buffer_tiling microtile,
-                               enum r300_buffer_tiling macrotile,
-                               unsigned stride_in_bytes_override,
-                               unsigned max_buffer_size)
+                               struct r300_resource *tex,
+                               const struct pipe_resource *base)
 {
-    desc->b.b = *base;
-    desc->b.b.screen = &rscreen->screen;
-    desc->stride_in_bytes_override = stride_in_bytes_override;
-    desc->width0 = base->width0;
-    desc->height0 = base->height0;
-    desc->depth0 = base->depth0;
-
-    r300_setup_flags(desc);
+    tex->b.b.b.target = base->target;
+    tex->b.b.b.format = base->format;
+    tex->b.b.b.width0 = base->width0;
+    tex->b.b.b.height0 = base->height0;
+    tex->b.b.b.depth0 = base->depth0;
+    tex->b.b.b.array_size = base->array_size;
+    tex->b.b.b.last_level = base->last_level;
+    tex->b.b.b.nr_samples = base->nr_samples;
+    tex->tex.width0 = base->width0;
+    tex->tex.height0 = base->height0;
+    tex->tex.depth0 = base->depth0;
+
+    r300_setup_flags(tex);
 
     /* Align a 3D NPOT texture to POT. */
-    if (base->target == PIPE_TEXTURE_3D && desc->is_npot) {
-        desc->width0 = util_next_power_of_two(desc->width0);
-        desc->height0 = util_next_power_of_two(desc->height0);
-        desc->depth0 = util_next_power_of_two(desc->depth0);
+    if (base->target == PIPE_TEXTURE_3D && tex->tex.is_npot) {
+        tex->tex.width0 = util_next_power_of_two(tex->tex.width0);
+        tex->tex.height0 = util_next_power_of_two(tex->tex.height0);
+        tex->tex.depth0 = util_next_power_of_two(tex->tex.depth0);
     }
 
     /* Setup tiling. */
-    if (microtile == R300_BUFFER_SELECT_LAYOUT ||
-        macrotile == R300_BUFFER_SELECT_LAYOUT) {
-        r300_setup_tiling(rscreen, desc);
-    } else {
-        desc->microtile = microtile;
-        desc->macrotile[0] = macrotile;
-        assert(desc->b.b.last_level == 0);
+    if (tex->tex.microtile == R300_BUFFER_SELECT_LAYOUT) {
+        r300_setup_tiling(rscreen, tex);
     }
 
-    r300_setup_cbzb_flags(rscreen, desc);
+    r300_setup_cbzb_flags(rscreen, tex);
 
     /* Setup the miptree description. */
-    r300_setup_miptree(rscreen, desc, TRUE);
+    r300_setup_miptree(rscreen, tex, TRUE);
     /* If the required buffer size is larger the given max size,
      * try again without the alignment for the CBZB clear. */
-    if (max_buffer_size && desc->size_in_bytes > max_buffer_size) {
-        r300_setup_miptree(rscreen, desc, FALSE);
+    if (tex->buf_size && tex->tex.size_in_bytes > tex->buf_size) {
+        r300_setup_miptree(rscreen, tex, FALSE);
     }
 
-    r300_texture_3d_fix_mipmapping(rscreen, desc);
+    r300_texture_3d_fix_mipmapping(rscreen, tex);
+    r300_setup_zmask_flags(rscreen, tex);
 
-    if (max_buffer_size) {
+    if (tex->buf_size) {
         /* Make sure the buffer we got is large enough. */
-        if (desc->size_in_bytes > max_buffer_size) {
+        if (tex->tex.size_in_bytes > tex->buf_size) {
             fprintf(stderr, "r300: texture_desc_init: The buffer is not "
                             "large enough. Got: %i, Need: %i, Info:\n",
-                            max_buffer_size, desc->size_in_bytes);
-            r300_tex_print_info(rscreen, desc, "texture_desc_init");
+                            tex->buf_size, tex->tex.size_in_bytes);
+            r300_tex_print_info(tex, "texture_desc_init");
             return FALSE;
         }
 
-        desc->buffer_size_in_bytes = max_buffer_size;
+        tex->tex.buffer_size_in_bytes = tex->buf_size;
     } else {
-        desc->buffer_size_in_bytes = desc->size_in_bytes;
+        tex->tex.buffer_size_in_bytes = tex->tex.size_in_bytes;
     }
 
     if (SCREEN_DBG_ON(rscreen, DBG_TEX))
-        r300_tex_print_info(rscreen, desc, "texture_desc_init");
+        r300_tex_print_info(tex, "texture_desc_init");
 
     return TRUE;
 }
 
-unsigned r300_texture_get_offset(struct r300_texture_desc *desc,
+unsigned r300_texture_get_offset(struct r300_resource *tex,
                                  unsigned level, unsigned layer)
 {
-    unsigned offset = desc->offset_in_bytes[level];
+    unsigned offset = tex->tex.offset_in_bytes[level];
 
-    switch (desc->b.b.target) {
+    switch (tex->b.b.b.target) {
         case PIPE_TEXTURE_3D:
         case PIPE_TEXTURE_CUBE:
-            return offset + layer * desc->layer_size_in_bytes[level];
+            return offset + layer * tex->tex.layer_size_in_bytes[level];
 
         default:
             assert(layer == 0);
index 121d215b4cbab2ddcedd6a4dd81c85b6bc36460c..ce6e9643ec6ffe8a6de7fc942483e824bdbb6826 100644 (file)
@@ -30,7 +30,7 @@
 struct pipe_resource;
 struct r300_screen;
 struct r300_texture_desc;
-struct r300_texture;
+struct r300_resource;
 
 enum r300_dim {
     DIM_WIDTH  = 0,
@@ -44,14 +44,10 @@ unsigned r300_get_pixel_alignment(enum pipe_format format,
                                   enum r300_dim dim, boolean is_rs690);
 
 boolean r300_texture_desc_init(struct r300_screen *rscreen,
-                               struct r300_texture_desc *desc,
-                               const struct pipe_resource *base,
-                               enum r300_buffer_tiling microtile,
-                               enum r300_buffer_tiling macrotile,
-                               unsigned stride_in_bytes_override,
-                               unsigned max_buffer_size);
-
-unsigned r300_texture_get_offset(struct r300_texture_desc *desc,
+                               struct r300_resource *tex,
+                               const struct pipe_resource *base);
+
+unsigned r300_texture_get_offset(struct r300_resource *tex,
                                  unsigned level, unsigned layer);
 
 #endif
index 15a323989b26965f43d6cd23dbfd70370c55d376..97ec0a1a1f20e5fdafc06daf5bedbdd2a52e7e72 100644 (file)
@@ -191,7 +191,12 @@ static void transform_dstreg(
     dst->File = translate_register_file(src->Register.File);
     dst->Index = translate_register_index(ttr, src->Register.File, src->Register.Index);
     dst->WriteMask = src->Register.WriteMask;
-    dst->RelAddr = src->Register.Indirect;
+
+    if (src->Register.Indirect) {
+        ttr->error = TRUE;
+        fprintf(stderr, "r300: Relative addressing of destination operands "
+                "is unsupported.\n");
+    }
 }
 
 static void transform_srcreg(
@@ -332,6 +337,8 @@ void r300_tgsi_to_rc(struct tgsi_to_rc * ttr,
     unsigned imm_index = 0;
     int i;
 
+    ttr->error = FALSE;
+
     /* Allocate constants placeholders.
      *
      * Note: What if declared constants are not contiguous? */
index 97641a954b9c77497c3406d0820f760679748e0a..adb044cfe5698582c40bf2432ff6d2ea40720067 100644 (file)
@@ -47,6 +47,9 @@ struct tgsi_to_rc {
     /* Vertex shaders have no half swizzles, and no way to handle them, so
      * until rc grows proper support, indicate if they're safe to use. */
     boolean use_half_swizzles;
+
+    /* If an error occured. */
+    boolean error;
 };
 
 void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens);
index ae93fab554e4b508c4d53d9a68bde38ef9d0cd4f..30de9ec1e32515fe52ed79e3040b2629c10b5d9f 100644 (file)
@@ -37,7 +37,7 @@ struct r300_transfer {
     unsigned offset;
 
     /* Linear texture. */
-    struct r300_texture *linear_texture;
+    struct r300_resource *linear_texture;
 };
 
 /* Convenience cast wrapper. */
@@ -54,7 +54,7 @@ static void r300_copy_from_tiled_texture(struct pipe_context *ctx,
     struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer;
     struct pipe_resource *tex = transfer->resource;
 
-    ctx->resource_copy_region(ctx, &r300transfer->linear_texture->desc.b.b, 0,
+    ctx->resource_copy_region(ctx, &r300transfer->linear_texture->b.b.b, 0,
                               0, 0, 0,
                               tex, transfer->level, &transfer->box);
 }
@@ -70,7 +70,7 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx,
 
     ctx->resource_copy_region(ctx, tex, transfer->level,
                               transfer->box.x, transfer->box.y, transfer->box.z,
-                              &r300transfer->linear_texture->desc.b.b, 0, &src_box);
+                              &r300transfer->linear_texture->b.b.b, 0, &src_box);
 
     ctx->flush(ctx, 0, NULL);
 }
@@ -83,25 +83,24 @@ r300_texture_get_transfer(struct pipe_context *ctx,
                           const struct pipe_box *box)
 {
     struct r300_context *r300 = r300_context(ctx);
-    struct r300_texture *tex = r300_texture(texture);
+    struct r300_resource *tex = r300_resource(texture);
     struct r300_transfer *trans;
     struct pipe_resource base;
     boolean referenced_cs, referenced_hw, blittable;
+    const struct util_format_description *desc =
+        util_format_description(texture->format);
 
     referenced_cs =
-        r300->rws->cs_is_buffer_referenced(r300->cs,
-                                           tex->cs_buffer, R300_REF_CS);
+        r300->rws->cs_is_buffer_referenced(r300->cs, tex->cs_buf);
     if (referenced_cs) {
         referenced_hw = TRUE;
     } else {
         referenced_hw =
-            r300->rws->cs_is_buffer_referenced(r300->cs,
-                                               tex->cs_buffer, R300_REF_HW);
+            r300->rws->buffer_is_busy(tex->buf);
     }
 
-    blittable = ctx->screen->is_format_supported(
-            ctx->screen, texture->format, texture->target, 0,
-            PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, 0);
+    blittable = desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ||
+                desc->layout == UTIL_FORMAT_LAYOUT_S3TC;
 
     trans = CALLOC_STRUCT(r300_transfer);
     if (trans) {
@@ -114,8 +113,13 @@ r300_texture_get_transfer(struct pipe_context *ctx,
         /* If the texture is tiled, we must create a temporary detiled texture
          * for this transfer.
          * Also make write transfers pipelined. */
-        if (tex->desc.microtile || tex->desc.macrotile[level] ||
-            ((referenced_hw & !(usage & PIPE_TRANSFER_READ)) && blittable)) {
+        if (tex->tex.microtile || tex->tex.macrotile[level] ||
+            (referenced_hw && blittable && !(usage & PIPE_TRANSFER_READ))) {
+            if (r300->blitter->running) {
+                fprintf(stderr, "r300: ERROR: Blitter recursion in texture_get_transfer.\n");
+                os_break();
+            }
+
             base.target = PIPE_TEXTURE_2D;
             base.format = texture->format;
             base.width0 = box->width;
@@ -140,7 +144,7 @@ r300_texture_get_transfer(struct pipe_context *ctx,
             }
 
             /* Create the temporary texture. */
-            trans->linear_texture = r300_texture(
+            trans->linear_texture = r300_resource(
                ctx->screen->resource_create(ctx->screen,
                                             &base));
 
@@ -149,14 +153,14 @@ r300_texture_get_transfer(struct pipe_context *ctx,
                  * Let's flush and try again. */
                 ctx->flush(ctx, 0, NULL);
 
-                trans->linear_texture = r300_texture(
+                trans->linear_texture = r300_resource(
                    ctx->screen->resource_create(ctx->screen,
                                                 &base));
 
                 if (!trans->linear_texture) {
                     /* For linear textures, it's safe to fallback to
                      * an unpipelined transfer. */
-                    if (!tex->desc.microtile && !tex->desc.macrotile[level]) {
+                    if (!tex->tex.microtile && !tex->tex.macrotile[level]) {
                         goto unpipelined;
                     }
 
@@ -168,8 +172,8 @@ r300_texture_get_transfer(struct pipe_context *ctx,
                 }
             }
 
-            assert(!trans->linear_texture->desc.microtile &&
-                   !trans->linear_texture->desc.macrotile[0]);
+            assert(!trans->linear_texture->tex.microtile &&
+                   !trans->linear_texture->tex.macrotile[0]);
 
             /* Set the stride.
             *
@@ -179,7 +183,7 @@ r300_texture_get_transfer(struct pipe_context *ctx,
             * right thing internally.
             */
             trans->transfer.stride =
-                    trans->linear_texture->desc.stride_in_bytes[0];
+                    trans->linear_texture->tex.stride_in_bytes[0];
 
             if (usage & PIPE_TRANSFER_READ) {
                 /* We cannot map a tiled texture directly because the data is
@@ -194,8 +198,8 @@ r300_texture_get_transfer(struct pipe_context *ctx,
 
     unpipelined:
         /* Unpipelined transfer. */
-        trans->transfer.stride = tex->desc.stride_in_bytes[level];
-        trans->offset = r300_texture_get_offset(&tex->desc, level, box->z);
+        trans->transfer.stride = tex->tex.stride_in_bytes[level];
+        trans->offset = r300_texture_get_offset(tex, level, box->z);
 
         if (referenced_cs)
             ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
@@ -227,20 +231,19 @@ void* r300_texture_transfer_map(struct pipe_context *ctx,
     struct r300_context *r300 = r300_context(ctx);
     struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys;
     struct r300_transfer *r300transfer = r300_transfer(transfer);
-    struct r300_texture *tex = r300_texture(transfer->resource);
+    struct r300_resource *tex = r300_resource(transfer->resource);
     char *map;
-    enum pipe_format format = tex->desc.b.b.format;
+    enum pipe_format format = tex->b.b.b.format;
 
     if (r300transfer->linear_texture) {
         /* The detiled texture is of the same size as the region being mapped
          * (no offset needed). */
-        return rws->buffer_map(rws,
-                               r300transfer->linear_texture->buffer,
+        return rws->buffer_map(r300transfer->linear_texture->buf,
                                r300->cs,
                                transfer->usage);
     } else {
         /* Tiling is disabled. */
-        map = rws->buffer_map(rws, tex->buffer, r300->cs,
+        map = rws->buffer_map(tex->buf, r300->cs,
                               transfer->usage);
 
         if (!map) {
@@ -258,11 +261,11 @@ void r300_texture_transfer_unmap(struct pipe_context *ctx,
 {
     struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys;
     struct r300_transfer *r300transfer = r300_transfer(transfer);
-    struct r300_texture *tex = r300_texture(transfer->resource);
+    struct r300_resource *tex = r300_resource(transfer->resource);
 
     if (r300transfer->linear_texture) {
-        rws->buffer_unmap(rws, r300transfer->linear_texture->buffer);
+        rws->buffer_unmap(r300transfer->linear_texture->buf);
     } else {
-        rws->buffer_unmap(rws, tex->buffer);
+        rws->buffer_unmap(tex->buf);
     }
 }
index 78021e2c5d4667ca544897847baba2fa6effbb13..b319890157fe970ea4a134612bf722c23922f635 100644 (file)
@@ -226,6 +226,13 @@ void r300_translate_vertex_shader(struct r300_context *r300,
 
     r300_tgsi_to_rc(&ttr, vs->state.tokens);
 
+    if (ttr.error) {
+        fprintf(stderr, "r300 VP: Cannot translate a shader. "
+                "Using a dummy shader instead.\n");
+        r300_dummy_vertex_shader(r300, vs);
+        return;
+    }
+
     if (compiler.Base.Program.Constants.Count > 200) {
         compiler.Base.remove_unused_constants = TRUE;
     }
index 460da77a4fb1f96963a4475a12d4b220e9fbdffe..d5c73585c81e2608e03f3673507b0654b6b2e2d9 100644 (file)
  * Any winsys hosting this pipe needs to implement r300_winsys_screen and then
  * call r300_screen_create to start things. */
 
+#include "r300_defines.h"
+
+#include "pipebuffer/pb_bufmgr.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_state.h"
 
-#include "r300_defines.h"
-
 #define R300_MAX_CMDBUF_DWORDS (16 * 1024)
 
 struct winsys_handle;
 struct r300_winsys_screen;
 
-struct r300_winsys_buffer;      /* for map/unmap etc. */
-struct r300_winsys_cs_buffer;   /* for write_reloc etc. */
+#define r300_winsys_bo                      pb_buffer
+#define r300_winsys_bo_reference(pdst, src) pb_reference(pdst, src)
+
+struct r300_winsys_cs_handle;   /* for write_reloc etc. */
 
 struct r300_winsys_cs {
-    unsigned cdw;                           /* Number of used dwords. */
-    uint32_t buf[R300_MAX_CMDBUF_DWORDS];   /* The command buffer. */
+    unsigned cdw;  /* Number of used dwords. */
+    uint32_t *buf; /* The command buffer. */
 };
 
 enum r300_value_id {
     R300_VID_PCI_ID,
     R300_VID_GB_PIPES,
     R300_VID_Z_PIPES,
-    R300_VID_SQUARE_TILING_SUPPORT,
-    R300_VID_DRM_2_3_0, /* R500 VAP regs, MSPOS regs, fixed tex3D size checking */
-    R300_VID_DRM_2_6_0, /* Hyper-Z, GB_Z_PEQ_CONFIG on rv350->r4xx, R500 FG_ALPHA_VALUE */
-    R300_VID_DRM_2_8_0, /* R500 US_FORMAT regs, R500 ARGB2101010 colorbuffer */
-    R300_CAN_HYPERZ,
-};
-
-enum r300_reference_domain { /* bitfield */
-    R300_REF_CS = 1,
-    R300_REF_HW = 2
+    R300_VID_GART_SIZE,
+    R300_VID_VRAM_SIZE,
+    R300_VID_DRM_MAJOR,
+    R300_VID_DRM_MINOR,
+    R300_VID_DRM_PATCHLEVEL,
+
+    /* These should probably go away: */
+    R300_VID_DRM_2_1_0,  /* Square tiling. */
+    R300_VID_DRM_2_3_0,  /* R500 VAP regs, MSPOS regs, fixed tex3D size checking */
+    R300_VID_DRM_2_6_0,  /* Hyper-Z, GB_Z_PEQ_CONFIG on rv350->r4xx, R500 FG_ALPHA_VALUE */
+    R300_VID_DRM_2_8_0,  /* R500 US_FORMAT regs, R500 ARGB2101010 colorbuffer, CMask */
+
+    R300_CAN_HYPERZ,     /* ZMask + HiZ */
+    R300_CAN_AACOMPRESS, /* CMask */
 };
 
 struct r300_winsys_screen {
@@ -98,91 +105,78 @@ struct r300_winsys_screen {
      * \param domain    A bitmask of the R300_DOMAIN_* flags.
      * \return          The created buffer object.
      */
-    struct r300_winsys_buffer *(*buffer_create)(struct r300_winsys_screen *ws,
+    struct r300_winsys_bo *(*buffer_create)(struct r300_winsys_screen *ws,
                                                 unsigned size,
                                                 unsigned alignment,
                                                 unsigned bind,
                                                 unsigned usage,
                                                 enum r300_buffer_domain domain);
 
-    struct r300_winsys_cs_buffer *(*buffer_get_cs_handle)(
-            struct r300_winsys_screen *ws,
-            struct r300_winsys_buffer *buf);
-
-    /**
-     * Reference a buffer object (assign with reference counting).
-     *
-     * \param ws        The winsys this function is called from.
-     * \param pdst      A destination pointer to set the source buffer to.
-     * \param src       A source buffer object.
-     */
-    void (*buffer_reference)(struct r300_winsys_screen *ws,
-                             struct r300_winsys_buffer **pdst,
-                             struct r300_winsys_buffer *src);
+    struct r300_winsys_cs_handle *(*buffer_get_cs_handle)(
+            struct r300_winsys_bo *buf);
 
     /**
      * Map the entire data store of a buffer object into the client's address
      * space.
      *
-     * \param ws        The winsys this function is called from.
      * \param buf       A winsys buffer object to map.
      * \param cs        A command stream to flush if the buffer is referenced by it.
      * \param usage     A bitmask of the PIPE_TRANSFER_* flags.
      * \return          The pointer at the beginning of the buffer.
      */
-    void *(*buffer_map)(struct r300_winsys_screen *ws,
-                        struct r300_winsys_buffer *buf,
+    void *(*buffer_map)(struct r300_winsys_bo *buf,
                         struct r300_winsys_cs *cs,
                         enum pipe_transfer_usage usage);
 
     /**
      * Unmap a buffer object from the client's address space.
      *
-     * \param ws        The winsys this function is called from.
      * \param buf       A winsys buffer object to unmap.
      */
-    void (*buffer_unmap)(struct r300_winsys_screen *ws,
-                         struct r300_winsys_buffer *buf);
+    void (*buffer_unmap)(struct r300_winsys_bo *buf);
+
+    /**
+     * Return TRUE if a buffer object is being used by the GPU.
+     *
+     * \param buf       A winsys buffer object.
+     */
+    boolean (*buffer_is_busy)(struct r300_winsys_bo *buf);
 
     /**
      * Wait for a buffer object until it is not used by a GPU. This is
      * equivalent to a fence placed after the last command using the buffer,
      * and synchronizing to the fence.
      *
-     * \param ws        The winsys this function is called from.
      * \param buf       A winsys buffer object to wait for.
      */
-    void (*buffer_wait)(struct r300_winsys_screen *ws,
-                        struct r300_winsys_buffer *buf);
+    void (*buffer_wait)(struct r300_winsys_bo *buf);
 
     /**
      * Return tiling flags describing a memory layout of a buffer object.
      *
-     * \param ws        The winsys this function is called from.
      * \param buf       A winsys buffer object to get the flags from.
      * \param macrotile A pointer to the return value of the microtile flag.
      * \param microtile A pointer to the return value of the macrotile flag.
      *
      * \note microtile and macrotile are not bitmasks!
      */
-    void (*buffer_get_tiling)(struct r300_winsys_screen *ws,
-                              struct r300_winsys_buffer *buf,
+    void (*buffer_get_tiling)(struct r300_winsys_bo *buf,
                               enum r300_buffer_tiling *microtile,
                               enum r300_buffer_tiling *macrotile);
 
     /**
      * Set tiling flags describing a memory layout of a buffer object.
      *
-     * \param ws        The winsys this function is called from.
      * \param buf       A winsys buffer object to set the flags for.
+     * \param cs        A command stream to flush if the buffer is referenced by it.
      * \param macrotile A macrotile flag.
      * \param microtile A microtile flag.
      * \param stride    A stride of the buffer in bytes, for texturing.
      *
      * \note microtile and macrotile are not bitmasks!
      */
-    void (*buffer_set_tiling)(struct r300_winsys_screen *ws,
-                              struct r300_winsys_buffer *buf,
+    void (*buffer_set_tiling)(struct r300_winsys_bo *buf,
+                              struct r300_winsys_cs *cs,
                               enum r300_buffer_tiling microtile,
                               enum r300_buffer_tiling macrotile,
                               unsigned stride);
@@ -197,7 +191,7 @@ struct r300_winsys_screen {
      * \param stride    The returned buffer stride in bytes.
      * \param size      The returned buffer size.
      */
-    struct r300_winsys_buffer *(*buffer_from_handle)(struct r300_winsys_screen *ws,
+    struct r300_winsys_bo *(*buffer_from_handle)(struct r300_winsys_screen *ws,
                                                      struct winsys_handle *whandle,
                                                      unsigned *stride,
                                                      unsigned *size);
@@ -206,14 +200,12 @@ struct r300_winsys_screen {
      * Get a winsys handle from a winsys buffer. The internal structure
      * of the handle is platform-specific and only a winsys should access it.
      *
-     * \param ws        The winsys this function is called from.
      * \param buf       A winsys buffer object to get the handle from.
      * \param whandle   A winsys handle pointer.
      * \param stride    A stride of the buffer in bytes, for texturing.
      * \return          TRUE on success.
      */
-    boolean (*buffer_get_handle)(struct r300_winsys_screen *ws,
-                                 struct r300_winsys_buffer *buf,
+    boolean (*buffer_get_handle)(struct r300_winsys_bo *buf,
                                  unsigned stride,
                                  struct winsys_handle *whandle);
 
@@ -248,7 +240,7 @@ struct r300_winsys_screen {
      * \param wd  A write domain containing a bitmask of the R300_DOMAIN_* flags.
      */
     void (*cs_add_reloc)(struct r300_winsys_cs *cs,
-                         struct r300_winsys_cs_buffer *buf,
+                         struct r300_winsys_cs_handle *buf,
                          enum r300_buffer_domain rd,
                          enum r300_buffer_domain wd);
 
@@ -269,7 +261,7 @@ struct r300_winsys_screen {
      * \param wd        A write domain containing a bitmask of the R300_DOMAIN_* flags.
      */
     void (*cs_write_reloc)(struct r300_winsys_cs *cs,
-                           struct r300_winsys_cs_buffer *buf);
+                           struct r300_winsys_cs_handle *buf);
 
     /**
      * Flush a command stream.
@@ -278,6 +270,13 @@ struct r300_winsys_screen {
      */
     void (*cs_flush)(struct r300_winsys_cs *cs);
 
+    /**
+     * Wait until the last flush is completed.
+     *
+     * \param cs        A command stream.
+     */
+    void (*cs_sync_flush)(struct r300_winsys_cs *cs);
+
     /**
      * Set a flush callback which is called from winsys when flush is
      * required.
@@ -291,16 +290,13 @@ struct r300_winsys_screen {
                          void *user);
 
     /**
-     * Return TRUE if a buffer is referenced by a command stream or by hardware
-     * (i.e. is busy), based on the domain parameter.
+     * Return TRUE if a buffer is referenced by a command stream.
      *
      * \param cs        A command stream.
      * \param buf       A winsys buffer.
-     * \param domain    A bitmask of the R300_REF_* enums.
      */
     boolean (*cs_is_buffer_referenced)(struct r300_winsys_cs *cs,
-                                       struct r300_winsys_cs_buffer *buf,
-                                       enum r300_reference_domain domain);
+                                       struct r300_winsys_cs_handle *buf);
 };
 
 #endif /* R300_WINSYS_H */
index a690b671e4965b243ec63c11f00a1f1b6c30de14..436de9c4dbde0d46318a59d81402e5f8f804e44d 100644 (file)
@@ -22,7 +22,6 @@ C_SOURCES = \
        evergreen_state.c \
        eg_asm.c \
        r600_translate.c \
-       r600_state_common.c \
-       r600_upload.c
+       r600_state_common.c
 
 include ../../Makefile.template
index e51f50c5df5ed77de4efbe45c916c9c8c7f7f5ba..5a5fa6d65fdd19c8eb1d6e8fca5c187542796fb3 100644 (file)
@@ -28,7 +28,6 @@ r600 = env.ConvenienceLibrary(
         'r600_state_common.c',
         'r600_texture.c',
         'r600_translate.c',
-        'r600_upload.c',
         'r700_asm.c',
         'evergreen_state.c',
         'eg_asm.c',
index 5a39d7cdeec2483b6b90f1d6f43406275bbccab8..b5fcc7106fe6109af51f788a94db7448a6f1b2a5 100644 (file)
@@ -253,9 +253,13 @@ static inline unsigned r600_tex_dim(unsigned dim)
        default:
        case PIPE_TEXTURE_1D:
                return V_030000_SQ_TEX_DIM_1D;
+       case PIPE_TEXTURE_1D_ARRAY:
+               return V_030000_SQ_TEX_DIM_1D_ARRAY;
        case PIPE_TEXTURE_2D:
        case PIPE_TEXTURE_RECT:
                return V_030000_SQ_TEX_DIM_2D;
+       case PIPE_TEXTURE_2D_ARRAY:
+               return V_030000_SQ_TEX_DIM_2D_ARRAY;
        case PIPE_TEXTURE_3D:
                return V_030000_SQ_TEX_DIM_3D;
        case PIPE_TEXTURE_CUBE:
@@ -289,10 +293,14 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format)
 {
        switch (format) {
                /* 8-bit buffers. */
+       case PIPE_FORMAT_L4A4_UNORM:
+               return V_028C70_SWAP_ALT;
+
        case PIPE_FORMAT_A8_UNORM:
                return V_028C70_SWAP_ALT_REV;
        case PIPE_FORMAT_I8_UNORM:
        case PIPE_FORMAT_L8_UNORM:
+       case PIPE_FORMAT_L8_SRGB:
        case PIPE_FORMAT_R8_UNORM:
        case PIPE_FORMAT_R8_SNORM:
                return V_028C70_SWAP_STD;
@@ -313,6 +321,7 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format)
                return V_028C70_SWAP_STD;
 
        case PIPE_FORMAT_L8A8_UNORM:
+       case PIPE_FORMAT_L8A8_SRGB:
                return V_028C70_SWAP_ALT;
        case PIPE_FORMAT_R8G8_UNORM:
                return V_028C70_SWAP_STD;
@@ -352,9 +361,11 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format)
 
        case PIPE_FORMAT_R10G10B10A2_UNORM:
        case PIPE_FORMAT_R10G10B10X2_SNORM:
-       case PIPE_FORMAT_B10G10R10A2_UNORM:
        case PIPE_FORMAT_R10SG10SB10SA2U_NORM:
-               return V_028C70_SWAP_STD_REV;
+               return V_028C70_SWAP_STD;
+
+       case PIPE_FORMAT_B10G10R10A2_UNORM:
+               return V_028C70_SWAP_ALT;
 
        case PIPE_FORMAT_R16G16_UNORM:
                return V_028C70_SWAP_STD;
@@ -362,14 +373,13 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format)
                /* 64-bit buffers. */
        case PIPE_FORMAT_R16G16B16A16_UNORM:
        case PIPE_FORMAT_R16G16B16A16_SNORM:
-               //              return V_028C70_COLOR_16_16_16_16;
        case PIPE_FORMAT_R16G16B16A16_FLOAT:
-               //              return V_028C70_COLOR_16_16_16_16_FLOAT;
 
                /* 128-bit buffers. */
        case PIPE_FORMAT_R32G32B32A32_FLOAT:
-               //              return V_028C70_COLOR_32_32_32_32_FLOAT;
-               return 0;
+       case PIPE_FORMAT_R32G32B32A32_SNORM:
+       case PIPE_FORMAT_R32G32B32A32_UNORM:
+               return V_028C70_SWAP_STD;
        default:
                R600_ERR("unsupported colorswap format %d\n", format);
                return ~0;
@@ -381,9 +391,13 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format)
 {
        switch (format) {
                /* 8-bit buffers. */
+       case PIPE_FORMAT_L4A4_UNORM:
+               return V_028C70_COLOR_4_4;
+
        case PIPE_FORMAT_A8_UNORM:
        case PIPE_FORMAT_I8_UNORM:
        case PIPE_FORMAT_L8_UNORM:
+       case PIPE_FORMAT_L8_SRGB:
        case PIPE_FORMAT_R8_UNORM:
        case PIPE_FORMAT_R8_SNORM:
                return V_028C70_COLOR_8;
@@ -404,6 +418,7 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format)
                return V_028C70_COLOR_16;
 
        case PIPE_FORMAT_L8A8_UNORM:
+       case PIPE_FORMAT_L8A8_SRGB:
        case PIPE_FORMAT_R8G8_UNORM:
                return V_028C70_COLOR_8_8;
 
@@ -430,7 +445,7 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format)
        case PIPE_FORMAT_R10G10B10X2_SNORM:
        case PIPE_FORMAT_B10G10R10A2_UNORM:
        case PIPE_FORMAT_R10SG10SB10SA2U_NORM:
-               return V_028C70_COLOR_10_10_10_2;
+               return V_028C70_COLOR_2_10_10_10;
 
        case PIPE_FORMAT_Z24X8_UNORM:
        case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
@@ -471,6 +486,9 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format)
                return V_028C70_COLOR_32_32;
 
                /* 128-bit buffers. */
+       case PIPE_FORMAT_R32G32B32A32_SNORM:
+       case PIPE_FORMAT_R32G32B32A32_UNORM:
+               return V_028C70_COLOR_32_32_32_32;
        case PIPE_FORMAT_R32G32B32_FLOAT:
                return V_028C70_COLOR_32_32_32_FLOAT;
        case PIPE_FORMAT_R32G32B32A32_FLOAT:
@@ -501,9 +519,4 @@ static INLINE boolean r600_is_zs_format_supported(enum pipe_format format)
        return r600_translate_dbformat(format) != ~0;
 }
 
-static INLINE boolean r600_is_vertex_format_supported(enum pipe_format format)
-{
-       return r600_translate_colorformat(format) != ~0;
-}
-
 #endif
index 306ca03234f0bd252182bff49ff1985f68679cb9..3efdbaba0c37fda1e58cb86ebaa5d3e7b55e87be 100644 (file)
@@ -103,7 +103,7 @@ static void *evergreen_create_blend_state(struct pipe_context *ctx,
        }
        blend->cb_target_mask = target_mask;
        r600_pipe_state_add_reg(rstate, R_028808_CB_COLOR_CONTROL,
-                               color_control, 0xFFFFFFFF, NULL);
+                               color_control, 0xFFFFFFFD, NULL);
        r600_pipe_state_add_reg(rstate, R_028C3C_PA_SC_AA_MASK, 0xFFFFFFFF, 0xFFFFFFFF, NULL);
 
        for (int i = 0; i < 8; i++) {
@@ -351,7 +351,7 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte
        struct r600_resource *rbuffer;
        unsigned format;
        uint32_t word4 = 0, yuv_format = 0, pitch = 0;
-       unsigned char swizzle[4];
+       unsigned char swizzle[4], array_mode = 0, tile_type = 0;
        struct r600_bo *bo[2];
 
        if (resource == NULL)
@@ -380,35 +380,42 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte
        if (desc == NULL) {
                R600_ERR("unknow format %d\n", state->format);
        }
-       tmp = (struct r600_resource_texture*)texture;
+       tmp = (struct r600_resource_texture *)texture;
+       if (tmp->depth && !tmp->is_flushing_texture) {
+               r600_texture_depth_flush(ctx, texture, TRUE);
+               tmp = tmp->flushed_depth_texture;
+       }
+
+       if (tmp->force_int_type) {
+               word4 &= C_030010_NUM_FORMAT_ALL;
+               word4 |= S_030010_NUM_FORMAT_ALL(V_030010_SQ_NUM_FORMAT_INT);
+       }
+
        rbuffer = &tmp->resource;
        bo[0] = rbuffer->bo;
        bo[1] = rbuffer->bo;
-       /* FIXME depth texture decompression */
-       if (tmp->depth) {
-               r600_texture_depth_flush(ctx, texture);
-               tmp = (struct r600_resource_texture*)texture;
-               rbuffer = &tmp->flushed_depth_texture->resource;
-               bo[0] = rbuffer->bo;
-               bo[1] = rbuffer->bo;
-       }
-       pitch = align(tmp->pitch_in_pixels[0], 8);
+
+       pitch = align(tmp->pitch_in_blocks[0] * util_format_get_blockwidth(state->format), 8);
+       array_mode = tmp->array_mode[0];
+       tile_type = tmp->tile_type;
 
        /* FIXME properly handle first level != 0 */
        r600_pipe_state_add_reg(rstate, R_030000_RESOURCE0_WORD0,
                                S_030000_DIM(r600_tex_dim(texture->target)) |
                                S_030000_PITCH((pitch / 8) - 1) |
+                               S_030000_NON_DISP_TILING_ORDER(tile_type) |
                                S_030000_TEX_WIDTH(texture->width0 - 1), 0xFFFFFFFF, NULL);
        r600_pipe_state_add_reg(rstate, R_030004_RESOURCE0_WORD1,
                                S_030004_TEX_HEIGHT(texture->height0 - 1) |
-                               S_030004_TEX_DEPTH(texture->depth0 - 1),
+                               S_030004_TEX_DEPTH(texture->depth0 - 1) |
+                               S_030004_ARRAY_MODE(array_mode),
                                0xFFFFFFFF, NULL);
        r600_pipe_state_add_reg(rstate, R_030008_RESOURCE0_WORD2,
                                (tmp->offset[0] + r600_bo_offset(bo[0])) >> 8, 0xFFFFFFFF, bo[0]);
        r600_pipe_state_add_reg(rstate, R_03000C_RESOURCE0_WORD3,
                                (tmp->offset[1] + r600_bo_offset(bo[1])) >> 8, 0xFFFFFFFF, bo[1]);
        r600_pipe_state_add_reg(rstate, R_030010_RESOURCE0_WORD4,
-                               word4 | S_030010_NUM_FORMAT_ALL(V_030010_SQ_NUM_FORMAT_NORM) |
+                               word4 |
                                S_030010_SRF_MODE_ALL(V_030010_SRF_MODE_NO_ZERO) |
                                S_030010_BASE_LEVEL(state->u.tex.first_level), 0xFFFFFFFF, NULL);
        r600_pipe_state_add_reg(rstate, R_030014_RESOURCE0_WORD5,
@@ -431,7 +438,8 @@ static void evergreen_set_vs_sampler_view(struct pipe_context *ctx, unsigned cou
 
        for (int i = 0; i < count; i++) {
                if (resource[i]) {
-                       evergreen_context_pipe_state_set_vs_resource(&rctx->ctx, &resource[i]->state, i);
+                       evergreen_context_pipe_state_set_vs_resource(&rctx->ctx, &resource[i]->state,
+                                                                    i + R600_MAX_CONST_BUFFERS);
                }
        }
 }
@@ -446,9 +454,11 @@ static void evergreen_set_ps_sampler_view(struct pipe_context *ctx, unsigned cou
        for (i = 0; i < count; i++) {
                if (&rctx->ps_samplers.views[i]->base != views[i]) {
                        if (resource[i])
-                               evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, &resource[i]->state, i);
+                               evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, &resource[i]->state,
+                                                                            i + R600_MAX_CONST_BUFFERS);
                        else
-                               evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, NULL, i);
+                               evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, NULL,
+                                                                            i + R600_MAX_CONST_BUFFERS);
 
                        pipe_sampler_view_reference(
                                (struct pipe_sampler_view **)&rctx->ps_samplers.views[i],
@@ -457,7 +467,8 @@ static void evergreen_set_ps_sampler_view(struct pipe_context *ctx, unsigned cou
        }
        for (i = count; i < NUM_TEX_UNITS; i++) {
                if (rctx->ps_samplers.views[i]) {
-                       evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, NULL, i);
+                       evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, NULL,
+                                                                    i + R600_MAX_CONST_BUFFERS);
                        pipe_sampler_view_reference((struct pipe_sampler_view **)&rctx->ps_samplers.views[i], NULL);
                }
        }
@@ -638,11 +649,19 @@ static void evergreen_cb(struct r600_pipe_context *rctx, struct r600_pipe_state
        unsigned color_info;
        unsigned format, swap, ntype;
        unsigned offset;
+       unsigned tile_type;
        const struct util_format_description *desc;
        struct r600_bo *bo[3];
+       int i;
 
        surf = (struct r600_surface *)state->cbufs[cb];
        rtex = (struct r600_resource_texture*)state->cbufs[cb]->texture;
+
+       if (rtex->depth && !rtex->is_flushing_texture) {
+               r600_texture_depth_flush(&rctx->context, state->cbufs[cb]->texture, TRUE);
+               rtex = rtex->flushed_depth_texture;
+       }
+
        rbuffer = &rtex->resource;
        bo[0] = rbuffer->bo;
        bo[1] = rbuffer->bo;
@@ -651,21 +670,43 @@ static void evergreen_cb(struct r600_pipe_context *rctx, struct r600_pipe_state
        /* XXX quite sure for dx10+ hw don't need any offset hacks */
        offset = r600_texture_get_offset((struct r600_resource_texture *)state->cbufs[cb]->texture,
                                         level, state->cbufs[cb]->u.tex.first_layer);
-       pitch = rtex->pitch_in_pixels[level] / 8 - 1;
-       slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
+       pitch = rtex->pitch_in_blocks[level] / 8 - 1;
+       slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1;
        ntype = 0;
-       desc = util_format_description(rtex->resource.base.b.format);
+       desc = util_format_description(surf->base.format);
        if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
                ntype = V_028C70_NUMBER_SRGB;
 
-       format = r600_translate_colorformat(rtex->resource.base.b.format);
-       swap = r600_translate_colorswap(rtex->resource.base.b.format);
+       format = r600_translate_colorformat(surf->base.format);
+       swap = r600_translate_colorswap(surf->base.format);
+
+       /* disable when gallium grows int textures */
+       if ((format == FMT_32_32_32_32 || format == FMT_16_16_16_16) && rtex->force_int_type)
+               ntype = 4;
+
        color_info = S_028C70_FORMAT(format) |
                S_028C70_COMP_SWAP(swap) |
+               S_028C70_ARRAY_MODE(rtex->array_mode[level]) |
                S_028C70_BLEND_CLAMP(1) |
                S_028C70_NUMBER_TYPE(ntype);
-       if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
-               color_info |= S_028C70_SOURCE_FORMAT(1);
+
+       for (i = 0; i < 4; i++) {
+               if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {
+                       break;
+               }
+       }
+
+       /* we can only set the export size if any thing is snorm/unorm component is > 11 bits,
+          if we aren't a float, sint or uint */
+       if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS &&
+           desc->channel[i].size < 12 && desc->channel[i].type != UTIL_FORMAT_TYPE_FLOAT &&
+           ntype != 4 && ntype != 5)
+               color_info |= S_028C70_SOURCE_FORMAT(V_028C70_EXPORT_4C_16BPC);
+
+       if (rtex->array_mode[level] > V_028C70_ARRAY_LINEAR_ALIGNED) {
+               tile_type = rtex->tile_type;
+       } else /* workaround for linear buffers */
+               tile_type = 1;
 
        /* FIXME handle enabling of CB beyond BASE8 which has different offset */
        r600_pipe_state_add_reg(rstate,
@@ -690,7 +731,7 @@ static void evergreen_cb(struct r600_pipe_context *rctx, struct r600_pipe_state
                                0x00000000, 0xFFFFFFFF, NULL);
        r600_pipe_state_add_reg(rstate,
                                R_028C74_CB_COLOR0_ATTRIB + cb * 0x3C,
-                               S_028C74_NON_DISP_TILING_ORDER(1),
+                               S_028C74_NON_DISP_TILING_ORDER(tile_type),
                                0xFFFFFFFF, bo[0]);
 }
 
@@ -711,17 +752,14 @@ static void evergreen_db(struct r600_pipe_context *rctx, struct r600_pipe_state
 
        surf = (struct r600_surface *)state->zsbuf;
        rtex = (struct r600_resource_texture*)state->zsbuf->texture;
-       rtex->tiled = 1;
-       rtex->array_mode[level] = 2;
-       rtex->tile_type = 1;
-       rtex->depth = 1;
+
        rbuffer = &rtex->resource;
 
        /* XXX quite sure for dx10+ hw don't need any offset hacks */
        offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture,
                                         level, state->zsbuf->u.tex.first_layer);
-       pitch = rtex->pitch_in_pixels[level] / 8 - 1;
-       slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
+       pitch = rtex->pitch_in_blocks[level] / 8 - 1;
+       slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1;
        format = r600_translate_dbformat(state->zsbuf->texture->format);
        stencil_format = r600_translate_stencilformat(state->zsbuf->texture->format);
 
@@ -837,51 +875,6 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx,
        }
 }
 
-static void evergreen_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
-                                       struct pipe_resource *buffer)
-{
-       struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
-       struct r600_resource *rbuffer = (struct r600_resource*)buffer;
-       uint32_t offset;
-
-       /* Note that the state tracker can unbind constant buffers by
-        * passing NULL here.
-        */
-       if (buffer == NULL) {
-               return;
-       }
-
-       r600_upload_const_buffer(rctx, buffer, &offset);
-
-       switch (shader) {
-       case PIPE_SHADER_VERTEX:
-               rctx->vs_const_buffer.nregs = 0;
-               r600_pipe_state_add_reg(&rctx->vs_const_buffer,
-                                       R_028180_ALU_CONST_BUFFER_SIZE_VS_0,
-                                       ALIGN_DIVUP(buffer->width0 >> 4, 16),
-                                       0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(&rctx->vs_const_buffer,
-                                       R_028980_ALU_CONST_CACHE_VS_0,
-                                       (r600_bo_offset(rbuffer->bo) + offset) >> 8, 0xFFFFFFFF, rbuffer->bo);
-               r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_const_buffer);
-               break;
-       case PIPE_SHADER_FRAGMENT:
-               rctx->ps_const_buffer.nregs = 0;
-               r600_pipe_state_add_reg(&rctx->ps_const_buffer,
-                                       R_028140_ALU_CONST_BUFFER_SIZE_PS_0,
-                                       ALIGN_DIVUP(buffer->width0 >> 4, 16),
-                                       0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(&rctx->ps_const_buffer,
-                                       R_028940_ALU_CONST_CACHE_PS_0,
-                                       (r600_bo_offset(rbuffer->bo) + offset) >> 8, 0xFFFFFFFF, rbuffer->bo);
-               r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_const_buffer);
-               break;
-       default:
-               R600_ERR("unsupported %d\n", shader);
-               return;
-       }
-}
-
 void evergreen_init_state_functions(struct r600_pipe_context *rctx)
 {
        rctx->context.create_blend_state = evergreen_create_blend_state;
@@ -909,7 +902,7 @@ void evergreen_init_state_functions(struct r600_pipe_context *rctx)
        rctx->context.delete_vs_state = r600_delete_vs_shader;
        rctx->context.set_blend_color = evergreen_set_blend_color;
        rctx->context.set_clip_state = evergreen_set_clip_state;
-       rctx->context.set_constant_buffer = evergreen_set_constant_buffer;
+       rctx->context.set_constant_buffer = r600_set_constant_buffer;
        rctx->context.set_fragment_sampler_views = evergreen_set_ps_sampler_view;
        rctx->context.set_framebuffer_state = evergreen_set_framebuffer_state;
        rctx->context.set_polygon_stipple = evergreen_set_polygon_stipple;
@@ -921,6 +914,7 @@ void evergreen_init_state_functions(struct r600_pipe_context *rctx)
        rctx->context.set_vertex_sampler_views = evergreen_set_vs_sampler_view;
        rctx->context.set_viewport_state = evergreen_set_viewport_state;
        rctx->context.sampler_view_destroy = r600_sampler_view_destroy;
+       rctx->context.redefine_user_buffer = u_default_redefine_user_buffer;
 }
 
 void evergreen_init_config(struct r600_pipe_context *rctx)
@@ -1325,216 +1319,6 @@ void evergreen_polygon_offset_update(struct r600_pipe_context *rctx)
        }
 }
 
-static void evergreen_spi_update(struct r600_pipe_context *rctx)
-{
-       struct r600_pipe_shader *shader = rctx->ps_shader;
-       struct r600_pipe_state rstate;
-       struct r600_shader *rshader = &shader->shader;
-       unsigned i, tmp;
-
-       rstate.nregs = 0;
-       for (i = 0; i < rshader->ninput; i++) {
-               tmp = S_028644_SEMANTIC(r600_find_vs_semantic_index(&rctx->vs_shader->shader, rshader, i));
-               if (rshader->input[i].name == TGSI_SEMANTIC_COLOR ||
-                               rshader->input[i].name == TGSI_SEMANTIC_BCOLOR ||
-                               rshader->input[i].name == TGSI_SEMANTIC_POSITION) {
-                       tmp |= S_028644_FLAT_SHADE(rctx->flatshade);
-               }
-               if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC &&
-                       rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) {
-                       tmp |= S_028644_PT_SPRITE_TEX(1);
-               }
-               r600_pipe_state_add_reg(&rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL);
-       }
-       r600_context_pipe_state_set(&rctx->ctx, &rstate);
-}
-
-void evergreen_vertex_buffer_update(struct r600_pipe_context *rctx)
-{
-       struct r600_pipe_state *rstate;
-       struct r600_resource *rbuffer;
-       struct pipe_vertex_buffer *vertex_buffer;
-       unsigned i, offset;
-
-       /* we don't update until we know vertex elements */
-       if (rctx->vertex_elements == NULL || !rctx->nvertex_buffer)
-               return;
-
-       if (rctx->vertex_elements->incompatible_layout) {
-               /* translate rebind new vertex elements so
-                * return once translated
-                */
-               r600_begin_vertex_translate(rctx);
-               return;
-       }
-
-       if (rctx->any_user_vbs) {
-               r600_upload_user_buffers(rctx);
-               rctx->any_user_vbs = FALSE;
-       }
-
-       if (rctx->vertex_elements->vbuffer_need_offset) {
-               /* one resource per vertex elements */
-               rctx->nvs_resource = rctx->vertex_elements->count;
-       } else {
-               /* bind vertex buffer once */
-               rctx->nvs_resource = rctx->nvertex_buffer;
-       }
-
-       for (i = 0 ; i < rctx->nvs_resource; i++) {
-               rstate = &rctx->vs_resource[i];
-               rstate->id = R600_PIPE_STATE_RESOURCE;
-               rstate->nregs = 0;
-
-               if (rctx->vertex_elements->vbuffer_need_offset) {
-                       /* one resource per vertex elements */
-                       unsigned vbuffer_index;
-                       vbuffer_index = rctx->vertex_elements->elements[i].vertex_buffer_index;
-                       vertex_buffer = &rctx->vertex_buffer[vbuffer_index];
-                       rbuffer = (struct r600_resource*)vertex_buffer->buffer;
-                       offset = rctx->vertex_elements->vbuffer_offset[i];
-               } else {
-                       /* bind vertex buffer once */
-                       vertex_buffer = &rctx->vertex_buffer[i];
-                       rbuffer = (struct r600_resource*)vertex_buffer->buffer;
-                       offset = 0;
-               }
-               if (vertex_buffer == NULL || rbuffer == NULL)
-                       continue;
-               offset += vertex_buffer->buffer_offset + r600_bo_offset(rbuffer->bo);
-
-               r600_pipe_state_add_reg(rstate, R_030000_RESOURCE0_WORD0,
-                                       offset, 0xFFFFFFFF, rbuffer->bo);
-               r600_pipe_state_add_reg(rstate, R_030004_RESOURCE0_WORD1,
-                                       rbuffer->bo_size - offset - 1, 0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(rstate, R_030008_RESOURCE0_WORD2,
-                                       S_030008_STRIDE(vertex_buffer->stride),
-                                       0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(rstate, R_03000C_RESOURCE0_WORD3,
-                                       S_03000C_DST_SEL_X(V_03000C_SQ_SEL_X) |
-                                       S_03000C_DST_SEL_Y(V_03000C_SQ_SEL_Y) |
-                                       S_03000C_DST_SEL_Z(V_03000C_SQ_SEL_Z) |
-                                       S_03000C_DST_SEL_W(V_03000C_SQ_SEL_W),
-                                       0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(rstate, R_030010_RESOURCE0_WORD4,
-                                       0x00000000, 0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(rstate, R_030014_RESOURCE0_WORD5,
-                                       0x00000000, 0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(rstate, R_030018_RESOURCE0_WORD6,
-                                       0x00000000, 0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(rstate, R_03001C_RESOURCE0_WORD7,
-                                       0xC0000000, 0xFFFFFFFF, NULL);
-               evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, rstate, i);
-       }
-}
-
-int r600_conv_pipe_prim(unsigned pprim, unsigned *prim);
-void evergreen_draw(struct pipe_context *ctx, const struct pipe_draw_info *info)
-{
-       struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
-       struct r600_resource *rbuffer;
-       u32 vgt_dma_index_type, vgt_draw_initiator, mask;
-       struct r600_draw rdraw;
-       struct r600_pipe_state vgt;
-       struct r600_drawl draw;
-       unsigned prim;
-
-       memset(&draw, 0, sizeof(struct r600_drawl));
-       draw.ctx = ctx;
-       draw.mode = info->mode;
-       draw.start = info->start;
-       draw.count = info->count;
-       if (info->indexed && rctx->index_buffer.buffer) {
-               draw.start += rctx->index_buffer.offset / rctx->index_buffer.index_size;
-               draw.min_index = info->min_index;
-               draw.max_index = info->max_index;
-               draw.index_bias = info->index_bias;
-
-               r600_translate_index_buffer(rctx, &rctx->index_buffer.buffer,
-                                           &rctx->index_buffer.index_size,
-                                           &draw.start,
-                                           info->count);
-
-               draw.index_size = rctx->index_buffer.index_size;
-               pipe_resource_reference(&draw.index_buffer, rctx->index_buffer.buffer);
-               draw.index_buffer_offset = draw.start * draw.index_size;
-               draw.start = 0;
-               r600_upload_index_buffer(rctx, &draw);
-       } else {
-               draw.index_size = 0;
-               draw.index_buffer = NULL;
-               draw.min_index = info->min_index;
-               draw.max_index = info->max_index;
-               draw.index_bias = info->start;
-       }
-
-       switch (draw.index_size) {
-       case 2:
-               vgt_draw_initiator = 0;
-               vgt_dma_index_type = 0;
-               break;
-       case 4:
-               vgt_draw_initiator = 0;
-               vgt_dma_index_type = 1;
-               break;
-       case 0:
-               vgt_draw_initiator = 2;
-               vgt_dma_index_type = 0;
-               break;
-       default:
-               R600_ERR("unsupported index size %d\n", draw.index_size);
-               return;
-       }
-       if (r600_conv_pipe_prim(draw.mode, &prim))
-               return;
-       if (unlikely(rctx->ps_shader == NULL)) {
-               R600_ERR("missing vertex shader\n");
-               return;
-       }
-       if (unlikely(rctx->vs_shader == NULL)) {
-               R600_ERR("missing vertex shader\n");
-               return;
-       }
-       /* there should be enough input */
-       if (rctx->vertex_elements->count < rctx->vs_shader->shader.bc.nresource) {
-               R600_ERR("%d resources provided, expecting %d\n",
-                       rctx->vertex_elements->count, rctx->vs_shader->shader.bc.nresource);
-               return;
-       }
-
-       evergreen_spi_update(rctx);
-
-       mask = 0;
-       for (int i = 0; i < rctx->framebuffer.nr_cbufs; i++) {
-               mask |= (0xF << (i * 4));
-       }
-
-       vgt.id = R600_PIPE_STATE_VGT;
-       vgt.nregs = 0;
-       r600_pipe_state_add_reg(&vgt, R_008958_VGT_PRIMITIVE_TYPE, prim, 0xFFFFFFFF, NULL);
-       r600_pipe_state_add_reg(&vgt, R_028408_VGT_INDX_OFFSET, draw.index_bias, 0xFFFFFFFF, NULL);
-       r600_pipe_state_add_reg(&vgt, R_028238_CB_TARGET_MASK, rctx->cb_target_mask & mask, 0xFFFFFFFF, NULL);
-       r600_pipe_state_add_reg(&vgt, R_028400_VGT_MAX_VTX_INDX, draw.max_index, 0xFFFFFFFF, NULL);
-       r600_pipe_state_add_reg(&vgt, R_028404_VGT_MIN_VTX_INDX, draw.min_index, 0xFFFFFFFF, NULL);
-       r600_pipe_state_add_reg(&vgt, R_03CFF0_SQ_VTX_BASE_VTX_LOC, 0, 0xFFFFFFFF, NULL);
-       r600_pipe_state_add_reg(&vgt, R_03CFF4_SQ_VTX_START_INST_LOC, 0, 0xFFFFFFFF, NULL);
-       r600_context_pipe_state_set(&rctx->ctx, &vgt);
-
-       rdraw.vgt_num_indices = draw.count;
-       rdraw.vgt_num_instances = 1;
-       rdraw.vgt_index_type = vgt_dma_index_type;
-       rdraw.vgt_draw_initiator = vgt_draw_initiator;
-       rdraw.indices = NULL;
-       if (draw.index_buffer) {
-               rbuffer = (struct r600_resource*)draw.index_buffer;
-               rdraw.indices = rbuffer->bo;
-               rdraw.indices_bo_offset = draw.index_buffer_offset;
-       }
-       evergreen_context_draw(&rctx->ctx, &rdraw);
-
-       pipe_resource_reference(&draw.index_buffer, NULL);
-}
-
 void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shader)
 {
        struct r600_pipe_state *rstate = &shader->rstate;
@@ -1733,3 +1517,31 @@ void *evergreen_create_db_flush_dsa(struct r600_pipe_context *rctx)
                                S_028000_COPY_CENTROID(1), NULL);
        return rstate;
 }
+
+void evergreen_pipe_set_buffer_resource(struct r600_pipe_context *rctx,
+                                       struct r600_pipe_state *rstate,
+                                       struct r600_resource *rbuffer,
+                                       unsigned offset, unsigned stride)
+{
+       r600_pipe_state_add_reg(rstate, R_030000_RESOURCE0_WORD0,
+                               offset, 0xFFFFFFFF, rbuffer->bo);
+       r600_pipe_state_add_reg(rstate, R_030004_RESOURCE0_WORD1,
+                               rbuffer->bo_size - offset - 1, 0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(rstate, R_030008_RESOURCE0_WORD2,
+                               S_030008_STRIDE(stride),
+                               0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(rstate, R_03000C_RESOURCE0_WORD3,
+                               S_03000C_DST_SEL_X(V_03000C_SQ_SEL_X) |
+                               S_03000C_DST_SEL_Y(V_03000C_SQ_SEL_Y) |
+                               S_03000C_DST_SEL_Z(V_03000C_SQ_SEL_Z) |
+                               S_03000C_DST_SEL_W(V_03000C_SQ_SEL_W),
+                               0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(rstate, R_030010_RESOURCE0_WORD4,
+                               0x00000000, 0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(rstate, R_030014_RESOURCE0_WORD5,
+                               0x00000000, 0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(rstate, R_030018_RESOURCE0_WORD6,
+                               0x00000000, 0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(rstate, R_03001C_RESOURCE0_WORD7,
+                               0xC0000000, 0xFFFFFFFF, NULL);
+}
index e09e02ca000bd8daed0551df666717f93206d9c1..f0a1ee0cd02e0abb27d264d2412ad7170ac99429 100644 (file)
 #define   S_028C70_SOURCE_FORMAT(x)                    (((x) & 0x3) << 24)
 #define   G_028C70_SOURCE_FORMAT(x)                    (((x) >> 24) & 0x3)
 #define   C_028C70_SOURCE_FORMAT                       0xFCFFFFFF
+#define     V_028C70_EXPORT_4C_32BPC                   0x0
+#define     V_028C70_EXPORT_4C_16BPC                   0x1
+#define     V_028C70_EXPORT_2C_32BPC                   0x2 /* Do not use */
 #define   S_028C70_RAT(x)                              (((x) & 0x1) << 26)
 #define   G_028C70_RAT(x)                              (((x) >> 26) & 0x1)
 #define   C_028C70_RAT                                 0xFBFFFFFF
 #define   C_028800_STENCILZFAIL_BF                     0x1FFFFFFF
 
 #define R_028808_CB_COLOR_CONTROL                    0x028808
-#define   S_028808_FOG_ENABLE(x)                       (((x) & 0x1) << 0)
-#define   G_028808_FOG_ENABLE(x)                       (((x) >> 0) & 0x1)
-#define   C_028808_FOG_ENABLE                          0xFFFFFFFE
-#define   S_028808_MULTIWRITE_ENABLE(x)                (((x) & 0x1) << 1)
-#define   G_028808_MULTIWRITE_ENABLE(x)                (((x) >> 1) & 0x1)
-#define   C_028808_MULTIWRITE_ENABLE                   0xFFFFFFFD
-#define   S_028808_DITHER_ENABLE(x)                    (((x) & 0x1) << 2)
-#define   G_028808_DITHER_ENABLE(x)                    (((x) >> 2) & 0x1)
-#define   C_028808_DITHER_ENABLE                       0xFFFFFFFB
 #define   S_028808_DEGAMMA_ENABLE(x)                   (((x) & 0x1) << 3)
 #define   G_028808_DEGAMMA_ENABLE(x)                   (((x) >> 3) & 0x1)
 #define   C_028808_DEGAMMA_ENABLE                      0xFFFFFFF7
 #define     V_030000_SQ_TEX_DIM_2D_ARRAY               0x00000005
 #define     V_030000_SQ_TEX_DIM_2D_MSAA                0x00000006
 #define     V_030000_SQ_TEX_DIM_2D_ARRAY_MSAA          0x00000007
+#define   S_030000_NON_DISP_TILING_ORDER(x)            (((x) & 0x1) << 5)
+#define   G_030000_NON_DISP_TILING_ORDER(x)            (((x) >> 5) & 0x1)
+#define   C_030000_NON_DISP_TILING_ORDER               0xFFFFFFDF
 #define   S_030000_PITCH(x)                            (((x) & 0xFFF) << 6)
 #define   G_030000_PITCH(x)                            (((x) >> 6) & 0xFFF)
 #define   C_030000_PITCH                               0xFFFC003F
index a852bef6156bfc4f215a37520f469843b6580d99..64c52bca795a248bed777e55002796d733413fee 100644 (file)
@@ -113,6 +113,7 @@ struct r600_tiling_info {
 enum radeon_family r600_get_family(struct radeon *rw);
 enum chip_class r600_get_family_class(struct radeon *radeon);
 struct r600_tiling_info *r600_get_tiling_info(struct radeon *radeon);
+unsigned r600_get_clock_crystal_freq(struct radeon *radeon);
 
 /* r600_bo.c */
 struct r600_bo;
@@ -249,6 +250,7 @@ struct r600_context {
        struct list_head        query_list;
        unsigned                num_query_running;
        struct list_head        fenced_bo;
+       unsigned                max_db; /* for OQ */
 };
 
 struct r600_draw {
index f4ff2fc3d43dc04fa4439c75bb32b969c1155bf3..1393df8875730e162231ae5adec6c6ffd42009de 100644 (file)
@@ -50,6 +50,7 @@ static inline unsigned int r600_bc_get_num_operands(struct r600_bc *bc, struct r
                case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP:
                        return 0;
                case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD:
+               case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD_INT:
                case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLE:
                case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT:
                case V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGE:
@@ -97,6 +98,7 @@ static inline unsigned int r600_bc_get_num_operands(struct r600_bc *bc, struct r
                case EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP:
                        return 0;
                case EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD:
+               case EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD_INT:
                case EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLE:
                case EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGT:
                case EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_KILLGE:
@@ -288,6 +290,31 @@ int r600_bc_add_output(struct r600_bc *bc, const struct r600_bc_output *output)
 {
        int r;
 
+       if (bc->cf_last && bc->cf_last->inst == BC_INST(bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT) &&
+               output->type == bc->cf_last->output.type &&
+               output->elem_size == bc->cf_last->output.elem_size &&
+               output->swizzle_x == bc->cf_last->output.swizzle_x &&
+               output->swizzle_y == bc->cf_last->output.swizzle_y &&
+               output->swizzle_z == bc->cf_last->output.swizzle_z &&
+               output->swizzle_w == bc->cf_last->output.swizzle_w &&
+               (output->burst_count + bc->cf_last->output.burst_count) <= 16) {
+
+               if ((output->gpr + output->burst_count) == bc->cf_last->output.gpr &&
+                       (output->array_base + output->burst_count) == bc->cf_last->output.array_base) {
+
+                       bc->cf_last->output.gpr = output->gpr;
+                       bc->cf_last->output.array_base = output->array_base;
+                       bc->cf_last->output.burst_count += output->burst_count;
+                       return 0;
+
+               } else if (output->gpr == (bc->cf_last->output.gpr + bc->cf_last->output.burst_count) &&
+                       output->array_base == (bc->cf_last->output.array_base + bc->cf_last->output.burst_count)) {
+
+                       bc->cf_last->output.burst_count += output->burst_count;
+                       return 0;
+               }
+       }
+
        r = r600_bc_add_cf(bc);
        if (r)
                return r;
@@ -418,6 +445,20 @@ static int is_alu_reduction_inst(struct r600_bc *bc, struct r600_bc_alu *alu)
        }
 }
 
+static int is_alu_cube_inst(struct r600_bc *bc, struct r600_bc_alu *alu)
+{
+       switch (bc->chiprev) {
+       case CHIPREV_R600:
+       case CHIPREV_R700:
+               return !alu->is_op3 &&
+                       alu->inst == V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_CUBE;
+       case CHIPREV_EVERGREEN:
+       default:
+               return !alu->is_op3 &&
+                       alu->inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_CUBE;
+       }
+}
+
 static int is_alu_mova_inst(struct r600_bc *bc, struct r600_bc_alu *alu)
 {
        switch (bc->chiprev) {
@@ -480,9 +521,9 @@ static int is_alu_trans_unit_inst(struct r600_bc *bc, struct r600_bc_alu *alu)
        case CHIPREV_EVERGREEN:
        default:
                if (!alu->is_op3)
+                       /* Note that FLT_TO_INT* instructions are vector instructions
+                        * on Evergreen, despite what the documentation says. */
                        return alu->inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ASHR_INT ||
-                               alu->inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_INT ||
-                               alu->inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_INT_FLOOR ||
                                alu->inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_INT_TO_FLT ||
                                alu->inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LSHL_INT ||
                                alu->inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LSHR_INT ||
@@ -563,7 +604,7 @@ struct alu_bank_swizzle {
        int     hw_cfile_elem[4];
 };
 
-const unsigned cycle_for_bank_swizzle_vec[][3] = {
+static const unsigned cycle_for_bank_swizzle_vec[][3] = {
        [SQ_ALU_VEC_012] = { 0, 1, 2 },
        [SQ_ALU_VEC_021] = { 0, 2, 1 },
        [SQ_ALU_VEC_120] = { 1, 2, 0 },
@@ -572,7 +613,7 @@ const unsigned cycle_for_bank_swizzle_vec[][3] = {
        [SQ_ALU_VEC_210] = { 2, 1, 0 }
 };
 
-const unsigned cycle_for_bank_swizzle_scl[][3] = {
+static const unsigned cycle_for_bank_swizzle_scl[][3] = {
        [SQ_ALU_SCL_210] = { 2, 1, 0 },
        [SQ_ALU_SCL_122] = { 1, 2, 2 },
        [SQ_ALU_SCL_212] = { 2, 1, 2 },
@@ -785,7 +826,8 @@ static int replace_gpr_with_pv_ps(struct r600_bc *bc,
        for (i = 0; i < 5; ++i) {
                if(prev[i] && prev[i]->dst.write && !prev[i]->dst.rel) {
                        gpr[i] = prev[i]->dst.sel;
-                       if (is_alu_reduction_inst(bc, prev[i]))
+                       /* cube writes more than PV.X */
+                       if (!is_alu_cube_inst(bc, prev[i]) && is_alu_reduction_inst(bc, prev[i]))
                                chan[i] = 0;
                        else
                                chan[i] = prev[i]->dst.chan;
@@ -865,7 +907,7 @@ static int r600_bc_alu_nliterals(struct r600_bc *bc, struct r600_bc_alu *alu,
 
        for (i = 0; i < num_src; ++i) {
                if (alu->src[i].sel == V_SQ_ALU_SRC_LITERAL) {
-                       uint32_t value = alu->src[i].value[alu->src[i].chan];
+                       uint32_t value = alu->src[i].value;
                        unsigned found = 0;
                        for (j = 0; j < *nliteral; ++j) {
                                if (literal[j] == value) {
@@ -892,7 +934,7 @@ static void r600_bc_alu_adjust_literals(struct r600_bc *bc,
 
        for (i = 0; i < num_src; ++i) {
                if (alu->src[i].sel == V_SQ_ALU_SRC_LITERAL) {
-                       uint32_t value = alu->src[i].value[alu->src[i].chan];
+                       uint32_t value = alu->src[i].value;
                        for (j = 0; j < nliteral; ++j) {
                                if (literal[j] == value) {
                                        alu->src[i].chan = j;
@@ -1195,8 +1237,7 @@ int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int
                        bc->ngpr = nalu->src[i].sel + 1;
                }
                if (nalu->src[i].sel == V_SQ_ALU_SRC_LITERAL)
-                       r600_bc_special_constants(
-                               nalu->src[i].value[nalu->src[i].chan],
+                       r600_bc_special_constants(nalu->src[i].value,
                                &nalu->src[i].sel, &nalu->src[i].neg);
        }
        if (nalu->dst.sel >= bc->ngpr) {
@@ -1308,6 +1349,18 @@ int r600_bc_add_tex(struct r600_bc *bc, const struct r600_bc_tex *tex)
                return -ENOMEM;
        memcpy(ntex, tex, sizeof(struct r600_bc_tex));
 
+       /* we can't fetch data und use it as texture lookup address in the same TEX clause */
+       if (bc->cf_last != NULL &&
+               bc->cf_last->inst == V_SQ_CF_WORD1_SQ_CF_INST_TEX) {
+               struct r600_bc_tex *ttex;
+               LIST_FOR_EACH_ENTRY(ttex, &bc->cf_last->tex, list) {
+                       if (ttex->dst_gpr == ntex->src_gpr) {
+                               bc->force_add_cf = 1;
+                               break;
+                       }
+               }
+       }
+
        /* cf can contains only alu or only vtx or only tex */
        if (bc->cf_last == NULL ||
                bc->cf_last->inst != V_SQ_CF_WORD1_SQ_CF_INST_TEX ||
@@ -1374,6 +1427,7 @@ static int r600_bc_vtx_build(struct r600_bc *bc, struct r600_bc_vtx *vtx, unsign
                }
        }
        bc->bytecode[id++] = S_SQ_VTX_WORD0_BUFFER_ID(vtx->buffer_id + fetch_resource_start) |
+                       S_SQ_VTX_WORD0_FETCH_TYPE(vtx->fetch_type) |
                        S_SQ_VTX_WORD0_SRC_GPR(vtx->src_gpr) |
                        S_SQ_VTX_WORD0_SRC_SEL_X(vtx->src_sel_x) |
                        S_SQ_VTX_WORD0_MEGA_FETCH_COUNT(vtx->mega_fetch_count);
@@ -2674,18 +2728,73 @@ void r600_bc_dump(struct r600_bc *bc)
                }
 
                LIST_FOR_EACH_ENTRY(tex, &cf->tex, list) {
-                       //TODO
+                       fprintf(stderr, "%04d %08X   ", id, bc->bytecode[id]);
+                       fprintf(stderr, "INST:%d ", tex->inst);
+                       fprintf(stderr, "RESOURCE_ID:%d ", tex->resource_id);
+                       fprintf(stderr, "SRC(GPR:%d ", tex->src_gpr);
+                       fprintf(stderr, "REL:%d)\n", tex->src_rel);
+                       id++;
+                       fprintf(stderr, "%04d %08X   ", id, bc->bytecode[id]);
+                       fprintf(stderr, "DST(GPR:%d ", tex->dst_gpr);
+                       fprintf(stderr, "REL:%d ", tex->dst_rel);
+                       fprintf(stderr, "SEL_X:%d ", tex->dst_sel_x);
+                       fprintf(stderr, "SEL_Y:%d ", tex->dst_sel_y);
+                       fprintf(stderr, "SEL_Z:%d ", tex->dst_sel_z);
+                       fprintf(stderr, "SEL_W:%d) ", tex->dst_sel_w);
+                       fprintf(stderr, "LOD_BIAS:%d ", tex->lod_bias);
+                       fprintf(stderr, "COORD_TYPE_X:%d ", tex->coord_type_x);
+                       fprintf(stderr, "COORD_TYPE_Y:%d ", tex->coord_type_y);
+                       fprintf(stderr, "COORD_TYPE_Z:%d ", tex->coord_type_z);
+                       fprintf(stderr, "COORD_TYPE_W:%d\n", tex->coord_type_w);
+                       id++;
+                       fprintf(stderr, "%04d %08X   ", id, bc->bytecode[id]);
+                       fprintf(stderr, "OFFSET_X:%d ", tex->offset_x);
+                       fprintf(stderr, "OFFSET_Y:%d ", tex->offset_y);
+                       fprintf(stderr, "OFFSET_Z:%d ", tex->offset_z);
+                       fprintf(stderr, "SAMPLER_ID:%d ", tex->sampler_id);
+                       fprintf(stderr, "SRC(SEL_X:%d ", tex->src_sel_x);
+                       fprintf(stderr, "SEL_Y:%d ", tex->src_sel_y);
+                       fprintf(stderr, "SEL_Z:%d ", tex->src_sel_z);
+                       fprintf(stderr, "SEL_W:%d)\n", tex->src_sel_w);
+                       id++;
+                       fprintf(stderr, "%04d %08X   \n", id, bc->bytecode[id]);
+                       id++;
                }
 
                LIST_FOR_EACH_ENTRY(vtx, &cf->vtx, list) {
+                       fprintf(stderr, "%04d %08X   ", id, bc->bytecode[id]);
+                       fprintf(stderr, "INST:%d ", vtx->inst);
+                       fprintf(stderr, "FETCH_TYPE:%d ", vtx->fetch_type);
+                       fprintf(stderr, "BUFFER_ID:%d\n", vtx->buffer_id);
+                       id++;
+                       /* This assumes that no semantic fetches exist */
+                       fprintf(stderr, "%04d %08X   ", id, bc->bytecode[id]);
+                       fprintf(stderr, "SRC(GPR:%d ", vtx->src_gpr);
+                       fprintf(stderr, "SEL_X:%d) ", vtx->src_sel_x);
+                       fprintf(stderr, "MEGA_FETCH_COUNT:%d ", vtx->mega_fetch_count);
+                       fprintf(stderr, "DST(GPR:%d ", vtx->dst_gpr);
+                       fprintf(stderr, "SEL_X:%d ", vtx->dst_sel_x);
+                       fprintf(stderr, "SEL_Y:%d ", vtx->dst_sel_y);
+                       fprintf(stderr, "SEL_Z:%d ", vtx->dst_sel_z);
+                       fprintf(stderr, "SEL_W:%d) ", vtx->dst_sel_w);
+                       fprintf(stderr, "USE_CONST_FIELDS:%d ", vtx->use_const_fields);
+                       fprintf(stderr, "DATA_FORMAT:%d ", vtx->data_format);
+                       fprintf(stderr, "NUM_FORMAT_ALL:%d ", vtx->num_format_all);
+                       fprintf(stderr, "FORMAT_COMP_ALL:%d ", vtx->format_comp_all);
+                       fprintf(stderr, "SRF_MODE_ALL:%d\n", vtx->srf_mode_all);
+                       id++;
+                       fprintf(stderr, "%04d %08X   \n", id, bc->bytecode[id]);
                        //TODO
+                       id++;
+                       fprintf(stderr, "%04d %08X   \n", id, bc->bytecode[id]);
+                       id++;
                }
        }
 
        fprintf(stderr, "--------------------------------------\n");
 }
 
-void r600_cf_vtx(struct r600_vertex_element *ve, u32 *bytecode, unsigned count)
+static void r600_cf_vtx(struct r600_vertex_element *ve, u32 *bytecode, unsigned count)
 {
        struct r600_pipe_state *rstate;
        unsigned i = 0;
@@ -2721,42 +2830,6 @@ void r600_cf_vtx(struct r600_vertex_element *ve, u32 *bytecode, unsigned count)
                                0xFFFFFFFF, ve->fetch_shader);
 }
 
-void r600_cf_vtx_tc(struct r600_vertex_element *ve, u32 *bytecode, unsigned count)
-{
-       struct r600_pipe_state *rstate;
-       unsigned i = 0;
-
-       if (count > 8) {
-               bytecode[i++] = S_SQ_CF_WORD0_ADDR(8 >> 1);
-               bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC) |
-                                               S_SQ_CF_WORD1_BARRIER(1) |
-                                               S_SQ_CF_WORD1_COUNT(8 - 1);
-               bytecode[i++] = S_SQ_CF_WORD0_ADDR(40 >> 1);
-               bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC) |
-                                               S_SQ_CF_WORD1_BARRIER(1) |
-                                               S_SQ_CF_WORD1_COUNT((count - 8) - 1);
-       } else {
-               bytecode[i++] = S_SQ_CF_WORD0_ADDR(8 >> 1);
-               bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_VTX_TC) |
-                                               S_SQ_CF_WORD1_BARRIER(1) |
-                                               S_SQ_CF_WORD1_COUNT(count - 1);
-       }
-       bytecode[i++] = S_SQ_CF_WORD0_ADDR(0);
-       bytecode[i++] = S_SQ_CF_WORD1_CF_INST(V_SQ_CF_WORD1_SQ_CF_INST_RETURN) |
-                       S_SQ_CF_WORD1_BARRIER(1);
-
-       rstate = &ve->rstate;
-       rstate->id = R600_PIPE_STATE_FETCH_SHADER;
-       rstate->nregs = 0;
-       r600_pipe_state_add_reg(rstate, R_0288A4_SQ_PGM_RESOURCES_FS,
-                               0x00000000, 0xFFFFFFFF, NULL);
-       r600_pipe_state_add_reg(rstate, R_0288DC_SQ_PGM_CF_OFFSET_FS,
-                               0x00000000, 0xFFFFFFFF, NULL);
-       r600_pipe_state_add_reg(rstate, R_028894_SQ_PGM_START_FS,
-                               r600_bo_offset(ve->fetch_shader) >> 8,
-                               0xFFFFFFFF, ve->fetch_shader);
-}
-
 static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format,
                                unsigned *num_format, unsigned *format_comp)
 {
@@ -2780,7 +2853,7 @@ static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format,
        }
 
        switch (desc->channel[i].type) {
-               /* Half-floats, floats, doubles */
+       /* Half-floats, floats, ints */
        case UTIL_FORMAT_TYPE_FLOAT:
                switch (desc->channel[i].size) {
                case 16:
@@ -2792,8 +2865,6 @@ static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format,
                                *format = FMT_16_16_FLOAT;
                                break;
                        case 3:
-                               *format = FMT_16_16_16_FLOAT;
-                               break;
                        case 4:
                                *format = FMT_16_16_16_16_FLOAT;
                                break;
@@ -2833,8 +2904,6 @@ static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format,
                                *format = FMT_8_8;
                                break;
                        case 3:
-                       //      *format = FMT_8_8_8; /* fails piglit draw-vertices test */
-                       //      break;
                        case 4:
                                *format = FMT_8_8_8_8;
                                break;
@@ -2849,8 +2918,6 @@ static void r600_vertex_data_type(enum pipe_format pformat, unsigned *format,
                                *format = FMT_16_16;
                                break;
                        case 3:
-                       //      *format = FMT_16_16_16; /* fails piglit draw-vertices test */
-                       //      break;
                        case 4:
                                *format = FMT_16_16_16_16;
                                break;
@@ -2938,10 +3005,10 @@ int r600_vertex_elements_build_fetch_shader(struct r600_pipe_context *rctx, stru
 
        for (i = 0; i < ve->count; i++) {
                unsigned vbuffer_index;
-               r600_vertex_data_type(ve->hw_format[i], &format, &num_format, &format_comp);
-               desc = util_format_description(ve->hw_format[i]);
+               r600_vertex_data_type(ve->elements[i].src_format, &format, &num_format, &format_comp);
+               desc = util_format_description(ve->elements[i].src_format);
                if (desc == NULL) {
-                       R600_ERR("unknown format %d\n", ve->hw_format[i]);
+                       R600_ERR("unknown format %d\n", ve->elements[i].src_format);
                        r600_bo_reference(rctx->radeon, &ve->fetch_shader, NULL);
                        return -EINVAL;
                }
index 519245f3af258fd947c8e7b552de4ee0a7f7aebd..453c29790c158b68309f7b73b64a983ddef60aa7 100644 (file)
@@ -34,7 +34,7 @@ struct r600_bc_alu_src {
        unsigned                        neg;
        unsigned                        abs;
        unsigned                        rel;
-       u32                             *value;
+       uint32_t                        value;
 };
 
 struct r600_bc_alu_dst {
@@ -201,8 +201,6 @@ 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);
 void r600_bc_special_constants(u32 value, unsigned *sel, unsigned *neg);
 void r600_bc_dump(struct r600_bc *bc);
-void r600_cf_vtx(struct r600_vertex_element *ve, u32 *bytecode, unsigned count);
-void r600_cf_vtx_tc(struct r600_vertex_element *ve, u32 *bytecode, unsigned count);
 
 int r600_vertex_elements_build_fetch_shader(struct r600_pipe_context *rctx, struct r600_vertex_element *ve);
 
index b9ec9592e357f9dac2ed5709bbb0003200ff6d37..9865ea17ae52a91e8c109b1b9de93d2d683e3fc6 100644 (file)
@@ -36,6 +36,7 @@ static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op
 {
        struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
 
+       rctx->blit = true;
        r600_context_queries_suspend(&rctx->ctx);
 
        util_blitter_save_blend(rctx->blitter, rctx->states[R600_PIPE_STATE_BLEND]);
@@ -53,9 +54,9 @@ static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op
        if (rctx->states[R600_PIPE_STATE_CLIP]) {
                util_blitter_save_clip(rctx->blitter, &rctx->clip);
        }
-       util_blitter_save_vertex_buffers(rctx->blitter, rctx->nvertex_buffer, rctx->vertex_buffer);
-
-       rctx->vertex_elements = NULL;
+       util_blitter_save_vertex_buffers(rctx->blitter,
+                                        rctx->vbuf_mgr->nr_vertex_buffers,
+                                        rctx->vbuf_mgr->vertex_buffer);
 
        if (op & (R600_CLEAR_SURFACE | R600_COPY))
                util_blitter_save_framebuffer(rctx->blitter, &rctx->framebuffer);
@@ -76,6 +77,7 @@ static void r600_blitter_end(struct pipe_context *ctx)
 {
        struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
        r600_context_queries_resume(&rctx->ctx);
+       rctx->blit = false;
 }
 
 void r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_texture *texture)
@@ -84,13 +86,17 @@ void r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_t
        struct pipe_surface *zsurf, *cbsurf, surf_tmpl;
        int level = 0;
        float depth = 1.0f;
-       surf_tmpl.format = texture->resource.base.b.format;
+
+       if (!texture->dirty_db)
+               return;
+
+       surf_tmpl.format = texture->resource.b.b.b.format;
        surf_tmpl.u.tex.level = level;
        surf_tmpl.u.tex.first_layer = 0;
        surf_tmpl.u.tex.last_layer = 0;
        surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL;
 
-       zsurf = ctx->create_surface(ctx, &texture->resource.base.b, &surf_tmpl);
+       zsurf = ctx->create_surface(ctx, &texture->resource.b.b.b, &surf_tmpl);
 
        surf_tmpl.format = ((struct pipe_resource*)texture->flushed_depth_texture)->format;
        surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
@@ -107,6 +113,48 @@ void r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_t
 
        pipe_surface_reference(&zsurf, NULL);
        pipe_surface_reference(&cbsurf, NULL);
+
+       texture->dirty_db = FALSE;
+}
+
+void r600_flush_depth_textures(struct r600_pipe_context *rctx)
+{
+       unsigned int i;
+
+       if (rctx->blit) return;
+
+       /* FIXME: This handles fragment shader textures only. */
+
+       for (i = 0; i < rctx->ps_samplers.n_views; ++i) {
+               struct r600_pipe_sampler_view *view;
+               struct r600_resource_texture *tex;
+
+               view = rctx->ps_samplers.views[i];
+               if (!view) continue;
+
+               tex = (struct r600_resource_texture *)view->base.texture;
+               if (!tex->depth)
+                       continue;
+
+               if (tex->is_flushing_texture)
+                       continue;
+
+               r600_blit_uncompress_depth(&rctx->context, tex);
+       }
+
+       /* also check CB here */
+       for (i = 0; i < rctx->framebuffer.nr_cbufs; i++) {
+               struct r600_resource_texture *tex;
+               tex = (struct r600_resource_texture *)rctx->framebuffer.cbufs[i]->texture;
+
+               if (!tex->depth)
+                       continue;
+
+               if (tex->is_flushing_texture)
+                       continue;
+
+               r600_blit_uncompress_depth(&rctx->context, tex);
+       }
 }
 
 static void r600_clear(struct pipe_context *ctx, unsigned buffers,
@@ -171,6 +219,52 @@ static void r600_hw_copy_region(struct pipe_context *ctx,
        r600_blitter_end(ctx);
 }
 
+struct texture_orig_info {
+       unsigned format;
+       unsigned width0;
+       unsigned height0;
+};
+
+static void r600_s3tc_to_blittable(struct pipe_resource *tex,
+                                  unsigned level,
+                                  struct texture_orig_info *orig)
+{
+       struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex;
+       unsigned pixsize = util_format_get_blocksize(tex->format);
+       int new_format;
+       int new_height, new_width;
+
+       orig->format = tex->format;
+       orig->width0 = tex->width0;
+       orig->height0 = tex->height0;
+
+       if (pixsize == 8)
+               new_format = PIPE_FORMAT_R16G16B16A16_UNORM; /* 64-bit block */
+       else
+               new_format = PIPE_FORMAT_R32G32B32A32_UNORM; /* 128-bit block */
+
+       new_width = util_format_get_nblocksx(tex->format, orig->width0);
+       new_height = util_format_get_nblocksy(tex->format, orig->height0);
+
+       rtex->force_int_type = true;
+       tex->width0 = new_width;
+       tex->height0 = new_height;
+       tex->format = new_format;
+
+}
+
+static void r600_reset_blittable_to_s3tc(struct pipe_resource *tex,
+                                        unsigned level,
+                                        struct texture_orig_info *orig)
+{
+       struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex;
+       rtex->force_int_type = false;
+
+       tex->format = orig->format;
+       tex->width0 = orig->width0;
+       tex->height0 = orig->height0;
+}
+
 static void r600_resource_copy_region(struct pipe_context *ctx,
                                      struct pipe_resource *dst,
                                      unsigned dst_level,
@@ -179,15 +273,36 @@ static void r600_resource_copy_region(struct pipe_context *ctx,
                                      unsigned src_level,
                                      const struct pipe_box *src_box)
 {
-       boolean is_depth;
-       /* there is something wrong with depth resource copies at the moment so avoid them for now */
-       is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
-       if (is_depth)
-               util_resource_copy_region(ctx, dst, dst_level, dstx, dsty, dstz,
-                                         src, src_level, src_box);
-       else
-               r600_hw_copy_region(ctx, dst, dst_level, dstx, dsty, dstz,
-                                   src, src_level, src_box);
+       struct r600_resource_texture *rsrc = (struct r600_resource_texture*)src;
+       struct texture_orig_info orig_info[2];
+       boolean restore_orig[2];
+
+       if (rsrc->depth && !rsrc->is_flushing_texture)
+               r600_texture_depth_flush(ctx, src, FALSE);
+
+       restore_orig[0] = restore_orig[1] = FALSE;
+
+       if (util_format_is_s3tc(src->format)) {
+               r600_s3tc_to_blittable(src, src_level, &orig_info[0]);
+               restore_orig[0] = TRUE;
+       }
+
+       if (util_format_is_s3tc(dst->format)) {
+               r600_s3tc_to_blittable(dst, dst_level, &orig_info[1]);
+               restore_orig[1] = TRUE;
+               /* translate the dst box as well */
+               dstx = util_format_get_nblocksx(orig_info[1].format, dstx);
+               dsty = util_format_get_nblocksy(orig_info[1].format, dsty);
+       }
+
+       r600_hw_copy_region(ctx, dst, dst_level, dstx, dsty, dstz,
+                           src, src_level, src_box);
+
+       if (restore_orig[0])
+               r600_reset_blittable_to_s3tc(src, src_level, &orig_info[0]);
+
+       if (restore_orig[1])
+               r600_reset_blittable_to_s3tc(dst, dst_level, &orig_info[1]);
 }
 
 void r600_init_blit_functions(struct r600_pipe_context *rctx)
@@ -197,3 +312,19 @@ void r600_init_blit_functions(struct r600_pipe_context *rctx)
        rctx->context.clear_depth_stencil = r600_clear_depth_stencil;
        rctx->context.resource_copy_region = r600_resource_copy_region;
 }
+
+void r600_blit_push_depth(struct pipe_context *ctx, struct r600_resource_texture *texture)
+{
+       struct pipe_box sbox;
+
+       sbox.x = sbox.y = sbox.z = 0;
+       sbox.width = texture->resource.b.b.b.width0;
+       sbox.height = texture->resource.b.b.b.height0;
+       /* XXX that might be wrong */
+       sbox.depth = 1;
+
+       r600_hw_copy_region(ctx, (struct pipe_resource *)texture, 0,
+                           0, 0, 0,
+                           (struct pipe_resource *)texture->flushed_depth_texture, 0,
+                           &sbox);
+}
index 469c8195fe9b7a8739fa1512dabd8239366b599e..0c5d7133c7ac4677a5ece370c3dad60ac7c318a8 100644 (file)
 #include <util/u_math.h>
 #include <util/u_inlines.h>
 #include <util/u_memory.h>
+#include "util/u_upload_mgr.h"
+
 #include "state_tracker/drm_driver.h"
+
 #include <xf86drm.h>
 #include "radeon_drm.h"
+
 #include "r600.h"
 #include "r600_pipe.h"
 
-extern struct u_resource_vtbl r600_buffer_vtbl;
-
-
-struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
-                                        const struct pipe_resource *templ)
-{
-       struct r600_resource_buffer *rbuffer;
-       struct r600_bo *bo;
-       /* XXX We probably want a different alignment for buffers and textures. */
-       unsigned alignment = 4096;
-
-       rbuffer = CALLOC_STRUCT(r600_resource_buffer);
-       if (rbuffer == NULL)
-               return NULL;
-
-       rbuffer->magic = R600_BUFFER_MAGIC;
-       rbuffer->user_buffer = NULL;
-       rbuffer->r.base.b = *templ;
-       pipe_reference_init(&rbuffer->r.base.b.reference, 1);
-       rbuffer->r.base.b.screen = screen;
-       rbuffer->r.base.vtbl = &r600_buffer_vtbl;
-       rbuffer->r.size = rbuffer->r.base.b.width0;
-       rbuffer->r.bo_size = rbuffer->r.size;
-       rbuffer->uploaded = FALSE;
-       bo = r600_bo((struct radeon*)screen->winsys, rbuffer->r.base.b.width0, alignment, rbuffer->r.base.b.bind, rbuffer->r.base.b.usage);
-       if (bo == NULL) {
-               FREE(rbuffer);
-               return NULL;
-       }
-       rbuffer->r.bo = bo;
-       return &rbuffer->r.base.b;
-}
-
-struct pipe_resource *r600_user_buffer_create(struct pipe_screen *screen,
-                                             void *ptr, unsigned bytes,
-                                             unsigned bind)
-{
-       struct r600_resource_buffer *rbuffer;
-
-       rbuffer = CALLOC_STRUCT(r600_resource_buffer);
-       if (rbuffer == NULL)
-               return NULL;
-
-       rbuffer->magic = R600_BUFFER_MAGIC;
-       pipe_reference_init(&rbuffer->r.base.b.reference, 1);
-       rbuffer->r.base.vtbl = &r600_buffer_vtbl;
-       rbuffer->r.base.b.screen = screen;
-       rbuffer->r.base.b.target = PIPE_BUFFER;
-       rbuffer->r.base.b.format = PIPE_FORMAT_R8_UNORM;
-       rbuffer->r.base.b.usage = PIPE_USAGE_IMMUTABLE;
-       rbuffer->r.base.b.bind = bind;
-       rbuffer->r.base.b.width0 = bytes;
-       rbuffer->r.base.b.height0 = 1;
-       rbuffer->r.base.b.depth0 = 1;
-       rbuffer->r.base.b.array_size = 1;
-       rbuffer->r.base.b.flags = 0;
-       rbuffer->r.bo = NULL;
-       rbuffer->r.bo_size = 0;
-       rbuffer->user_buffer = ptr;
-       rbuffer->uploaded = FALSE;
-       return &rbuffer->r.base.b;
-}
-
 static void r600_buffer_destroy(struct pipe_screen *screen,
                                struct pipe_resource *buf)
 {
+       struct r600_screen *rscreen = (struct r600_screen*)screen;
        struct r600_resource_buffer *rbuffer = r600_buffer(buf);
 
        if (rbuffer->r.bo) {
                r600_bo_reference((struct radeon*)screen->winsys, &rbuffer->r.bo, NULL);
        }
        rbuffer->r.bo = NULL;
-       FREE(rbuffer);
+       util_slab_free(&rscreen->pool_buffers, rbuffer);
+}
+
+static unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context,
+                                               struct pipe_resource *buf,
+                                               unsigned level, int layer)
+{
+       /* FIXME */
+       return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+static struct pipe_transfer *r600_get_transfer(struct pipe_context *ctx,
+                                              struct pipe_resource *resource,
+                                              unsigned level,
+                                              unsigned usage,
+                                              const struct pipe_box *box)
+{
+       struct r600_pipe_context *rctx = (struct r600_pipe_context*)ctx;
+       struct pipe_transfer *transfer = util_slab_alloc(&rctx->pool_transfers);
+
+       transfer->resource = resource;
+       transfer->level = level;
+       transfer->usage = usage;
+       transfer->box = *box;
+       transfer->stride = 0;
+       transfer->layer_stride = 0;
+       transfer->data = NULL;
+
+       /* Note strides are zero, this is ok for buffers, but not for
+        * textures 2d & higher at least.
+        */
+       return transfer;
 }
 
 static void *r600_buffer_transfer_map(struct pipe_context *pipe,
@@ -117,8 +90,8 @@ static void *r600_buffer_transfer_map(struct pipe_context *pipe,
        int write = 0;
        uint8_t *data;
 
-       if (rbuffer->user_buffer)
-               return (uint8_t*)rbuffer->user_buffer + transfer->box.x;
+       if (rbuffer->r.b.user_ptr)
+               return (uint8_t*)rbuffer->r.b.user_ptr + transfer->box.x;
 
        if (transfer->usage & PIPE_TRANSFER_DONTBLOCK) {
                /* FIXME */
@@ -138,7 +111,7 @@ static void r600_buffer_transfer_unmap(struct pipe_context *pipe,
 {
        struct r600_resource_buffer *rbuffer = r600_buffer(transfer->resource);
 
-       if (rbuffer->user_buffer)
+       if (rbuffer->r.b.user_ptr)
                return;
 
        if (rbuffer->r.bo)
@@ -151,128 +124,163 @@ static void r600_buffer_transfer_flush_region(struct pipe_context *pipe,
 {
 }
 
-unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context,
-                                        struct pipe_resource *buf,
-                                        unsigned level, int layer)
+static void r600_transfer_destroy(struct pipe_context *ctx,
+                                 struct pipe_transfer *transfer)
 {
-       /* FIXME */
-       return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+       struct r600_pipe_context *rctx = (struct r600_pipe_context*)ctx;
+       util_slab_free(&rctx->pool_transfers, transfer);
 }
 
-struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen,
-                                             struct winsys_handle *whandle)
+static void r600_buffer_transfer_inline_write(struct pipe_context *pipe,
+                                              struct pipe_resource *resource,
+                                              unsigned level,
+                                              unsigned usage,
+                                              const struct pipe_box *box,
+                                              const void *data,
+                                              unsigned stride,
+                                              unsigned layer_stride)
 {
-       struct radeon *rw = (struct radeon*)screen->winsys;
-       struct r600_resource *rbuffer;
-       struct r600_bo *bo = NULL;
+       struct radeon *ws = (struct radeon*)pipe->winsys;
+       struct r600_resource_buffer *rbuffer = r600_buffer(resource);
+       uint8_t *map = NULL;
 
-       bo = r600_bo_handle(rw, whandle->handle, NULL);
-       if (bo == NULL) {
-               return NULL;
-       }
+       assert(rbuffer->r.b.user_ptr == NULL);
 
-       rbuffer = CALLOC_STRUCT(r600_resource);
-       if (rbuffer == NULL) {
-               r600_bo_reference(rw, &bo, NULL);
-               return NULL;
-       }
+       map = r600_bo_map(ws, rbuffer->r.bo,
+                         PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | usage,
+                         pipe);
 
-       pipe_reference_init(&rbuffer->base.b.reference, 1);
-       rbuffer->base.b.target = PIPE_BUFFER;
-       rbuffer->base.b.screen = screen;
-       rbuffer->base.vtbl = &r600_buffer_vtbl;
-       rbuffer->bo = bo;
-       return &rbuffer->base.b;
+       memcpy(map + box->x, data, box->width);
+
+       if (rbuffer->r.bo)
+               r600_bo_unmap(ws, rbuffer->r.bo);
 }
 
-struct u_resource_vtbl r600_buffer_vtbl =
+static const struct u_resource_vtbl r600_buffer_vtbl =
 {
        u_default_resource_get_handle,          /* get_handle */
        r600_buffer_destroy,                    /* resource_destroy */
        r600_buffer_is_referenced_by_cs,        /* is_buffer_referenced */
-       u_default_get_transfer,                 /* get_transfer */
-       u_default_transfer_destroy,             /* transfer_destroy */
+       r600_get_transfer,                      /* get_transfer */
+       r600_transfer_destroy,                  /* transfer_destroy */
        r600_buffer_transfer_map,               /* transfer_map */
        r600_buffer_transfer_flush_region,      /* transfer_flush_region */
        r600_buffer_transfer_unmap,             /* transfer_unmap */
-       u_default_transfer_inline_write         /* transfer_inline_write */
+       r600_buffer_transfer_inline_write       /* transfer_inline_write */
 };
 
-int r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw)
+struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
+                                        const struct pipe_resource *templ)
 {
-       if (r600_buffer_is_user_buffer(draw->index_buffer)) {
-               struct r600_resource_buffer *rbuffer = r600_buffer(draw->index_buffer);
-               unsigned upload_offset;
-               int ret = 0;
-
-               ret = r600_upload_buffer(rctx->rupload_vb,
-                                       draw->index_buffer_offset,
-                                       draw->count * draw->index_size,
-                                       rbuffer,
-                                       &upload_offset,
-                                       &rbuffer->r.bo_size,
-                                       &rbuffer->r.bo);
-               if (ret)
-                       return ret;
-               rbuffer->uploaded = TRUE;
-               draw->index_buffer_offset = upload_offset;
+       struct r600_screen *rscreen = (struct r600_screen*)screen;
+       struct r600_resource_buffer *rbuffer;
+       struct r600_bo *bo;
+       /* XXX We probably want a different alignment for buffers and textures. */
+       unsigned alignment = 4096;
+
+       rbuffer = util_slab_alloc(&rscreen->pool_buffers);
+
+       rbuffer->magic = R600_BUFFER_MAGIC;
+       rbuffer->r.b.b.b = *templ;
+       pipe_reference_init(&rbuffer->r.b.b.b.reference, 1);
+       rbuffer->r.b.b.b.screen = screen;
+       rbuffer->r.b.b.vtbl = &r600_buffer_vtbl;
+       rbuffer->r.b.user_ptr = NULL;
+       rbuffer->r.size = rbuffer->r.b.b.b.width0;
+       rbuffer->r.bo_size = rbuffer->r.size;
+
+       bo = r600_bo((struct radeon*)screen->winsys,
+                    rbuffer->r.b.b.b.width0,
+                    alignment, rbuffer->r.b.b.b.bind,
+                    rbuffer->r.b.b.b.usage);
+
+       if (bo == NULL) {
+               FREE(rbuffer);
+               return NULL;
        }
+       rbuffer->r.bo = bo;
+       return &rbuffer->r.b.b.b;
+}
+
+struct pipe_resource *r600_user_buffer_create(struct pipe_screen *screen,
+                                             void *ptr, unsigned bytes,
+                                             unsigned bind)
+{
+       struct r600_screen *rscreen = (struct r600_screen*)screen;
+       struct r600_resource_buffer *rbuffer;
 
-       return 0;
+       rbuffer = util_slab_alloc(&rscreen->pool_buffers);
+
+       rbuffer->magic = R600_BUFFER_MAGIC;
+       pipe_reference_init(&rbuffer->r.b.b.b.reference, 1);
+       rbuffer->r.b.b.vtbl = &r600_buffer_vtbl;
+       rbuffer->r.b.b.b.screen = screen;
+       rbuffer->r.b.b.b.target = PIPE_BUFFER;
+       rbuffer->r.b.b.b.format = PIPE_FORMAT_R8_UNORM;
+       rbuffer->r.b.b.b.usage = PIPE_USAGE_IMMUTABLE;
+       rbuffer->r.b.b.b.bind = bind;
+       rbuffer->r.b.b.b.width0 = bytes;
+       rbuffer->r.b.b.b.height0 = 1;
+       rbuffer->r.b.b.b.depth0 = 1;
+       rbuffer->r.b.b.b.array_size = 1;
+       rbuffer->r.b.b.b.flags = 0;
+        rbuffer->r.b.user_ptr = ptr;
+       rbuffer->r.bo = NULL;
+       rbuffer->r.bo_size = 0;
+       return &rbuffer->r.b.b.b;
 }
 
-int r600_upload_user_buffers(struct r600_pipe_context *rctx)
+struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen,
+                                             struct winsys_handle *whandle)
 {
-       enum pipe_error ret = PIPE_OK;
-       int i, nr;
-
-       nr = rctx->vertex_elements->count;
-       nr = rctx->nvertex_buffer;
-
-       for (i = 0; i < nr; i++) {
-               struct pipe_vertex_buffer *vb = &rctx->vertex_buffer[i];
-
-               if (r600_buffer_is_user_buffer(vb->buffer)) {
-                       struct r600_resource_buffer *rbuffer = r600_buffer(vb->buffer);
-                       unsigned upload_offset;
-
-                       ret = r600_upload_buffer(rctx->rupload_vb,
-                                               0, vb->buffer->width0,
-                                               rbuffer,
-                                               &upload_offset,
-                                               &rbuffer->r.bo_size,
-                                               &rbuffer->r.bo);
-                       if (ret)
-                               return ret;
-                       rbuffer->uploaded = TRUE;
-                       vb->buffer_offset = upload_offset;
-               }
+       struct radeon *rw = (struct radeon*)screen->winsys;
+       struct r600_resource *rbuffer;
+       struct r600_bo *bo = NULL;
+
+       bo = r600_bo_handle(rw, whandle->handle, NULL);
+       if (bo == NULL) {
+               return NULL;
+       }
+
+       rbuffer = CALLOC_STRUCT(r600_resource);
+       if (rbuffer == NULL) {
+               r600_bo_reference(rw, &bo, NULL);
+               return NULL;
        }
-       return ret;
+
+       pipe_reference_init(&rbuffer->b.b.b.reference, 1);
+       rbuffer->b.b.b.target = PIPE_BUFFER;
+       rbuffer->b.b.b.screen = screen;
+       rbuffer->b.b.vtbl = &r600_buffer_vtbl;
+       rbuffer->bo = bo;
+       return &rbuffer->b.b.b;
 }
 
+void r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw)
+{
+       struct r600_resource_buffer *rbuffer = r600_buffer(draw->index_buffer);
+       boolean flushed;
+
+       u_upload_data(rctx->vbuf_mgr->uploader, 0,
+                     draw->info.count * draw->index_size,
+                     rbuffer->r.b.user_ptr,
+                     &draw->index_buffer_offset,
+                     &draw->index_buffer, &flushed);
+}
 
-int r600_upload_const_buffer(struct r600_pipe_context *rctx, struct pipe_resource *cbuffer,
+void r600_upload_const_buffer(struct r600_pipe_context *rctx, struct r600_resource_buffer **rbuffer,
                             uint32_t *const_offset)
 {
-       if (r600_buffer_is_user_buffer(cbuffer)) {
-               struct r600_resource_buffer *rbuffer = r600_buffer(cbuffer);
-               unsigned upload_offset;
-               int ret = 0;
-
-               ret = r600_upload_buffer(rctx->rupload_const,
-                                        0, cbuffer->width0,
-                                        rbuffer,
-                                        &upload_offset,
-                                        &rbuffer->r.bo_size,
-                                        &rbuffer->r.bo);
-               if (ret)
-                       return ret;
-               rbuffer->uploaded = TRUE;
-               *const_offset = upload_offset;
-               return 0;
-       }
+       if ((*rbuffer)->r.b.user_ptr) {
+               uint8_t *ptr = (*rbuffer)->r.b.user_ptr;
+               unsigned size = (*rbuffer)->r.b.b.b.width0;
+               boolean flushed;
+
+               *rbuffer = NULL;
 
-       *const_offset = 0;
-       return 0;
+               u_upload_data(rctx->vbuf_mgr->uploader, 0, size, ptr, const_offset,
+                             (struct pipe_resource**)rbuffer, &flushed);
+       } else {
+               *const_offset = 0;
+       }
 }
index 68b625cc3b4ec59997045dc508fadc736df5765b..34094001b755f77162bfba7a37e66d267dc8ff5e 100644 (file)
 #include <tgsi/tgsi_util.h>
 #include <util/u_blitter.h>
 #include <util/u_double_list.h>
+#include <util/u_format_s3tc.h>
 #include <util/u_transfer.h>
 #include <util/u_surface.h>
 #include <util/u_pack_color.h>
 #include <util/u_memory.h>
 #include <util/u_inlines.h>
+#include "util/u_upload_mgr.h"
 #include <pipebuffer/pb_buffer.h>
 #include "r600.h"
 #include "r600d.h"
@@ -69,8 +71,30 @@ static void r600_flush(struct pipe_context *ctx, unsigned flags,
 #endif
        r600_context_flush(&rctx->ctx);
 
-       r600_upload_flush(rctx->rupload_vb);
-       r600_upload_flush(rctx->rupload_const);
+       /* XXX This shouldn't be really necessary, but removing it breaks some tests.
+        * Needless buffer reallocations may significantly increase memory consumption,
+        * so getting rid of this call is important. */
+       u_upload_flush(rctx->vbuf_mgr->uploader);
+}
+
+static void r600_update_num_contexts(struct r600_screen *rscreen,
+                                     int diff)
+{
+       pipe_mutex_lock(rscreen->mutex_num_contexts);
+       if (diff > 0) {
+               rscreen->num_contexts++;
+
+               if (rscreen->num_contexts > 1)
+                       util_slab_set_thread_safety(&rscreen->pool_buffers,
+                                                   UTIL_SLAB_MULTITHREADED);
+       } else {
+               rscreen->num_contexts--;
+
+               if (rscreen->num_contexts <= 1)
+                       util_slab_set_thread_safety(&rscreen->pool_buffers,
+                                                   UTIL_SLAB_SINGLETHREADED);
+       }
+       pipe_mutex_unlock(rscreen->mutex_num_contexts);
 }
 
 static void r600_destroy_context(struct pipe_context *context)
@@ -79,8 +103,6 @@ static void r600_destroy_context(struct pipe_context *context)
 
        rctx->context.delete_depth_stencil_alpha_state(&rctx->context, rctx->custom_dsa_flush);
 
-       r600_end_vertex_translate(rctx);
-
        r600_context_fini(&rctx->ctx);
 
        util_blitter_destroy(rctx->blitter);
@@ -89,14 +111,11 @@ static void r600_destroy_context(struct pipe_context *context)
                free(rctx->states[i]);
        }
 
-       r600_upload_destroy(rctx->rupload_vb);
-       r600_upload_destroy(rctx->rupload_const);
+       u_vbuf_mgr_destroy(rctx->vbuf_mgr);
+       util_slab_destroy(&rctx->pool_transfers);
 
-       if (rctx->tran.translate_cache)
-               translate_cache_destroy(rctx->tran.translate_cache);
+       r600_update_num_contexts(rctx->screen, -1);
 
-       FREE(rctx->ps_resource);
-       FREE(rctx->vs_resource);
        FREE(rctx);
 }
 
@@ -108,6 +127,9 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
 
        if (rctx == NULL)
                return NULL;
+
+       r600_update_num_contexts(rscreen, 1);
+
        rctx->context.winsys = rscreen->screen.winsys;
        rctx->context.screen = screen;
        rctx->context.priv = priv;
@@ -123,6 +145,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
        r600_init_query_functions(rctx);
        r600_init_context_resource_functions(rctx);
        r600_init_surface_functions(rctx);
+       rctx->context.draw_vbo = r600_draw_vbo;
 
        switch (r600_get_family(rctx->radeon)) {
        case CHIP_R600:
@@ -137,7 +160,6 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
        case CHIP_RV730:
        case CHIP_RV710:
        case CHIP_RV740:
-               rctx->context.draw_vbo = r600_draw_vbo;
                r600_init_state_functions(rctx);
                if (r600_context_init(&rctx->ctx, rctx->radeon)) {
                        r600_destroy_context(&rctx->context);
@@ -154,7 +176,6 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
        case CHIP_BARTS:
        case CHIP_TURKS:
        case CHIP_CAICOS:
-               rctx->context.draw_vbo = evergreen_draw;
                evergreen_init_state_functions(rctx);
                if (evergreen_context_init(&rctx->ctx, rctx->radeon)) {
                        r600_destroy_context(&rctx->context);
@@ -168,39 +189,23 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
                return NULL;
        }
 
-       rctx->rupload_vb = r600_upload_create(rctx, 128 * 1024, 16);
-       if (rctx->rupload_vb == NULL) {
-               r600_destroy_context(&rctx->context);
-               return NULL;
-       }
+       util_slab_create(&rctx->pool_transfers,
+                        sizeof(struct pipe_transfer), 64,
+                        UTIL_SLAB_SINGLETHREADED);
 
-       rctx->rupload_const = r600_upload_create(rctx, 128 * 1024, 256);
-       if (rctx->rupload_const == NULL) {
+       rctx->vbuf_mgr = u_vbuf_mgr_create(&rctx->context, 1024 * 1024, 256,
+                                          PIPE_BIND_VERTEX_BUFFER |
+                                          PIPE_BIND_INDEX_BUFFER |
+                                          PIPE_BIND_CONSTANT_BUFFER,
+                                          U_VERTEX_FETCH_DWORD_ALIGNED);
+       if (!rctx->vbuf_mgr) {
                r600_destroy_context(&rctx->context);
                return NULL;
        }
 
        rctx->blitter = util_blitter_create(&rctx->context);
        if (rctx->blitter == NULL) {
-               FREE(rctx);
-               return NULL;
-       }
-
-       rctx->tran.translate_cache = translate_cache_create();
-       if (rctx->tran.translate_cache == NULL) {
-               FREE(rctx);
-               return NULL;
-       }
-
-       rctx->vs_resource = CALLOC(R600_RESOURCE_ARRAY_SIZE, sizeof(struct r600_pipe_state));
-       if (!rctx->vs_resource) {
-               FREE(rctx);
-               return NULL;
-       }
-
-       rctx->ps_resource = CALLOC(R600_RESOURCE_ARRAY_SIZE, sizeof(struct r600_pipe_state));
-       if (!rctx->ps_resource) {
-               FREE(rctx);
+               r600_destroy_context(&rctx->context);
                return NULL;
        }
 
@@ -284,13 +289,16 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
                return 1;
 
        /* Unsupported features (boolean caps). */
-       case PIPE_CAP_TIMER_QUERY:
        case PIPE_CAP_STREAM_OUTPUT:
        case PIPE_CAP_PRIMITIVE_RESTART:
        case PIPE_CAP_INDEP_BLEND_FUNC: /* FIXME allow this */
        case PIPE_CAP_INSTANCED_DRAWING:
                return 0;
 
+       case PIPE_CAP_ARRAY_TEXTURES:
+               /* fix once the CS checker upstream is fixed */
+               return debug_get_bool_option("R600_ARRAY_TEXTURE", FALSE);
+
        /* Texturing. */
        case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
        case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
@@ -319,6 +327,10 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
        case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
                return 0;
 
+       /* Timer queries, present when the clock frequency is non zero. */
+       case PIPE_CAP_TIMER_QUERY:
+               return r600_get_clock_crystal_freq(rscreen->radeon) != 0;
+
        default:
                R600_ERR("r600: unknown param %d\n", param);
                return 0;
@@ -385,7 +397,7 @@ static int r600_get_shader_param(struct pipe_screen* pscreen, unsigned shader, e
        case PIPE_SHADER_CAP_MAX_CONSTS:
                return 256; //max native parameters
        case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
-               return 1;
+               return R600_MAX_CONST_BUFFERS;
        case PIPE_SHADER_CAP_MAX_PREDS:
                return 0; /* FIXME */
        case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
@@ -441,9 +453,14 @@ static boolean r600_is_format_supported(struct pipe_screen* screen,
                retval |= PIPE_BIND_DEPTH_STENCIL;
        }
 
-       if ((usage & PIPE_BIND_VERTEX_BUFFER) &&
-           r600_is_vertex_format_supported(format))
-               retval |= PIPE_BIND_VERTEX_BUFFER;
+       if (usage & PIPE_BIND_VERTEX_BUFFER) {
+               struct r600_screen *rscreen = (struct r600_screen *)screen;
+               enum radeon_family family = r600_get_family(rscreen->radeon);
+
+               if (r600_is_vertex_format_supported(format, family)) {
+                       retval |= PIPE_BIND_VERTEX_BUFFER;
+               }
+       }
 
        if (usage & PIPE_BIND_TRANSFER_READ)
                retval |= PIPE_BIND_TRANSFER_READ;
@@ -462,6 +479,8 @@ static void r600_destroy_screen(struct pipe_screen* pscreen)
 
        radeon_decref(rscreen->radeon);
 
+       util_slab_destroy(&rscreen->pool_buffers);
+       pipe_mutex_destroy(rscreen->mutex_num_contexts);
        FREE(rscreen);
 }
 
@@ -489,6 +508,13 @@ struct pipe_screen *r600_screen_create(struct radeon *radeon)
        r600_init_screen_resource_functions(&rscreen->screen);
 
        rscreen->tiling_info = r600_get_tiling_info(radeon);
+       util_format_s3tc_init();
+
+       util_slab_create(&rscreen->pool_buffers,
+                        sizeof(struct r600_resource_buffer), 64,
+                        UTIL_SLAB_SINGLETHREADED);
+
+       pipe_mutex_init(rscreen->mutex_num_contexts);
 
        return &rscreen->screen;
 }
index 7f74fda0daf7c200ec84453cc5ff4b0168949e2c..8dc1f4ad5c3500885bdc7e39136bc7f08520d5cd 100644 (file)
 #include <pipe/p_screen.h>
 #include <pipe/p_context.h>
 #include <util/u_math.h>
-#include "translate/translate_cache.h"
+#include "util/u_slab.h"
+#include "util/u_vbuf_mgr.h"
 #include "r600.h"
 #include "r600_public.h"
 #include "r600_shader.h"
 #include "r600_resource.h"
 
+#define R600_MAX_CONST_BUFFERS 1
+
 enum r600_pipe_state_id {
        R600_PIPE_STATE_BLEND = 0,
        R600_PIPE_STATE_BLEND_COLOR,
@@ -62,6 +65,11 @@ struct r600_screen {
        struct pipe_screen              screen;
        struct radeon                   *radeon;
        struct r600_tiling_info         *tiling_info;
+       struct util_slab_mempool        pool_buffers;
+       unsigned                        num_contexts;
+
+       /* for thread-safe write accessing to num_contexts */
+       pipe_mutex                      mutex_num_contexts;
 };
 
 struct r600_pipe_sampler_view {
@@ -86,9 +94,7 @@ struct r600_vertex_element
 {
        unsigned                        count;
        struct pipe_vertex_element      elements[PIPE_MAX_ATTRIBS];
-       enum pipe_format                hw_format[PIPE_MAX_ATTRIBS];
-       unsigned                        hw_format_size[PIPE_MAX_ATTRIBS];
-       boolean                         incompatible_layout;
+       struct u_vbuf_mgr_elements      *vmgr_elements;
        struct r600_bo                  *fetch_shader;
        unsigned                        fs_size;
        struct r600_pipe_state          rstate;
@@ -117,22 +123,9 @@ struct r600_textures_info {
        unsigned                        n_samplers;
 };
 
-/* vertex buffer translation context, used to translate vertex input that
- * hw doesn't natively support, so far only FLOAT64 is unsupported.
- */
-struct r600_translate_context {
-       /* Translate cache for incompatible vertex offset/stride/format fallback. */
-       struct translate_cache          *translate_cache;
-       /* The vertex buffer slot containing the translated buffer. */
-       unsigned                        vb_slot;
-       void                            *new_velems;
-};
-
 #define R600_CONSTANT_ARRAY_SIZE 256
 #define R600_RESOURCE_ARRAY_SIZE 160
 
-struct r600_upload;
-
 struct r600_pipe_context {
        struct pipe_context             context;
        struct blitter_context          *blitter;
@@ -143,43 +136,35 @@ struct r600_pipe_context {
        struct r600_pipe_state          *states[R600_PIPE_NSTATES];
        struct r600_context             ctx;
        struct r600_vertex_element      *vertex_elements;
+       struct r600_pipe_state          fs_resource[PIPE_MAX_ATTRIBS];
        struct pipe_framebuffer_state   framebuffer;
        struct pipe_index_buffer        index_buffer;
-       struct pipe_vertex_buffer       vertex_buffer[PIPE_MAX_ATTRIBS];
-       unsigned                        nvertex_buffer;
        unsigned                        cb_target_mask;
        /* for saving when using blitter */
        struct pipe_stencil_ref         stencil_ref;
        struct pipe_viewport_state      viewport;
        struct pipe_clip_state          clip;
-       unsigned                        nvs_resource;
-       struct r600_pipe_state          *vs_resource;
-       struct r600_pipe_state          *ps_resource;
        struct r600_pipe_state          config;
        struct r600_pipe_shader         *ps_shader;
        struct r600_pipe_shader         *vs_shader;
        struct r600_pipe_state          vs_const_buffer;
+       struct r600_pipe_state          vs_const_buffer_resource[R600_MAX_CONST_BUFFERS];
        struct r600_pipe_state          ps_const_buffer;
+       struct r600_pipe_state          ps_const_buffer_resource[R600_MAX_CONST_BUFFERS];
        struct r600_pipe_rasterizer     *rasterizer;
        /* shader information */
        unsigned                        sprite_coord_enable;
        bool                            flatshade;
-       struct r600_upload              *rupload_vb;
-       unsigned                        any_user_vbs;
        struct r600_textures_info       ps_samplers;
-       unsigned                        vb_max_index;
-       struct r600_translate_context   tran;
-       struct r600_upload              *rupload_const;
+
+       struct u_vbuf_mgr               *vbuf_mgr;
+       struct util_slab_mempool        pool_transfers;
+       bool                            blit;
 };
 
 struct r600_drawl {
+       struct pipe_draw_info   info;
        struct pipe_context     *ctx;
-       unsigned                mode;
-       unsigned                min_index;
-       unsigned                max_index;
-       unsigned                index_bias;
-       unsigned                start;
-       unsigned                count;
        unsigned                index_size;
        unsigned                index_buffer_offset;
        struct pipe_resource    *index_buffer;
@@ -188,16 +173,20 @@ struct r600_drawl {
 /* evergreen_state.c */
 void evergreen_init_state_functions(struct r600_pipe_context *rctx);
 void evergreen_init_config(struct r600_pipe_context *rctx);
-void evergreen_draw(struct pipe_context *ctx, const struct pipe_draw_info *info);
 void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shader);
 void evergreen_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shader *shader);
 void *evergreen_create_db_flush_dsa(struct r600_pipe_context *rctx);
 void evergreen_polygon_offset_update(struct r600_pipe_context *rctx);
-void evergreen_vertex_buffer_update(struct r600_pipe_context *rctx);
+void evergreen_pipe_set_buffer_resource(struct r600_pipe_context *rctx,
+                                       struct r600_pipe_state *rstate,
+                                       struct r600_resource *rbuffer,
+                                       unsigned offset, unsigned stride);
 
 /* r600_blit.c */
 void r600_init_blit_functions(struct r600_pipe_context *rctx);
 void r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_texture *texture);
+void r600_blit_push_depth(struct pipe_context *ctx, struct r600_resource_texture *texture);
+void r600_flush_depth_textures(struct r600_pipe_context *rctx);
 
 /* r600_buffer.c */
 struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
@@ -205,13 +194,9 @@ struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
 struct pipe_resource *r600_user_buffer_create(struct pipe_screen *screen,
                                              void *ptr, unsigned bytes,
                                              unsigned bind);
-unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context,
-                                        struct pipe_resource *buf,
-                                        unsigned level, int layer);
 struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen,
                                              struct winsys_handle *whandle);
-int r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw);
-int r600_upload_user_buffers(struct r600_pipe_context *rctx);
+void r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw);
 
 /* r600_query.c */
 void r600_init_query_functions(struct r600_pipe_context *rctx);
@@ -220,7 +205,6 @@ void r600_init_query_functions(struct r600_pipe_context *rctx);
 void r600_init_context_resource_functions(struct r600_pipe_context *r600);
 
 /* r600_shader.c */
-int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *shader);
 int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *shader, const struct tgsi_token *tokens);
 void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *shader);
 int r600_find_vs_semantic_index(struct r600_shader *vs,
@@ -228,11 +212,14 @@ int r600_find_vs_semantic_index(struct r600_shader *vs,
 
 /* r600_state.c */
 void r600_init_state_functions(struct r600_pipe_context *rctx);
-void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info);
+void r600_spi_update(struct r600_pipe_context *rctx);
 void r600_init_config(struct r600_pipe_context *rctx);
 void *r600_create_db_flush_dsa(struct r600_pipe_context *rctx);
 void r600_polygon_offset_update(struct r600_pipe_context *rctx);
-void r600_vertex_buffer_update(struct r600_pipe_context *rctx);
+void r600_pipe_set_buffer_resource(struct r600_pipe_context *rctx,
+                                  struct r600_pipe_state *rstate,
+                                  struct r600_resource *rbuffer,
+                                  unsigned offset, unsigned stride);
 
 /* r600_helper.h */
 int r600_conv_pipe_prim(unsigned pprim, unsigned *prim);
@@ -247,8 +234,6 @@ unsigned r600_texture_get_offset(struct r600_resource_texture *rtex,
                                        unsigned level, unsigned layer);
 
 /* r600_translate.c */
-void r600_begin_vertex_translate(struct r600_pipe_context *rctx);
-void r600_end_vertex_translate(struct r600_pipe_context *rctx);
 void r600_translate_index_buffer(struct r600_pipe_context *r600,
                                 struct pipe_resource **index_buffer,
                                 unsigned *index_size,
@@ -277,6 +262,9 @@ void r600_bind_ps_shader(struct pipe_context *ctx, void *state);
 void r600_bind_vs_shader(struct pipe_context *ctx, void *state);
 void r600_delete_ps_shader(struct pipe_context *ctx, void *state);
 void r600_delete_vs_shader(struct pipe_context *ctx, void *state);
+void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
+                             struct pipe_resource *buffer);
+void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info);
 
 /*
  * common helpers
index 28b3e1e5e40b22e978a217c82b32d7f9babf9be2..836e7491f1ff37601262b800f4fd376db0f539f1 100644 (file)
@@ -24,6 +24,7 @@
 #define R600_RESOURCE_H
 
 #include "util/u_transfer.h"
+#include "util/u_vbuf_mgr.h"
 
 /* flag to indicate a resource is to be used as a transfer so should not be tiled */
 #define R600_RESOURCE_FLAG_TRANSFER     PIPE_RESOURCE_FLAG_DRV_PRIV
@@ -43,7 +44,7 @@ struct r600_transfer {
  * underlying implementations.
  */
 struct r600_resource {
-       struct u_resource               base;
+       struct u_vbuf_resource          b;
        struct r600_bo                  *bo;
        u32                             size;
        unsigned                        bo_size;
@@ -52,26 +53,31 @@ struct r600_resource {
 struct r600_resource_texture {
        struct r600_resource            resource;
        unsigned                        offset[PIPE_MAX_TEXTURE_LEVELS];
-       unsigned                        pitch_in_bytes[PIPE_MAX_TEXTURE_LEVELS];
-       unsigned                        pitch_in_pixels[PIPE_MAX_TEXTURE_LEVELS];
+       unsigned                        pitch_in_bytes[PIPE_MAX_TEXTURE_LEVELS];  /* transfer */
+       unsigned                        pitch_in_blocks[PIPE_MAX_TEXTURE_LEVELS]; /* texture resource */
        unsigned                        layer_size[PIPE_MAX_TEXTURE_LEVELS];
        unsigned                        array_mode[PIPE_MAX_TEXTURE_LEVELS];
        unsigned                        pitch_override;
        unsigned                        size;
-       unsigned                        tiled;
        unsigned                        tile_type;
        unsigned                        depth;
-       unsigned                        dirty;
+       unsigned                        dirty_db;
        struct r600_resource_texture    *flushed_depth_texture;
+       boolean                         is_flushing_texture;
+
+       /* on some cards we have to use integer 64/128-bit types
+          for s3tc blits, do this until gallium grows int formats */
+       boolean force_int_type;
 };
 
+#define R600_TEX_IS_TILED(tex, level) ((tex)->array_mode[level] != V_038000_ARRAY_LINEAR_GENERAL && (tex)->array_mode[level] != V_038000_ARRAY_LINEAR_ALIGNED)
+
 #define R600_BUFFER_MAGIC 0xabcd1600
 
+/* XXX this could be removed */
 struct r600_resource_buffer {
        struct r600_resource            r;
        uint32_t                        magic;
-       void                            *user_buffer;
-       bool                            uploaded;
 };
 
 struct r600_surface {
@@ -98,14 +104,7 @@ static INLINE struct r600_resource_buffer *r600_buffer(struct pipe_resource *buf
        return NULL;
 }
 
-static INLINE boolean r600_buffer_is_user_buffer(struct pipe_resource *buffer)
-{
-       if (r600_buffer(buffer)->uploaded)
-               return FALSE;
-       return r600_buffer(buffer)->user_buffer ? TRUE : FALSE;
-}
-
-int r600_texture_depth_flush(struct pipe_context *ctx, struct pipe_resource *texture);
+int r600_texture_depth_flush(struct pipe_context *ctx, struct pipe_resource *texture, boolean just_create);
 
 /* r600_texture.c texture transfer functions. */
 struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
@@ -121,15 +120,7 @@ void r600_texture_transfer_unmap(struct pipe_context *ctx,
                                 struct pipe_transfer* transfer);
 
 struct r600_pipe_context;
-struct r600_upload *r600_upload_create(struct r600_pipe_context *rctx,
-                                       unsigned default_size,
-                                       unsigned alignment);
-void r600_upload_flush(struct r600_upload *upload);
-void r600_upload_destroy(struct r600_upload *upload);
-int r600_upload_buffer(struct r600_upload *upload, unsigned offset,
-                       unsigned size, struct r600_resource_buffer *in_buffer,
-                       unsigned *out_offset, unsigned *out_size,
-                       struct r600_bo **out_buffer);
-
-int r600_upload_const_buffer(struct r600_pipe_context *rctx, struct pipe_resource *cbuffer, uint32_t *offset);
+
+void r600_upload_const_buffer(struct r600_pipe_context *rctx, struct r600_resource_buffer **rbuffer, uint32_t *offset);
+
 #endif
index c982471a04f7f8fa08fe63402c3fb4dcc1b68aa0..240c8f1ffd086c8d31143913d892086ea01b5860 100644 (file)
@@ -28,6 +28,7 @@
 #include "r600_pipe.h"
 #include "r600_asm.h"
 #include "r600_sq.h"
+#include "r600_formats.h"
 #include "r600_opcodes.h"
 #include "r600d.h"
 #include <stdio.h>
@@ -175,6 +176,13 @@ static void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shade
                                R_0288CC_SQ_PGM_CF_OFFSET_PS,
                                0x00000000, 0xFFFFFFFF, NULL);
 
+       if (rshader->fs_write_all) {
+               r600_pipe_state_add_reg(rstate, R_028808_CB_COLOR_CONTROL,
+                                       S_028808_MULTIWRITE_ENABLE(1),
+                                       S_028808_MULTIWRITE_ENABLE(1),
+                                       NULL);
+       }
+
        if (rshader->uses_kill) {
                /* only set some bits here, the other bits are set in the dsa state */
                r600_pipe_state_add_reg(rstate,
@@ -187,7 +195,7 @@ static void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shade
                                0xFFFFFFFF, NULL);
 }
 
-int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *shader)
+static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *shader)
 {
        struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
        struct r600_shader *rshader = &shader->shader;
@@ -225,12 +233,12 @@ int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *shader)
        return 0;
 }
 
-int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader, u32 **literals);
+static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader);
+
 int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *shader, const struct tgsi_token *tokens)
 {
        static int dump_shaders = -1;
        struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
-       u32 *literals;
        int r;
 
         /* Would like some magic "get_bool_option_once" routine.
@@ -243,13 +251,12 @@ int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *s
                tgsi_dump(tokens, 0);
        }
        shader->shader.family = r600_get_family(rctx->radeon);
-       r = r600_shader_from_tgsi(tokens, &shader->shader, &literals);
+       r = r600_shader_from_tgsi(tokens, &shader->shader);
        if (r) {
                R600_ERR("translation from TGSI failed !\n");
                return r;
        }
        r = r600_bc_build(&shader->shader.bc);
-       free(literals);
        if (r) {
                R600_ERR("building bytecode failed !\n");
                return r;
@@ -274,6 +281,15 @@ void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader
  */
 struct r600_shader_tgsi_instruction;
 
+struct r600_shader_src {
+       unsigned                                sel;
+       unsigned                                swizzle[4];
+       unsigned                                neg;
+       unsigned                                abs;
+       unsigned                                rel;
+       uint32_t                                value[4];
+};
+
 struct r600_shader_ctx {
        struct tgsi_shader_info                 info;
        struct tgsi_parse_context               parse;
@@ -281,9 +297,11 @@ struct r600_shader_ctx {
        unsigned                                type;
        unsigned                                file_offset[TGSI_FILE_COUNT];
        unsigned                                temp_reg;
+       unsigned                                ar_reg;
        struct r600_shader_tgsi_instruction     *inst_info;
        struct r600_bc                          *bc;
        struct r600_shader                      *shader;
+       struct r600_shader_src                  src[3];
        u32                                     *literals;
        u32                                     nliterals;
        u32                                     max_driver_temp_used;
@@ -492,9 +510,179 @@ static int evergreen_gpr_count(struct r600_shader_ctx *ctx)
        return ctx->num_interp_gpr;
 }
 
-int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader, u32 **literals)
+static void tgsi_src(struct r600_shader_ctx *ctx,
+                    const struct tgsi_full_src_register *tgsi_src,
+                    struct r600_shader_src *r600_src)
+{
+       memset(r600_src, 0, sizeof(*r600_src));
+       r600_src->swizzle[0] = tgsi_src->Register.SwizzleX;
+       r600_src->swizzle[1] = tgsi_src->Register.SwizzleY;
+       r600_src->swizzle[2] = tgsi_src->Register.SwizzleZ;
+       r600_src->swizzle[3] = tgsi_src->Register.SwizzleW;
+       r600_src->neg = tgsi_src->Register.Negate;
+       r600_src->abs = tgsi_src->Register.Absolute;
+       if (tgsi_src->Register.File == TGSI_FILE_IMMEDIATE) {
+               int index;
+               if ((tgsi_src->Register.SwizzleX == tgsi_src->Register.SwizzleY) &&
+                       (tgsi_src->Register.SwizzleX == tgsi_src->Register.SwizzleZ) &&
+                       (tgsi_src->Register.SwizzleX == tgsi_src->Register.SwizzleW)) {
+
+                       index = tgsi_src->Register.Index * 4 + tgsi_src->Register.SwizzleX;
+                       r600_bc_special_constants(ctx->literals[index], &r600_src->sel, &r600_src->neg);
+                       if (r600_src->sel != V_SQ_ALU_SRC_LITERAL)
+                               return;
+               }
+               index = tgsi_src->Register.Index;
+               r600_src->sel = V_SQ_ALU_SRC_LITERAL;
+               memcpy(r600_src->value, ctx->literals + index * 4, sizeof(r600_src->value));
+       } else {
+               if (tgsi_src->Register.Indirect)
+                       r600_src->rel = V_SQ_REL_RELATIVE;
+               r600_src->sel = tgsi_src->Register.Index;
+               r600_src->sel += ctx->file_offset[tgsi_src->Register.File];
+       }
+}
+
+static int tgsi_fetch_rel_const(struct r600_shader_ctx *ctx, unsigned int offset, unsigned int dst_reg)
+{
+       struct r600_bc_vtx vtx;
+       unsigned int ar_reg;
+       int r;
+
+       if (offset) {
+               struct r600_bc_alu alu;
+
+               memset(&alu, 0, sizeof(alu));
+
+               alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD_INT);
+               alu.src[0].sel = ctx->ar_reg;
+
+               alu.src[1].sel = V_SQ_ALU_SRC_LITERAL;
+               alu.src[1].value = offset;
+
+               alu.dst.sel = dst_reg;
+               alu.dst.write = 1;
+               alu.last = 1;
+
+               if ((r = r600_bc_add_alu(ctx->bc, &alu)))
+                       return r;
+
+               ar_reg = dst_reg;
+       } else {
+               ar_reg = ctx->ar_reg;
+       }
+
+       memset(&vtx, 0, sizeof(vtx));
+       vtx.fetch_type = 2;             /* VTX_FETCH_NO_INDEX_OFFSET */
+       vtx.src_gpr = ar_reg;
+       vtx.mega_fetch_count = 16;
+       vtx.dst_gpr = dst_reg;
+       vtx.dst_sel_x = 0;              /* SEL_X */
+       vtx.dst_sel_y = 1;              /* SEL_Y */
+       vtx.dst_sel_z = 2;              /* SEL_Z */
+       vtx.dst_sel_w = 3;              /* SEL_W */
+       vtx.data_format = FMT_32_32_32_32_FLOAT;
+       vtx.num_format_all = 2;         /* NUM_FORMAT_SCALED */
+       vtx.format_comp_all = 1;        /* FORMAT_COMP_SIGNED */
+       vtx.srf_mode_all = 1;           /* SRF_MODE_NO_ZERO */
+
+       if ((r = r600_bc_add_vtx(ctx->bc, &vtx)))
+               return r;
+
+       return 0;
+}
+
+static int tgsi_split_constant(struct r600_shader_ctx *ctx)
+{
+       struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+       struct r600_bc_alu alu;
+       int i, j, k, nconst, r;
+
+       for (i = 0, nconst = 0; i < inst->Instruction.NumSrcRegs; i++) {
+               if (inst->Src[i].Register.File == TGSI_FILE_CONSTANT) {
+                       nconst++;
+               }
+               tgsi_src(ctx, &inst->Src[i], &ctx->src[i]);
+       }
+       for (i = 0, j = nconst - 1; i < inst->Instruction.NumSrcRegs; i++) {
+               if (inst->Src[i].Register.File != TGSI_FILE_CONSTANT) {
+                       continue;
+               }
+
+               if (ctx->src[i].rel) {
+                       int treg = r600_get_temp(ctx);
+                       if ((r = tgsi_fetch_rel_const(ctx, ctx->src[i].sel - 512, treg)))
+                               return r;
+
+                       ctx->src[i].sel = treg;
+                       ctx->src[i].rel = 0;
+                       j--;
+               } else if (j > 0) {
+                       int treg = r600_get_temp(ctx);
+                       for (k = 0; k < 4; k++) {
+                               memset(&alu, 0, sizeof(struct r600_bc_alu));
+                               alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV);
+                               alu.src[0].sel = ctx->src[i].sel;
+                               alu.src[0].chan = k;
+                               alu.src[0].rel = ctx->src[i].rel;
+                               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;
+                       }
+                       ctx->src[i].sel = treg;
+                       ctx->src[i].rel =0;
+                       j--;
+               }
+       }
+       return 0;
+}
+
+/* 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 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 (ctx->src[i].sel == V_SQ_ALU_SRC_LITERAL) {
+                       nliteral++;
+               }
+       }
+       for (i = 0, j = nliteral - 1; i < inst->Instruction.NumSrcRegs; i++) {
+               if (j > 0 && ctx->src[i].sel == V_SQ_ALU_SRC_LITERAL) {
+                       int treg = r600_get_temp(ctx);
+                       for (k = 0; k < 4; k++) {
+                               memset(&alu, 0, sizeof(struct r600_bc_alu));
+                               alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV);
+                               alu.src[0].sel = ctx->src[i].sel;
+                               alu.src[0].chan = k;
+                               alu.src[0].value = ctx->src[i].value[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;
+                       }
+                       ctx->src[i].sel = treg;
+                       j--;
+               }
+       }
+       return 0;
+}
+
+static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader)
 {
        struct tgsi_full_immediate *immediate;
+       struct tgsi_full_property *property;
        struct r600_shader_ctx ctx;
        struct r600_bc_output output[32];
        unsigned noutput;
@@ -558,12 +746,13 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s
        ctx.file_offset[TGSI_FILE_CONSTANT] = 512;
 
        ctx.file_offset[TGSI_FILE_IMMEDIATE] = V_SQ_ALU_SRC_LITERAL;
-       ctx.temp_reg = ctx.file_offset[TGSI_FILE_TEMPORARY] +
+       ctx.ar_reg = ctx.file_offset[TGSI_FILE_TEMPORARY] +
                        ctx.info.file_count[TGSI_FILE_TEMPORARY];
+       ctx.temp_reg = ctx.ar_reg + 1;
 
        ctx.nliterals = 0;
        ctx.literals = NULL;
-
+       shader->fs_write_all = FALSE;
        while (!tgsi_parse_end_of_tokens(&ctx.parse)) {
                tgsi_parse_token(&ctx.parse);
                switch (ctx.parse.FullToken.Token.Type) {
@@ -592,7 +781,12 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s
                        ctx.max_driver_temp_used = 0;
                        /* reserve first tmp for everyone */
                        r600_get_temp(&ctx);
+
                        opcode = ctx.parse.FullToken.FullInstruction.Instruction.Opcode;
+                       if ((r = tgsi_split_constant(&ctx)))
+                               goto out_err;
+                       if ((r = tgsi_split_literal_constant(&ctx)))
+                               goto out_err;
                        if (ctx.bc->chiprev == CHIPREV_EVERGREEN)
                                ctx.inst_info = &eg_shader_tgsi_instruction[opcode];
                        else
@@ -602,6 +796,11 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s
                                goto out_err;
                        break;
                case TGSI_TOKEN_TYPE_PROPERTY:
+                       property = &ctx.parse.FullToken.FullProperty;
+                       if (property->Property.PropertyName == TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS) {
+                               if (property->u[0].Data == 1)
+                                       shader->fs_write_all = TRUE;
+                       }
                        break;
                default:
                        R600_ERR("unsupported token type %d\n", ctx.parse.FullToken.Token.Type);
@@ -619,6 +818,7 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s
                output[i].swizzle_y = 1;
                output[i].swizzle_z = 2;
                output[i].swizzle_w = 3;
+               output[i].burst_count = 1;
                output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM;
                output[i].array_base = i - pos0;
                switch (ctx.type) {
@@ -680,6 +880,7 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s
                        output[i].swizzle_y = 1;
                        output[i].swizzle_z = 2;
                        output[i].swizzle_w = 3;
+                       output[i].burst_count = 1;
                        output[i].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PARAM;
                        output[i].array_base = 0;
                        noutput++;
@@ -694,6 +895,7 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s
                output[0].swizzle_y = 7;
                output[0].swizzle_z = 7;
                output[0].swizzle_w = 7;
+               output[0].burst_count = 1;
                output[0].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
                output[0].array_base = 0;
                noutput++;
@@ -704,7 +906,7 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s
                if (r)
                        goto out_err;
        }
-       *literals = ctx.literals;
+       free(ctx.literals);
        tgsi_parse_free(&ctx.parse);
        return 0;
 out_err:
@@ -724,40 +926,22 @@ static int tgsi_end(struct r600_shader_ctx *ctx)
        return 0;
 }
 
-static int tgsi_src(struct r600_shader_ctx *ctx,
-                       const struct tgsi_full_src_register *tgsi_src,
-                       struct r600_bc_alu_src *r600_src)
+static void r600_bc_src(struct r600_bc_alu_src *bc_src,
+                       const struct r600_shader_src *shader_src,
+                       unsigned chan)
 {
-       memset(r600_src, 0, sizeof(struct r600_bc_alu_src));
-       r600_src->neg = tgsi_src->Register.Negate;
-       r600_src->abs = tgsi_src->Register.Absolute;
-       if (tgsi_src->Register.File == TGSI_FILE_IMMEDIATE) {
-               int index;
-               if((tgsi_src->Register.SwizzleX == tgsi_src->Register.SwizzleY) &&
-                       (tgsi_src->Register.SwizzleX == tgsi_src->Register.SwizzleZ) &&
-                       (tgsi_src->Register.SwizzleX == tgsi_src->Register.SwizzleW)) {
-
-                       index = tgsi_src->Register.Index * 4 + tgsi_src->Register.SwizzleX;
-                       r600_bc_special_constants(ctx->literals[index], &r600_src->sel, &r600_src->neg);
-                       if (r600_src->sel != V_SQ_ALU_SRC_LITERAL)
-                               return 0;
-               }
-               index = tgsi_src->Register.Index;
-               r600_src->sel = V_SQ_ALU_SRC_LITERAL;
-               r600_src->value = ctx->literals + index * 4;
-       } else {
-               if (tgsi_src->Register.Indirect)
-                       r600_src->rel = V_SQ_REL_RELATIVE;
-               r600_src->sel = tgsi_src->Register.Index;
-               r600_src->sel += ctx->file_offset[tgsi_src->Register.File];
-       }
-       return 0;
+       bc_src->sel = shader_src->sel;
+       bc_src->chan = shader_src->swizzle[chan];
+       bc_src->neg = shader_src->neg;
+       bc_src->abs = shader_src->abs;
+       bc_src->rel = shader_src->rel;
+       bc_src->value = shader_src->value[bc_src->chan];
 }
 
-static int tgsi_dst(struct r600_shader_ctx *ctx,
-                       const struct tgsi_full_dst_register *tgsi_dst,
-                       unsigned swizzle,
-                       struct r600_bc_alu_dst *r600_dst)
+static void tgsi_dst(struct r600_shader_ctx *ctx,
+                    const struct tgsi_full_dst_register *tgsi_dst,
+                    unsigned swizzle,
+                    struct r600_bc_alu_dst *r600_dst)
 {
        struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
 
@@ -770,101 +954,6 @@ static int tgsi_dst(struct r600_shader_ctx *ctx,
        if (inst->Instruction.Saturate) {
                r600_dst->clamp = 1;
        }
-       return 0;
-}
-
-static unsigned tgsi_chan(const struct tgsi_full_src_register *tgsi_src, unsigned swizzle)
-{
-       switch (swizzle) {
-       case 0:
-               return tgsi_src->Register.SwizzleX;
-       case 1:
-               return tgsi_src->Register.SwizzleY;
-       case 2:
-               return tgsi_src->Register.SwizzleZ;
-       case 3:
-               return tgsi_src->Register.SwizzleW;
-       default:
-               return 0;
-       }
-}
-
-static int tgsi_split_constant(struct r600_shader_ctx *ctx, struct r600_bc_alu_src r600_src[3])
-{
-       struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
-       struct r600_bc_alu alu;
-       int i, j, k, nconst, r;
-
-       for (i = 0, nconst = 0; i < inst->Instruction.NumSrcRegs; i++) {
-               if (inst->Src[i].Register.File == TGSI_FILE_CONSTANT) {
-                       nconst++;
-               }
-               r = tgsi_src(ctx, &inst->Src[i], &r600_src[i]);
-               if (r) {
-                       return r;
-               }
-       }
-       for (i = 0, j = nconst - 1; i < inst->Instruction.NumSrcRegs; i++) {
-               if (j > 0 && inst->Src[i].Register.File == TGSI_FILE_CONSTANT) {
-                       int treg = r600_get_temp(ctx);
-                       for (k = 0; k < 4; k++) {
-                               memset(&alu, 0, sizeof(struct r600_bc_alu));
-                               alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV);
-                               alu.src[0].sel = r600_src[i].sel;
-                               alu.src[0].chan = k;
-                               alu.src[0].rel = r600_src[i].rel;
-                               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;
-                       }
-                       r600_src[i].sel = treg;
-                       r600_src[i].rel =0;
-                       j--;
-               }
-       }
-       return 0;
-}
-
-/* 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 (r600_src[i].sel == V_SQ_ALU_SRC_LITERAL) {
-                       nliteral++;
-               }
-       }
-       for (i = 0, j = nliteral - 1; i < inst->Instruction.NumSrcRegs; i++) {
-               if (j > 0 && r600_src[i].sel == V_SQ_ALU_SRC_LITERAL) {
-                       int treg = r600_get_temp(ctx);
-                       for (k = 0; k < 4; k++) {
-                               memset(&alu, 0, sizeof(struct r600_bc_alu));
-                               alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV);
-                               alu.src[0].sel = r600_src[i].sel;
-                               alu.src[0].chan = k;
-                               alu.src[0].value = r600_src[i].value;
-                               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;
-                       }
-                       r600_src[i].sel = treg;
-                       j--;
-               }
-       }
-       return 0;
 }
 
 static int tgsi_last_instruction(unsigned writemask)
@@ -882,38 +971,25 @@ static int tgsi_last_instruction(unsigned writemask)
 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 = tgsi_last_instruction(inst->Dst[0].Register.WriteMask);
 
-       r = tgsi_split_constant(ctx, r600_src);
-       if (r)
-               return r;
-       r = tgsi_split_literal_constant(ctx, r600_src);
-       if (r)
-               return r;
        for (i = 0; i < lasti + 1; i++) {
                if (!(inst->Dst[0].Register.WriteMask & (1 << i)))
                        continue;
 
                memset(&alu, 0, sizeof(struct r600_bc_alu));
-               r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
-               if (r)
-                       return r;
+               tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
 
                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);
+                               r600_bc_src(&alu.src[j], &ctx->src[j], i);
                        }
                } 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);
+                       r600_bc_src(&alu.src[0], &ctx->src[1], i);
+                       r600_bc_src(&alu.src[1], &ctx->src[0], i);
                }
                /* handle some special cases */
                switch (ctx->inst_info->tgsi_opcode) {
@@ -951,24 +1027,15 @@ static int tgsi_op2_swap(struct r600_shader_ctx *ctx)
  * 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])
+static int tgsi_setup_trig(struct r600_shader_ctx *ctx)
 {
        static float half_inv_pi = 1.0 /(3.1415926535 * 2);
        static float double_pi = 3.1415926535 * 2;
        static float neg_pi = -3.1415926535;
 
-       struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
        int r;
        struct r600_bc_alu alu;
 
-       r = tgsi_split_constant(ctx, r600_src);
-       if (r)
-               return r;
-       r = tgsi_split_literal_constant(ctx, r600_src);
-       if (r)
-               return r;
-
        memset(&alu, 0, sizeof(struct r600_bc_alu));
        alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD);
        alu.is_op3 = 1;
@@ -977,12 +1044,11 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx,
        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);
+       r600_bc_src(&alu.src[0], &ctx->src[0], 0);
 
        alu.src[1].sel = V_SQ_ALU_SRC_LITERAL;
        alu.src[1].chan = 0;
-       alu.src[1].value = (uint32_t *)&half_inv_pi;
+       alu.src[1].value = *(uint32_t *)&half_inv_pi;
        alu.src[2].sel = V_SQ_ALU_SRC_0_5;
        alu.src[2].chan = 0;
        alu.last = 1;
@@ -1021,8 +1087,8 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx,
        alu.src[2].chan = 0;
 
        if (ctx->bc->chiprev == CHIPREV_R600) {
-               alu.src[1].value = (uint32_t *)&double_pi;
-               alu.src[2].value = (uint32_t *)&neg_pi;
+               alu.src[1].value = *(uint32_t *)&double_pi;
+               alu.src[2].value = *(uint32_t *)&neg_pi;
        } else {
                alu.src[1].sel = V_SQ_ALU_SRC_1;
                alu.src[2].sel = V_SQ_ALU_SRC_0_5;
@@ -1039,12 +1105,11 @@ static int tgsi_setup_trig(struct r600_shader_ctx *ctx,
 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 = tgsi_last_instruction(inst->Dst[0].Register.WriteMask);
 
-       r = tgsi_setup_trig(ctx, r600_src);
+       r = tgsi_setup_trig(ctx);
        if (r)
                return r;
 
@@ -1070,9 +1135,7 @@ static int tgsi_trig(struct r600_shader_ctx *ctx)
                alu.inst = CTX_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;
+               tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
                if (i == lasti)
                        alu.last = 1;
                r = r600_bc_add_alu(ctx->bc, &alu);
@@ -1085,7 +1148,6 @@ static int tgsi_trig(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 r;
 
@@ -1093,7 +1155,7 @@ static int tgsi_scs(struct r600_shader_ctx *ctx)
         * X or Y components of the destination vector.
         */
        if (likely(inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XY)) {
-               r = tgsi_setup_trig(ctx, r600_src);
+               r = tgsi_setup_trig(ctx);
                if (r)
                        return r;
        }
@@ -1102,9 +1164,7 @@ static int tgsi_scs(struct r600_shader_ctx *ctx)
        if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
                memset(&alu, 0, sizeof(struct r600_bc_alu));
                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_COS);
-               r = tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst);
-               if (r)
-                       return r;
+               tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst);
 
                alu.src[0].sel = ctx->temp_reg;
                alu.src[0].chan = 0;
@@ -1118,9 +1178,7 @@ static int tgsi_scs(struct r600_shader_ctx *ctx)
        if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
                memset(&alu, 0, sizeof(struct r600_bc_alu));
                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_SIN);
-               r = tgsi_dst(ctx, &inst->Dst[0], 1, &alu.dst);
-               if (r)
-                       return r;
+               tgsi_dst(ctx, &inst->Dst[0], 1, &alu.dst);
 
                alu.src[0].sel = ctx->temp_reg;
                alu.src[0].chan = 0;
@@ -1136,9 +1194,7 @@ static int tgsi_scs(struct r600_shader_ctx *ctx)
 
                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV);
 
-               r = tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst);
-               if (r)
-                       return r;
+               tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst);
 
                alu.src[0].sel = V_SQ_ALU_SRC_0;
                alu.src[0].chan = 0;
@@ -1156,9 +1212,7 @@ static int tgsi_scs(struct r600_shader_ctx *ctx)
 
                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV);
 
-               r = tgsi_dst(ctx, &inst->Dst[0], 3, &alu.dst);
-               if (r)
-                       return r;
+               tgsi_dst(ctx, &inst->Dst[0], 3, &alu.dst);
 
                alu.src[0].sel = V_SQ_ALU_SRC_1;
                alu.src[0].chan = 0;
@@ -1175,7 +1229,6 @@ static int tgsi_scs(struct r600_shader_ctx *ctx)
 
 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;
 
@@ -1191,10 +1244,7 @@ static int tgsi_kill(struct r600_shader_ctx *ctx)
                        alu.src[1].sel = V_SQ_ALU_SRC_1;
                        alu.src[1].neg = 1;
                } else {
-                       r = tgsi_src(ctx, &inst->Src[0], &alu.src[1]);
-                       if (r)
-                               return r;
-                       alu.src[1].chan = tgsi_chan(&inst->Src[0], i);
+                       r600_bc_src(&alu.src[1], &ctx->src[0], i);
                }
                if (i == 3) {
                        alu.last = 1;
@@ -1214,24 +1264,14 @@ 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 = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV);
        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)
-               return r;
+       tgsi_dst(ctx, &inst->Dst[0], 0, &alu.dst);
        alu.dst.write = (inst->Dst[0].Register.WriteMask >> 0) & 1;
        r = r600_bc_add_alu(ctx->bc, &alu);
        if (r)
@@ -1240,12 +1280,10 @@ 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 = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MAX);
-       alu.src[0] = r600_src[0];
+       r600_bc_src(&alu.src[0], &ctx->src[0], 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;
+       tgsi_dst(ctx, &inst->Dst[0], 1, &alu.dst);
        alu.dst.write = (inst->Dst[0].Register.WriteMask >> 1) & 1;
        r = r600_bc_add_alu(ctx->bc, &alu);
        if (r)
@@ -1256,9 +1294,7 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
        alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV);
        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)
-               return r;
+       tgsi_dst(ctx, &inst->Dst[0], 3, &alu.dst);
        alu.dst.write = (inst->Dst[0].Register.WriteMask >> 3) & 1;
        alu.last = 1;
        r = r600_bc_add_alu(ctx->bc, &alu);
@@ -1273,11 +1309,8 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
                /* dst.z = log(src.y) */
                memset(&alu, 0, sizeof(struct r600_bc_alu));
                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LOG_CLAMPED);
-               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)
-                       return r;
+               r600_bc_src(&alu.src[0], &ctx->src[0], 1);
+               tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst);
                alu.last = 1;
                r = r600_bc_add_alu(ctx->bc, &alu);
                if (r)
@@ -1289,13 +1322,11 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
                /* tmp.x = amd MUL_LIT(src.w, dst.z, src.x ) */
                memset(&alu, 0, sizeof(struct r600_bc_alu));
                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MUL_LIT);
-               alu.src[0] = r600_src[0];
-               alu.src[0].chan = tgsi_chan(&inst->Src[0], 3);
+               r600_bc_src(&alu.src[0], &ctx->src[0], 3);
                alu.src[1].sel  = sel;
                alu.src[1].chan = chan;
 
-               alu.src[2] = r600_src[0];
-               alu.src[2].chan = tgsi_chan(&inst->Src[0], 0);
+               r600_bc_src(&alu.src[2], &ctx->src[0], 0);
                alu.dst.sel = ctx->temp_reg;
                alu.dst.chan = 0;
                alu.dst.write = 1;
@@ -1310,9 +1341,7 @@ static int tgsi_lit(struct r600_shader_ctx *ctx)
                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_EXP_IEEE);
                alu.src[0].sel = ctx->temp_reg;
                alu.src[0].chan = 0;
-               r = tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst);
-               if (r)
-                       return r;
+               tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst);
                alu.last = 1;
                r = r600_bc_add_alu(ctx->bc, &alu);
                if (r)
@@ -1336,10 +1365,7 @@ static int tgsi_rsq(struct r600_shader_ctx *ctx)
        alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_RECIPSQRT_CLAMPED);
 
        for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
-               r = tgsi_src(ctx, &inst->Src[i], &alu.src[i]);
-               if (r)
-                       return r;
-               alu.src[i].chan = tgsi_chan(&inst->Src[i], 0);
+               r600_bc_src(&alu.src[i], &ctx->src[i], 0);
                alu.src[i].abs = 1;
        }
        alu.dst.sel = ctx->temp_reg;
@@ -1363,9 +1389,7 @@ static int tgsi_helper_tempx_replicate(struct r600_shader_ctx *ctx)
                alu.src[0].sel = ctx->temp_reg;
                alu.inst = CTX_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;
+               tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
                alu.dst.write = (inst->Dst[0].Register.WriteMask >> i) & 1;
                if (i == 3)
                        alu.last = 1;
@@ -1385,10 +1409,7 @@ static int tgsi_trans_srcx_replicate(struct r600_shader_ctx *ctx)
        memset(&alu, 0, sizeof(struct r600_bc_alu));
        alu.inst = ctx->inst_info->r600_opcode;
        for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
-               r = tgsi_src(ctx, &inst->Src[i], &alu.src[i]);
-               if (r)
-                       return r;
-               alu.src[i].chan = tgsi_chan(&inst->Src[i], 0);
+               r600_bc_src(&alu.src[i], &ctx->src[i], 0);
        }
        alu.dst.sel = ctx->temp_reg;
        alu.dst.write = 1;
@@ -1402,17 +1423,13 @@ static int tgsi_trans_srcx_replicate(struct r600_shader_ctx *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 = CTX_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);
+       r600_bc_src(&alu.src[0], &ctx->src[0], 0);
        alu.dst.sel = ctx->temp_reg;
        alu.dst.write = 1;
        alu.last = 1;
@@ -1422,10 +1439,7 @@ static int tgsi_pow(struct r600_shader_ctx *ctx)
        /* b * LOG2(a) */
        memset(&alu, 0, sizeof(struct r600_bc_alu));
        alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL);
-       r = tgsi_src(ctx, &inst->Src[1], &alu.src[0]);
-       if (r)
-               return r;
-       alu.src[0].chan = tgsi_chan(&inst->Src[1], 0);
+       r600_bc_src(&alu.src[0], &ctx->src[1], 0);
        alu.src[1].sel = ctx->temp_reg;
        alu.dst.sel = ctx->temp_reg;
        alu.dst.write = 1;
@@ -1450,16 +1464,8 @@ 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;
-       r = tgsi_split_literal_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));
@@ -1469,13 +1475,10 @@ static int tgsi_ssg(struct r600_shader_ctx *ctx)
                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);
-
+               r600_bc_src(&alu.src[0], &ctx->src[0], i);
                alu.src[1].sel = V_SQ_ALU_SRC_1;
+               r600_bc_src(&alu.src[2], &ctx->src[0], i);
 
-               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);
@@ -1488,9 +1491,7 @@ static int tgsi_ssg(struct r600_shader_ctx *ctx)
                memset(&alu, 0, sizeof(struct r600_bc_alu));
                alu.inst = CTX_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;
+               tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
 
                alu.src[0].sel = ctx->temp_reg;
                alu.src[0].chan = i;
@@ -1523,9 +1524,7 @@ static int tgsi_helper_copy(struct r600_shader_ctx *ctx, struct tgsi_full_instru
                        alu.dst.chan = i;
                } else {
                        alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV);
-                       r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
-                       if (r)
-                               return r;
+                       tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
                        alu.src[0].sel = ctx->temp_reg;
                        alu.src[0].chan = i;
                }
@@ -1542,17 +1541,10 @@ static int tgsi_helper_copy(struct r600_shader_ctx *ctx, struct tgsi_full_instru
 static int tgsi_op3(struct r600_shader_ctx *ctx)
 {
        struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
-       struct r600_bc_alu_src r600_src[3];
        struct r600_bc_alu alu;
        int i, j, r;
        int lasti = tgsi_last_instruction(inst->Dst[0].Register.WriteMask);
 
-       r = tgsi_split_constant(ctx, r600_src);
-       if (r)
-               return r;
-       r = tgsi_split_literal_constant(ctx, r600_src);
-       if (r)
-               return r;
        for (i = 0; i < lasti + 1; i++) {
                if (!(inst->Dst[0].Register.WriteMask & (1 << i)))
                        continue;
@@ -1560,14 +1552,10 @@ static int tgsi_op3(struct r600_shader_ctx *ctx)
                memset(&alu, 0, sizeof(struct r600_bc_alu));
                alu.inst = ctx->inst_info->r600_opcode;
                for (j = 0; j < inst->Instruction.NumSrcRegs; j++) {
-                       alu.src[j] = r600_src[j];
-                       alu.src[j].chan = tgsi_chan(&inst->Src[j], i);
+                       r600_bc_src(&alu.src[j], &ctx->src[j], i);
                }
 
-               r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
-               if (r)
-                       return r;
-
+               tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
                alu.dst.chan = i;
                alu.dst.write = 1;
                alu.is_op3 = 1;
@@ -1584,28 +1572,17 @@ static int tgsi_op3(struct r600_shader_ctx *ctx)
 static int tgsi_dp(struct r600_shader_ctx *ctx)
 {
        struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
-       struct r600_bc_alu_src r600_src[3];
        struct r600_bc_alu alu;
        int i, j, r;
 
-       r = tgsi_split_constant(ctx, r600_src);
-       if (r)
-               return r;
-       r = tgsi_split_literal_constant(ctx, r600_src);
-       if (r)
-               return r;
        for (i = 0; i < 4; i++) {
                memset(&alu, 0, sizeof(struct r600_bc_alu));
                alu.inst = ctx->inst_info->r600_opcode;
                for (j = 0; j < inst->Instruction.NumSrcRegs; j++) {
-                       alu.src[j] = r600_src[j];
-                       alu.src[j].chan = tgsi_chan(&inst->Src[j], i);
+                       r600_bc_src(&alu.src[j], &ctx->src[j], i);
                }
 
-               r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
-               if (r)
-                       return r;
-
+               tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
                alu.dst.chan = i;
                alu.dst.write = (inst->Dst[0].Register.WriteMask >> i) & 1;
                /* handle some special cases */
@@ -1661,11 +1638,8 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
                /* Add perspective divide */
                memset(&alu, 0, sizeof(struct r600_bc_alu));
                alu.inst = CTX_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;
+               r600_bc_src(&alu.src[0], &ctx->src[0], 3);
 
-               alu.src[0].chan = tgsi_chan(&inst->Src[0], 3);
                alu.dst.sel = ctx->temp_reg;
                alu.dst.chan = 3;
                alu.last = 1;
@@ -1679,10 +1653,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
                        alu.inst = CTX_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);
+                       r600_bc_src(&alu.src[1], &ctx->src[0], i);
                        alu.dst.sel = ctx->temp_reg;
                        alu.dst.chan = i;
                        alu.dst.write = 1;
@@ -1735,14 +1706,8 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
                                src2_chan = 0;
                                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);
+                       r600_bc_src(&alu.src[0], &ctx->src[0], src_chan);
+                       r600_bc_src(&alu.src[1], &ctx->src[0], src2_chan);
                        alu.dst.sel = ctx->temp_reg;
                        alu.dst.chan = i;
                        if (i == 3)
@@ -1782,7 +1747,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
 
                alu.src[2].sel = V_SQ_ALU_SRC_LITERAL;
                alu.src[2].chan = 0;
-               alu.src[2].value = (u32*)&one_point_five;
+               alu.src[2].value = *(uint32_t *)&one_point_five;
 
                alu.dst.sel = ctx->temp_reg;
                alu.dst.chan = 0;
@@ -1803,7 +1768,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
 
                alu.src[2].sel = V_SQ_ALU_SRC_LITERAL;
                alu.src[2].chan = 0;
-               alu.src[2].value = (u32*)&one_point_five;
+               alu.src[2].value = *(uint32_t *)&one_point_five;
 
                alu.dst.sel = ctx->temp_reg;
                alu.dst.chan = 1;
@@ -1822,10 +1787,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
                for (i = 0; i < 4; i++) {
                        memset(&alu, 0, sizeof(struct r600_bc_alu));
                        alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV);
-                       r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
-                       if (r)
-                               return r;
-                       alu.src[0].chan = tgsi_chan(&inst->Src[0], i);
+                       r600_bc_src(&alu.src[0], &ctx->src[0], i);
                        alu.dst.sel = ctx->temp_reg;
                        alu.dst.chan = i;
                        if (i == 3)
@@ -1846,7 +1808,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
        memset(&tex, 0, sizeof(struct r600_bc_tex));
        tex.inst = opcode;
        tex.sampler_id = ctx->file_offset[inst->Src[1].Register.File] + inst->Src[1].Register.Index;
-       tex.resource_id = tex.sampler_id;
+       tex.resource_id = tex.sampler_id + R600_MAX_CONST_BUFFERS;
        tex.src_gpr = src_gpr;
        tex.dst_gpr = ctx->file_offset[inst->Dst[0].Register.File] + inst->Dst[0].Register.Index;
        tex.dst_sel_x = (inst->Dst[0].Register.WriteMask & 1) ? 0 : 7;
@@ -1872,6 +1834,12 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
                tex.coord_type_w = 1;
        }
 
+       if (inst->Texture.Texture == TGSI_TEXTURE_1D_ARRAY) {
+               tex.coord_type_z = 0;
+               tex.src_sel_z = 1;
+       } else if (inst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY)
+               tex.coord_type_z = 0;
+
        if (inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D || inst->Texture.Texture == TGSI_TEXTURE_SHADOW2D)
                tex.src_sel_w = 2;
 
@@ -1886,36 +1854,23 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
 static int tgsi_lrp(struct r600_shader_ctx *ctx)
 {
        struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
-       struct r600_bc_alu_src r600_src[3];
        struct r600_bc_alu alu;
        int lasti = tgsi_last_instruction(inst->Dst[0].Register.WriteMask);
        unsigned i;
        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;
-
        /* optimize if it's just an equal balance */
-       if(r600_src[0].sel == V_SQ_ALU_SRC_0_5) {
+       if (ctx->src[0].sel == V_SQ_ALU_SRC_0_5) {
                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(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD);
-                       alu.src[0] = r600_src[1];
-                       alu.src[0].chan = tgsi_chan(&inst->Src[1], i);
-                       alu.src[1] = r600_src[2];
-                       alu.src[1].chan = tgsi_chan(&inst->Src[2], i);
+                       r600_bc_src(&alu.src[0], &ctx->src[1], i);
+                       r600_bc_src(&alu.src[1], &ctx->src[2], i);
                        alu.omod = 3;
-                       r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
-                       if (r)
-                               return r;
-
+                       tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
                        alu.dst.chan = i;
                        if (i == lasti) {
                                alu.last = 1;
@@ -1936,8 +1891,7 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx)
                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_ADD);
                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);
+               r600_bc_src(&alu.src[1], &ctx->src[0], i);
                alu.src[1].neg = 1;
                alu.dst.sel = ctx->temp_reg;
                alu.dst.chan = i;
@@ -1959,8 +1913,7 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx)
                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL);
                alu.src[0].sel = ctx->temp_reg;
                alu.src[0].chan = i;
-               alu.src[1] = r600_src[2];
-               alu.src[1].chan = tgsi_chan(&inst->Src[2], i);
+               r600_bc_src(&alu.src[1], &ctx->src[2], i);
                alu.dst.sel = ctx->temp_reg;
                alu.dst.chan = i;
                if (i == lasti) {
@@ -1980,17 +1933,12 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx)
                memset(&alu, 0, sizeof(struct r600_bc_alu));
                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_MULADD);
                alu.is_op3 = 1;
-               alu.src[0] = r600_src[0];
-               alu.src[0].chan = tgsi_chan(&inst->Src[0], i);
-               alu.src[1] = r600_src[1];
-               alu.src[1].chan = tgsi_chan(&inst->Src[1], i);
+               r600_bc_src(&alu.src[0], &ctx->src[0], i);
+               r600_bc_src(&alu.src[1], &ctx->src[1], i);
                alu.src[2].sel = ctx->temp_reg;
                alu.src[2].chan = i;
 
-               r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
-               if (r)
-                       return r;
-
+               tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
                alu.dst.chan = i;
                if (i == lasti) {
                        alu.last = 1;
@@ -2005,37 +1953,20 @@ static int tgsi_lrp(struct r600_shader_ctx *ctx)
 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 i, r;
        int lasti = tgsi_last_instruction(inst->Dst[0].Register.WriteMask);
 
-       r = tgsi_split_constant(ctx, r600_src);
-       if (r)
-               return r;
-       r = tgsi_split_literal_constant(ctx, r600_src);
-       if (r)
-               return r;
-
        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(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);
-
-               r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
-               if (r)
-                       return r;
-
+               r600_bc_src(&alu.src[0], &ctx->src[0], i);
+               r600_bc_src(&alu.src[1], &ctx->src[2], i);
+               r600_bc_src(&alu.src[2], &ctx->src[1], i);
+               tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
                alu.dst.chan = i;
                alu.dst.write = 1;
                alu.is_op3 = 1;
@@ -2051,7 +1982,6 @@ static int tgsi_cmp(struct r600_shader_ctx *ctx)
 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;
@@ -2059,43 +1989,34 @@ static int tgsi_xpd(struct r600_shader_ctx *ctx)
        if (inst->Dst[0].Register.WriteMask != 0xf)
                use_temp = 1;
 
-       r = tgsi_split_constant(ctx, r600_src);
-       if (r)
-               return r;
-       r = tgsi_split_literal_constant(ctx, r600_src);
-       if (r)
-               return r;
-
        for (i = 0; i < 4; i++) {
                memset(&alu, 0, sizeof(struct r600_bc_alu));
                alu.inst = CTX_INST(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);
+                       r600_bc_src(&alu.src[0], &ctx->src[0], 2);
                        break;
                case 1:
-                       alu.src[0].chan = tgsi_chan(&inst->Src[0], 0);
+                       r600_bc_src(&alu.src[0], &ctx->src[0], 0);
                        break;
                case 2:
-                       alu.src[0].chan = tgsi_chan(&inst->Src[0], 1);
+                       r600_bc_src(&alu.src[0], &ctx->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);
+                       r600_bc_src(&alu.src[1], &ctx->src[1], 1);
                        break;
                case 1:
-                       alu.src[1].chan = tgsi_chan(&inst->Src[1], 2);
+                       r600_bc_src(&alu.src[1], &ctx->src[1], 2);
                        break;
                case 2:
-                       alu.src[1].chan = tgsi_chan(&inst->Src[1], 0);
+                       r600_bc_src(&alu.src[1], &ctx->src[1], 0);
                        break;
                case 3:
                        alu.src[1].sel = V_SQ_ALU_SRC_0;
@@ -2117,32 +2038,30 @@ static int tgsi_xpd(struct r600_shader_ctx *ctx)
                memset(&alu, 0, sizeof(struct r600_bc_alu));
                alu.inst = CTX_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);
+                       r600_bc_src(&alu.src[0], &ctx->src[0], 1);
                        break;
                case 1:
-                       alu.src[0].chan = tgsi_chan(&inst->Src[0], 2);
+                       r600_bc_src(&alu.src[0], &ctx->src[0], 2);
                        break;
                case 2:
-                       alu.src[0].chan = tgsi_chan(&inst->Src[0], 0);
+                       r600_bc_src(&alu.src[0], &ctx->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);
+                       r600_bc_src(&alu.src[1], &ctx->src[1], 2);
                        break;
                case 1:
-                       alu.src[1].chan = tgsi_chan(&inst->Src[1], 0);
+                       r600_bc_src(&alu.src[1], &ctx->src[1], 0);
                        break;
                case 2:
-                       alu.src[1].chan = tgsi_chan(&inst->Src[1], 1);
+                       r600_bc_src(&alu.src[1], &ctx->src[1], 1);
                        break;
                case 3:
                        alu.src[1].sel = V_SQ_ALU_SRC_0;
@@ -2155,11 +2074,8 @@ static int tgsi_xpd(struct r600_shader_ctx *ctx)
 
                if (use_temp)
                        alu.dst.sel = ctx->temp_reg;
-               else {
-                       r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
-                       if (r)
-                               return r;
-               }
+               else
+                       tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
                alu.dst.chan = i;
                alu.dst.write = 1;
                alu.is_op3 = 1;
@@ -2177,7 +2093,6 @@ static int tgsi_xpd(struct r600_shader_ctx *ctx)
 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] = { { 0 } };
        struct r600_bc_alu alu;
        int r;
 
@@ -2186,11 +2101,7 @@ static int tgsi_exp(struct r600_shader_ctx *ctx)
                memset(&alu, 0, sizeof(struct r600_bc_alu));
 
                alu.inst = CTX_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);
+               r600_bc_src(&alu.src[0], &ctx->src[0], 0);
 
                alu.dst.sel = ctx->temp_reg;
                alu.dst.chan = 0;
@@ -2218,11 +2129,7 @@ static int tgsi_exp(struct r600_shader_ctx *ctx)
                memset(&alu, 0, sizeof(struct r600_bc_alu));
 
                alu.inst = CTX_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);
+               r600_bc_src(&alu.src[0], &ctx->src[0], 0);
 
                alu.dst.sel = ctx->temp_reg;
 //             r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
@@ -2242,10 +2149,7 @@ static int tgsi_exp(struct r600_shader_ctx *ctx)
        if ((inst->Dst[0].Register.WriteMask >> 2) & 0x1) {
                memset(&alu, 0, sizeof(struct r600_bc_alu));
                alu.inst = CTX_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);
+               r600_bc_src(&alu.src[0], &ctx->src[0], 0);
 
                alu.dst.sel = ctx->temp_reg;
                alu.dst.write = 1;
@@ -2288,11 +2192,7 @@ static int tgsi_log(struct r600_shader_ctx *ctx)
                memset(&alu, 0, sizeof(struct r600_bc_alu));
 
                alu.inst = CTX_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);
+               r600_bc_src(&alu.src[0], &ctx->src[0], 0);
 
                alu.dst.sel = ctx->temp_reg;
                alu.dst.chan = 0;
@@ -2321,11 +2221,7 @@ static int tgsi_log(struct r600_shader_ctx *ctx)
                memset(&alu, 0, sizeof(struct r600_bc_alu));
 
                alu.inst = CTX_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);
+               r600_bc_src(&alu.src[0], &ctx->src[0], 0);
 
                alu.dst.sel = ctx->temp_reg;
                alu.dst.chan = 1;
@@ -2385,11 +2281,7 @@ static int tgsi_log(struct r600_shader_ctx *ctx)
 
                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL);
 
-               r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
-               if (r)
-                       return r;
-
-               alu.src[0].chan = tgsi_chan(&inst->Src[0], 0);
+               r600_bc_src(&alu.src[0], &ctx->src[0], 0);
 
                alu.src[1].sel = ctx->temp_reg;
                alu.src[1].chan = 1;
@@ -2409,11 +2301,7 @@ static int tgsi_log(struct r600_shader_ctx *ctx)
                memset(&alu, 0, sizeof(struct r600_bc_alu));
 
                alu.inst = CTX_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);
+               r600_bc_src(&alu.src[0], &ctx->src[0], 0);
 
                alu.dst.sel = ctx->temp_reg;
                alu.dst.write = 1;
@@ -2451,6 +2339,7 @@ static int tgsi_eg_arl(struct r600_shader_ctx *ctx)
        struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
        struct r600_bc_alu alu;
        int r;
+
        memset(&alu, 0, sizeof(struct r600_bc_alu));
 
        switch (inst->Instruction.Opcode) {
@@ -2465,23 +2354,23 @@ static int tgsi_eg_arl(struct r600_shader_ctx *ctx)
                return -1;
        }
 
-       r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
-       if (r)
-               return r;
-       alu.src[0].chan = tgsi_chan(&inst->Src[0], 0);
+       r600_bc_src(&alu.src[0], &ctx->src[0], 0);
        alu.last = 1;
-       alu.dst.chan = 0;
-       alu.dst.sel = ctx->temp_reg;
+       alu.dst.sel = ctx->ar_reg;
        alu.dst.write = 1;
        r = r600_bc_add_alu(ctx->bc, &alu);
        if (r)
                return r;
+
+       /* TODO: Note that the MOVA can be avoided if we never use AR for
+        * indexing non-CB registers in the current ALU clause. Similarly, we
+        * need to load AR from ar_reg again if we started a new clause
+        * between ARL and AR usage. The easy way to do that is to remove
+        * the MOVA here, and load it for the first AR access after ar_reg
+        * has been modified in each clause. */
        memset(&alu, 0, sizeof(struct r600_bc_alu));
        alu.inst = EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_INT;
-       r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
-       if (r)
-               return r;
-       alu.src[0].sel = ctx->temp_reg;
+       alu.src[0].sel = ctx->ar_reg;
        alu.src[0].chan = 0;
        alu.last = 1;
        r = r600_bc_add_alu(ctx->bc, &alu);
@@ -2495,26 +2384,48 @@ static int tgsi_r600_arl(struct r600_shader_ctx *ctx)
        struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
        struct r600_bc_alu alu;
        int r;
-       memset(&alu, 0, sizeof(struct r600_bc_alu));
 
        switch (inst->Instruction.Opcode) {
        case TGSI_OPCODE_ARL:
-               alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_FLOOR;
+               memset(&alu, 0, sizeof(alu));
+               alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLOOR;
+               r600_bc_src(&alu.src[0], &ctx->src[0], 0);
+               alu.dst.sel = ctx->ar_reg;
+               alu.dst.write = 1;
+               alu.last = 1;
+
+               if ((r = r600_bc_add_alu(ctx->bc, &alu)))
+                       return r;
+
+               memset(&alu, 0, sizeof(alu));
+               alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_INT;
+               alu.src[0].sel = ctx->ar_reg;
+               alu.dst.sel = ctx->ar_reg;
+               alu.dst.write = 1;
+               alu.last = 1;
+
+               if ((r = r600_bc_add_alu(ctx->bc, &alu)))
+                       return r;
                break;
        case TGSI_OPCODE_ARR:
-               alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA;
+               memset(&alu, 0, sizeof(alu));
+               alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_INT;
+               r600_bc_src(&alu.src[0], &ctx->src[0], 0);
+               alu.dst.sel = ctx->ar_reg;
+               alu.dst.write = 1;
+               alu.last = 1;
+
+               if ((r = r600_bc_add_alu(ctx->bc, &alu)))
+                       return r;
                break;
        default:
                assert(0);
                return -1;
        }
 
-
-       r = tgsi_src(ctx, &inst->Src[0], &alu.src[0]);
-       if (r)
-               return r;
-       alu.src[0].chan = tgsi_chan(&inst->Src[0], 0);
-
+       memset(&alu, 0, sizeof(alu));
+       alu.inst = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOVA_INT;
+       alu.src[0].sel = ctx->ar_reg;
        alu.last = 1;
 
        r = r600_bc_add_alu(ctx->bc, &alu);
@@ -2534,26 +2445,18 @@ static int tgsi_opdst(struct r600_shader_ctx *ctx)
                memset(&alu, 0, sizeof(struct r600_bc_alu));
 
                alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MUL);
-               r = tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
-               if (r)
-                       return r;
+               tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
 
                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);
+                       r600_bc_src(&alu.src[0], &ctx->src[0], i);
                }
 
-               if (i == 0 || i == 2) {
+               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);
+                       r600_bc_src(&alu.src[1], &ctx->src[1], i);
                }
                if (i == 3)
                        alu.last = 1;
@@ -2566,7 +2469,6 @@ static int tgsi_opdst(struct r600_shader_ctx *ctx)
 
 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;
 
@@ -2578,10 +2480,7 @@ static int emit_logic_pred(struct r600_shader_ctx *ctx, int opcode)
        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);
+       r600_bc_src(&alu.src[0], &ctx->src[0], 0);
        alu.src[1].sel = V_SQ_ALU_SRC_0;
        alu.src[1].chan = 0;
 
index 935dd6fe3abebf4d41071f55997138bed83007c8..8f96ce5085cae1fb1c40d2a22f0c95858c77213c 100644 (file)
@@ -45,8 +45,7 @@ struct r600_shader {
        struct r600_shader_io   output[32];
        enum radeon_family      family;
        boolean                 uses_kill;
+       boolean                 fs_write_all;
 };
 
-int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader, u32 **literals);
-
 #endif
index de2668cee163f38d07ec1cb9c689e632f75e8d5d..576067ae81e215861d30927b73c14e001c1665e7 100644 (file)
@@ -37,6 +37,7 @@
 #include <util/u_memory.h>
 #include <util/u_inlines.h>
 #include <util/u_framebuffer.h>
+#include "util/u_transfer.h"
 #include <pipebuffer/pb_buffer.h>
 #include "r600.h"
 #include "r600d.h"
@@ -94,221 +95,6 @@ void r600_polygon_offset_update(struct r600_pipe_context *rctx)
        }
 }
 
-/* FIXME optimize away spi update when it's not needed */
-static void r600_spi_update(struct r600_pipe_context *rctx)
-{
-       struct r600_pipe_shader *shader = rctx->ps_shader;
-       struct r600_pipe_state rstate;
-       struct r600_shader *rshader = &shader->shader;
-       unsigned i, tmp;
-
-       rstate.nregs = 0;
-       for (i = 0; i < rshader->ninput; i++) {
-               tmp = S_028644_SEMANTIC(r600_find_vs_semantic_index(&rctx->vs_shader->shader, rshader, i));
-               if (rshader->input[i].centroid)
-                       tmp |= S_028644_SEL_CENTROID(1);
-               if (rshader->input[i].interpolate == TGSI_INTERPOLATE_LINEAR)
-                       tmp |= S_028644_SEL_LINEAR(1);
-
-               if (rshader->input[i].name == TGSI_SEMANTIC_COLOR ||
-                   rshader->input[i].name == TGSI_SEMANTIC_BCOLOR ||
-                   rshader->input[i].name == TGSI_SEMANTIC_POSITION) {
-                       tmp |= S_028644_FLAT_SHADE(rctx->flatshade);
-               }
-               if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC &&
-                       rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) {
-                       tmp |= S_028644_PT_SPRITE_TEX(1);
-               }
-               r600_pipe_state_add_reg(&rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL);
-       }
-       r600_context_pipe_state_set(&rctx->ctx, &rstate);
-}
-
-void r600_vertex_buffer_update(struct r600_pipe_context *rctx)
-{
-       struct r600_pipe_state *rstate;
-       struct r600_resource *rbuffer;
-       struct pipe_vertex_buffer *vertex_buffer;
-       unsigned i, offset;
-
-       /* we don't update until we know vertex elements */
-       if (rctx->vertex_elements == NULL || !rctx->nvertex_buffer)
-               return;
-
-       if (rctx->vertex_elements->incompatible_layout) {
-               /* translate rebind new vertex elements so
-                * return once translated
-                */
-               r600_begin_vertex_translate(rctx);
-               return;
-       }
-
-       if (rctx->any_user_vbs) {
-               r600_upload_user_buffers(rctx);
-               rctx->any_user_vbs = FALSE;
-       }
-
-       if (rctx->vertex_elements->vbuffer_need_offset) {
-               /* one resource per vertex elements */
-               rctx->nvs_resource = rctx->vertex_elements->count;
-       } else {
-               /* bind vertex buffer once */
-               rctx->nvs_resource = rctx->nvertex_buffer;
-       }
-
-       for (i = 0 ; i < rctx->nvs_resource; i++) {
-               rstate = &rctx->vs_resource[i];
-               rstate->id = R600_PIPE_STATE_RESOURCE;
-               rstate->nregs = 0;
-
-               if (rctx->vertex_elements->vbuffer_need_offset) {
-                       /* one resource per vertex elements */
-                       unsigned vbuffer_index;
-                       vbuffer_index = rctx->vertex_elements->elements[i].vertex_buffer_index;
-                       vertex_buffer = &rctx->vertex_buffer[vbuffer_index];
-                       rbuffer = (struct r600_resource*)vertex_buffer->buffer;
-                       offset = rctx->vertex_elements->vbuffer_offset[i];
-               } else {
-                       /* bind vertex buffer once */
-                       vertex_buffer = &rctx->vertex_buffer[i];
-                       rbuffer = (struct r600_resource*)vertex_buffer->buffer;
-                       offset = 0;
-               }
-               if (vertex_buffer == NULL || rbuffer == NULL)
-                       continue;
-               offset += vertex_buffer->buffer_offset + r600_bo_offset(rbuffer->bo);
-
-               r600_pipe_state_add_reg(rstate, R_038000_RESOURCE0_WORD0,
-                                       offset, 0xFFFFFFFF, rbuffer->bo);
-               r600_pipe_state_add_reg(rstate, R_038004_RESOURCE0_WORD1,
-                                       rbuffer->bo_size - offset - 1, 0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(rstate, R_038008_RESOURCE0_WORD2,
-                                       S_038008_STRIDE(vertex_buffer->stride),
-                                       0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(rstate, R_03800C_RESOURCE0_WORD3,
-                                       0x00000000, 0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(rstate, R_038010_RESOURCE0_WORD4,
-                                       0x00000000, 0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(rstate, R_038014_RESOURCE0_WORD5,
-                                       0x00000000, 0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(rstate, R_038018_RESOURCE0_WORD6,
-                                       0xC0000000, 0xFFFFFFFF, NULL);
-               r600_context_pipe_state_set_fs_resource(&rctx->ctx, rstate, i);
-       }
-}
-
-static void r600_draw_common(struct r600_drawl *draw)
-{
-       struct r600_pipe_context *rctx = (struct r600_pipe_context *)draw->ctx;
-       struct r600_resource *rbuffer;
-       unsigned prim;
-       u32 vgt_dma_index_type, vgt_draw_initiator, mask;
-       struct r600_draw rdraw;
-       struct r600_pipe_state vgt;
-
-       switch (draw->index_size) {
-       case 2:
-               vgt_draw_initiator = 0;
-               vgt_dma_index_type = 0;
-               break;
-       case 4:
-               vgt_draw_initiator = 0;
-               vgt_dma_index_type = 1;
-               break;
-       case 0:
-               vgt_draw_initiator = 2;
-               vgt_dma_index_type = 0;
-               break;
-       default:
-               R600_ERR("unsupported index size %d\n", draw->index_size);
-               return;
-       }
-       if (r600_conv_pipe_prim(draw->mode, &prim))
-               return;
-       if (unlikely(rctx->ps_shader == NULL)) {
-               R600_ERR("missing vertex shader\n");
-               return;
-       }
-       if (unlikely(rctx->vs_shader == NULL)) {
-               R600_ERR("missing vertex shader\n");
-               return;
-       }
-       /* there should be enough input */
-       if (rctx->vertex_elements->count < rctx->vs_shader->shader.bc.nresource) {
-               R600_ERR("%d resources provided, expecting %d\n",
-                       rctx->vertex_elements->count, rctx->vs_shader->shader.bc.nresource);
-               return;
-       }
-
-       r600_spi_update(rctx);
-
-       mask = 0;
-       for (int i = 0; i < rctx->framebuffer.nr_cbufs; i++) {
-               mask |= (0xF << (i * 4));
-       }
-
-       vgt.id = R600_PIPE_STATE_VGT;
-       vgt.nregs = 0;
-       r600_pipe_state_add_reg(&vgt, R_008958_VGT_PRIMITIVE_TYPE, prim, 0xFFFFFFFF, NULL);
-       r600_pipe_state_add_reg(&vgt, R_028408_VGT_INDX_OFFSET, draw->index_bias, 0xFFFFFFFF, NULL);
-       r600_pipe_state_add_reg(&vgt, R_028400_VGT_MAX_VTX_INDX, draw->max_index, 0xFFFFFFFF, NULL);
-       r600_pipe_state_add_reg(&vgt, R_028404_VGT_MIN_VTX_INDX, draw->min_index, 0xFFFFFFFF, NULL);
-       r600_pipe_state_add_reg(&vgt, R_028238_CB_TARGET_MASK, rctx->cb_target_mask & mask, 0xFFFFFFFF, NULL);
-       r600_pipe_state_add_reg(&vgt, R_03CFF0_SQ_VTX_BASE_VTX_LOC, 0, 0xFFFFFFFF, NULL);
-       r600_pipe_state_add_reg(&vgt, R_03CFF4_SQ_VTX_START_INST_LOC, 0, 0xFFFFFFFF, NULL);
-       r600_context_pipe_state_set(&rctx->ctx, &vgt);
-
-       rdraw.vgt_num_indices = draw->count;
-       rdraw.vgt_num_instances = 1;
-       rdraw.vgt_index_type = vgt_dma_index_type;
-       rdraw.vgt_draw_initiator = vgt_draw_initiator;
-       rdraw.indices = NULL;
-       if (draw->index_buffer) {
-               rbuffer = (struct r600_resource*)draw->index_buffer;
-               rdraw.indices = rbuffer->bo;
-               rdraw.indices_bo_offset = draw->index_buffer_offset;
-       }
-       r600_context_draw(&rctx->ctx, &rdraw);
-}
-
-void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
-{
-       struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
-       struct r600_drawl draw;
-
-       memset(&draw, 0, sizeof(struct r600_drawl));
-       draw.ctx = ctx;
-       draw.mode = info->mode;
-       draw.start = info->start;
-       draw.count = info->count;
-       if (info->indexed && rctx->index_buffer.buffer) {
-               draw.start += rctx->index_buffer.offset / rctx->index_buffer.index_size;
-               draw.min_index = info->min_index;
-               draw.max_index = info->max_index;
-               draw.index_bias = info->index_bias;
-
-               r600_translate_index_buffer(rctx, &rctx->index_buffer.buffer,
-                                           &rctx->index_buffer.index_size,
-                                           &draw.start,
-                                           info->count);
-
-               draw.index_size = rctx->index_buffer.index_size;
-               pipe_resource_reference(&draw.index_buffer, rctx->index_buffer.buffer);
-               draw.index_buffer_offset = draw.start * draw.index_size;
-               draw.start = 0;
-               r600_upload_index_buffer(rctx, &draw);
-       } else {
-               draw.index_size = 0;
-               draw.index_buffer = NULL;
-               draw.min_index = info->min_index;
-               draw.max_index = info->max_index;
-               draw.index_bias = info->start;
-       }
-       r600_draw_common(&draw);
-
-       pipe_resource_reference(&draw.index_buffer, NULL);
-}
-
 static void r600_set_blend_color(struct pipe_context *ctx,
                                        const struct pipe_blend_color *state)
 {
@@ -616,6 +402,7 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c
        uint32_t word4 = 0, yuv_format = 0, pitch = 0;
        unsigned char swizzle[4], array_mode = 0, tile_type = 0;
        struct r600_bo *bo[2];
+       unsigned height, depth;
 
        if (resource == NULL)
                return NULL;
@@ -643,22 +430,30 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c
        if (desc == NULL) {
                R600_ERR("unknow format %d\n", state->format);
        }
-       tmp = (struct r600_resource_texture*)texture;
+       tmp = (struct r600_resource_texture *)texture;
+       if (tmp->depth && !tmp->is_flushing_texture) {
+               r600_texture_depth_flush(ctx, texture, TRUE);
+               tmp = tmp->flushed_depth_texture;
+       }
+
+       if (tmp->force_int_type) {
+               word4 &= C_038010_NUM_FORMAT_ALL;
+               word4 |= S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_INT);
+       }
        rbuffer = &tmp->resource;
        bo[0] = rbuffer->bo;
        bo[1] = rbuffer->bo;
-       /* FIXME depth texture decompression */
-       if (tmp->depth) {
-               r600_texture_depth_flush(ctx, texture);
-               tmp = (struct r600_resource_texture*)texture;
-               rbuffer = &tmp->flushed_depth_texture->resource;
-               bo[0] = rbuffer->bo;
-               bo[1] = rbuffer->bo;
-       }
-       pitch = align(tmp->pitch_in_pixels[0], 8);
-       if (tmp->tiled) {
-               array_mode = tmp->array_mode[0];
-               tile_type = tmp->tile_type;
+       pitch = align(tmp->pitch_in_blocks[0] * util_format_get_blockwidth(state->format), 8);
+       array_mode = tmp->array_mode[0];
+       tile_type = tmp->tile_type;
+
+       height = texture->height0;
+       depth = texture->depth0;
+       if (texture->target == PIPE_TEXTURE_1D_ARRAY) {
+               height = 1;
+               depth = texture->array_size;
+       } else if (texture->target == PIPE_TEXTURE_2D_ARRAY) {
+               depth = texture->array_size;
        }
 
        /* FIXME properly handle first level != 0 */
@@ -669,22 +464,22 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c
                                S_038000_PITCH((pitch / 8) - 1) |
                                S_038000_TEX_WIDTH(texture->width0 - 1), 0xFFFFFFFF, NULL);
        r600_pipe_state_add_reg(rstate, R_038004_RESOURCE0_WORD1,
-                               S_038004_TEX_HEIGHT(texture->height0 - 1) |
-                               S_038004_TEX_DEPTH(texture->depth0 - 1) |
+                               S_038004_TEX_HEIGHT(height - 1) |
+                               S_038004_TEX_DEPTH(depth - 1) |
                                S_038004_DATA_FORMAT(format), 0xFFFFFFFF, NULL);
        r600_pipe_state_add_reg(rstate, R_038008_RESOURCE0_WORD2,
                                (tmp->offset[0] + r600_bo_offset(bo[0])) >> 8, 0xFFFFFFFF, bo[0]);
        r600_pipe_state_add_reg(rstate, R_03800C_RESOURCE0_WORD3,
                                (tmp->offset[1] + r600_bo_offset(bo[1])) >> 8, 0xFFFFFFFF, bo[1]);
        r600_pipe_state_add_reg(rstate, R_038010_RESOURCE0_WORD4,
-                               word4 | S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_NORM) |
+                               word4 |
                                S_038010_SRF_MODE_ALL(V_038010_SRF_MODE_NO_ZERO) |
                                S_038010_REQUEST_SIZE(1) |
                                S_038010_BASE_LEVEL(state->u.tex.first_level), 0xFFFFFFFF, NULL);
        r600_pipe_state_add_reg(rstate, R_038014_RESOURCE0_WORD5,
                                S_038014_LAST_LEVEL(state->u.tex.last_level) |
-                               S_038014_BASE_ARRAY(0) |
-                               S_038014_LAST_ARRAY(0), 0xFFFFFFFF, NULL);
+                               S_038014_BASE_ARRAY(state->u.tex.first_layer) |
+                               S_038014_LAST_ARRAY(state->u.tex.last_layer), 0xFFFFFFFF, NULL);
        r600_pipe_state_add_reg(rstate, R_038018_RESOURCE0_WORD6,
                                S_038018_TYPE(V_038010_SQ_TEX_VTX_VALID_TEXTURE), 0xFFFFFFFF, NULL);
 
@@ -714,9 +509,11 @@ static void r600_set_ps_sampler_view(struct pipe_context *ctx, unsigned count,
        for (i = 0; i < count; i++) {
                if (&rctx->ps_samplers.views[i]->base != views[i]) {
                        if (resource[i])
-                               r600_context_pipe_state_set_ps_resource(&rctx->ctx, &resource[i]->state, i);
+                               r600_context_pipe_state_set_ps_resource(&rctx->ctx, &resource[i]->state,
+                                                                       i + R600_MAX_CONST_BUFFERS);
                        else
-                               r600_context_pipe_state_set_ps_resource(&rctx->ctx, NULL, i);
+                               r600_context_pipe_state_set_ps_resource(&rctx->ctx, NULL,
+                                                                       i + R600_MAX_CONST_BUFFERS);
 
                        pipe_sampler_view_reference(
                                (struct pipe_sampler_view **)&rctx->ps_samplers.views[i],
@@ -726,7 +523,8 @@ static void r600_set_ps_sampler_view(struct pipe_context *ctx, unsigned count,
        }
        for (i = count; i < NUM_TEX_UNITS; i++) {
                if (rctx->ps_samplers.views[i]) {
-                       r600_context_pipe_state_set_ps_resource(&rctx->ctx, NULL, i);
+                       r600_context_pipe_state_set_ps_resource(&rctx->ctx, NULL,
+                                                               i + R600_MAX_CONST_BUFFERS);
                        pipe_sampler_view_reference((struct pipe_sampler_view **)&rctx->ps_samplers.views[i], NULL);
                }
        }
@@ -908,21 +706,28 @@ static void r600_cb(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta
        unsigned offset;
        const struct util_format_description *desc;
        struct r600_bo *bo[3];
+       int i;
 
        surf = (struct r600_surface *)state->cbufs[cb];
        rtex = (struct r600_resource_texture*)state->cbufs[cb]->texture;
+
+       if (rtex->depth && !rtex->is_flushing_texture) {
+               r600_texture_depth_flush(&rctx->context, state->cbufs[cb]->texture, TRUE);
+               rtex = rtex->flushed_depth_texture;
+       }
+
        rbuffer = &rtex->resource;
        bo[0] = rbuffer->bo;
        bo[1] = rbuffer->bo;
        bo[2] = rbuffer->bo;
 
        /* XXX quite sure for dx10+ hw don't need any offset hacks */
-       offset = r600_texture_get_offset((struct r600_resource_texture *)state->cbufs[cb]->texture,
+       offset = r600_texture_get_offset(rtex,
                                         level, state->cbufs[cb]->u.tex.first_layer);
-       pitch = rtex->pitch_in_pixels[level] / 8 - 1;
-       slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
+       pitch = rtex->pitch_in_blocks[level] / 8 - 1;
+       slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1;
        ntype = 0;
-       desc = util_format_description(rtex->resource.base.b.format);
+       desc = util_format_description(surf->base.format);
        if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
                ntype = V_0280A0_NUMBER_SRGB;
         else if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN) {
@@ -937,15 +742,30 @@ static void r600_cb(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta
                }
        }
 
-       format = r600_translate_colorformat(rtex->resource.base.b.format);
-       swap = r600_translate_colorswap(rtex->resource.base.b.format);
+       for (i = 0; i < 4; i++) {
+               if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {
+                       break;
+               }
+       }
+
+       format = r600_translate_colorformat(surf->base.format);
+       swap = r600_translate_colorswap(surf->base.format);
+
+       /* disable when gallium grows int textures */
+       if ((format == FMT_32_32_32_32 || format == FMT_16_16_16_16) && rtex->force_int_type)
+               ntype = 4;
+
        color_info = S_0280A0_FORMAT(format) |
                S_0280A0_COMP_SWAP(swap) |
                S_0280A0_ARRAY_MODE(rtex->array_mode[level]) |
                S_0280A0_BLEND_CLAMP(1) |
                S_0280A0_NUMBER_TYPE(ntype);
-       if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
-               color_info |= S_0280A0_SOURCE_FORMAT(1);
+
+       /* on R600 this can't be set if BLEND_CLAMP isn't set,
+          if BLEND_FLOAT32 is set of > 11 bits in a UNORM or SNORM */
+       if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS &&
+           desc->channel[i].size < 12)
+               color_info |= S_0280A0_SOURCE_FORMAT(V_0280A0_EXPORT_NORM);
 
        r600_pipe_state_add_reg(rstate,
                                R_028040_CB_COLOR0_BASE + cb * 4,
@@ -989,17 +809,14 @@ static void r600_db(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta
 
        surf = (struct r600_surface *)state->zsbuf;
        rtex = (struct r600_resource_texture*)state->zsbuf->texture;
-       rtex->tiled = 1;
-       rtex->array_mode[level] = 2;
-       rtex->tile_type = 1;
-       rtex->depth = 1;
+
        rbuffer = &rtex->resource;
 
        /* XXX quite sure for dx10+ hw don't need any offset hacks */
        offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture,
                                         level, state->zsbuf->u.tex.first_layer);
-       pitch = rtex->pitch_in_pixels[level] / 8 - 1;
-       slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
+       pitch = rtex->pitch_in_blocks[level] / 8 - 1;
+       slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1;
        format = r600_translate_dbformat(state->zsbuf->texture->format);
 
        r600_pipe_state_add_reg(rstate, R_02800C_DB_DEPTH_BASE,
@@ -1115,51 +932,6 @@ static void r600_set_framebuffer_state(struct pipe_context *ctx,
        }
 }
 
-static void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
-                                       struct pipe_resource *buffer)
-{
-       struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
-       struct r600_resource *rbuffer = (struct r600_resource*)buffer;
-       uint32_t offset;
-
-       /* Note that the state tracker can unbind constant buffers by
-        * passing NULL here.
-        */
-       if (buffer == NULL) {
-               return;
-       }
-
-       r600_upload_const_buffer(rctx, buffer, &offset);
-
-       switch (shader) {
-       case PIPE_SHADER_VERTEX:
-               rctx->vs_const_buffer.nregs = 0;
-               r600_pipe_state_add_reg(&rctx->vs_const_buffer,
-                                       R_028180_ALU_CONST_BUFFER_SIZE_VS_0,
-                                       ALIGN_DIVUP(buffer->width0 >> 4, 16),
-                                       0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(&rctx->vs_const_buffer,
-                                       R_028980_ALU_CONST_CACHE_VS_0,
-                                       (r600_bo_offset(rbuffer->bo) + offset) >> 8, 0xFFFFFFFF, rbuffer->bo);
-               r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_const_buffer);
-               break;
-       case PIPE_SHADER_FRAGMENT:
-               rctx->ps_const_buffer.nregs = 0;
-               r600_pipe_state_add_reg(&rctx->ps_const_buffer,
-                                       R_028140_ALU_CONST_BUFFER_SIZE_PS_0,
-                                       ALIGN_DIVUP(buffer->width0 >> 4, 16),
-                                       0xFFFFFFFF, NULL);
-               r600_pipe_state_add_reg(&rctx->ps_const_buffer,
-                                       R_028940_ALU_CONST_CACHE_PS_0,
-                                       (r600_bo_offset(rbuffer->bo) + offset) >> 8, 0xFFFFFFFF, rbuffer->bo);
-               r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_const_buffer);
-               break;
-       default:
-               R600_ERR("unsupported %d\n", shader);
-               return;
-       }
-}
-
 void r600_init_state_functions(struct r600_pipe_context *rctx)
 {
        rctx->context.create_blend_state = r600_create_blend_state;
@@ -1199,6 +971,7 @@ void r600_init_state_functions(struct r600_pipe_context *rctx)
        rctx->context.set_vertex_sampler_views = r600_set_vs_sampler_view;
        rctx->context.set_viewport_state = r600_set_viewport_state;
        rctx->context.sampler_view_destroy = r600_sampler_view_destroy;
+       rctx->context.redefine_user_buffer = u_default_redefine_user_buffer;
 }
 
 void r600_init_config(struct r600_pipe_context *rctx)
@@ -1489,3 +1262,25 @@ void *r600_create_db_flush_dsa(struct r600_pipe_context *rctx)
                                S_028D0C_COPY_CENTROID(1), NULL);
        return rstate;
 }
+
+void r600_pipe_set_buffer_resource(struct r600_pipe_context *rctx,
+                                  struct r600_pipe_state *rstate,
+                                  struct r600_resource *rbuffer,
+                                  unsigned offset, unsigned stride)
+{
+       r600_pipe_state_add_reg(rstate, R_038000_RESOURCE0_WORD0,
+                               offset, 0xFFFFFFFF, rbuffer->bo);
+       r600_pipe_state_add_reg(rstate, R_038004_RESOURCE0_WORD1,
+                               rbuffer->bo_size - offset - 1, 0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(rstate, R_038008_RESOURCE0_WORD2,
+                               S_038008_STRIDE(stride),
+                               0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(rstate, R_03800C_RESOURCE0_WORD3,
+                               0x00000000, 0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(rstate, R_038010_RESOURCE0_WORD4,
+                               0x00000000, 0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(rstate, R_038014_RESOURCE0_WORD5,
+                               0x00000000, 0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(rstate, R_038018_RESOURCE0_WORD6,
+                               0xC0000000, 0xFFFFFFFF, NULL);
+}
index 3603376f738b9ffd1faa3537441fe72fbc5903ff..72707fbd8b8b687a6e9ebc6c9c6c8b6a7a6d2d56 100644 (file)
@@ -27,7 +27,9 @@
 #include <util/u_memory.h>
 #include <util/u_format.h>
 #include <pipebuffer/pb_buffer.h>
+#include "pipe/p_shader_tokens.h"
 #include "r600_pipe.h"
+#include "r600d.h"
 
 /* common state between evergreen and r600 */
 void r600_bind_blend_state(struct pipe_context *ctx, void *state)
@@ -119,24 +121,13 @@ void r600_bind_vertex_elements(struct pipe_context *ctx, void *state)
        struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
        struct r600_vertex_element *v = (struct r600_vertex_element*)state;
 
-       /* delete previous translated vertex elements */
-       if (rctx->tran.new_velems) {
-               r600_end_vertex_translate(rctx);
-       }
-
        rctx->vertex_elements = v;
        if (v) {
+               u_vbuf_mgr_bind_vertex_elements(rctx->vbuf_mgr, state,
+                                               v->vmgr_elements);
+
                rctx->states[v->rstate.id] = &v->rstate;
                r600_context_pipe_state_set(&rctx->ctx, &v->rstate);
-               if (rctx->family >= CHIP_CEDAR) {
-                       evergreen_vertex_buffer_update(rctx);
-               } else {
-                       r600_vertex_buffer_update(rctx);
-               }
-       }
-
-       if (v) {
-//             rctx->vs_rebuild = TRUE;
        }
 }
 
@@ -152,6 +143,7 @@ void r600_delete_vertex_element(struct pipe_context *ctx, void *state)
                rctx->vertex_elements = NULL;
 
        r600_bo_reference(rctx->radeon, &v->fetch_shader, NULL);
+       u_vbuf_mgr_destroy_vertex_elements(rctx->vbuf_mgr, v->vmgr_elements);
        FREE(state);
 }
 
@@ -176,88 +168,44 @@ void r600_set_vertex_buffers(struct pipe_context *ctx, unsigned count,
                             const struct pipe_vertex_buffer *buffers)
 {
        struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
-       struct pipe_vertex_buffer *vbo;
-       unsigned max_index = (unsigned)-1;
+       int i;
 
-       if (rctx->family >= CHIP_CEDAR) {
-               for (int i = 0; i < rctx->nvertex_buffer; i++) {
-                       pipe_resource_reference(&rctx->vertex_buffer[i].buffer, NULL);
-                       evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
+       /* Zero states. */
+       for (i = 0; i < count; i++) {
+               if (!buffers[i].buffer) {
+                       if (rctx->family >= CHIP_CEDAR) {
+                               evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
+                       } else {
+                               r600_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
+                       }
                }
-       } else {
-               for (int i = 0; i < rctx->nvertex_buffer; i++) {
-                       pipe_resource_reference(&rctx->vertex_buffer[i].buffer, NULL);
+       }
+       for (; i < rctx->vbuf_mgr->nr_real_vertex_buffers; i++) {
+               if (rctx->family >= CHIP_CEDAR) {
+                       evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
+               } else {
                        r600_context_pipe_state_set_fs_resource(&rctx->ctx, NULL, i);
                }
        }
-       memcpy(rctx->vertex_buffer, buffers, sizeof(struct pipe_vertex_buffer) * count);
-
-       for (int i = 0; i < count; i++) {
-               vbo = (struct pipe_vertex_buffer*)&buffers[i];
-
-               rctx->vertex_buffer[i].buffer = NULL;
-               if (buffers[i].buffer == NULL)
-                       continue;
-               if (r600_buffer_is_user_buffer(buffers[i].buffer))
-                       rctx->any_user_vbs = TRUE;
-               pipe_resource_reference(&rctx->vertex_buffer[i].buffer, buffers[i].buffer);
 
-               /* The stride of zero means we will be fetching only the first
-                * vertex, so don't care about max_index. */
-               if (!vbo->stride)
-                       continue;
-
-               if (vbo->max_index == ~0) {
-                       vbo->max_index = (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride;
-               }
-               max_index = MIN2(vbo->max_index, max_index);
-       }
-       rctx->nvertex_buffer = count;
-       rctx->vb_max_index = max_index;
-       if (rctx->family >= CHIP_CEDAR) {
-               evergreen_vertex_buffer_update(rctx);
-       } else {
-               r600_vertex_buffer_update(rctx);
-       }
+       u_vbuf_mgr_set_vertex_buffers(rctx->vbuf_mgr, count, buffers);
 }
 
-
-#define FORMAT_REPLACE(what, withwhat) \
-       case PIPE_FORMAT_##what: *format = PIPE_FORMAT_##withwhat; break
-
 void *r600_create_vertex_elements(struct pipe_context *ctx,
                                  unsigned count,
                                  const struct pipe_vertex_element *elements)
 {
        struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
        struct r600_vertex_element *v = CALLOC_STRUCT(r600_vertex_element);
-       enum pipe_format *format;
-       int i;
 
        assert(count < 32);
        if (!v)
                return NULL;
 
        v->count = count;
-       memcpy(v->elements, elements, count * sizeof(struct pipe_vertex_element));
-
-       for (i = 0; i < count; i++) {
-               v->hw_format[i] = v->elements[i].src_format;
-               format = &v->hw_format[i];
-
-               switch (*format) {
-               FORMAT_REPLACE(R64_FLOAT,           R32_FLOAT);
-               FORMAT_REPLACE(R64G64_FLOAT,        R32G32_FLOAT);
-               FORMAT_REPLACE(R64G64B64_FLOAT,     R32G32B32_FLOAT);
-               FORMAT_REPLACE(R64G64B64A64_FLOAT,  R32G32B32A32_FLOAT);
-               default:;
-               }
-               v->incompatible_layout =
-                       v->incompatible_layout ||
-                       v->elements[i].src_format != v->hw_format[i];
-
-               v->hw_format_size[i] = align(util_format_get_blocksize(v->hw_format[i]), 4);
-       }
+       v->vmgr_elements =
+               u_vbuf_mgr_create_vertex_elements(rctx->vbuf_mgr, count,
+                                                 elements, v->elements);
 
        if (r600_vertex_elements_build_fetch_shader(rctx, v)) {
                FREE(v);
@@ -327,3 +275,274 @@ void r600_delete_vs_shader(struct pipe_context *ctx, void *state)
        r600_pipe_shader_destroy(ctx, shader);
        free(shader);
 }
+
+/* FIXME optimize away spi update when it's not needed */
+void r600_spi_update(struct r600_pipe_context *rctx)
+{
+       struct r600_pipe_shader *shader = rctx->ps_shader;
+       struct r600_pipe_state rstate;
+       struct r600_shader *rshader = &shader->shader;
+       unsigned i, tmp;
+
+       rstate.nregs = 0;
+       for (i = 0; i < rshader->ninput; i++) {
+               tmp = S_028644_SEMANTIC(r600_find_vs_semantic_index(&rctx->vs_shader->shader, rshader, i));
+
+               if (rshader->input[i].name == TGSI_SEMANTIC_COLOR ||
+                   rshader->input[i].name == TGSI_SEMANTIC_BCOLOR ||
+                   rshader->input[i].name == TGSI_SEMANTIC_POSITION) {
+                       tmp |= S_028644_FLAT_SHADE(rctx->flatshade);
+               }
+
+               if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC &&
+                   rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) {
+                       tmp |= S_028644_PT_SPRITE_TEX(1);
+               }
+
+                if (rctx->family < CHIP_CEDAR) {
+                    if (rshader->input[i].centroid)
+                            tmp |= S_028644_SEL_CENTROID(1);
+
+                    if (rshader->input[i].interpolate == TGSI_INTERPOLATE_LINEAR)
+                            tmp |= S_028644_SEL_LINEAR(1);
+                }
+
+               r600_pipe_state_add_reg(&rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL);
+       }
+       r600_context_pipe_state_set(&rctx->ctx, &rstate);
+}
+
+void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
+                             struct pipe_resource *buffer)
+{
+       struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
+       struct r600_resource_buffer *rbuffer = r600_buffer(buffer);
+       struct r600_pipe_state *rstate;
+       uint32_t offset;
+
+       /* Note that the state tracker can unbind constant buffers by
+        * passing NULL here.
+        */
+       if (buffer == NULL) {
+               return;
+       }
+
+       r600_upload_const_buffer(rctx, &rbuffer, &offset);
+       offset += r600_bo_offset(rbuffer->r.bo);
+
+       switch (shader) {
+       case PIPE_SHADER_VERTEX:
+               rctx->vs_const_buffer.nregs = 0;
+               r600_pipe_state_add_reg(&rctx->vs_const_buffer,
+                                       R_028180_ALU_CONST_BUFFER_SIZE_VS_0,
+                                       ALIGN_DIVUP(buffer->width0 >> 4, 16),
+                                       0xFFFFFFFF, NULL);
+               r600_pipe_state_add_reg(&rctx->vs_const_buffer,
+                                       R_028980_ALU_CONST_CACHE_VS_0,
+                                       offset >> 8, 0xFFFFFFFF, rbuffer->r.bo);
+               r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_const_buffer);
+
+               rstate = &rctx->vs_const_buffer_resource[index];
+               rstate->id = R600_PIPE_STATE_RESOURCE;
+               rstate->nregs = 0;
+               if (rctx->family >= CHIP_CEDAR) {
+                       evergreen_pipe_set_buffer_resource(rctx, rstate, &rbuffer->r, offset, 16);
+                       evergreen_context_pipe_state_set_vs_resource(&rctx->ctx, rstate, index);
+               } else {
+                       r600_pipe_set_buffer_resource(rctx, rstate, &rbuffer->r, offset, 16);
+                       r600_context_pipe_state_set_vs_resource(&rctx->ctx, rstate, index);
+               }
+               break;
+       case PIPE_SHADER_FRAGMENT:
+               rctx->ps_const_buffer.nregs = 0;
+               r600_pipe_state_add_reg(&rctx->ps_const_buffer,
+                                       R_028140_ALU_CONST_BUFFER_SIZE_PS_0,
+                                       ALIGN_DIVUP(buffer->width0 >> 4, 16),
+                                       0xFFFFFFFF, NULL);
+               r600_pipe_state_add_reg(&rctx->ps_const_buffer,
+                                       R_028940_ALU_CONST_CACHE_PS_0,
+                                       offset >> 8, 0xFFFFFFFF, rbuffer->r.bo);
+               r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_const_buffer);
+
+               rstate = &rctx->ps_const_buffer_resource[index];
+               rstate->id = R600_PIPE_STATE_RESOURCE;
+               rstate->nregs = 0;
+               if (rctx->family >= CHIP_CEDAR) {
+                       evergreen_pipe_set_buffer_resource(rctx, rstate, &rbuffer->r, offset, 16);
+                       evergreen_context_pipe_state_set_ps_resource(&rctx->ctx, rstate, index);
+               } else {
+                       r600_pipe_set_buffer_resource(rctx, rstate, &rbuffer->r, offset, 16);
+                       r600_context_pipe_state_set_ps_resource(&rctx->ctx, rstate, index);
+               }
+               break;
+       default:
+               R600_ERR("unsupported %d\n", shader);
+               return;
+       }
+
+       if (buffer != &rbuffer->r.b.b.b)
+               pipe_resource_reference((struct pipe_resource**)&rbuffer, NULL);
+}
+
+static void r600_vertex_buffer_update(struct r600_pipe_context *rctx)
+{
+       struct r600_pipe_state *rstate;
+       struct r600_resource *rbuffer;
+       struct pipe_vertex_buffer *vertex_buffer;
+       unsigned i, count, offset;
+
+       if (rctx->vertex_elements->vbuffer_need_offset) {
+               /* one resource per vertex elements */
+               count = rctx->vertex_elements->count;
+       } else {
+               /* bind vertex buffer once */
+               count = rctx->vbuf_mgr->nr_real_vertex_buffers;
+       }
+
+       for (i = 0 ; i < count; i++) {
+               rstate = &rctx->fs_resource[i];
+               rstate->id = R600_PIPE_STATE_RESOURCE;
+               rstate->nregs = 0;
+
+               if (rctx->vertex_elements->vbuffer_need_offset) {
+                       /* one resource per vertex elements */
+                       unsigned vbuffer_index;
+                       vbuffer_index = rctx->vertex_elements->elements[i].vertex_buffer_index;
+                       vertex_buffer = &rctx->vbuf_mgr->vertex_buffer[vbuffer_index];
+                       rbuffer = (struct r600_resource*)rctx->vbuf_mgr->real_vertex_buffer[vbuffer_index];
+                       offset = rctx->vertex_elements->vbuffer_offset[i];
+               } else {
+                       /* bind vertex buffer once */
+                       vertex_buffer = &rctx->vbuf_mgr->vertex_buffer[i];
+                       rbuffer = (struct r600_resource*)rctx->vbuf_mgr->real_vertex_buffer[i];
+                       offset = 0;
+               }
+               if (vertex_buffer == NULL || rbuffer == NULL)
+                       continue;
+               offset += vertex_buffer->buffer_offset + r600_bo_offset(rbuffer->bo);
+
+               if (rctx->family >= CHIP_CEDAR) {
+                       evergreen_pipe_set_buffer_resource(rctx, rstate, rbuffer, offset, vertex_buffer->stride);
+                       evergreen_context_pipe_state_set_fs_resource(&rctx->ctx, rstate, i);
+               } else {
+                       r600_pipe_set_buffer_resource(rctx, rstate, rbuffer, offset, vertex_buffer->stride);
+                       r600_context_pipe_state_set_fs_resource(&rctx->ctx, rstate, i);
+               }
+       }
+}
+
+void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
+{
+       struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
+       struct r600_resource *rbuffer;
+       u32 vgt_dma_index_type, vgt_draw_initiator, mask;
+       struct r600_draw rdraw;
+       struct r600_pipe_state vgt;
+       struct r600_drawl draw = {};
+       unsigned prim;
+
+       r600_flush_depth_textures(rctx);
+       u_vbuf_mgr_draw_begin(rctx->vbuf_mgr, info, NULL, NULL);
+       r600_vertex_buffer_update(rctx);
+
+       draw.info = *info;
+       draw.ctx = ctx;
+       if (info->indexed && rctx->index_buffer.buffer) {
+               draw.info.start += rctx->index_buffer.offset / rctx->index_buffer.index_size;
+               pipe_resource_reference(&draw.index_buffer, rctx->index_buffer.buffer);
+
+               r600_translate_index_buffer(rctx, &draw.index_buffer,
+                                           &rctx->index_buffer.index_size,
+                                           &draw.info.start,
+                                           info->count);
+
+               draw.index_size = rctx->index_buffer.index_size;
+               draw.index_buffer_offset = draw.info.start * draw.index_size;
+               draw.info.start = 0;
+
+               if (u_vbuf_resource(draw.index_buffer)->user_ptr) {
+                       r600_upload_index_buffer(rctx, &draw);
+               }
+       } else {
+               draw.info.index_bias = info->start;
+       }
+
+       switch (draw.index_size) {
+       case 2:
+               vgt_draw_initiator = 0;
+               vgt_dma_index_type = 0;
+               break;
+       case 4:
+               vgt_draw_initiator = 0;
+               vgt_dma_index_type = 1;
+               break;
+       case 0:
+               vgt_draw_initiator = 2;
+               vgt_dma_index_type = 0;
+               break;
+       default:
+               R600_ERR("unsupported index size %d\n", draw.index_size);
+               return;
+       }
+       if (r600_conv_pipe_prim(draw.info.mode, &prim))
+               return;
+       if (unlikely(rctx->ps_shader == NULL)) {
+               R600_ERR("missing vertex shader\n");
+               return;
+       }
+       if (unlikely(rctx->vs_shader == NULL)) {
+               R600_ERR("missing vertex shader\n");
+               return;
+       }
+       /* there should be enough input */
+       if (rctx->vertex_elements->count < rctx->vs_shader->shader.bc.nresource) {
+               R600_ERR("%d resources provided, expecting %d\n",
+                       rctx->vertex_elements->count, rctx->vs_shader->shader.bc.nresource);
+               return;
+       }
+
+       r600_spi_update(rctx);
+
+       mask = 0;
+       for (int i = 0; i < rctx->framebuffer.nr_cbufs; i++) {
+               mask |= (0xF << (i * 4));
+       }
+
+       vgt.id = R600_PIPE_STATE_VGT;
+       vgt.nregs = 0;
+       r600_pipe_state_add_reg(&vgt, R_008958_VGT_PRIMITIVE_TYPE, prim, 0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(&vgt, R_028408_VGT_INDX_OFFSET, draw.info.index_bias, 0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(&vgt, R_028400_VGT_MAX_VTX_INDX, draw.info.max_index, 0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(&vgt, R_028404_VGT_MIN_VTX_INDX, draw.info.min_index, 0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(&vgt, R_028238_CB_TARGET_MASK, rctx->cb_target_mask & mask, 0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(&vgt, R_03CFF0_SQ_VTX_BASE_VTX_LOC, 0, 0xFFFFFFFF, NULL);
+       r600_pipe_state_add_reg(&vgt, R_03CFF4_SQ_VTX_START_INST_LOC, 0, 0xFFFFFFFF, NULL);
+       r600_context_pipe_state_set(&rctx->ctx, &vgt);
+
+       rdraw.vgt_num_indices = draw.info.count;
+       rdraw.vgt_num_instances = 1;
+       rdraw.vgt_index_type = vgt_dma_index_type;
+       rdraw.vgt_draw_initiator = vgt_draw_initiator;
+       rdraw.indices = NULL;
+       if (draw.index_buffer) {
+               rbuffer = (struct r600_resource*)draw.index_buffer;
+               rdraw.indices = rbuffer->bo;
+               rdraw.indices_bo_offset = draw.index_buffer_offset;
+       }
+
+       if (rctx->family >= CHIP_CEDAR) {
+               evergreen_context_draw(&rctx->ctx, &rdraw);
+       } else {
+               r600_context_draw(&rctx->ctx, &rdraw);
+       }
+
+       if (rctx->framebuffer.zsbuf)
+       {
+               struct pipe_resource *tex = rctx->framebuffer.zsbuf->texture;
+               ((struct r600_resource_texture *)tex)->dirty_db = TRUE;
+       }
+
+       pipe_resource_reference(&draw.index_buffer, NULL);
+
+       u_vbuf_mgr_draw_end(rctx->vbuf_mgr);
+}
index a0ec493fc8582736ea58664a216c891954f39829..3dd54f45202c50253566dbbb56a76aa83178af8f 100644 (file)
@@ -253,9 +253,13 @@ static inline unsigned r600_tex_dim(unsigned dim)
        default:
        case PIPE_TEXTURE_1D:
                return V_038000_SQ_TEX_DIM_1D;
+       case PIPE_TEXTURE_1D_ARRAY:
+               return V_038000_SQ_TEX_DIM_1D_ARRAY;
        case PIPE_TEXTURE_2D:
        case PIPE_TEXTURE_RECT:
                return V_038000_SQ_TEX_DIM_2D;
+       case PIPE_TEXTURE_2D_ARRAY:
+               return V_038000_SQ_TEX_DIM_2D_ARRAY;
        case PIPE_TEXTURE_3D:
                return V_038000_SQ_TEX_DIM_3D;
        case PIPE_TEXTURE_CUBE:
@@ -285,10 +289,14 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format)
                return V_0280A0_SWAP_ALT_REV;
        case PIPE_FORMAT_I8_UNORM:
        case PIPE_FORMAT_L8_UNORM:
+       case PIPE_FORMAT_L8_SRGB:
        case PIPE_FORMAT_R8_UNORM:
        case PIPE_FORMAT_R8_SNORM:
                return V_0280A0_SWAP_STD;
 
+       case PIPE_FORMAT_L4A4_UNORM:
+               return V_0280A0_SWAP_ALT;
+
                /* 16-bit buffers. */
        case PIPE_FORMAT_B5G6R5_UNORM:
                return V_0280A0_SWAP_STD_REV;
@@ -305,6 +313,7 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format)
                return V_0280A0_SWAP_STD;
 
        case PIPE_FORMAT_L8A8_UNORM:
+       case PIPE_FORMAT_L8A8_SRGB:
                return V_0280A0_SWAP_ALT;
        case PIPE_FORMAT_R8G8_UNORM:
                return V_0280A0_SWAP_STD;
@@ -328,6 +337,7 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format)
        case PIPE_FORMAT_X8R8G8B8_UNORM:
                return V_0280A0_SWAP_ALT_REV;
        case PIPE_FORMAT_R8G8B8A8_SNORM:
+       case PIPE_FORMAT_R8G8B8A8_UNORM:
        case PIPE_FORMAT_R8G8B8X8_UNORM:
                return V_0280A0_SWAP_STD;
 
@@ -346,9 +356,11 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format)
 
        case PIPE_FORMAT_R10G10B10A2_UNORM:
        case PIPE_FORMAT_R10G10B10X2_SNORM:
-       case PIPE_FORMAT_B10G10R10A2_UNORM:
        case PIPE_FORMAT_R10SG10SB10SA2U_NORM:
-               return V_0280A0_SWAP_STD_REV;
+               return V_0280A0_SWAP_STD;
+
+       case PIPE_FORMAT_B10G10R10A2_UNORM:
+               return V_0280A0_SWAP_ALT;
 
        case PIPE_FORMAT_R16G16_UNORM:
                return V_0280A0_SWAP_STD;
@@ -356,14 +368,13 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format)
                /* 64-bit buffers. */
        case PIPE_FORMAT_R16G16B16A16_UNORM:
        case PIPE_FORMAT_R16G16B16A16_SNORM:
-               //              return FMT_16_16_16_16;
        case PIPE_FORMAT_R16G16B16A16_FLOAT:
-               //              return FMT_16_16_16_16_FLOAT;
 
                /* 128-bit buffers. */
-       //case PIPE_FORMAT_R32G32B32A32_FLOAT:
-               //              return FMT_32_32_32_32_FLOAT;
-               return 0;
+       case PIPE_FORMAT_R32G32B32A32_FLOAT:
+       case PIPE_FORMAT_R32G32B32A32_SNORM:
+       case PIPE_FORMAT_R32G32B32A32_UNORM:
+               return V_0280A0_SWAP_STD;
        default:
                R600_ERR("unsupported colorswap format %d\n", format);
                return ~0;
@@ -374,10 +385,14 @@ static inline uint32_t r600_translate_colorswap(enum pipe_format format)
 static INLINE uint32_t r600_translate_colorformat(enum pipe_format format)
 {
        switch (format) {
+       case PIPE_FORMAT_L4A4_UNORM:
+               return V_0280A0_COLOR_4_4;
+
                /* 8-bit buffers. */
        case PIPE_FORMAT_A8_UNORM:
        case PIPE_FORMAT_I8_UNORM:
        case PIPE_FORMAT_L8_UNORM:
+       case PIPE_FORMAT_L8_SRGB:
        case PIPE_FORMAT_R8_UNORM:
        case PIPE_FORMAT_R8_SNORM:
                return V_0280A0_COLOR_8;
@@ -398,6 +413,7 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format)
                return V_0280A0_COLOR_16;
 
        case PIPE_FORMAT_L8A8_UNORM:
+       case PIPE_FORMAT_L8A8_SRGB:
        case PIPE_FORMAT_R8G8_UNORM:
                return V_0280A0_COLOR_8_8;
 
@@ -425,7 +441,7 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format)
        case PIPE_FORMAT_R10G10B10X2_SNORM:
        case PIPE_FORMAT_B10G10R10A2_UNORM:
        case PIPE_FORMAT_R10SG10SB10SA2U_NORM:
-               return V_0280A0_COLOR_10_10_10_2;
+               return V_0280A0_COLOR_2_10_10_10;
 
        case PIPE_FORMAT_Z24X8_UNORM:
        case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
@@ -467,10 +483,13 @@ static INLINE uint32_t r600_translate_colorformat(enum pipe_format format)
                return V_0280A0_COLOR_32_32;
 
                /* 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;
+       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;
+       case PIPE_FORMAT_R32G32B32A32_SNORM:
+       case PIPE_FORMAT_R32G32B32A32_UNORM:
+               return V_0280A0_COLOR_32_32_32_32;
 
                /* YUV buffers. */
        case PIPE_FORMAT_UYVY:
@@ -497,9 +516,37 @@ static INLINE boolean r600_is_zs_format_supported(enum pipe_format format)
        return r600_translate_dbformat(format) != ~0;
 }
 
-static INLINE boolean r600_is_vertex_format_supported(enum pipe_format format)
+static INLINE boolean r600_is_vertex_format_supported(enum pipe_format format,
+                                                     enum radeon_family family)
 {
-       return r600_translate_colorformat(format) != ~0;
+       unsigned i;
+       const struct util_format_description *desc = util_format_description(format);
+       if (!desc)
+               return FALSE;
+
+       /* Find the first non-VOID channel. */
+       for (i = 0; i < 4; i++) {
+               if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {
+                       break;
+               }
+       }
+       if (i == 4)
+               return FALSE;
+
+       /* No fixed, no double. */
+       if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
+           desc->channel[i].type == UTIL_FORMAT_TYPE_FIXED ||
+           (desc->channel[i].size == 64 &&
+            desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT))
+               return FALSE;
+
+       /* No scaled/norm formats with 32 bits per channel. */
+       if (desc->channel[i].size == 32 &&
+           (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED ||
+            desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED))
+               return FALSE;
+
+       return TRUE;
 }
 
 #endif
index 1f4f453c091b81fd7b547bd57d9765b18d8d5731..03af367401d9b8c411072f42bc3b94bfa67d4e36 100644 (file)
@@ -27,6 +27,7 @@
 #include <errno.h>
 #include <pipe/p_screen.h>
 #include <util/u_format.h>
+#include <util/u_format_s3tc.h>
 #include <util/u_math.h>
 #include <util/u_inlines.h>
 #include <util/u_memory.h>
@@ -38,8 +39,6 @@
 #include "r600d.h"
 #include "r600_formats.h"
 
-extern struct u_resource_vtbl r600_texture_vtbl;
-
 /* Copy from a full GPU texture to a transfer's staging one. */
 static void r600_copy_to_staging_texture(struct pipe_context *ctx, struct r600_transfer *rtransfer)
 {
@@ -77,17 +76,15 @@ unsigned r600_texture_get_offset(struct r600_resource_texture *rtex,
 {
        unsigned offset = rtex->offset[level];
 
-       switch (rtex->resource.base.b.target) {
+       switch (rtex->resource.b.b.b.target) {
        case PIPE_TEXTURE_3D:
        case PIPE_TEXTURE_CUBE:
-               return offset + layer * rtex->layer_size[level];
        default:
-               assert(layer == 0);
-               return offset;
+               return offset + layer * rtex->layer_size[level];
        }
 }
 
-static unsigned r600_get_pixel_alignment(struct pipe_screen *screen,
+static unsigned r600_get_block_alignment(struct pipe_screen *screen,
                                         enum pipe_format format,
                                         unsigned array_mode)
 {
@@ -105,6 +102,9 @@ static unsigned r600_get_pixel_alignment(struct pipe_screen *screen,
                               (((rscreen->tiling_info->group_bytes / 8 / pixsize)) *
                                rscreen->tiling_info->num_banks)) * 8;
                break;
+       case V_038000_ARRAY_LINEAR_ALIGNED:
+               p_align = MAX2(64, rscreen->tiling_info->group_bytes / pixsize);
+               break;
        case V_038000_ARRAY_LINEAR_GENERAL:
        default:
                p_align = rscreen->tiling_info->group_bytes / pixsize;
@@ -124,8 +124,10 @@ static unsigned r600_get_height_alignment(struct pipe_screen *screen,
                h_align = rscreen->tiling_info->num_channels * 8;
                break;
        case V_038000_ARRAY_1D_TILED_THIN1:
+       case V_038000_ARRAY_LINEAR_ALIGNED:
                h_align = 8;
                break;
+       case V_038000_ARRAY_LINEAR_GENERAL:
        default:
                h_align = 1;
                break;
@@ -139,7 +141,7 @@ static unsigned r600_get_base_alignment(struct pipe_screen *screen,
 {
        struct r600_screen* rscreen = (struct r600_screen *)screen;
        unsigned pixsize = util_format_get_blocksize(format);
-       int p_align = r600_get_pixel_alignment(screen, format, array_mode);
+       int p_align = r600_get_block_alignment(screen, format, array_mode);
        int h_align = r600_get_height_alignment(screen, array_mode);
        int b_align;
 
@@ -149,6 +151,8 @@ static unsigned r600_get_base_alignment(struct pipe_screen *screen,
                               p_align * pixsize * h_align);
                break;
        case V_038000_ARRAY_1D_TILED_THIN1:
+       case V_038000_ARRAY_LINEAR_ALIGNED:
+       case V_038000_ARRAY_LINEAR_GENERAL:
        default:
                b_align = rscreen->tiling_info->group_bytes;
                break;
@@ -165,55 +169,46 @@ static unsigned mip_minify(unsigned size, unsigned level)
        return val;
 }
 
-static unsigned r600_texture_get_stride(struct pipe_screen *screen,
-                                       struct r600_resource_texture *rtex,
-                                       unsigned level)
+static unsigned r600_texture_get_nblocksx(struct pipe_screen *screen,
+                                         struct r600_resource_texture *rtex,
+                                         unsigned level)
 {
-       struct pipe_resource *ptex = &rtex->resource.base.b;
-       unsigned width, stride, tile_width;
+       struct pipe_resource *ptex = &rtex->resource.b.b.b;
+       unsigned nblocksx, block_align, width;
+       unsigned blocksize = util_format_get_blocksize(ptex->format);
 
        if (rtex->pitch_override)
-               return rtex->pitch_override;
+               return rtex->pitch_override / blocksize;
 
        width = mip_minify(ptex->width0, level);
-       if (util_format_is_plain(ptex->format)) {
-               tile_width = r600_get_pixel_alignment(screen, ptex->format,
-                                                     rtex->array_mode[level]);
-               width = align(width, tile_width);
-       }
-       stride = util_format_get_stride(ptex->format, width);
+       nblocksx = util_format_get_nblocksx(ptex->format, width);
 
-       return stride;
+       block_align = r600_get_block_alignment(screen, ptex->format,
+                                             rtex->array_mode[level]);
+       nblocksx = align(nblocksx, block_align);
+       return nblocksx;
 }
 
 static unsigned r600_texture_get_nblocksy(struct pipe_screen *screen,
                                          struct r600_resource_texture *rtex,
                                          unsigned level)
 {
-       struct pipe_resource *ptex = &rtex->resource.base.b;
+       struct pipe_resource *ptex = &rtex->resource.b.b.b;
        unsigned height, tile_height;
 
        height = mip_minify(ptex->height0, level);
-       if (util_format_is_plain(ptex->format)) {
-               tile_height = r600_get_height_alignment(screen,
-                                                       rtex->array_mode[level]);
-               height = align(height, tile_height);
-       }
-       return util_format_get_nblocksy(ptex->format, height);
-}
-
-/* Get a width in pixels from a stride in bytes. */
-static unsigned pitch_to_width(enum pipe_format format, unsigned pitch_in_bytes)
-{
-       return (pitch_in_bytes / util_format_get_blocksize(format)) *
-               util_format_get_blockwidth(format);
+       height = util_format_get_nblocksy(ptex->format, height);
+       tile_height = r600_get_height_alignment(screen,
+                                               rtex->array_mode[level]);
+       height = align(height, tile_height);
+       return height;
 }
 
 static void r600_texture_set_array_mode(struct pipe_screen *screen,
                                        struct r600_resource_texture *rtex,
                                        unsigned level, unsigned array_mode)
 {
-       struct pipe_resource *ptex = &rtex->resource.base.b;
+       struct pipe_resource *ptex = &rtex->resource.b.b.b;
 
        switch (array_mode) {
        case V_0280A0_ARRAY_LINEAR_GENERAL:
@@ -227,7 +222,7 @@ static void r600_texture_set_array_mode(struct pipe_screen *screen,
                unsigned w, h, tile_height, tile_width;
 
                tile_height = r600_get_height_alignment(screen, array_mode);
-               tile_width = r600_get_pixel_alignment(screen, ptex->format, array_mode);
+               tile_width = r600_get_block_alignment(screen, ptex->format, array_mode);
 
                w = mip_minify(ptex->width0, level);
                h = mip_minify(ptex->height0, level);
@@ -244,40 +239,128 @@ static void r600_setup_miptree(struct pipe_screen *screen,
                               struct r600_resource_texture *rtex,
                               unsigned array_mode)
 {
-       struct pipe_resource *ptex = &rtex->resource.base.b;
+       struct pipe_resource *ptex = &rtex->resource.b.b.b;
        struct radeon *radeon = (struct radeon *)screen->winsys;
        enum chip_class chipc = r600_get_family_class(radeon);
-       unsigned pitch, size, layer_size, i, offset;
-       unsigned nblocksy;
+       unsigned size, layer_size, i, offset;
+       unsigned nblocksx, nblocksy;
 
        for (i = 0, offset = 0; i <= ptex->last_level; i++) {
+               unsigned blocksize = util_format_get_blocksize(ptex->format);
+
                r600_texture_set_array_mode(screen, rtex, i, array_mode);
 
-               pitch = r600_texture_get_stride(screen, rtex, i);
+               nblocksx = r600_texture_get_nblocksx(screen, rtex, i);
                nblocksy = r600_texture_get_nblocksy(screen, rtex, i);
 
-               layer_size = pitch * nblocksy;
-
+               layer_size = nblocksx * nblocksy * blocksize;
                if (ptex->target == PIPE_TEXTURE_CUBE) {
                        if (chipc >= R700)
                                size = layer_size * 8;
                        else
                                size = layer_size * 6;
                }
-               else
+               else if (ptex->target == PIPE_TEXTURE_3D)
                        size = layer_size * u_minify(ptex->depth0, i);
+               else
+                       size = layer_size * ptex->array_size;
+
                /* align base image and start of miptree */
                if ((i == 0) || (i == 1))
                        offset = align(offset, r600_get_base_alignment(screen, ptex->format, array_mode));
                rtex->offset[i] = offset;
                rtex->layer_size[i] = layer_size;
-               rtex->pitch_in_bytes[i] = pitch;
-               rtex->pitch_in_pixels[i] = pitch_to_width(ptex->format, pitch);
+               rtex->pitch_in_blocks[i] = nblocksx; /* CB talks in elements */
+               rtex->pitch_in_bytes[i] = nblocksx * blocksize;
+
                offset += size;
        }
        rtex->size = offset;
 }
 
+/* Figure out whether u_blitter will fallback to a transfer operation.
+ * If so, don't use a staging resource.
+ */
+static boolean permit_hardware_blit(struct pipe_screen *screen,
+                                       const struct pipe_resource *res)
+{
+       unsigned bind;
+
+       if (util_format_is_depth_or_stencil(res->format))
+               bind = PIPE_BIND_DEPTH_STENCIL;
+       else
+               bind = PIPE_BIND_RENDER_TARGET;
+
+       /* hackaround for S3TC */
+       if (util_format_is_s3tc(res->format))
+               return TRUE;
+
+       if (!screen->is_format_supported(screen,
+                               res->format,
+                               res->target,
+                               res->nr_samples,
+                               bind, 0))
+               return FALSE;
+
+       if (!screen->is_format_supported(screen,
+                               res->format,
+                               res->target,
+                               res->nr_samples,
+                               PIPE_BIND_SAMPLER_VIEW, 0))
+               return FALSE;
+
+       return TRUE;
+}
+
+static boolean r600_texture_get_handle(struct pipe_screen* screen,
+                                       struct pipe_resource *ptex,
+                                       struct winsys_handle *whandle)
+{
+       struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex;
+       struct r600_resource *resource = &rtex->resource;
+       struct radeon *radeon = (struct radeon *)screen->winsys;
+
+       return r600_bo_get_winsys_handle(radeon, resource->bo,
+                       rtex->pitch_in_bytes[0], whandle);
+}
+
+static void r600_texture_destroy(struct pipe_screen *screen,
+                                struct pipe_resource *ptex)
+{
+       struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex;
+       struct r600_resource *resource = &rtex->resource;
+       struct radeon *radeon = (struct radeon *)screen->winsys;
+
+       if (rtex->flushed_depth_texture)
+               pipe_resource_reference((struct pipe_resource **)&rtex->flushed_depth_texture, NULL);
+
+       if (resource->bo) {
+               r600_bo_reference(radeon, &resource->bo, NULL);
+       }
+       FREE(rtex);
+}
+
+static unsigned int r600_texture_is_referenced(struct pipe_context *context,
+                                               struct pipe_resource *texture,
+                                               unsigned level, int layer)
+{
+       /* FIXME */
+       return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
+}
+
+static const struct u_resource_vtbl r600_texture_vtbl =
+{
+       r600_texture_get_handle,        /* get_handle */
+       r600_texture_destroy,           /* resource_destroy */
+       r600_texture_is_referenced,     /* is_resource_referenced */
+       r600_texture_get_transfer,      /* get_transfer */
+       r600_texture_transfer_destroy,  /* transfer_destroy */
+       r600_texture_transfer_map,      /* transfer_map */
+       u_default_transfer_flush_region,/* transfer_flush_region */
+       r600_texture_transfer_unmap,    /* transfer_unmap */
+       u_default_transfer_inline_write /* transfer_inline_write */
+};
+
 static struct r600_resource_texture *
 r600_texture_create_object(struct pipe_screen *screen,
                           const struct pipe_resource *base,
@@ -295,21 +378,22 @@ r600_texture_create_object(struct pipe_screen *screen,
                return NULL;
 
        resource = &rtex->resource;
-       resource->base.b = *base;
-       resource->base.vtbl = &r600_texture_vtbl;
-       pipe_reference_init(&resource->base.b.reference, 1);
-       resource->base.b.screen = screen;
+       resource->b.b.b = *base;
+       resource->b.b.vtbl = &r600_texture_vtbl;
+       pipe_reference_init(&resource->b.b.b.reference, 1);
+       resource->b.b.b.screen = screen;
        resource->bo = bo;
        rtex->pitch_override = pitch_in_bytes_override;
+       /* only mark depth textures the HW can hit as depth textures */
+       if (util_format_is_depth_or_stencil(base->format) && permit_hardware_blit(screen, base))
+               rtex->depth = 1;
 
-       if (array_mode)
-               rtex->tiled = 1;
        r600_setup_miptree(screen, rtex, array_mode);
 
        resource->size = rtex->size;
 
        if (!resource->bo) {
-               struct pipe_resource *ptex = &rtex->resource.base.b;
+               struct pipe_resource *ptex = &rtex->resource.b.b.b;
                int base_align = r600_get_base_alignment(screen, ptex->format, array_mode);
 
                resource->bo = r600_bo(radeon, rtex->size, base_align, base->bind, base->usage);
@@ -321,48 +405,6 @@ r600_texture_create_object(struct pipe_screen *screen,
        return rtex;
 }
 
-/* Figure out whether u_blitter will fallback to a transfer operation.
- * If so, don't use a staging resource.
- */
-static boolean permit_hardware_blit(struct pipe_screen *screen,
-                                       const struct pipe_resource *res)
-{
-       unsigned bind;
-
-       if (util_format_is_depth_or_stencil(res->format))
-               bind = PIPE_BIND_DEPTH_STENCIL;
-       else
-               bind = PIPE_BIND_RENDER_TARGET;
-
-       /* See r600_resource_copy_region: there is something wrong
-        * with depth resource copies at the moment so avoid them for
-        * now.
-        */
-       if (util_format_get_component_bits(res->format,
-                               UTIL_FORMAT_COLORSPACE_ZS,
-                               0) != 0)
-               return FALSE;
-
-       if (!screen->is_format_supported(screen,
-                               res->format,
-                               res->target,
-                               res->nr_samples,
-                               bind, 0))
-               return FALSE;
-
-       if (!screen->is_format_supported(screen,
-                               res->format,
-                               res->target,
-                               res->nr_samples,
-                               PIPE_BIND_SAMPLER_VIEW, 0))
-               return FALSE;
-
-       if (res->usage == PIPE_USAGE_STREAM)
-               return FALSE;
-
-       return TRUE;
-}
-
 struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
                                                const struct pipe_resource *templ)
 {
@@ -381,46 +423,21 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
                }
        }
 
+       if (!(templ->flags & R600_RESOURCE_FLAG_TRANSFER) &&
+           util_format_is_s3tc(templ->format))
+               array_mode = V_038000_ARRAY_1D_TILED_THIN1;
+
        return (struct pipe_resource *)r600_texture_create_object(screen, templ, array_mode,
                                                                  0, 0, NULL);
 
 }
 
-static void r600_texture_destroy(struct pipe_screen *screen,
-                                struct pipe_resource *ptex)
-{
-       struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex;
-       struct r600_resource *resource = &rtex->resource;
-       struct radeon *radeon = (struct radeon *)screen->winsys;
-
-       if (rtex->flushed_depth_texture)
-               pipe_resource_reference((struct pipe_resource **)&rtex->flushed_depth_texture, NULL);
-
-       if (resource->bo) {
-               r600_bo_reference(radeon, &resource->bo, NULL);
-       }
-       FREE(rtex);
-}
-
-static boolean r600_texture_get_handle(struct pipe_screen* screen,
-                                       struct pipe_resource *ptex,
-                                       struct winsys_handle *whandle)
-{
-       struct r600_resource_texture *rtex = (struct r600_resource_texture*)ptex;
-       struct r600_resource *resource = &rtex->resource;
-       struct radeon *radeon = (struct radeon *)screen->winsys;
-
-       return r600_bo_get_winsys_handle(radeon, resource->bo,
-                       rtex->pitch_in_bytes[0], whandle);
-}
-
 static struct pipe_surface *r600_create_surface(struct pipe_context *pipe,
                                                struct pipe_resource *texture,
                                                const struct pipe_surface *surf_tmpl)
 {
        struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
        struct r600_surface *surface = CALLOC_STRUCT(r600_surface);
-       unsigned tile_height;
        unsigned level = surf_tmpl->u.tex.level;
 
        assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
@@ -440,8 +457,8 @@ static struct pipe_surface *r600_create_surface(struct pipe_context *pipe,
        surface->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
        surface->base.u.tex.level = level;
 
-       tile_height = r600_get_height_alignment(pipe->screen, rtex->array_mode[level]);
-       surface->aligned_height = align(surface->base.height, tile_height);
+       surface->aligned_height = r600_texture_get_nblocksy(pipe->screen,
+                                                           rtex, level);
        return &surface->base;
 }
 
@@ -477,16 +494,8 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen,
                                                                  bo);
 }
 
-static unsigned int r600_texture_is_referenced(struct pipe_context *context,
-                                               struct pipe_resource *texture,
-                                               unsigned level, int layer)
-{
-       /* FIXME */
-       return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
-}
-
 int r600_texture_depth_flush(struct pipe_context *ctx,
-                            struct pipe_resource *texture)
+                            struct pipe_resource *texture, boolean just_create)
 {
        struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
        struct pipe_resource resource;
@@ -499,7 +508,8 @@ int r600_texture_depth_flush(struct pipe_context *ctx,
        resource.width0 = texture->width0;
        resource.height0 = texture->height0;
        resource.depth0 = 1;
-       resource.last_level = 0;
+       resource.array_size = 1;
+       resource.last_level = texture->last_level;
        resource.nr_samples = 0;
        resource.usage = PIPE_USAGE_DYNAMIC;
        resource.bind = 0;
@@ -513,7 +523,11 @@ int r600_texture_depth_flush(struct pipe_context *ctx,
                return -ENOMEM;
        }
 
+       ((struct r600_resource_texture *)rtex->flushed_depth_texture)->is_flushing_texture = TRUE;
 out:
+       if (just_create)
+               return 0;
+
        /* XXX: only do this if the depth texture has actually changed:
         */
        r600_blit_uncompress_depth(ctx, rtex);
@@ -546,7 +560,7 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
         * the CPU is much happier reading out of cached system memory
         * than uncached VRAM.
         */
-       if (rtex->tiled)
+       if (R600_TEX_IS_TILED(rtex, level))
                use_staging_texture = TRUE;
 
        if ((usage & PIPE_TRANSFER_READ) && u_box_volume(box) > 1024)
@@ -579,13 +593,16 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
                */
                /* XXX: when discard is true, no need to read back from depth texture
                */
-               r = r600_texture_depth_flush(ctx, texture);
+               r = r600_texture_depth_flush(ctx, texture, FALSE);
                if (r < 0) {
                        R600_ERR("failed to create temporary texture to hold untiled copy\n");
                        pipe_resource_reference(&trans->transfer.resource, NULL);
                        FREE(trans);
                        return NULL;
                }
+               trans->transfer.stride = rtex->flushed_depth_texture->pitch_in_bytes[level];
+               trans->offset = r600_texture_get_offset(rtex->flushed_depth_texture, level, box->z);
+               return &trans->transfer;
        } else if (use_staging_texture) {
                resource.target = PIPE_TEXTURE_2D;
                resource.format = texture->format;
@@ -627,6 +644,7 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
                return &trans->transfer;
        }
        trans->transfer.stride = rtex->pitch_in_bytes[level];
+       trans->transfer.layer_stride = rtex->layer_size[level];
        trans->offset = r600_texture_get_offset(rtex, level, box->z);
        return &trans->transfer;
 }
@@ -635,7 +653,8 @@ void r600_texture_transfer_destroy(struct pipe_context *ctx,
                                   struct pipe_transfer *transfer)
 {
        struct r600_transfer *rtransfer = (struct r600_transfer*)transfer;
-       struct r600_resource_texture *rtex = (struct r600_resource_texture*)transfer->resource;
+       struct pipe_resource *texture = transfer->resource;
+       struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
 
        if (rtransfer->staging_texture) {
                if (transfer->usage & PIPE_TRANSFER_WRITE) {
@@ -643,9 +662,12 @@ void r600_texture_transfer_destroy(struct pipe_context *ctx,
                }
                pipe_resource_reference(&rtransfer->staging_texture, NULL);
        }
-       if (rtex->flushed_depth_texture) {
-               pipe_resource_reference((struct pipe_resource **)&rtex->flushed_depth_texture, NULL);
+
+       if (rtex->depth && !rtex->is_flushing_texture) {
+               if ((transfer->usage & PIPE_TRANSFER_WRITE) && rtex->flushed_depth_texture)
+                       r600_blit_push_depth(ctx, rtex);
        }
+
        pipe_resource_reference(&transfer->resource, NULL);
        FREE(transfer);
 }
@@ -727,19 +749,6 @@ void r600_texture_transfer_unmap(struct pipe_context *ctx,
        r600_bo_unmap(radeon, bo);
 }
 
-struct u_resource_vtbl r600_texture_vtbl =
-{
-       r600_texture_get_handle,        /* get_handle */
-       r600_texture_destroy,           /* resource_destroy */
-       r600_texture_is_referenced,     /* is_resource_referenced */
-       r600_texture_get_transfer,      /* get_transfer */
-       r600_texture_transfer_destroy,  /* transfer_destroy */
-       r600_texture_transfer_map,      /* transfer_map */
-       u_default_transfer_flush_region,/* transfer_flush_region */
-       r600_texture_transfer_unmap,    /* transfer_unmap */
-       u_default_transfer_inline_write /* transfer_inline_write */
-};
-
 void r600_init_surface_functions(struct r600_pipe_context *r600)
 {
        r600->context.create_surface = r600_create_surface;
@@ -802,6 +811,8 @@ uint32_t r600_translate_texformat(enum pipe_format format,
        uint32_t result = 0, word4 = 0, yuv_format = 0;
        const struct util_format_description *desc;
        boolean uniform = TRUE;
+       static int r600_enable_s3tc = -1;
+
        int i;
        const uint32_t sign_bit[4] = {
                S_038010_FORMAT_COMP_X(V_038010_SQ_FORMAT_COMP_SIGNED),
@@ -853,34 +864,55 @@ uint32_t r600_translate_texformat(enum pipe_format format,
 
        case UTIL_FORMAT_COLORSPACE_SRGB:
                word4 |= S_038010_FORCE_DEGAMMA(1);
-               if (format == PIPE_FORMAT_L8A8_SRGB || format == PIPE_FORMAT_L8_SRGB)
-                       goto out_unknown; /* fails for some reason - TODO */
                break;
 
        default:
                break;
        }
 
-       /* S3TC formats. TODO */
-       if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
-               static int r600_enable_s3tc = -1;
+       if (r600_enable_s3tc == -1)
+               r600_enable_s3tc = debug_get_bool_option("R600_ENABLE_S3TC", FALSE);
+
+       if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) {
+               if (!r600_enable_s3tc)
+                       goto out_unknown;
+
+               switch (format) {
+               case PIPE_FORMAT_RGTC1_UNORM:
+               case PIPE_FORMAT_RGTC1_SNORM:
+                       result = FMT_BC4;
+                       goto out_word4;
+               case PIPE_FORMAT_RGTC2_UNORM:
+               case PIPE_FORMAT_RGTC2_SNORM:
+                       result = FMT_BC5;
+                       goto out_word4;
+               default:
+                       goto out_unknown;
+               }
+       }
 
-               if (r600_enable_s3tc == -1)
-                       r600_enable_s3tc =
-                               debug_get_bool_option("R600_ENABLE_S3TC", FALSE);
+       if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
 
                if (!r600_enable_s3tc)
                        goto out_unknown;
 
+               if (!util_format_s3tc_enabled) {
+                       goto out_unknown;
+               }
+
                switch (format) {
                case PIPE_FORMAT_DXT1_RGB:
                case PIPE_FORMAT_DXT1_RGBA:
+               case PIPE_FORMAT_DXT1_SRGB:
+               case PIPE_FORMAT_DXT1_SRGBA:
                        result = FMT_BC1;
                        goto out_word4;
                case PIPE_FORMAT_DXT3_RGBA:
+               case PIPE_FORMAT_DXT3_SRGBA:
                        result = FMT_BC2;
                        goto out_word4;
                case PIPE_FORMAT_DXT5_RGBA:
+               case PIPE_FORMAT_DXT5_SRGBA:
                        result = FMT_BC3;
                        goto out_word4;
                default:
@@ -897,8 +929,6 @@ uint32_t r600_translate_texformat(enum pipe_format format,
 
        /* R8G8Bx_SNORM - TODO CxV8U8 */
 
-       /* RGTC - TODO */
-
        /* See whether the components are of the same size. */
        for (i = 1; i < desc->nr_channels; i++) {
                uniform = uniform && desc->channel[0].size == desc->channel[i].size;
@@ -927,7 +957,7 @@ uint32_t r600_translate_texformat(enum pipe_format format,
                            desc->channel[1].size == 10 &&
                            desc->channel[2].size == 10 &&
                            desc->channel[3].size == 2) {
-                               result = FMT_10_10_10_2;
+                               result = FMT_2_10_10_10;
                                goto out_word4;
                        }
                        goto out_unknown;
@@ -990,6 +1020,19 @@ uint32_t r600_translate_texformat(enum pipe_format format,
                                result = FMT_16_16_16_16;
                                goto out_word4;
                        }
+                       goto out_unknown;
+               case 32:
+                       switch (desc->nr_channels) {
+                       case 1:
+                               result = FMT_32;
+                               goto out_word4;
+                       case 2:
+                               result = FMT_32_32;
+                               goto out_word4;
+                       case 4:
+                               result = FMT_32_32_32_32;
+                               goto out_word4;
+                       }
                }
                goto out_unknown;
 
index f80fa7af941a3da920785b8a7c0a94479671bdf2..7482d15e12fb629a5cd152fa096bfaa27a3d8646 100644 (file)
  *
  * Authors: Dave Airlie <airlied@redhat.com>
  */
-#include "translate/translate_cache.h"
-#include "translate/translate.h"
-#include <pipebuffer/pb_buffer.h>
+
 #include <util/u_index_modify.h>
+#include "util/u_inlines.h"
+#include "util/u_upload_mgr.h"
 #include "r600_pipe.h"
 
-void r600_begin_vertex_translate(struct r600_pipe_context *rctx)
-{
-       struct pipe_context *pipe = &rctx->context;
-       struct translate_key key = {0};
-       struct translate_element *te;
-       unsigned tr_elem_index[PIPE_MAX_ATTRIBS] = {0};
-       struct translate *tr;
-       struct r600_vertex_element *ve = rctx->vertex_elements;
-       boolean vb_translated[PIPE_MAX_ATTRIBS] = {0};
-       void *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map;
-       struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}, *out_transfer;
-       struct pipe_resource *out_buffer;
-       unsigned i, num_verts;
-       struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS];
-       void *tmp;
-
-       /* Initialize the translate key, i.e. the recipe how vertices should be
-        * translated. */
-       for (i = 0; i < ve->count; i++) {
-               struct pipe_vertex_buffer *vb =
-                       &rctx->vertex_buffer[ve->elements[i].vertex_buffer_index];
-               enum pipe_format output_format = ve->hw_format[i];
-               unsigned output_format_size = ve->hw_format_size[i];
-
-               /* Check for support. */
-               if (ve->elements[i].src_format == ve->hw_format[i]) {
-                       continue;
-               }
-
-               /* Workaround for translate: output floats instead of halfs. */
-               switch (output_format) {
-               case PIPE_FORMAT_R16_FLOAT:
-                       output_format = PIPE_FORMAT_R32_FLOAT;
-                       output_format_size = 4;
-                       break;
-               case PIPE_FORMAT_R16G16_FLOAT:
-                       output_format = PIPE_FORMAT_R32G32_FLOAT;
-                       output_format_size = 8;
-                       break;
-               case PIPE_FORMAT_R16G16B16_FLOAT:
-                       output_format = PIPE_FORMAT_R32G32B32_FLOAT;
-                       output_format_size = 12;
-                       break;
-               case PIPE_FORMAT_R16G16B16A16_FLOAT:
-                       output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
-                       output_format_size = 16;
-                       break;
-               default:;
-               }
-
-               /* Add this vertex element. */
-               te = &key.element[key.nr_elements];
-               /*te->type;
-                 te->instance_divisor;*/
-               te->input_buffer = ve->elements[i].vertex_buffer_index;
-               te->input_format = ve->elements[i].src_format;
-               te->input_offset = vb->buffer_offset + ve->elements[i].src_offset;
-               te->output_format = output_format;
-               te->output_offset = key.output_stride;
-
-               key.output_stride += output_format_size;
-               vb_translated[ve->elements[i].vertex_buffer_index] = TRUE;
-               tr_elem_index[i] = key.nr_elements;
-               key.nr_elements++;
-       }
-
-       /* Get a translate object. */
-       tr = translate_cache_find(rctx->tran.translate_cache, &key);
-
-       /* Map buffers we want to translate. */
-       for (i = 0; i < rctx->nvertex_buffer; i++) {
-               if (vb_translated[i]) {
-                       struct pipe_vertex_buffer *vb = &rctx->vertex_buffer[i];
-
-                       vb_map[i] = pipe_buffer_map(pipe, vb->buffer,
-                                                   PIPE_TRANSFER_READ, &vb_transfer[i]);
-
-                       tr->set_buffer(tr, i, vb_map[i], vb->stride, vb->max_index);
-               }
-       }
-
-       /* Create and map the output buffer. */
-       num_verts = rctx->vb_max_index + 1;
-
-       out_buffer = pipe_buffer_create(&rctx->screen->screen,
-                                       PIPE_BIND_VERTEX_BUFFER,
-                                       key.output_stride * num_verts);
-
-       out_map = pipe_buffer_map(pipe, out_buffer, PIPE_TRANSFER_WRITE,
-                                 &out_transfer);
-
-       /* Translate. */
-       tr->run(tr, 0, num_verts, 0, out_map);
-
-       /* Unmap all buffers. */
-       for (i = 0; i < rctx->nvertex_buffer; i++) {
-               if (vb_translated[i]) {
-                       pipe_buffer_unmap(pipe, vb_transfer[i]);
-               }
-       }
-
-       pipe_buffer_unmap(pipe, out_transfer);
-
-       /* Setup the new vertex buffer in the first free slot. */
-       for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
-               struct pipe_vertex_buffer *vb = &rctx->vertex_buffer[i];
-
-               if (!vb->buffer) {
-                       pipe_resource_reference(&vb->buffer, out_buffer);
-                       vb->buffer_offset = 0;
-                       vb->max_index = num_verts - 1;
-                       vb->stride = key.output_stride;
-                       rctx->tran.vb_slot = i;
-                       break;
-               }
-       }
-
-       /* Save and replace vertex elements. */
-       for (i = 0; i < ve->count; i++) {
-               if (vb_translated[ve->elements[i].vertex_buffer_index]) {
-                       te = &key.element[tr_elem_index[i]];
-                       new_velems[i].instance_divisor = ve->elements[i].instance_divisor;
-                       new_velems[i].src_format = te->output_format;
-                       new_velems[i].src_offset = te->output_offset;
-                       new_velems[i].vertex_buffer_index = rctx->tran.vb_slot;
-               } else {
-                       memcpy(&new_velems[i], &ve->elements[i],
-                                       sizeof(struct pipe_vertex_element));
-               }
-       }
-
-       tmp = pipe->create_vertex_elements_state(pipe, ve->count, new_velems);
-       pipe->bind_vertex_elements_state(pipe, tmp);
-       rctx->tran.new_velems = tmp;
-
-       pipe_resource_reference(&out_buffer, NULL);
-}
-
-void r600_end_vertex_translate(struct r600_pipe_context *rctx)
-{
-       struct pipe_context *pipe = &rctx->context;
-
-       if (rctx->tran.new_velems == NULL) {
-               return;
-       }
-       /* Restore vertex elements. */
-       pipe->delete_vertex_elements_state(pipe, rctx->tran.new_velems);
-       rctx->tran.new_velems = NULL;
-
-       /* Delete the now-unused VBO. */
-       pipe_resource_reference(&rctx->vertex_buffer[rctx->tran.vb_slot].buffer, NULL);
-}
 
 void r600_translate_index_buffer(struct r600_pipe_context *r600,
-                                       struct pipe_resource **index_buffer,
-                                       unsigned *index_size,
-                                       unsigned *start, unsigned count)
+                                struct pipe_resource **index_buffer,
+                                unsigned *index_size,
+                                unsigned *start, unsigned count)
 {
+       struct pipe_resource *out_buffer = NULL;
+       unsigned out_offset;
+       void *ptr;
+       boolean flushed;
+
        switch (*index_size) {
        case 1:
-               util_shorten_ubyte_elts(&r600->context, index_buffer, 0, *start, count);
+               u_upload_alloc(r600->vbuf_mgr->uploader, 0, count * 2,
+                              &out_offset, &out_buffer, &flushed, &ptr);
+
+               util_shorten_ubyte_elts_to_userptr(
+                               &r600->context, *index_buffer, 0, *start, count, ptr);
+
+               pipe_resource_reference(index_buffer, out_buffer);
                *index_size = 2;
-               *start = 0;
-               break;
-       case 2:
-       case 4:
+               *start = out_offset / 2;
                break;
        }
 }
diff --git a/src/gallium/drivers/r600/r600_upload.c b/src/gallium/drivers/r600/r600_upload.c
deleted file mode 100644 (file)
index 44102ff..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *      Jerome Glisse <jglisse@redhat.com>
- */
-#include <errno.h>
-#include "util/u_inlines.h"
-#include "util/u_memory.h"
-#include "r600.h"
-#include "r600_pipe.h"
-#include "r600_resource.h"
-
-struct r600_upload {
-       struct r600_pipe_context        *rctx;
-       struct r600_bo                  *buffer;
-       char                            *ptr;
-       unsigned                        size;
-       unsigned                        default_size;
-       unsigned                        total_alloc_size;
-       unsigned                        offset;
-       unsigned                        alignment;
-};
-
-struct r600_upload *r600_upload_create(struct r600_pipe_context *rctx,
-                                       unsigned default_size,
-                                       unsigned alignment)
-{
-       struct r600_upload *upload = CALLOC_STRUCT(r600_upload);
-
-       if (upload == NULL)
-               return NULL;
-
-       upload->rctx = rctx;
-       upload->size = 0;
-       upload->default_size = default_size;
-       upload->alignment = alignment;
-       upload->ptr = NULL;
-       upload->buffer = NULL;
-       upload->total_alloc_size = 0;
-
-       return upload;
-}
-
-void r600_upload_flush(struct r600_upload *upload)
-{
-       if (upload->buffer) {
-               r600_bo_reference(upload->rctx->radeon, &upload->buffer, NULL);
-       }
-       upload->default_size = MAX2(upload->total_alloc_size, upload->default_size);
-       upload->total_alloc_size = 0;
-       upload->size = 0;
-       upload->offset = 0;
-       upload->ptr = NULL;
-       upload->buffer = NULL;
-}
-
-void r600_upload_destroy(struct r600_upload *upload)
-{
-       r600_upload_flush(upload);
-       FREE(upload);
-}
-
-int r600_upload_buffer(struct r600_upload *upload, unsigned offset,
-                       unsigned size, struct r600_resource_buffer *in_buffer,
-                       unsigned *out_offset, unsigned *out_size,
-                       struct r600_bo **out_buffer)
-{
-       unsigned alloc_size = align(size, upload->alignment);
-       const void *in_ptr = NULL;
-
-       if (upload->offset + alloc_size > upload->size) {
-               if (upload->size) {
-                       r600_bo_reference(upload->rctx->radeon, &upload->buffer, NULL);
-               }
-               upload->size = align(MAX2(upload->default_size, alloc_size), 4096);
-               upload->total_alloc_size += upload->size;
-               upload->offset = 0;
-               upload->buffer = r600_bo(upload->rctx->radeon, upload->size, 4096, PIPE_BIND_VERTEX_BUFFER, 0);
-               if (upload->buffer == NULL) {
-                       return -ENOMEM;
-               }
-               upload->ptr = r600_bo_map(upload->rctx->radeon, upload->buffer, 0, NULL);
-       }
-
-       in_ptr = in_buffer->user_buffer;
-       memcpy(upload->ptr + upload->offset, (uint8_t *) in_ptr + offset, size);
-       *out_offset = upload->offset;
-       *out_size = upload->size;
-       *out_buffer = NULL;
-       r600_bo_reference(upload->rctx->radeon, out_buffer, upload->buffer);
-       upload->offset += alloc_size;
-
-       return 0;
-}
index 8c391936db00e1211b4651270c832bb6c4e10237..e8558c49a7cab03827b6773f2b3a3d4d05727f87 100644 (file)
 #define   S_0280A0_SOURCE_FORMAT(x)                    (((x) & 0x1) << 27)
 #define   G_0280A0_SOURCE_FORMAT(x)                    (((x) >> 27) & 0x1)
 #define   C_0280A0_SOURCE_FORMAT                       0xF7FFFFFF
+#define     V_0280A0_EXPORT_FULL                       0
+#define     V_0280A0_EXPORT_NORM                       1
 #define R_028060_CB_COLOR0_SIZE                      0x028060
 #define   S_028060_PITCH_TILE_MAX(x)                   (((x) & 0x3FF) << 0)
 #define   G_028060_PITCH_TILE_MAX(x)                   (((x) >> 0) & 0x3FF)
 #define R_0280D4_CB_COLOR5_TILE                      0x0280D4
 #define R_0280D8_CB_COLOR6_TILE                      0x0280D8
 #define R_0280DC_CB_COLOR7_TILE                      0x0280DC
-#define R_028808_CB_COLOR_CONTROL                    0x028808
-#define   S_028808_FOG_ENABLE(x)                       (((x) & 0x1) << 0)
-#define   G_028808_FOG_ENABLE(x)                       (((x) >> 0) & 0x1)
-#define   C_028808_FOG_ENABLE                          0xFFFFFFFE
-#define   S_028808_MULTIWRITE_ENABLE(x)                (((x) & 0x1) << 1)
-#define   G_028808_MULTIWRITE_ENABLE(x)                (((x) >> 1) & 0x1)
-#define   C_028808_MULTIWRITE_ENABLE                   0xFFFFFFFD
-#define   S_028808_DITHER_ENABLE(x)                    (((x) & 0x1) << 2)
-#define   G_028808_DITHER_ENABLE(x)                    (((x) >> 2) & 0x1)
-#define   C_028808_DITHER_ENABLE                       0xFFFFFFFB
-#define   S_028808_DEGAMMA_ENABLE(x)                   (((x) & 0x1) << 3)
-#define   G_028808_DEGAMMA_ENABLE(x)                   (((x) >> 3) & 0x1)
-#define   C_028808_DEGAMMA_ENABLE                      0xFFFFFFF7
-#define   S_028808_SPECIAL_OP(x)                       (((x) & 0x7) << 4)
-#define   G_028808_SPECIAL_OP(x)                       (((x) >> 4) & 0x7)
-#define   C_028808_SPECIAL_OP                          0xFFFFFF8F
-#define   S_028808_PER_MRT_BLEND(x)                    (((x) & 0x1) << 7)
-#define   G_028808_PER_MRT_BLEND(x)                    (((x) >> 7) & 0x1)
-#define   C_028808_PER_MRT_BLEND                       0xFFFFFF7F
-#define   S_028808_TARGET_BLEND_ENABLE(x)              (((x) & 0xFF) << 8)
-#define   G_028808_TARGET_BLEND_ENABLE(x)              (((x) >> 8) & 0xFF)
-#define   C_028808_TARGET_BLEND_ENABLE                 0xFFFF00FF
-#define   S_028808_ROP3(x)                             (((x) & 0xFF) << 16)
-#define   G_028808_ROP3(x)                             (((x) >> 16) & 0xFF)
-#define   C_028808_ROP3                                0xFF00FFFF
 #define R_028614_SPI_VS_OUT_ID_0                     0x028614
 #define   S_028614_SEMANTIC_0(x)                       (((x) & 0xFF) << 0)
 #define   G_028614_SEMANTIC_0(x)                       (((x) >> 0) & 0xFF)
index 94e57e40f86d78e7d4110dc5be00cf478897f7ea..3aefb5b3bb519ecee83038720b0df7f55e14af20 100644 (file)
@@ -987,6 +987,19 @@ rbug_context_transfer_inline_write(struct pipe_context *_context,
 }
 
 
+static void rbug_redefine_user_buffer(struct pipe_context *_context,
+                                      struct pipe_resource *_resource,
+                                      unsigned offset, unsigned size)
+{
+   struct rbug_context *rb_pipe = rbug_context(_context);
+   struct rbug_resource *rb_resource = rbug_resource(_resource);
+   struct pipe_context *context = rb_pipe->pipe;
+   struct pipe_resource *resource = rb_resource->resource;
+
+   context->redefine_user_buffer(context, resource, offset, size);
+}
+
+
 struct pipe_context *
 rbug_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
 {
@@ -1072,6 +1085,7 @@ rbug_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
    rb_pipe->base.transfer_unmap = rbug_context_transfer_unmap;
    rb_pipe->base.transfer_flush_region = rbug_context_transfer_flush_region;
    rb_pipe->base.transfer_inline_write = rbug_context_transfer_inline_write;
+   rb_pipe->base.redefine_user_buffer = rbug_redefine_user_buffer;
 
    rb_pipe->pipe = pipe;
 
index 7d7cc482ae68b92020116bc10dc82e4e3ad6f038..15f5db40093eb61c01438b8ce48e6c7d0b0f6baa 100644 (file)
@@ -98,8 +98,9 @@ rbug_surface_create(struct rbug_context *rb_context,
 
    pipe_reference_init(&rb_surface->base.reference, 1);
    rb_surface->base.texture = NULL;
+   rb_surface->base.context = &rb_context->base;
+   rb_surface->surface = surface; /* we own the surface already */
    pipe_resource_reference(&rb_surface->base.texture, &rb_resource->base);
-   rb_surface->surface = surface;
 
    return &rb_surface->base;
 
@@ -113,8 +114,7 @@ rbug_surface_destroy(struct rbug_context *rb_context,
                      struct rbug_surface *rb_surface)
 {
    pipe_resource_reference(&rb_surface->base.texture, NULL);
-   rb_context->pipe->surface_destroy(rb_context->pipe,
-                                     rb_surface->surface);
+   pipe_surface_reference(&rb_surface->surface, NULL);
    FREE(rb_surface);
 }
 
index fe54f92addf7d0c4052b3161abf2ee598a85633f..70fdfb7ddf3fbecc83873873ad26fc3bef95d88a 100644 (file)
@@ -230,7 +230,7 @@ softpipe_create_context( struct pipe_screen *screen,
    softpipe->use_sse = FALSE;
 #endif
 
-   softpipe->dump_fs = debug_get_bool_option( "GALLIUM_DUMP_FS", FALSE );
+   softpipe->dump_fs = debug_get_bool_option( "SOFTPIPE_DUMP_FS", FALSE );
    softpipe->dump_gs = debug_get_bool_option( "SOFTPIPE_DUMP_GS", FALSE );
 
    softpipe->pipe.winsys = NULL;
@@ -315,7 +315,7 @@ softpipe_create_context( struct pipe_screen *screen,
                          (struct tgsi_sampler **)
                             softpipe->tgsi.geom_samplers_list);
 
-   if (debug_get_bool_option( "SP_NO_RAST", FALSE ))
+   if (debug_get_bool_option( "SOFTPIPE_NO_RAST", FALSE ))
       softpipe->no_rast = TRUE;
 
    softpipe->vbuf_backend = sp_create_vbuf_backend(softpipe);
index 035d712d17cb14c299154738bf1c4161fc4846cf..c91709aef06303f7279b4099fbc217b810232400 100644 (file)
@@ -58,7 +58,7 @@ struct softpipe_context {
 
    /** Constant state objects */
    struct pipe_blend_state *blend;
-   struct pipe_sampler_state *sampler[PIPE_MAX_SAMPLERS];
+   struct pipe_sampler_state *fragment_samplers[PIPE_MAX_SAMPLERS];
    struct pipe_sampler_state *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS];
    struct pipe_sampler_state *geometry_samplers[PIPE_MAX_GEOMETRY_SAMPLERS];
    struct pipe_depth_stencil_alpha_state *depth_stencil;
@@ -91,8 +91,8 @@ struct softpipe_context {
    } so_target;
    struct pipe_query_data_so_statistics so_stats;
 
-   unsigned num_samplers;
-   unsigned num_sampler_views;
+   unsigned num_fragment_samplers;
+   unsigned num_fragment_sampler_views;
    unsigned num_vertex_samplers;
    unsigned num_vertex_sampler_views;
    unsigned num_geometry_samplers;
index d422cb17a4bbfabe7caeafd25e09073f584d6779..6f7addd441a94828c807baa81e378ef07baeaca7 100644 (file)
@@ -51,7 +51,7 @@ softpipe_flush( struct pipe_context *pipe,
    draw_flush(softpipe->draw);
 
    if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
-      for (i = 0; i < softpipe->num_sampler_views; i++) {
+      for (i = 0; i < softpipe->num_fragment_sampler_views; i++) {
          sp_flush_tex_tile_cache(softpipe->fragment_tex_cache[i]);
       }
       for (i = 0; i < softpipe->num_vertex_sampler_views; i++) {
index c433405cb66365b105becbcf0d0638da69381be0..a06817c573527f677737f7f9a4cf9f044f99c63d 100644 (file)
@@ -126,6 +126,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
       return 1;
    case PIPE_CAP_INSTANCED_DRAWING:
       return 1;
+   case PIPE_CAP_ARRAY_TEXTURES:
+      return 1;
    default:
       return 0;
    }
@@ -186,7 +188,9 @@ softpipe_is_format_supported( struct pipe_screen *screen,
 
    assert(target == PIPE_BUFFER ||
           target == PIPE_TEXTURE_1D ||
+          target == PIPE_TEXTURE_1D_ARRAY ||
           target == PIPE_TEXTURE_2D ||
+          target == PIPE_TEXTURE_2D_ARRAY ||
           target == PIPE_TEXTURE_RECT ||
           target == PIPE_TEXTURE_3D ||
           target == PIPE_TEXTURE_CUBE);
index 5d727dc00df0952ebdfe7ca1676aa28da45ff60b..0ce28f4c6ee09d070b8f15f43b26e49165fd0b79 100644 (file)
@@ -575,7 +575,7 @@ setup_fragcoord_coeff(struct setup_context *setup, uint slot)
    setup->coef[slot].dady[0] = 0.0;
    /*Y*/
    setup->coef[slot].a0[1] =
-                  (spfs->origin_lower_left ? setup->softpipe->framebuffer.height : 0)
+                  (spfs->origin_lower_left ? setup->softpipe->framebuffer.height-1 : 0)
                   + (spfs->pixel_center_integer ? 0.0 : 0.5);
    setup->coef[slot].dadx[1] = 0.0;
    setup->coef[slot].dady[1] = spfs->origin_lower_left ? -1.0 : 1.0;
index 389435638005a74e62d2dd41acedf259f499caff..60331bc49763bff20d59f91818f844845908964a 100644 (file)
@@ -76,18 +76,18 @@ softpipe_bind_fragment_sampler_states(struct pipe_context *pipe,
    assert(num <= PIPE_MAX_SAMPLERS);
 
    /* Check for no-op */
-   if (num == softpipe->num_samplers &&
-       !memcmp(softpipe->sampler, sampler, num * sizeof(void *)))
+   if (num == softpipe->num_fragment_samplers &&
+       !memcmp(softpipe->fragment_samplers, sampler, num * sizeof(void *)))
       return;
 
    draw_flush(softpipe->draw);
 
    for (i = 0; i < num; ++i)
-      softpipe->sampler[i] = sampler[i];
+      softpipe->fragment_samplers[i] = sampler[i];
    for (i = num; i < PIPE_MAX_SAMPLERS; ++i)
-      softpipe->sampler[i] = NULL;
+      softpipe->fragment_samplers[i] = NULL;
 
-   softpipe->num_samplers = num;
+   softpipe->num_fragment_samplers = num;
 
    softpipe->dirty |= SP_NEW_SAMPLER;
 }
@@ -191,7 +191,7 @@ softpipe_set_fragment_sampler_views(struct pipe_context *pipe,
    assert(num <= PIPE_MAX_SAMPLERS);
 
    /* Check for no-op */
-   if (num == softpipe->num_sampler_views &&
+   if (num == softpipe->num_fragment_sampler_views &&
        !memcmp(softpipe->fragment_sampler_views, views,
                num * sizeof(struct pipe_sampler_view *)))
       return;
@@ -205,7 +205,7 @@ softpipe_set_fragment_sampler_views(struct pipe_context *pipe,
       sp_tex_tile_cache_set_sampler_view(softpipe->fragment_tex_cache[i], view);
    }
 
-   softpipe->num_sampler_views = num;
+   softpipe->num_fragment_sampler_views = num;
 
    softpipe->dirty |= SP_NEW_TEXTURE;
 }
@@ -374,10 +374,10 @@ softpipe_reset_sampler_variants(struct softpipe_context *softpipe)
    }
 
    for (i = 0; i <= softpipe->fs->info.file_max[TGSI_FILE_SAMPLER]; i++) {
-      if (softpipe->sampler[i]) {
+      if (softpipe->fragment_samplers[i]) {
          softpipe->tgsi.frag_samplers_list[i] =
             get_sampler_variant( i,
-                                 sp_sampler(softpipe->sampler[i]),
+                                 sp_sampler(softpipe->fragment_samplers[i]),
                                  softpipe->fragment_sampler_views[i],
                                  TGSI_PROCESSOR_FRAGMENT );
 
index 5f4d661abde74ed6cb0297ed69caacf4fe7bcda0..aa0b333c7a9ae348145f5a8e57cbf852fd8c83e2 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "util/u_memory.h"
 #include "util/u_inlines.h"
+#include "util/u_transfer.h"
 #include "draw/draw_context.h"
 
 
@@ -119,4 +120,5 @@ softpipe_init_vertex_funcs(struct pipe_context *pipe)
 
    pipe->set_vertex_buffers = softpipe_set_vertex_buffers;
    pipe->set_index_buffer = softpipe_set_index_buffer;
+   pipe->redefine_user_buffer = u_default_redefine_user_buffer;
 }
index 242c27c7ebd6eb43d46b6892c42cc038dd1481c3..8a4ef934348390229288cb713e157249e6b6af39 100644 (file)
@@ -539,6 +539,19 @@ wrap_linear_unorm_clamp_to_edge(const float s[4], unsigned size,
 }
 
 
+/**
+ * Do coordinate to array index conversion.  For array textures.
+ */
+static INLINE void
+wrap_array_layer(const float coord[4], unsigned size, int layer[4])
+{
+   uint ch;
+   for (ch = 0; ch < 4; ch++) {
+      int c = util_ifloor(coord[ch] + 0.5F);
+      layer[ch] = CLAMP(c, 0, size - 1);
+   }
+}
+
 
 /**
  * Examine the quad's texture coordinates to compute the partial
@@ -761,6 +774,43 @@ get_texel_3d(const struct sp_sampler_variant *samp,
 }
 
 
+/* Get texel pointer for 1D array texture */
+static INLINE const float *
+get_texel_1d_array(const struct sp_sampler_variant *samp,
+                   union tex_tile_address addr, int x, int y)
+{
+   const struct pipe_resource *texture = samp->view->texture;
+   unsigned level = addr.bits.level;
+
+   if (x < 0 || x >= (int) u_minify(texture->width0, level)) {
+      return samp->sampler->border_color;
+   }
+   else {
+      return get_texel_2d_no_border(samp, addr, x, y);
+   }
+}
+
+
+/* Get texel pointer for 2D array texture */
+static INLINE const float *
+get_texel_2d_array(const struct sp_sampler_variant *samp,
+                   union tex_tile_address addr, int x, int y, int layer)
+{
+   const struct pipe_resource *texture = samp->view->texture;
+   unsigned level = addr.bits.level;
+
+   assert(layer < texture->array_size);
+
+   if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
+       y < 0 || y >= (int) u_minify(texture->height0, level)) {
+      return samp->sampler->border_color;
+   }
+   else {
+      return get_texel_3d_no_border(samp, addr, x, y, layer);
+   }
+}
+
+
 /**
  * Given the logbase2 of a mipmap's base level size and a mipmap level,
  * return the size (in texels) of that mipmap level.
@@ -989,6 +1039,47 @@ img_filter_1d_nearest(struct tgsi_sampler *tgsi_sampler,
 }
 
 
+static void
+img_filter_1d_array_nearest(struct tgsi_sampler *tgsi_sampler,
+                            const float s[QUAD_SIZE],
+                            const float t[QUAD_SIZE],
+                            const float p[QUAD_SIZE],
+                            const float c0[QUAD_SIZE],
+                            enum tgsi_sampler_control control,
+                            float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+   const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
+   const struct pipe_resource *texture = samp->view->texture;
+   unsigned level0, j;
+   int width;
+   int x[4], layer[4];
+   union tex_tile_address addr;
+
+   level0 = samp->level;
+   width = u_minify(texture->width0, level0);
+
+   assert(width > 0);
+
+   addr.value = 0;
+   addr.bits.level = samp->level;
+
+   samp->nearest_texcoord_s(s, width, x);
+   wrap_array_layer(t, texture->array_size, layer);
+
+   for (j = 0; j < QUAD_SIZE; j++) {
+      const float *out = get_texel_1d_array(samp, addr, x[j], layer[j]);
+      int c;
+      for (c = 0; c < 4; c++) {
+         rgba[c][j] = out[c];
+      }
+   }
+
+   if (DEBUG_TEX) {
+      print_sample(__FUNCTION__, rgba);
+   }
+}
+
+
 static void
 img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler,
                       const float s[QUAD_SIZE],
@@ -1033,6 +1124,50 @@ img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler,
 }
 
 
+static void
+img_filter_2d_array_nearest(struct tgsi_sampler *tgsi_sampler,
+                            const float s[QUAD_SIZE],
+                            const float t[QUAD_SIZE],
+                            const float p[QUAD_SIZE],
+                            const float c0[QUAD_SIZE],
+                            enum tgsi_sampler_control control,
+                            float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+   const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
+   const struct pipe_resource *texture = samp->view->texture;
+   unsigned level0, j;
+   int width, height;
+   int x[4], y[4], layer[4];
+   union tex_tile_address addr;
+
+   level0 = samp->level;
+   width = u_minify(texture->width0, level0);
+   height = u_minify(texture->height0, level0);
+
+   assert(width > 0);
+   assert(height > 0);
+   addr.value = 0;
+   addr.bits.level = samp->level;
+
+   samp->nearest_texcoord_s(s, width, x);
+   samp->nearest_texcoord_t(t, height, y);
+   wrap_array_layer(p, texture->array_size, layer);
+
+   for (j = 0; j < QUAD_SIZE; j++) {
+      const float *out = get_texel_2d_array(samp, addr, x[j], y[j], layer[j]);
+      int c;
+      for (c = 0; c < 4; c++) {
+         rgba[c][j] = out[c];
+      }
+   }
+
+   if (DEBUG_TEX) {
+      print_sample(__FUNCTION__, rgba);
+   }
+}
+
+
 static INLINE union tex_tile_address
 face(union tex_tile_address addr, unsigned face )
 {
@@ -1167,6 +1302,47 @@ img_filter_1d_linear(struct tgsi_sampler *tgsi_sampler,
 }
 
 
+static void
+img_filter_1d_array_linear(struct tgsi_sampler *tgsi_sampler,
+                           const float s[QUAD_SIZE],
+                           const float t[QUAD_SIZE],
+                           const float p[QUAD_SIZE],
+                           const float c0[QUAD_SIZE],
+                           enum tgsi_sampler_control control,
+                           float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+   const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
+   const struct pipe_resource *texture = samp->view->texture;
+   unsigned level0, j;
+   int width;
+   int x0[4], x1[4], layer[4];
+   float xw[4]; /* weights */
+   union tex_tile_address addr;
+
+   level0 = samp->level;
+   width = u_minify(texture->width0, level0);
+
+   assert(width > 0);
+
+   addr.value = 0;
+   addr.bits.level = samp->level;
+
+   samp->linear_texcoord_s(s, width, x0, x1, xw);
+   wrap_array_layer(t, texture->array_size, layer);
+
+   for (j = 0; j < QUAD_SIZE; j++) {
+      const float *tx0 = get_texel_1d_array(samp, addr, x0[j], layer[j]);
+      const float *tx1 = get_texel_1d_array(samp, addr, x1[j], layer[j]);
+      int c;
+
+      /* interpolate R, G, B, A */
+      for (c = 0; c < 4; c++) {
+         rgba[c][j] = lerp(xw[j], tx0[c], tx1[c]);
+      }
+   }
+}
+
+
 static void
 img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler,
                      const float s[QUAD_SIZE],
@@ -1214,6 +1390,54 @@ img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler,
 }
 
 
+static void
+img_filter_2d_array_linear(struct tgsi_sampler *tgsi_sampler,
+                           const float s[QUAD_SIZE],
+                           const float t[QUAD_SIZE],
+                           const float p[QUAD_SIZE],
+                           const float c0[QUAD_SIZE],
+                           enum tgsi_sampler_control control,
+                           float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+   const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
+   const struct pipe_resource *texture = samp->view->texture;
+   unsigned level0, j;
+   int width, height;
+   int x0[4], y0[4], x1[4], y1[4], layer[4];
+   float xw[4], yw[4]; /* weights */
+   union tex_tile_address addr;
+
+   level0 = samp->level;
+   width = u_minify(texture->width0, level0);
+   height = u_minify(texture->height0, level0);
+
+   assert(width > 0);
+   assert(height > 0);
+
+   addr.value = 0;
+   addr.bits.level = samp->level;
+
+   samp->linear_texcoord_s(s, width,  x0, x1, xw);
+   samp->linear_texcoord_t(t, height, y0, y1, yw);
+   wrap_array_layer(p, texture->array_size, layer);
+
+   for (j = 0; j < QUAD_SIZE; j++) {
+      const float *tx0 = get_texel_2d_array(samp, addr, x0[j], y0[j], layer[j]);
+      const float *tx1 = get_texel_2d_array(samp, addr, x1[j], y0[j], layer[j]);
+      const float *tx2 = get_texel_2d_array(samp, addr, x0[j], y1[j], layer[j]);
+      const float *tx3 = get_texel_2d_array(samp, addr, x1[j], y1[j], layer[j]);
+      int c;
+
+      /* interpolate R, G, B, A */
+      for (c = 0; c < 4; c++) {
+         rgba[c][j] = lerp_2d(xw[j], yw[j],
+                              tx0[c], tx1[c],
+                              tx2[c], tx3[c]);
+      }
+   }
+}
+
+
 static void
 img_filter_cube_linear(struct tgsi_sampler *tgsi_sampler,
                        const float s[QUAD_SIZE],
@@ -1906,8 +2130,10 @@ get_lambda_func(const union sp_sampler_key key)
    
    switch (key.bits.target) {
    case PIPE_TEXTURE_1D:
+   case PIPE_TEXTURE_1D_ARRAY:
       return compute_lambda_1d;
    case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_2D_ARRAY:
    case PIPE_TEXTURE_RECT:
    case PIPE_TEXTURE_CUBE:
       return compute_lambda_2d;
@@ -1932,6 +2158,12 @@ get_img_filter(const union sp_sampler_key key,
       else
          return img_filter_1d_linear;
       break;
+   case PIPE_TEXTURE_1D_ARRAY:
+      if (filter == PIPE_TEX_FILTER_NEAREST) 
+         return img_filter_1d_array_nearest;
+      else
+         return img_filter_1d_array_linear;
+      break;
    case PIPE_TEXTURE_2D:
    case PIPE_TEXTURE_RECT:
       /* Try for fast path:
@@ -1967,6 +2199,12 @@ get_img_filter(const union sp_sampler_key key,
       else
          return img_filter_2d_linear;
       break;
+   case PIPE_TEXTURE_2D_ARRAY:
+      if (filter == PIPE_TEX_FILTER_NEAREST) 
+         return img_filter_2d_array_nearest;
+      else
+         return img_filter_2d_array_linear;
+      break;
    case PIPE_TEXTURE_CUBE:
       if (filter == PIPE_TEX_FILTER_NEAREST) 
          return img_filter_cube_nearest;
index e42015ad498099e0a5674081d368da7c28d28231..e589ee7c84100b8393a4f9392d2e98c2579b71ae 100644 (file)
@@ -251,6 +251,7 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc,
           tc->tex_level != addr.bits.level ||
           tc->tex_z != addr.bits.z) {
          /* get new transfer (view into texture) */
+         unsigned width, height, layer;
 
          if (tc->tex_trans) {
             if (tc->tex_trans_map) {
@@ -262,14 +263,22 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc,
             tc->tex_trans = NULL;
          }
 
+         width = u_minify(tc->texture->width0, addr.bits.level);
+         if (tc->texture->target == PIPE_TEXTURE_1D_ARRAY) {
+            height = tc->texture->array_size;
+            layer = 0;
+         }
+         else {
+            height = u_minify(tc->texture->height0, addr.bits.level);
+            layer = addr.bits.face + addr.bits.z;
+         }
+
          tc->tex_trans = 
             pipe_get_transfer(tc->pipe, tc->texture,
                               addr.bits.level,
-                              addr.bits.face + addr.bits.z,
+                              layer,
                               PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED,
-                              0, 0,
-                              u_minify(tc->texture->width0, addr.bits.level),
-                              u_minify(tc->texture->height0, addr.bits.level));
+                              0, 0, width, height);
 
          tc->tex_trans_map = tc->pipe->transfer_map(tc->pipe, tc->tex_trans);
 
@@ -278,22 +287,17 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc,
          tc->tex_z = addr.bits.z;
       }
 
-      /* get tile from the transfer (view into texture)
-       * Note we're using the swizzle version of this fuction only because
-       * we need to pass the texture cache's format explicitly.
+      /* Get tile from the transfer (view into texture), explicitly passing
+       * the image format.
        */
-      pipe_get_tile_swizzle(tc->pipe,
-                           tc->tex_trans,
-                            addr.bits.x * TILE_SIZE, 
-                            addr.bits.y * TILE_SIZE,
-                            TILE_SIZE,
-                            TILE_SIZE,
-                            PIPE_SWIZZLE_RED,
-                            PIPE_SWIZZLE_GREEN,
-                            PIPE_SWIZZLE_BLUE,
-                            PIPE_SWIZZLE_ALPHA,
-                            tc->format,
-                            (float *) tile->data.color);
+      pipe_get_tile_rgba_format(tc->pipe,
+                                tc->tex_trans,
+                                addr.bits.x * TILE_SIZE, 
+                                addr.bits.y * TILE_SIZE,
+                                TILE_SIZE,
+                                TILE_SIZE,
+                                tc->format,
+                                (float *) tile->data.color);
 
       tile->addr = addr;
    }
index 2220955b715cb12a39151ac00ef8aa708f3e84a3..9bced37990a48e1797d9e327f4b49f8e70df94a1 100644 (file)
@@ -92,7 +92,7 @@ struct softpipe_tex_tile_cache
    unsigned swizzle_g;
    unsigned swizzle_b;
    unsigned swizzle_a;
-   unsigned format;
+   enum pipe_format format;
 
    struct softpipe_tex_cached_tile *last_tile;  /**< most recently retrieved tile */
 };
index 509d9982b17b9504a413f5c9553e5f155181dca4..95374c34ec3fd335f73ef71dbd48b6729bba87fc 100644 (file)
@@ -62,13 +62,21 @@ softpipe_resource_layout(struct pipe_screen *screen,
    unsigned buffer_size = 0;
 
    for (level = 0; level <= pt->last_level; level++) {
+      unsigned slices;
+
+      if (pt->target == PIPE_TEXTURE_CUBE)
+         slices = 6;
+      else if (pt->target == PIPE_TEXTURE_3D)
+         slices = depth;
+      else
+         slices = pt->array_size;
+
       spr->stride[level] = util_format_get_stride(pt->format, width);
 
       spr->level_offset[level] = buffer_size;
 
       buffer_size += (util_format_get_nblocksy(pt->format, height) *
-                      ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) *
-                      spr->stride[level]);
+                      slices * spr->stride[level]);
 
       width  = u_minify(width, 1);
       height = u_minify(height, 1);
@@ -227,9 +235,13 @@ sp_get_tex_image_offset(const struct softpipe_resource *spr,
    unsigned offset = spr->level_offset[level];
 
    if (spr->base.target == PIPE_TEXTURE_CUBE ||
-       spr->base.target == PIPE_TEXTURE_3D) {
+       spr->base.target == PIPE_TEXTURE_3D ||
+       spr->base.target == PIPE_TEXTURE_2D_ARRAY) {
       offset += layer * nblocksy * spr->stride[level];
    }
+   else if (spr->base.target == PIPE_TEXTURE_1D_ARRAY) {
+      offset += layer * spr->stride[level];
+   }
    else {
       assert(layer == 0);
    }
@@ -292,7 +304,7 @@ softpipe_surface_destroy(struct pipe_context *pipe,
  * a resource object.
  * \param pipe  rendering context
  * \param resource  the resource to transfer in/out of
- * \param sr  indicates cube face or 3D texture slice
+ * \param level  which mipmap level
  * \param usage  bitmask of PIPE_TRANSFER_x flags
  * \param box  the 1D/2D/3D region of interest
  */
@@ -311,8 +323,21 @@ softpipe_get_transfer(struct pipe_context *pipe,
 
    /* make sure the requested region is in the image bounds */
    assert(box->x + box->width <= u_minify(resource->width0, level));
-   assert(box->y + box->height <= u_minify(resource->height0, level));
-   assert(box->z + box->depth <= (u_minify(resource->depth0, level) + resource->array_size - 1));
+   if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
+      assert(box->y + box->height <= resource->array_size);
+   }
+   else {
+      assert(box->y + box->height <= u_minify(resource->height0, level));
+      if (resource->target == PIPE_TEXTURE_2D_ARRAY) {
+         assert(box->z + box->depth <= resource->array_size);
+      }
+      else if (resource->target == PIPE_TEXTURE_CUBE) {
+         assert(box->z < 6);
+      }
+      else {
+         assert(box->z + box->depth <= (u_minify(resource->depth0, level)));
+      }
+   }
 
    /*
     * Transfers, like other pipe operations, must happen in order, so flush the
index 480860af63b3cf4a543d1ba90353b3c81542bc70..60870b8bee5a606e93d1e11a03b87b4b87261552 100644 (file)
@@ -357,11 +357,12 @@ sp_flush_tile(struct softpipe_tile_cache* tc, unsigned pos)
                            tc->entries[pos]->data.depth32, 0/*STRIDE*/);
       }
       else {
-         pipe_put_tile_rgba(tc->pipe, tc->transfer,
-                            tc->tile_addrs[pos].bits.x * TILE_SIZE,
-                            tc->tile_addrs[pos].bits.y * TILE_SIZE,
-                            TILE_SIZE, TILE_SIZE,
-                            (float *) tc->entries[pos]->data.color);
+         pipe_put_tile_rgba_format(tc->pipe, tc->transfer,
+                                   tc->tile_addrs[pos].bits.x * TILE_SIZE,
+                                   tc->tile_addrs[pos].bits.y * TILE_SIZE,
+                                   TILE_SIZE, TILE_SIZE,
+                                   tc->surface->format,
+                                   (float *) tc->entries[pos]->data.color);
       }
       tc->tile_addrs[pos].bits.invalid = 1;  /* mark as empty */
    }
@@ -468,11 +469,12 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc,
                               tile->data.depth32, 0/*STRIDE*/);
          }
          else {
-            pipe_put_tile_rgba(tc->pipe, pt,
-                               tc->tile_addrs[pos].bits.x * TILE_SIZE,
-                               tc->tile_addrs[pos].bits.y * TILE_SIZE,
-                               TILE_SIZE, TILE_SIZE,
-                               (float *) tile->data.color);
+            pipe_put_tile_rgba_format(tc->pipe, pt,
+                                      tc->tile_addrs[pos].bits.x * TILE_SIZE,
+                                      tc->tile_addrs[pos].bits.y * TILE_SIZE,
+                                      TILE_SIZE, TILE_SIZE,
+                                      tc->surface->format,
+                                      (float *) tile->data.color);
          }
       }
 
index 1e513f1039f48908854ddf3b4daa595afb0054ba..f0f875b2b23583ae3e8ab656599f99d7f51d3e69 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "svga_context.h"
 #include "svga_screen.h"
+#include "svga_surface.h"
 #include "svga_resource_texture.h"
 #include "svga_resource_buffer.h"
 #include "svga_resource.h"
 #include "svga_debug.h"
 #include "svga_state.h"
 
+DEBUG_GET_ONCE_BOOL_OPTION(no_swtnl, "SVGA_NO_SWTNL", FALSE)
+DEBUG_GET_ONCE_BOOL_OPTION(force_swtnl, "SVGA_FORCE_SWTNL", FALSE);
+DEBUG_GET_ONCE_BOOL_OPTION(use_min_mipmap, "SVGA_USE_MIN_MIPMAP", FALSE);
+DEBUG_GET_ONCE_NUM_OPTION(disable_shader, "SVGA_DISABLE_SHADER", ~0);
+DEBUG_GET_ONCE_BOOL_OPTION(no_line_width, "SVGA_NO_LINE_WIDTH", FALSE);
+DEBUG_GET_ONCE_BOOL_OPTION(force_hw_line_stipple, "SVGA_FORCE_HW_LINE_STIPPLE", FALSE);
 
 static void svga_destroy( struct pipe_context *pipe )
 {
@@ -113,13 +120,12 @@ struct pipe_context *svga_context_create( struct pipe_screen *screen,
 
 
    /* debug */
-   svga->debug.no_swtnl = debug_get_bool_option("SVGA_NO_SWTNL", FALSE);
-   svga->debug.force_swtnl = debug_get_bool_option("SVGA_FORCE_SWTNL", FALSE);
-   svga->debug.use_min_mipmap = debug_get_bool_option("SVGA_USE_MIN_MIPMAP", FALSE);
-   svga->debug.disable_shader = debug_get_num_option("SVGA_DISABLE_SHADER", ~0);
-
-   if (!svga_init_swtnl(svga))
-      goto no_swtnl;
+   svga->debug.no_swtnl = debug_get_option_no_swtnl();
+   svga->debug.force_swtnl = debug_get_option_force_swtnl();
+   svga->debug.use_min_mipmap = debug_get_option_use_min_mipmap();
+   svga->debug.disable_shader = debug_get_option_disable_shader();
+   svga->debug.no_line_width = debug_get_option_no_line_width();
+   svga->debug.force_hw_line_stipple = debug_get_option_force_hw_line_stipple();
 
    svga->fs_bm = util_bitmask_create();
    if (svga->fs_bm == NULL)
@@ -149,6 +155,8 @@ struct pipe_context *svga_context_create( struct pipe_screen *screen,
    if (svga->hwtnl == NULL)
       goto no_hwtnl;
 
+   if (!svga_init_swtnl(svga))
+      goto no_swtnl;
 
    ret = svga_emit_initial_state( svga );
    if (ret)
@@ -171,6 +179,8 @@ struct pipe_context *svga_context_create( struct pipe_screen *screen,
    return &svga->pipe;
 
 no_state:
+   svga_destroy_swtnl(svga);
+no_swtnl:
    svga_hwtnl_destroy( svga->hwtnl );
 no_hwtnl:
    u_upload_destroy( svga->upload_vb );
@@ -181,8 +191,6 @@ no_upload_ib:
 no_vs_bm:
    util_bitmask_destroy( svga->fs_bm );
 no_fs_bm:
-   svga_destroy_swtnl(svga);
-no_swtnl:
    svga->swc->destroy(svga->swc);
 no_swc:
    FREE(svga);
@@ -196,14 +204,10 @@ void svga_context_flush( struct svga_context *svga,
 {
    struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
    struct pipe_fence_handle *fence = NULL;
+   enum pipe_error ret;
 
    svga->curr.nr_fbs = 0;
 
-   /* Unmap upload manager buffers: 
-    */
-   u_upload_flush(svga->upload_vb);
-   u_upload_flush(svga->upload_ib);
-
    /* Ensure that texture dma uploads are processed
     * before submitting commands.
     */
@@ -220,6 +224,21 @@ void svga_context_flush( struct svga_context *svga,
     */
    svga->dirty |= SVGA_NEW_COMMAND_BUFFER;
 
+   /*
+    * We must reemit the surface bindings here, because svga_update_state
+    * will always flush the primitives before processing the
+    * SVGA_NEW_COMMAND_BUFFER state change.
+    *
+    * TODO: Refactor this.
+    */
+   ret = svga_reemit_framebuffer_bindings(svga);
+   assert(ret == PIPE_OK);
+
+   ret = svga_reemit_tss_bindings(svga);
+   assert(ret == PIPE_OK);
+
+   svga->dirty &= ~SVGA_NEW_COMMAND_BUFFER;
+
    if (SVGA_DEBUG & DEBUG_SYNC) {
       if (fence)
          svga->pipe.screen->fence_finish( svga->pipe.screen, fence, 0);
@@ -245,6 +264,30 @@ void svga_hwtnl_flush_retry( struct svga_context *svga )
    assert(ret == 0);
 }
 
+
+/* Emit all operations pending on host surfaces.
+ */ 
+void svga_surfaces_flush(struct svga_context *svga)
+{
+   unsigned i;
+
+   /* Emit buffered drawing commands.
+    */
+   svga_hwtnl_flush_retry( svga );
+
+   /* Emit back-copy from render target view to texture.
+    */
+   for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
+      if (svga->curr.framebuffer.cbufs[i])
+         svga_propagate_surface(svga, svga->curr.framebuffer.cbufs[i]);
+   }
+
+   if (svga->curr.framebuffer.zsbuf)
+      svga_propagate_surface(svga, svga->curr.framebuffer.zsbuf);
+
+}
+
+
 struct svga_winsys_context *
 svga_winsys_context( struct pipe_context *pipe )
 {
index d4970908b1e97e0a070f8e366a05d0191c199762..7b36a3606e06c23e3db4dac13151bd7c1f961637 100644 (file)
@@ -35,6 +35,8 @@
 
 #include "tgsi/tgsi_scan.h"
 
+#include "svga_state.h"
+
 
 #define SVGA_TEX_UNITS 8
 #define SVGA_MAX_POINTSIZE 80.0
@@ -147,7 +149,14 @@ struct svga_rasterizer_state {
    float pointsize;
    
    unsigned hw_unfilled:16;         /* PIPE_POLYGON_MODE_x */
-   unsigned need_pipeline:16;    /* which prims do we need help for? */
+
+   /** Which prims do we need help for?  Bitmask of (1 << PIPE_PRIM_x) flags */
+   unsigned need_pipeline:16;
+
+   /** For debugging: */
+   const char* need_pipeline_tris_str;
+   const char* need_pipeline_lines_str;
+   const char* need_pipeline_points_str;
 };
 
 struct svga_sampler_state {
@@ -237,7 +246,7 @@ struct svga_prescale {
 };
 
 
-/* Updated by calling svga_update_state( SVGA_STATE_HW_VIEWPORT )
+/* Updated by calling svga_update_state( SVGA_STATE_HW_CLEAR )
  */
 struct svga_hw_clear_state
 {
@@ -317,6 +326,9 @@ struct svga_context
       unsigned shader_id;
 
       unsigned disable_shader;
+
+      boolean no_line_width;
+      boolean force_hw_line_stipple;
    } debug;
 
    struct {
@@ -332,7 +344,7 @@ struct svga_context
    struct util_bitmask *vs_bm;
 
    struct {
-      unsigned dirty[4];
+      unsigned dirty[SVGA_STATE_MAX];
 
       unsigned texture_timestamp;
 
@@ -355,6 +367,9 @@ struct svga_context
 
    /** List of buffers with queued transfers */
    struct list_head dirty_buffers;
+
+   /** Was the previous draw done with the SW path? */
+   boolean prev_draw_swtnl;
 };
 
 /* A flag for each state_tracker state object:
@@ -438,6 +453,8 @@ void svga_context_flush( struct svga_context *svga,
 
 void svga_hwtnl_flush_retry( struct svga_context *svga );
 
+void svga_surfaces_flush(struct svga_context *svga);
+
 struct pipe_context *
 svga_context_create(struct pipe_screen *screen,
                    void *priv);
index 97cbac447d6ba506667de84c1f950fb8374d0d8f..2c873a0f7ac276fc65ccb80c0c12df6ef20fecb2 100644 (file)
@@ -28,6 +28,7 @@
 #include "pipe/p_defines.h"
 #include "util/u_memory.h"
 #include "util/u_math.h"
+#include "util/u_upload_mgr.h"
 
 #include "svga_context.h"
 #include "svga_draw.h"
@@ -143,6 +144,9 @@ svga_hwtnl_flush( struct svga_hwtnl *hwtnl )
       SVGA3dPrimitiveRange *prim;
       unsigned i;
 
+      /* Unmap upload manager vertex buffers */
+      u_upload_flush(svga->upload_vb);
+
       for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
          handle = svga_buffer_handle(svga, hwtnl->cmd.vdecl_vb[i]);
          if (handle == NULL)
@@ -151,6 +155,9 @@ svga_hwtnl_flush( struct svga_hwtnl *hwtnl )
          vb_handle[i] = handle;
       }
 
+      /* Unmap upload manager index buffers */
+      u_upload_flush(svga->upload_ib);
+
       for (i = 0; i < hwtnl->cmd.prim_count; i++) {
          if (hwtnl->cmd.prim_ib[i]) {
             handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i]);
index be0e7abe21b4187f5a94499cfcb6b3ecbc8f7ce5..a6518042eb9d76e5487e910440f34e101059d2d5 100644 (file)
@@ -53,6 +53,7 @@ static enum pipe_error generate_indices( struct svga_hwtnl *hwtnl,
 
    dst = pipe_buffer_create( pipe->screen, 
                             PIPE_BIND_INDEX_BUFFER, 
+                            PIPE_USAGE_STATIC,
                             size );
    if (dst == NULL)
       goto fail;
index 83527c6ef496ce4d04084adf8ce7f50152251a3a..7d420c6b2954bbf1b9a7e4e1ed969901fcbf4b71 100644 (file)
@@ -56,6 +56,7 @@ translate_indices( struct svga_hwtnl *hwtnl,
 
    dst = pipe_buffer_create( pipe->screen, 
                             PIPE_BIND_INDEX_BUFFER, 
+                            PIPE_USAGE_STATIC,
                             size );
    if (dst == NULL)
       goto fail;
index 426698806c8b181ef73d000d91f1e7288ebd6f06..c87afb6946c9f2161fae8be21d0b9b1b71865ec7 100644 (file)
@@ -50,7 +50,9 @@ static void svga_surface_copy(struct pipe_context *pipe,
    struct pipe_surface *srcsurf, *dstsurf;*/
    unsigned dst_face, dst_z, src_face, src_z;
 
-   svga_hwtnl_flush_retry( svga );
+   /* Emit buffered drawing commands, and any back copies.
+    */
+   svga_surfaces_flush( svga );
 
 #if 0
    srcsurf = screen->get_tex_surface(screen, src_tex,
index 001ec3616c4017d1e92fb74ffff6cbd94d323c10..d98b9b0e0005bd8b0b53c419dd557a2de4823dc9 100644 (file)
@@ -157,6 +157,14 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
    if (!u_trim_pipe_prim( info->mode, &count ))
       return;
 
+   if (svga->state.sw.need_swtnl != svga->prev_draw_swtnl) {
+      /* We're switching between SW and HW drawing.  Do a flush to avoid
+       * mixing HW and SW rendering with the same vertex buffer.
+       */
+      pipe->flush(pipe, ~0, NULL);
+      svga->prev_draw_swtnl = svga->state.sw.need_swtnl;
+   }
+
    /*
     * Mark currently bound target surfaces as dirty
     * doesn't really matter if it is done before drawing.
index ab243aa6ec59160a4d399d83610efecd99d64090..9357d827f289805054398421ec1ad09e8e10044a 100644 (file)
@@ -24,6 +24,7 @@
  **********************************************************/
 
 #include "pipe/p_defines.h"
+#include "util/u_string.h"
 #include "svga_screen.h"
 #include "svga_surface.h"
 #include "svga_context.h"
@@ -35,20 +36,10 @@ static void svga_flush( struct pipe_context *pipe,
                         struct pipe_fence_handle **fence )
 {
    struct svga_context *svga = svga_context(pipe);
-   int i;
 
-   /* Emit buffered drawing commands.
+   /* Emit buffered drawing commands, and any back copies.
     */
-   svga_hwtnl_flush_retry( svga );
-
-   /* Emit back-copy from render target view to texture.
-    */
-   for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
-      if (svga->curr.framebuffer.cbufs[i])
-         svga_propagate_surface(pipe, svga->curr.framebuffer.cbufs[i]);
-   }
-   if (svga->curr.framebuffer.zsbuf)
-      svga_propagate_surface(pipe, svga->curr.framebuffer.zsbuf);
+   svga_surfaces_flush( svga );
 
    /* Flush command queue.
     */
@@ -56,6 +47,28 @@ static void svga_flush( struct pipe_context *pipe,
 
    SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "%s flags %x fence_ptr %p\n",
             __FUNCTION__, flags, fence ? *fence : 0x0);
+
+   /* Enable to dump BMPs of the color/depth buffers each frame */
+   if (0) {
+      if (flags & PIPE_FLUSH_FRAME) {
+         struct pipe_framebuffer_state *fb = &svga->curr.framebuffer;
+         static unsigned frame_no = 1;
+         char filename[256];
+         unsigned i;
+
+         for (i = 0; i < fb->nr_cbufs; i++) {
+            util_snprintf(filename, sizeof(filename), "cbuf%u_%04u", i, frame_no);
+            debug_dump_surface_bmp(&svga->pipe, filename, fb->cbufs[i]);
+         }
+
+         if (0 && fb->zsbuf) {
+            util_snprintf(filename, sizeof(filename), "zsbuf_%04u", frame_no);
+            debug_dump_surface_bmp(&svga->pipe, filename, fb->zsbuf);
+         }
+
+         ++frame_no;
+      }
+   }
 }
 
 
index 8c24fb302f7d4d11eec491a5531c1499437b88d3..440919c6262ee2fd403eabec1603874af7aeccc2 100644 (file)
@@ -94,7 +94,7 @@ static void svga_set_framebuffer_state(struct pipe_context *pipe,
    
       for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
          if (dst->cbufs[i] && dst->cbufs[i] != fb->cbufs[i])
-            svga_propagate_surface(pipe, dst->cbufs[i]);
+            svga_propagate_surface(svga, dst->cbufs[i]);
    }
 
    /* XXX: Actually the virtual hardware may support rendertargets with
index e97b4e57415b9ceec803ef1c6c277fcbf080da9a..4a1a37f1765972dcee81c1df9672f8da7a029c53 100644 (file)
@@ -64,7 +64,9 @@ static void *
 svga_create_rasterizer_state(struct pipe_context *pipe,
                              const struct pipe_rasterizer_state *templ)
 {
+   struct svga_context *svga = svga_context(pipe);
    struct svga_rasterizer_state *rast = CALLOC_STRUCT( svga_rasterizer_state );
+
    /* need this for draw module. */
    rast->templ = *templ;
 
@@ -75,7 +77,6 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
    /* point_quad_rasterization - ? */
    /* point_size_per_vertex  - ? */
    /* sprite_coord_mode      - ??? */
-   /* bypass_vs_viewport_and_clip        - handled by viewport setup */
    /* flatshade_first        - handled by index translation */
    /* gl_rasterization_rules - XXX - viewport code */
    /* line_width             - draw module */
@@ -93,17 +94,22 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
 
    /* Use swtnl + decomposition implement these:
     */
-   if (templ->poly_stipple_enable)
+   if (templ->poly_stipple_enable) {
       rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
+      rast->need_pipeline_tris_str = "poly stipple";
+   }
 
-   if (templ->line_width != 1.0 &&
-       templ->line_width != 0.0)
+   if (templ->line_width >= 1.5f &&
+       !svga->debug.no_line_width) {
       rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
+      rast->need_pipeline_lines_str = "line width";
+   }
 
    if (templ->line_stipple_enable) {
-      /* LinePattern not implemented on all backends. 
+      /* XXX: LinePattern not implemented on all backends, and there is no
+       * mechanism to query it.
        */
-      if (0) {
+      if (!svga->debug.force_hw_line_stipple) {
          SVGA3dLinePattern lp;
          lp.repeat = templ->line_stipple_factor + 1;
          lp.pattern = templ->line_stipple_pattern;
@@ -111,11 +117,19 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
       }
       else {
          rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
+         rast->need_pipeline_lines_str = "line stipple";
       }
    } 
 
-   if (templ->point_smooth)
+   if (templ->point_smooth) {
       rast->need_pipeline |= SVGA_PIPELINE_FLAG_POINTS;
+      rast->need_pipeline_points_str = "smooth points";
+   }
+
+   if (templ->line_smooth) {
+      rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
+      rast->need_pipeline_lines_str = "smooth lines";
+   }
 
    {
       int fill_front = templ->fill_front;
@@ -148,6 +162,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
              * front/back fill modes:
              */
             rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
+            rast->need_pipeline_tris_str = "different front/back fillmodes";
          }
          else {
             offset = offset_front;
@@ -172,6 +187,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
       {
          fill = PIPE_POLYGON_MODE_FILL;
          rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
+         rast->need_pipeline_tris_str = "unfilled primitives with no index manipulation";
       }
 
       /* If we are decomposing to lines, and lines need the pipeline,
@@ -182,6 +198,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
       {
          fill = PIPE_POLYGON_MODE_FILL;
          rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
+         rast->need_pipeline_tris_str = "decomposing lines";
       }
 
       /* Similarly for points:
@@ -191,6 +208,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
       {
          fill = PIPE_POLYGON_MODE_FILL;
          rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
+         rast->need_pipeline_tris_str = "decomposing points";
       }
 
       if (offset) {
@@ -201,9 +219,6 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
       rast->hw_unfilled = fill;
    }
 
-
-
-
    if (rast->need_pipeline & SVGA_PIPELINE_FLAG_TRIS) {
       /* Turn off stuff which will get done in the draw module:
        */
index f44a0e1325a1e9ea2b88a343c2c9acb9b9023a33..446fcc440782f5a2bae4d3ff2a5cec3701f91fb5 100644 (file)
@@ -144,8 +144,9 @@ svga_create_sampler_state(struct pipe_context *pipe,
    return cso;
 }
 
-static void svga_bind_sampler_states(struct pipe_context *pipe,
-                                     unsigned num, void **sampler)
+static void
+svga_bind_fragment_sampler_states(struct pipe_context *pipe,
+                                  unsigned num, void **sampler)
 {
    struct svga_context *svga = svga_context(pipe);
    unsigned i;
@@ -203,9 +204,10 @@ svga_sampler_view_destroy(struct pipe_context *pipe,
    FREE(view);
 }
 
-static void svga_set_sampler_views(struct pipe_context *pipe,
-                                   unsigned num,
-                                   struct pipe_sampler_view **views)
+static void
+svga_set_fragment_sampler_views(struct pipe_context *pipe,
+                                unsigned num,
+                                struct pipe_sampler_view **views)
 {
    struct svga_context *svga = svga_context(pipe);
    unsigned flag_1d = 0;
@@ -256,9 +258,9 @@ static void svga_set_sampler_views(struct pipe_context *pipe,
 void svga_init_sampler_functions( struct svga_context *svga )
 {
    svga->pipe.create_sampler_state = svga_create_sampler_state;
-   svga->pipe.bind_fragment_sampler_states = svga_bind_sampler_states;
+   svga->pipe.bind_fragment_sampler_states = svga_bind_fragment_sampler_states;
    svga->pipe.delete_sampler_state = svga_delete_sampler_state;
-   svga->pipe.set_fragment_sampler_views = svga_set_sampler_views;
+   svga->pipe.set_fragment_sampler_views = svga_set_fragment_sampler_views;
    svga->pipe.create_sampler_view = svga_create_sampler_view;
    svga->pipe.sampler_view_destroy = svga_sampler_view_destroy;
 }
index 86c79459f3e51c3c31e2d1d615da1e491c541a29..58469910732ea9970bfef84f1c223300cfce790a 100644 (file)
@@ -27,6 +27,7 @@
 #include "pipe/p_defines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
+#include "util/u_transfer.h"
 #include "tgsi/tgsi_parse.h"
 
 #include "svga_screen.h"
index ef2a0c40f03026eb2377377da7c5860dd41c9f0a..bed15ec02e53f8d128bc7916db7d9e1e1598c0f7 100644 (file)
@@ -40,6 +40,7 @@ svga_init_resource_functions(struct svga_context *svga)
    svga->pipe.transfer_unmap = u_transfer_unmap_vtbl;
    svga->pipe.transfer_destroy = u_transfer_destroy_vtbl;
    svga->pipe.transfer_inline_write = u_transfer_inline_write_vtbl;
+   svga->pipe.redefine_user_buffer = svga_redefine_user_buffer;
 }
 
 void
index f12e2b686270230b600dba255a9f04d096b869ae..e1f07d655b96f314c097878fa05cdaf7d956f508 100644 (file)
@@ -105,9 +105,12 @@ svga_buffer_map_range( struct pipe_screen *screen,
           * We can't create a hardware buffer big enough, so create a malloc
           * buffer instead.
           */
-         debug_printf("%s: failed to allocate %u KB of DMA, splitting DMA transfers\n",
-                      __FUNCTION__,
-                      (sbuf->b.b.width0 + 1023)/1024);
+         if (0) {
+            debug_printf("%s: failed to allocate %u KB of DMA, "
+                         "splitting DMA transfers\n",
+                         __FUNCTION__,
+                         (sbuf->b.b.width0 + 1023)/1024);
+         }
 
          sbuf->swbuf = align_malloc(sbuf->b.b.width0, 16);
       }
@@ -308,6 +311,9 @@ svga_buffer_create(struct pipe_screen *screen,
          goto error2;
    }
       
+   debug_reference(&sbuf->b.b.reference,
+                   (debug_reference_descriptor)debug_describe_resource, 0);
+
    return &sbuf->b.b; 
 
 error2:
@@ -341,6 +347,9 @@ svga_user_buffer_create(struct pipe_screen *screen,
 
    sbuf->swbuf = ptr;
    sbuf->user = TRUE;
+
+   debug_reference(&sbuf->b.b.reference,
+                   (debug_reference_descriptor)debug_describe_resource, 0);
    
    return &sbuf->b.b; 
 
index d3ec11bfd527af0bef7cc6678c8533b414b88ee3..c559f70ec12430f6d8452e58ed9c0d84f955374e 100644 (file)
@@ -243,4 +243,10 @@ svga_winsys_buffer_create(struct svga_context *svga,
                           unsigned usage,
                           unsigned size);
 
+void
+svga_redefine_user_buffer(struct pipe_context *ctx,
+                          struct pipe_resource *resource,
+                          unsigned offset,
+                          unsigned size);
+
 #endif /* SVGA_BUFFER_H */
index 3de5216a949324d1d4fc5b7fc66730643bc415b6..76a3803224a268ea38ce554c6cab3d95dae832d5 100644 (file)
@@ -40,6 +40,9 @@
 #include "svga_debug.h"
 
 
+#define MAX_DMA_SIZE (8 * 1024 * 1024)
+
+
 /**
  * Allocate a winsys_buffer (ie. DMA, aka GMR memory).
  *
@@ -57,6 +60,13 @@ svga_winsys_buffer_create( struct svga_context *svga,
    struct svga_winsys_screen *sws = svgascreen->sws;
    struct svga_winsys_buffer *buf;
    
+   /* XXX this shouldn't be a hard-coded number; it should be queried
+    * somehow.
+    */
+   if (size > MAX_DMA_SIZE) {
+      return NULL;
+   }
+
    /* Just try */
    buf = sws->buffer_create(sws, alignment, usage, size);
    if(!buf) {
@@ -248,6 +258,7 @@ svga_buffer_upload_flush(struct svga_context *svga,
 {
    SVGA3dCopyBox *boxes;
    unsigned i;
+   struct pipe_resource *dummy;
 
    assert(sbuf->handle); 
    assert(sbuf->hwbuf);
@@ -289,9 +300,9 @@ svga_buffer_upload_flush(struct svga_context *svga,
    sbuf->dma.svga = NULL;
    sbuf->dma.boxes = NULL;
 
-   /* Decrement reference count */
-   pipe_reference(&(sbuf->b.b.reference), NULL);
-   sbuf = NULL;
+   /* Decrement reference count (and potentially destroy) */
+   dummy = &sbuf->b.b;
+   pipe_resource_reference(&dummy, NULL);
 }
 
 
@@ -638,3 +649,54 @@ svga_context_flush_buffers(struct svga_context *svga)
       next = curr->next;
    }
 }
+
+
+void
+svga_redefine_user_buffer(struct pipe_context *pipe,
+                          struct pipe_resource *resource,
+                          unsigned offset,
+                          unsigned size)
+{
+   struct svga_screen *ss = svga_screen(pipe->screen);
+   struct svga_context *svga = svga_context(pipe);
+   struct svga_buffer *sbuf = svga_buffer(resource);
+
+   assert(sbuf->user);
+
+   /*
+    * Release any uploaded user buffer.
+    *
+    * TODO: As an optimization, we could try to update the uploaded buffer
+    * instead.
+    */
+
+   pipe_resource_reference(&sbuf->uploaded.buffer, NULL);
+
+   pipe_mutex_lock(ss->swc_mutex);
+
+   if (offset + size > resource->width0) {
+      /*
+       * User buffers shouldn't have DMA directly, unless
+       * SVGA_COMBINE_USERBUFFERS is not set.
+       */
+
+      if (sbuf->dma.pending) {
+         svga_buffer_upload_flush(svga, sbuf);
+      }
+
+      if (sbuf->handle) {
+         svga_buffer_destroy_host_surface(ss, sbuf);
+      }
+
+      if (sbuf->hwbuf) {
+         svga_buffer_destroy_hw_storage(ss, sbuf);
+      }
+
+      sbuf->key.size.width = sbuf->b.b.width0 = offset + size;
+   }
+
+   pipe_mutex_unlock(ss->swc_mutex);
+
+   svga->curr.any_user_vertex_buffers = TRUE;
+   svga->dirty |= SVGA_NEW_VBUFFER | SVGA_NEW_VELEMENT;
+}
index 7c9e600b9f441664c8776360daaaa3c89bab61e5..994f30719ae443c44e1ace385b3d145b4a7b285f 100644 (file)
@@ -146,16 +146,6 @@ svga_translate_format_render(enum pipe_format format)
    case PIPE_FORMAT_L8_UNORM:
       return svga_translate_format(format);
 
-#if 1
-   /* For on host conversion */
-   case PIPE_FORMAT_DXT1_RGB:
-      return SVGA3D_X8R8G8B8;
-   case PIPE_FORMAT_DXT1_RGBA:
-   case PIPE_FORMAT_DXT3_RGBA:
-   case PIPE_FORMAT_DXT5_RGBA:
-      return SVGA3D_A8R8G8B8;
-#endif
-
    default:
       return SVGA3D_FORMAT_INVALID;
    }
@@ -204,7 +194,7 @@ svga_transfer_dma_band(struct svga_context *svga,
 
    ret = SVGA3D_SurfaceDMA(svga->swc, st, transfer, &box, 1);
    if(ret != PIPE_OK) {
-      svga->swc->flush(svga->swc, NULL);
+      svga_context_flush(svga, NULL);
       ret = SVGA3D_SurfaceDMA(svga->swc, st, transfer, &box, 1);
       assert(ret == PIPE_OK);
    }
@@ -225,6 +215,10 @@ svga_transfer_dma(struct svga_context *svga,
       SVGA_DBG(DEBUG_PERF, "%s: readback transfer\n", __FUNCTION__);
    }
 
+   /* Ensure any pending operations on host surfaces are queued on the command
+    * buffer first.
+    */
+   svga_surfaces_flush( svga );
 
    if(!st->swbuf) {
       /* Do the DMA transfer in a single go */
@@ -390,11 +384,15 @@ svga_texture_get_transfer(struct pipe_context *pipe,
    if(st->hw_nblocksy < nblocksy) {
       /* We couldn't allocate a hardware buffer big enough for the transfer, 
        * so allocate regular malloc memory instead */
-      debug_printf("%s: failed to allocate %u KB of DMA, splitting into %u x %u KB DMA transfers\n",
-                   __FUNCTION__,
-                   (nblocksy*st->base.stride + 1023)/1024,
-                   (nblocksy + st->hw_nblocksy - 1)/st->hw_nblocksy,
-                   (st->hw_nblocksy*st->base.stride + 1023)/1024);
+      if (0) {
+         debug_printf("%s: failed to allocate %u KB of DMA, "
+                      "splitting into %u x %u KB DMA transfers\n",
+                      __FUNCTION__,
+                      (nblocksy*st->base.stride + 1023)/1024,
+                      (nblocksy + st->hw_nblocksy - 1)/st->hw_nblocksy,
+                      (st->hw_nblocksy*st->base.stride + 1023)/1024);
+      }
+
       st->swbuf = MALLOC(nblocksy*st->base.stride);
       if(!st->swbuf)
          goto no_swbuf;
@@ -527,7 +525,8 @@ svga_texture_create(struct pipe_screen *screen,
       tex->key.numFaces = 1;
    }
 
-   tex->key.cachable = 1;
+   /* XXX: Disabled for now */
+   tex->key.cachable = 0;
 
    if (template->bind & PIPE_BIND_SAMPLER_VIEW)
       tex->key.flags |= SVGA3D_SURFACE_HINT_TEXTURE;
@@ -571,6 +570,9 @@ svga_texture_create(struct pipe_screen *screen,
    if (tex->handle)
       SVGA_DBG(DEBUG_DMA, "  --> got sid %p (texture)\n", tex->handle);
 
+   debug_reference(&tex->b.b.reference,
+                   (debug_reference_descriptor)debug_describe_resource, 0);
+
    return &tex->b.b;
 
 error2:
index 6911f13f778b0e1095cc32fc427c91739a7e7f62..4f1f4b597e844e27cf3140c8164d6b2d3f4a4d3b 100644 (file)
@@ -32,6 +32,7 @@
 #include "util/u_format.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
+#include "util/u_string.h"
 
 #include "svga_screen.h"
 #include "svga_context.h"
 #include "svga_surface.h"
 
 
+void
+svga_debug_describe_sampler_view(char *buf, const struct svga_sampler_view *sv)
+{
+   char res[128];
+   debug_describe_resource(res, sv->texture);
+   util_sprintf(buf, "svga_sampler_view<%s,[%u,%u]>", res, sv->min_lod, sv->max_lod);
+}
+
 struct svga_sampler_view *
 svga_get_tex_sampler_view(struct pipe_context *pipe,
                          struct pipe_resource *pt,
                           unsigned min_lod, unsigned max_lod)
 {
-   struct svga_screen *ss = svga_screen(pt->screen);
+   struct svga_context *svga = svga_context(pipe);
+   struct svga_screen *ss = svga_screen(pipe->screen);
    struct svga_texture *tex = svga_texture(pt); 
    struct svga_sampler_view *sv = NULL;
+   SVGA3dSurfaceFlags flags = SVGA3D_SURFACE_HINT_TEXTURE;
    SVGA3dSurfaceFormat format = svga_translate_format(pt->format);
    boolean view = TRUE;
 
@@ -68,10 +79,6 @@ svga_get_tex_sampler_view(struct pipe_context *pipe,
       if (min_lod == 0 && max_lod >= pt->last_level)
          view = FALSE;
 
-      if (util_format_is_s3tc(pt->format) && view) {
-         format = svga_translate_format_render(pt->format);
-      }
-
       if (ss->debug.no_sampler_view)
          view = FALSE;
 
@@ -113,6 +120,8 @@ svga_get_tex_sampler_view(struct pipe_context *pipe,
                pt->last_level);
       sv->key.cachable = 0;
       sv->handle = tex->handle;
+      debug_reference(&sv->reference,
+                      (debug_reference_descriptor)svga_debug_describe_sampler_view, 0);
       return sv;
    }
 
@@ -126,7 +135,7 @@ svga_get_tex_sampler_view(struct pipe_context *pipe,
             pt->last_level);
 
    sv->age = tex->age;
-   sv->handle = svga_texture_view_surface(pipe, tex, format,
+   sv->handle = svga_texture_view_surface(svga, tex, flags, format,
                                           min_lod,
                                           max_lod - min_lod + 1,
                                           -1, -1,
@@ -136,6 +145,8 @@ svga_get_tex_sampler_view(struct pipe_context *pipe,
       assert(0);
       sv->key.cachable = 0;
       sv->handle = tex->handle;
+      debug_reference(&sv->reference,
+                      (debug_reference_descriptor)svga_debug_describe_sampler_view, 0);
       return sv;
    }
 
@@ -143,6 +154,9 @@ svga_get_tex_sampler_view(struct pipe_context *pipe,
    svga_sampler_view_reference(&tex->cached_view, sv);
    pipe_mutex_unlock(ss->tex_mutex);
 
+   debug_reference(&sv->reference,
+                   (debug_reference_descriptor)svga_debug_describe_sampler_view, 0);
+
    return sv;
 }
 
index e64665f2e584a8549a3cdb8bdf9386c46f5bba51..2087c1be85e87748b4de45df4a4e661d90a0174a 100644 (file)
@@ -83,12 +83,16 @@ svga_validate_sampler_view(struct svga_context *svga, struct svga_sampler_view *
 void
 svga_destroy_sampler_view_priv(struct svga_sampler_view *v);
 
+void
+svga_debug_describe_sampler_view(char *buf, const struct svga_sampler_view *sv);
+
 static INLINE void
 svga_sampler_view_reference(struct svga_sampler_view **ptr, struct svga_sampler_view *v)
 {
    struct svga_sampler_view *old = *ptr;
 
-   if (pipe_reference(&(*ptr)->reference, &v->reference))
+   if (pipe_reference_described(&(*ptr)->reference, &v->reference, 
+                                (debug_reference_descriptor)svga_debug_describe_sampler_view))
       svga_destroy_sampler_view_priv(old);
    *ptr = v;
 }
index d0f42c614c9e677728b8660b8010a4f8302dbd50..ef1d3098d51155ecdd18fe717f68e528c8c8ba5c 100644 (file)
@@ -225,13 +225,18 @@ static int svga_get_shader_param(struct pipe_screen *screen, unsigned shader, en
             return svgascreen->use_ps30 ? 32 : 12;
          return result.u;
       case PIPE_SHADER_CAP_MAX_ADDRS:
-         return svgascreen->use_ps30 ? 1 : 0;
+      case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
+        /* 
+         * Although PS 3.0 has some addressing abilities it can only represent
+         * loops that can be statically determined and unrolled. Given we can
+         * only handle a subset of the cases that the state tracker already
+         * does it is better to defer loop unrolling to the state tracker.
+         */
+         return 0;
       case PIPE_SHADER_CAP_MAX_PREDS:
          return svgascreen->use_ps30 ? 1 : 0;
       case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
          return 1;
-      case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
-         return svgascreen->use_ps30 ? 1 : 0;
       case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
       case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
       case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
@@ -360,13 +365,6 @@ svga_is_format_supported( struct pipe_screen *screen,
       case PIPE_FORMAT_B5G5R5A1_UNORM:
          return FALSE;
          
-      /* Simulate ability to render into compressed textures */
-      case PIPE_FORMAT_DXT1_RGB:
-      case PIPE_FORMAT_DXT1_RGBA:
-      case PIPE_FORMAT_DXT3_RGBA:
-      case PIPE_FORMAT_DXT5_RGBA:
-         return TRUE;
-
       default:
          break;
       }
index 22d5a6d552a71d560007d442a90c4e9e47f67c6a..7f239e7a3222d432e2d86f07ab35c8693ea64b8a 100644 (file)
@@ -92,4 +92,8 @@ void svga_update_state_retry( struct svga_context *svga,
 
 enum pipe_error svga_emit_initial_state( struct svga_context *svga );
 
+enum pipe_error svga_reemit_framebuffer_bindings( struct svga_context *svga );
+
+enum pipe_error svga_reemit_tss_bindings( struct svga_context *svga );
+
 #endif
index fcbb35e797253243fad076b461d0e2e4c85a2b84..cdadb20c178517816db701aa2fec9c49bb7d3944 100644 (file)
@@ -93,6 +93,55 @@ static int emit_framebuffer( struct svga_context *svga,
 }
 
 
+/*
+ * Rebind rendertargets.
+ *
+ * Similar to emit_framebuffer, but without any state checking/update.
+ *
+ * Called at the beginning of every new command buffer to ensure that
+ * non-dirty rendertargets are properly paged-in.
+ */
+enum pipe_error
+svga_reemit_framebuffer_bindings(struct svga_context *svga)
+{
+   struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
+   unsigned i;
+   enum pipe_error ret;
+
+   for (i = 0; i < MIN2(PIPE_MAX_COLOR_BUFS, 8); ++i) {
+      if (hw->cbufs[i]) {
+         ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_COLOR0 + i, hw->cbufs[i]);
+         if (ret != PIPE_OK) {
+            return ret;
+         }
+      }
+   }
+
+   if (hw->zsbuf) {
+      ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_DEPTH, hw->zsbuf);
+      if (ret != PIPE_OK) {
+         return ret;
+      }
+
+      if (hw->zsbuf &&
+          hw->zsbuf->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM) {
+         ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, hw->zsbuf);
+         if (ret != PIPE_OK) {
+            return ret;
+         }
+      }
+      else {
+         ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, NULL);
+         if (ret != PIPE_OK) {
+            return ret;
+         }
+      }
+   }
+
+   return PIPE_OK;
+}
+
+
 struct svga_tracked_state svga_hw_framebuffer = 
 {
    "hw framebuffer state",
index 8ba5ac8cdb4ac1b61c0430ba5c107b3d9ff59776..68c025787894240282f6732d55410b379912900a 100644 (file)
 /***********************************************************************
  */
 
+
+/**
+ * Given a gallium vertex element format, return the corresponding SVGA3D
+ * format.  Return SVGA3D_DECLTYPE_MAX for unsupported gallium formats.
+ */
 static INLINE SVGA3dDeclType 
 svga_translate_vertex_format(enum pipe_format format)
 {
@@ -80,6 +85,7 @@ static int update_need_swvfetch( struct svga_context *svga,
    for (i = 0; i < svga->curr.velems->count; i++) {
       svga->state.sw.ve_format[i] = svga_translate_vertex_format(svga->curr.velems->velem[i].src_format);
       if (svga->state.sw.ve_format[i] == SVGA3D_DECLTYPE_MAX) {
+         /* Unsupported format - use software fetch */
          need_swvfetch = TRUE;
          break;
       }
@@ -118,6 +124,11 @@ static int update_need_pipeline( struct svga_context *svga,
                  __FUNCTION__,
                  svga->curr.rast->need_pipeline,
                  (1 << svga->curr.reduced_prim) );
+      SVGA_DBG(DEBUG_SWTNL, "%s: rast need_pipeline tris (%s), lines (%s), points (%s)\n",
+                 __FUNCTION__,
+                 svga->curr.rast->need_pipeline_tris_str,
+                 svga->curr.rast->need_pipeline_lines_str,
+                 svga->curr.rast->need_pipeline_points_str);
       need_pipeline = TRUE;
    }
 
@@ -140,6 +151,10 @@ static int update_need_pipeline( struct svga_context *svga,
       svga->dirty |= SVGA_NEW_NEED_PIPELINE;
    }
 
+   /* DEBUG */
+   if (0 && svga->state.sw.need_pipeline)
+      debug_printf("sw.need_pipeline = %d\n", svga->state.sw.need_pipeline);
+
    return 0;
 }
 
@@ -164,15 +179,15 @@ static int update_need_swtnl( struct svga_context *svga,
    boolean need_swtnl;
 
    if (svga->debug.no_swtnl) {
-      svga->state.sw.need_swvfetch = 0;
-      svga->state.sw.need_pipeline = 0;
+      svga->state.sw.need_swvfetch = FALSE;
+      svga->state.sw.need_pipeline = FALSE;
    }
 
    need_swtnl = (svga->state.sw.need_swvfetch ||
                  svga->state.sw.need_pipeline);
 
    if (svga->debug.force_swtnl) {
-      need_swtnl = 1;
+      need_swtnl = TRUE;
    }
 
    /*
@@ -181,7 +196,7 @@ static int update_need_swtnl( struct svga_context *svga,
     * the wrong buffers and vertex formats. Try trivial/line-wide.
     */
    if (svga->state.sw.in_swtnl_draw)
-      need_swtnl = 1;
+      need_swtnl = TRUE;
 
    if (need_swtnl != svga->state.sw.need_swtnl) {
       SVGA_DBG(DEBUG_SWTNL|DEBUG_PERF,
index f8b269a101efd2df77ca47eb93ea2282cd4d81f4..c502506b93bd444258514cd6f98c8172f55055d5 100644 (file)
@@ -52,6 +52,16 @@ void svga_cleanup_tss_binding(struct svga_context *svga)
 }
 
 
+struct bind_queue {
+   struct {
+      unsigned unit;
+      struct svga_hw_view_state *view;
+   } bind[PIPE_MAX_SAMPLERS];
+
+   unsigned bind_count;
+};
+
+
 static int
 update_tss_binding(struct svga_context *svga, 
                    unsigned dirty )
@@ -63,15 +73,7 @@ update_tss_binding(struct svga_context *svga,
    unsigned min_lod;
    unsigned max_lod;
 
-
-   struct {
-      struct {
-         unsigned unit;
-         struct svga_hw_view_state *view;
-      } bind[PIPE_MAX_SAMPLERS];
-
-      unsigned bind_count;
-   } queue;
+   struct bind_queue queue;
 
    queue.bind_count = 0;
    
@@ -164,6 +166,64 @@ fail:
 }
 
 
+/*
+ * Rebind textures.
+ *
+ * Similar to update_tss_binding, but without any state checking/update.
+ *
+ * Called at the beginning of every new command buffer to ensure that
+ * non-dirty textures are properly paged-in.
+ */
+enum pipe_error
+svga_reemit_tss_bindings(struct svga_context *svga)
+{
+   unsigned i;
+   enum pipe_error ret;
+   struct bind_queue queue;
+
+   queue.bind_count = 0;
+
+   for (i = 0; i < svga->state.hw_draw.num_views; i++) {
+      struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
+
+      if (view->v) {
+         queue.bind[queue.bind_count].unit = i;
+         queue.bind[queue.bind_count].view = view;
+         queue.bind_count++;
+      }
+   }
+
+   if (queue.bind_count) {
+      SVGA3dTextureState *ts;
+
+      ret = SVGA3D_BeginSetTextureState(svga->swc,
+                                        &ts,
+                                        queue.bind_count);
+      if (ret != PIPE_OK) {
+         return ret;
+      }
+
+      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;
+
+         assert(queue.bind[i].view->v);
+         handle = queue.bind[i].view->v->handle;
+         svga->swc->surface_relocation(svga->swc,
+                                       &ts[i].value,
+                                       handle,
+                                       SVGA_RELOC_READ);
+      }
+
+      SVGA_FIFOCommitAll(svga->swc);
+   }
+
+   return PIPE_OK;
+}
+
+
 struct svga_tracked_state svga_hw_tss_binding = {
    "texture binding emit",
    SVGA_NEW_TEXTURE_BINDING |
index 6682a1efe66ae1aea88136b3777c1835dca5a6eb..ae9a20ebb816e113a106ae2dd7c148517a1fa0e8 100644 (file)
@@ -229,7 +229,7 @@ static int update_zero_stride( struct svga_context *svga,
 
          translate->set_buffer(translate, vel->vertex_buffer_index,
                                mapped_buffer,
-                               vbuffer->stride, vbuffer->max_index);
+                               vbuffer->stride, ~0);
          translate->run(translate, 0, 1, 0,
                         svga->curr.zero_stride_constants);
 
index 3e4bed76c052295dd00d20d25e23f4015c2cf67b..3e8fb5f02718f18486bbbb3b9168bf8a69851f45 100644 (file)
@@ -100,8 +100,9 @@ svga_texture_copy_handle(struct svga_context *svga,
 
 
 struct svga_winsys_surface *
-svga_texture_view_surface(struct pipe_context *pipe,
+svga_texture_view_surface(struct svga_context *svga,
                           struct svga_texture *tex,
+                          SVGA3dSurfaceFlags flags,
                           SVGA3dSurfaceFormat format,
                           unsigned start_mip,
                           unsigned num_mip,
@@ -109,7 +110,7 @@ svga_texture_view_surface(struct pipe_context *pipe,
                           int zslice_pick,
                           struct svga_host_surface_cache_key *key) /* OUT */
 {
-   struct svga_screen *ss = svga_screen(pipe->screen);
+   struct svga_screen *ss = svga_screen(svga->pipe.screen);
    struct svga_winsys_surface *handle;
    uint32_t i, j;
    unsigned z_offset = 0;
@@ -118,7 +119,7 @@ svga_texture_view_surface(struct pipe_context *pipe,
             "svga: Create surface view: face %d zslice %d mips %d..%d\n",
             face_pick, zslice_pick, start_mip, start_mip+num_mip-1);
 
-   key->flags = 0;
+   key->flags = flags;
    key->format = format;
    key->numMipLevels = num_mip;
    key->size.width = u_minify(tex->b.b.width0, start_mip);
@@ -161,7 +162,7 @@ svga_texture_view_surface(struct pipe_context *pipe,
                               u_minify(tex->b.b.depth0, i + start_mip) :
                               1);
 
-            svga_texture_copy_handle(svga_context(pipe),
+            svga_texture_copy_handle(svga,
                                      tex->handle, 
                                      0, 0, z_offset, 
                                      i + start_mip, 
@@ -183,6 +184,7 @@ svga_create_surface(struct pipe_context *pipe,
                     struct pipe_resource *pt,
                     const struct pipe_surface *surf_tmpl)
 {
+   struct svga_context *svga = svga_context(pipe);
    struct svga_texture *tex = svga_texture(pt);
    struct pipe_screen *screen = pipe->screen;
    struct svga_surface *s;
@@ -191,6 +193,7 @@ svga_create_surface(struct pipe_context *pipe,
    boolean render = (surf_tmpl->usage & (PIPE_BIND_RENDER_TARGET |
                                          PIPE_BIND_DEPTH_STENCIL)) ? TRUE : FALSE;
    boolean view = FALSE;
+   SVGA3dSurfaceFlags flags;
    SVGA3dSurfaceFormat format;
 
    assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
@@ -219,10 +222,18 @@ svga_create_surface(struct pipe_context *pipe,
    s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
    s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
 
-   if (!render)
+   if (!render) {
+      flags = SVGA3D_SURFACE_HINT_TEXTURE;
       format = svga_translate_format(surf_tmpl->format);
-   else
+   } else {
+      if (surf_tmpl->usage & PIPE_BIND_RENDER_TARGET) {
+         flags = SVGA3D_SURFACE_HINT_RENDERTARGET;
+      }
+      if (surf_tmpl->usage & PIPE_BIND_DEPTH_STENCIL) {
+         flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL;
+      }
       format = svga_translate_format_render(surf_tmpl->format);
+   }
 
    assert(format != SVGA3D_FORMAT_INVALID);
 
@@ -249,7 +260,8 @@ svga_create_surface(struct pipe_context *pipe,
       SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: yes %p, level %u face %u z %u, %p\n",
                pt, surf_tmpl->u.tex.level, face, zslice, s);
 
-      s->handle = svga_texture_view_surface(NULL, tex, format, surf_tmpl->u.tex.level,
+      s->handle = svga_texture_view_surface(svga, tex, flags, format,
+                                            surf_tmpl->u.tex.level,
                                            1, face, zslice, &s->key);
       s->real_face = 0;
       s->real_level = 0;
@@ -329,7 +341,7 @@ void svga_mark_surfaces_dirty(struct svga_context *svga)
  * pipe is optional context to inline the blit command in.
  */
 void
-svga_propagate_surface(struct pipe_context *pipe, struct pipe_surface *surf)
+svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf)
 {
    struct svga_surface *s = svga_surface(surf);
    struct svga_texture *tex = svga_texture(surf->texture);
@@ -354,7 +366,7 @@ svga_propagate_surface(struct pipe_context *pipe, struct pipe_surface *surf)
 
    if (s->handle != tex->handle) {
       SVGA_DBG(DEBUG_VIEWS, "svga: Surface propagate: tex %p, level %u, from %p\n", tex, surf->u.tex.level, surf);
-      svga_texture_copy_handle(svga_context(pipe),
+      svga_texture_copy_handle(svga,
                                s->handle, 0, 0, 0, s->real_level, s->real_face,
                                tex->handle, 0, 0, zslice, surf->u.tex.level, face,
                                u_minify(tex->b.b.width0, surf->u.tex.level),
index afb8326e1f38703de365dc9c32d951daf2b7d332..bffc8c22c60d946d0a9483ab8034d13941228c83 100644 (file)
@@ -56,14 +56,15 @@ struct svga_surface
 
 
 extern void
-svga_propagate_surface(struct pipe_context *pipe, struct pipe_surface *surf);
+svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf);
 
 extern boolean
 svga_surface_needs_propagation(struct pipe_surface *surf);
 
 struct svga_winsys_surface *
-svga_texture_view_surface(struct pipe_context *pipe,
+svga_texture_view_surface(struct svga_context *svga,
                           struct svga_texture *tex,
+                          SVGA3dSurfaceFlags flags,
                           SVGA3dSurfaceFormat format,
                           unsigned start_mip,
                           unsigned num_mip,
index d5db6bf641a2fbbb254336d2be147fea9afa4059..ac9d637f8cb88720eb5f90dc6798b2757aebe9de 100644 (file)
@@ -87,11 +87,14 @@ svga_vbuf_render_allocate_vertices( struct vbuf_render *render,
       svga_render->vbuf_size = MAX2(size, svga_render->vbuf_alloc_size);
       svga_render->vbuf = pipe_buffer_create(screen,
                                              PIPE_BIND_VERTEX_BUFFER,
+                                             PIPE_USAGE_STREAM,
                                              svga_render->vbuf_size);
       if(!svga_render->vbuf) {
          svga_context_flush(svga, NULL);
+         assert(!svga_render->vbuf);
          svga_render->vbuf = pipe_buffer_create(screen,
                                                 PIPE_BIND_VERTEX_BUFFER,
+                                                PIPE_USAGE_STREAM,
                                                 svga_render->vbuf_size);
          assert(svga_render->vbuf);
       }
@@ -261,6 +264,7 @@ svga_vbuf_render_draw_elements( struct vbuf_render *render,
       svga_render->ibuf_size = MAX2(size, svga_render->ibuf_alloc_size);
       svga_render->ibuf = pipe_buffer_create(screen,
                                              PIPE_BIND_INDEX_BUFFER,
+                                             PIPE_USAGE_STREAM,
                                              svga_render->ibuf_size);
       svga_render->ibuf_offset = 0;
    }
index 05d86e1fb16ca85a351e46283b1f1b8e857d09d1..ad29c1b6425232aa6910627b06f1848c9567b2ae 100644 (file)
@@ -124,6 +124,7 @@ svga_swtnl_draw_vbo(struct svga_context *svga,
 
    /* Now safe to remove the need_swtnl flag in any update_state call */
    svga->state.sw.in_swtnl_draw = FALSE;
+   svga->dirty |= SVGA_NEW_NEED_PIPELINE | SVGA_NEW_NEED_SWVFETCH;
 
    return ret;
 }
index a75923829364190c4a1c8f2812c3c442c2e39078..efda2f605b93fa1c68b96cdbe145a4565fa8d31e 100644 (file)
@@ -61,7 +61,7 @@ static void set_draw_viewport( struct svga_context *svga )
        * going to be drawn with triangles, but we're not catching all
        * cases where that will happen.
        */
-      if (svga->curr.rast->templ.line_width > 1.0) 
+      if (svga->curr.rast->need_pipeline & SVGA_PIPELINE_FLAG_LINES)
       {
          adjx = SVGA_LINE_ADJ_X + 0.175;
          adjy = SVGA_LINE_ADJ_Y - 0.175;
index f2591c5721a26b8ef5c33ad27cf26087c9aeffd0..99600cf5c0066f321ffc4f042f408f8a7bc4f220 100644 (file)
@@ -57,7 +57,6 @@ translate_opcode(
    case TGSI_OPCODE_MUL:        return SVGA3DOP_MUL;
    case TGSI_OPCODE_NOP:        return SVGA3DOP_NOP;
    case TGSI_OPCODE_NRM4:       return SVGA3DOP_NRM;
-   case TGSI_OPCODE_SSG:        return SVGA3DOP_SGN;
    default:
       debug_printf("Unkown opcode %u\n", opcode);
       assert( 0 );
@@ -285,6 +284,41 @@ static void reset_temp_regs( struct svga_shader_emitter *emit )
 }
    
 
+/* Replace the src with the temporary specified in the dst, but copying
+ * only the necessary channels, and preserving the original swizzle (which is
+ * important given that several opcodes have constraints in the allowed
+ * swizzles).
+ */
+static boolean emit_repl( struct svga_shader_emitter *emit,
+                          SVGA3dShaderDestToken dst,
+                          struct src_register *src0)
+{
+   unsigned src0_swizzle;
+   unsigned chan;
+
+   assert(SVGA3dShaderGetRegType(dst.value) == SVGA3DREG_TEMP);
+
+   src0_swizzle = src0->base.swizzle;
+
+   dst.mask = 0;
+   for (chan = 0; chan < 4; ++chan) {
+      unsigned swizzle = (src0_swizzle >> (chan *2)) & 0x3;
+      dst.mask |= 1 << swizzle;
+   }
+   assert(dst.mask);
+
+   src0->base.swizzle = SVGA3DSWIZZLE_NONE;
+
+   if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), dst, *src0 ))
+      return FALSE;
+
+   *src0 = src( dst );
+   src0->base.swizzle = src0_swizzle;
+
+   return TRUE;
+}
+
+
 static boolean submit_op0( struct svga_shader_emitter *emit,
                            SVGA3dShaderInstToken inst,
                            SVGA3dShaderDestToken dest )
@@ -333,14 +367,11 @@ static boolean submit_op2( struct svga_shader_emitter *emit,
        src0.base.num != src1.base.num)
       need_temp = TRUE;
 
-   if (need_temp)
-   {
+   if (need_temp) {
       temp = get_temp( emit );
 
-      if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp, src0 ))
+      if (!emit_repl( emit, temp, &src0 ))
          return FALSE;
-
-      src0 = src( temp );
    }
 
    if (!emit_op2( emit, inst, dest, src0, src1 ))
@@ -396,24 +427,18 @@ static boolean submit_op3( struct svga_shader_emitter *emit,
        (type2 == SVGA3DREG_INPUT && src1.base.num != src2.base.num))
       need_temp1 = TRUE;
 
-   if (need_temp0)
-   {
+   if (need_temp0) {
       temp0 = get_temp( emit );
  
-      if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp0, src0 ))
+      if (!emit_repl( emit, temp0, &src0 ))
          return FALSE;
-         
-      src0 = src( temp0 );
    }
 
-   if (need_temp1)
-   {
+   if (need_temp1) {
       temp1 = get_temp( emit );
 
-      if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp1, src1 ))
+      if (!emit_repl( emit, temp1, &src1 ))
          return FALSE;
-
-      src1 = src( temp1 );
    }
 
    if (!emit_op3( emit, inst, dest, src0, src1, src2 ))
@@ -478,24 +503,18 @@ static boolean submit_op4( struct svga_shader_emitter *emit,
        (type2 == SVGA3DREG_INPUT && src3.base.num != src2.base.num))
       need_temp3 = TRUE;
 
-   if (need_temp0)
-   {
+   if (need_temp0) {
       temp0 = get_temp( emit );
  
-      if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp0, src0 ))
+      if (!emit_repl( emit, temp0, &src0 ))
          return FALSE;
-         
-      src0 = src( temp0 );
    }
 
-   if (need_temp3)
-   {
+   if (need_temp3) {
       temp3 = get_temp( emit );
 
-      if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp3, src3 ))
+      if (!emit_repl( emit, temp3, &src3 ))
          return FALSE;
-
-      src3 = src( temp3 );
    }
 
    if (!emit_op4( emit, inst, dest, src0, src1, src2, src3 ))
@@ -509,6 +528,55 @@ static boolean submit_op4( struct svga_shader_emitter *emit,
 }
 
 
+static boolean alias_src_dst( struct src_register src,
+                              SVGA3dShaderDestToken dst )
+{
+   if (src.base.num != dst.num)
+      return FALSE;
+
+   if (SVGA3dShaderGetRegType(dst.value) !=
+       SVGA3dShaderGetRegType(src.base.value))
+      return FALSE;
+
+   return TRUE;
+}
+
+
+static boolean submit_lrp(struct svga_shader_emitter *emit,
+                          SVGA3dShaderDestToken dst,
+                          struct src_register src0,
+                          struct src_register src1,
+                          struct src_register src2)
+{
+   SVGA3dShaderDestToken tmp;
+   boolean need_dst_tmp = FALSE;
+
+   /* The dst reg must be a temporary, and not be the same as src0 or src2 */
+   if (SVGA3dShaderGetRegType(dst.value) != SVGA3DREG_TEMP ||
+       alias_src_dst(src0, dst) ||
+       alias_src_dst(src2, dst))
+      need_dst_tmp = TRUE;
+
+   if (need_dst_tmp) {
+      tmp = get_temp( emit );
+      tmp.mask = dst.mask;
+   }
+   else {
+      tmp = dst;
+   }
+
+   if (!submit_op3(emit, inst_token( SVGA3DOP_LRP ), tmp, src0, src1, src2))
+      return FALSE;
+
+   if (need_dst_tmp) {
+      if (!submit_op1(emit, inst_token( SVGA3DOP_MOV ), dst, src( tmp )))
+         return FALSE;
+   }
+
+   return TRUE;
+}
+
+
 static boolean emit_def_const( struct svga_shader_emitter *emit,
                                SVGA3dShaderConstType type,
                                unsigned idx,
@@ -747,7 +815,7 @@ static boolean emit_fake_arl(struct svga_shader_emitter *emit,
 static boolean emit_if(struct svga_shader_emitter *emit,
                        const struct tgsi_full_instruction *insn)
 {
-   const struct src_register src = translate_src_register(
+   struct src_register src0 = translate_src_register(
       emit, &insn->Src[0] );
    struct src_register zero = get_zero_immediate( emit );
    SVGA3dShaderInstToken if_token = inst_token( SVGA3DOP_IFC );
@@ -755,10 +823,23 @@ static boolean emit_if(struct svga_shader_emitter *emit,
    if_token.control = SVGA3DOPCOMPC_NE;
    zero = scalar(zero, TGSI_SWIZZLE_X);
 
+   if (SVGA3dShaderGetRegType(src0.base.value) == SVGA3DREG_CONST) {
+      /*
+       * Max different constant registers readable per IFC instruction is 1.
+       */
+
+      SVGA3dShaderDestToken tmp = get_temp( emit );
+
+      if (!submit_op1(emit, inst_token( SVGA3DOP_MOV ), tmp, src0))
+         return FALSE;
+
+      src0 = scalar(src( tmp ), TGSI_SWIZZLE_X);
+   }
+
    emit->dynamic_branching_level++;
 
    return (emit_instruction( emit, if_token ) &&
-           emit_src( emit, src ) &&
+           emit_src( emit, src0 ) &&
            emit_src( emit, zero ) );
 }
 
@@ -832,7 +913,7 @@ static boolean emit_cmp(struct svga_shader_emitter *emit,
        */
       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);
+      return submit_lrp(emit, dst, src(temp), src1, src2);
    }
 
    /* CMP  DST, SRC0, SRC2, SRC1 */
@@ -1066,6 +1147,41 @@ static boolean emit_cos(struct svga_shader_emitter *emit,
    return TRUE;
 }
 
+static boolean emit_ssg(struct svga_shader_emitter *emit,
+                        const struct tgsi_full_instruction *insn )
+{
+   SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
+   struct src_register src0 = translate_src_register(
+      emit, &insn->Src[0] );
+   SVGA3dShaderDestToken temp0 = get_temp( emit );
+   SVGA3dShaderDestToken temp1 = get_temp( emit );
+   struct src_register zero, one;
+
+   if (emit->unit == PIPE_SHADER_VERTEX) {
+      /* SGN  DST, SRC0, TMP0, TMP1 */
+      return submit_op3( emit, inst_token( SVGA3DOP_SGN ), dst, src0,
+                         src( temp0 ), src( temp1 ) );
+   }
+
+   zero = get_zero_immediate( emit );
+   one = scalar( zero, TGSI_SWIZZLE_W );
+   zero = scalar( zero, TGSI_SWIZZLE_X );
+
+   /* CMP  TMP0, SRC0, one, zero */
+   if (!submit_op3( emit, inst_token( SVGA3DOP_CMP ),
+                    writemask( temp0, dst.mask ), src0, one, zero ))
+      return FALSE;
+
+   /* CMP  TMP1, negate(SRC0), negate(one), zero */
+   if (!submit_op3( emit, inst_token( SVGA3DOP_CMP ),
+                    writemask( temp1, dst.mask ), negate( src0 ), negate( one ),
+                    zero ))
+      return FALSE;
+
+   /* ADD  DST, TMP0, TMP1 */
+   return submit_op2( emit, inst_token( SVGA3DOP_ADD ), dst, src( temp0 ),
+                      src( temp1 ) );
+}
 
 /*
  * ADD DST SRC0, negate(SRC0)
@@ -1588,6 +1704,10 @@ static boolean emit_deriv(struct svga_shader_emitter *emit,
    }
    else {
       unsigned opcode;
+      const struct tgsi_full_src_register *reg = &insn->Src[0];
+      SVGA3dShaderInstToken inst;
+      SVGA3dShaderDestToken dst;
+      struct src_register src0;
 
       switch (insn->Instruction.Opcode) {
       case TGSI_OPCODE_DDX:
@@ -1600,7 +1720,21 @@ static boolean emit_deriv(struct svga_shader_emitter *emit,
          return FALSE;
       }
 
-      return emit_simple_instruction( emit, opcode, insn );
+      inst = inst_token( opcode );
+      dst = translate_dst_register( emit, insn, 0 );
+      src0 = translate_src_register( emit, reg );
+
+      /* We cannot use negate or abs on source to dsx/dsy instruction.
+       */
+      if (reg->Register.Absolute ||
+          reg->Register.Negate) {
+         SVGA3dShaderDestToken temp = get_temp( emit );
+
+         if (!emit_repl( emit, temp, &src0 ))
+            return FALSE;
+      }
+
+      return submit_op1( emit, inst, dst, src0 );
    }
 }
 
@@ -1624,19 +1758,6 @@ static boolean emit_arl(struct svga_shader_emitter *emit,
    }
 }
 
-static boolean alias_src_dst( struct src_register src,
-                              SVGA3dShaderDestToken dst )
-{
-   if (src.base.num != dst.num)
-      return FALSE;
-
-   if (SVGA3dShaderGetRegType(dst.value) != 
-       SVGA3dShaderGetRegType(src.base.value))
-      return FALSE;
-
-   return TRUE;
-}
-
 static boolean emit_pow(struct svga_shader_emitter *emit,
                         const struct tgsi_full_instruction *insn)
 {
@@ -1729,37 +1850,14 @@ static boolean emit_lrp(struct svga_shader_emitter *emit,
                         const struct tgsi_full_instruction *insn)
 {
    SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 );
-   SVGA3dShaderDestToken tmp;
    const struct src_register src0 = translate_src_register(
       emit, &insn->Src[0] );
    const struct src_register src1 = translate_src_register(
       emit, &insn->Src[1] );
    const struct src_register src2 = translate_src_register(
       emit, &insn->Src[2] );
-   boolean need_dst_tmp = FALSE;
-
-   /* The dst reg must not be the same as src0 or src2 */
-   if (alias_src_dst(src0, dst) ||
-       alias_src_dst(src2, dst))
-      need_dst_tmp = TRUE;
 
-   if (need_dst_tmp) {
-      tmp = get_temp( emit );
-      tmp.mask = dst.mask;
-   }
-   else {
-      tmp = dst;
-   }
-
-   if (!submit_op3(emit, inst_token( SVGA3DOP_LRP ), tmp, src0, src1, src2))
-      return FALSE;
-
-   if (need_dst_tmp) {
-      if (!submit_op1(emit, inst_token( SVGA3DOP_MOV ), dst, src( tmp )))
-         return FALSE;      
-   } 
-
-   return TRUE;
+   return submit_lrp(emit, dst, src0, src1, src2);
 }
 
 
@@ -2366,6 +2464,9 @@ static boolean svga_emit_instruction( struct svga_shader_emitter *emit,
    case TGSI_OPCODE_LRP:
       return emit_lrp( emit, insn );
 
+   case TGSI_OPCODE_SSG:
+      return emit_ssg( emit, insn );
+
    default: {
       unsigned opcode = translate_opcode(insn->Instruction.Opcode);
 
@@ -2715,6 +2816,7 @@ needs_to_create_zero( struct svga_shader_emitter *emit )
          return TRUE;
 
       if (emit->info.opcode_count[TGSI_OPCODE_DST] >= 1 ||
+          emit->info.opcode_count[TGSI_OPCODE_SSG] >= 1 ||
           emit->info.opcode_count[TGSI_OPCODE_LIT] >= 1)
          return TRUE;
    }
index 95612a8006306665a5784637b475d22e40d2abfa..ad1549d9f81fc1e7cc7e6e7a385bd306c6b0510b 100644 (file)
@@ -136,7 +136,7 @@ static struct sh_opcode_info opcode_info[] =
    { "dsy",          1, 1, 0, 0, SVGA3DOP_INVALID,     },
    { "texldd",       1, 4, 0, 0, SVGA3DOP_INVALID,     },
    { "setp",         1, 2, 0, 0, SVGA3DOP_SETP,        },
-   { "texldl",       1, 2, 0, 0, SVGA3DOP_INVALID,     },
+   { "texldl",       1, 2, 0, 0, SVGA3DOP_TEXLDL,      },
    { "breakp",       0, 1, 0, 0, SVGA3DOP_INVALID,     },
 };
 
@@ -156,6 +156,8 @@ const struct sh_opcode_info *svga_opcode_info( uint op )
    if (info->svga_opcode == SVGA3DOP_INVALID) {
       /* No valid information. Please provide number of dst/src registers.
        */
+      _debug_printf("Missing information for opcode %u, '%s'\n", op,
+                    opcode_info[op].mnemonic);
       assert( 0 );
       return NULL;
    }
index eaabae8ce422137eb4564fc9d6a1035cd9ad3557..d24cc623c2ee26c82a4061c3596e7e8fbab99969 100644 (file)
@@ -1419,6 +1419,28 @@ trace_context_transfer_inline_write(struct pipe_context *_context,
 }
 
 
+static void trace_redefine_user_buffer(struct pipe_context *_context,
+                                       struct pipe_resource *_resource,
+                                       unsigned offset, unsigned size)
+{
+   struct trace_context *tr_context = trace_context(_context);
+   struct trace_resource *tr_tex = trace_resource(_resource);
+   struct pipe_context *context = tr_context->pipe;
+   struct pipe_resource *resource = tr_tex->resource;
+
+   assert(resource->screen == context->screen);
+
+   trace_dump_call_begin("pipe_context", "redefine_user_buffer");
+
+   trace_dump_arg(ptr, context);
+   trace_dump_arg(ptr, resource);
+   trace_dump_arg(uint, offset);
+   trace_dump_arg(uint, size);
+
+   trace_dump_call_end();
+
+   context->redefine_user_buffer(context, resource, offset, size);
+}
 
 
 static const struct debug_named_value rbug_blocker_flags[] = {
@@ -1506,6 +1528,7 @@ trace_context_create(struct trace_screen *tr_scr,
    tr_ctx->base.transfer_unmap = trace_context_transfer_unmap;
    tr_ctx->base.transfer_flush_region = trace_context_transfer_flush_region;
    tr_ctx->base.transfer_inline_write = trace_context_transfer_inline_write;
+   tr_ctx->base.redefine_user_buffer = trace_redefine_user_buffer;
 
    tr_ctx->pipe = pipe;
 
index 155c869fbd95652725ec7e5868025b3bf9e4649d..18805655bd77b56a59236a0e1076949713011d44 100644 (file)
@@ -517,7 +517,6 @@ void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state)
    trace_dump_struct_begin("pipe_vertex_buffer");
 
    trace_dump_member(uint, state, stride);
-   trace_dump_member(uint, state, max_index);
    trace_dump_member(uint, state, buffer_offset);
    trace_dump_member(resource_ptr, state, buffer);
 
index 589cac2ddd3b85da1621fed21168a49ded05f01f..24ee3fe117535a2a08013e38852ba1fef7532263 100644 (file)
@@ -399,6 +399,14 @@ struct pipe_context {
                                   unsigned stride,
                                   unsigned layer_stride);
 
+
+   /* Notify a driver that a content of a user buffer has been changed.
+    * The changed range is [offset, offset+size-1].
+    * The new width0 of the buffer is offset+size. */
+   void (*redefine_user_buffer)(struct pipe_context *,
+                                struct pipe_resource *,
+                                unsigned offset,
+                                unsigned size);
 };
 
 
index a7f8503251b529a90ef14556ed677df433d1bdea..8cf738fa2c081bc76068c9696a42e224eaa6508c 100644 (file)
@@ -225,13 +225,13 @@ enum pipe_transfer_usage {
    /**
     * Discards the memory within the mapped region.
     *
-    * It should not be used with PIPE_TRANSFER_CPU_READ.
+    * It should not be used with PIPE_TRANSFER_READ.
     *
     * See also:
     * - OpenGL's ARB_map_buffer_range extension, MAP_INVALIDATE_RANGE_BIT flag.
-    * - Direct3D's D3DLOCK_DISCARD flag.
     */
-   PIPE_TRANSFER_DISCARD = (1 << 8),
+   PIPE_TRANSFER_DISCARD = (1 << 8), /* DEPRECATED */
+   PIPE_TRANSFER_DISCARD_RANGE = (1 << 8),
 
    /**
     * Fail if the resource cannot be mapped immediately.
@@ -246,7 +246,7 @@ enum pipe_transfer_usage {
    /**
     * Do not attempt to synchronize pending operations on the resource when mapping.
     *
-    * It should not be used with PIPE_TRANSFER_CPU_READ.
+    * It should not be used with PIPE_TRANSFER_READ.
     *
     * See also:
     * - OpenGL's ARB_map_buffer_range extension, MAP_UNSYNCHRONIZED_BIT flag.
@@ -260,13 +260,28 @@ enum pipe_transfer_usage {
     * Written ranges will be notified later with
     * pipe_context::transfer_flush_region.
     *
-    * It should not be used with PIPE_TRANSFER_CPU_READ.
+    * It should not be used with PIPE_TRANSFER_READ.
     *
     * See also:
     * - pipe_context::transfer_flush_region
     * - OpenGL's ARB_map_buffer_range extension, MAP_FLUSH_EXPLICIT_BIT flag.
     */
-   PIPE_TRANSFER_FLUSH_EXPLICIT = (1 << 11)
+   PIPE_TRANSFER_FLUSH_EXPLICIT = (1 << 11),
+
+   /**
+    * Discards all memory backing the resource.
+    *
+    * It should not be used with PIPE_TRANSFER_READ.
+    *
+    * This is equivalent to:
+    * - OpenGL's ARB_map_buffer_range extension, MAP_INVALIDATE_BUFFER_BIT
+    * - BufferData(NULL) on a GL buffer
+    * - Direct3D's D3DLOCK_DISCARD flag.
+    * - WDDM's D3DDDICB_LOCKFLAGS.Discard flag.
+    * - D3D10 DDI's D3D10_DDI_MAP_WRITE_DISCARD flag
+    * - D3D10's D3D10_MAP_WRITE_DISCARD flag.
+    */
+   PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE = (1 << 12)
 
 };
 
@@ -380,7 +395,8 @@ enum pipe_transfer_usage {
 #define PIPE_QUERY_SO_STATISTICS         5
 #define PIPE_QUERY_GPU_FINISHED          6
 #define PIPE_QUERY_TIMESTAMP_DISJOINT    7
-#define PIPE_QUERY_TYPES                 8
+#define PIPE_QUERY_OCCLUSION_PREDICATE   8
+#define PIPE_QUERY_TYPES                 9
 
 
 /**
index 3aa11be4b5b9aa26bfa0ab85f1494dc2b8d83280..e2cc32222de0fb5b6a596afb01a10100c418f8d1 100644 (file)
 extern "C" {
 #endif
 
+
+enum pipe_type {
+   PIPE_TYPE_UNORM = 0,
+   PIPE_TYPE_SNORM,
+   PIPE_TYPE_SINT,
+   PIPE_TYPE_UINT,
+   PIPE_TYPE_FLOAT,
+   PIPE_TYPE_COUNT
+};
+
 /**
  * Texture/surface image formats (preliminary)
  */
index 0a9e14154d732a942ef3bac40f46def92aa0b25e..d3a3632654c15fdd657b961dd3a5088155c7744f 100644 (file)
@@ -75,6 +75,7 @@ enum tgsi_file_type {
    TGSI_FILE_SYSTEM_VALUE        =9,
    TGSI_FILE_IMMEDIATE_ARRAY     =10,
    TGSI_FILE_TEMPORARY_ARRAY     =11,
+   TGSI_FILE_RESOURCE            =12,
    TGSI_FILE_COUNT      /**< how many TGSI_FILE_ types */
 };
 
@@ -153,6 +154,14 @@ struct tgsi_declaration_semantic
    unsigned Padding        : 8;
 };
 
+struct tgsi_declaration_resource {
+   unsigned Resource    : 8; /**< one of TGSI_TEXTURE_ */
+   unsigned ReturnTypeX : 6; /**< one of enum pipe_type */
+   unsigned ReturnTypeY : 6; /**< one of enum pipe_type */
+   unsigned ReturnTypeZ : 6; /**< one of enum pipe_type */
+   unsigned ReturnTypeW : 6; /**< one of enum pipe_type */
+};
+
 #define TGSI_IMM_FLOAT32   0
 #define TGSI_IMM_UINT32    1
 #define TGSI_IMM_INT32     2
@@ -339,7 +348,22 @@ struct tgsi_property_data {
 #define TGSI_OPCODE_CASE                142
 #define TGSI_OPCODE_DEFAULT             143
 #define TGSI_OPCODE_ENDSWITCH           144
-#define TGSI_OPCODE_LAST                145
+
+/* resource related opcodes */
+#define TGSI_OPCODE_LOAD                145
+#define TGSI_OPCODE_LOAD_MS             146
+#define TGSI_OPCODE_SAMPLE              147
+#define TGSI_OPCODE_SAMPLE_B            148
+#define TGSI_OPCODE_SAMPLE_C            149
+#define TGSI_OPCODE_SAMPLE_C_LZ         150
+#define TGSI_OPCODE_SAMPLE_D            151
+#define TGSI_OPCODE_SAMPLE_L            152
+#define TGSI_OPCODE_GATHER4             153
+#define TGSI_OPCODE_RESINFO             154
+#define TGSI_OPCODE_SAMPLE_POS          155
+#define TGSI_OPCODE_SAMPLE_INFO         156
+
+#define TGSI_OPCODE_LAST                157
 
 #define TGSI_SAT_NONE            0  /* do not saturate */
 #define TGSI_SAT_ZERO_ONE        1  /* clamp to [0,1] */
@@ -406,7 +430,9 @@ struct tgsi_instruction_label
 #define TGSI_TEXTURE_SHADOW1D       6
 #define TGSI_TEXTURE_SHADOW2D       7
 #define TGSI_TEXTURE_SHADOWRECT     8
-#define TGSI_TEXTURE_COUNT          9
+#define TGSI_TEXTURE_1D_ARRAY       9
+#define TGSI_TEXTURE_2D_ARRAY      10
+#define TGSI_TEXTURE_COUNT         11
 
 struct tgsi_instruction_texture
 {
index 226ae8667b703d17f12cbb920f9fd2914a1ab1c9..cf6c5b50268d3cb85f938893a4a474f8bfb5291f 100644 (file)
@@ -62,6 +62,7 @@ extern "C" {
 #define PIPE_MAX_GEOMETRY_SAMPLERS  16
 #define PIPE_MAX_SHADER_INPUTS    32
 #define PIPE_MAX_SHADER_OUTPUTS   32
+#define PIPE_MAX_SHADER_RESOURCES 32
 #define PIPE_MAX_TEXTURE_LEVELS   16
 #define PIPE_MAX_SO_BUFFERS        4
 
@@ -389,11 +390,11 @@ struct pipe_stream_output_state
 struct pipe_transfer
 {
    struct pipe_resource *resource; /**< resource to transfer to/from  */
-   unsigned level;
+   unsigned level;                 /**< texture mipmap level */
    enum pipe_transfer_usage usage;
-   struct pipe_box box;
-   unsigned stride;
-   unsigned layer_stride;
+   struct pipe_box box;            /**< region of the resource to access */
+   unsigned stride;                /**< row stride in bytes */
+   unsigned layer_stride;          /**< image/layer stride in bytes */
    void *data;
 };
 
@@ -407,7 +408,6 @@ struct pipe_transfer
 struct pipe_vertex_buffer
 {
    unsigned stride;    /**< stride to same attrib in next vertex, in bytes */
-   unsigned max_index;   /**< number of vertices in this buffer */
    unsigned buffer_offset;  /**< offset to start of data in buffer, in bytes */
    struct pipe_resource *buffer;  /**< the actual buffer */
 };
index 2ff24e17d41c9a321de9ebca56bb0df8407befce..2e45f3f43e97be64ae08a34cc4309bbd416209d4 100644 (file)
@@ -794,9 +794,9 @@ struct dxgi_blitter
                const unsigned semantic_indices[] = { 0, 0 };
                vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names, semantic_indices);
 
-               vbuf.buffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, sizeof(quad_data));
+               vbuf.buffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER,
+                                                PIPE_USAGE_STREAM, sizeof(quad_data));
                vbuf.buffer_offset = 0;
-               vbuf.max_index = ~0;
                vbuf.stride = 4 * sizeof(float);
                pipe_buffer_write(pipe, vbuf.buffer, 0, sizeof(quad_data), quad_data);
 
index e1ba6c184fdc9a939afa19e41f9f00efcf6ef8d9..542d65912936c1e8f44346a1540dce0d9a04e36c 100644 (file)
@@ -623,7 +623,6 @@ struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
                                vertex_buffers[start + i].buffer = buffer ? ((GalliumD3D11Buffer*)buffer)->resource : 0;
                                vertex_buffers[start + i].buffer_offset = new_offsets[i];
                                vertex_buffers[start + i].stride = new_strides[i];
-                               vertex_buffers[start + i].max_index = ~0;
                                last_different = i;
                        }
                }
index 3d5d24e692c39d51719067d2943606063e70e18b..fc68ee13eaa3e20586b1f7ff1a0147f9fe9fa945 100644 (file)
@@ -141,12 +141,18 @@ GLboolean
 dri_unbind_context(__DRIcontext * cPriv)
 {
    /* dri_util.c ensures cPriv is not null */
+   struct dri_screen *screen = dri_screen(cPriv->driScreenPriv);
    struct dri_context *ctx = dri_context(cPriv);
+   struct dri_drawable *draw = dri_drawable(ctx->dPriv);
+   struct dri_drawable *read = dri_drawable(ctx->rPriv);
+   struct st_api *stapi = screen->st_api;
 
    if (--ctx->bind_count == 0) {
       if (ctx->st == ctx->stapi->get_current(ctx->stapi)) {
          ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
-         ctx->stapi->make_current(ctx->stapi, NULL, NULL, NULL);
+         stapi->make_current(stapi, NULL, NULL, NULL);
+         draw->context = NULL;
+         read->context = NULL;
       }
    }
 
@@ -169,17 +175,23 @@ dri_make_current(__DRIcontext * cPriv,
 
    ++ctx->bind_count;
 
+   if (!driDrawPriv && !driReadPriv)
+      return ctx->stapi->make_current(ctx->stapi, ctx->st, NULL, NULL);
+   else if (!driDrawPriv || !driReadPriv)
+      return GL_FALSE;
+
+   draw->context = ctx;
    if (ctx->dPriv != driDrawPriv) {
       ctx->dPriv = driDrawPriv;
       draw->texture_stamp = driDrawPriv->lastStamp - 1;
    }
+   read->context = ctx;
    if (ctx->rPriv != driReadPriv) {
       ctx->rPriv = driReadPriv;
       read->texture_stamp = driReadPriv->lastStamp - 1;
    }
 
-   ctx->stapi->make_current(ctx->stapi, ctx->st,
-         (draw) ? &draw->base : NULL, (read) ? &read->base : NULL);
+   ctx->stapi->make_current(ctx->stapi, ctx->st, &draw->base, &read->base);
 
    return GL_TRUE;
 }
index 060748622c9dfbc82857fd7382f955d5e96b89b5..28a33ac7d07c0077bc4f87880177a226996b80fc 100644 (file)
@@ -132,6 +132,7 @@ dri_create_buffer(__DRIscreen * sPriv,
    drawable->base.validate = dri_st_framebuffer_validate;
    drawable->base.st_manager_private = (void *) drawable;
 
+   drawable->screen = screen;
    drawable->sPriv = sPriv;
    drawable->dPriv = dPriv;
    dPriv->driverPrivate = (void *)drawable;
index 2ff6b7132935cd5892db62cd36019ee5137521fa..7f1aa512ca1bd4decd510c30e37c37b9398d0580 100644 (file)
@@ -41,6 +41,9 @@ struct dri_drawable
    struct st_framebuffer_iface base;
    struct st_visual stvis;
 
+   struct dri_screen *screen;
+   struct dri_context *context;
+
    /* dri */
    __DRIdrawable *dPriv;
    __DRIscreen *sPriv;
index f6e22c74b4e68fac3a7174c74c8f93d22241cd79..69c2e7e9ec83ed35ac22ad6464436e079e7b6833 100644 (file)
@@ -235,7 +235,6 @@ dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
       return;
 
    stvis->samples = mode->samples;
-   stvis->render_buffer = ST_ATTACHMENT_INVALID;
 
    if (mode->redBits == 8) {
       if (mode->alphaBits == 8)
@@ -274,8 +273,11 @@ dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
       PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
 
    stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
-   if (mode->doubleBufferMode)
+   stvis->render_buffer = ST_ATTACHMENT_FRONT_LEFT;
+   if (mode->doubleBufferMode) {
       stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
+      stvis->render_buffer = ST_ATTACHMENT_BACK_LEFT;
+   }
    if (mode->stereoMode) {
       stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
       if (mode->doubleBufferMode)
index a9d05a80fbd395c24c4b5c9115fe013ba378a299..0181588096defeff826bdddcd2f8107096d3702b 100644 (file)
@@ -38,6 +38,7 @@
 #include "dri_screen.h"
 #include "dri_context.h"
 #include "dri_drawable.h"
+#include "dri2_buffer.h"
 
 /**
  * DRI2 flush extension.
@@ -51,7 +52,7 @@ static void
 dri2_invalidate_drawable(__DRIdrawable *dPriv)
 {
    struct dri_drawable *drawable = dri_drawable(dPriv);
-   struct dri_context *ctx = dri_context(dPriv->driContextPriv);
+   struct dri_context *ctx = drawable->context;
 
    dri2InvalidateDrawable(dPriv);
    drawable->dPriv->lastStamp = *drawable->dPriv->pStamp;
@@ -259,6 +260,91 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable,
    memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count);
 }
 
+static __DRIbuffer *
+dri2_allocate_buffer(__DRIscreen *sPriv,
+                     unsigned attachment, unsigned format,
+                     int width, int height)
+{
+   struct dri_screen *screen = dri_screen(sPriv);
+   struct dri2_buffer *buffer;
+   struct pipe_resource templ;
+   enum st_attachment_type statt;
+   enum pipe_format pf;
+   unsigned bind;
+   struct winsys_handle whandle;
+
+   switch (attachment) {
+      case __DRI_BUFFER_FRONT_LEFT:
+      case __DRI_BUFFER_FAKE_FRONT_LEFT:
+         statt = ST_ATTACHMENT_FRONT_LEFT;
+         bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+         break;
+      case __DRI_BUFFER_BACK_LEFT:
+         statt = ST_ATTACHMENT_BACK_LEFT;
+         bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+         break;
+      case __DRI_BUFFER_DEPTH:
+      case __DRI_BUFFER_DEPTH_STENCIL:
+      case __DRI_BUFFER_STENCIL:
+            statt = ST_ATTACHMENT_DEPTH_STENCIL;
+            bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
+         break;
+      default:
+         statt = ST_ATTACHMENT_INVALID;
+         break;
+   }
+
+   switch (format) {
+      case 32:
+         pf = PIPE_FORMAT_B8G8R8X8_UNORM;
+         break;
+      case 16:
+         pf = PIPE_FORMAT_Z16_UNORM;
+         break;
+      default:
+         return NULL;
+   }
+
+   buffer = CALLOC_STRUCT(dri2_buffer);
+   if (!buffer)
+      return NULL;
+
+   memset(&templ, 0, sizeof(templ));
+   templ.bind = bind;
+   templ.format = pf;
+   templ.target = PIPE_TEXTURE_2D;
+   templ.last_level = 0;
+   templ.width0 = width;
+   templ.height0 = height;
+   templ.depth0 = 1;
+
+   buffer->resource =
+      screen->base.screen->resource_create(screen->base.screen, &templ);
+   if (!buffer->resource)
+      return NULL;
+
+   memset(&whandle, 0, sizeof(whandle));
+   whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+   screen->base.screen->resource_get_handle(screen->base.screen,
+         buffer->resource, &whandle);
+
+   buffer->base.attachment = attachment;
+   buffer->base.name = whandle.handle;
+   buffer->base.cpp = util_format_get_blocksize(pf);
+   buffer->base.pitch = whandle.stride;
+
+   return &buffer->base;
+}
+
+static void
+dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
+{
+   struct dri2_buffer *buffer = dri2_buffer(bPriv);
+
+   pipe_resource_reference(&buffer->resource, NULL);
+   FREE(buffer);
+}
+
 /*
  * Backend functions for st_framebuffer interface.
  */
@@ -373,7 +459,7 @@ static __DRIimage *
 dri2_create_image_from_renderbuffer(__DRIcontext *context,
                                    int renderbuffer, void *loaderPrivate)
 {
-   struct dri_context *ctx = dri_context(context->driverPrivate);
+   struct dri_context *ctx = dri_context(context);
 
    if (!ctx->st->get_resource_for_egl_image)
       return NULL;
@@ -601,6 +687,9 @@ const struct __DriverAPIRec driDriverAPI = {
 
    .SwapBuffers = NULL,
    .CopySubBuffer = NULL,
+
+   .AllocateBuffer = dri2_allocate_buffer,
+   .ReleaseBuffer  = dri2_release_buffer,
 };
 
 /* This is the table of extensions that the loader will dlsym() for. */
diff --git a/src/gallium/state_trackers/dri/drm/dri2_buffer.h b/src/gallium/state_trackers/dri/drm/dri2_buffer.h
new file mode 100644 (file)
index 0000000..1cd8dbb
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef DRI2_BUFFER_H
+#define DRI2_BUFFER_H
+
+#include "dri_wrapper.h"
+
+struct pipe_surface;
+
+struct dri2_buffer
+{
+   __DRIbuffer base;
+   struct pipe_resource *resource;
+};
+
+static INLINE struct dri2_buffer *
+dri2_buffer(__DRIbuffer * driBufferPriv)
+{
+   return (struct dri2_buffer *) driBufferPriv;
+}
+
+#endif
+
+/* vim: set sw=3 ts=8 sts=3 expandtab: */
index 8cfcef968eda0e32ac5e38f6f3052859fd3f37cc..98167cceeb3770727f8cfddd1018108d4c9c2446 100644 (file)
@@ -23,6 +23,13 @@ x11_SOURCES = $(wildcard x11/*.c) \
              $(TOP)/src/glx/dri2.c
 x11_OBJECTS = $(x11_SOURCES:.c=.o)
 
+wayland_INCLUDES = \
+       -I$(TOP)/src/gallium/winsys \
+       -I$(TOP)/src/egl/wayland \
+       $(shell pkg-config --cflags-only-I libdrm wayland-client)
+
+wayland_SOURCES = $(wildcard wayland/*.c)
+wayland_OBJECTS = $(wayland_SOURCES:.c=.o)
 
 drm_INCLUDES = -I$(TOP)/src/gallium/winsys $(shell pkg-config --cflags-only-I libdrm)
 drm_SOURCES = $(wildcard drm/*.c)
@@ -45,6 +52,10 @@ ifneq ($(findstring x11, $(EGL_PLATFORMS)),)
 EGL_OBJECTS += $(x11_OBJECTS)
 EGL_CPPFLAGS += -DHAVE_X11_BACKEND
 endif
+ifneq ($(findstring wayland, $(EGL_PLATFORMS)),)
+EGL_OBJECTS += $(wayland_OBJECTS)
+EGL_CPPFLAGS += -DHAVE_WAYLAND_BACKEND
+endif
 ifneq ($(findstring drm, $(EGL_PLATFORMS)),)
 EGL_OBJECTS += $(drm_OBJECTS)
 EGL_CPPFLAGS += -DHAVE_DRM_BACKEND
@@ -87,6 +98,9 @@ $(common_OBJECTS): %.o: %.c
 $(x11_OBJECTS): %.o: %.c
        $(call egl-cc,x11)
 
+$(wayland_OBJECTS): %.o: %.c
+       $(call egl-cc,wayland)
+
 $(drm_OBJECTS): %.o: %.c
        $(call egl-cc,drm)
 
index 9024f945b8cd774e12f3202a3fd4b8b9202bffe5..6107df48822dab0b98ef2b8ba49bd02f0723789c 100644 (file)
@@ -101,6 +101,12 @@ egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat)
          plat_name = "X11";
 #ifdef HAVE_X11_BACKEND
          nplat = native_get_x11_platform();
+#endif
+        break;
+      case _EGL_PLATFORM_WAYLAND:
+         plat_name = "wayland";
+#ifdef HAVE_WAYLAND_BACKEND
+         nplat = native_get_wayland_platform();
 #endif
          break;
       case _EGL_PLATFORM_DRM:
@@ -546,6 +552,9 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy)
          dpy->Extensions.MESA_drm_image = EGL_TRUE;
    }
 
+   if (dpy->Platform == _EGL_PLATFORM_WAYLAND && gdpy->native->buffer)
+      dpy->Extensions.MESA_drm_image = EGL_TRUE;
+
    if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
       _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
       goto fail;
index 78c035a2af059f9c0fb385e6c208435089b7ff7a..81ce7ab45c7a135ac69120e9bc1ad3c5917b37f5 100644 (file)
@@ -135,7 +135,7 @@ egl_g3d_reference_drm_buffer(_EGLDisplay *dpy, EGLint name,
    _EGLImageAttribs attrs;
    EGLint format;
 
-   if (dpy->Platform != _EGL_PLATFORM_DRM)
+   if (!dpy->Extensions.MESA_drm_image)
       return NULL;
 
    if (_eglParseImageAttribList(&attrs, dpy, attribs) != EGL_SUCCESS)
@@ -295,7 +295,7 @@ egl_g3d_export_drm_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img,
    struct egl_g3d_image *gimg = egl_g3d_image(img);
    struct winsys_handle wsh;
 
-   if (dpy->Platform != _EGL_PLATFORM_DRM)
+   if (!dpy->Extensions.MESA_drm_image)
       return EGL_FALSE;
 
    /* get shared handle */
index 6461b5edbdf000ada763f5d0c95119f54f1fd09c..42889075a3970b61cf1337f2d82282076147ff52 100644 (file)
@@ -238,6 +238,9 @@ native_get_gdi_platform(void);
 const struct native_platform *
 native_get_x11_platform(void);
 
+const struct native_platform *
+native_get_wayland_platform(void);
+
 const struct native_platform *
 native_get_drm_platform(void);
 
index 0f2d02032b575707d08ce7f587c503fa44030640..a9d8f32e007bc35dc81020212e0289c923104683 100644 (file)
@@ -143,6 +143,14 @@ resource_surface_add_resources(struct resource_surface *rsurf,
    return ((rsurf->resource_mask & resource_mask) == resource_mask);
 }
 
+void
+resource_surface_import_resource(struct resource_surface *rsurf,
+                                 enum native_attachment which,
+                                 struct pipe_resource *pres)
+{
+       pipe_resource_reference(&rsurf->resources[which], pres);
+       rsurf->resource_mask |= 1 << which;
+}
 
 void
 resource_surface_get_resources(struct resource_surface *rsurf,
index d1569ac3ea6dd561564527f6eee19897af88ecc6..03995de19ae30c5afe3b3c39b325f340c9eaae13 100644 (file)
@@ -50,6 +50,11 @@ boolean
 resource_surface_add_resources(struct resource_surface *rsurf,
                                uint resource_mask);
 
+void
+resource_surface_import_resource(struct resource_surface *rsurf,
+                                 enum native_attachment which,
+                                 struct pipe_resource *pres);
+
 void
 resource_surface_get_resources(struct resource_surface *rsurf,
                                struct pipe_resource **resources,
index 14c134ea1ada10346e8d904c58f853b0ca7166e6..6932f30a6a4b1bc11f1b6fe68737ec8ab125535b 100644 (file)
@@ -178,7 +178,7 @@ drm_display_init_screen(struct native_display *ndpy)
    drmFreeVersion(version);
 
    if (!drmdpy->base.screen) {
-      _eglLog(_EGL_WARNING, "failed to create DRM screen");
+      _eglLog(_EGL_DEBUG, "failed to create DRM screen");
       return FALSE;
    }
 
diff --git a/src/gallium/state_trackers/egl/wayland/native_wayland.c b/src/gallium/state_trackers/egl/wayland/native_wayland.c
new file mode 100644 (file)
index 0000000..d4d5f9c
--- /dev/null
@@ -0,0 +1,626 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.11
+ *
+ * Copyright (C) 2011 Benjamin Franzke <benjaminfranzke@googlemail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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_memory.h"
+#include "util/u_inlines.h"
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "state_tracker/drm_driver.h"
+
+#include "egllog.h"
+
+#include "native_wayland.h"
+
+/* see get_drm_screen_name */
+#include <radeon_drm.h>
+#include "radeon/drm/radeon_drm_public.h"
+
+#include <wayland-client.h>
+#include "wayland-egl-priv.h"
+
+#include <xf86drm.h>
+
+static struct native_event_handler *wayland_event_handler;
+
+static void
+sync_callback(void *data)
+{
+   int *done = data;
+
+   *done = 1;
+}
+
+static void
+force_roundtrip(struct wl_display *display)
+{
+   int done = 0;
+
+   wl_display_sync_callback(display, sync_callback, &done);
+   wl_display_iterate(display, WL_DISPLAY_WRITABLE);
+   while (!done)
+      wl_display_iterate(display, WL_DISPLAY_READABLE);
+}
+
+static const struct native_config **
+wayland_display_get_configs (struct native_display *ndpy, int *num_configs)
+{
+   struct wayland_display *display = wayland_display(ndpy);
+   const struct native_config **configs;
+
+   if (!display->config) {
+      struct native_config *nconf;
+      enum pipe_format format;
+      display->config = CALLOC(1, sizeof(*display->config));
+      if (!display->config)
+         return NULL;
+      nconf = &display->config->base;
+
+      nconf->buffer_mask =
+         (1 << NATIVE_ATTACHMENT_FRONT_LEFT) |
+         (1 << NATIVE_ATTACHMENT_BACK_LEFT);
+
+      format = PIPE_FORMAT_B8G8R8A8_UNORM;
+
+      nconf->color_format = format;
+      nconf->window_bit = TRUE;
+      nconf->pixmap_bit = TRUE;
+   }
+
+   configs = MALLOC(sizeof(*configs));
+   if (configs) {
+      configs[0] = &display->config->base;
+      if (num_configs)
+         *num_configs = 1;
+   }
+
+   return configs;
+}
+
+static int
+wayland_display_get_param(struct native_display *ndpy,
+                          enum native_param_type param)
+{
+   int val;
+
+   switch (param) {
+      case NATIVE_PARAM_USE_NATIVE_BUFFER:
+      case NATIVE_PARAM_PRESERVE_BUFFER:
+      case NATIVE_PARAM_MAX_SWAP_INTERVAL:
+      default:
+         val = 0;
+         break;
+   }
+
+   return val;
+}
+
+static boolean
+wayland_display_is_pixmap_supported(struct native_display *ndpy,
+                                    EGLNativePixmapType pix,
+                                    const struct native_config *nconf)
+{
+   /* all wl_egl_pixmaps are supported */
+
+   return TRUE;
+}
+
+static void 
+wayland_display_destroy(struct native_display *ndpy)
+{
+   struct wayland_display *display = wayland_display(ndpy);
+
+   if (display->config)
+      FREE(display->config);
+
+   if (display->base.screen)
+      display->base.screen->destroy(display->base.screen);
+
+   FREE(display);
+}
+
+
+static struct wl_buffer *
+wayland_create_buffer(struct wayland_surface *surface,
+                      enum native_attachment attachment)
+{
+   struct wayland_display *display = surface->display;
+   struct pipe_resource *resource;
+   struct winsys_handle wsh;
+   uint width, height;
+
+   resource = resource_surface_get_single_resource(surface->rsurf, attachment);
+   resource_surface_get_size(surface->rsurf, &width, &height);
+
+   wsh.type = DRM_API_HANDLE_TYPE_SHARED;
+   display->base.screen->resource_get_handle(display->base.screen, resource, &wsh);
+
+   pipe_resource_reference(&resource, NULL);
+
+   return wl_drm_create_buffer(display->dpy->drm, wsh.handle,
+                               width, height,
+                               wsh.stride, surface->win->visual);
+}
+
+static void
+wayland_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap)
+{
+   struct pipe_resource *resource = egl_pixmap->driver_private;
+
+   assert(resource);
+
+   pipe_resource_reference(&resource, NULL);
+   
+   egl_pixmap->driver_private = NULL;
+   egl_pixmap->destroy = NULL;
+   egl_pixmap->name = 0;
+}
+
+static void
+wayland_pixmap_surface_intialize(struct wayland_surface *surface)
+{
+   struct native_display *ndpy = &surface->display->base;
+   struct pipe_resource *resource;
+   struct winsys_handle wsh;
+   const enum native_attachment front_natt = NATIVE_ATTACHMENT_FRONT_LEFT;
+
+   if (surface->pix->name > 0)
+      return;
+
+   resource = resource_surface_get_single_resource(surface->rsurf, front_natt);
+
+   wsh.type = DRM_API_HANDLE_TYPE_SHARED;
+   ndpy->screen->resource_get_handle(ndpy->screen, resource, &wsh);
+
+   surface->pix->name           = wsh.handle;
+   surface->pix->stride         = wsh.stride;
+   surface->pix->destroy        = wayland_pixmap_destroy;
+   surface->pix->driver_private = resource;
+}
+
+static void
+wayland_release_pending_resource(void *data)
+{
+   struct wayland_surface *surface = data;
+
+   /* FIXME: print internal error */
+   if (!surface->pending_resource)
+      return;
+
+   pipe_resource_reference(&surface->pending_resource, NULL);
+}
+
+static void
+wayland_window_surface_handle_resize(struct wayland_surface *surface)
+{
+   struct wayland_display *display = surface->display;
+   struct pipe_resource *front_resource;
+   const enum native_attachment front_natt = NATIVE_ATTACHMENT_FRONT_LEFT;
+   int i;
+   
+   front_resource = resource_surface_get_single_resource(surface->rsurf,
+                                                         front_natt);
+   if (resource_surface_set_size(surface->rsurf,
+       surface->win->width, surface->win->height)) {
+
+      if (surface->pending_resource)
+         force_roundtrip(display->dpy->display);
+
+      if (front_resource) {
+         surface->pending_resource = front_resource;
+         front_resource = NULL;
+         wl_display_sync_callback(display->dpy->display,
+                                  wayland_release_pending_resource, surface);
+      }
+
+      for (i = 0; i < WL_BUFFER_COUNT; ++i) {
+         if (surface->buffer[i])
+            wl_buffer_destroy(surface->buffer[i]);
+         surface->buffer[i] = NULL;
+      }
+   }
+   pipe_resource_reference(&front_resource, NULL);
+
+   surface->dx = surface->win->dx;
+   surface->dy = surface->win->dy;
+   surface->win->dx = 0;
+   surface->win->dy = 0;
+}
+
+static boolean
+wayland_surface_validate(struct native_surface *nsurf, uint attachment_mask,
+                         unsigned int *seq_num, struct pipe_resource **textures,
+                         int *width, int *height)
+{
+   struct wayland_surface *surface = wayland_surface(nsurf);
+
+   if (surface->type == WL_WINDOW_SURFACE)
+      wayland_window_surface_handle_resize(surface);
+
+   if (!resource_surface_add_resources(surface->rsurf, attachment_mask |
+                                       surface->attachment_mask))
+      return FALSE;
+
+   if (textures)
+      resource_surface_get_resources(surface->rsurf, textures, attachment_mask);
+
+   if (seq_num)
+      *seq_num = surface->sequence_number;
+
+   resource_surface_get_size(surface->rsurf, (uint *) width, (uint *) height);
+
+   if (surface->type == WL_PIXMAP_SURFACE)
+      wayland_pixmap_surface_intialize(surface);
+
+   return TRUE;
+}
+
+static void
+wayland_frame_callback(void *data, uint32_t time)
+{
+   struct wayland_surface *surface = data;
+
+   surface->block_swap_buffers = FALSE;
+}
+
+static INLINE void
+wayland_buffers_swap(struct wl_buffer **buffer,
+                     enum wayland_buffer_type buf1,
+                     enum wayland_buffer_type buf2)
+{
+   struct wl_buffer *tmp = buffer[buf1];
+   buffer[buf1] = buffer[buf2];
+   buffer[buf2] = tmp;
+}
+
+static boolean
+wayland_surface_swap_buffers(struct native_surface *nsurf)
+{
+   struct wayland_surface *surface = wayland_surface(nsurf);
+   struct wayland_display *display = surface->display;
+
+   while (surface->block_swap_buffers)
+      wl_display_iterate(display->dpy->display, WL_DISPLAY_READABLE);
+
+   surface->block_swap_buffers = TRUE;
+   wl_display_frame_callback(display->dpy->display, wayland_frame_callback,
+                             surface);
+
+   if (surface->type == WL_WINDOW_SURFACE) {
+      resource_surface_swap_buffers(surface->rsurf,
+       NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, FALSE);
+
+      wayland_buffers_swap(surface->buffer, WL_BUFFER_FRONT, WL_BUFFER_BACK);
+
+      if (surface->buffer[WL_BUFFER_FRONT] == NULL)
+         surface->buffer[WL_BUFFER_FRONT] =
+       wayland_create_buffer(surface, NATIVE_ATTACHMENT_FRONT_LEFT);
+
+      wl_surface_attach(surface->win->surface, surface->buffer[WL_BUFFER_FRONT],
+                        surface->dx, surface->dy);
+     
+      resource_surface_get_size(surface->rsurf,
+                                (uint *) &surface->win->attached_width,
+                                (uint *) &surface->win->attached_height);
+      surface->dx = 0;
+      surface->dy = 0;
+   }
+
+   surface->sequence_number++;
+   wayland_event_handler->invalid_surface(&display->base,
+        &surface->base, surface->sequence_number);
+
+   return TRUE;
+}
+
+static boolean
+wayland_surface_present(struct native_surface *nsurf,
+                        enum native_attachment natt,
+                        boolean preserve,
+                        uint swap_interval)
+{
+   struct wayland_surface *surface = wayland_surface(nsurf);
+   uint width, height;
+   boolean ret;
+
+   if (preserve || swap_interval)
+      return FALSE;
+
+   switch (natt) {
+   case NATIVE_ATTACHMENT_FRONT_LEFT:
+      ret = TRUE;
+      break;
+   case NATIVE_ATTACHMENT_BACK_LEFT:
+      ret = wayland_surface_swap_buffers(nsurf);
+      break;
+   default:
+      ret = FALSE;
+      break;
+   }
+
+   if (surface->type == WL_WINDOW_SURFACE) {
+      resource_surface_get_size(surface->rsurf, &width, &height);
+      wl_surface_damage(surface->win->surface, 0, 0, width, height);
+   }
+
+   return ret;
+}
+
+static void
+wayland_surface_wait(struct native_surface *nsurf)
+{
+   /* no-op */
+}
+
+static void
+wayland_surface_destroy(struct native_surface *nsurf)
+{
+   struct wayland_surface *surface = wayland_surface(nsurf);
+   enum wayland_buffer_type buffer;
+
+   for (buffer = 0; buffer < WL_BUFFER_COUNT; ++buffer) {
+      if (surface->buffer[buffer])
+         wl_buffer_destroy(surface->buffer[buffer]);
+   }
+
+   resource_surface_destroy(surface->rsurf);
+   FREE(surface);
+}
+
+static struct native_surface *
+wayland_create_pixmap_surface(struct native_display *ndpy,
+                              EGLNativePixmapType pix,
+                              const struct native_config *nconf)
+{
+   struct wayland_display *display = wayland_display(ndpy);
+   struct wayland_config *config = wayland_config(nconf);
+   struct wayland_surface *surface;
+   struct wl_egl_pixmap *egl_pixmap = (struct wl_egl_pixmap *) pix;
+   enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT;
+
+   surface = CALLOC_STRUCT(wayland_surface);
+   if (!surface)
+      return NULL;
+
+   surface->display = display;
+
+   surface->pending_resource = NULL;
+   surface->type = WL_PIXMAP_SURFACE;
+   surface->pix = egl_pixmap;
+
+   if (surface->pix->visual == wl_display_get_rgb_visual(display->dpy->display))
+      surface->color_format = PIPE_FORMAT_B8G8R8X8_UNORM;
+   else
+      surface->color_format = PIPE_FORMAT_B8G8R8A8_UNORM;
+
+   surface->attachment_mask = (1 << NATIVE_ATTACHMENT_FRONT_LEFT);
+   
+   surface->rsurf = resource_surface_create(display->base.screen,
+           surface->color_format,
+           PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW |
+           PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT);
+
+   if (!surface->rsurf) {
+       FREE(surface);
+       return NULL;
+   }
+
+   resource_surface_set_size(surface->rsurf,
+                             egl_pixmap->width, egl_pixmap->height);
+
+   /* the pixmap is already allocated, so import it */
+   if (surface->pix->name > 0)
+      resource_surface_import_resource(surface->rsurf, natt,
+                                       surface->pix->driver_private);
+
+   surface->base.destroy = wayland_surface_destroy;
+   surface->base.present = wayland_surface_present;
+   surface->base.validate = wayland_surface_validate;
+   surface->base.wait = wayland_surface_wait;
+
+   return &surface->base;
+}
+
+static struct native_surface *
+wayland_create_window_surface(struct native_display *ndpy,
+                              EGLNativeWindowType win,
+                              const struct native_config *nconf)
+{
+   struct wayland_display *display = wayland_display(ndpy);
+   struct wayland_config *config = wayland_config(nconf);
+   struct wayland_surface *surface;
+
+   surface = CALLOC_STRUCT(wayland_surface);
+   if (!surface)
+      return NULL;
+
+   surface->display = display;
+   surface->color_format = config->base.color_format;
+
+   surface->win = (struct wl_egl_window *) win;
+
+   surface->pending_resource = NULL;
+   surface->block_swap_buffers = FALSE;
+   surface->type = WL_WINDOW_SURFACE;
+
+   surface->buffer[WL_BUFFER_FRONT] = NULL;
+   surface->buffer[WL_BUFFER_BACK] = NULL;
+   surface->attachment_mask = (1 << NATIVE_ATTACHMENT_FRONT_LEFT) |
+                              (1 << NATIVE_ATTACHMENT_BACK_LEFT);
+
+   surface->rsurf = resource_surface_create(display->base.screen,
+           surface->color_format,
+           PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW |
+           PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT);
+
+   if (!surface->rsurf) {
+       FREE(surface);
+       return NULL;
+   }
+
+   surface->base.destroy = wayland_surface_destroy;
+   surface->base.present = wayland_surface_present;
+   surface->base.validate = wayland_surface_validate;
+   surface->base.wait = wayland_surface_wait;
+
+   return &surface->base;
+}
+
+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;
+}
+
+static boolean
+wayland_display_init_screen(struct native_display *ndpy)
+{
+   struct wayland_display *display = wayland_display(ndpy);
+   drmVersionPtr version;
+   const char *driver_name;
+
+   if (display->dpy->fd == -1)
+          force_roundtrip(display->dpy->display);
+   if (display->dpy->fd == -1)
+          return FALSE;
+
+   if (!display->dpy->authenticated)
+          force_roundtrip(display->dpy->display);
+   if (!display->dpy->authenticated)
+          return FALSE;
+
+   version = drmGetVersion(display->dpy->fd);
+   if (!version) {
+      _eglLog(_EGL_WARNING, "invalid fd %d", display->dpy->fd);
+      return FALSE;
+   }
+
+   /* FIXME: share this with native_drm or egl_dri2 */
+   driver_name = get_drm_screen_name(display->dpy->fd, version);
+
+   display->base.screen =
+      wayland_event_handler->new_drm_screen(&display->base,
+            driver_name, display->dpy->fd);
+   drmFreeVersion(version);
+
+   if (!display->base.screen) {
+      _eglLog(_EGL_WARNING, "failed to create DRM screen");
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+
+static void
+wayland_set_event_handler(struct native_event_handler *event_handler)
+{
+   wayland_event_handler = event_handler;
+}
+
+static struct pipe_resource *
+wayland_display_import_buffer(struct native_display *ndpy,
+                              const struct pipe_resource *templ,
+                              void *buf)
+{
+   return ndpy->screen->resource_from_handle(ndpy->screen,
+         templ, (struct winsys_handle *) buf);
+}
+
+static boolean
+wayland_display_export_buffer(struct native_display *ndpy,
+                              struct pipe_resource *res,
+                              void *buf)
+{
+   return ndpy->screen->resource_get_handle(ndpy->screen,
+         res, (struct winsys_handle *) buf);
+}
+
+static struct native_display_buffer wayland_display_buffer = {
+   wayland_display_import_buffer,
+   wayland_display_export_buffer
+};
+
+static struct native_display *
+wayland_display_create(void *dpy, boolean use_sw, void *user_data)
+{
+   struct wayland_display *display;
+
+   display = CALLOC_STRUCT(wayland_display);
+   if (!display)
+      return NULL;
+
+   display->base.user_data = user_data;
+
+   display->dpy = dpy;
+   if (!display->dpy->display) {
+      wayland_display_destroy(&display->base);
+      return NULL;
+   }
+
+   if (!wayland_display_init_screen(&display->base)) {
+      wayland_display_destroy(&display->base);
+      return NULL;
+   }
+
+   display->base.destroy = wayland_display_destroy;
+   display->base.get_param = wayland_display_get_param;
+   display->base.get_configs = wayland_display_get_configs;
+   display->base.is_pixmap_supported = wayland_display_is_pixmap_supported;
+   display->base.create_window_surface = wayland_create_window_surface;
+   display->base.create_pixmap_surface = wayland_create_pixmap_surface;
+   display->base.buffer = &wayland_display_buffer;
+
+   return &display->base;
+}
+
+static const struct native_platform wayland_platform = {
+   "wayland", /* name */
+   wayland_set_event_handler,
+   wayland_display_create
+};
+
+const struct native_platform *
+native_get_wayland_platform(void)
+{
+   return &wayland_platform;
+}
diff --git a/src/gallium/state_trackers/egl/wayland/native_wayland.h b/src/gallium/state_trackers/egl/wayland/native_wayland.h
new file mode 100644 (file)
index 0000000..271c10d
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.11
+ *
+ * Copyright (C) 2011 Benjamin Franzke <benjaminfranzke@googlemail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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.
+ */
+
+#ifndef _NATIVE_WAYLAND_H_
+#define _NATIVE_WAYLAND_H_
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+
+#include "common/native.h"
+#include "common/native_helper.h"
+
+#include "wayland-egl-priv.h"
+
+struct wayland_display {
+   struct native_display base;
+
+   struct wayland_config *config;
+   struct wl_egl_display *dpy;
+};
+
+enum wayland_buffer_type {
+   WL_BUFFER_FRONT,
+   WL_BUFFER_BACK,
+   WL_BUFFER_COUNT
+};
+
+enum wayland_surface_type {
+   WL_WINDOW_SURFACE,
+   WL_PIXMAP_SURFACE,
+   WL_PBUFFER_SURFACE
+};
+
+struct wayland_surface {
+   struct native_surface base;
+   struct wayland_display *display;
+
+   struct wl_egl_window *win;
+   struct wl_egl_pixmap *pix;
+   enum wayland_surface_type type;
+   int dx, dy;
+   struct resource_surface *rsurf;
+   struct pipe_resource *pending_resource;
+   enum pipe_format color_format;
+
+   unsigned int sequence_number;
+   struct wl_buffer *buffer[WL_BUFFER_COUNT];
+   unsigned int attachment_mask;
+
+   boolean block_swap_buffers;
+};
+
+struct wayland_config {
+    struct native_config base;
+};
+
+static INLINE struct wayland_display *
+wayland_display(const struct native_display *ndpy)
+{
+   return (struct wayland_display *) ndpy;
+}
+
+static INLINE struct wayland_surface *
+wayland_surface(const struct native_surface *nsurf)
+{
+   return (struct wayland_surface *) nsurf;
+}
+
+static INLINE struct wayland_config *
+wayland_config(const struct native_config *nconf)
+{
+   return (struct wayland_config *) nconf;
+}
+
+#endif /* _NATIVE_WAYLAND_H_ */
index c82e2da863b7c47df681e28a6a89545bc639a607..b18c3132c578142ac5ec69c8d132e0fe916246d4 100644 (file)
@@ -782,7 +782,7 @@ dri2_display_init_screen(struct native_display *ndpy)
       dri2dpy->event_handler->new_drm_screen(&dri2dpy->base,
             dri2dpy->dri_driver, fd);
    if (!dri2dpy->base.screen) {
-      _eglLog(_EGL_WARNING, "failed to create DRM screen");
+      _eglLog(_EGL_DEBUG, "failed to create DRM screen");
       return FALSE;
    }
 
index d694651eef77b9777c0357cca776c57cb7189fff..b30050bf6d4e5664643ba47d2defb0c23d64806f 100644 (file)
@@ -268,7 +268,6 @@ struct st_context {
 
    void set_vertex_buffer(unsigned index,
                           unsigned stride, 
-                          unsigned max_index,
                           unsigned buffer_offset,
                           struct pipe_resource *buffer)
    {
@@ -277,7 +276,6 @@ struct st_context {
       
       memset(&state, 0, sizeof(state));
       state.stride = stride;
-      state.max_index = max_index;
       state.buffer_offset = buffer_offset;
       state.buffer = buffer;
 
@@ -352,6 +350,7 @@ struct st_context {
 
       vbuf = pipe_buffer_create(screen,
                                 PIPE_BIND_VERTEX_BUFFER, 
+                                PIPE_USAGE_STATIC,
                                 size);
       if(!vbuf)
          goto error1;
@@ -378,7 +377,6 @@ struct st_context {
       vbuffer.buffer = vbuf;
       vbuffer.stride = num_attribs * 4 * sizeof(float);  /* vertex size */
       vbuffer.buffer_offset = 0;
-      vbuffer.max_index = num_verts - 1;
       pipe->set_vertex_buffers(pipe, 1, &vbuffer);
 
       /* draw */
index d55086fefd54b8b4756f1abcd694990d29256f67..cc67da937cd5dbe1e67caa9053ecdef5fe1feffb 100644 (file)
@@ -134,7 +134,7 @@ struct st_device {
    }
 
    struct pipe_resource *
-   buffer_create(unsigned size, unsigned bind = 0) {
-      return pipe_buffer_create($self->screen, bind, size);
+   buffer_create(unsigned size, unsigned usage, unsigned bind = 0) {
+      return pipe_buffer_create($self->screen, bind, usage, size);
    }
 };
index 7342c124c287469a47de5b7cf2b19b7928373f1a..3e8ad49b7675ccfaa87ae7ea1f9604dda32c8f80 100644 (file)
@@ -24,23 +24,25 @@ C_SOURCES = \
            api_path.c      \
            api_text.c      \
            api_transform.c \
-           vgu.c        \
-           vg_context.c \
-           vg_manager.c \
-           vg_state.c   \
-           vg_translate.c \
-           polygon.c    \
-           bezier.c     \
-           path.c       \
-           paint.c      \
            arc.c \
+           bezier.c \
+           handle.c \
            image.c \
+           mask.c \
+           paint.c \
+           path.c \
+           polygon.c \
            renderer.c \
+           shader.c \
+           shaders_cache.c \
            stroker.c \
-           mask.c \
            text.c \
-           shader.c \
-           shaders_cache.c
+           vg_context.c \
+           vg_manager.c \
+           vg_state.c \
+           vg_translate.c \
+           vgu.c
+
 
 GENERATED_SOURCES := api_tmp.h
 
index 4900135a1c53d5fdaa9b3ddb07bfd90bd16c6737..f3732aa15776b7ad69aac7de559c00c924d57330 100644 (file)
@@ -26,23 +26,24 @@ vega_sources = [
     'api_path.c',
     'api_text.c',
     'api_transform.c',
-    'vgu.c',
-    'vg_context.c',
-    'vg_manager.c',
-    'vg_state.c',
-    'vg_translate.c',
-    'polygon.c',
-    'bezier.c',
-    'path.c',
-    'paint.c',
     'arc.c',
+    'bezier.c',
+    'handle.c',
     'image.c',
-    'renderer.c',
-    'stroker.c',
     'mask.c',
+    'paint.c',
+    'path.c',
+    'polygon.c',
+    'renderer.c',
     'shader.c',
     'shaders_cache.c',
+    'stroker.c',
     'text.c',
+    'vg_context.c',
+    'vg_manager.c',
+    'vg_state.c',
+    'vg_translate.c',
+    'vgu.c'
 ]
 
 api_tmp = env.CodeGenerate(
index 724e38241b52232a49459d92dd5268683a3eeaa4..6be460c495c94cc6baaa7ab0c7f0eb89b68034f8 100644 (file)
@@ -29,6 +29,7 @@
 #include "vg_context.h"
 #include "image.h"
 #include "api.h"
+#include "handle.h"
 #include "renderer.h"
 #include "shaders_cache.h"
 
@@ -251,8 +252,8 @@ void vegaColorMatrix(VGImage dst, VGImage src,
       return;
    }
 
-   d = (struct vg_image*)dst;
-   s = (struct vg_image*)src;
+   d = handle_to_image(dst);
+   s = handle_to_image(src);
 
    if (vg_image_overlaps(d, s)) {
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
@@ -293,7 +294,7 @@ void vegaConvolve(VGImage dst, VGImage src,
    struct vg_image *d, *s;
    VGint kernel_size = kernelWidth * kernelHeight;
    struct filter_info info;
-   const VGint max_kernel_size = vgGeti(VG_MAX_KERNEL_SIZE);
+   const VGint max_kernel_size = vegaGeti(VG_MAX_KERNEL_SIZE);
 
    if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
@@ -317,8 +318,8 @@ void vegaConvolve(VGImage dst, VGImage src,
       return;
    }
 
-   d = (struct vg_image*)dst;
-   s = (struct vg_image*)src;
+   d = handle_to_image(dst);
+   s = handle_to_image(src);
 
    if (vg_image_overlaps(d, s)) {
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
@@ -395,7 +396,7 @@ void vegaSeparableConvolve(VGImage dst, VGImage src,
    struct vg_context *ctx = vg_current_context();
    VGshort *kernel;
    VGint i, j, idx = 0;
-   const VGint max_kernel_size = vgGeti(VG_MAX_SEPARABLE_KERNEL_SIZE);
+   const VGint max_kernel_size = vegaGeti(VG_MAX_SEPARABLE_KERNEL_SIZE);
 
    if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
@@ -425,8 +426,8 @@ void vegaSeparableConvolve(VGImage dst, VGImage src,
          ++idx;
       }
    }
-   vgConvolve(dst, src, kernelWidth, kernelHeight, shiftX, shiftY,
-              kernel, scale, bias, tilingMode);
+   vegaConvolve(dst, src, kernelWidth, kernelHeight, shiftX, shiftY,
+                kernel, scale, bias, tilingMode);
    free(kernel);
 }
 
@@ -502,8 +503,8 @@ void vegaGaussianBlur(VGImage dst, VGImage src,
       return;
    }
 
-   d = (struct vg_image*)dst;
-   s = (struct vg_image*)src;
+   d = handle_to_image(dst);
+   s = handle_to_image(src);
 
    if (vg_image_overlaps(d, s)) {
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
@@ -599,8 +600,8 @@ void vegaLookup(VGImage dst, VGImage src,
       return;
    }
 
-   d = (struct vg_image*)dst;
-   s = (struct vg_image*)src;
+   d = handle_to_image(dst);
+   s = handle_to_image(src);
 
    if (vg_image_overlaps(d, s)) {
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
@@ -662,8 +663,8 @@ void vegaLookupSingle(VGImage dst, VGImage src,
       return;
    }
 
-   d = (struct vg_image*)dst;
-   s = (struct vg_image*)src;
+   d = handle_to_image(dst);
+   s = handle_to_image(src);
 
    if (vg_image_overlaps(d, s)) {
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
index ad95409cd00411334554f802511a6dfcc4be1e27..b993ba62c26802016420b1fb55c7bfdc9030ee97 100644 (file)
@@ -32,6 +32,7 @@
 #include "vg_translate.h"
 #include "api_consts.h"
 #include "api.h"
+#include "handle.h"
 
 #include "pipe/p_context.h"
 #include "pipe/p_screen.h"
@@ -105,12 +106,12 @@ VGImage vegaCreateImage(VGImageFormat format,
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       return VG_INVALID_HANDLE;
    }
-   if (width > vgGeti(VG_MAX_IMAGE_WIDTH) ||
-       height > vgGeti(VG_MAX_IMAGE_HEIGHT)) {
+   if (width > vegaGeti(VG_MAX_IMAGE_WIDTH) ||
+       height > vegaGeti(VG_MAX_IMAGE_HEIGHT)) {
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       return VG_INVALID_HANDLE;
    }
-   if (width * height > vgGeti(VG_MAX_IMAGE_PIXELS)) {
+   if (width * height > vegaGeti(VG_MAX_IMAGE_PIXELS)) {
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       return VG_INVALID_HANDLE;
    }
@@ -122,19 +123,19 @@ VGImage vegaCreateImage(VGImageFormat format,
       return VG_INVALID_HANDLE;
    }
 
-   return (VGImage)image_create(format, width, height);
+   return image_to_handle(image_create(format, width, height));
 }
 
 void vegaDestroyImage(VGImage image)
 {
    struct vg_context *ctx = vg_current_context();
-   struct vg_image *img = (struct vg_image *)image;
+   struct vg_image *img = handle_to_image(image);
 
    if (image == VG_INVALID_HANDLE) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
-   if (!vg_object_is_valid((void*)image, VG_OBJECT_IMAGE)) {
+   if (!vg_object_is_valid(image, VG_OBJECT_IMAGE)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
@@ -157,7 +158,7 @@ void vegaClearImage(VGImage image,
       return;
    }
 
-   img = (struct vg_image*)image;
+   img = handle_to_image(image);
 
    if (x + width < 0 || y + height < 0)
       return;
@@ -189,7 +190,7 @@ void vegaImageSubData(VGImage image,
       return;
    }
 
-   img = (struct vg_image*)(image);
+   img = handle_to_image(image);
    image_sub_data(img, data, dataStride, dataFormat,
                   x, y, width, height);
 }
@@ -216,7 +217,7 @@ void vegaGetImageSubData(VGImage image,
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       return;
    }
-   img = (struct vg_image*)image;
+   img = handle_to_image(image);
    image_get_sub_data(img, data, dataStride, dataFormat,
                       x, y, width, height);
 }
@@ -229,8 +230,8 @@ VGImage vegaChildImage(VGImage parent,
    struct vg_image *p;
 
    if (parent == VG_INVALID_HANDLE ||
-       !vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void*)parent) ||
-       !vg_object_is_valid((void*)parent, VG_OBJECT_IMAGE)) {
+       !vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, parent) ||
+       !vg_object_is_valid(parent, VG_OBJECT_IMAGE)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return VG_INVALID_HANDLE;
    }
@@ -238,7 +239,7 @@ VGImage vegaChildImage(VGImage parent,
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       return VG_INVALID_HANDLE;
    }
-   p = (struct vg_image *)parent;
+   p = handle_to_image(parent);
    if (x > p->width  || y > p->height) {
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       return VG_INVALID_HANDLE;
@@ -248,7 +249,7 @@ VGImage vegaChildImage(VGImage parent,
       return VG_INVALID_HANDLE;
    }
 
-   return (VGImage)image_child_image(p, x, y, width, height);
+   return image_to_handle(image_child_image(p, x, y, width, height));
 }
 
 VGImage vegaGetParent(VGImage image)
@@ -261,9 +262,9 @@ VGImage vegaGetParent(VGImage image)
       return VG_INVALID_HANDLE;
    }
 
-   img = (struct vg_image*)image;
+   img = handle_to_image(image);
    if (img->parent)
-      return (VGImage)img->parent;
+      return image_to_handle(img->parent);
    else
       return image;
 }
@@ -285,8 +286,8 @@ void vegaCopyImage(VGImage dst, VGint dx, VGint dy,
       return;
    }
    vg_validate_state(ctx);
-   image_copy((struct vg_image*)dst, dx, dy,
-              (struct vg_image*)src, sx, sy,
+   image_copy(handle_to_image(dst), dx, dy,
+              handle_to_image(src), sx, sy,
               width, height, dither);
 }
 
@@ -303,7 +304,7 @@ void vegaDrawImage(VGImage image)
    }
 
    vg_validate_state(ctx);
-   image_draw((struct vg_image*)image,
+   image_draw(handle_to_image(image),
          &ctx->state.vg.image_user_to_surface_matrix);
 }
 
@@ -323,7 +324,7 @@ void vegaSetPixels(VGint dx, VGint dy,
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       return;
    }
-   image_set_pixels(dx, dy, (struct vg_image*)src, sx, sy, width,
+   image_set_pixels(dx, dy, handle_to_image(src), sx, sy, width,
                     height);
 }
 
@@ -343,7 +344,7 @@ void vegaGetPixels(VGImage dst, VGint dx, VGint dy,
       return;
    }
 
-   img = (struct vg_image*)dst;
+   img = handle_to_image(dst);
 
    image_get_pixels(img, dx, dy,
                     sx, sy, width, height);
@@ -487,7 +488,7 @@ void vegaCopyPixels(VGint dx, VGint dy,
 
    vg_validate_state(ctx);
    /* make sure rendering has completed */
-   vgFinish();
+   vegaFinish();
 
    vg_copy_surface(ctx, strb->surface, dx, dy,
                    strb->surface, sx, sy, width, height);
index d96afe663874f1f0b29b07ebe9a20d5105197691..cdbf0026e8977b0569de298da886f2dabeb3df18 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "mask.h"
 #include "api.h"
+#include "handle.h"
 #include "renderer.h"
 
 #include "vg_context.h"
@@ -56,11 +57,11 @@ void vegaMask(VGHandle mask, VGMaskOperation operation,
       mask_fill(x, y, width, height, 0.f);
    } else if (operation == VG_FILL_MASK) {
       mask_fill(x, y, width, height, 1.f);
-   } else if (vg_object_is_valid((void*)mask, VG_OBJECT_IMAGE)) {
-      struct vg_image *image = (struct vg_image *)mask;
+   } else if (vg_object_is_valid(mask, VG_OBJECT_IMAGE)) {
+      struct vg_image *image = handle_to_image(mask);
       mask_using_image(image, operation, x, y, width, height);
-   } else if (vg_object_is_valid((void*)mask, VG_OBJECT_MASK)) {
-      struct vg_mask_layer *layer = (struct vg_mask_layer *)mask;
+   } else if (vg_object_is_valid(mask, VG_OBJECT_MASK)) {
+      struct vg_mask_layer *layer = handle_to_masklayer(mask);
       mask_using_layer(layer, operation, x, y, width, height);
    } else {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
@@ -123,14 +124,14 @@ void vegaRenderToMask(VGPath path,
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       return;
    }
-   if (!vg_object_is_valid((void*)path, VG_OBJECT_PATH)) {
+   if (!vg_object_is_valid(path, VG_OBJECT_PATH)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
 
    vg_validate_state(ctx);
 
-   mask_render_to((struct path *)path, paintModes, operation);
+   mask_render_to(handle_to_path(path), paintModes, operation);
 }
 
 VGMaskLayer vegaCreateMaskLayer(VGint width, VGint height)
@@ -138,13 +139,13 @@ VGMaskLayer vegaCreateMaskLayer(VGint width, VGint height)
    struct vg_context *ctx = vg_current_context();
 
    if (width <= 0 || height <= 0 ||
-       width > vgGeti(VG_MAX_IMAGE_WIDTH) ||
-       height > vgGeti(VG_MAX_IMAGE_HEIGHT)) {
+       width > vegaGeti(VG_MAX_IMAGE_WIDTH) ||
+       height > vegaGeti(VG_MAX_IMAGE_HEIGHT)) {
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       return VG_INVALID_HANDLE;
    }
 
-   return (VGMaskLayer)mask_layer_create(width, height);
+   return masklayer_to_handle(mask_layer_create(width, height));
 }
 
 void vegaDestroyMaskLayer(VGMaskLayer maskLayer)
@@ -156,12 +157,12 @@ void vegaDestroyMaskLayer(VGMaskLayer maskLayer)
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
-   if (!vg_object_is_valid((void*)maskLayer, VG_OBJECT_MASK)) {
+   if (!vg_object_is_valid(maskLayer, VG_OBJECT_MASK)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
 
-   mask = (struct vg_mask_layer *)maskLayer;
+   mask = handle_to_masklayer(maskLayer);
    mask_layer_destroy(mask);
 }
 
@@ -192,12 +193,12 @@ void vegaFillMaskLayer(VGMaskLayer maskLayer,
       return;
    }
 
-   if (!vg_object_is_valid((void*)maskLayer, VG_OBJECT_MASK)) {
+   if (!vg_object_is_valid(maskLayer, VG_OBJECT_MASK)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
 
-   mask = (struct vg_mask_layer*)maskLayer;
+   mask = handle_to_masklayer(maskLayer);
 
    if (x + width > mask_layer_width(mask) ||
        y + height > mask_layer_height(mask)) {
@@ -226,14 +227,14 @@ void vegaCopyMask(VGMaskLayer maskLayer,
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       return;
    }
-   if (!vg_object_is_valid((void*)maskLayer, VG_OBJECT_MASK)) {
+   if (!vg_object_is_valid(maskLayer, VG_OBJECT_MASK)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
 
    vg_validate_state(ctx);
 
-   mask = (struct vg_mask_layer*)maskLayer;
+   mask = handle_to_masklayer(maskLayer);
    mask_copy(mask, sx, sy, dx, dy, width, height);
 }
 
index 1411806455cfa032e01cf4b5720e46d42b70d8ef..2610ebe0576ee2d763af3db22b6a4bd2ad7c359a 100644 (file)
 #include "vg_context.h"
 #include "paint.h"
 #include "api.h"
+#include "handle.h"
+
 
 VGPaint vegaCreatePaint(void)
 {
-   return (VGPaint) paint_create(vg_current_context());
+   return paint_to_handle(paint_create(vg_current_context()));
 }
 
 void vegaDestroyPaint(VGPaint p)
 {
    struct vg_context *ctx = vg_current_context();
-   struct vg_paint *paint;
 
    if (p == VG_INVALID_HANDLE) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
 
-   paint = (struct vg_paint *)p;
-   paint_destroy(paint);
+   paint_destroy(handle_to_paint(p));
 }
 
 void vegaSetPaint(VGPaint paint, VGbitfield paintModes)
@@ -55,8 +55,8 @@ void vegaSetPaint(VGPaint paint, VGbitfield paintModes)
 
    if (paint == VG_INVALID_HANDLE) {
       /* restore the default */
-      paint = (VGPaint)ctx->default_paint;
-   } else if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT)) {
+      paint = paint_to_handle(ctx->default_paint);
+   } else if (!vg_object_is_valid(paint, VG_OBJECT_PAINT)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
@@ -67,11 +67,13 @@ void vegaSetPaint(VGPaint paint, VGbitfield paintModes)
    }
 
    if (paintModes & VG_FILL_PATH) {
-      ctx->state.vg.fill_paint = (struct vg_paint *)paint;
+      ctx->state.vg.fill_paint = handle_to_paint(paint);
    }
    if (paintModes & VG_STROKE_PATH) {
-      ctx->state.vg.stroke_paint = (struct vg_paint *)paint;
+      ctx->state.vg.stroke_paint = handle_to_paint(paint);
    }
+
+   ctx->state.dirty |= PAINT_DIRTY;
 }
 
 VGPaint vegaGetPaint(VGPaintMode paintMode)
@@ -85,11 +87,11 @@ VGPaint vegaGetPaint(VGPaintMode paintMode)
    }
 
    if (paintMode == VG_FILL_PATH)
-      paint = (VGPaint)ctx->state.vg.fill_paint;
+      paint = paint_to_handle(ctx->state.vg.fill_paint);
    else if (paintMode == VG_STROKE_PATH)
-      paint = (VGPaint)ctx->state.vg.stroke_paint;
+      paint = paint_to_handle(ctx->state.vg.stroke_paint);
 
-   if (paint == (VGPaint)ctx->default_paint)
+   if (paint == paint_to_handle(ctx->default_paint))
       paint = VG_INVALID_HANDLE;
 
    return paint;
@@ -98,20 +100,24 @@ VGPaint vegaGetPaint(VGPaintMode paintMode)
 void vegaSetColor(VGPaint paint, VGuint rgba)
 {
    struct vg_context *ctx = vg_current_context();
+   struct vg_paint *p;
 
    if (paint == VG_INVALID_HANDLE) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
 
-   if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT)) {
+   if (!vg_object_is_valid(paint, VG_OBJECT_PAINT)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
-   {
-      struct vg_paint *p = (struct vg_paint *)paint;
-      paint_set_colori(p, rgba);
-   }
+
+   p = handle_to_paint(paint);
+   paint_set_colori(p, rgba);
+
+   if (ctx->state.vg.fill_paint == p ||
+       ctx->state.vg.stroke_paint == p)
+      ctx->state.dirty |= PAINT_DIRTY;
 }
 
 VGuint vegaGetColor(VGPaint paint)
@@ -125,11 +131,11 @@ VGuint vegaGetColor(VGPaint paint)
       return rgba;
    }
 
-   if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT)) {
+   if (!vg_object_is_valid(paint, VG_OBJECT_PAINT)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return rgba;
    }
-   p = (struct vg_paint *)paint;
+   p = handle_to_paint(paint);
 
    return paint_colori(p);
 }
@@ -139,28 +145,28 @@ void vegaPaintPattern(VGPaint paint, VGImage pattern)
    struct vg_context *ctx = vg_current_context();
 
    if (paint == VG_INVALID_HANDLE ||
-       !vg_context_is_object_valid(ctx, VG_OBJECT_PAINT, (void *)paint)) {
+       !vg_context_is_object_valid(ctx, VG_OBJECT_PAINT, paint)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
 
    if (pattern == VG_INVALID_HANDLE) {
-      paint_set_type((struct vg_paint*)paint, VG_PAINT_TYPE_COLOR);
+      paint_set_type(handle_to_paint(paint), VG_PAINT_TYPE_COLOR);
       return;
    }
 
-   if (!vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void *)pattern)) {
+   if (!vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, pattern)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
 
 
-   if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT) ||
-       !vg_object_is_valid((void*)pattern, VG_OBJECT_IMAGE)) {
+   if (!vg_object_is_valid(paint, VG_OBJECT_PAINT) ||
+       !vg_object_is_valid(pattern, VG_OBJECT_IMAGE)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
-   paint_set_pattern((struct vg_paint*)paint,
-                     (struct vg_image*)pattern);
+   paint_set_pattern(handle_to_paint(paint),
+                     handle_to_image(pattern));
 }
 
index a73b6c3effead5f3ea5aea4711f40155379ef7dc..aa1e5dd280aabd7e0b4ff1fddc6e97d95e12dfaa 100644 (file)
@@ -29,6 +29,7 @@
 #include "vg_context.h"
 #include "paint.h"
 #include "path.h"
+#include "handle.h"
 #include "image.h"
 #include "text.h"
 #include "matrix.h"
@@ -60,7 +61,7 @@ static INLINE VGboolean count_in_bounds(VGParamType type, VGint count)
    else if (type == VG_STROKE_DASH_PATTERN) {
       return count <= VEGA_MAX_DASH_COUNT;
    } else {
-      VGint real_count = vgGetVectorSize(type);
+      VGint real_count = vegaGetVectorSize(type);
       return count == real_count;
    }
 }
@@ -103,7 +104,7 @@ void vegaSetf (VGParamType type, VGfloat value)
    case VG_MAX_IMAGE_BYTES:
    case VG_MAX_GAUSSIAN_STD_DEVIATION:
    case VG_MAX_FLOAT:
-      vgSeti(type, floor(value));
+      vegaSeti(type, floor(value));
       return;
       break;
    case VG_STROKE_LINE_WIDTH:
@@ -289,7 +290,7 @@ void vegaSetfv(VGParamType type, VGint count,
    case VG_FILTER_FORMAT_LINEAR:
    case VG_FILTER_FORMAT_PREMULTIPLIED:
    case VG_FILTER_CHANNEL_MASK:
-      vgSeti(type, floor(values[0]));
+      vegaSeti(type, floor(values[0]));
       return;
       break;
    case VG_SCISSOR_RECTS: {
@@ -416,7 +417,7 @@ void vegaSetiv(VGParamType type, VGint count,
    case VG_FILTER_FORMAT_LINEAR:
    case VG_FILTER_FORMAT_PREMULTIPLIED:
    case VG_FILTER_CHANNEL_MASK:
-      vgSeti(type, values[0]);
+      vegaSeti(type, values[0]);
       return;
       break;
    case VG_SCISSOR_RECTS: {
@@ -536,7 +537,7 @@ VGfloat vegaGetf(VGParamType type)
    case VG_FILTER_FORMAT_LINEAR:
    case VG_FILTER_FORMAT_PREMULTIPLIED:
    case VG_FILTER_CHANNEL_MASK:
-      return vgGeti(type);
+      return vegaGeti(type);
       break;
    case VG_STROKE_LINE_WIDTH:
       value = state->stroke.line_width.f;
@@ -558,7 +559,7 @@ VGfloat vegaGetf(VGParamType type)
    case VG_MAX_IMAGE_PIXELS:
    case VG_MAX_IMAGE_BYTES:
    case VG_MAX_GAUSSIAN_STD_DEVIATION:
-      return vgGeti(type);
+      return vegaGeti(type);
       break;
    case VG_MAX_FLOAT:
       value = 1e+10;/*must be at least 1e+10*/
@@ -674,7 +675,7 @@ VGint vegaGeti(VGParamType type)
       break;
 
    case VG_MAX_FLOAT: {
-      VGfloat val = vgGetf(type);
+      VGfloat val = vegaGetf(type);
       value = float_to_int_floor(*((VGuint*)&val));
    }
       break;
@@ -765,7 +766,7 @@ void vegaGetfv(VGParamType type, VGint count,
 {
    const struct vg_state *state = current_state();
    struct vg_context *ctx = vg_current_context();
-   VGint real_count = vgGetVectorSize(type);
+   VGint real_count = vegaGetVectorSize(type);
 
    if (!values || count <= 0 || count > real_count || !is_aligned(values)) {
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
@@ -802,10 +803,10 @@ void vegaGetfv(VGParamType type, VGint count,
    case VG_MAX_IMAGE_PIXELS:
    case VG_MAX_IMAGE_BYTES:
    case VG_MAX_GAUSSIAN_STD_DEVIATION:
-      values[0] = vgGeti(type);
+      values[0] = vegaGeti(type);
       break;
    case VG_MAX_FLOAT:
-      values[0] = vgGetf(type);
+      values[0] = vegaGetf(type);
       break;
    case VG_SCISSOR_RECTS: {
       VGint i;
@@ -866,7 +867,7 @@ void vegaGetiv(VGParamType type, VGint count,
 {
    const struct vg_state *state = current_state();
    struct vg_context *ctx = vg_current_context();
-   VGint real_count = vgGetVectorSize(type);
+   VGint real_count = vegaGetVectorSize(type);
 
    if (!values || count <= 0 || count > real_count || !is_aligned(values)) {
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
@@ -903,10 +904,10 @@ void vegaGetiv(VGParamType type, VGint count,
    case VG_MAX_IMAGE_PIXELS:
    case VG_MAX_IMAGE_BYTES:
    case VG_MAX_GAUSSIAN_STD_DEVIATION:
-      values[0] = vgGeti(type);
+      values[0] = vegaGeti(type);
       break;
    case VG_MAX_FLOAT: {
-      VGfloat val = vgGetf(type);
+      VGfloat val = vegaGetf(type);
       values[0] = float_to_int_floor(*((VGuint*)&val));
    }
       break;
@@ -972,9 +973,9 @@ void vegaSetParameterf(VGHandle object,
                        VGfloat value)
 {
    struct vg_context *ctx = vg_current_context();
-   void *ptr = (void*)object;
+   void *ptr = handle_to_pointer(object);
 
-   if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
+   if (object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
@@ -983,7 +984,7 @@ void vegaSetParameterf(VGHandle object,
    case VG_PAINT_TYPE:
    case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
    case VG_PAINT_PATTERN_TILING_MODE:
-      vgSetParameteri(object, paramType, floor(value));
+      vegaSetParameteri(object, paramType, floor(value));
       return;
       break;
    case VG_PAINT_COLOR:
@@ -994,7 +995,7 @@ void vegaSetParameterf(VGHandle object,
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       break;
    case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: {
-      struct vg_paint *p = (struct vg_paint *)object;
+      struct vg_paint *p = handle_to_paint(object);
       paint_set_color_ramp_premultiplied(p, value);
    }
       break;
@@ -1026,9 +1027,9 @@ void vegaSetParameteri(VGHandle object,
                        VGint value)
 {
    struct vg_context *ctx = vg_current_context();
-   void *ptr = (void*)object;
+   void *ptr = handle_to_pointer(object);
 
-   if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
+   if (object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
@@ -1039,7 +1040,7 @@ void vegaSetParameteri(VGHandle object,
           value > VG_PAINT_TYPE_PATTERN)
          vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       else {
-         struct vg_paint *paint = (struct vg_paint *)ptr;
+         struct vg_paint *paint = handle_to_paint(object);
          paint_set_type(paint, value);
       }
       break;
@@ -1055,12 +1056,12 @@ void vegaSetParameteri(VGHandle object,
           value > VG_COLOR_RAMP_SPREAD_REFLECT)
          vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       else {
-         struct vg_paint *paint = (struct vg_paint *)ptr;
+         struct vg_paint *paint = handle_to_paint(object);
          paint_set_spread_mode(paint, value);
       }
       break;
    case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: {
-      struct vg_paint *p = (struct vg_paint *)object;
+      struct vg_paint *p = handle_to_paint(object);
       paint_set_color_ramp_premultiplied(p, value);
    }
       break;
@@ -1069,7 +1070,7 @@ void vegaSetParameteri(VGHandle object,
           value > VG_TILE_REFLECT)
          vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       else {
-         struct vg_paint *paint = (struct vg_paint *)ptr;
+         struct vg_paint *paint = handle_to_paint(object);
          paint_set_pattern_tiling(paint, value);
       }
       break;
@@ -1102,10 +1103,10 @@ void vegaSetParameterfv(VGHandle object,
                         const VGfloat * values)
 {
    struct vg_context *ctx = vg_current_context();
-   void *ptr = (void*)object;
-   VGint real_count = vgGetParameterVectorSize(object, paramType);
+   void *ptr = handle_to_pointer(object);
+   VGint real_count = vegaGetParameterVectorSize(object, paramType);
 
-   if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
+   if (object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
@@ -1125,15 +1126,18 @@ void vegaSetParameterfv(VGHandle object,
       if (count != 1)
          vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       else
-         vgSetParameterf(object, paramType, values[0]);
+         vegaSetParameterf(object, paramType, values[0]);
       return;
       break;
    case VG_PAINT_COLOR: {
       if (count != 4)
          vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       else {
-         struct vg_paint *paint = (struct vg_paint *)object;
+         struct vg_paint *paint = handle_to_paint(object);
          paint_set_color(paint, values);
+         if (ctx->state.vg.fill_paint == paint ||
+             ctx->state.vg.stroke_paint == paint)
+            ctx->state.dirty |= PAINT_DIRTY;
       }
    }
       break;
@@ -1141,7 +1145,7 @@ void vegaSetParameterfv(VGHandle object,
       if (count && count < 4)
          vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       else {
-         struct vg_paint *paint = (struct vg_paint *)object;
+         struct vg_paint *paint = handle_to_paint(object);
          count = MIN2(count, VEGA_MAX_COLOR_RAMP_STOPS);
          paint_set_ramp_stops(paint, values, count);
          {
@@ -1159,7 +1163,7 @@ void vegaSetParameterfv(VGHandle object,
       if (count != 4)
          vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       else {
-         struct vg_paint *paint = (struct vg_paint *)object;
+         struct vg_paint *paint = handle_to_paint(object);
          paint_set_linear_gradient(paint, values);
          {
             VGint vals[4];
@@ -1176,7 +1180,7 @@ void vegaSetParameterfv(VGHandle object,
       if (count != 5)
          vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       else {
-         struct vg_paint *paint = (struct vg_paint *)object;
+         struct vg_paint *paint = handle_to_paint(object);
          paint_set_radial_gradient(paint, values);
          {
             VGint vals[5];
@@ -1215,10 +1219,10 @@ void vegaSetParameteriv(VGHandle object,
                         const VGint * values)
 {
    struct vg_context *ctx = vg_current_context();
-   void *ptr = (void*)object;
-   VGint real_count = vgGetParameterVectorSize(object, paramType);
+   void *ptr = handle_to_pointer(object);
+   VGint real_count = vegaGetParameterVectorSize(object, paramType);
 
-   if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
+   if (object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
@@ -1238,15 +1242,18 @@ void vegaSetParameteriv(VGHandle object,
       if (count != 1)
          vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       else
-         vgSetParameteri(object, paramType, values[0]);
+         vegaSetParameteri(object, paramType, values[0]);
       return;
       break;
    case VG_PAINT_COLOR: {
       if (count != 4)
          vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       else {
-         struct vg_paint *paint = (struct vg_paint *)object;
+         struct vg_paint *paint = handle_to_paint(object);
          paint_set_coloriv(paint, values);
+         if (ctx->state.vg.fill_paint == paint ||
+             ctx->state.vg.stroke_paint == paint)
+            ctx->state.dirty |= PAINT_DIRTY;
       }
    }
       break;
@@ -1256,7 +1263,7 @@ void vegaSetParameteriv(VGHandle object,
       else {
          VGfloat *vals = 0;
          int i;
-         struct vg_paint *paint = (struct vg_paint *)object;
+         struct vg_paint *paint = handle_to_paint(object);
          if (count) {
             vals = malloc(sizeof(VGfloat)*count);
             for (i = 0; i < count; ++i)
@@ -1274,7 +1281,7 @@ void vegaSetParameteriv(VGHandle object,
          vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       else {
          VGfloat vals[4];
-         struct vg_paint *paint = (struct vg_paint *)object;
+         struct vg_paint *paint = handle_to_paint(object);
          vals[0] = values[0];
          vals[1] = values[1];
          vals[2] = values[2];
@@ -1289,7 +1296,7 @@ void vegaSetParameteriv(VGHandle object,
          vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       else {
          VGfloat vals[5];
-         struct vg_paint *paint = (struct vg_paint *)object;
+         struct vg_paint *paint = handle_to_paint(object);
          vals[0] = values[0];
          vals[1] = values[1];
          vals[2] = values[2];
@@ -1318,9 +1325,8 @@ VGint vegaGetParameterVectorSize(VGHandle object,
                                  VGint paramType)
 {
    struct vg_context *ctx = vg_current_context();
-   void *ptr = (void*)object;
 
-   if (!ptr || object == VG_INVALID_HANDLE) {
+   if (object == VG_INVALID_HANDLE) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return 0;
    }
@@ -1334,7 +1340,7 @@ VGint vegaGetParameterVectorSize(VGHandle object,
    case VG_PAINT_COLOR:
       return 4;
    case VG_PAINT_COLOR_RAMP_STOPS: {
-      struct vg_paint *p = (struct vg_paint *)object;
+      struct vg_paint *p = handle_to_paint(object);
       return paint_num_ramp_stops(p);
    }
       break;
@@ -1374,9 +1380,8 @@ VGfloat vegaGetParameterf(VGHandle object,
                           VGint paramType)
 {
    struct vg_context *ctx = vg_current_context();
-   void *ptr = (void*)object;
 
-   if (!ptr || object == VG_INVALID_HANDLE) {
+   if (object == VG_INVALID_HANDLE) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return 0;
    }
@@ -1386,7 +1391,7 @@ VGfloat vegaGetParameterf(VGHandle object,
    case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
    case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
    case VG_PAINT_PATTERN_TILING_MODE:
-      return vgGetParameteri(object, paramType);
+      return vegaGetParameteri(object, paramType);
       break;
    case VG_PAINT_COLOR:
    case VG_PAINT_COLOR_RAMP_STOPS:
@@ -1398,17 +1403,17 @@ VGfloat vegaGetParameterf(VGHandle object,
    case VG_PATH_FORMAT:
       return VG_PATH_FORMAT_STANDARD;
    case VG_PATH_SCALE: {
-      struct path *p = (struct path*)object;
+      struct path *p = handle_to_path(object);
       return path_scale(p);
    }
    case VG_PATH_BIAS: {
-      struct path *p = (struct path*)object;
+      struct path *p = handle_to_path(object);
       return path_bias(p);
    }
    case VG_PATH_DATATYPE:
    case VG_PATH_NUM_SEGMENTS:
    case VG_PATH_NUM_COORDS:
-      return vgGetParameteri(object, paramType);
+      return vegaGetParameteri(object, paramType);
       break;
 
    case VG_IMAGE_FORMAT:
@@ -1416,7 +1421,7 @@ VGfloat vegaGetParameterf(VGHandle object,
    case VG_IMAGE_HEIGHT:
 #ifdef OPENVG_VERSION_1_1
    case VG_FONT_NUM_GLYPHS: 
-      return vgGetParameteri(object, paramType);
+      return vegaGetParameteri(object, paramType);
       break;
 #endif
 
@@ -1431,30 +1436,29 @@ VGint vegaGetParameteri(VGHandle object,
                         VGint paramType)
 {
    struct vg_context *ctx = vg_current_context();
-   void *ptr = (void*)object;
 
-   if (!ptr || object == VG_INVALID_HANDLE) {
+   if (object == VG_INVALID_HANDLE) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return 0;
    }
 
    switch(paramType) {
    case VG_PAINT_TYPE: {
-         struct vg_paint *paint = (struct vg_paint *)ptr;
+         struct vg_paint *paint = handle_to_paint(object);
          return paint_type(paint);
    }
       break;
    case VG_PAINT_COLOR_RAMP_SPREAD_MODE: {
-      struct vg_paint *p = (struct vg_paint *)object;
+      struct vg_paint *p = handle_to_paint(object);
       return paint_spread_mode(p);
    }
    case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: {
-      struct vg_paint *p = (struct vg_paint *)object;
+      struct vg_paint *p = handle_to_paint(object);
       return paint_color_ramp_premultiplied(p);
    }
       break;
    case VG_PAINT_PATTERN_TILING_MODE: {
-      struct vg_paint *p = (struct vg_paint *)object;
+      struct vg_paint *p = handle_to_paint(object);
       return paint_pattern_tiling(p);
    }
       break;
@@ -1469,40 +1473,40 @@ VGint vegaGetParameteri(VGHandle object,
       return VG_PATH_FORMAT_STANDARD;
    case VG_PATH_SCALE:
    case VG_PATH_BIAS:
-      return vgGetParameterf(object, paramType);
+      return vegaGetParameterf(object, paramType);
    case VG_PATH_DATATYPE: {
-      struct path *p = (struct path*)object;
+      struct path *p = handle_to_path(object);
       return path_datatype(p);
    }
    case VG_PATH_NUM_SEGMENTS: {
-      struct path *p = (struct path*)object;
+      struct path *p = handle_to_path(object);
       return path_num_segments(p);
    }
    case VG_PATH_NUM_COORDS: {
-      struct path *p = (struct path*)object;
+      struct path *p = handle_to_path(object);
       return path_num_coords(p);
    }
       break;
 
    case VG_IMAGE_FORMAT: {
-      struct vg_image *img = (struct vg_image*)object;
+      struct vg_image *img = handle_to_image(object);
       return img->format;
    }
       break;
    case VG_IMAGE_WIDTH: {
-      struct vg_image *img = (struct vg_image*)object;
+      struct vg_image *img = handle_to_image(object);
       return img->width;
    }
       break;
    case VG_IMAGE_HEIGHT: {
-      struct vg_image *img = (struct vg_image*)object;
+      struct vg_image *img = handle_to_image(object);
       return img->height;
    }
       break;
 
 #ifdef OPENVG_VERSION_1_1
    case VG_FONT_NUM_GLYPHS: {
-      struct vg_font *font = (struct vg_font*)object;
+      struct vg_font *font = handle_to_font(object);
       return font_num_glyphs(font);
    }
       break;
@@ -1521,10 +1525,9 @@ void vegaGetParameterfv(VGHandle object,
                         VGfloat * values)
 {
    struct vg_context *ctx = vg_current_context();
-   void *ptr = (void*)object;
-   VGint real_count = vgGetParameterVectorSize(object, paramType);
+   VGint real_count = vegaGetParameterVectorSize(object, paramType);
 
-   if (!ptr || object == VG_INVALID_HANDLE) {
+   if (object == VG_INVALID_HANDLE) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
@@ -1537,41 +1540,41 @@ void vegaGetParameterfv(VGHandle object,
 
    switch(paramType) {
    case VG_PAINT_TYPE: {
-      struct vg_paint *p = (struct vg_paint *)object;
+      struct vg_paint *p = handle_to_paint(object);
       values[0] = paint_type(p);
    }
       break;
    case VG_PAINT_COLOR_RAMP_SPREAD_MODE: {
-      struct vg_paint *p = (struct vg_paint *)object;
+      struct vg_paint *p = handle_to_paint(object);
       values[0] = paint_spread_mode(p);
    }
       break;
    case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: {
-      struct vg_paint *p = (struct vg_paint *)object;
+      struct vg_paint *p = handle_to_paint(object);
       values[0] = paint_color_ramp_premultiplied(p);
    }
       break;
    case VG_PAINT_PATTERN_TILING_MODE: {
-      values[0] = vgGetParameterf(object, paramType);
+      values[0] = vegaGetParameterf(object, paramType);
    }
       break;
    case VG_PAINT_COLOR: {
-      struct vg_paint *paint = (struct vg_paint *)object;
+      struct vg_paint *paint = handle_to_paint(object);
       paint_get_color(paint, values);
    }
       break;
    case VG_PAINT_COLOR_RAMP_STOPS: {
-      struct vg_paint *paint = (struct vg_paint *)object;
+      struct vg_paint *paint = handle_to_paint(object);
       paint_ramp_stops(paint, values, count);
    }
       break;
    case VG_PAINT_LINEAR_GRADIENT: {
-      struct vg_paint *paint = (struct vg_paint *)object;
+      struct vg_paint *paint = handle_to_paint(object);
       paint_linear_gradient(paint, values);
    }
       break;
    case VG_PAINT_RADIAL_GRADIENT: {
-      struct vg_paint *paint = (struct vg_paint *)object;
+      struct vg_paint *paint = handle_to_paint(object);
       paint_radial_gradient(paint, values);
    }
       break;
@@ -1580,11 +1583,11 @@ void vegaGetParameterfv(VGHandle object,
    case VG_PATH_DATATYPE:
    case VG_PATH_NUM_SEGMENTS:
    case VG_PATH_NUM_COORDS:
-      values[0] = vgGetParameteri(object, paramType);
+      values[0] = vegaGetParameteri(object, paramType);
       break;
    case VG_PATH_SCALE:
    case VG_PATH_BIAS:
-      values[0] = vgGetParameterf(object, paramType);
+      values[0] = vegaGetParameterf(object, paramType);
       break;
 
    case VG_IMAGE_FORMAT:
@@ -1592,7 +1595,7 @@ void vegaGetParameterfv(VGHandle object,
    case VG_IMAGE_HEIGHT:
 #ifdef OPENVG_VERSION_1_1
    case VG_FONT_NUM_GLYPHS:
-      values[0] = vgGetParameteri(object, paramType);
+      values[0] = vegaGetParameteri(object, paramType);
       break;
 #endif
 
@@ -1608,10 +1611,9 @@ void vegaGetParameteriv(VGHandle object,
                         VGint * values)
 {
    struct vg_context *ctx = vg_current_context();
-   void *ptr = (void*)object;
-   VGint real_count = vgGetParameterVectorSize(object, paramType);
+   VGint real_count = vegaGetParameterVectorSize(object, paramType);
 
-   if (!ptr || object == VG_INVALID_HANDLE) {
+   if (object || object == VG_INVALID_HANDLE) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
@@ -1629,45 +1631,45 @@ void vegaGetParameteriv(VGHandle object,
    case VG_PAINT_PATTERN_TILING_MODE:
 #ifdef OPENVG_VERSION_1_1
    case VG_FONT_NUM_GLYPHS:
-      values[0] = vgGetParameteri(object, paramType);
+      values[0] = vegaGetParameteri(object, paramType);
       break;
 #endif
    case VG_PAINT_COLOR: {
-      struct vg_paint *paint = (struct vg_paint *)object;
+      struct vg_paint *paint = handle_to_paint(object);
       paint_get_coloriv(paint, values);
    }
       break;
    case VG_PAINT_COLOR_RAMP_STOPS: {
-      struct vg_paint *paint = (struct vg_paint *)object;
+      struct vg_paint *paint = handle_to_paint(object);
       paint_ramp_stopsi(paint, values, count);
    }
       break;
    case VG_PAINT_LINEAR_GRADIENT: {
-      struct vg_paint *paint = (struct vg_paint *)object;
+      struct vg_paint *paint = handle_to_paint(object);
       paint_linear_gradienti(paint, values);
    }
       break;
    case VG_PAINT_RADIAL_GRADIENT: {
-      struct vg_paint *paint = (struct vg_paint *)object;
+      struct vg_paint *paint = handle_to_paint(object);
       paint_radial_gradienti(paint, values);
    }
       break;
 
    case VG_PATH_SCALE:
    case VG_PATH_BIAS:
-      values[0] = vgGetParameterf(object, paramType);
+      values[0] = vegaGetParameterf(object, paramType);
       break;
    case VG_PATH_FORMAT:
    case VG_PATH_DATATYPE:
    case VG_PATH_NUM_SEGMENTS:
    case VG_PATH_NUM_COORDS:
-      values[0] = vgGetParameteri(object, paramType);
+      values[0] = vegaGetParameteri(object, paramType);
       break;
 
    case VG_IMAGE_FORMAT:
    case VG_IMAGE_WIDTH:
    case VG_IMAGE_HEIGHT:
-      values[0] = vgGetParameteri(object, paramType);
+      values[0] = vegaGetParameteri(object, paramType);
       break;
 
    default:
index fe57b7671d95513b8a664ff24eb535abcefed068..ab6ce958945d71db883dea2d3308b47dc1a5b27c 100644 (file)
@@ -27,6 +27,7 @@
 #include "VG/openvg.h"
 
 #include "vg_context.h"
+#include "handle.h"
 #include "path.h"
 #include "api.h"
 
@@ -55,9 +56,9 @@ VGPath vegaCreatePath(VGint pathFormat,
       return VG_INVALID_HANDLE;
    }
 
-   return (VGPath)path_create(datatype, scale, bias,
-                              segmentCapacityHint, coordCapacityHint,
-                              capabilities);
+   return path_to_handle(path_create(datatype, scale, bias,
+                                     segmentCapacityHint, coordCapacityHint,
+                                     capabilities));
 }
 
 void vegaClearPath(VGPath path, VGbitfield capabilities)
@@ -70,7 +71,7 @@ void vegaClearPath(VGPath path, VGbitfield capabilities)
       return;
    }
 
-   p = (struct path *)path;
+   p = handle_to_path(path);
    path_clear(p, capabilities);
 }
 
@@ -84,7 +85,7 @@ void vegaDestroyPath(VGPath p)
       return;
    }
 
-   path = (struct path *)p;
+   path = handle_to_path(p);
    path_destroy(path);
 }
 
@@ -100,7 +101,7 @@ void vegaRemovePathCapabilities(VGPath path,
       return;
    }
 
-   p = (struct path*)path;
+   p = handle_to_path(path);
    current = path_capabilities(p);
    path_set_capabilities(p, (current &
                              (~(capabilities & VG_PATH_CAPABILITY_ALL))));
@@ -115,7 +116,7 @@ VGbitfield vegaGetPathCapabilities(VGPath path)
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return 0;
    }
-   p = (struct path*)path;
+   p = handle_to_path(path);
    return path_capabilities(p);
 }
 
@@ -128,8 +129,8 @@ void vegaAppendPath(VGPath dstPath, VGPath srcPath)
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
-   src = (struct path *)srcPath;
-   dst = (struct path *)dstPath;
+   src = handle_to_path(srcPath);
+   dst = handle_to_path(dstPath);
 
    if (!(path_capabilities(src) & VG_PATH_CAPABILITY_APPEND_FROM) ||
        !(path_capabilities(dst) & VG_PATH_CAPABILITY_APPEND_TO)) {
@@ -167,9 +168,9 @@ void vegaAppendPathData(VGPath dstPath,
       }
    }
 
-   p = (struct path*)dstPath;
+   p = handle_to_path(dstPath);
 
-   if (!pathData || !is_aligned_to(pathData, path_datatype_size(p))) {
+   if (!p || !is_aligned_to(p, path_datatype_size(p))) {
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       return;
    }
@@ -199,7 +200,7 @@ void vegaModifyPathCoords(VGPath dstPath,
       return;
    }
 
-   p = (struct path *)dstPath;
+   p = handle_to_path(dstPath);
 
    if (!pathData || !is_aligned_to(pathData, path_datatype_size(p))) {
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
@@ -226,8 +227,8 @@ void vegaTransformPath(VGPath dstPath, VGPath srcPath)
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
-   src = (struct path *)srcPath;
-   dst = (struct path *)dstPath;
+   src = handle_to_path(srcPath);
+   dst = handle_to_path(dstPath);
 
    if (!(path_capabilities(src) & VG_PATH_CAPABILITY_TRANSFORM_FROM) ||
        !(path_capabilities(dst) & VG_PATH_CAPABILITY_TRANSFORM_TO)) {
@@ -251,9 +252,9 @@ VGboolean vegaInterpolatePath(VGPath dstPath,
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return VG_FALSE;
    }
-   dst = (struct path *)dstPath;
-   start = (struct path *)startPath;
-   end = (struct path *)endPath;
+   dst = handle_to_path(dstPath);
+   start = handle_to_path(startPath);
+   end = handle_to_path(endPath);
 
    if (!(path_capabilities(dst) & VG_PATH_CAPABILITY_INTERPOLATE_TO) ||
        !(path_capabilities(start) & VG_PATH_CAPABILITY_INTERPOLATE_FROM) ||
@@ -285,7 +286,7 @@ VGfloat vegaPathLength(VGPath path,
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       return -1;
    }
-   p = (struct path*)path;
+   p = handle_to_path(path);
 
    if (!(path_capabilities(p) & VG_PATH_CAPABILITY_PATH_LENGTH)) {
       vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
@@ -330,7 +331,7 @@ void vegaPointAlongPath(VGPath path,
       return;
    }
 
-   p = (struct path*)path;
+   p = handle_to_path(path);
 
    caps = path_capabilities(p);
    if (!(caps & VG_PATH_CAPABILITY_POINT_ALONG_PATH) ||
@@ -385,7 +386,7 @@ void vegaPathBounds(VGPath path,
       return;
    }
 
-   p = (struct path*)path;
+   p = handle_to_path(path);
 
    caps = path_capabilities(p);
    if (!(caps & VG_PATH_CAPABILITY_PATH_BOUNDS)) {
@@ -422,7 +423,7 @@ void vegaPathTransformedBounds(VGPath path,
       return;
    }
 
-   p = (struct path*)path;
+   p = handle_to_path(path);
 
    caps = path_capabilities(p);
    if (!(caps & VG_PATH_CAPABILITY_PATH_TRANSFORMED_BOUNDS)) {
@@ -466,6 +467,7 @@ void vegaPathTransformedBounds(VGPath path,
 void vegaDrawPath(VGPath path, VGbitfield paintModes)
 {
    struct vg_context *ctx = vg_current_context();
+   struct path *p = handle_to_path(path);
 
    if (path == VG_INVALID_HANDLE) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
@@ -477,9 +479,9 @@ void vegaDrawPath(VGPath path, VGbitfield paintModes)
       return;
    }
 
-   if (path_is_empty((struct path*)path))
+   if (path_is_empty(p))
       return;
-   path_render((struct path*)path, paintModes,
+   path_render(p, paintModes,
          &ctx->state.vg.path_user_to_surface_matrix);
 }
 
index 7c6b479409921154c0e022f5317fa6ea97c86e35..824c7630403442a3381faa46d303f5c1891709da 100644 (file)
@@ -29,6 +29,7 @@
 #include "vg_context.h"
 #include "text.h"
 #include "api.h"
+#include "handle.h"
 
 #include "util/u_memory.h"
 
@@ -43,19 +44,19 @@ VGFont vegaCreateFont(VGint glyphCapacityHint)
       return VG_INVALID_HANDLE;
    }
 
-   return (VGFont) font_create(glyphCapacityHint);
+   return font_to_handle(font_create(glyphCapacityHint));
 }
 
 void vegaDestroyFont(VGFont f)
 {
-   struct vg_font *font = (struct vg_font *)f;
+   struct vg_font *font = handle_to_font(f);
    struct vg_context *ctx = vg_current_context();
 
    if (f == VG_INVALID_HANDLE) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
-   if (!vg_object_is_valid((void *) font, VG_OBJECT_FONT)) {
+   if (!vg_object_is_valid(f, VG_OBJECT_FONT)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
@@ -75,7 +76,7 @@ void vegaSetGlyphToPath(VGFont font,
    struct vg_font *f;
 
    if (font == VG_INVALID_HANDLE ||
-       !vg_context_is_object_valid(ctx, VG_OBJECT_FONT, (void *)font)) {
+       !vg_context_is_object_valid(ctx, VG_OBJECT_FONT, font)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
@@ -85,13 +86,13 @@ void vegaSetGlyphToPath(VGFont font,
       return;
    }
    if (path != VG_INVALID_HANDLE &&
-       !vg_context_is_object_valid(ctx, VG_OBJECT_PATH, (void *)path)) {
+       !vg_context_is_object_valid(ctx, VG_OBJECT_PATH, path)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
 
-   pathObj = (struct path*) path;
-   f = (struct vg_font*) font;
+   pathObj = handle_to_path(path);
+   f = handle_to_font(font);
 
    font_set_glyph_to_path(f, glyphIndex, pathObj,
          isHinted, glyphOrigin, escapement);
@@ -108,7 +109,7 @@ void vegaSetGlyphToImage(VGFont font,
    struct vg_font *f;
 
    if (font == VG_INVALID_HANDLE ||
-       !vg_context_is_object_valid(ctx, VG_OBJECT_FONT, (void *)font)) {
+       !vg_context_is_object_valid(ctx, VG_OBJECT_FONT, font)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
@@ -118,13 +119,13 @@ void vegaSetGlyphToImage(VGFont font,
       return;
    }
    if (image != VG_INVALID_HANDLE &&
-       !vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void *)image)) {
+       !vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, image)) {
       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
       return;
    }
 
-   img_obj = (struct vg_image*)image;
-   f = (struct vg_font*)font;
+   img_obj = handle_to_image(image);
+   f = handle_to_font(font);
 
    font_set_glyph_to_image(f, glyphIndex, img_obj, glyphOrigin, escapement);
 }
@@ -140,7 +141,7 @@ void vegaClearGlyph(VGFont font,
       return;
    }
 
-   f = (struct vg_font*) font;
+   f = handle_to_font(font);
 
    font_clear_glyph(f, glyphIndex);
 }
@@ -161,7 +162,7 @@ void vegaDrawGlyph(VGFont font,
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       return;
    }
-   f = (struct vg_font*)font;
+   f = handle_to_font(font);
 
    font_draw_glyph(f, glyphIndex, paintModes, allowAutoHinting);
 }
@@ -199,7 +200,7 @@ void vegaDrawGlyphs(VGFont font,
       return;
    }
 
-   f = (struct vg_font*)font;
+   f = handle_to_font(font);
 
    font_draw_glyphs(f, glyphCount, glyphIndices,
          adjustments_x, adjustments_y, paintModes, allowAutoHinting);
diff --git a/src/gallium/state_trackers/vega/handle.c b/src/gallium/state_trackers/vega/handle.c
new file mode 100644 (file)
index 0000000..11eedd9
--- /dev/null
@@ -0,0 +1,93 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "handle.h"
+#include "util/u_hash.h"
+#include "util/u_hash_table.h"
+
+
+/**
+ * Hash keys are 32-bit VGHandles
+ */
+
+struct util_hash_table *handle_hash = NULL;
+
+
+static unsigned next_handle = 1;
+
+
+static unsigned
+hash_func(void *key)
+{
+   /* XXX this kind of ugly */
+   intptr_t ip = pointer_to_intptr(key);
+   return (unsigned) (ip & 0xffffffff);
+}
+
+
+static int
+compare(void *key1, void *key2)
+{
+   if (key1 < key2)
+      return -1;
+   else if (key1 > key2)
+      return +1;
+   else
+      return 0;
+}
+
+
+void
+init_handles(void)
+{
+   if (!handle_hash)
+      handle_hash = util_hash_table_create(hash_func, compare);
+}
+
+
+void
+free_handles(void)
+{
+   /* XXX destroy */
+}
+
+
+VGHandle
+create_handle(void *object)
+{
+   VGHandle h = next_handle++;
+   util_hash_table_set(handle_hash, intptr_to_pointer(h), object);
+   return h;
+}
+
+
+void
+destroy_handle(VGHandle h)
+{
+   util_hash_table_remove(handle_hash, intptr_to_pointer(h));
+}
+
diff --git a/src/gallium/state_trackers/vega/handle.h b/src/gallium/state_trackers/vega/handle.h
new file mode 100644 (file)
index 0000000..9ed326d
--- /dev/null
@@ -0,0 +1,171 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+/**
+ * Convert opaque VG object handles into pointers and vice versa.
+ * XXX This is not yet 64-bit safe!  All VG handles are 32 bits in size.
+ */
+
+
+#ifndef HANDLE_H
+#define HANDLE_H
+
+#include "pipe/p_compiler.h"
+#include "util/u_hash_table.h"
+#include "util/u_pointer.h"
+
+#include "VG/openvg.h"
+#include "vg_context.h"
+
+
+extern struct util_hash_table *handle_hash;
+
+
+struct vg_mask_layer;
+struct vg_font;
+struct vg_image;
+struct vg_paint;
+struct path;
+
+
+extern void
+init_handles(void);
+
+
+extern void
+free_handles(void);
+
+
+extern VGHandle
+create_handle(void *object);
+
+
+extern void
+destroy_handle(VGHandle h);
+
+
+static INLINE VGHandle
+object_to_handle(struct vg_object *obj)
+{
+   return obj ? obj->handle : VG_INVALID_HANDLE;
+}
+
+
+static INLINE VGHandle
+image_to_handle(struct vg_image *img)
+{
+   /* vg_image is derived from vg_object */
+   return object_to_handle((struct vg_object *) img);
+}
+
+
+static INLINE VGHandle
+masklayer_to_handle(struct vg_mask_layer *mask)
+{
+   /* vg_object is derived from vg_object */
+   return object_to_handle((struct vg_object *) mask);
+}
+
+
+static INLINE VGHandle
+font_to_handle(struct vg_font *font)
+{
+   return object_to_handle((struct vg_object *) font);
+}
+
+
+static INLINE VGHandle
+paint_to_handle(struct vg_paint *paint)
+{
+   return object_to_handle((struct vg_object *) paint);
+}
+
+
+static INLINE VGHandle
+path_to_handle(struct path *path)
+{
+   return object_to_handle((struct vg_object *) path);
+}
+
+
+static INLINE void *
+handle_to_pointer(VGHandle h)
+{
+   void *v = util_hash_table_get(handle_hash, intptr_to_pointer(h));
+#ifdef DEBUG
+   if (v) {
+      struct vg_object *obj = (struct vg_object *) v;
+      assert(obj->handle == h);
+   }
+#endif
+   return v;
+}
+
+
+static INLINE struct vg_font *
+handle_to_font(VGHandle h)
+{
+   return (struct vg_font *) handle_to_pointer(h);
+}
+
+
+static INLINE struct vg_image *
+handle_to_image(VGHandle h)
+{
+   return (struct vg_image *) handle_to_pointer(h);
+}
+
+
+static INLINE struct vg_mask_layer *
+handle_to_masklayer(VGHandle h)
+{
+   return (struct vg_mask_layer *) handle_to_pointer(h);
+}
+
+
+static INLINE struct vg_object *
+handle_to_object(VGHandle h)
+{
+   return (struct vg_object *) handle_to_pointer(h);
+}
+
+
+static INLINE struct vg_paint *
+handle_to_paint(VGHandle h)
+{
+   return (struct vg_paint *) handle_to_pointer(h);
+}
+
+
+static INLINE struct path *
+handle_to_path(VGHandle h)
+{
+   return (struct path *) handle_to_pointer(h);
+}
+
+
+#endif /* HANDLE_H */
index 318ea94bdfba1b853755433e6ce9f1146e21e2af..73351b671f996fcbb176336f36a4023be3ba8934 100644 (file)
@@ -349,6 +349,8 @@ void image_destroy(struct vg_image *img)
       array_destroy(img->children_array);
    }
 
+   vg_free_object(&img->base);
+
    pipe_sampler_view_reference(&img->sampler_view, NULL);
    FREE(img);
 }
index 2db8cbcf7c89f01305e5527122cd3f89b8578cd1..6e5348a1ff21b60b0a49e7edbddd99ba9125c5f7 100644 (file)
@@ -748,3 +748,10 @@ void paint_fill_constant_buffer(struct vg_paint *paint,
       abort();
    }
 }
+
+VGboolean paint_is_opaque(struct vg_paint *paint)
+{
+   /* TODO add other paint types and make sure PAINT_DIRTY gets set */
+   return (paint->type == VG_PAINT_TYPE_COLOR &&
+           floatsEqual(paint->solid.color[3], 1.0f));
+}
index 3de3bbe12eda91fc9c00fd03df54ecdab09a5359..e5357763b8936199e9e6c71616c75ea5c6b30352 100644 (file)
@@ -118,5 +118,6 @@ void paint_fill_constant_buffer(struct vg_paint *paint,
                                 const struct matrix *mat,
                                 void *buffer);
 
+VGboolean paint_is_opaque(struct vg_paint *paint);
 
 #endif
index a491de27fa675613c9197f6263a3ab389eece1cc..bcc5cb272ca45d93fb2d19c03ee1adce898906ef 100644 (file)
@@ -303,7 +303,6 @@ void polygon_fill(struct polygon *poly, struct vg_context *ctx)
    vbuffer.buffer = poly->vbuf;
    vbuffer.stride = COMPONENTS * sizeof(float);  /* vertex size */
    vbuffer.buffer_offset = 0;
-   vbuffer.max_index = poly->num_verts - 1;
 
    renderer_polygon_stencil_begin(ctx->renderer,
          &velement, ctx->state.vg.fill_rule, VG_FALSE);
@@ -354,7 +353,6 @@ void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx)
 
       polygon_prepare_buffer(ctx, poly);
       vbuffer.buffer = poly->vbuf;
-      vbuffer.max_index = poly->num_verts - 1;
 
       renderer_polygon_stencil(ctx->renderer, &vbuffer,
             PIPE_PRIM_TRIANGLE_FAN, 0, (VGuint) poly->num_verts);
index e42bad764922494d4478f617d2168ebc23e1b3fc..9de2cb1014dde3fcb47d7edda98283b1ac79bd5e 100644 (file)
@@ -28,6 +28,7 @@
 #include "renderer.h"
 
 #include "vg_context.h"
+#include "paint.h" /* for paint_is_opaque */
 
 #include "pipe/p_context.h"
 #include "pipe/p_state.h"
@@ -173,6 +174,7 @@ static void renderer_set_mvp(struct renderer *renderer,
    pipe_resource_reference(&cbuf, NULL);
    cbuf = pipe_buffer_create(renderer->pipe->screen,
                              PIPE_BIND_CONSTANT_BUFFER,
+                             PIPE_USAGE_STATIC,
                              sizeof(consts));
    if (cbuf) {
       pipe_buffer_write(renderer->pipe, cbuf,
@@ -473,7 +475,8 @@ static void renderer_set_custom_fs(struct renderer *renderer,
          pipe_resource_reference(&cbuf, NULL);
 
          cbuf = pipe_buffer_create(renderer->pipe->screen,
-               PIPE_BIND_CONSTANT_BUFFER, const_buffer_len);
+               PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STATIC,
+               const_buffer_len);
          pipe_buffer_write(renderer->pipe, cbuf, 0,
                const_buffer_len, const_buffer);
          renderer->pipe->set_constant_buffer(renderer->pipe,
@@ -571,7 +574,7 @@ static void renderer_quad_draw(struct renderer *r)
                                  sizeof(r->vertices),
                                  PIPE_BIND_VERTEX_BUFFER);
    if (buf) {
-      util_draw_vertex_buffer(r->pipe, buf, 0,
+      util_draw_vertex_buffer(r->pipe, r->cso, buf, 0,
                               PIPE_PRIM_TRIANGLE_FAN,
                               Elements(r->vertices),     /* verts */
                               Elements(r->vertices[0])); /* attribs/vert */
@@ -1049,7 +1052,7 @@ void renderer_polygon_stencil(struct renderer *renderer,
 {
    assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
 
-   renderer->pipe->set_vertex_buffers(renderer->pipe, 1, vbuf);
+   cso_set_vertex_buffers(renderer->cso, 1, vbuf);
 
    if (!renderer->u.polygon_stencil.manual_two_sides) {
       util_draw_arrays(renderer->pipe, mode, start, count);
@@ -1289,7 +1292,11 @@ static void renderer_validate_blend(struct renderer *renderer,
       blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
       break;
    case VG_BLEND_SRC_OVER:
-      if (!util_format_has_alpha(fb_format)) {
+      if (paint_is_opaque(state->fill_paint) &&
+          paint_is_opaque(state->stroke_paint)) {
+         /* no blending */
+      }
+      else if (!util_format_has_alpha(fb_format)) {
          blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_SRC_ALPHA;
          blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
          blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
index 2a6bae8a6305071579864645e398bf41a0640b8d..bee6d84001d03de92430f5f3f660eef06808fa88 100644 (file)
@@ -134,6 +134,8 @@ static VGboolean blend_use_shader(struct vg_context *ctx)
    switch (ctx->state.vg.blend_mode) {
    case VG_BLEND_SRC_OVER:
       advanced_blending =
+         (!paint_is_opaque(ctx->state.vg.fill_paint) ||
+          !paint_is_opaque(ctx->state.vg.stroke_paint)) &&
          util_format_has_alpha(ctx->draw_buffer->strb->format);
       break;
    case VG_BLEND_DST_OVER:
index f36f55d6c89fbcf0b840cbd802a1d63d81c9e870..83b42609e03432c8fc58e6435e9d7a02f0358ede 100644 (file)
@@ -33,6 +33,7 @@
 #include "vg_manager.h"
 #include "api.h"
 #include "mask.h"
+#include "handle.h"
 
 #include "pipe/p_context.h"
 #include "util/u_inlines.h"
@@ -182,17 +183,26 @@ void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_objec
 {
    obj->type = type;
    obj->ctx = ctx;
+   obj->handle = create_handle(obj);
+}
+
+/** free object resources, but not the object itself */
+void vg_free_object(struct vg_object *obj)
+{
+   obj->type = 0;
+   obj->ctx = NULL;
+   destroy_handle(obj->handle);
 }
 
 VGboolean vg_context_is_object_valid(struct vg_context *ctx,
                                 enum vg_object_type type,
-                                void *ptr)
+                                VGHandle object)
 {
     if (ctx) {
        struct cso_hash *hash = ctx->owned_objects[type];
        if (!hash)
           return VG_FALSE;
-       return cso_hash_contains(hash, (unsigned)(long)ptr);
+       return cso_hash_contains(hash, (unsigned)(long)object);
     }
     return VG_FALSE;
 }
@@ -398,8 +408,9 @@ void vg_validate_state(struct vg_context *ctx)
    if (vg_context_update_depth_stencil_rb(ctx, stfb->width, stfb->height))
       ctx->state.dirty |= DEPTH_STENCIL_DIRTY;
 
-   /* blend state depends on fb format */
-   if (ctx->state.dirty & FRAMEBUFFER_DIRTY)
+   /* blend state depends on fb format and paint color */
+   if ((ctx->state.dirty & FRAMEBUFFER_DIRTY) ||
+       (ctx->state.dirty & PAINT_DIRTY))
       ctx->state.dirty |= BLEND_DIRTY;
 
    renderer_validate(ctx->renderer, ctx->state.dirty,
@@ -412,10 +423,10 @@ void vg_validate_state(struct vg_context *ctx)
    shader_set_color_transform(ctx->shader, ctx->state.vg.color_transform);
 }
 
-VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type)
+VGboolean vg_object_is_valid(VGHandle object, enum vg_object_type type)
 {
-   struct vg_object *obj = ptr;
-   if (ptr && is_aligned(obj) && obj->type == type)
+   struct vg_object *obj = handle_to_object(object);
+   if (obj && is_aligned(obj) && obj->type == type)
       return VG_TRUE;
    else
       return VG_FALSE;
index d616a20a3d9aa532c9108e3161e130132bb6749e..71491a5aa22e9f57d6cc507b73927338faf02394 100644 (file)
@@ -81,10 +81,12 @@ enum dirty_state {
    BLEND_DIRTY         = 1 << 0,
    FRAMEBUFFER_DIRTY   = 1 << 1,
    DEPTH_STENCIL_DIRTY = 1 << 2,
+   PAINT_DIRTY         = 1 << 3,
 
    ALL_DIRTY           = BLEND_DIRTY |
                          FRAMEBUFFER_DIRTY |
-                         DEPTH_STENCIL_DIRTY
+                         DEPTH_STENCIL_DIRTY |
+                         PAINT_DIRTY
 };
 
 struct vg_context
@@ -129,12 +131,21 @@ struct vg_context
    struct blit_state *blit;
 };
 
+
+/**
+ *  Base class for VG objects like paths, images, fonts.
+ */
 struct vg_object {
    enum vg_object_type type;
+   VGHandle handle;
    struct vg_context *ctx;
 };
+
+
 void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type);
-VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type);
+void vg_free_object(struct vg_object *obj);
+
+VGboolean vg_object_is_valid(VGHandle object, enum vg_object_type type);
 
 struct vg_context *vg_create_context(struct pipe_context *pipe,
                                      const void *visual,
@@ -145,7 +156,7 @@ void vg_set_current_context(struct vg_context *ctx);
 
 VGboolean vg_context_is_object_valid(struct vg_context *ctx,
                                      enum vg_object_type type,
-                                     void *ptr);
+                                     VGHandle object);
 void vg_context_add_object(struct vg_context *ctx,
                            enum vg_object_type type,
                            void *ptr);
index ec713b7fb1d5dc649ab59c9616b2e19b8d53e802..44d2996bb4580f52dc1b762a8f8c1f26da4dd566 100644 (file)
@@ -40,6 +40,7 @@
 #include "vg_manager.h"
 #include "vg_context.h"
 #include "api.h"
+#include "handle.h"
 
 static boolean
 vg_context_update_color_rb(struct vg_context *ctx, struct pipe_resource *pt)
@@ -172,6 +173,9 @@ vg_api_create_context(struct st_api *stapi, struct st_manager *smapi,
    if (attribs->major > 1 || (attribs->major == 1 && attribs->minor > 0))
       return NULL;
 
+   /* for VGHandle / pointer lookups */
+   init_handles();
+
    pipe = smapi->screen->context_create(smapi->screen, NULL);
    if (!pipe)
       return NULL;
index 7dc51c5599cd575801ebee36fb664e3eee411d24..4206a91e006b060ec8446feda7a3b3790f69f018 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "matrix.h"
 #include "path.h"
+#include "handle.h"
 
 #include "util/u_debug.h"
 #include "util/u_pointer.h"
 #include <math.h>
 #include <assert.h>
 
-static VGboolean is_aligned_to(const void *ptr, VGbyte alignment)
-{
-   void *aligned = align_pointer(ptr, alignment);
-   return (ptr == aligned) ? VG_TRUE : VG_FALSE;
-}
-
-static VGboolean is_aligned(const void *ptr)
-{
-   return is_aligned_to(ptr, 4);
-}
 
 static void vgu_append_float_coords(VGPath path,
                                     const VGubyte *cmds,
@@ -54,7 +45,7 @@ static void vgu_append_float_coords(VGPath path,
                                     VGint num_coords)
 {
    VGubyte common_data[40 * sizeof(VGfloat)];
-   struct path *p = (struct path *)path;
+   struct path *p = handle_to_path(path);
 
    vg_float_to_datatype(path_datatype(p), common_data, coords, num_coords);
    vgAppendPathData(path, num_cmds, cmds, common_data);
index 1b7597de44056d3ae8b4253468ccafe457e24506..7cb953ba7420a19c1a3143bd37737db53aefa398 100644 (file)
@@ -15,6 +15,9 @@ env.AppendUnique(CPPDEFINES = [
     'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers 
     'WIN32_LEAN_AND_MEAN', # http://msdn2.microsoft.com/en-us/library/6dwk3a1z.aspx
 ])
+if not env['gles']:
+    # prevent _glapi_* from being declared __declspec(dllimport)
+    env.Append(CPPDEFINES = ['_GLAPI_NO_EXPORTS'])
 
 sources = [
     'stw_context.c',
index c4822d4d8aa9943919abebc277cd79c27d9b5880..4ece4e4979abb3ed4a6cadeb45aab87915653ee0 100644 (file)
@@ -170,7 +170,10 @@ stw_cleanup(void)
 
    _glthread_DESTROY_MUTEX(OneTimeLock);
 
+   /* glapi is statically linked: we can call the local destroy function. */
+#ifdef _GLAPI_NO_EXPORTS
    _glapi_destroy_multithread();
+#endif
 
 #ifdef DEBUG
    debug_memory_end(stw_dev->memdbg_no);
index 71f7b8c21d0379222d2e3c44299f8eea2f1b41a1..d751ac18704edb77c7b0dd6ba3d3b48fbe32e3df 100644 (file)
@@ -135,14 +135,12 @@ crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 
     /* Only set gamma when needed, to avoid unneeded delays. */
 #if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3
-    if (!crtc->active)
-#endif
+    if (!crtc->active && crtc->version >= 3)
        crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
                               crtc->gamma_blue, crtc->gamma_size);
-
-#if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3
     crtc->active = TRUE;
 #endif
+
     crtc->x = x;
     crtc->y = y;
     crtc->mode = *mode;
index a3d7c5a70e21d4af59dee3e7c705c5bd49f33d6a..3b3ae455c0b6648cad00c000483d8cb2ad378e64 100644 (file)
@@ -73,7 +73,7 @@ renderer_draw(struct xorg_renderer *r)
    if (buf) {
       cso_set_vertex_elements(r->cso, r->attrs_per_vertex, r->velems);
 
-      util_draw_vertex_buffer(pipe, buf, 0,
+      util_draw_vertex_buffer(pipe, r->cso, buf, 0,
                               PIPE_PRIM_QUADS,
                               num_verts,  /* verts */
                               r->attrs_per_vertex); /* attribs/vert */
@@ -429,6 +429,7 @@ void renderer_set_constants(struct xorg_renderer *r,
    pipe_resource_reference(cbuf, NULL);
    *cbuf = pipe_buffer_create(r->pipe->screen,
                               PIPE_BIND_CONSTANT_BUFFER,
+                              PIPE_USAGE_STATIC,
                               param_bytes);
 
    if (*cbuf) {
@@ -616,7 +617,7 @@ void renderer_draw_yuv(struct xorg_renderer *r,
 
       cso_set_vertex_elements(r->cso, num_attribs, r->velems);
 
-      util_draw_vertex_buffer(pipe, buf, 0,
+      util_draw_vertex_buffer(pipe, r->cso, buf, 0,
                               PIPE_PRIM_QUADS,
                               4,  /* verts */
                               num_attribs); /* attribs/vert */
index 4a835c04d8ad8e173cb1ac2fac8f6c7661eccce1..78de154bdd7b962fee05026ccf95d90f067b1854 100644 (file)
@@ -14,7 +14,7 @@
  * The above copyright notice and this permission notice (including the
  * next paragraph) shall be included in all copies or substantial portions
  * of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS 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.
@@ -176,6 +176,7 @@ Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *
       template.height0 = util_next_power_of_two(height);
    }
    template.depth0 = 1;
+   template.array_size = 1;
    template.usage = PIPE_USAGE_DYNAMIC;
    template.bind = PIPE_BIND_SAMPLER_VIEW;
    template.flags = 0;
@@ -222,7 +223,7 @@ Status XvMCClearSubpicture(Display *dpy, XvMCSubpicture *subpicture, short x, sh
 
    if (!subpicture)
       return XvMCBadSubpicture;
-               
+
    /* Convert color to float */
    util_format_read_4f(PIPE_FORMAT_B8G8R8A8_UNORM,
                     color_f, 1,
index d7285a478fb4e473663cb0060e4b52dadf76d6b6..c90ad409c1008f40eabd14b928c08b69ac35a57c 100644 (file)
@@ -122,6 +122,7 @@ CreateOrResizeBackBuffer(struct vl_context *vctx, unsigned int width, unsigned i
    template.width0 = width;
    template.height0 = height;
    template.depth0 = 1;
+   template.array_size = 1;
    template.usage = PIPE_USAGE_DEFAULT;
    template.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_BLIT_SOURCE;
    template.flags = 0;
@@ -240,6 +241,7 @@ Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surfac
       template.height0 = util_next_power_of_two(context->height);
    }
    template.depth0 = 1;
+   template.array_size = 1;
    template.usage = PIPE_USAGE_DEFAULT;
    template.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
    template.flags = 0;
index bc3671a256bb4612fb92bb61edc5a2b138223270..101863a68489c3dd9775da2b04bd4b793e3d811c 100644 (file)
@@ -72,7 +72,6 @@ COMMON_DRI_DRM_OBJECTS = [
 
 drienv.AppendUnique(LIBS = [
     'expat',
-    'talloc',
 ])
 
 Export([
index 9afbb13276d224d82ab93d0cba710cd5a79264cb..cc77a4bc20d6f6354c15d0ba45a7f3bc9593b4ac 100644 (file)
@@ -22,6 +22,4 @@ DRIVER_DEFINES = \
 
 include ../Makefile.dri
 
-DRI_LIB_DEPS += -ldrm_radeon
-
 symlinks:
index 005b4bbf7f1d65d1f71b6e561340ecada09147c1..683b6c6972d4beaadd762d498a6af4e7c2435ff8 100644 (file)
@@ -2,8 +2,6 @@ Import('*')
 
 env = drienv.Clone()
 
-env.ParseConfig('pkg-config --cflags --libs libdrm_radeon')
-
 env.Append(CPPDEFINES = ['GALLIUM_RBUG', 'GALLIUM_TRACE', 'GALLIUM_GALAHAD'])
 
 env.Prepend(LIBS = [
index aa771db2d1af1c38a6d19bef8b4d24268e0e7d26..1df11a8747b8b0303d044a2c0cd4995bb467cc38 100644 (file)
@@ -2,8 +2,6 @@ Import('*')
 
 env = drienv.Clone()
 
-env.ParseConfig('pkg-config --cflags --libs libdrm_radeon')
-
 env.Append(CPPDEFINES = ['GALLIUM_RBUG', 'GALLIUM_TRACE'])
 
 env.Prepend(LIBS = [
index 38f78932e136db87fef797b1f9b8517be7ed8907..8c716f42fe2cf5a4de9e500e0e92ffd84f34430e 100644 (file)
@@ -6,6 +6,7 @@ LIBNAME = vmwgfx_dri.so
 PIPE_DRIVERS = \
        $(TOP)/src/gallium/state_trackers/dri/drm/libdridrm.a \
        $(TOP)/src/gallium/winsys/svga/drm/libsvgadrm.a \
+       $(TOP)/src/gallium/winsys/sw/wrapper/libwsw.a \
        $(TOP)/src/gallium/drivers/trace/libtrace.a \
        $(TOP)/src/gallium/drivers/rbug/librbug.a \
        $(TOP)/src/gallium/drivers/svga/libsvga.a
index 381ef4e862de53fdeff48503f088f88a3c8d4adf..cbd98cc416ab37647e5807e25347416b92a979b5 100644 (file)
@@ -58,10 +58,18 @@ if env['platform'] == 'windows':
     env.Prepend(LIBS = [
         ws_gdi,
     ])
-else:
-    # OpenGL
-    env.Append(CPPDEFINES = ['FEATURE_GL=1'])
-    env.Prepend(LIBS = ['GL', 'talloc', glsl, mesa])
+
+# OpenGL ES and OpenGL
+if env['gles']:
+    env.Append(CPPDEFINES = [
+        'FEATURE_GL=1',
+        'FEATURE_ES1=1',
+        'FEATURE_ES2=1'
+    ])
+    env.Prepend(LIBPATH = [shared_glapi.dir])
+    # manually add LIBPREFIX on windows
+    glapi_name = 'glapi' if env['platform'] != 'windows' else 'libglapi'
+    env.Prepend(LIBS = [glapi_name, glsl, mesa])
 
 # OpenVG
 if True:
@@ -96,7 +104,6 @@ if env['drm']:
         ])
 
     if env['drm_radeon']:
-        env.ParseConfig('pkg-config --cflags --libs libdrm_radeon')
         env.Append(CPPDEFINES = ['_EGL_PIPE_R300', '_EGL_PIPE_R600'])
         env.Prepend(LIBS = [
             radeonwinsys,
index 92d971bab013f280972280737c355dea810d2d1d..de01939e5f12a7eb97dea35ed9fd4497151bfedd 100644 (file)
@@ -46,6 +46,9 @@ ifneq ($(findstring x11, $(EGL_PLATFORMS)),)
 egl_SYS += -lX11 -lXext -lXfixes $(LIBDRM_LIB)
 egl_LIBS += $(TOP)/src/gallium/winsys/sw/xlib/libws_xlib.a
 endif
+ifneq ($(findstring wayland, $(EGL_PLATFORMS)),)
+egl_SYS += $(WAYLAND_LIBS) $(LIBDRM_LIB)
+endif
 ifneq ($(findstring drm, $(EGL_PLATFORMS)),)
 egl_SYS += $(LIBDRM_LIB)
 endif
@@ -89,7 +92,7 @@ nouveau_LIBS := \
 
 # r300 pipe driver
 r300_CPPFLAGS :=
-r300_SYS := -ldrm -ldrm_radeon
+r300_SYS := -ldrm
 r300_LIBS := \
        $(TOP)/src/gallium/winsys/radeon/drm/libradeonwinsys.a \
        $(TOP)/src/gallium/drivers/r300/libr300.a
index 6fa0851a1ab867441a3cc4c419e15b85a40debf7..49462a8e309cf4235fdae2035f799579770c3cb9 100644 (file)
@@ -15,7 +15,6 @@ env.Append(LIBS = [
     'user32',
     'kernel32',
     'ws2_32',
-    talloc,
 ])
 
 sources = ['libgl_gdi.c']
@@ -37,6 +36,12 @@ drivers += [trace, rbug]
 
 env['no_import_lib'] = 1
 
+# when GLES is enabled, gl* and _glapi_* belong to bridge_glapi and
+# shared_glapi respectively
+if env['gles']:
+    env.Prepend(LIBPATH = [shared_glapi.dir])
+    glapi = [bridge_glapi, 'libglapi']
+
 opengl32 = env.SharedLibrary(
     target ='opengl32',
     source = sources,
index d932736be780719f3dcd621129b8be2104809dce..ca15372f1d9dc14d00dbe482a53f20ba6acb2cf1 100644 (file)
@@ -16,6 +16,12 @@ env.Append(CPPDEFINES = ['USE_XSHM'])
 
 env.Prepend(LIBS = env['X11_LIBS'])
 
+# when GLES is enabled, gl* and _glapi_* belong to bridge_glapi and
+# shared_glapi respectively
+if env['gles']:
+    env.Prepend(LIBPATH = [shared_glapi.dir])
+    glapi = [bridge_glapi, 'glapi']
+
 env.Prepend(LIBS = [
     st_xlib,
     ws_xlib,
@@ -23,7 +29,6 @@ env.Prepend(LIBS = [
     mesa,
     glsl,
     gallium,
-    'talloc'
 ])
 
 sources = [
index d3bc35699290d5d97239dc78fa1a6a4aca9a6cdc..6d5f2c3d16e8b23ca2af318f13c862050c3e2a89 100644 (file)
@@ -19,6 +19,6 @@ DRIVER_PIPES = \
        $(TOP)/src/gallium/drivers/rbug/librbug.a
 
 DRIVER_LINKS = \
-       $(shell pkg-config --libs libdrm libdrm_radeon)
+       $(shell pkg-config --libs libdrm)
 
 include ../Makefile.xorg
index 3341b884985e50aec843a52691cfd3b4212365fd..565fa5279cdb575526fa536b76da919697d4dcc9 100644 (file)
@@ -24,6 +24,7 @@ progs = [
     'gs-test',
     'shader-leak',
     'tri-gs',
+    'quad-sample',
 ]
 
 for name in progs:
index d21eb44e1164c24f31ba33c7734ec8856a909113..ff82b6071100c76350f8fcbbaf610e344ffdd3b6 100644 (file)
@@ -215,7 +215,6 @@ static void set_vertices( void )
 
 
    vbuf.stride = sizeof( struct vertex );
-   vbuf.max_index = sizeof(vertices) / vbuf.stride;
    vbuf.buffer_offset = 0;
    vbuf.buffer = screen->user_buffer_create(screen,
                                             vertices,
index 0c65390e109c171a29696b2a228a985fb66951dd..cc05889dd05c66ca3aceef8a301bdeb7c81ef4c4 100644 (file)
@@ -251,13 +251,11 @@ static void set_vertices( void )
    vbuf.stride = sizeof( struct vertex );
    vbuf.buffer_offset = 0;
    if (draw_strip) {
-      vbuf.max_index = sizeof(vertices_strip) / vbuf.stride;
       vbuf.buffer = screen->user_buffer_create(screen,
                                                vertices_strip,
                                                sizeof(vertices_strip),
                                                PIPE_BIND_VERTEX_BUFFER);
    } else {
-      vbuf.max_index = sizeof(vertices) / vbuf.stride;
       vbuf.buffer = screen->user_buffer_create(screen,
                                                vertices,
                                                sizeof(vertices),
diff --git a/src/gallium/tests/graw/quad-sample.c b/src/gallium/tests/graw/quad-sample.c
new file mode 100644 (file)
index 0000000..3c6458b
--- /dev/null
@@ -0,0 +1,414 @@
+/* Display a cleared blue window.  This demo has no dependencies on
+ * any utility code, just the graw interface and gallium.
+ */
+
+#include "state_tracker/graw.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_shader_tokens.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+
+#include "util/u_debug.h"       /* debug_dump_surface_bmp() */
+#include "util/u_inlines.h"
+#include "util/u_memory.h"      /* Offset() */
+#include "util/u_draw_quad.h"
+#include "util/u_box.h"    
+
+#include <stdio.h>
+
+enum pipe_format formats[] = {
+   PIPE_FORMAT_R8G8B8A8_UNORM,
+   PIPE_FORMAT_B8G8R8A8_UNORM,
+   PIPE_FORMAT_NONE
+};
+
+static const int WIDTH = 300;
+static const int HEIGHT = 300;
+
+static struct pipe_screen *screen = NULL;
+static struct pipe_context *ctx = NULL;
+static struct pipe_resource *rttex = NULL;
+static struct pipe_resource *samptex = NULL;
+static struct pipe_surface *surf = NULL;
+static struct pipe_sampler_view *sv = NULL;
+static void *sampler = NULL;
+static void *window = NULL;
+
+struct vertex {
+   float position[4];
+   float color[4];
+};
+
+static struct vertex vertices[] =
+{
+   { { 0.9, -0.9, 0.0, 1.0 },
+     { 1, 0, 0, 1 } },
+
+   { { 0.9,  0.9, 0.0, 1.0 },
+     { 1, 1, 0, 1 } },
+
+   { {-0.9,  0.9, 0.0, 1.0 },
+     { 0, 1, 0, 1 } },
+
+   { {-0.9,  -0.9, 0.0, 1.0 },
+     { 0, 0, 0, 1 } },
+};
+
+
+
+
+static void set_viewport( float x, float y,
+                          float width, float height,
+                          float near, float far)
+{
+   float z = far;
+   float half_width = (float)width / 2.0f;
+   float half_height = (float)height / 2.0f;
+   float half_depth = ((float)far - (float)near) / 2.0f;
+   struct pipe_viewport_state vp;
+
+   vp.scale[0] = half_width;
+   vp.scale[1] = half_height;
+   vp.scale[2] = half_depth;
+   vp.scale[3] = 1.0f;
+
+   vp.translate[0] = half_width + x;
+   vp.translate[1] = half_height + y;
+   vp.translate[2] = half_depth + z;
+   vp.translate[3] = 0.0f;
+
+   ctx->set_viewport_state( ctx, &vp );
+}
+
+static void set_vertices( void )
+{
+   struct pipe_vertex_element ve[2];
+   struct pipe_vertex_buffer vbuf;
+   void *handle;
+
+   memset(ve, 0, sizeof ve);
+
+   ve[0].src_offset = Offset(struct vertex, position);
+   ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+   ve[1].src_offset = Offset(struct vertex, color);
+   ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+
+   handle = ctx->create_vertex_elements_state(ctx, 2, ve);
+   ctx->bind_vertex_elements_state(ctx, handle);
+
+
+   vbuf.stride = sizeof( struct vertex );
+   vbuf.buffer_offset = 0;
+   vbuf.buffer = screen->user_buffer_create(screen,
+                                            vertices,
+                                            sizeof(vertices),
+                                            PIPE_BIND_VERTEX_BUFFER);
+
+   ctx->set_vertex_buffers(ctx, 1, &vbuf);
+}
+
+static void set_vertex_shader( void )
+{
+   void *handle;
+   const char *text =
+      "VERT\n"
+      "DCL IN[0]\n"
+      "DCL IN[1]\n"
+      "DCL OUT[0], POSITION\n"
+      "DCL OUT[1], GENERIC[0]\n"
+      "  0: MOV OUT[1], IN[1]\n"
+      "  1: MOV OUT[0], IN[0]\n"
+      "  2: END\n";
+
+   handle = graw_parse_vertex_shader(ctx, text);
+   ctx->bind_vs_state(ctx, handle);
+}
+
+static void set_fragment_shader( void )
+{
+   void *handle;
+   const char *text =
+      "FRAG\n"
+      "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+      "DCL OUT[0], COLOR\n"
+      "DCL TEMP[0]\n"
+      "DCL SAMP[0]\n"
+      "DCL RES[0], 2D, FLOAT\n"
+      "  0: SAMPLE TEMP[0], IN[0], RES[0], SAMP[0]\n"
+      "  1: MOV OUT[0], TEMP[0]\n"
+      "  2: END\n";
+
+   handle = graw_parse_fragment_shader(ctx, text);
+   ctx->bind_fs_state(ctx, handle);
+}
+
+
+static void draw( void )
+{
+   float clear_color[4] = {.5,.5,.5,1};
+
+   ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
+   util_draw_arrays(ctx, PIPE_PRIM_QUADS, 0, 4);
+   ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+   graw_save_surface_to_file(ctx, surf, NULL);
+
+   screen->flush_frontbuffer(screen, rttex, 0, 0, window);
+}
+
+#define SIZE 16
+
+static void init_tex( void )
+{ 
+   struct pipe_sampler_view sv_template;
+   struct pipe_sampler_state sampler_desc;
+   struct pipe_resource templat;
+   struct pipe_box box;
+   ubyte tex2d[SIZE][SIZE][4];
+   int s, t;
+
+#if (SIZE != 2)
+   for (s = 0; s < SIZE; s++) {
+      for (t = 0; t < SIZE; t++) {
+         if (0) {
+            int x = (s ^ t) & 1;
+           tex2d[t][s][0] = (x) ? 0 : 63;
+           tex2d[t][s][1] = (x) ? 0 : 128;
+           tex2d[t][s][2] = 0;
+           tex2d[t][s][3] = 0xff;
+         }
+         else {
+            int x = ((s ^ t) >> 2) & 1;
+           tex2d[t][s][0] = s*255/(SIZE-1);
+           tex2d[t][s][1] = t*255/(SIZE-1);
+           tex2d[t][s][2] = (x) ? 0 : 128;
+           tex2d[t][s][3] = 0xff;
+         }
+      }
+   }
+#else
+   tex2d[0][0][0] = 0;
+   tex2d[0][0][1] = 255;
+   tex2d[0][0][2] = 255;
+   tex2d[0][0][3] = 0;
+
+   tex2d[0][1][0] = 0;
+   tex2d[0][1][1] = 0;
+   tex2d[0][1][2] = 255;
+   tex2d[0][1][3] = 255;
+
+   tex2d[1][0][0] = 255;
+   tex2d[1][0][1] = 255;
+   tex2d[1][0][2] = 0;
+   tex2d[1][0][3] = 255;
+
+   tex2d[1][1][0] = 255;
+   tex2d[1][1][1] = 0;
+   tex2d[1][1][2] = 0;
+   tex2d[1][1][3] = 255;
+#endif
+
+   templat.target = PIPE_TEXTURE_2D;
+   templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
+   templat.width0 = SIZE;
+   templat.height0 = SIZE;
+   templat.depth0 = 1;
+   templat.last_level = 0;
+   templat.nr_samples = 1;
+   templat.bind = PIPE_BIND_SAMPLER_VIEW;
+
+   
+   samptex = screen->resource_create(screen,
+                                 &templat);
+   if (samptex == NULL)
+      exit(4);
+
+   u_box_2d(0,0,SIZE,SIZE, &box);
+
+   ctx->transfer_inline_write(ctx,
+                              samptex,
+                              0,
+                              PIPE_TRANSFER_WRITE,
+                              &box,
+                              tex2d,
+                              sizeof tex2d[0],
+                              sizeof tex2d);
+
+   /* Possibly read back & compare against original data:
+    */
+   if (0)
+   {
+      struct pipe_transfer *t;
+      uint32_t *ptr;
+      t = pipe_get_transfer(ctx, samptex,
+                            0, 0, /* level, layer */
+                            PIPE_TRANSFER_READ,
+                            0, 0, SIZE, SIZE); /* x, y, width, height */
+
+      ptr = ctx->transfer_map(ctx, t);
+
+      if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
+         assert(0);
+         exit(9);
+      }
+
+      ctx->transfer_unmap(ctx, t);
+
+      ctx->transfer_destroy(ctx, t);
+   }
+
+   memset(&sv_template, 0, sizeof sv_template);
+   sv_template.format = samptex->format;
+   sv_template.texture = samptex;
+   sv_template.swizzle_r = 0;
+   sv_template.swizzle_g = 1;
+   sv_template.swizzle_b = 2;
+   sv_template.swizzle_a = 3;
+   sv = ctx->create_sampler_view(ctx, samptex, &sv_template);
+   if (sv == NULL)
+      exit(5);
+
+   ctx->set_fragment_sampler_views(ctx, 1, &sv);
+   
+
+   memset(&sampler_desc, 0, sizeof sampler_desc);
+   sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT;
+   sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT;
+   sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT;
+   sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+   sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+   sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+   sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
+   sampler_desc.compare_func = 0;
+   sampler_desc.normalized_coords = 1;
+   sampler_desc.max_anisotropy = 0;
+   
+   sampler = ctx->create_sampler_state(ctx, &sampler_desc);
+   if (sampler == NULL)
+      exit(6);
+
+   ctx->bind_fragment_sampler_states(ctx, 1, &sampler);
+   
+}
+
+static void init( void )
+{
+   struct pipe_framebuffer_state fb;
+   struct pipe_resource templat;
+   struct pipe_surface surf_tmpl;
+   int i;
+
+   /* It's hard to say whether window or screen should be created
+    * first.  Different environments would prefer one or the other.
+    *
+    * Also, no easy way of querying supported formats if the screen
+    * cannot be created first.
+    */
+   for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) {
+      screen = graw_create_window_and_screen(0, 0, 300, 300,
+                                             formats[i],
+                                             &window);
+      if (window && screen)
+         break;
+   }
+   if (!screen || !window) {
+      fprintf(stderr, "Unable to create window\n");
+      exit(1);
+   }
+
+   ctx = screen->context_create(screen, NULL);
+   if (ctx == NULL)
+      exit(3);
+
+   templat.target = PIPE_TEXTURE_2D;
+   templat.format = formats[i];
+   templat.width0 = WIDTH;
+   templat.height0 = HEIGHT;
+   templat.depth0 = 1;
+   templat.array_size = 1;
+   templat.last_level = 0;
+   templat.nr_samples = 1;
+   templat.bind = (PIPE_BIND_RENDER_TARGET |
+                   PIPE_BIND_DISPLAY_TARGET);
+   
+   rttex = screen->resource_create(screen,
+                                 &templat);
+   if (rttex == NULL)
+      exit(4);
+
+   surf_tmpl.format = templat.format;
+   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+   surf_tmpl.u.tex.level = 0;
+   surf_tmpl.u.tex.first_layer = 0;
+   surf_tmpl.u.tex.last_layer = 0;
+   surf = ctx->create_surface(ctx, rttex, &surf_tmpl);
+   if (surf == NULL)
+      exit(5);
+
+   memset(&fb, 0, sizeof fb);
+   fb.nr_cbufs = 1;
+   fb.width = WIDTH;
+   fb.height = HEIGHT;
+   fb.cbufs[0] = surf;
+
+   ctx->set_framebuffer_state(ctx, &fb);
+   
+   {
+      struct pipe_blend_state blend;
+      void *handle;
+      memset(&blend, 0, sizeof blend);
+      blend.rt[0].colormask = PIPE_MASK_RGBA;
+      handle = ctx->create_blend_state(ctx, &blend);
+      ctx->bind_blend_state(ctx, handle);
+   }
+
+   {
+      struct pipe_depth_stencil_alpha_state depthstencil;
+      void *handle;
+      memset(&depthstencil, 0, sizeof depthstencil);
+      handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);
+      ctx->bind_depth_stencil_alpha_state(ctx, handle);
+   }
+
+   {
+      struct pipe_rasterizer_state rasterizer;
+      void *handle;
+      memset(&rasterizer, 0, sizeof rasterizer);
+      rasterizer.cull_face = PIPE_FACE_NONE;
+      rasterizer.gl_rasterization_rules = 1;
+      handle = ctx->create_rasterizer_state(ctx, &rasterizer);
+      ctx->bind_rasterizer_state(ctx, handle);
+   }
+
+   set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
+
+   init_tex();
+
+   set_vertices();
+   set_vertex_shader();
+   set_fragment_shader();
+}
+
+static void args(int argc, char *argv[])
+{
+   int i;
+
+   for (i = 1; i < argc;) {
+      if (graw_parse_args(&i, argc, argv)) {
+         continue;
+      }
+      exit(1);
+   }
+}
+
+
+int main( int argc, char *argv[] )
+{
+   args(argc, argv);
+   init();
+
+   graw_set_display_func( draw );
+   graw_main_loop();
+   return 0;
+}
index 58ca639d2073c879fec739356ab55918addccb8a..4e66813b301274304e5d1c7d3d62fd89f977eeb1 100644 (file)
@@ -97,7 +97,6 @@ static void set_vertices( void )
 
 
    vbuf.stride = sizeof( struct vertex );
-   vbuf.max_index = sizeof(vertices) / vbuf.stride;
    vbuf.buffer_offset = 0;
    vbuf.buffer = screen->user_buffer_create(screen,
                                             vertices,
index 9af76f51ea2d881cb5b4a85e38aaa514189c9902..a23ca73ac1df4eee14ef8841045335e25a70f561 100644 (file)
@@ -88,7 +88,6 @@ static void set_vertices( void )
 
 
    vbuf.stride = sizeof(struct vertex);
-   vbuf.max_index = sizeof(vertices) / vbuf.stride;
    vbuf.buffer_offset = 0;
    vbuf.buffer = screen->user_buffer_create(screen,
                                             vertices,
index a1a00b3209857fd80a76cc580cdef91396af4b89..47b76530c6b2d62d302f9f0c41d62d52f880fa56 100644 (file)
@@ -89,7 +89,6 @@ static void set_vertices( void )
 
 
    vbuf.stride = sizeof( struct vertex );
-   vbuf.max_index = sizeof(vertices) / vbuf.stride;
    vbuf.buffer_offset = 0;
    vbuf.buffer = screen->user_buffer_create(screen,
                                             vertices,
index f61d8b9844d4eb7cadf03cc9a7f453f04d213953..259b3d9527c92cf1a983dac92f8c2200b440c064 100644 (file)
@@ -132,7 +132,6 @@ static void set_vertices( void )
 
    /* vertex data */
    vbuf[0].stride = sizeof( struct vertex );
-   vbuf[0].max_index = sizeof(vertices) / vbuf[0].stride;
    vbuf[0].buffer_offset = 0;
    vbuf[0].buffer = screen->user_buffer_create(screen,
                                                vertices,
@@ -141,7 +140,6 @@ static void set_vertices( void )
 
    /* instance data */
    vbuf[1].stride = sizeof( inst_data[0] );
-   vbuf[1].max_index = sizeof(inst_data) / vbuf[1].stride;
    vbuf[1].buffer_offset = 0;
    vbuf[1].buffer = screen->user_buffer_create(screen,
                                                inst_data,
index 006d61ca88c8c237ddbe10ea46d9f867cd6e38f6..4266c0394d813b80350a01e747b66b865e99c750 100644 (file)
@@ -93,7 +93,6 @@ static void set_vertices( void )
 
 
    vbuf.stride = sizeof( struct vertex );
-   vbuf.max_index = sizeof(vertices) / vbuf.stride;
    vbuf.buffer_offset = 0;
    vbuf.buffer = screen->user_buffer_create(screen,
                                             vertices,
index 1358fa85dfd82d7ea8eb9b075d9fea5f4cf47032..dd64d8b9301d7c5502ce2b4b19bca32cebac6d0f 100644 (file)
@@ -171,7 +171,6 @@ static void set_vertices( void )
    }
 
    vbuf.stride = sizeof( struct vertex );
-   vbuf.max_index = sizeof(vertices) / vbuf.stride;
    vbuf.buffer_offset = 0;
    vbuf.buffer = screen->user_buffer_create(screen,
                                             vertices,
index 92c5b4dbb183f3ac5111ae6b9551d98a1d8b7511..af93e09d8d4ecd8a45b0130de3e3ecec6f821db5 100644 (file)
@@ -129,7 +129,8 @@ static void init_prog(struct program *p)
                        }
                };
 
-               p->vbuf = pipe_buffer_create(p->screen, PIPE_BIND_VERTEX_BUFFER, sizeof(vertices));
+               p->vbuf = pipe_buffer_create(p->screen, PIPE_BIND_VERTEX_BUFFER,
+                                            PIPE_USAGE_STATIC, sizeof(vertices));
                pipe_buffer_write(p->pipe, p->vbuf, 0, sizeof(vertices), vertices);
        }
 
index 37c1573051f1da16ee2b18dc612d1539008acda9..b89cfe0d98920ef2a79d5fd19b6b5542abc7e7a2 100644 (file)
@@ -120,7 +120,8 @@ static void init_prog(struct program *p)
                        }
                };
 
-               p->vbuf = pipe_buffer_create(p->screen, PIPE_BIND_VERTEX_BUFFER, sizeof(vertices));
+               p->vbuf = pipe_buffer_create(p->screen, PIPE_BIND_VERTEX_BUFFER,
+                                            PIPE_USAGE_STATIC, sizeof(vertices));
                pipe_buffer_write(p->pipe, p->vbuf, 0, sizeof(vertices), vertices);
        }
 
index d74f8a2e989a465293a1d44f1a5eb01fa06d1d9d..9f36d225e10e60dc0f89b93ddbc27150a98fbe24 100644 (file)
@@ -13,6 +13,10 @@ SConscript([
     'sw/gdi/SConscript',
 ])
 
+SConscript([
+    'i915/sw/SConscript',
+])
+
 if env['dri']:
     SConscript([
         'sw/dri/SConscript',
index ebe86dcf196d0a2b39da746724219bb4bea10e25..afeab5eef42b07fe902cfa91c45767b59250582d 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "i915_drm.h"
 #include "i915/i915_debug.h"
+#include <xf86drm.h>
 
 #define BATCH_RESERVED 16
 
@@ -34,7 +35,6 @@ static void
 i915_drm_batchbuffer_reset(struct i915_drm_batchbuffer *batch)
 {
    struct i915_drm_winsys *idws = i915_drm_winsys(batch->base.iws);
-   int ret;
 
    if (batch->bo)
       drm_intel_bo_unreference(batch->bo);
@@ -43,18 +43,6 @@ i915_drm_batchbuffer_reset(struct i915_drm_batchbuffer *batch)
                                   batch->actual_size,
                                   4096);
 
-#ifdef INTEL_MAP_BATCHBUFFER
-#ifdef INTEL_MAP_GTT
-   ret = drm_intel_gem_bo_map_gtt(batch->bo);
-#else
-   ret = drm_intel_bo_map(batch->bo, TRUE);
-#endif
-   assert(ret == 0);
-   batch->base.map = batch->bo->virtual;
-#else
-   (void)ret;
-#endif
-
    memset(batch->base.map, 0, batch->actual_size);
    batch->base.ptr = batch->base.map;
    batch->base.size = batch->actual_size - BATCH_RESERVED;
@@ -87,7 +75,7 @@ static int
 i915_drm_batchbuffer_reloc(struct i915_winsys_batchbuffer *ibatch,
                             struct i915_winsys_buffer *buffer,
                             enum i915_winsys_buffer_usage usage,
-                            unsigned pre_add, bool fenced)
+                            unsigned pre_add, boolean fenced)
 {
    struct i915_drm_batchbuffer *batch = i915_drm_batchbuffer(ibatch);
    unsigned write_domain = 0;
@@ -145,6 +133,12 @@ i915_drm_batchbuffer_reloc(struct i915_winsys_batchbuffer *ibatch,
    return ret;
 }
 
+static void 
+i915_drm_throttle(struct i915_drm_winsys *idws)
+{
+   drmIoctl(idws->fd, DRM_IOCTL_I915_GEM_THROTTLE, NULL);
+}
+
 static void
 i915_drm_batchbuffer_flush(struct i915_winsys_batchbuffer *ibatch,
                             struct pipe_fence_handle **fence)
@@ -168,6 +162,8 @@ i915_drm_batchbuffer_flush(struct i915_winsys_batchbuffer *ibatch,
    if (ret == 0 && i915_drm_winsys(ibatch->iws)->send_cmd)
       ret = drm_intel_bo_exec(batch->bo, used, NULL, 0, 0);
 
+   i915_drm_throttle(i915_drm_winsys(ibatch->iws));
+
    if (ret != 0 || i915_drm_winsys(ibatch->iws)->dump_cmd) {
       i915_dump_batchbuffer(ibatch);
       assert(ret == 0);
index 44773ae30e7492bd368683593267af9f73128286..8085591c8ebe072aff0afbe59c1dd8a23c75f285 100644 (file)
@@ -1,6 +1,7 @@
 
 #include "i915_sw_winsys.h"
 #include "i915/i915_batchbuffer.h"
+#include "i915/i915_debug.h"
 #include "util/u_memory.h"
 
 #define BATCH_RESERVED 16
@@ -61,7 +62,7 @@ static int
 i915_sw_batchbuffer_reloc(struct i915_winsys_batchbuffer *ibatch,
                           struct i915_winsys_buffer *buffer,
                           enum i915_winsys_buffer_usage usage,
-                          unsigned pre_add, bool fenced)
+                          unsigned pre_add, boolean fenced)
 {
    struct i915_sw_batchbuffer *batch = i915_sw_batchbuffer(ibatch);
    int ret = 0;
@@ -98,7 +99,6 @@ i915_sw_batchbuffer_flush(struct i915_winsys_batchbuffer *ibatch,
 {
    struct i915_sw_batchbuffer *batch = i915_sw_batchbuffer(ibatch);
    unsigned used = 0;
-   int i;
 
    assert(i915_winsys_batchbuffer_space(ibatch) >= 0);
 
@@ -122,12 +122,7 @@ i915_sw_batchbuffer_flush(struct i915_winsys_batchbuffer *ibatch,
    assert((used & 4) == 0);
 
    if (i915_sw_winsys(ibatch->iws)->dump_cmd) {
-      unsigned *ptr = (unsigned *)batch->base.map;
-
-      debug_printf("%s:\n", __func__);
-      for (i = 0; i < used / 4; i++, ptr++) {
-         debug_printf("\t%08x:    %08x\n", i*4, *ptr);
-      }
+      i915_dump_batchbuffer(ibatch);
    }
 
    if (fence) {
index 834805e621df2ab1c7000e6bb9fb7f8d54115c1c..9a7e90e2173509f9f6e0b2c1da13eeb40c4d64a5 100644 (file)
@@ -84,7 +84,7 @@ i915_sw_buffer_write(struct i915_winsys *iws,
 {
    struct i915_sw_buffer *buf = i915_sw_buffer(buffer);
 
-   memcpy(buf->ptr + offset, data, size);
+   memcpy((char*)buf->ptr + offset, data, size);
    return 0;
 }
 
index f97434e995df9b780fea08e35a7eb971e3225459..cc9a06a239341d4ffb889298aa6d7c369155e5ea 100644 (file)
@@ -13,7 +13,12 @@ r600_sources = [
     'r600_bomgr.c',
 ]
 
-env.ParseConfig('pkg-config --cflags libdrm_radeon')
+try:
+    env.ParseConfig('pkg-config --cflags libdrm_radeon')
+except OSError:
+    print 'warning: not building r600g'
+    Return()
+
 env.Append(CPPPATH = '#/src/gallium/drivers/r600')
 
 r600winsys = env.ConvenienceLibrary(
index 3fdafc3928378d58b51dde49ece2814957f3afcd..aa4035a302bf80daf24123aa664c437be4155fdb 100644 (file)
@@ -621,6 +621,8 @@ int evergreen_context_init(struct r600_context *ctx, struct radeon *radeon)
        /* save 16dwords space for fence mecanism */
        ctx->pm4_ndwords -= 16;
 
+       ctx->max_db = 8;
+
        LIST_INITHEAD(&ctx->fenced_bo);
 
        /* init dirty list */
index 339d5dc47f46a35d409c5b9f85d0f347b4062e17..06e8f6910f339ed49e439f9c9f52c1a9433cc231 100644 (file)
@@ -108,11 +108,10 @@ struct r600_bo *r600_bo_handle(struct radeon *radeon,
        radeon_bo_get_tiling_flags(radeon, rbo, &bo->tiling_flags, &bo->kernel_pitch);
        if (array_mode) {
                if (bo->tiling_flags) {
-                       if (bo->tiling_flags & RADEON_TILING_MICRO)
-                               *array_mode = V_0280A0_ARRAY_1D_TILED_THIN1;
-                       if ((bo->tiling_flags & (RADEON_TILING_MICRO | RADEON_TILING_MACRO)) ==
-                           (RADEON_TILING_MICRO | RADEON_TILING_MACRO))
+                       if (bo->tiling_flags & RADEON_TILING_MACRO)
                                *array_mode = V_0280A0_ARRAY_2D_TILED_THIN1;
+                       else if (bo->tiling_flags & RADEON_TILING_MICRO)
+                               *array_mode = V_0280A0_ARRAY_1D_TILED_THIN1;
                } else {
                        *array_mode = 0;
                }
index 69b0a1dcd720ac05f0e0b8c6dbe9f4afcf143bcf..f5cd48d39c67367746958bba4f77f0953fb9cee8 100644 (file)
 #define RADEON_INFO_TILING_CONFIG 0x6
 #endif
 
+#ifndef RADEON_INFO_CLOCK_CRYSTAL_FREQ
+#define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x9
+#endif
+
 enum radeon_family r600_get_family(struct radeon *r600)
 {
        return r600->family;
@@ -56,9 +60,14 @@ struct r600_tiling_info *r600_get_tiling_info(struct radeon *radeon)
        return &radeon->tiling_info;
 }
 
+unsigned r600_get_clock_crystal_freq(struct radeon *radeon)
+{
+       return radeon->clock_crystal_freq;
+}
+
 static int radeon_get_device(struct radeon *radeon)
 {
-       struct drm_radeon_info info;
+       struct drm_radeon_info info = {};
        int r;
 
        radeon->device = 0;
@@ -69,20 +78,8 @@ static int radeon_get_device(struct radeon *radeon)
        return r;
 }
 
-static int radeon_drm_get_tiling(struct radeon *radeon)
+static int r600_interpret_tiling(struct radeon *radeon, uint32_t tiling_config)
 {
-       struct drm_radeon_info info;
-       int r;
-       uint32_t tiling_config;
-
-       info.request = RADEON_INFO_TILING_CONFIG;
-       info.value = (uintptr_t)&tiling_config;
-       r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
-                               sizeof(struct drm_radeon_info));
-
-       if (r)
-               return 0;
-
        switch ((tiling_config & 0xe) >> 1) {
        case 0:
                radeon->tiling_info.num_channels = 1;
@@ -124,6 +121,80 @@ static int radeon_drm_get_tiling(struct radeon *radeon)
        return 0;
 }
 
+static int eg_interpret_tiling(struct radeon *radeon, uint32_t tiling_config)
+{
+       switch (tiling_config & 0xf) {
+       case 0:
+               radeon->tiling_info.num_channels = 1;
+               break;
+       case 1:
+               radeon->tiling_info.num_channels = 2;
+               break;
+       case 2:
+               radeon->tiling_info.num_channels = 4;
+               break;
+       case 3:
+               radeon->tiling_info.num_channels = 8;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       radeon->tiling_info.num_banks = (tiling_config & 0xf0) >> 4;
+
+       switch ((tiling_config & 0xf00) >> 8) {
+       case 0:
+               radeon->tiling_info.group_bytes = 256;
+               break;
+       case 1:
+               radeon->tiling_info.group_bytes = 512;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int radeon_drm_get_tiling(struct radeon *radeon)
+{
+       struct drm_radeon_info info;
+       int r;
+       uint32_t tiling_config = 0;
+
+       info.request = RADEON_INFO_TILING_CONFIG;
+       info.value = (uintptr_t)&tiling_config;
+       r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
+                               sizeof(struct drm_radeon_info));
+
+       if (r)
+               return 0;
+
+       if (radeon->chip_class == R600 || radeon->chip_class == R700) {
+               r = r600_interpret_tiling(radeon, tiling_config);
+       } else {
+               r = eg_interpret_tiling(radeon, tiling_config);
+       }
+       return r;
+}
+
+static int radeon_get_clock_crystal_freq(struct radeon *radeon)
+{
+       struct drm_radeon_info info;
+       uint32_t clock_crystal_freq;
+       int r;
+
+       radeon->device = 0;
+       info.request = RADEON_INFO_CLOCK_CRYSTAL_FREQ;
+       info.value = (uintptr_t)&clock_crystal_freq;
+       r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
+                       sizeof(struct drm_radeon_info));
+       if (r)
+               return r;
+
+       radeon->clock_crystal_freq = clock_crystal_freq;
+       return 0;
+}
+
 static int radeon_init_fence(struct radeon *radeon)
 {
        radeon->fence = 1;
@@ -201,10 +272,12 @@ static struct radeon *radeon_new(int fd, unsigned device)
                break;
        }
 
-       if (radeon->chip_class == R600 || radeon->chip_class == R700) {
-               if (radeon_drm_get_tiling(radeon))
-                       return NULL;
-       }
+       if (radeon_drm_get_tiling(radeon))
+               return NULL;
+
+       /* get the GPU counter frequency, failure is non fatal */
+       radeon_get_clock_crystal_freq(radeon);
+
        radeon->bomgr = r600_bomgr_create(radeon, 1000000);
        if (radeon->bomgr == NULL) {
                return NULL;
index f10e2fda6f2b530f3038b45ae818e2301258746d..f170640407d4089ad237f577f9d0c16e4fe1d352 100644 (file)
@@ -637,7 +637,8 @@ int r600_context_init(struct r600_context *ctx, struct radeon *radeon)
                ctx->range[i].end_offset = ((i + 1) << ctx->hash_shift) - 1;
                ctx->range[i].blocks = calloc(1 << ctx->hash_shift, sizeof(void*));
                if (ctx->range[i].blocks == NULL) {
-                       return -ENOMEM;
+                       r = -ENOMEM;
+                       goto out_err;
                }
        }
 
@@ -750,6 +751,9 @@ int r600_context_init(struct r600_context *ctx, struct radeon *radeon)
 
        /* init dirty list */
        LIST_INITHEAD(&ctx->dirty);
+
+       ctx->max_db = 4;
+
        return 0;
 out_err:
        r600_context_fini(ctx);
@@ -1084,7 +1088,7 @@ void r600_context_draw(struct r600_context *ctx, const struct r600_draw *draw)
 
 void r600_context_flush(struct r600_context *ctx)
 {
-       struct drm_radeon_cs drmib;
+       struct drm_radeon_cs drmib = {};
        struct drm_radeon_cs_chunk chunks[2];
        uint64_t chunk_array[2];
        unsigned fence;
@@ -1246,43 +1250,70 @@ out_err:
        bof_decref(root);
 }
 
-static void r600_query_result(struct r600_context *ctx, struct r600_query *query)
+static boolean r600_query_result(struct r600_context *ctx, struct r600_query *query, boolean wait)
 {
        u64 start, end;
        u32 *results;
        int i;
+       int size;
+
+       if (wait)
+               results = r600_bo_map(ctx->radeon, query->buffer, PB_USAGE_CPU_READ, NULL);
+       else
+               results = r600_bo_map(ctx->radeon, query->buffer, PB_USAGE_DONTBLOCK | PB_USAGE_CPU_READ, NULL);
+       if (!results)
+               return FALSE;
 
-       results = r600_bo_map(ctx->radeon, query->buffer, 0, NULL);
-       for (i = 0; i < query->num_results; i += 4) {
+       size = query->num_results * (query->type == PIPE_QUERY_OCCLUSION_COUNTER ? ctx->max_db : 1);
+       for (i = 0; i < size; 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)) {
+               if (((start & 0x8000000000000000UL) && (end & 0x8000000000000000UL))
+                    || query->type == PIPE_QUERY_TIME_ELAPSED) {
                        query->result += end - start;
                }
        }
        r600_bo_unmap(ctx->radeon, query->buffer);
        query->num_results = 0;
+
+       return TRUE;
 }
 
 void r600_query_begin(struct r600_context *ctx, struct r600_query *query)
 {
-       /* query request needs 6 dwords for begin + 6 dwords for end */
-       if ((12 + ctx->pm4_cdwords) > ctx->pm4_ndwords) {
+       unsigned required_space;
+
+       /* query request needs 6/8 dwords for begin + 6/8 dwords for end */
+       if (query->type == PIPE_QUERY_TIME_ELAPSED)
+               required_space = 16;
+       else
+               required_space = 12;
+
+       if ((required_space + ctx->pm4_cdwords) > ctx->pm4_ndwords) {
                /* need to flush */
                r600_context_flush(ctx);
        }
 
        /* if query buffer is full force a flush */
-       if (query->num_results >= ((query->buffer_size >> 2) - 2)) {
+       if (query->num_results*4 >= query->buffer_size - 16) {
                r600_context_flush(ctx);
-               r600_query_result(ctx, query);
+               r600_query_result(ctx, query, TRUE);
        }
 
        /* emit begin query */
-       ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2);
-       ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1);
-       ctx->pm4[ctx->pm4_cdwords++] = query->num_results + r600_bo_offset(query->buffer);
-       ctx->pm4[ctx->pm4_cdwords++] = 0;
+       if (query->type == PIPE_QUERY_TIME_ELAPSED) {
+               ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE_EOP, 4);
+               ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5);
+               ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + r600_bo_offset(query->buffer);
+               ctx->pm4[ctx->pm4_cdwords++] = (3 << 29);
+               ctx->pm4[ctx->pm4_cdwords++] = 0;
+               ctx->pm4[ctx->pm4_cdwords++] = 0;
+       } else {
+               ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2);
+               ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1);
+               ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + r600_bo_offset(query->buffer);
+               ctx->pm4[ctx->pm4_cdwords++] = 0;
+       }
        ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0);
        ctx->pm4[ctx->pm4_cdwords++] = 0;
        r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], query->buffer);
@@ -1295,15 +1326,24 @@ void r600_query_begin(struct r600_context *ctx, struct r600_query *query)
 void r600_query_end(struct r600_context *ctx, struct r600_query *query)
 {
        /* emit begin query */
-       ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2);
-       ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1);
-       ctx->pm4[ctx->pm4_cdwords++] = query->num_results + 8 + r600_bo_offset(query->buffer);
-       ctx->pm4[ctx->pm4_cdwords++] = 0;
+       if (query->type == PIPE_QUERY_TIME_ELAPSED) {
+               ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE_EOP, 4);
+               ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5);
+               ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + 8 + r600_bo_offset(query->buffer);
+               ctx->pm4[ctx->pm4_cdwords++] = (3 << 29);
+               ctx->pm4[ctx->pm4_cdwords++] = 0;
+               ctx->pm4[ctx->pm4_cdwords++] = 0;
+       } else {
+               ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2);
+               ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1);
+               ctx->pm4[ctx->pm4_cdwords++] = query->num_results*4 + 8 + r600_bo_offset(query->buffer);
+               ctx->pm4[ctx->pm4_cdwords++] = 0;
+       }
        ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0);
        ctx->pm4[ctx->pm4_cdwords++] = 0;
        r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], query->buffer);
 
-       query->num_results += 16;
+       query->num_results += 4 * (query->type == PIPE_QUERY_OCCLUSION_COUNTER ? ctx->max_db : 1);
        query->state ^= R600_QUERY_STATE_STARTED;
        query->state |= R600_QUERY_STATE_ENDED;
        ctx->num_query_running--;
@@ -1313,7 +1353,7 @@ struct r600_query *r600_context_query_create(struct r600_context *ctx, unsigned
 {
        struct r600_query *query;
 
-       if (query_type != PIPE_QUERY_OCCLUSION_COUNTER)
+       if (query_type != PIPE_QUERY_OCCLUSION_COUNTER && query_type != PIPE_QUERY_TIME_ELAPSED)
                return NULL;
 
        query = calloc(1, sizeof(struct r600_query));
@@ -1355,8 +1395,12 @@ boolean r600_context_query_result(struct r600_context *ctx,
        if (query->num_results) {
                r600_context_flush(ctx);
        }
-       r600_query_result(ctx, query);
-       *result = query->result;
+       if (!r600_query_result(ctx, query, wait))
+               return FALSE;
+       if (query->type == PIPE_QUERY_TIME_ELAPSED)
+               *result = (1000000*query->result)/r600_get_clock_crystal_freq(ctx->radeon);
+       else
+               *result = query->result;
        query->result = 0;
        return TRUE;
 }
index a38a6481b4febf8d9ed294ecb3f13e28dc8cc7f0..2d91cd97d6854bf4f13f207879b703c37688d475 100644 (file)
@@ -49,6 +49,7 @@ struct radeon {
        unsigned                        fence;
        unsigned                        *cfence;
        struct r600_bo                  *fence_bo;
+       unsigned                        clock_crystal_freq;
 };
 
 struct r600_reg {
index 999de82646d307e2e6955efdd1aec5e518000ab6..3643ddbcb93ebbd1af40928885fcf3a922bf1039 100644 (file)
@@ -98,7 +98,7 @@ struct radeon_bo *radeon_bo(struct radeon *radeon, unsigned handle,
                bo->size = open_arg.size;
                bo->shared = TRUE;
        } else {
-               struct drm_radeon_gem_create args;
+               struct drm_radeon_gem_create args = {};
 
                args.size = size;
                args.alignment = alignment;
@@ -204,7 +204,7 @@ int radeon_bo_get_tiling_flags(struct radeon *radeon,
                               uint32_t *tiling_flags,
                               uint32_t *pitch)
 {
-       struct drm_radeon_gem_get_tiling args;
+       struct drm_radeon_gem_get_tiling args = {};
        int ret;
 
        args.handle = bo->handle;
index 06681791e579b0bfa206e8c015a8fdb35701e0a9..f19956931de3b8152c6aaa3c31706bf4813c2cde 100644 (file)
@@ -32,7 +32,7 @@ struct pci_id {
        unsigned        family;
 };
 
-struct pci_id radeon_pci_id[] = {
+static const struct pci_id radeon_pci_id[] = {
        {0x1002, 0x3150, CHIP_RV380},
        {0x1002, 0x3152, CHIP_RV380},
        {0x1002, 0x3154, CHIP_RV380},
index 7e339a2ecfeffd418f51b70b4f0ce675e57da663..e63ae6f500602deb04fa91fd7211842d0fdd14d1 100644 (file)
@@ -5,10 +5,9 @@ include $(TOP)/configs/current
 LIBNAME = radeonwinsys
 
 C_SOURCES = \
-       radeon_drm_buffer.c \
+       radeon_drm_bo.c \
        radeon_drm_cs.c \
-       radeon_drm_common.c \
-       radeon_r300.c
+       radeon_drm_common.c
 
 LIBRARY_INCLUDES = -I$(TOP)/src/gallium/drivers/r300 \
                   $(shell pkg-config libdrm --cflags-only-I)
index 80816621848e2afc223524b5ad366c09d4f18c9b..b16e03556d39211dea9a65e53e24cbc2dc89b947 100644 (file)
@@ -3,13 +3,17 @@ Import('*')
 env = env.Clone()
 
 radeon_sources = [
-    'radeon_drm_buffer.c',
+    'radeon_drm_bo.c',
     'radeon_drm_cs.c',
     'radeon_drm_common.c',
-    'radeon_r300.c',
 ]
 
-env.ParseConfig('pkg-config --cflags libdrm_radeon')
+try:
+    env.ParseConfig('pkg-config --cflags libdrm_radeon')
+except:
+    print 'warning: not building r300g'
+    Return()
+
 env.Append(CPPPATH = '#/src/gallium/drivers/r300')
 
 radeonwinsys = env.ConvenienceLibrary(
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
new file mode 100644 (file)
index 0000000..3094337
--- /dev/null
@@ -0,0 +1,599 @@
+/*
+ * Copyright © 2011 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, 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.
+ */
+
+#define _FILE_OFFSET_BITS 64
+#include "radeon_drm_cs.h"
+
+#include "util/u_hash_table.h"
+#include "util/u_memory.h"
+#include "util/u_simple_list.h"
+#include "os/os_thread.h"
+
+#include "state_tracker/drm_driver.h"
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <xf86drm.h>
+#include <errno.h>
+
+#define RADEON_BO_FLAGS_MACRO_TILE  1
+#define RADEON_BO_FLAGS_MICRO_TILE  2
+#define RADEON_BO_FLAGS_MICRO_TILE_SQUARE 0x20
+
+extern const struct pb_vtbl radeon_bo_vtbl;
+
+
+static INLINE struct radeon_bo *radeon_bo(struct pb_buffer *bo)
+{
+    assert(bo->vtbl == &radeon_bo_vtbl);
+    return (struct radeon_bo *)bo;
+}
+
+struct radeon_bomgr {
+    /* Base class. */
+    struct pb_manager base;
+
+    /* Winsys. */
+    struct radeon_drm_winsys *rws;
+
+    /* List of buffer handles and its mutex. */
+    struct util_hash_table *bo_handles;
+    pipe_mutex bo_handles_mutex;
+};
+
+static INLINE struct radeon_bomgr *radeon_bomgr(struct pb_manager *mgr)
+{
+    return (struct radeon_bomgr *)mgr;
+}
+
+static struct radeon_bo *get_radeon_bo(struct pb_buffer *_buf)
+{
+    struct radeon_bo *bo = NULL;
+
+    if (_buf->vtbl == &radeon_bo_vtbl) {
+        bo = radeon_bo(_buf);
+    } else {
+       struct pb_buffer *base_buf;
+       pb_size offset;
+       pb_get_base_buffer(_buf, &base_buf, &offset);
+
+        if (base_buf->vtbl == &radeon_bo_vtbl)
+            bo = radeon_bo(base_buf);
+    }
+
+    return bo;
+}
+
+void radeon_bo_unref(struct radeon_bo *bo)
+{
+    struct drm_gem_close args = {};
+
+    if (!p_atomic_dec_zero(&bo->ref_count))
+        return;
+
+    if (bo->name) {
+        pipe_mutex_lock(bo->mgr->bo_handles_mutex);
+        util_hash_table_remove(bo->mgr->bo_handles,
+                              (void*)(uintptr_t)bo->name);
+        pipe_mutex_unlock(bo->mgr->bo_handles_mutex);
+    }
+
+    if (bo->ptr)
+        munmap(bo->ptr, bo->size);
+
+    /* Close object. */
+    args.handle = bo->handle;
+    drmIoctl(bo->rws->fd, DRM_IOCTL_GEM_CLOSE, &args);
+    pipe_mutex_destroy(bo->map_mutex);
+    FREE(bo);
+}
+
+static void radeon_bo_wait(struct r300_winsys_bo *_buf)
+{
+    struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf));
+    struct drm_radeon_gem_wait_idle args = {};
+
+    while (p_atomic_read(&bo->num_active_ioctls)) {
+        sched_yield();
+    }
+
+    args.handle = bo->handle;
+    while (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT_IDLE,
+                               &args, sizeof(args)) == -EBUSY);
+}
+
+static boolean radeon_bo_is_busy(struct r300_winsys_bo *_buf)
+{
+    struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf));
+    struct drm_radeon_gem_busy args = {};
+
+    if (p_atomic_read(&bo->num_active_ioctls)) {
+        return TRUE;
+    }
+
+    args.handle = bo->handle;
+    return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY,
+                               &args, sizeof(args)) != 0;
+}
+
+static void radeon_bo_destroy(struct pb_buffer *_buf)
+{
+    struct radeon_bo *bo = radeon_bo(_buf);
+
+    radeon_bo_unref(bo);
+}
+
+static unsigned get_pb_usage_from_transfer_flags(enum pipe_transfer_usage usage)
+{
+    unsigned res = 0;
+
+    if (usage & PIPE_TRANSFER_DONTBLOCK)
+        res |= PB_USAGE_DONTBLOCK;
+
+    if (usage & PIPE_TRANSFER_UNSYNCHRONIZED)
+        res |= PB_USAGE_UNSYNCHRONIZED;
+
+    return res;
+}
+
+static void *radeon_bo_map_internal(struct pb_buffer *_buf,
+                                    unsigned flags, void *flush_ctx)
+{
+    struct radeon_bo *bo = radeon_bo(_buf);
+    struct radeon_drm_cs *cs = flush_ctx;
+    struct drm_radeon_gem_mmap args = {};
+    void *ptr;
+
+    /* If it's not unsynchronized bo_map, flush CS if needed and then wait. */
+    if (!(flags & PB_USAGE_UNSYNCHRONIZED)) {
+        /* DONTBLOCK doesn't make sense with UNSYNCHRONIZED. */
+        if (flags & PB_USAGE_DONTBLOCK) {
+            if (radeon_bo_is_referenced_by_cs(cs, bo)) {
+                cs->flush_cs(cs->flush_data);
+                return NULL;
+            }
+
+            if (radeon_bo_is_busy((struct r300_winsys_bo*)bo)) {
+                return NULL;
+            }
+        } else {
+            if (radeon_bo_is_referenced_by_cs(cs, bo)) {
+                cs->flush_cs(cs->flush_data);
+            }
+
+            radeon_bo_wait((struct r300_winsys_bo*)bo);
+        }
+    }
+
+    /* Return the pointer if it's already mapped. */
+    if (bo->ptr)
+        return bo->ptr;
+
+    /* Map the buffer. */
+    pipe_mutex_lock(bo->map_mutex);
+    args.handle = bo->handle;
+    args.offset = 0;
+    args.size = (uint64_t)bo->size;
+    if (drmCommandWriteRead(bo->rws->fd,
+                            DRM_RADEON_GEM_MMAP,
+                            &args,
+                            sizeof(args))) {
+        pipe_mutex_unlock(bo->map_mutex);
+        fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n",
+                bo, bo->handle);
+        return NULL;
+    }
+
+    ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED,
+               bo->rws->fd, args.addr_ptr);
+    if (ptr == MAP_FAILED) {
+        pipe_mutex_unlock(bo->map_mutex);
+        fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno);
+        return NULL;
+    }
+    bo->ptr = ptr;
+    pipe_mutex_unlock(bo->map_mutex);
+
+    return bo->ptr;
+}
+
+static void radeon_bo_unmap_internal(struct pb_buffer *_buf)
+{
+    /* NOP */
+}
+
+static void radeon_bo_get_base_buffer(struct pb_buffer *buf,
+                                     struct pb_buffer **base_buf,
+                                     unsigned *offset)
+{
+    *base_buf = buf;
+    *offset = 0;
+}
+
+static enum pipe_error radeon_bo_validate(struct pb_buffer *_buf,
+                                         struct pb_validate *vl,
+                                         unsigned flags)
+{
+    /* Always pinned */
+    return PIPE_OK;
+}
+
+static void radeon_bo_fence(struct pb_buffer *buf,
+                            struct pipe_fence_handle *fence)
+{
+}
+
+const struct pb_vtbl radeon_bo_vtbl = {
+    radeon_bo_destroy,
+    radeon_bo_map_internal,
+    radeon_bo_unmap_internal,
+    radeon_bo_validate,
+    radeon_bo_fence,
+    radeon_bo_get_base_buffer,
+};
+
+static struct pb_buffer *radeon_bomgr_create_bo(struct pb_manager *_mgr,
+                                               pb_size size,
+                                               const struct pb_desc *desc)
+{
+    struct radeon_bomgr *mgr = radeon_bomgr(_mgr);
+    struct radeon_drm_winsys *rws = mgr->rws;
+    struct radeon_bo *bo;
+    struct drm_radeon_gem_create args = {};
+
+    args.size = size;
+    args.alignment = desc->alignment;
+    args.initial_domain =
+        (desc->usage & RADEON_PB_USAGE_DOMAIN_GTT  ?
+         RADEON_GEM_DOMAIN_GTT  : 0) |
+        (desc->usage & RADEON_PB_USAGE_DOMAIN_VRAM ?
+         RADEON_GEM_DOMAIN_VRAM : 0);
+
+    if (drmCommandWriteRead(rws->fd, DRM_RADEON_GEM_CREATE,
+                            &args, sizeof(args))) {
+        fprintf(stderr, "Failed to allocate :\n");
+        fprintf(stderr, "   size      : %d bytes\n", size);
+        fprintf(stderr, "   alignment : %d bytes\n", desc->alignment);
+        fprintf(stderr, "   domains   : %d\n", args.initial_domain);
+        return NULL;
+    }
+
+    bo = CALLOC_STRUCT(radeon_bo);
+    if (!bo)
+       return NULL;
+
+    pipe_reference_init(&bo->base.base.reference, 1);
+    bo->base.base.alignment = desc->alignment;
+    bo->base.base.usage = desc->usage;
+    bo->base.base.size = size;
+    bo->base.vtbl = &radeon_bo_vtbl;
+    bo->mgr = mgr;
+    bo->rws = mgr->rws;
+    bo->handle = args.handle;
+    bo->size = size;
+    pipe_mutex_init(bo->map_mutex);
+
+    radeon_bo_ref(bo);
+    return &bo->base;
+}
+
+static void radeon_bomgr_flush(struct pb_manager *mgr)
+{
+    /* NOP */
+}
+
+/* This is for the cache bufmgr. */
+static boolean radeon_bomgr_is_buffer_busy(struct pb_manager *_mgr,
+                                           struct pb_buffer *_buf)
+{
+   struct radeon_bo *bo = radeon_bo(_buf);
+
+   if (radeon_bo_is_referenced_by_any_cs(bo)) {
+       return TRUE;
+   }
+
+   if (radeon_bo_is_busy((struct r300_winsys_bo*)bo)) {
+       return TRUE;
+   }
+
+   return FALSE;
+}
+
+static void radeon_bomgr_destroy(struct pb_manager *_mgr)
+{
+    struct radeon_bomgr *mgr = radeon_bomgr(_mgr);
+    util_hash_table_destroy(mgr->bo_handles);
+    pipe_mutex_destroy(mgr->bo_handles_mutex);
+    FREE(mgr);
+}
+
+#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x)))
+
+static unsigned handle_hash(void *key)
+{
+    return PTR_TO_UINT(key);
+}
+
+static int handle_compare(void *key1, void *key2)
+{
+    return PTR_TO_UINT(key1) != PTR_TO_UINT(key2);
+}
+
+struct pb_manager *radeon_bomgr_create(struct radeon_drm_winsys *rws)
+{
+    struct radeon_bomgr *mgr;
+
+    mgr = CALLOC_STRUCT(radeon_bomgr);
+    if (!mgr)
+       return NULL;
+
+    mgr->base.destroy = radeon_bomgr_destroy;
+    mgr->base.create_buffer = radeon_bomgr_create_bo;
+    mgr->base.flush = radeon_bomgr_flush;
+    mgr->base.is_buffer_busy = radeon_bomgr_is_buffer_busy;
+
+    mgr->rws = rws;
+    mgr->bo_handles = util_hash_table_create(handle_hash, handle_compare);
+    pipe_mutex_init(mgr->bo_handles_mutex);
+    return &mgr->base;
+}
+
+static void *radeon_bo_map(struct r300_winsys_bo *buf,
+                           struct r300_winsys_cs *cs,
+                           enum pipe_transfer_usage usage)
+{
+    struct pb_buffer *_buf = pb_buffer(buf);
+
+    return pb_map(_buf, get_pb_usage_from_transfer_flags(usage), cs);
+}
+
+static void radeon_bo_get_tiling(struct r300_winsys_bo *_buf,
+                                 enum r300_buffer_tiling *microtiled,
+                                 enum r300_buffer_tiling *macrotiled)
+{
+    struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf));
+    struct drm_radeon_gem_set_tiling args = {};
+
+    args.handle = bo->handle;
+
+    drmCommandWriteRead(bo->rws->fd,
+                        DRM_RADEON_GEM_GET_TILING,
+                        &args,
+                        sizeof(args));
+
+    *microtiled = R300_BUFFER_LINEAR;
+    *macrotiled = R300_BUFFER_LINEAR;
+    if (args.tiling_flags & RADEON_BO_FLAGS_MICRO_TILE)
+       *microtiled = R300_BUFFER_TILED;
+
+    if (args.tiling_flags & RADEON_BO_FLAGS_MACRO_TILE)
+       *macrotiled = R300_BUFFER_TILED;
+}
+
+static void radeon_bo_set_tiling(struct r300_winsys_bo *_buf,
+                                 struct r300_winsys_cs *rcs,
+                                 enum r300_buffer_tiling microtiled,
+                                 enum r300_buffer_tiling macrotiled,
+                                 uint32_t pitch)
+{
+    struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf));
+    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
+    struct drm_radeon_gem_set_tiling args = {};
+
+    /* Tiling determines how DRM treats the buffer data.
+     * We must flush CS when changing it if the buffer is referenced. */
+    if (cs && radeon_bo_is_referenced_by_cs(cs, bo)) {
+        radeon_drm_cs_flush(rcs);
+        radeon_drm_cs_sync_flush(rcs);
+    }
+
+    while (p_atomic_read(&bo->num_active_ioctls)) {
+        sched_yield();
+    }
+
+    if (microtiled == R300_BUFFER_TILED)
+        args.tiling_flags |= RADEON_BO_FLAGS_MICRO_TILE;
+    else if (microtiled == R300_BUFFER_SQUARETILED)
+        args.tiling_flags |= RADEON_BO_FLAGS_MICRO_TILE_SQUARE;
+
+    if (macrotiled == R300_BUFFER_TILED)
+        args.tiling_flags |= RADEON_BO_FLAGS_MACRO_TILE;
+
+    args.handle = bo->handle;
+    args.pitch = pitch;
+
+    drmCommandWriteRead(bo->rws->fd,
+                        DRM_RADEON_GEM_SET_TILING,
+                        &args,
+                        sizeof(args));
+}
+
+static struct r300_winsys_cs_handle *radeon_drm_get_cs_handle(
+        struct r300_winsys_bo *_buf)
+{
+    /* return radeon_bo. */
+    return (struct r300_winsys_cs_handle*)
+            get_radeon_bo(pb_buffer(_buf));
+}
+
+static unsigned get_pb_usage_from_create_flags(unsigned bind, unsigned usage,
+                                               enum r300_buffer_domain domain)
+{
+    unsigned res = 0;
+
+    if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
+        res |= RADEON_PB_USAGE_CACHE;
+
+    if (domain & R300_DOMAIN_GTT)
+        res |= RADEON_PB_USAGE_DOMAIN_GTT;
+
+    if (domain & R300_DOMAIN_VRAM)
+        res |= RADEON_PB_USAGE_DOMAIN_VRAM;
+
+    return res;
+}
+
+static struct r300_winsys_bo *
+radeon_winsys_bo_create(struct r300_winsys_screen *rws,
+                        unsigned size,
+                        unsigned alignment,
+                        unsigned bind,
+                        unsigned usage,
+                        enum r300_buffer_domain domain)
+{
+    struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
+    struct pb_desc desc;
+    struct pb_manager *provider;
+    struct pb_buffer *buffer;
+
+    memset(&desc, 0, sizeof(desc));
+    desc.alignment = alignment;
+    desc.usage = get_pb_usage_from_create_flags(bind, usage, domain);
+
+    /* Assign a buffer manager. */
+    if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
+       provider = ws->cman;
+    else
+        provider = ws->kman;
+
+    buffer = provider->create_buffer(provider, size, &desc);
+    if (!buffer)
+       return NULL;
+
+    return (struct r300_winsys_bo*)buffer;
+}
+
+static struct r300_winsys_bo *radeon_winsys_bo_from_handle(struct r300_winsys_screen *rws,
+                                                           struct winsys_handle *whandle,
+                                                           unsigned *stride,
+                                                           unsigned *size)
+{
+    struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
+    struct radeon_bo *bo;
+    struct radeon_bomgr *mgr = radeon_bomgr(ws->kman);
+    struct drm_gem_open open_arg = {};
+
+    /* We must maintain a list of pairs <handle, bo>, so that we always return
+     * the same BO for one particular handle. If we didn't do that and created
+     * more than one BO for the same handle and then relocated them in a CS,
+     * we would hit a deadlock in the kernel.
+     *
+     * The list of pairs is guarded by a mutex, of course. */
+    pipe_mutex_lock(mgr->bo_handles_mutex);
+
+    /* First check if there already is an existing bo for the handle. */
+    bo = util_hash_table_get(mgr->bo_handles, (void*)(uintptr_t)whandle->handle);
+    if (bo) {
+        /* Increase the refcount. */
+        struct pb_buffer *b = NULL;
+        pb_reference(&b, &bo->base);
+        goto done;
+    }
+
+    /* There isn't, create a new one. */
+    bo = CALLOC_STRUCT(radeon_bo);
+    if (!bo) {
+        goto fail;
+    }
+
+    /* Open the BO. */
+    open_arg.name = whandle->handle;
+    if (drmIoctl(ws->fd, DRM_IOCTL_GEM_OPEN, &open_arg)) {
+        FREE(bo);
+        goto fail;
+    }
+    bo->handle = open_arg.handle;
+    bo->size = open_arg.size;
+    bo->name = whandle->handle;
+    radeon_bo_ref(bo);
+
+    /* Initialize it. */
+    pipe_reference_init(&bo->base.base.reference, 1);
+    bo->base.base.alignment = 0;
+    bo->base.base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ;
+    bo->base.base.size = bo->size;
+    bo->base.vtbl = &radeon_bo_vtbl;
+    bo->mgr = mgr;
+    bo->rws = mgr->rws;
+    pipe_mutex_init(bo->map_mutex);
+
+    util_hash_table_set(mgr->bo_handles, (void*)(uintptr_t)whandle->handle, bo);
+
+done:
+    pipe_mutex_unlock(mgr->bo_handles_mutex);
+
+    if (stride)
+        *stride = whandle->stride;
+    if (size)
+        *size = bo->base.base.size;
+
+    return (struct r300_winsys_bo*)bo;
+
+fail:
+    pipe_mutex_unlock(mgr->bo_handles_mutex);
+    return NULL;
+}
+
+static boolean radeon_winsys_bo_get_handle(struct r300_winsys_bo *buffer,
+                                           unsigned stride,
+                                           struct winsys_handle *whandle)
+{
+    struct drm_gem_flink flink = {};
+    struct radeon_bo *bo = get_radeon_bo(pb_buffer(buffer));
+
+    if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
+        if (!bo->flinked) {
+            flink.handle = bo->handle;
+
+            if (ioctl(bo->rws->fd, DRM_IOCTL_GEM_FLINK, &flink)) {
+                return FALSE;
+            }
+
+            bo->flinked = TRUE;
+            bo->flink = flink.name;
+        }
+        whandle->handle = bo->flink;
+    } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
+        whandle->handle = bo->handle;
+    }
+
+    whandle->stride = stride;
+    return TRUE;
+}
+
+void radeon_bomgr_init_functions(struct radeon_drm_winsys *ws)
+{
+    ws->base.buffer_get_cs_handle = radeon_drm_get_cs_handle;
+    ws->base.buffer_set_tiling = radeon_bo_set_tiling;
+    ws->base.buffer_get_tiling = radeon_bo_get_tiling;
+    ws->base.buffer_map = radeon_bo_map;
+    ws->base.buffer_unmap = pb_unmap;
+    ws->base.buffer_wait = radeon_bo_wait;
+    ws->base.buffer_is_busy = radeon_bo_is_busy;
+    ws->base.buffer_create = radeon_winsys_bo_create;
+    ws->base.buffer_from_handle = radeon_winsys_bo_from_handle;
+    ws->base.buffer_get_handle = radeon_winsys_bo_get_handle;
+}
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.h b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h
new file mode 100644 (file)
index 0000000..a26866b
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright © 2008 Jérôme Glisse
+ * Copyright © 2011 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, 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.
+ */
+/*
+ * Authors:
+ *      Jérôme Glisse <glisse@freedesktop.org>
+ *      Marek Olšák <maraeo@gmail.com>
+ */
+#ifndef RADEON_DRM_BUFFER_H
+#define RADEON_DRM_BUFFER_H
+
+#include "radeon_winsys.h"
+#include "pipebuffer/pb_bufmgr.h"
+#include "os/os_thread.h"
+
+#define RADEON_PB_USAGE_CACHE       (1 << 28)
+#define RADEON_PB_USAGE_DOMAIN_GTT  (1 << 29)
+#define RADEON_PB_USAGE_DOMAIN_VRAM (1 << 30)
+
+struct radeon_bomgr;
+
+struct radeon_bo {
+    struct pb_buffer base;
+    struct radeon_bomgr *mgr;
+    struct radeon_drm_winsys *rws;
+
+    void *ptr;
+    pipe_mutex map_mutex;
+
+    uint32_t size;
+    uint32_t handle;
+    uint32_t name;
+
+    int ref_count;
+
+    /* how many command streams is this bo referenced in? */
+    int num_cs_references;
+
+    /* how many command streams, which are being emitted in a separate
+     * thread, is this bo referenced in? */
+    int num_active_ioctls;
+
+    boolean flinked;
+    uint32_t flink;
+};
+
+struct pb_manager *radeon_bomgr_create(struct radeon_drm_winsys *rws);
+void radeon_bomgr_init_functions(struct radeon_drm_winsys *ws);
+
+void radeon_bo_unref(struct radeon_bo *buf);
+
+
+static INLINE void radeon_bo_ref(struct radeon_bo *bo)
+{
+    p_atomic_inc(&bo->ref_count);
+}
+
+static INLINE struct pb_buffer *
+pb_buffer(struct r300_winsys_bo *buffer)
+{
+    return (struct pb_buffer *)buffer;
+}
+
+#endif
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
deleted file mode 100644 (file)
index 5e14287..0000000
+++ /dev/null
@@ -1,532 +0,0 @@
-#include "radeon_drm_buffer.h"
-#include "radeon_drm_cs.h"
-
-#include "util/u_hash_table.h"
-#include "util/u_memory.h"
-#include "util/u_simple_list.h"
-#include "pipebuffer/pb_bufmgr.h"
-#include "os/os_thread.h"
-
-#include "state_tracker/drm_driver.h"
-
-#include <radeon_drm.h>
-#include <radeon_bo_gem.h>
-#include <sys/ioctl.h>
-
-struct radeon_drm_bufmgr;
-
-struct radeon_drm_buffer {
-    struct pb_buffer base;
-    struct radeon_drm_bufmgr *mgr;
-
-    struct radeon_bo *bo;
-
-    boolean flinked;
-    uint32_t flink;
-
-    struct radeon_drm_buffer *next, *prev;
-};
-
-extern const struct pb_vtbl radeon_drm_buffer_vtbl;
-
-
-static INLINE struct radeon_drm_buffer *
-radeon_drm_buffer(struct pb_buffer *buf)
-{
-    assert(buf);
-    assert(buf->vtbl == &radeon_drm_buffer_vtbl);
-    return (struct radeon_drm_buffer *)buf;
-}
-
-struct radeon_drm_bufmgr {
-    /* Base class. */
-    struct pb_manager base;
-
-    /* Winsys. */
-    struct radeon_drm_winsys *rws;
-
-    /* List of mapped buffers and its mutex. */
-    struct radeon_drm_buffer buffer_map_list;
-    pipe_mutex buffer_map_list_mutex;
-
-    /* List of buffer handles and its mutex. */
-    struct util_hash_table *buffer_handles;
-    pipe_mutex buffer_handles_mutex;
-};
-
-static INLINE struct radeon_drm_bufmgr *
-radeon_drm_bufmgr(struct pb_manager *mgr)
-{
-    assert(mgr);
-    return (struct radeon_drm_bufmgr *)mgr;
-}
-
-static void
-radeon_drm_buffer_destroy(struct pb_buffer *_buf)
-{
-    struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
-    int name;
-
-    if (buf->bo->ptr != NULL) {
-        pipe_mutex_lock(buf->mgr->buffer_map_list_mutex);
-        /* Now test it again inside the mutex. */
-        if (buf->bo->ptr != NULL) {
-            remove_from_list(buf);
-            radeon_bo_unmap(buf->bo);
-            buf->bo->ptr = NULL;
-        }
-        pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex);
-    }
-    name = radeon_gem_name_bo(buf->bo);
-    if (name) {
-        pipe_mutex_lock(buf->mgr->buffer_handles_mutex);
-       util_hash_table_remove(buf->mgr->buffer_handles,
-                              (void*)(uintptr_t)name);
-        pipe_mutex_unlock(buf->mgr->buffer_handles_mutex);
-    }
-    radeon_bo_unref(buf->bo);
-
-    FREE(buf);
-}
-
-static unsigned get_pb_usage_from_transfer_flags(enum pipe_transfer_usage usage)
-{
-    unsigned res = 0;
-
-    if (usage & PIPE_TRANSFER_READ)
-        res |= PB_USAGE_CPU_READ;
-
-    if (usage & PIPE_TRANSFER_WRITE)
-        res |= PB_USAGE_CPU_WRITE;
-
-    if (usage & PIPE_TRANSFER_DONTBLOCK)
-        res |= PB_USAGE_DONTBLOCK;
-
-    if (usage & PIPE_TRANSFER_UNSYNCHRONIZED)
-        res |= PB_USAGE_UNSYNCHRONIZED;
-
-    return res;
-}
-
-static void *
-radeon_drm_buffer_map_internal(struct pb_buffer *_buf,
-                              unsigned flags, void *flush_ctx)
-{
-    struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
-    struct radeon_drm_cs *cs = flush_ctx;
-    int write = 0;
-
-    /* Note how we use radeon_bo_is_referenced_by_cs here. There are
-     * basically two places this map function can be called from:
-     * - pb_map
-     * - create_buffer (in the buffer reuse case)
-     *
-     * Since pb managers are per-winsys managers, not per-context managers,
-     * and we shouldn't reuse buffers if they are in-use in any context,
-     * we simply ask: is this buffer referenced by *any* CS?
-     *
-     * The problem with buffer_create is that it comes from pipe_screen,
-     * so we have no CS to look at, though luckily the following code
-     * is sufficient to tell whether the buffer is in use. */
-    if (flags & PB_USAGE_DONTBLOCK) {
-        if (_buf->base.usage & RADEON_PB_USAGE_VERTEX)
-            if (radeon_bo_is_referenced_by_cs(buf->bo, NULL))
-               return NULL;
-    }
-
-    if (buf->bo->ptr != NULL) {
-        pipe_mutex_lock(buf->mgr->buffer_map_list_mutex);
-        /* Now test ptr again inside the mutex. We might have gotten a race
-         * during the first test. */
-        if (buf->bo->ptr != NULL) {
-            remove_from_list(buf);
-        }
-        pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex);
-       return buf->bo->ptr;
-    }
-
-    if (flags & PB_USAGE_DONTBLOCK) {
-        uint32_t domain;
-        if (radeon_bo_is_busy(buf->bo, &domain))
-            return NULL;
-    }
-
-    /* If we don't have any CS and the buffer is referenced,
-     * we cannot flush. */
-    assert(cs || !radeon_bo_is_referenced_by_cs(buf->bo, NULL));
-
-    if (cs && radeon_bo_is_referenced_by_cs(buf->bo, NULL)) {
-        cs->flush_cs(cs->flush_data);
-    }
-
-    if (flags & PB_USAGE_CPU_WRITE) {
-        write = 1;
-    }
-
-    if (radeon_bo_map(buf->bo, write)) {
-        return NULL;
-    }
-
-    pipe_mutex_lock(buf->mgr->buffer_map_list_mutex);
-    remove_from_list(buf);
-    pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex);
-    return buf->bo->ptr;
-}
-
-static void
-radeon_drm_buffer_unmap_internal(struct pb_buffer *_buf)
-{
-    struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
-    pipe_mutex_lock(buf->mgr->buffer_map_list_mutex);
-    if (is_empty_list(buf)) { /* = is not inserted... */
-        insert_at_tail(&buf->mgr->buffer_map_list, buf);
-    }
-    pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex);
-}
-
-static void
-radeon_drm_buffer_get_base_buffer(struct pb_buffer *buf,
-                                 struct pb_buffer **base_buf,
-                                 unsigned *offset)
-{
-    *base_buf = buf;
-    *offset = 0;
-}
-
-
-static enum pipe_error
-radeon_drm_buffer_validate(struct pb_buffer *_buf,
-                          struct pb_validate *vl,
-                          unsigned flags)
-{
-   /* Always pinned */
-   return PIPE_OK;
-}
-
-static void
-radeon_drm_buffer_fence(struct pb_buffer *buf,
-                       struct pipe_fence_handle *fence)
-{
-}
-
-const struct pb_vtbl radeon_drm_buffer_vtbl = {
-    radeon_drm_buffer_destroy,
-    radeon_drm_buffer_map_internal,
-    radeon_drm_buffer_unmap_internal,
-    radeon_drm_buffer_validate,
-    radeon_drm_buffer_fence,
-    radeon_drm_buffer_get_base_buffer,
-};
-
-static struct pb_buffer *
-radeon_drm_bufmgr_create_buffer_from_handle_unsafe(struct pb_manager *_mgr,
-                                                   uint32_t handle)
-{
-    struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
-    struct radeon_drm_winsys *rws = mgr->rws;
-    struct radeon_drm_buffer *buf;
-    struct radeon_bo *bo;
-
-    buf = util_hash_table_get(mgr->buffer_handles, (void*)(uintptr_t)handle);
-
-    if (buf) {
-        struct pb_buffer *b = NULL;
-        pb_reference(&b, &buf->base);
-        return b;
-    }
-
-    bo = radeon_bo_open(rws->bom, handle, 0,
-                       0, 0, 0);
-    if (bo == NULL)
-       return NULL;
-
-    buf = CALLOC_STRUCT(radeon_drm_buffer);
-    if (!buf) {
-       radeon_bo_unref(bo);
-       return NULL;
-    }
-
-    make_empty_list(buf);
-
-    pipe_reference_init(&buf->base.base.reference, 1);
-    buf->base.base.alignment = 0;
-    buf->base.base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ;
-    buf->base.base.size = bo->size;
-    buf->base.vtbl = &radeon_drm_buffer_vtbl;
-    buf->mgr = mgr;
-
-    buf->bo = bo;
-
-    util_hash_table_set(mgr->buffer_handles, (void*)(uintptr_t)handle, buf);
-
-    return &buf->base;
-}
-
-struct pb_buffer *
-radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr,
-                                            uint32_t handle)
-{
-    struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
-    struct pb_buffer *pb;
-
-    pipe_mutex_lock(mgr->buffer_handles_mutex);
-    pb = radeon_drm_bufmgr_create_buffer_from_handle_unsafe(_mgr, handle);
-    pipe_mutex_unlock(mgr->buffer_handles_mutex);
-
-    return pb;
-}
-
-static struct pb_buffer *
-radeon_drm_bufmgr_create_buffer(struct pb_manager *_mgr,
-                               pb_size size,
-                               const struct pb_desc *desc)
-{
-    struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
-    struct radeon_drm_winsys *rws = mgr->rws;
-    struct radeon_drm_buffer *buf;
-    uint32_t domain;
-
-    buf = CALLOC_STRUCT(radeon_drm_buffer);
-    if (!buf)
-       goto error1;
-
-    pipe_reference_init(&buf->base.base.reference, 1);
-    buf->base.base.alignment = desc->alignment;
-    buf->base.base.usage = desc->usage;
-    buf->base.base.size = size;
-    buf->base.vtbl = &radeon_drm_buffer_vtbl;
-    buf->mgr = mgr;
-
-    make_empty_list(buf);
-
-    domain =
-        (desc->usage & RADEON_PB_USAGE_DOMAIN_GTT  ? RADEON_GEM_DOMAIN_GTT  : 0) |
-        (desc->usage & RADEON_PB_USAGE_DOMAIN_VRAM ? RADEON_GEM_DOMAIN_VRAM : 0);
-
-    buf->bo = radeon_bo_open(rws->bom, 0, size,
-                            desc->alignment, domain, 0);
-    if (buf->bo == NULL)
-       goto error2;
-
-    return &buf->base;
-
- error2:
-    FREE(buf);
- error1:
-    return NULL; 
-}
-
-static void
-radeon_drm_bufmgr_flush(struct pb_manager *mgr)
-{
-    /* NOP */
-}
-
-static void
-radeon_drm_bufmgr_destroy(struct pb_manager *_mgr)
-{
-    struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
-    util_hash_table_destroy(mgr->buffer_handles);
-    pipe_mutex_destroy(mgr->buffer_map_list_mutex);
-    pipe_mutex_destroy(mgr->buffer_handles_mutex);
-    FREE(mgr);
-}
-
-static unsigned handle_hash(void *key)
-{
-    return (unsigned)key;
-}
-
-static int handle_compare(void *key1, void *key2)
-{
-    return !((int)key1 == (int)key2);
-}
-
-struct pb_manager *
-radeon_drm_bufmgr_create(struct radeon_drm_winsys *rws)
-{
-    struct radeon_drm_bufmgr *mgr;
-
-    mgr = CALLOC_STRUCT(radeon_drm_bufmgr);
-    if (!mgr)
-       return NULL;
-
-    mgr->base.destroy = radeon_drm_bufmgr_destroy;
-    mgr->base.create_buffer = radeon_drm_bufmgr_create_buffer;
-    mgr->base.flush = radeon_drm_bufmgr_flush;
-
-    mgr->rws = rws;
-    make_empty_list(&mgr->buffer_map_list);
-    mgr->buffer_handles = util_hash_table_create(handle_hash, handle_compare);
-    pipe_mutex_init(mgr->buffer_map_list_mutex);
-    pipe_mutex_init(mgr->buffer_handles_mutex);
-    return &mgr->base;
-}
-
-static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf)
-{
-    struct radeon_drm_buffer *buf = NULL;
-
-    if (_buf->vtbl == &radeon_drm_buffer_vtbl) {
-        buf = radeon_drm_buffer(_buf);
-    } else {
-       struct pb_buffer *base_buf;
-       pb_size offset;
-       pb_get_base_buffer(_buf, &base_buf, &offset);
-
-        if (base_buf->vtbl == &radeon_drm_buffer_vtbl)
-            buf = radeon_drm_buffer(base_buf);
-    }
-
-    return buf;
-}
-
-static void *radeon_drm_buffer_map(struct r300_winsys_screen *ws,
-                                   struct r300_winsys_buffer *buf,
-                                   struct r300_winsys_cs *cs,
-                                   enum pipe_transfer_usage usage)
-{
-    struct pb_buffer *_buf = radeon_pb_buffer(buf);
-
-    return pb_map(_buf, get_pb_usage_from_transfer_flags(usage), radeon_drm_cs(cs));
-}
-
-static void radeon_drm_buffer_unmap(struct r300_winsys_screen *ws,
-                                    struct r300_winsys_buffer *buf)
-{
-    struct pb_buffer *_buf = radeon_pb_buffer(buf);
-
-    pb_unmap(_buf);
-}
-
-boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf,
-                                    struct winsys_handle *whandle)
-{
-    struct drm_gem_flink flink;
-    struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
-
-    if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
-       if (!buf->flinked) {
-           flink.handle = buf->bo->handle;
-
-            if (ioctl(buf->mgr->rws->fd, DRM_IOCTL_GEM_FLINK, &flink)) {
-               return FALSE;
-           }
-
-           buf->flinked = TRUE;
-           buf->flink = flink.name;
-       }
-       whandle->handle = buf->flink;
-    } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
-       whandle->handle = buf->bo->handle;
-    }
-    return TRUE;
-}
-
-static void radeon_drm_buffer_get_tiling(struct r300_winsys_screen *ws,
-                                         struct r300_winsys_buffer *_buf,
-                                         enum r300_buffer_tiling *microtiled,
-                                         enum r300_buffer_tiling *macrotiled)
-{
-    struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
-    uint32_t flags = 0, pitch;
-
-    radeon_bo_get_tiling(buf->bo, &flags, &pitch);
-
-    *microtiled = R300_BUFFER_LINEAR;
-    *macrotiled = R300_BUFFER_LINEAR;
-    if (flags & RADEON_BO_FLAGS_MICRO_TILE)
-       *microtiled = R300_BUFFER_TILED;
-
-    if (flags & RADEON_BO_FLAGS_MACRO_TILE)
-       *macrotiled = R300_BUFFER_TILED;
-}
-
-static void radeon_drm_buffer_set_tiling(struct r300_winsys_screen *ws,
-                                         struct r300_winsys_buffer *_buf,
-                                         enum r300_buffer_tiling microtiled,
-                                         enum r300_buffer_tiling macrotiled,
-                                         uint32_t pitch)
-{
-    struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
-    uint32_t flags = 0;
-    if (microtiled == R300_BUFFER_TILED)
-        flags |= RADEON_BO_FLAGS_MICRO_TILE;
-/* XXX Remove this ifdef when libdrm version 2.4.19 becomes mandatory. */
-#ifdef RADEON_BO_FLAGS_MICRO_TILE_SQUARE
-    else if (microtiled == R300_BUFFER_SQUARETILED)
-        flags |= RADEON_BO_FLAGS_MICRO_TILE_SQUARE;
-#endif
-    if (macrotiled == R300_BUFFER_TILED)
-        flags |= RADEON_BO_FLAGS_MACRO_TILE;
-
-    radeon_bo_set_tiling(buf->bo, flags, pitch);
-}
-
-static struct r300_winsys_cs_buffer *radeon_drm_get_cs_handle(
-        struct r300_winsys_screen *rws,
-        struct r300_winsys_buffer *_buf)
-{
-    /* return pure radeon_bo. */
-    return (struct r300_winsys_cs_buffer*)
-            get_drm_buffer(radeon_pb_buffer(_buf))->bo;
-}
-
-static boolean radeon_drm_is_buffer_referenced(struct r300_winsys_cs *rcs,
-                                               struct r300_winsys_cs_buffer *_buf,
-                                               enum r300_reference_domain domain)
-{
-    struct radeon_bo *bo = (struct radeon_bo*)_buf;
-    uint32_t tmp;
-
-    if (domain & R300_REF_CS) {
-        if (radeon_bo_is_referenced_by_cs(bo, NULL)) {
-            return TRUE;
-        }
-    }
-
-    if (domain & R300_REF_HW) {
-        if (radeon_bo_is_busy(bo, &tmp)) {
-            return TRUE;
-        }
-    }
-
-    return FALSE;
-}
-
-void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr)
-{
-    struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
-    struct radeon_drm_buffer *rpb, *t_rpb;
-
-    pipe_mutex_lock(mgr->buffer_map_list_mutex);
-
-    foreach_s(rpb, t_rpb, &mgr->buffer_map_list) {
-       radeon_bo_unmap(rpb->bo);
-       rpb->bo->ptr = NULL;
-       remove_from_list(rpb);
-    }
-
-    make_empty_list(&mgr->buffer_map_list);
-
-    pipe_mutex_unlock(mgr->buffer_map_list_mutex);
-}
-
-static void radeon_drm_buffer_wait(struct r300_winsys_screen *ws,
-                                   struct r300_winsys_buffer *_buf)
-{
-    struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
-
-    radeon_bo_wait(buf->bo);
-}
-
-void radeon_drm_bufmgr_init_functions(struct radeon_drm_winsys *ws)
-{
-    ws->base.buffer_get_cs_handle = radeon_drm_get_cs_handle;
-    ws->base.buffer_set_tiling = radeon_drm_buffer_set_tiling;
-    ws->base.buffer_get_tiling = radeon_drm_buffer_get_tiling;
-    ws->base.buffer_map = radeon_drm_buffer_map;
-    ws->base.buffer_unmap = radeon_drm_buffer_unmap;
-    ws->base.buffer_wait = radeon_drm_buffer_wait;
-    ws->base.cs_is_buffer_referenced = radeon_drm_is_buffer_referenced;
-}
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.h b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.h
deleted file mode 100644 (file)
index 494abdc..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright © 2008 Jérôme Glisse
- * 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.
- */
-/*
- * Authors:
- *      Jérôme Glisse <glisse@freedesktop.org>
- */
-#ifndef RADEON_DRM_BUFFER_H
-#define RADEON_DRM_BUFFER_H
-
-#include "radeon_winsys.h"
-
-#define RADEON_PB_USAGE_VERTEX      (1 << 28)
-#define RADEON_PB_USAGE_DOMAIN_GTT  (1 << 29)
-#define RADEON_PB_USAGE_DOMAIN_VRAM (1 << 30)
-
-static INLINE struct pb_buffer *
-radeon_pb_buffer(struct r300_winsys_buffer *buffer)
-{
-    return (struct pb_buffer *)buffer;
-}
-
-struct pb_manager *radeon_drm_bufmgr_create(struct radeon_drm_winsys *rws);
-struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr,
-                                                             uint32_t handle);
-void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr);
-boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf,
-                                    struct winsys_handle *whandle);
-void radeon_drm_bufmgr_init_functions(struct radeon_drm_winsys *ws);
-
-#endif
index fe71f0805921f19d587e8c92d701d2e5268d4a0c..4676c2a1ea977a87b2f76af5150fa7718375e4a8 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2009 Corbin Simpson
+ * Copyright © 2011 Marek Olšák <maraeo@gmail.com>
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * Authors:
  *      Corbin Simpson <MostAwesomeDude@gmail.com>
  *      Joakim Sindholt <opensource@zhasha.com>
+ *      Marek Olšák <maraeo@gmail.com>
  */
 
 #include "radeon_winsys.h"
-#include "radeon_drm_buffer.h"
+#include "radeon_drm_bo.h"
 #include "radeon_drm_cs.h"
 #include "radeon_drm_public.h"
 
 #include "pipebuffer/pb_bufmgr.h"
 #include "util/u_memory.h"
 
-#include <radeon_drm.h>
-#include <radeon_bo_gem.h>
-#include <radeon_cs_gem.h>
 #include <xf86drm.h>
 #include <stdio.h>
 
-
-/* Enable/disable Hyper-Z access. Return TRUE on success. */
-static boolean radeon_set_hyperz_access(int fd, boolean enable)
-{
 #ifndef RADEON_INFO_WANT_HYPERZ
 #define RADEON_INFO_WANT_HYPERZ 7
 #endif
+#ifndef RADEON_INFO_WANT_CMASK
+#define RADEON_INFO_WANT_CMASK 8
+#endif
 
+/* Enable/disable feature access. Return TRUE on success. */
+static boolean radeon_set_fd_access(int fd, unsigned request, boolean enable)
+{
     struct drm_radeon_info info = {0};
     unsigned value = enable ? 1 : 0;
 
-    if (!debug_get_bool_option("RADEON_HYPERZ", FALSE))
-        return FALSE;
-
     info.value = (unsigned long)&value;
-    info.request = RADEON_INFO_WANT_HYPERZ;
+    info.request = request;
 
     if (drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)) != 0)
         return FALSE;
@@ -107,23 +105,9 @@ static void do_ioctls(struct radeon_drm_winsys *winsys)
         exit(1);
     }
 
-/* XXX Remove this ifdef when libdrm version 2.4.19 becomes mandatory. */
-#ifdef RADEON_BO_FLAGS_MICRO_TILE_SQUARE
-    // Supported since 2.1.0.
-    winsys->squaretiling = version->version_major > 2 ||
-                           version->version_minor >= 1;
-#endif
-
-    winsys->drm_2_3_0 = version->version_major > 2 ||
-                        version->version_minor >= 3;
-
-    winsys->drm_2_6_0 = version->version_major > 2 ||
-                        (version->version_major == 2 &&
-                         version->version_minor >= 6);
-
-    winsys->drm_2_8_0 = version->version_major > 2 ||
-                        (version->version_major == 2 &&
-                         version->version_minor >= 8);
+    winsys->drm_major = version->version_major;
+    winsys->drm_minor = version->version_minor;
+    winsys->drm_patchlevel = version->version_patchlevel;
 
     info.request = RADEON_INFO_DEVICE_ID;
     retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_INFO, &info, sizeof(info));
@@ -152,7 +136,15 @@ static void do_ioctls(struct radeon_drm_winsys *winsys)
     }
     winsys->z_pipes = target;
 
-    winsys->hyperz = radeon_set_hyperz_access(winsys->fd, TRUE);
+    if (debug_get_bool_option("RADEON_HYPERZ", FALSE)) {
+        winsys->hyperz = radeon_set_fd_access(winsys->fd,
+                                              RADEON_INFO_WANT_HYPERZ, TRUE);
+    }
+
+    if (debug_get_bool_option("RADEON_CMASK", FALSE)) {
+        winsys->aacompress = radeon_set_fd_access(winsys->fd,
+                                                  RADEON_INFO_WANT_CMASK, TRUE);
+    }
 
     retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_GEM_INFO,
             &gem_info, sizeof(gem_info));
@@ -164,17 +156,6 @@ static void do_ioctls(struct radeon_drm_winsys *winsys)
     winsys->gart_size = gem_info.gart_size;
     winsys->vram_size = gem_info.vram_size;
 
-    debug_printf("radeon: Successfully grabbed chipset info from kernel!\n"
-                 "radeon: DRM version: %d.%d.%d ID: 0x%04x GB: %d Z: %d\n"
-                 "radeon: GART size: %d MB VRAM size: %d MB\n"
-                 "radeon: HyperZ: %s\n",
-                 version->version_major, version->version_minor,
-                 version->version_patchlevel, winsys->pci_id,
-                 winsys->gb_pipes, winsys->z_pipes,
-                 winsys->gart_size / 1024 / 1024,
-                 winsys->vram_size / 1024 / 1024,
-                 winsys->hyperz ? "YES" : "NO");
-
     drmFreeVersion(version);
 }
 
@@ -184,11 +165,47 @@ static void radeon_winsys_destroy(struct r300_winsys_screen *rws)
 
     ws->cman->destroy(ws->cman);
     ws->kman->destroy(ws->kman);
-
-    radeon_bo_manager_gem_dtor(ws->bom);
     FREE(rws);
 }
 
+static uint32_t radeon_get_value(struct r300_winsys_screen *rws,
+                                 enum r300_value_id id)
+{
+    struct radeon_drm_winsys *ws = (struct radeon_drm_winsys *)rws;
+
+    switch(id) {
+    case R300_VID_PCI_ID:
+       return ws->pci_id;
+    case R300_VID_GB_PIPES:
+       return ws->gb_pipes;
+    case R300_VID_Z_PIPES:
+       return ws->z_pipes;
+    case R300_VID_GART_SIZE:
+        return ws->gart_size;
+    case R300_VID_VRAM_SIZE:
+        return ws->vram_size;
+    case R300_VID_DRM_MAJOR:
+        return ws->drm_major;
+    case R300_VID_DRM_MINOR:
+        return ws->drm_minor;
+    case R300_VID_DRM_PATCHLEVEL:
+        return ws->drm_patchlevel;
+    case R300_VID_DRM_2_1_0:
+        return ws->drm_major*100 + ws->drm_minor >= 201;
+    case R300_VID_DRM_2_3_0:
+        return ws->drm_major*100 + ws->drm_minor >= 203;
+    case R300_VID_DRM_2_6_0:
+        return ws->drm_major*100 + ws->drm_minor >= 206;
+    case R300_VID_DRM_2_8_0:
+        return ws->drm_major*100 + ws->drm_minor >= 208;
+    case R300_CAN_HYPERZ:
+        return ws->hyperz;
+    case R300_CAN_AACOMPRESS:
+        return ws->aacompress;
+    }
+    return 0;
+}
+
 struct r300_winsys_screen *r300_drm_winsys_screen_create(int fd)
 {
     struct radeon_drm_winsys *ws = CALLOC_STRUCT(radeon_drm_winsys);
@@ -204,10 +221,7 @@ struct r300_winsys_screen *r300_drm_winsys_screen_create(int fd)
     }
 
     /* Create managers. */
-    ws->bom = radeon_bo_manager_gem_ctor(fd);
-    if (!ws->bom)
-       goto fail;
-    ws->kman = radeon_drm_bufmgr_create(ws);
+    ws->kman = radeon_bomgr_create(ws);
     if (!ws->kman)
        goto fail;
     ws->cman = pb_cache_manager_create(ws->kman, 1000000);
@@ -216,22 +230,18 @@ struct r300_winsys_screen *r300_drm_winsys_screen_create(int fd)
 
     /* Set functions. */
     ws->base.destroy = radeon_winsys_destroy;
+    ws->base.get_value = radeon_get_value;
 
-    radeon_drm_bufmgr_init_functions(ws);
+    radeon_bomgr_init_functions(ws);
     radeon_drm_cs_init_functions(ws);
-    radeon_winsys_init_functions(ws);
 
     return &ws->base;
 
 fail:
-    if (ws->bom)
-       radeon_bo_manager_gem_dtor(ws->bom);
-
     if (ws->cman)
        ws->cman->destroy(ws->cman);
     if (ws->kman)
        ws->kman->destroy(ws->kman);
-
     FREE(ws);
     return NULL;
 }
index 60bc36b092914cb0503aa71be187c31343f76bc0..a38b01048b2c124ea7436caec1c3d68bbc4877ca 100644 (file)
 */
 
 #include "radeon_drm_cs.h"
-#include "radeon_drm_buffer.h"
 
 #include "util/u_memory.h"
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
-#include <radeon_bo.h>
 #include <xf86drm.h>
 
 #define RELOC_DWORDS (sizeof(struct drm_radeon_cs_reloc) / sizeof(uint32_t))
 
+static boolean radeon_init_cs_context(struct radeon_cs_context *csc, int fd)
+{
+    csc->fd = fd;
+    csc->nrelocs = 512;
+    csc->relocs_bo = (struct radeon_bo**)
+                     CALLOC(1, csc->nrelocs * sizeof(struct radeon_bo*));
+    if (!csc->relocs_bo) {
+        return FALSE;
+    }
+
+    csc->relocs = (struct drm_radeon_cs_reloc*)
+                  CALLOC(1, csc->nrelocs * sizeof(struct drm_radeon_cs_reloc));
+    if (!csc->relocs) {
+        FREE(csc->relocs_bo);
+        return FALSE;
+    }
+
+    csc->chunks[0].chunk_id = RADEON_CHUNK_ID_IB;
+    csc->chunks[0].length_dw = 0;
+    csc->chunks[0].chunk_data = (uint64_t)(uintptr_t)csc->buf;
+    csc->chunks[1].chunk_id = RADEON_CHUNK_ID_RELOCS;
+    csc->chunks[1].length_dw = 0;
+    csc->chunks[1].chunk_data = (uint64_t)(uintptr_t)csc->relocs;
+
+    csc->chunk_array[0] = (uint64_t)(uintptr_t)&csc->chunks[0];
+    csc->chunk_array[1] = (uint64_t)(uintptr_t)&csc->chunks[1];
+
+    csc->cs.num_chunks = 2;
+    csc->cs.chunks = (uint64_t)(uintptr_t)csc->chunk_array;
+    return TRUE;
+}
+
+static void radeon_cs_context_cleanup(struct radeon_cs_context *csc)
+{
+    unsigned i;
+
+    for (i = 0; i < csc->crelocs; i++) {
+        p_atomic_dec(&csc->relocs_bo[i]->num_cs_references);
+        radeon_bo_unref(csc->relocs_bo[i]);
+        csc->relocs_bo[i] = NULL;
+    }
+
+    csc->crelocs = 0;
+    csc->chunks[0].length_dw = 0;
+    csc->chunks[1].length_dw = 0;
+    csc->used_gart = 0;
+    csc->used_vram = 0;
+    memset(csc->is_handle_added, 0, sizeof(csc->is_handle_added));
+}
+
+static void radeon_destroy_cs_context(struct radeon_cs_context *csc)
+{
+    radeon_cs_context_cleanup(csc);
+    FREE(csc->relocs_bo);
+    FREE(csc->relocs);
+}
+
 static struct r300_winsys_cs *radeon_drm_cs_create(struct r300_winsys_screen *rws)
 {
     struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
@@ -85,34 +141,29 @@ static struct r300_winsys_cs *radeon_drm_cs_create(struct r300_winsys_screen *rw
     }
 
     cs->ws = ws;
-    cs->nrelocs = 256;
-    cs->relocs_bo = (struct radeon_bo**)
-                     CALLOC(1, cs->nrelocs * sizeof(struct radeon_bo*));
-    if (!cs->relocs_bo) {
+
+    if (!radeon_init_cs_context(&cs->csc1, cs->ws->fd)) {
         FREE(cs);
         return NULL;
     }
-
-    cs->relocs = (struct drm_radeon_cs_reloc*)
-                 CALLOC(1, cs->nrelocs * sizeof(struct drm_radeon_cs_reloc));
-    if (!cs->relocs) {
-        FREE(cs->relocs_bo);
+    if (!radeon_init_cs_context(&cs->csc2, cs->ws->fd)) {
+        radeon_destroy_cs_context(&cs->csc1);
         FREE(cs);
         return NULL;
     }
 
-    cs->chunks[0].chunk_id = RADEON_CHUNK_ID_IB;
-    cs->chunks[0].length_dw = 0;
-    cs->chunks[0].chunk_data = (uint64_t)(uintptr_t)cs->base.buf;
-    cs->chunks[1].chunk_id = RADEON_CHUNK_ID_RELOCS;
-    cs->chunks[1].length_dw = 0;
-    cs->chunks[1].chunk_data = (uint64_t)(uintptr_t)cs->relocs;
+    /* Set the first command buffer as current. */
+    cs->csc = &cs->csc1;
+    cs->cst = &cs->csc2;
+    cs->base.buf = cs->csc->buf;
+
+    p_atomic_inc(&ws->num_cs);
     return &cs->base;
 }
 
 #define OUT_CS(cs, value) (cs)->buf[(cs)->cdw++] = (value)
 
-static inline void update_domains(struct drm_radeon_cs_reloc *reloc,
+static INLINE void update_domains(struct drm_radeon_cs_reloc *reloc,
                                   enum r300_buffer_domain rd,
                                   enum r300_buffer_domain wd,
                                   enum r300_buffer_domain *added_domains)
@@ -131,23 +182,22 @@ static inline void update_domains(struct drm_radeon_cs_reloc *reloc,
     }
 }
 
-static int radeon_get_reloc(struct radeon_drm_cs *cs,
-                            struct radeon_bo *bo)
+int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo)
 {
     struct drm_radeon_cs_reloc *reloc;
     unsigned i;
-    unsigned hash = bo->handle & (sizeof(cs->is_handle_added)-1);
+    unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1);
 
-    if (cs->is_handle_added[hash]) {
-        reloc = cs->relocs_hashlist[hash];
+    if (csc->is_handle_added[hash]) {
+        reloc = csc->relocs_hashlist[hash];
         if (reloc->handle == bo->handle) {
-            return cs->reloc_indices_hashlist[hash];
+            return csc->reloc_indices_hashlist[hash];
         }
 
         /* Hash collision, look for the BO in the list of relocs linearly. */
-        for (i = cs->crelocs; i != 0;) {
+        for (i = csc->crelocs; i != 0;) {
             --i;
-            reloc = &cs->relocs[i];
+            reloc = &csc->relocs[i];
             if (reloc->handle == bo->handle) {
                 /* Put this reloc in the hash list.
                  * This will prevent additional hash collisions if there are
@@ -158,8 +208,8 @@ static int radeon_get_reloc(struct radeon_drm_cs *cs,
                  *         AAAAAAAAAAABBBBBBBBBBBBBBCCCCCCCC
                  * will collide here: ^ and here:   ^,
                  * meaning that we should get very few collisions in the end. */
-                cs->relocs_hashlist[hash] = reloc;
-                cs->reloc_indices_hashlist[hash] = i;
+                csc->relocs_hashlist[hash] = reloc;
+                csc->reloc_indices_hashlist[hash] = i;
                 /*printf("write_reloc collision, hash: %i, handle: %i\n", hash, bo->handle);*/
                 return i;
             }
@@ -169,7 +219,7 @@ static int radeon_get_reloc(struct radeon_drm_cs *cs,
     return -1;
 }
 
-static void radeon_add_reloc(struct radeon_drm_cs *cs,
+static void radeon_add_reloc(struct radeon_cs_context *csc,
                              struct radeon_bo *bo,
                              enum r300_buffer_domain rd,
                              enum r300_buffer_domain wd,
@@ -177,24 +227,24 @@ static void radeon_add_reloc(struct radeon_drm_cs *cs,
 {
     struct drm_radeon_cs_reloc *reloc;
     unsigned i;
-    unsigned hash = bo->handle & (sizeof(cs->is_handle_added)-1);
+    unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1);
 
-    if (cs->is_handle_added[hash]) {
-        reloc = cs->relocs_hashlist[hash];
+    if (csc->is_handle_added[hash]) {
+        reloc = csc->relocs_hashlist[hash];
         if (reloc->handle == bo->handle) {
             update_domains(reloc, rd, wd, added_domains);
             return;
         }
 
         /* Hash collision, look for the BO in the list of relocs linearly. */
-        for (i = cs->crelocs; i != 0;) {
+        for (i = csc->crelocs; i != 0;) {
             --i;
-            reloc = &cs->relocs[i];
+            reloc = &csc->relocs[i];
             if (reloc->handle == bo->handle) {
                 update_domains(reloc, rd, wd, added_domains);
 
-                cs->relocs_hashlist[hash] = reloc;
-                cs->reloc_indices_hashlist[hash] = i;
+                csc->relocs_hashlist[hash] = reloc;
+                csc->reloc_indices_hashlist[hash] = i;
                 /*printf("write_reloc collision, hash: %i, handle: %i\n", hash, bo->handle);*/
                 return;
             }
@@ -202,40 +252,41 @@ static void radeon_add_reloc(struct radeon_drm_cs *cs,
     }
 
     /* New relocation, check if the backing array is large enough. */
-    if (cs->crelocs >= cs->nrelocs) {
+    if (csc->crelocs >= csc->nrelocs) {
         uint32_t size;
-        cs->nrelocs += 10;
+        csc->nrelocs += 10;
 
-        size = cs->nrelocs * sizeof(struct radeon_bo*);
-        cs->relocs_bo = (struct radeon_bo**)realloc(cs->relocs_bo, size);
+        size = csc->nrelocs * sizeof(struct radeon_bo*);
+        csc->relocs_bo = (struct radeon_bo**)realloc(csc->relocs_bo, size);
 
-        size = cs->nrelocs * sizeof(struct drm_radeon_cs_reloc);
-        cs->relocs = (struct drm_radeon_cs_reloc*)realloc(cs->relocs, size);
+        size = csc->nrelocs * sizeof(struct drm_radeon_cs_reloc);
+        csc->relocs = (struct drm_radeon_cs_reloc*)realloc(csc->relocs, size);
 
-        cs->chunks[1].chunk_data = (uint64_t)(uintptr_t)cs->relocs;
+        csc->chunks[1].chunk_data = (uint64_t)(uintptr_t)csc->relocs;
     }
 
     /* Initialize the new relocation. */
     radeon_bo_ref(bo);
-    cs->relocs_bo[cs->crelocs] = bo;
-    reloc = &cs->relocs[cs->crelocs];
+    p_atomic_inc(&bo->num_cs_references);
+    csc->relocs_bo[csc->crelocs] = bo;
+    reloc = &csc->relocs[csc->crelocs];
     reloc->handle = bo->handle;
     reloc->read_domains = rd;
     reloc->write_domain = wd;
     reloc->flags = 0;
 
-    cs->is_handle_added[hash] = TRUE;
-    cs->relocs_hashlist[hash] = reloc;
-    cs->reloc_indices_hashlist[hash] = cs->crelocs;
+    csc->is_handle_added[hash] = TRUE;
+    csc->relocs_hashlist[hash] = reloc;
+    csc->reloc_indices_hashlist[hash] = csc->crelocs;
 
-    cs->chunks[1].length_dw += RELOC_DWORDS;
-    cs->crelocs++;
+    csc->chunks[1].length_dw += RELOC_DWORDS;
+    csc->crelocs++;
 
     *added_domains = rd | wd;
 }
 
 static void radeon_drm_cs_add_reloc(struct r300_winsys_cs *rcs,
-                                    struct r300_winsys_cs_buffer *buf,
+                                    struct r300_winsys_cs_handle *buf,
                                     enum r300_buffer_domain rd,
                                     enum r300_buffer_domain wd)
 {
@@ -243,32 +294,32 @@ static void radeon_drm_cs_add_reloc(struct r300_winsys_cs *rcs,
     struct radeon_bo *bo = (struct radeon_bo*)buf;
     enum r300_buffer_domain added_domains;
 
-    radeon_add_reloc(cs, bo, rd, wd, &added_domains);
+    radeon_add_reloc(cs->csc, bo, rd, wd, &added_domains);
 
     if (!added_domains)
         return;
 
     if (added_domains & R300_DOMAIN_GTT)
-        cs->used_gart += bo->size;
+        cs->csc->used_gart += bo->size;
     if (added_domains & R300_DOMAIN_VRAM)
-        cs->used_vram += bo->size;
+        cs->csc->used_vram += bo->size;
 }
 
 static boolean radeon_drm_cs_validate(struct r300_winsys_cs *rcs)
 {
     struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
 
-    return cs->used_gart < cs->ws->gart_size * 0.8 &&
-           cs->used_vram < cs->ws->vram_size * 0.8;
+    return cs->csc->used_gart < cs->ws->gart_size * 0.8 &&
+           cs->csc->used_vram < cs->ws->vram_size * 0.8;
 }
 
 static void radeon_drm_cs_write_reloc(struct r300_winsys_cs *rcs,
-                                      struct r300_winsys_cs_buffer *buf)
+                                      struct r300_winsys_cs_handle *buf)
 {
     struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
     struct radeon_bo *bo = (struct radeon_bo*)buf;
 
-    unsigned index = radeon_get_reloc(cs, bo);
+    unsigned index = radeon_get_reloc(cs->csc, bo);
 
     if (index == -1) {
         fprintf(stderr, "r300: Cannot get a relocation in %s.\n", __func__);
@@ -279,75 +330,109 @@ static void radeon_drm_cs_write_reloc(struct r300_winsys_cs *rcs,
     OUT_CS(&cs->base, index * RELOC_DWORDS);
 }
 
-static void radeon_drm_cs_emit(struct r300_winsys_cs *rcs)
+static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param)
 {
-    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
-    uint64_t chunk_array[2];
+    struct radeon_cs_context *csc = (struct radeon_cs_context*)param;
     unsigned i;
-    int r;
 
-    if (cs->base.cdw) {
-        /* Unmap buffers. */
-        radeon_drm_bufmgr_flush_maps(cs->ws->kman);
-
-        /* Prepare the arguments. */
-        cs->chunks[0].length_dw = cs->base.cdw;
-
-        chunk_array[0] = (uint64_t)(uintptr_t)&cs->chunks[0];
-        chunk_array[1] = (uint64_t)(uintptr_t)&cs->chunks[1];
-
-        cs->cs.num_chunks = 2;
-        cs->cs.chunks = (uint64_t)(uintptr_t)chunk_array;
-
-        /* Emit. */
-        r = drmCommandWriteRead(cs->ws->fd, DRM_RADEON_CS,
-                                &cs->cs, sizeof(struct drm_radeon_cs));
-        if (r) {
-            if (debug_get_bool_option("RADEON_DUMP_CS", FALSE)) {
-                fprintf(stderr, "radeon: The kernel rejected CS, dumping...\n");
-                fprintf(stderr, "VENDORID:DEVICEID 0x%04X:0x%04X\n", 0x1002,
-                        cs->ws->pci_id);
-                for (i = 0; i < cs->base.cdw; i++) {
-                    fprintf(stderr, "0x%08X\n", cs->base.buf[i]);
-                }
-            } else {
-                fprintf(stderr, "radeon: The kernel rejected CS, "
-                                "see dmesg for more information.\n");
+    if (drmCommandWriteRead(csc->fd, DRM_RADEON_CS,
+                            &csc->cs, sizeof(struct drm_radeon_cs))) {
+        if (debug_get_bool_option("RADEON_DUMP_CS", FALSE)) {
+            unsigned i;
+
+            fprintf(stderr, "radeon: The kernel rejected CS, dumping...\n");
+            for (i = 0; i < csc->chunks[0].length_dw; i++) {
+                fprintf(stderr, "0x%08X\n", csc->buf[i]);
             }
+        } else {
+            fprintf(stderr, "radeon: The kernel rejected CS, "
+                    "see dmesg for more information.\n");
         }
     }
 
-    /* Unreference buffers, cleanup. */
-    for (i = 0; i < cs->crelocs; i++) {
-        radeon_bo_unref((struct radeon_bo*)cs->relocs_bo[i]);
-        cs->relocs_bo[i] = NULL;
+    for (i = 0; i < csc->crelocs; i++)
+        p_atomic_dec(&csc->relocs_bo[i]->num_active_ioctls);
+    return NULL;
+}
+
+void radeon_drm_cs_sync_flush(struct r300_winsys_cs *rcs)
+{
+    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
+
+    /* Wait for any pending ioctl to complete. */
+    if (cs->thread) {
+        pipe_thread_wait(cs->thread);
+        cs->thread = 0;
     }
+}
+
+DEBUG_GET_ONCE_BOOL_OPTION(thread, "RADEON_THREAD", TRUE)
+
+void radeon_drm_cs_flush(struct r300_winsys_cs *rcs)
+{
+    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
+    struct radeon_cs_context *tmp;
+
+    radeon_drm_cs_sync_flush(rcs);
+
+    /* If the CS is not empty, emit it in a newly-spawned thread. */
+    if (cs->base.cdw) {
+        unsigned i, crelocs = cs->csc->crelocs;
 
+        cs->csc->chunks[0].length_dw = cs->base.cdw;
+
+        for (i = 0; i < crelocs; i++)
+            p_atomic_inc(&cs->csc->relocs_bo[i]->num_active_ioctls);
+
+        if (debug_get_option_thread()) {
+            cs->thread = pipe_thread_create(radeon_drm_cs_emit_ioctl, cs->csc);
+            assert(cs->thread);
+        } else {
+            radeon_drm_cs_emit_ioctl(cs->csc);
+        }
+    }
+
+    /* Flip command streams. */
+    tmp = cs->csc;
+    cs->csc = cs->cst;
+    cs->cst = tmp;
+
+    /* Prepare a new CS. */
+    radeon_cs_context_cleanup(cs->csc);
+
+    cs->base.buf = cs->csc->buf;
     cs->base.cdw = 0;
-    cs->crelocs = 0;
-    cs->chunks[0].length_dw = 0;
-    cs->chunks[1].length_dw = 0;
-    cs->used_gart = 0;
-    cs->used_vram = 0;
-    memset(cs->is_handle_added, 0, sizeof(cs->is_handle_added));
 }
 
 static void radeon_drm_cs_destroy(struct r300_winsys_cs *rcs)
 {
     struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
-    FREE(cs->relocs_bo);
-    FREE(cs->relocs);
+    radeon_drm_cs_sync_flush(rcs);
+    radeon_cs_context_cleanup(&cs->csc1);
+    radeon_cs_context_cleanup(&cs->csc2);
+    p_atomic_dec(&cs->ws->num_cs);
+    radeon_destroy_cs_context(&cs->csc1);
+    radeon_destroy_cs_context(&cs->csc2);
     FREE(cs);
 }
 
 static void radeon_drm_cs_set_flush(struct r300_winsys_cs *rcs,
-                             void (*flush)(void *), void *user)
+                                    void (*flush)(void *), void *user)
 {
     struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
     cs->flush_cs = flush;
     cs->flush_data = user;
 }
 
+static boolean radeon_bo_is_referenced(struct r300_winsys_cs *rcs,
+                                       struct r300_winsys_cs_handle *_buf)
+{
+    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
+    struct radeon_bo *bo = (struct radeon_bo*)_buf;
+
+    return radeon_bo_is_referenced_by_cs(cs, bo);
+}
+
 void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws)
 {
     ws->base.cs_create = radeon_drm_cs_create;
@@ -355,6 +440,8 @@ void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws)
     ws->base.cs_add_reloc = radeon_drm_cs_add_reloc;
     ws->base.cs_validate = radeon_drm_cs_validate;
     ws->base.cs_write_reloc = radeon_drm_cs_write_reloc;
-    ws->base.cs_flush = radeon_drm_cs_emit;
+    ws->base.cs_flush = radeon_drm_cs_flush;
+    ws->base.cs_sync_flush = radeon_drm_cs_sync_flush;
     ws->base.cs_set_flush = radeon_drm_cs_set_flush;
+    ws->base.cs_is_buffer_referenced = radeon_bo_is_referenced;
 }
index 76046534b6567ea418061427a88f7b13fc1179d2..4cc97f37e09ed38c27f2726f1ff90efe45873f28 100644 (file)
+/*
+ * Copyright © 2011 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, 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.
+ */
+
 #ifndef RADEON_DRM_CS_H
 #define RADEON_DRM_CS_H
 
-#include "radeon_winsys.h"
+#include "radeon_drm_bo.h"
 #include <radeon_drm.h>
 
-struct radeon_drm_cs {
-    struct r300_winsys_cs base;
-
-    /* The winsys. */
-    struct radeon_drm_winsys *ws;
+struct radeon_cs_context {
+    uint32_t                    buf[R300_MAX_CMDBUF_DWORDS];
 
-    /* Flush CS. */
-    void (*flush_cs)(void *);
-    void *flush_data;
+    int fd;
+    struct drm_radeon_cs        cs;
+    struct drm_radeon_cs_chunk  chunks[2];
+    uint64_t                    chunk_array[2];
 
     /* Relocs. */
-    unsigned                    crelocs;
     unsigned                    nrelocs;
-    struct drm_radeon_cs_reloc  *relocs;
+    unsigned                    crelocs;
     struct radeon_bo            **relocs_bo;
-    struct drm_radeon_cs        cs;
-    struct drm_radeon_cs_chunk  chunks[2];
-
-    unsigned used_vram;
-    unsigned used_gart;
+    struct drm_radeon_cs_reloc  *relocs;
 
     /* 0 = BO not added, 1 = BO added */
     char                        is_handle_added[256];
     struct drm_radeon_cs_reloc  *relocs_hashlist[256];
     unsigned                    reloc_indices_hashlist[256];
+
+    unsigned used_vram;
+    unsigned used_gart;
 };
 
+struct radeon_drm_cs {
+    struct r300_winsys_cs base;
+
+    /* We flip between these two CS. While one is being consumed
+     * by the kernel in another thread, the other one is being filled
+     * by the pipe driver. */
+    struct radeon_cs_context csc1;
+    struct radeon_cs_context csc2;
+    /* The currently-used CS. */
+    struct radeon_cs_context *csc;
+    /* The CS being currently-owned by the other thread. */
+    struct radeon_cs_context *cst;
+
+    /* The winsys. */
+    struct radeon_drm_winsys *ws;
+
+    /* Flush CS. */
+    void (*flush_cs)(void *);
+    void *flush_data;
+
+    pipe_thread thread;
+};
+
+int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo);
+
 static INLINE struct radeon_drm_cs *
 radeon_drm_cs(struct r300_winsys_cs *base)
 {
     return (struct radeon_drm_cs*)base;
 }
 
+static INLINE boolean radeon_bo_is_referenced_by_cs(struct radeon_drm_cs *cs,
+                                                    struct radeon_bo *bo)
+{
+    return bo->num_cs_references == bo->rws->num_cs ||
+           (bo->num_cs_references && radeon_get_reloc(cs->csc, bo) != -1);
+}
+
+static INLINE boolean radeon_bo_is_referenced_by_any_cs(struct radeon_bo *bo)
+{
+    return bo->num_cs_references;
+}
+
+void radeon_drm_cs_flush(struct r300_winsys_cs *rcs);
+void radeon_drm_cs_sync_flush(struct r300_winsys_cs *rcs);
 void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws);
 
 #endif
diff --git a/src/gallium/winsys/radeon/drm/radeon_r300.c b/src/gallium/winsys/radeon/drm/radeon_r300.c
deleted file mode 100644 (file)
index bacf181..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-#include "radeon_drm_buffer.h"
-
-#include "util/u_memory.h"
-#include "pipebuffer/pb_bufmgr.h"
-
-#include "state_tracker/drm_driver.h"
-
-static unsigned get_pb_usage_from_create_flags(unsigned bind, unsigned usage,
-                                               enum r300_buffer_domain domain)
-{
-    unsigned res = 0;
-
-    if (bind & (PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET |
-                PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT))
-        res |= PB_USAGE_GPU_WRITE;
-
-    if (bind & PIPE_BIND_SAMPLER_VIEW)
-        res |= PB_USAGE_GPU_READ | PB_USAGE_GPU_WRITE;
-
-    if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
-        res |= PB_USAGE_GPU_READ;
-
-    if (bind & PIPE_BIND_TRANSFER_WRITE)
-        res |= PB_USAGE_CPU_WRITE;
-
-    if (bind & PIPE_BIND_TRANSFER_READ)
-        res |= PB_USAGE_CPU_READ;
-
-    /* Is usage of any use for us? Probably not. */
-
-    /* Now add driver-specific usage flags. */
-    if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
-        res |= RADEON_PB_USAGE_VERTEX;
-
-    if (domain & R300_DOMAIN_GTT)
-        res |= RADEON_PB_USAGE_DOMAIN_GTT;
-
-    if (domain & R300_DOMAIN_VRAM)
-        res |= RADEON_PB_USAGE_DOMAIN_VRAM;
-
-    return res;
-}
-
-static struct r300_winsys_buffer *
-radeon_r300_winsys_buffer_create(struct r300_winsys_screen *rws,
-                                 unsigned size,
-                                 unsigned alignment,
-                                 unsigned bind,
-                                 unsigned usage,
-                                 enum r300_buffer_domain domain)
-{
-    struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
-    struct pb_desc desc;
-    struct pb_manager *provider;
-    struct pb_buffer *buffer;
-
-    memset(&desc, 0, sizeof(desc));
-    desc.alignment = alignment;
-    desc.usage = get_pb_usage_from_create_flags(bind, usage, domain);
-
-    /* Assign a buffer manager. */
-    if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
-       provider = ws->cman;
-    else
-        provider = ws->kman;
-
-    buffer = provider->create_buffer(provider, size, &desc);
-    if (!buffer)
-       return NULL;
-
-    return (struct r300_winsys_buffer*)buffer;
-}
-
-static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws,
-                                               struct r300_winsys_buffer **pdst,
-                                               struct r300_winsys_buffer *src)
-{
-    struct pb_buffer *_src = radeon_pb_buffer(src);
-    struct pb_buffer *_dst = radeon_pb_buffer(*pdst);
-
-    pb_reference(&_dst, _src);
-
-    *pdst = (struct r300_winsys_buffer*)_dst;
-}
-
-static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen *rws,
-                                                                        struct winsys_handle *whandle,
-                                                                        unsigned *stride,
-                                                                        unsigned *size)
-{
-    struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
-    struct pb_buffer *_buf;
-
-    _buf = radeon_drm_bufmgr_create_buffer_from_handle(ws->kman, whandle->handle);
-
-    if (stride)
-        *stride = whandle->stride;
-    if (size)
-        *size = _buf->base.size;
-
-    return (struct r300_winsys_buffer*)_buf;
-}
-
-static boolean radeon_r300_winsys_buffer_get_handle(struct r300_winsys_screen *rws,
-                                                   struct r300_winsys_buffer *buffer,
-                                                    unsigned stride,
-                                                    struct winsys_handle *whandle)
-{
-    struct pb_buffer *_buf = radeon_pb_buffer(buffer);
-    whandle->stride = stride;
-    return radeon_drm_bufmgr_get_handle(_buf, whandle);
-}
-
-static uint32_t radeon_get_value(struct r300_winsys_screen *rws,
-                                 enum r300_value_id id)
-{
-    struct radeon_drm_winsys *ws = (struct radeon_drm_winsys *)rws;
-
-    switch(id) {
-    case R300_VID_PCI_ID:
-       return ws->pci_id;
-    case R300_VID_GB_PIPES:
-       return ws->gb_pipes;
-    case R300_VID_Z_PIPES:
-       return ws->z_pipes;
-    case R300_VID_SQUARE_TILING_SUPPORT:
-        return ws->squaretiling;
-    case R300_VID_DRM_2_3_0:
-        return ws->drm_2_3_0;
-    case R300_VID_DRM_2_6_0:
-        return ws->drm_2_6_0;
-    case R300_VID_DRM_2_8_0:
-        return ws->drm_2_8_0;
-    case R300_CAN_HYPERZ:
-        return ws->hyperz;
-    }
-    return 0;
-}
-
-void radeon_winsys_init_functions(struct radeon_drm_winsys *ws)
-{
-    ws->base.get_value = radeon_get_value;
-    ws->base.buffer_create = radeon_r300_winsys_buffer_create;
-    ws->base.buffer_reference = radeon_r300_winsys_buffer_reference;
-    ws->base.buffer_from_handle = radeon_r300_winsys_buffer_from_handle;
-    ws->base.buffer_get_handle = radeon_r300_winsys_buffer_get_handle;
-}
index 492edfef8c3cde378a91e45547020d81d8f869d3..f8a89abcfe45922c040055e3ba3c46aba0902f79 100644 (file)
@@ -36,8 +36,8 @@ struct radeon_drm_winsys {
     struct r300_winsys_screen base;
 
     int fd; /* DRM file descriptor */
+    int num_cs; /* The number of command streams created. */
 
-    struct radeon_bo_manager *bom; /* Radeon BO manager. */
     struct pb_manager *kman;
     struct pb_manager *cman;
 
@@ -46,15 +46,15 @@ struct radeon_drm_winsys {
     uint32_t z_pipes;       /* Z pipe count (rv530 only) */
     uint32_t gart_size;     /* GART size. */
     uint32_t vram_size;     /* VRAM size. */
-    boolean squaretiling;   /* Square tiling support. */
-    /* DRM 2.3.0 (R500 VAP regs, MSPOS regs, fixed tex3D size checking) */
-    boolean drm_2_3_0;
-    /* DRM 2.6.0 (Hyper-Z, GB_Z_PEQ_CONFIG allowed on rv350->r4xx, FG_ALPHA_VALUE) */
-    boolean drm_2_6_0;
-    /* DRM 2.8.0 (US_FORMAT regs, ARGB2101010 colorbuffer) */
-    boolean drm_2_8_0;
+
+    unsigned drm_major;
+    unsigned drm_minor;
+    unsigned drm_patchlevel;
+
     /* Hyper-Z user */
     boolean hyperz;
+    /* AA compression (CMask) */
+    boolean aacompress;
 };
 
 static INLINE struct radeon_drm_winsys *
@@ -63,6 +63,4 @@ radeon_drm_winsys(struct r300_winsys_screen *base)
     return (struct radeon_drm_winsys*)base;
 }
 
-void radeon_winsys_init_functions(struct radeon_drm_winsys *ws);
-
 #endif
index eca174a6c56028f77f16a1e0ca2a36c2df0aebc5..80d5dfc3ed49f107bc07c059a02012c614b61989 100644 (file)
@@ -120,7 +120,8 @@ vmw_gmr_buffer_destroy(struct pb_buffer *_buf)
 
 static void *
 vmw_gmr_buffer_map(struct pb_buffer *_buf,
-               unsigned flags)
+                   unsigned flags,
+                   void *flush_ctx)
 {
    struct vmw_gmr_buffer *buf = vmw_gmr_buffer(_buf);
    return buf->map;
index 11626ee637d9a93db90a85a7ce4e60c4800b1bc8..f2124c1bf6508a2c877a9906d63d2aea0ab704d7 100644 (file)
@@ -320,7 +320,7 @@ vmw_swc_region_relocation(struct svga_winsys_context *swc,
     * to the FIFO won't cause flushing in the host.
     */
    vswc->seen_regions += reloc->buffer->base.size;
-   if(vswc->seen_regions >= VMW_GMR_POOL_SIZE/2)
+   if(vswc->seen_regions >= VMW_GMR_POOL_SIZE/3)
       vswc->preemptive_flush = TRUE;
 }
 
index df01a9ec2bfd0524afd9537fc14bcecaf499f4ea..f6c4741183146d00b518d60362aa27db27e253a2 100644 (file)
@@ -4,7 +4,7 @@
 
 Import('*')
 
-if env['platform'] in ('cygwin', 'linux'):
+if env['platform'] in ('cygwin_nt-5.1', 'cygwin_nt-6.1', 'linux'):
 
     env = env.Clone()
 
index c9525446633aa9a02ad6964add8279e359f74c67..876f0dfc2a5ef68e68401d499a8761b888105d79 100644 (file)
@@ -1,3 +1,4 @@
+
 #src/glsl/pp/Makefile
 
 TOP = ../..
@@ -13,10 +14,12 @@ LIBGLCPP_SOURCES = \
 
 GLCPP_SOURCES = \
        $(LIBGLCPP_SOURCES) \
+       ralloc.c \
        glcpp/glcpp.c
 
 C_SOURCES = \
        strtod.c \
+       ralloc.c \
        $(LIBGLCPP_SOURCES)
 
 CXX_SOURCES = \
@@ -68,6 +71,7 @@ CXX_SOURCES = \
        opt_constant_propagation.cpp \
        opt_constant_variable.cpp \
        opt_copy_propagation.cpp \
+       opt_copy_propagation_elements.cpp \
        opt_dead_code.cpp \
        opt_dead_code_local.cpp \
        opt_dead_functions.cpp \
@@ -82,8 +86,7 @@ CXX_SOURCES = \
        s_expression.cpp
 
 LIBS = \
-       $(TOP)/src/glsl/libglsl.a \
-       $(TALLOC_LIBS)
+       $(TOP)/src/glsl/libglsl.a
 
 APPS = glsl_compiler glcpp/glcpp
 
@@ -111,8 +114,10 @@ OBJECTS = \
        $(C_SOURCES:.c=.o) \
        $(CXX_SOURCES:.cpp=.o)
 
+DRICORE_OBJ_DIR = obj-visible
+OBJECTS_DRICORE = $(addprefix $(DRICORE_OBJ_DIR)/,$(OBJECTS))
+
 INCLUDES = \
-       $(TALLOC_CFLAGS) \
        -I. \
        -I../mesa \
        -I../mapi \
@@ -127,7 +132,13 @@ ALL_SOURCES = \
 
 ##### TARGETS #####
 
-default: depend lib$(LIBNAME).a $(APPS)
+default: depend lib$(LIBNAME).a $(APPS) $(DRICORE_GLSL_LIBS)
+
+$(TOP)/$(LIB_DIR)/libglsl.so: $(OBJECTS_DRICORE) builtin_function.o Makefile $(TOP)/src/glsl/Makefile.template
+       $(MKLIB) -o $@ -linker '$(CXX)' -ldflags '$(LDFLAGS)' \
+               -cplusplus -noprefix \
+               -install $(TOP)/$(LIB_DIR) -id $(INSTALL_LIB_DIR)/$@.dylib \
+               $(OBJECTS_DRICORE) builtin_function.o
 
 lib$(LIBNAME).a: $(OBJECTS) builtin_function.o Makefile $(TOP)/src/glsl/Makefile.template
        $(MKLIB) -cplusplus -o $(LIBNAME) -static $(OBJECTS) builtin_function.o
@@ -138,22 +149,33 @@ depend: $(ALL_SOURCES) Makefile
        $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(ALL_SOURCES) 2> /dev/null
 
 # Remove .o and backup files
-clean:
+clean: clean-dricore
        rm -f $(GLCPP_OBJECTS) $(GLSL2_OBJECTS) $(OBJECTS) lib$(LIBNAME).a depend depend.bak builtin_function.cpp builtin_function.o builtin_stubs.o builtin_compiler
        -rm -f $(APPS)
 
+clean-dricore:
+       -rm -f $(DRICORE_OBJ_DIR) $(TOP)/$(LIB_DIR)/libglsl.so libglsl.so
+
+ifneq (,$(DRICORE_GLSL_LIBS))
+DRICORE_INSTALL_TARGET = install-dricore
+endif
+
 # Dummy target
-install:
+install: $(DRICORE_INSTALL_TARGET)
        @echo -n ""
 
+install-dricore: default
+       $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+       $(INSTALL) -m 755 $(DRICORE_GLSL_LIBS) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
 
 ##### RULES #####
 
-glsl_compiler: $(GLSL2_OBJECTS) libglsl.a
-       $(APP_CXX) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(GLSL2_OBJECTS) $(LIBS) -o $@
+glsl_compiler: $(GLSL2_OBJECTS) libglsl.a builtin_stubs.o
+       $(APP_CXX) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(GLSL2_OBJECTS) builtin_stubs.o $(LIBS) -o $@
 
-glcpp/glcpp: $(GLCPP_OBJECTS) libglsl.a
-       $(APP_CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(GLCPP_OBJECTS) $(LIBS) -o $@
+glcpp: glcpp/glcpp
+glcpp/glcpp: $(GLCPP_OBJECTS)
+       $(APP_CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(GLCPP_OBJECTS) -o $@
 
 .cpp.o:
        $(CXX) -c $(INCLUDES) $(CXXFLAGS) $(DEFINES) $< -o $@
@@ -161,6 +183,14 @@ glcpp/glcpp: $(GLCPP_OBJECTS) libglsl.a
 .c.o:
        $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
 
+$(DRICORE_OBJ_DIR)/%.o : %.cpp
+       @mkdir -p $(dir $@)
+       $(CXX) -c $(INCLUDES) $(DRI_CXXFLAGS) $(DEFINES) $< -o $@
+
+$(DRICORE_OBJ_DIR)/%.o : %.c
+       @mkdir -p $(dir $@)
+       $(CC) -c $(INCLUDES) $(DRI_CFLAGS) $(DEFINES) $< -o $@
+
 glsl_lexer.cpp: glsl_lexer.lpp
        flex --nounistd -o$@  $<
 
@@ -174,10 +204,10 @@ glcpp/glcpp-parse.c: glcpp/glcpp-parse.y
        bison -v -o "$@" --defines=glcpp/glcpp-parse.h $<
 
 builtin_compiler: $(GLSL2_OBJECTS) $(OBJECTS) builtin_stubs.o
-       $(APP_CXX) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $(GLSL2_OBJECTS) builtin_stubs.o $(TALLOC_LIBS) -o $@
+       $(APP_CXX) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $(GLSL2_OBJECTS) builtin_stubs.o -o $@
 
 builtin_function.cpp: builtins/profiles/* builtins/ir/* builtins/tools/generate_builtins.py builtins/tools/texture_builtins.py builtin_compiler
        @echo Regenerating builtin_function.cpp...
-       $(PYTHON2) $(PYTHON_FLAGS) builtins/tools/generate_builtins.py $(PWD)/builtin_compiler > builtin_function.cpp
+       $(PYTHON2) $(PYTHON_FLAGS) builtins/tools/generate_builtins.py ./builtin_compiler > builtin_function.cpp
 
 -include depend
index 88a83fdb6fa0c37649d2c5a3cf523c1bdf14e4e0..7c6b6ae8c4df80541653cf1a257c3424a2933fa2 100644 (file)
@@ -7,14 +7,12 @@ from sys import executable as python_cmd
 env = env.Clone()
 
 env.Prepend(CPPPATH = [
+    '#include',
     '#src/mapi',
     '#src/mesa',
     '#src/glsl',
 ])
 
-if env['platform'] == 'windows':
-    env.Prepend(CPPPATH = ['#src/talloc'])
-
 sources = [
     'glcpp/glcpp-lex.c',
     'glcpp/glcpp-parse.c',
@@ -66,6 +64,7 @@ sources = [
     'opt_constant_propagation.cpp',
     'opt_constant_variable.cpp',
     'opt_copy_propagation.cpp',
+    'opt_copy_propagation_elements.cpp',
     'opt_dead_code.cpp',
     'opt_dead_code_local.cpp',
     'opt_dead_functions.cpp',
@@ -77,22 +76,19 @@ sources = [
     'opt_structure_splitting.cpp',
     'opt_swizzle_swizzle.cpp',
     'opt_tree_grafting.cpp',
+    'ralloc.c',
     's_expression.cpp',
     'strtod.c',
 ] 
 
 
-if env['platform'] == common.host_platform:
+if env['crosscompile'] and env['platform'] != 'embedded':
+    Import('builtin_glsl_function')
+else:
     if env['msvc']:
         env.Prepend(CPPPATH = ['#/src/getopt'])
         env.PrependUnique(LIBS = [getopt])
 
-    if env['platform'] == 'windows':
-        env.Prepend(CPPPATH = ['#src/talloc'])
-        env.Prepend(LIBS = [talloc])
-    else:
-        env.Prepend(LIBS = ['talloc'])
-
     builtin_compiler = env.Program(
         target = 'builtin_compiler',
         source = sources + ['main.cpp', 'builtin_stubs.cpp',
@@ -109,19 +105,12 @@ if env['platform'] == common.host_platform:
 
     env.Depends(builtin_glsl_function, ['builtins/tools/generate_builtins.py', 'builtins/tools/texture_builtins.py'] + Glob('builtins/ir/*'))
 
-    if env['msvc']:
-        # There is no LD_LIBRARY_PATH equivalent on Windows. We need to ensure
-        # talloc.dll is on the same dir as builtin_function.
-        talloc_dll_src = talloc.dir.File('talloc.dll')
-        talloc_dll_dst = builtin_compiler[0].dir.File('talloc.dll')
-        talloc_dll = env.Command(talloc_dll_dst, talloc_dll_src, Copy(talloc_dll_dst, talloc_dll_src))
-        env.Depends('builtin_function.cpp', talloc_dll)
-
     Export('builtin_glsl_function')
 
-    if common.cross_compiling:
+    if env['hostonly']:
         Return()
 
+
 sources += builtin_glsl_function
 
 glsl = env.ConvenienceLibrary(
@@ -141,7 +130,7 @@ if env['platform'] == 'windows':
         'user32',
     ])
 
-env.Prepend(LIBS = [glsl, talloc])
+env.Prepend(LIBS = [glsl])
 
 env.Program(
     target = 'glsl2',
index 0e2811ca665022e20988345e7c3cb040ee6e352f..878f48b20706613373c7959c998c499559ecf616 100644 (file)
@@ -49,23 +49,23 @@ 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). */
+   /* Callers of this ralloc-based new need not call delete. It's
+    * easier to just ralloc_free 'ctx' (or any of its ancestors). */
    static void* operator new(size_t size, void *ctx)
    {
       void *node;
 
-      node = talloc_zero_size(ctx, size);
+      node = rzalloc_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. */
+    * ralloc_free in that case. */
    static void operator delete(void *table)
    {
-      talloc_free(table);
+      ralloc_free(table);
    }
 
    /**
@@ -350,6 +350,14 @@ struct ast_type_qualifier {
          * qualifier is used.
          */
         unsigned explicit_location:1;
+
+         /** \name Layout qualifiers for GL_AMD_conservative_depth */
+         /** \{ */
+         unsigned depth_any:1;
+         unsigned depth_greater:1;
+         unsigned depth_less:1;
+         unsigned depth_unchanged:1;
+         /** \} */
       }
       /** \brief Set of flags, accessed by name. */
       q;
@@ -606,25 +614,6 @@ private:
 };
 
 
-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 *);
index 4e83decb924d95e775b5004c7227ffbf5865b033..e624d11cf3b271844fbe3c6c35157d188d252d49 100644 (file)
@@ -20,8 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
-#include <cstdio>
-#include <cassert>
+#include <assert.h>
 #include "ast.h"
 
 const char *
index 6ecf779c935abaf7a8ef7741f7ae5387f30b6a59..e5cb8733952f3f05266f3618afdc4253cd1c58b1 100644 (file)
@@ -66,7 +66,7 @@ process_parameters(exec_list *instructions, exec_list *actual_parameters,
  *                    formal or actual parameter list.  Only the type is used.
  *
  * \return
- * A talloced string representing the prototype of the function.
+ * A ralloced string representing the prototype of the function.
  */
 char *
 prototype_string(const glsl_type *return_type, const char *name,
@@ -75,19 +75,19 @@ prototype_string(const glsl_type *return_type, const char *name,
    char *str = NULL;
 
    if (return_type != NULL)
-      str = talloc_asprintf(str, "%s ", return_type->name);
+      str = ralloc_asprintf(NULL, "%s ", return_type->name);
 
-   str = talloc_asprintf_append(str, "%s(", name);
+   ralloc_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);
+      ralloc_asprintf_append(&str, "%s%s", comma, param->type->name);
       comma = ", ";
    }
 
-   str = talloc_strdup_append(str, ")");
+   ralloc_strcat(&str, ")");
    return str;
 }
 
@@ -132,6 +132,9 @@ match_function_by_name(exec_list *instructions, const char *name,
       /* 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.
+       *
+       * Also, validate that 'const_in' formal parameters (an extension of our
+       * IR) correspond to ir_constant actual parameters.
        */
       exec_list_iterator actual_iter = actual_parameters->iterator();
       exec_list_iterator formal_iter = sig->parameters.iterator();
@@ -143,14 +146,35 @@ match_function_by_name(exec_list *instructions, const char *name,
         assert(actual != NULL);
         assert(formal != NULL);
 
+        if (formal->mode == ir_var_const_in && !actual->as_constant()) {
+           _mesa_glsl_error(loc, state,
+                            "parameter `%s' must be a constant expression",
+                            formal->name);
+        }
+
         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");
+           const char *mode = NULL;
+           switch (formal->mode) {
+           case ir_var_out:   mode = "out";   break;
+           case ir_var_inout: mode = "inout"; break;
+           default:           assert(false);  break;
+           }
+            /* FIXME: 'loc' is incorrect (as of 2011-01-21). It is always
+             * FIXME: 0:0(0).
+             */
+           if (actual->variable_referenced()
+               && actual->variable_referenced()->read_only) {
+              _mesa_glsl_error(loc, state,
+                               "function parameter '%s %s' references the "
+                               "read-only variable '%s'",
+                               mode, formal->name,
+                               actual->variable_referenced()->name);
+
+           } else if (!actual->is_lvalue()) {
+               _mesa_glsl_error(loc, state,
+                                "function parameter '%s %s' is not an lvalue",
+                                mode, formal->name);
            }
         }
 
@@ -173,7 +197,7 @@ match_function_by_name(exec_list *instructions, const char *name,
         ir_dereference_variable *deref;
 
         var = new(ctx) ir_variable(sig->return_type,
-                                   talloc_asprintf(ctx, "%s_retval",
+                                   ralloc_asprintf(ctx, "%s_retval",
                                                    sig->function_name()),
                                    ir_var_temporary);
         instructions->push_tail(var);
@@ -195,11 +219,11 @@ match_function_by_name(exec_list *instructions, const char *name,
 
       _mesa_glsl_error(loc, state, "no matching function for call to `%s'",
                       str);
-      talloc_free(str);
+      ralloc_free(str);
 
       const char *prefix = "candidates are: ";
 
-      for (int i = -1; i < state->num_builtins_to_link; i++) {
+      for (int i = -1; i < (int) state->num_builtins_to_link; i++) {
         glsl_symbol_table *syms = i >= 0 ? state->builtins_to_link[i]->symbols
                                          : state->symbols;
         f = syms->get_function(name);
@@ -211,7 +235,7 @@ match_function_by_name(exec_list *instructions, const char *name,
 
            str = prototype_string(sig->return_type, f->name, &sig->parameters);
            _mesa_glsl_error(loc, state, "%s%s\n", prefix, str);
-           talloc_free(str);
+           ralloc_free(str);
 
            prefix = "                ";
         }
@@ -232,7 +256,7 @@ match_function_by_name(exec_list *instructions, const char *name,
 static ir_rvalue *
 convert_component(ir_rvalue *src, const glsl_type *desired_type)
 {
-   void *ctx = talloc_parent(src);
+   void *ctx = ralloc_parent(src);
    const unsigned a = desired_type->base_type;
    const unsigned b = src->type->base_type;
    ir_expression *result = NULL;
@@ -295,7 +319,7 @@ convert_component(ir_rvalue *src, const glsl_type *desired_type)
 static ir_rvalue *
 dereference_component(ir_rvalue *src, unsigned component)
 {
-   void *ctx = talloc_parent(src);
+   void *ctx = ralloc_parent(src);
    assert(component < src->type->components());
 
    /* If the source is a constant, just create a new constant instead of a
@@ -993,6 +1017,16 @@ ast_function_expression::hir(exec_list *instructions,
 
       const glsl_type *const constructor_type = type->glsl_type(& name, state);
 
+      /* constructor_type can be NULL if a variable with the same name as the
+       * structure has come into scope.
+       */
+      if (constructor_type == NULL) {
+        _mesa_glsl_error(& loc, state, "unknown type `%s' (structure name "
+                         "may be shadowed by a variable with the same name)",
+                         type->type_name);
+        return ir_call::get_error_instruction(ctx);
+      }
+
 
       /* Constructors for samplers are illegal.
        */
@@ -1022,6 +1056,57 @@ ast_function_expression::hir(exec_list *instructions,
        * correct order.  These constructors follow essentially the same type
        * matching rules as functions.
        */
+      if (constructor_type->is_record()) {
+        exec_list actual_parameters;
+
+        process_parameters(instructions, &actual_parameters,
+                           &this->expressions, state);
+
+        exec_node *node = actual_parameters.head;
+        for (unsigned i = 0; i < constructor_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'",
+                               constructor_type->name);
+              return ir_call::get_error_instruction(ctx);
+           }
+
+           if (apply_implicit_conversion(constructor_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)",
+                               constructor_type->name,
+                               constructor_type->fields.structure[i].name,
+                               ir->type->name,
+                               constructor_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'", constructor_type->name);
+           return ir_call::get_error_instruction(ctx);
+        }
+
+        ir_rvalue *const constant =
+           constant_record_constructor(constructor_type, &actual_parameters,
+                                       state);
+
+        return (constant != NULL)
+           ? constant
+           : emit_inline_record_constructor(constructor_type, instructions,
+                                            &actual_parameters, state);
+      }
+
       if (!constructor_type->is_numeric() && !constructor_type->is_boolean())
         return ir_call::get_error_instruction(ctx);
 
@@ -1197,54 +1282,6 @@ ast_function_expression::hir(exec_list *instructions,
       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);
index 7a171f3a2bbb627008c2d6abb704559e2495acbb..bef099cca3b9036f76348e179f2584ee4e4bf015 100644 (file)
@@ -435,6 +435,13 @@ modulus_result_type(const struct glsl_type *type_a,
                    const struct glsl_type *type_b,
                    struct _mesa_glsl_parse_state *state, YYLTYPE *loc)
 {
+   if (state->language_version < 130) {
+      _mesa_glsl_error(loc, state,
+                       "operator '%%' is reserved in %s",
+                       state->version_string);
+      return glsl_type::error_type;
+   }
+
    /* 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
@@ -639,7 +646,14 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
    bool error_emitted = (lhs->type->is_error() || rhs->type->is_error());
 
    if (!error_emitted) {
-      if (!lhs->is_lvalue()) {
+      if (lhs->variable_referenced() != NULL
+          && lhs->variable_referenced()->read_only) {
+         _mesa_glsl_error(&lhs_loc, state,
+                          "assignment to read-only variable '%s'",
+                          lhs->variable_referenced()->name);
+         error_emitted = true;
+
+      } else if (!lhs->is_lvalue()) {
         _mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment");
         error_emitted = true;
       }
@@ -712,7 +726,7 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
 static ir_rvalue *
 get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue)
 {
-   void *ctx = talloc_parent(lvalue);
+   void *ctx = ralloc_parent(lvalue);
    ir_variable *var;
 
    var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp",
@@ -1809,7 +1823,6 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
       }
    }
 
-   /* FINISHME: Mark 'in' variables at global scope as read-only. */
    if (qual->flags.q.constant || qual->flags.q.attribute
        || qual->flags.q.uniform
        || (qual->flags.q.varying && (state->target == fragment_shader)))
@@ -2003,6 +2016,40 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
       }
    }
 
+   /* Layout qualifiers for gl_FragDepth, which are enabled by extension
+    * AMD_conservative_depth.
+    */
+   int depth_layout_count = qual->flags.q.depth_any
+      + qual->flags.q.depth_greater
+      + qual->flags.q.depth_less
+      + qual->flags.q.depth_unchanged;
+   if (depth_layout_count > 0
+       && !state->AMD_conservative_depth_enable) {
+       _mesa_glsl_error(loc, state,
+                        "extension GL_AMD_conservative_depth must be enabled "
+                       "to use depth layout qualifiers");
+   } else if (depth_layout_count > 0
+              && strcmp(var->name, "gl_FragDepth") != 0) {
+       _mesa_glsl_error(loc, state,
+                        "depth layout qualifiers can be applied only to "
+                        "gl_FragDepth");
+   } else if (depth_layout_count > 1
+              && strcmp(var->name, "gl_FragDepth") == 0) {
+      _mesa_glsl_error(loc, state,
+                       "at most one depth layout qualifier can be applied to "
+                       "gl_FragDepth");
+   }
+   if (qual->flags.q.depth_any)
+      var->depth_layout = ir_depth_layout_any;
+   else if (qual->flags.q.depth_greater)
+      var->depth_layout = ir_depth_layout_greater;
+   else if (qual->flags.q.depth_less)
+      var->depth_layout = ir_depth_layout_less;
+   else if (qual->flags.q.depth_unchanged)
+       var->depth_layout = ir_depth_layout_unchanged;
+   else
+       var->depth_layout = ir_depth_layout_none;
+
    if (var->type->is_array() && state->language_version != 110) {
       var->array_lvalue = true;
    }
@@ -2206,6 +2253,8 @@ ast_declarator_list::hir(exec_list *instructions,
                             mode, var->name, extra);
         }
       } else if (var->mode == ir_var_in) {
+         var->read_only = true;
+
         if (state->target == vertex_shader) {
            bool error_emitted = false;
 
@@ -2591,6 +2640,36 @@ ast_declarator_list::hir(exec_list *instructions,
                    && earlier->type == var->type
                    && earlier->mode == var->mode) {
            earlier->interpolation = var->interpolation;
+
+         /* Layout qualifiers for gl_FragDepth. */
+         } else if (state->AMD_conservative_depth_enable
+                    && strcmp(var->name, "gl_FragDepth") == 0
+                    && earlier->type == var->type
+                    && earlier->mode == var->mode) {
+
+            /** From the AMD_conservative_depth spec:
+             *     Within any shader, the first redeclarations of gl_FragDepth
+             *     must appear before any use of gl_FragDepth.
+             */
+            if (earlier->used) {
+               _mesa_glsl_error(&loc, state,
+                                "the first redeclaration of gl_FragDepth "
+                                "must appear before any use of gl_FragDepth");
+            }
+
+            /* Prevent inconsistent redeclaration of depth layout qualifier. */
+            if (earlier->depth_layout != ir_depth_layout_none
+                && earlier->depth_layout != var->depth_layout) {
+               _mesa_glsl_error(&loc, state,
+                                "gl_FragDepth: depth layout is declared here "
+                                "as '%s, but it was previously declared as "
+                                "'%s'",
+                                depth_layout_string(var->depth_layout),
+                                depth_layout_string(earlier->depth_layout));
+            }
+
+            earlier->depth_layout = var->depth_layout;
+
         } else {
            YYLTYPE loc = this->get_location();
            _mesa_glsl_error(&loc, state, "`%s' redeclared", decl->identifier);
@@ -3002,27 +3081,26 @@ ast_jump_statement::hir(exec_list *instructions,
       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_rvalue *const ret = opt_return_value->hir(instructions, state);
-        assert(ret != NULL);
+
+        /* The value of the return type can be NULL if the shader says
+         * 'return foo();' and foo() is a function that returns void.
+         *
+         * NOTE: The GLSL spec doesn't say that this is an error.  The type
+         * of the return value is void.  If the return type of the function is
+         * also void, then this should compile without error.  Seriously.
+         */
+        const glsl_type *const ret_type =
+           (ret == NULL) ? glsl_type::void_type : ret->type;
 
         /* Implicit conversions are not allowed for return values. */
-        if (state->current_function->return_type != ret->type) {
+        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,
+                            ret_type->name,
                             state->current_function->function_name(),
                             state->current_function->return_type->name);
         }
@@ -3321,7 +3399,7 @@ ast_struct_specifier::hir(exec_list *instructions,
     * 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,
+   glsl_struct_field *const fields = ralloc_array(state, glsl_struct_field,
                                                  decl_count);
 
    unsigned i = 0;
index d14077473f0fc0c83b96e8eea12049fd236006a0..c680ae5f67123f326f3ccf41c6b112fa817b9c51 100644 (file)
@@ -21,7 +21,6 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-#include <cstdio>
 #include "ast.h"
 extern "C" {
 #include "program/symbol_table.h"
index 329116f2a28843b1816e3e4dcf5d9099dc22b304..43653a906f8ce49d64871076ab5b14ed65afec9f 100644 (file)
@@ -635,7 +635,6 @@ 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);
@@ -687,7 +686,6 @@ 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);
@@ -710,7 +708,6 @@ uvec4 texelFetch(usampler1DArray sampler, ivec2 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);
@@ -801,7 +798,6 @@ 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);
@@ -825,7 +821,6 @@ 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);
@@ -847,7 +842,6 @@ 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);
@@ -881,7 +875,6 @@ 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);
@@ -912,7 +905,6 @@ 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);
@@ -936,7 +928,6 @@ 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);
@@ -958,7 +949,6 @@ 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:
index 1c212ebb3c5ef8da79e9b7eba8b9cb4ef195712c..742dec6e6d51e658388e6fa9ac98c0a49e342e03 100644 (file)
@@ -637,7 +637,6 @@ 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);
@@ -689,7 +688,6 @@ 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);
@@ -712,7 +710,6 @@ uvec4 texelFetch(usampler1DArray sampler, ivec2 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);
@@ -803,7 +800,6 @@ 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);
@@ -827,7 +823,6 @@ 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);
@@ -849,7 +844,6 @@ 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);
@@ -883,7 +877,6 @@ 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);
@@ -914,7 +907,6 @@ 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);
@@ -938,7 +930,6 @@ 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);
@@ -960,7 +951,6 @@ 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:
index 3a938a022da5e571fb181269c7a2ac79439acfe2..edd3c70e00bdcdc078d171a0f2e2fe07b0feec57 100755 (executable)
@@ -152,6 +152,8 @@ read_builtins(GLenum target, const char *protos, const char **functions, unsigne
 {
    struct gl_context fakeCtx;
    fakeCtx.API = API_OPENGL;
+   fakeCtx.Const.GLSLVersion = 130;
+   fakeCtx.Extensions.ARB_ES2_compatibility = true;
    gl_shader *sh = _mesa_new_shader(NULL, 0, target);
    struct _mesa_glsl_parse_state *st =
       new(sh) _mesa_glsl_parse_state(&fakeCtx, target, sh);
@@ -178,7 +180,7 @@ read_builtins(GLenum target, const char *protos, const char **functions, unsigne
       if (st->error) {
          printf("error reading builtin: %.35s ...\\n", functions[i]);
          printf("Info log:\\n%s\\n", st->info_log);
-         talloc_free(sh);
+         ralloc_free(sh);
          return NULL;
       }
    }
@@ -203,7 +205,7 @@ void *builtin_mem_ctx = NULL;
 void
 _mesa_glsl_release_functions(void)
 {
-   talloc_free(builtin_mem_ctx);
+   ralloc_free(builtin_mem_ctx);
    builtin_mem_ctx = NULL;
    memset(builtin_profiles, 0, sizeof(builtin_profiles));
 }
@@ -219,7 +221,7 @@ _mesa_read_profile(struct _mesa_glsl_parse_state *state,
 
    if (sh == NULL) {
       sh = read_builtins(GL_VERTEX_SHADER, prototypes, functions, count);
-      talloc_steal(builtin_mem_ctx, sh);
+      ralloc_steal(builtin_mem_ctx, sh);
       builtin_profiles[profile_index] = sh;
    }
 
@@ -231,7 +233,7 @@ void
 _mesa_glsl_initialize_functions(struct _mesa_glsl_parse_state *state)
 {
    if (builtin_mem_ctx == NULL) {
-      builtin_mem_ctx = talloc_init("GLSL built-in functions");
+      builtin_mem_ctx = ralloc_context(NULL); // "GLSL built-in functions"
       memset(&builtin_profiles, 0, sizeof(builtin_profiles));
    }
 
index 8bf708b5aac7c536a272cdb29e4fbdc80bcc5f8d..8017e943b1ba877e99b1b751831c385c061c7c96 100755 (executable)
@@ -3,6 +3,10 @@
 import sys
 import StringIO
 
+# Bitfield constants for the 'variant' argument to generate_sigs
+Proj = 1
+Offset = 2
+
 def vec_type(g, size):
     if size == 1:
         if g == "i":
@@ -12,16 +16,20 @@ def vec_type(g, size):
         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):
+# Get the sampler dimension - i.e. sampler3D gives 3
+def get_sampler_dim(sampler_type):
     if sampler_type[0].isdigit():
-        coord_dim = int(sampler_type[0])
+        sampler_dim = int(sampler_type[0])
     elif sampler_type.startswith("Cube"):
-        coord_dim = 3
+        sampler_dim = 3
     else:
         assert False ("coord_dim: invalid sampler_type: " + sampler_type)
+    return sampler_dim
 
+# Get the coordinate dimension for a given sampler type.
+# Array samplers also get +1 here since the layer is really an extra coordinate
+def get_coord_dim(sampler_type):
+    coord_dim = get_sampler_dim(sampler_type)
     if sampler_type.find("Array") != -1:
         coord_dim += 1
     return coord_dim
@@ -35,18 +43,17 @@ def get_extra_dim(sampler_type, use_proj, unused_fields):
         extra_dim += 1
     return extra_dim
 
-def generate_sigs(g, tex_inst, sampler_type, use_proj = False, unused_fields = 0):
+def generate_sigs(g, tex_inst, sampler_type, variant = 0, unused_fields = 0):
     coord_dim = get_coord_dim(sampler_type)
-    extra_dim = get_extra_dim(sampler_type, use_proj, unused_fields)
+    extra_dim = get_extra_dim(sampler_type, variant & Proj, unused_fields)
+    offset_dim = get_sampler_dim(sampler_type)
 
     # 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":
+    if tex_inst == "txl":
         print "\n       (declare (in) float lod)",
     elif tex_inst == "txf":
         print "\n       (declare (in) int lod)",
@@ -55,6 +62,11 @@ def generate_sigs(g, tex_inst, sampler_type, use_proj = False, unused_fields = 0
         print "\n       (declare (in) " + grad_type + " dPdx)",
         print "\n       (declare (in) " + grad_type + " dPdy)",
 
+    if variant & Offset:
+        print "\n       (declare (const_in) " + vec_type("i", offset_dim) + " offset)",
+    if tex_inst == "txb":
+        print "\n       (declare (in) float bias)",
+
     print ")\n     ((return (" + tex_inst + " (var_ref sampler)",
 
     # Coordinate
@@ -63,12 +75,14 @@ def generate_sigs(g, tex_inst, sampler_type, use_proj = False, unused_fields = 0
     else:
         print "(var_ref P)",
 
-    # Offset
-    print "(0 0 0)",
+    if variant & Offset:
+        print "(var_ref offset)",
+    else:
+        print "0",
 
     if tex_inst != "txf":
         # Projective divisor
-        if use_proj:
+        if variant & Proj:
             print "(swiz " + "xyzw"[coord_dim + extra_dim-1] + " (var_ref P))",
         else:
             print "1",
@@ -90,10 +104,10 @@ def generate_sigs(g, tex_inst, sampler_type, use_proj = False, unused_fields = 0
         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 generate_fiu_sigs(tex_inst, sampler_type, variant = 0, unused_fields = 0):
+    generate_sigs("",  tex_inst, sampler_type, variant, unused_fields)
+    generate_sigs("i", tex_inst, sampler_type, variant, unused_fields)
+    generate_sigs("u", tex_inst, sampler_type, variant, unused_fields)
 
 def start_function(name):
     sys.stdout = StringIO.StringIO()
@@ -127,17 +141,17 @@ def generate_texture_functions(fs):
     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)
+    generate_fiu_sigs("tex", "1D", Proj)
+    generate_fiu_sigs("tex", "1D", Proj, 2)
+    generate_fiu_sigs("tex", "2D", Proj)
+    generate_fiu_sigs("tex", "2D", Proj, 1)
+    generate_fiu_sigs("tex", "3D", Proj)
+
+    generate_fiu_sigs("txb", "1D", Proj)
+    generate_fiu_sigs("txb", "1D", Proj, 2)
+    generate_fiu_sigs("txb", "2D", Proj)
+    generate_fiu_sigs("txb", "2D", Proj, 1)
+    generate_fiu_sigs("txb", "3D", Proj)
     end_function(fs, "textureProj")
 
     start_function("textureLod")
@@ -149,6 +163,28 @@ def generate_texture_functions(fs):
     generate_fiu_sigs("txl", "2DArray")
     end_function(fs, "textureLod")
 
+    start_function("textureLodOffset")
+    generate_fiu_sigs("txl", "1D", Offset)
+    generate_fiu_sigs("txl", "2D", Offset)
+    generate_fiu_sigs("txl", "3D", Offset)
+    generate_fiu_sigs("txl", "1DArray", Offset)
+    generate_fiu_sigs("txl", "2DArray", Offset)
+    end_function(fs, "textureLodOffset")
+
+    start_function("textureOffset")
+    generate_fiu_sigs("tex", "1D", Offset)
+    generate_fiu_sigs("tex", "2D", Offset)
+    generate_fiu_sigs("tex", "3D", Offset)
+    generate_fiu_sigs("tex", "1DArray", Offset)
+    generate_fiu_sigs("tex", "2DArray", Offset)
+
+    generate_fiu_sigs("txb", "1D", Offset)
+    generate_fiu_sigs("txb", "2D", Offset)
+    generate_fiu_sigs("txb", "3D", Offset)
+    generate_fiu_sigs("txb", "1DArray", Offset)
+    generate_fiu_sigs("txb", "2DArray", Offset)
+    end_function(fs, "textureOffset")
+
     start_function("texelFetch")
     generate_fiu_sigs("txf", "1D")
     generate_fiu_sigs("txf", "2D")
@@ -157,14 +193,44 @@ def generate_texture_functions(fs):
     generate_fiu_sigs("txf", "2DArray")
     end_function(fs, "texelFetch")
 
+    start_function("texelFetchOffset")
+    generate_fiu_sigs("txf", "1D", Offset)
+    generate_fiu_sigs("txf", "2D", Offset)
+    generate_fiu_sigs("txf", "3D", Offset)
+    generate_fiu_sigs("txf", "1DArray", Offset)
+    generate_fiu_sigs("txf", "2DArray", Offset)
+    end_function(fs, "texelFetchOffset")
+
+    start_function("textureProjOffset")
+    generate_fiu_sigs("tex", "1D", Proj | Offset)
+    generate_fiu_sigs("tex", "1D", Proj | Offset, 2)
+    generate_fiu_sigs("tex", "2D", Proj | Offset)
+    generate_fiu_sigs("tex", "2D", Proj | Offset, 1)
+    generate_fiu_sigs("tex", "3D", Proj | Offset)
+
+    generate_fiu_sigs("txb", "1D", Proj | Offset)
+    generate_fiu_sigs("txb", "1D", Proj | Offset, 2)
+    generate_fiu_sigs("txb", "2D", Proj | Offset)
+    generate_fiu_sigs("txb", "2D", Proj | Offset, 1)
+    generate_fiu_sigs("txb", "3D", Proj | Offset)
+    end_function(fs, "textureProjOffset")
+
     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)
+    generate_fiu_sigs("txl", "1D", Proj)
+    generate_fiu_sigs("txl", "1D", Proj, 2)
+    generate_fiu_sigs("txl", "2D", Proj)
+    generate_fiu_sigs("txl", "2D", Proj, 1)
+    generate_fiu_sigs("txl", "3D", Proj)
     end_function(fs, "textureProjLod")
 
+    start_function("textureProjLodOffset")
+    generate_fiu_sigs("txl", "1D", Proj | Offset)
+    generate_fiu_sigs("txl", "1D", Proj | Offset, 2)
+    generate_fiu_sigs("txl", "2D", Proj | Offset)
+    generate_fiu_sigs("txl", "2D", Proj | Offset, 1)
+    generate_fiu_sigs("txl", "3D", Proj | Offset)
+    end_function(fs, "textureProjLodOffset")
+
     start_function("textureGrad")
     generate_fiu_sigs("txd", "1D")
     generate_fiu_sigs("txd", "2D")
@@ -174,22 +240,40 @@ def generate_texture_functions(fs):
     generate_fiu_sigs("txd", "2DArray")
     end_function(fs, "textureGrad")
 
+    start_function("textureGradOffset")
+    generate_fiu_sigs("txd", "1D", Offset)
+    generate_fiu_sigs("txd", "2D", Offset)
+    generate_fiu_sigs("txd", "3D", Offset)
+    generate_fiu_sigs("txd", "Cube", Offset)
+    generate_fiu_sigs("txd", "1DArray", Offset)
+    generate_fiu_sigs("txd", "2DArray", Offset)
+    end_function(fs, "textureGradOffset")
+
     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)
+    generate_fiu_sigs("txd", "1D", Proj)
+    generate_fiu_sigs("txd", "1D", Proj, 2)
+    generate_fiu_sigs("txd", "2D", Proj)
+    generate_fiu_sigs("txd", "2D", Proj, 1)
+    generate_fiu_sigs("txd", "3D", Proj)
     end_function(fs, "textureProjGrad")
 
+    start_function("textureProjGradOffset")
+    generate_fiu_sigs("txd", "1D", Proj | Offset)
+    generate_fiu_sigs("txd", "1D", Proj | Offset, 2)
+    generate_fiu_sigs("txd", "2D", Proj | Offset)
+    generate_fiu_sigs("txd", "2D", Proj | Offset, 1)
+    generate_fiu_sigs("txd", "3D", Proj | Offset)
+    end_function(fs, "textureProjGradOffset")
+
+
     # 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)
+    generate_sigs("", "tex", "2DRect", Proj)
+    generate_sigs("", "tex", "2DRect", Proj, 1)
     end_function(fs, "texture2DRectProj")
 
     start_function("shadow2DRect")
@@ -197,7 +281,7 @@ def generate_texture_functions(fs):
     end_function(fs, "shadow2DRect")
 
     start_function("shadow2DRectProj")
-    generate_sigs("", "tex", "2DRectShadow", True)
+    generate_sigs("", "tex", "2DRectShadow", Proj)
     end_function(fs, "shadow2DRectProj")
 
     # EXT_texture_array extension
@@ -243,15 +327,15 @@ def generate_texture_functions(fs):
     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)
+    generate_sigs("", "tex", "1D", Proj)
+    generate_sigs("", "tex", "1D", Proj, 2)
+    generate_sigs("", "txb", "1D", Proj)
+    generate_sigs("", "txb", "1D", Proj, 2)
     end_function(fs, "texture1DProj")
 
     start_function("texture1DProjLod")
-    generate_sigs("", "txl", "1D", True)
-    generate_sigs("", "txl", "1D", True, 2)
+    generate_sigs("", "txl", "1D", Proj)
+    generate_sigs("", "txl", "1D", Proj, 2)
     end_function(fs, "texture1DProjLod")
 
     start_function("texture2D")
@@ -264,15 +348,15 @@ def generate_texture_functions(fs):
     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)
+    generate_sigs("", "tex", "2D", Proj)
+    generate_sigs("", "tex", "2D", Proj, 1)
+    generate_sigs("", "txb", "2D", Proj)
+    generate_sigs("", "txb", "2D", Proj, 1)
     end_function(fs, "texture2DProj")
 
     start_function("texture2DProjLod")
-    generate_sigs("", "txl", "2D", True)
-    generate_sigs("", "txl", "2D", True, 1)
+    generate_sigs("", "txl", "2D", Proj)
+    generate_sigs("", "txl", "2D", Proj, 1)
     end_function(fs, "texture2DProjLod")
 
     start_function("texture3D")
@@ -285,12 +369,12 @@ def generate_texture_functions(fs):
     end_function(fs, "texture3DLod")
 
     start_function("texture3DProj")
-    generate_sigs("", "tex", "3D", True)
-    generate_sigs("", "txb", "3D", True)
+    generate_sigs("", "tex", "3D", Proj)
+    generate_sigs("", "txb", "3D", Proj)
     end_function(fs, "texture3DProj")
 
     start_function("texture3DProjLod")
-    generate_sigs("", "txl", "3D", True)
+    generate_sigs("", "txl", "3D", Proj)
     end_function(fs, "texture3DProjLod")
 
     start_function("textureCube")
@@ -312,12 +396,12 @@ def generate_texture_functions(fs):
     end_function(fs, "shadow1DLod")
 
     start_function("shadow1DProj")
-    generate_sigs("", "tex", "1DShadow", True, 1)
-    generate_sigs("", "txb", "1DShadow", True, 1)
+    generate_sigs("", "tex", "1DShadow", Proj, 1)
+    generate_sigs("", "txb", "1DShadow", Proj, 1)
     end_function(fs, "shadow1DProj")
 
     start_function("shadow1DProjLod")
-    generate_sigs("", "txl", "1DShadow", True, 1)
+    generate_sigs("", "txl", "1DShadow", Proj, 1)
     end_function(fs, "shadow1DProjLod")
 
     start_function("shadow2D")
@@ -330,12 +414,12 @@ def generate_texture_functions(fs):
     end_function(fs, "shadow2DLod")
 
     start_function("shadow2DProj")
-    generate_sigs("", "tex", "2DShadow", True)
-    generate_sigs("", "txb", "2DShadow", True)
+    generate_sigs("", "tex", "2DShadow", Proj)
+    generate_sigs("", "txb", "2DShadow", Proj)
     end_function(fs, "shadow2DProj")
 
     start_function("shadow2DProjLod")
-    generate_sigs("", "txl", "2DShadow", True)
+    generate_sigs("", "txl", "2DShadow", Proj)
     end_function(fs, "shadow2DProjLod")
 
     sys.stdout = sys.__stdout__
@@ -346,4 +430,4 @@ if __name__ == "__main__":
     fs = {}
     generate_texture_functions(fs);
     for k, v in fs.iteritems():
-       print v
+        print v
diff --git a/src/glsl/configure.ac b/src/glsl/configure.ac
deleted file mode 100644 (file)
index 73ce67d..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-#                                               -*- 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])
index 156af3008c073cea5952e08de2b7947a4d909c54..b53bea6271d1ca9169cad9f87fd001f8f884e565 100644 (file)
@@ -795,6 +795,10 @@ int glcpp_get_lineno (yyscan_t yyscanner );
 
 void glcpp_set_lineno (int line_number ,yyscan_t yyscanner );
 
+int glcpp_get_column  (yyscan_t yyscanner );
+
+void glcpp_set_column (int column_no ,yyscan_t yyscanner );
+
 YYSTYPE * glcpp_get_lval (yyscan_t yyscanner );
 
 void glcpp_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
@@ -954,7 +958,7 @@ YY_DECL
 
 
        /* Single-line comments */
-#line 958 "glcpp/glcpp-lex.c"
+#line 962 "glcpp/glcpp-lex.c"
 
     yylval = yylval_param;
 
@@ -1121,7 +1125,7 @@ case 8:
 YY_RULE_SETUP
 #line 94 "glcpp/glcpp-lex.l"
 {
-       yylval->str = talloc_strdup (yyextra, yytext);
+       yylval->str = ralloc_strdup (yyextra, yytext);
        yyextra->space_tokens = 0;
        return HASH_VERSION;
 }
@@ -1132,7 +1136,7 @@ case 9:
 YY_RULE_SETUP
 #line 102 "glcpp/glcpp-lex.l"
 {
-       yylval->str = talloc_strdup (yyextra, yytext);
+       yylval->str = ralloc_strdup (yyextra, yytext);
        yylineno++;
        yycolumn = 0;
        return OTHER;
@@ -1312,7 +1316,7 @@ case 24:
 YY_RULE_SETUP
 #line 221 "glcpp/glcpp-lex.l"
 {
-       yylval->str = talloc_strdup (yyextra, yytext);
+       yylval->str = ralloc_strdup (yyextra, yytext);
        return INTEGER_STRING;
 }
        YY_BREAK
@@ -1320,7 +1324,7 @@ case 25:
 YY_RULE_SETUP
 #line 226 "glcpp/glcpp-lex.l"
 {
-       yylval->str = talloc_strdup (yyextra, yytext);
+       yylval->str = ralloc_strdup (yyextra, yytext);
        return INTEGER_STRING;
 }
        YY_BREAK
@@ -1328,7 +1332,7 @@ case 26:
 YY_RULE_SETUP
 #line 231 "glcpp/glcpp-lex.l"
 {
-       yylval->str = talloc_strdup (yyextra, yytext);
+       yylval->str = ralloc_strdup (yyextra, yytext);
        return INTEGER_STRING;
 }
        YY_BREAK
@@ -1406,7 +1410,7 @@ case 37:
 YY_RULE_SETUP
 #line 276 "glcpp/glcpp-lex.l"
 {
-       yylval->str = talloc_strdup (yyextra, yytext);
+       yylval->str = ralloc_strdup (yyextra, yytext);
        return IDENTIFIER;
 }
        YY_BREAK
@@ -1421,7 +1425,7 @@ case 39:
 YY_RULE_SETUP
 #line 285 "glcpp/glcpp-lex.l"
 {
-       yylval->str = talloc_strdup (yyextra, yytext);
+       yylval->str = ralloc_strdup (yyextra, yytext);
        return OTHER;
 }
        YY_BREAK
@@ -1471,7 +1475,7 @@ YY_RULE_SETUP
 #line 319 "glcpp/glcpp-lex.l"
 ECHO;
        YY_BREAK
-#line 1475 "glcpp/glcpp-lex.c"
+#line 1479 "glcpp/glcpp-lex.c"
                        case YY_STATE_EOF(DONE):
                        case YY_STATE_EOF(COMMENT):
                        case YY_STATE_EOF(UNREACHABLE):
index e936854cf2c51e3df3bdb87da554b82b391d7b07..11b73aea88b4f68ac34b0ca1c520312038230cdb 100644 (file)
@@ -92,7 +92,7 @@ HEXADECIMAL_INTEGER   0[xX][0-9a-fA-F]+[uU]?
 }
 
 {HASH}version {
-       yylval->str = talloc_strdup (yyextra, yytext);
+       yylval->str = ralloc_strdup (yyextra, yytext);
        yyextra->space_tokens = 0;
        return HASH_VERSION;
 }
@@ -100,7 +100,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
        /* 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);
+       yylval->str = ralloc_strdup (yyextra, yytext);
        yylineno++;
        yycolumn = 0;
        return OTHER;
@@ -219,17 +219,17 @@ HEXADECIMAL_INTEGER       0[xX][0-9a-fA-F]+[uU]?
 }
 
 {DECIMAL_INTEGER} {
-       yylval->str = talloc_strdup (yyextra, yytext);
+       yylval->str = ralloc_strdup (yyextra, yytext);
        return INTEGER_STRING;
 }
 
 {OCTAL_INTEGER} {
-       yylval->str = talloc_strdup (yyextra, yytext);
+       yylval->str = ralloc_strdup (yyextra, yytext);
        return INTEGER_STRING;
 }
 
 {HEXADECIMAL_INTEGER} {
-       yylval->str = talloc_strdup (yyextra, yytext);
+       yylval->str = ralloc_strdup (yyextra, yytext);
        return INTEGER_STRING;
 }
 
@@ -274,7 +274,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
 }
 
 {IDENTIFIER} {
-       yylval->str = talloc_strdup (yyextra, yytext);
+       yylval->str = ralloc_strdup (yyextra, yytext);
        return IDENTIFIER;
 }
 
@@ -283,7 +283,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
 }
 
 {OTHER}+ {
-       yylval->str = talloc_strdup (yyextra, yytext);
+       yylval->str = ralloc_strdup (yyextra, yytext);
        return OTHER;
 }
 
index a5566dc0aaf7a2d8418b72a201134a42ccbf2bc4..1e71b18c4cbea5cb156a594c16d74e33278c1c7a 100644 (file)
@@ -1,10 +1,9 @@
-
-/* A Bison parser, made by GNU Bison 2.4.1.  */
+/* A Bison parser, made by GNU Bison 2.4.3.  */
 
 /* 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.
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2009, 2010 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
@@ -46,7 +45,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.4.1"
+#define YYBISON_VERSION "2.4.3"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
 #include "main/core.h" /* for struct gl_extensions */
 #include "main/mtypes.h" /* for gl_api enum */
 
-#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);
 
@@ -150,7 +145,7 @@ _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. */
+/* Note: This function ralloc_steal()s the str pointer. */
 static token_t *
 _token_create_str (void *ctx, int type, char *str);
 
@@ -160,10 +155,7 @@ _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. */
+/* Note: This function calls ralloc_steal on token. */
 static void
 _token_list_append (token_list_t *list, token_t *token);
 
@@ -220,7 +212,7 @@ add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
 
 
 /* Line 189 of yacc.c  */
-#line 224 "glcpp/glcpp-parse.c"
+#line 216 "glcpp/glcpp-parse.c"
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
@@ -308,7 +300,7 @@ typedef struct YYLTYPE
 
 
 /* Line 264 of yacc.c  */
-#line 312 "glcpp/glcpp-parse.c"
+#line 304 "glcpp/glcpp-parse.c"
 
 #ifdef short
 # undef short
@@ -358,7 +350,7 @@ typedef short int yytype_int16;
 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
 #ifndef YY_
-# if YYENABLE_NLS
+# if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
 #   define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -633,17 +625,17 @@ static const yytype_int8 yyrhs[] =
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   188,   188,   190,   194,   197,   202,   203,   207,   210,
-     216,   219,   222,   225,   233,   252,   262,   267,   272,   291,
-     306,   309,   312,   333,   337,   346,   351,   352,   355,   358,
-     361,   364,   367,   370,   373,   376,   379,   382,   385,   388,
-     391,   394,   397,   400,   408,   411,   414,   417,   420,   423,
-     429,   434,   442,   443,   447,   453,   454,   457,   459,   466,
-     470,   474,   479,   484,   492,   498,   506,   510,   514,   518,
-     522,   529,   530,   531,   532,   533,   534,   535,   536,   537,
-     538,   539,   540,   541,   542,   543,   544,   545,   546,   547,
-     548,   549,   550,   551,   552,   553,   554,   555,   556,   557,
-     558,   559
+       0,   181,   181,   183,   187,   190,   195,   196,   200,   203,
+     209,   212,   215,   218,   226,   245,   255,   260,   265,   284,
+     299,   302,   305,   326,   330,   339,   344,   345,   348,   351,
+     354,   357,   360,   363,   366,   369,   372,   375,   378,   381,
+     384,   387,   390,   398,   406,   409,   412,   415,   418,   421,
+     427,   432,   440,   441,   445,   451,   452,   455,   457,   464,
+     468,   472,   477,   481,   488,   493,   500,   504,   508,   512,
+     516,   523,   524,   525,   526,   527,   528,   529,   530,   531,
+     532,   533,   534,   535,   536,   537,   538,   539,   540,   541,
+     542,   543,   544,   545,   546,   547,   548,   549,   550,   551,
+     552,   553
 };
 #endif
 
@@ -946,9 +938,18 @@ static const yytype_uint8 yystos[] =
 
 /* 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.  */
+   Once GCC version 2 has supplanted version 1, this can go.  However,
+   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
+   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+   discussed.  */
 
 #define YYFAIL         goto yyerrlab
+#if defined YYFAIL
+  /* This is here to suppress warnings from the GCC cpp's
+     -Wunused-macros.  Normally we don't worry about that warning, but
+     some users do, and we want to make it easy for users to remove
+     YYFAIL uses, which will produce warnings from Bison 2.5.  */
+#endif
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
@@ -1005,7 +1006,7 @@ while (YYID (0))
    we won't break user code: when these are the locations we know.  */
 
 #ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
 #  define YY_LOCATION_PRINT(File, Loc)                 \
      fprintf (File, "%d.%d-%d.%d",                     \
              (Loc).first_line, (Loc).first_column,     \
@@ -1547,7 +1548,7 @@ YYLTYPE yylloc;
     YYLTYPE *yylsp;
 
     /* The locations where the error started and ended.  */
-    YYLTYPE yyerror_range[2];
+    YYLTYPE yyerror_range[3];
 
     YYSIZE_T yystacksize;
 
@@ -1594,7 +1595,7 @@ YYLTYPE yylloc;
   yyvsp = yyvs;
   yylsp = yyls;
 
-#if YYLTYPE_IS_TRIVIAL
+#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
   /* Initialize the default location before parsing starts.  */
   yylloc.first_line   = yylloc.last_line   = 1;
   yylloc.first_column = yylloc.last_column = 1;
@@ -1602,8 +1603,8 @@ YYLTYPE yylloc;
 
 /* User initialization code.  */
 
-/* Line 1242 of yacc.c  */
-#line 155 "glcpp/glcpp-parse.y"
+/* Line 1251 of yacc.c  */
+#line 148 "glcpp/glcpp-parse.y"
 {
        yylloc.first_line = 1;
        yylloc.first_column = 1;
@@ -1612,8 +1613,8 @@ YYLTYPE yylloc;
        yylloc.source = 0;
 }
 
-/* Line 1242 of yacc.c  */
-#line 1617 "glcpp/glcpp-parse.c"
+/* Line 1251 of yacc.c  */
+#line 1618 "glcpp/glcpp-parse.c"
   yylsp[0] = yylloc;
 
   goto yysetstate;
@@ -1800,28 +1801,28 @@ yyreduce:
     {
         case 4:
 
-/* Line 1455 of yacc.c  */
-#line 194 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 187 "glcpp/glcpp-parse.y"
     {
-               glcpp_print(parser->output, "\n");
+               ralloc_strcat (&parser->output, "\n");
        ;}
     break;
 
   case 5:
 
-/* Line 1455 of yacc.c  */
-#line 197 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 190 "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));
+               ralloc_strcat (&parser->output, "\n");
+               ralloc_free ((yyvsp[(1) - (1)].token_list));
        ;}
     break;
 
   case 8:
 
-/* Line 1455 of yacc.c  */
-#line 207 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 200 "glcpp/glcpp-parse.y"
     {
                _glcpp_parser_skip_stack_push_if (parser, & (yylsp[(1) - (3)]), (yyvsp[(2) - (3)].ival));
        ;}
@@ -1829,8 +1830,8 @@ yyreduce:
 
   case 9:
 
-/* Line 1455 of yacc.c  */
-#line 210 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 203 "glcpp/glcpp-parse.y"
     {
                _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (3)]), "elif", (yyvsp[(2) - (3)].ival));
        ;}
@@ -1838,8 +1839,8 @@ yyreduce:
 
   case 10:
 
-/* Line 1455 of yacc.c  */
-#line 216 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 209 "glcpp/glcpp-parse.y"
     {
                _define_object_macro (parser, & (yylsp[(2) - (4)]), (yyvsp[(2) - (4)].str), (yyvsp[(3) - (4)].token_list));
        ;}
@@ -1847,8 +1848,8 @@ yyreduce:
 
   case 11:
 
-/* Line 1455 of yacc.c  */
-#line 219 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 212 "glcpp/glcpp-parse.y"
     {
                _define_function_macro (parser, & (yylsp[(2) - (6)]), (yyvsp[(2) - (6)].str), NULL, (yyvsp[(5) - (6)].token_list));
        ;}
@@ -1856,8 +1857,8 @@ yyreduce:
 
   case 12:
 
-/* Line 1455 of yacc.c  */
-#line 222 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 215 "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));
        ;}
@@ -1865,22 +1866,22 @@ yyreduce:
 
   case 13:
 
-/* Line 1455 of yacc.c  */
-#line 225 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 218 "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);
+                       ralloc_free (macro);
                }
-               talloc_free ((yyvsp[(2) - (3)].str));
+               ralloc_free ((yyvsp[(2) - (3)].str));
        ;}
     break;
 
   case 14:
 
-/* Line 1455 of yacc.c  */
-#line 233 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 226 "glcpp/glcpp-parse.y"
     {
                /* Be careful to only evaluate the 'if' expression if
                 * we are not skipping. When we are skipping, we
@@ -1904,8 +1905,8 @@ yyreduce:
 
   case 15:
 
-/* Line 1455 of yacc.c  */
-#line 252 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 245 "glcpp/glcpp-parse.y"
     {
                /* #if without an expression is only an error if we
                 *  are not skipping */
@@ -1920,30 +1921,30 @@ yyreduce:
 
   case 16:
 
-/* Line 1455 of yacc.c  */
-#line 262 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 255 "glcpp/glcpp-parse.y"
     {
                macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (4)].str));
-               talloc_free ((yyvsp[(2) - (4)].str));
+               ralloc_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 267 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 260 "glcpp/glcpp-parse.y"
     {
                macro_t *macro = hash_table_find (parser->defines, (yyvsp[(2) - (4)].str));
-               talloc_free ((yyvsp[(2) - (4)].str));
+               ralloc_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 272 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 265 "glcpp/glcpp-parse.y"
     {
                /* Be careful to only evaluate the 'elif' expression
                 * if we are not skipping. When we are skipping, we
@@ -1967,8 +1968,8 @@ yyreduce:
 
   case 19:
 
-/* Line 1455 of yacc.c  */
-#line 291 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 284 "glcpp/glcpp-parse.y"
     {
                /* #elif without an expression is an error unless we
                 * are skipping. */
@@ -1988,8 +1989,8 @@ yyreduce:
 
   case 20:
 
-/* Line 1455 of yacc.c  */
-#line 306 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 299 "glcpp/glcpp-parse.y"
     {
                _glcpp_parser_skip_stack_change_if (parser, & (yylsp[(1) - (2)]), "else", 1);
        ;}
@@ -1997,8 +1998,8 @@ yyreduce:
 
   case 21:
 
-/* Line 1455 of yacc.c  */
-#line 309 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 302 "glcpp/glcpp-parse.y"
     {
                _glcpp_parser_skip_stack_pop (parser, & (yylsp[(1) - (2)]));
        ;}
@@ -2006,13 +2007,13 @@ yyreduce:
 
   case 22:
 
-/* Line 1455 of yacc.c  */
-#line 312 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 305 "glcpp/glcpp-parse.y"
     {
                macro_t *macro = hash_table_find (parser->defines, "__VERSION__");
                if (macro) {
                        hash_table_remove (parser->defines, "__VERSION__");
-                       talloc_free (macro);
+                       ralloc_free (macro);
                }
                add_builtin_define (parser, "__VERSION__", (yyvsp[(2) - (3)].ival));
 
@@ -2027,14 +2028,14 @@ yyreduce:
                if ((yyvsp[(2) - (3)].ival) >= 130 || (yyvsp[(2) - (3)].ival) == 100)
                        add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1);
 
-               glcpp_printf(parser->output, "#version %" PRIiMAX, (yyvsp[(2) - (3)].ival));
+               ralloc_asprintf_append (&parser->output, "#version %" PRIiMAX, (yyvsp[(2) - (3)].ival));
        ;}
     break;
 
   case 24:
 
-/* Line 1455 of yacc.c  */
-#line 337 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 330 "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);
@@ -2048,8 +2049,8 @@ yyreduce:
 
   case 25:
 
-/* Line 1455 of yacc.c  */
-#line 346 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 339 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (1)].ival);
        ;}
@@ -2057,8 +2058,8 @@ yyreduce:
 
   case 27:
 
-/* Line 1455 of yacc.c  */
-#line 352 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 345 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) || (yyvsp[(3) - (3)].ival);
        ;}
@@ -2066,8 +2067,8 @@ yyreduce:
 
   case 28:
 
-/* Line 1455 of yacc.c  */
-#line 355 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 348 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) && (yyvsp[(3) - (3)].ival);
        ;}
@@ -2075,8 +2076,8 @@ yyreduce:
 
   case 29:
 
-/* Line 1455 of yacc.c  */
-#line 358 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 351 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) | (yyvsp[(3) - (3)].ival);
        ;}
@@ -2084,8 +2085,8 @@ yyreduce:
 
   case 30:
 
-/* Line 1455 of yacc.c  */
-#line 361 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 354 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) ^ (yyvsp[(3) - (3)].ival);
        ;}
@@ -2093,8 +2094,8 @@ yyreduce:
 
   case 31:
 
-/* Line 1455 of yacc.c  */
-#line 364 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 357 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) & (yyvsp[(3) - (3)].ival);
        ;}
@@ -2102,8 +2103,8 @@ yyreduce:
 
   case 32:
 
-/* Line 1455 of yacc.c  */
-#line 367 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 360 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) != (yyvsp[(3) - (3)].ival);
        ;}
@@ -2111,8 +2112,8 @@ yyreduce:
 
   case 33:
 
-/* Line 1455 of yacc.c  */
-#line 370 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 363 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) == (yyvsp[(3) - (3)].ival);
        ;}
@@ -2120,8 +2121,8 @@ yyreduce:
 
   case 34:
 
-/* Line 1455 of yacc.c  */
-#line 373 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 366 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) >= (yyvsp[(3) - (3)].ival);
        ;}
@@ -2129,8 +2130,8 @@ yyreduce:
 
   case 35:
 
-/* Line 1455 of yacc.c  */
-#line 376 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 369 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) <= (yyvsp[(3) - (3)].ival);
        ;}
@@ -2138,8 +2139,8 @@ yyreduce:
 
   case 36:
 
-/* Line 1455 of yacc.c  */
-#line 379 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 372 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) > (yyvsp[(3) - (3)].ival);
        ;}
@@ -2147,8 +2148,8 @@ yyreduce:
 
   case 37:
 
-/* Line 1455 of yacc.c  */
-#line 382 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 375 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) < (yyvsp[(3) - (3)].ival);
        ;}
@@ -2156,8 +2157,8 @@ yyreduce:
 
   case 38:
 
-/* Line 1455 of yacc.c  */
-#line 385 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 378 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) >> (yyvsp[(3) - (3)].ival);
        ;}
@@ -2165,8 +2166,8 @@ yyreduce:
 
   case 39:
 
-/* Line 1455 of yacc.c  */
-#line 388 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 381 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) << (yyvsp[(3) - (3)].ival);
        ;}
@@ -2174,8 +2175,8 @@ yyreduce:
 
   case 40:
 
-/* Line 1455 of yacc.c  */
-#line 391 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 384 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) - (yyvsp[(3) - (3)].ival);
        ;}
@@ -2183,8 +2184,8 @@ yyreduce:
 
   case 41:
 
-/* Line 1455 of yacc.c  */
-#line 394 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 387 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) + (yyvsp[(3) - (3)].ival);
        ;}
@@ -2192,17 +2193,22 @@ yyreduce:
 
   case 42:
 
-/* Line 1455 of yacc.c  */
-#line 397 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 390 "glcpp/glcpp-parse.y"
     {
-               (yyval.ival) = (yyvsp[(1) - (3)].ival) % (yyvsp[(3) - (3)].ival);
+               if ((yyvsp[(3) - (3)].ival) == 0) {
+                       yyerror (& (yylsp[(1) - (3)]), parser,
+                                "zero modulus in preprocessor directive");
+               } else {
+                       (yyval.ival) = (yyvsp[(1) - (3)].ival) % (yyvsp[(3) - (3)].ival);
+               }
        ;}
     break;
 
   case 43:
 
-/* Line 1455 of yacc.c  */
-#line 400 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 398 "glcpp/glcpp-parse.y"
     {
                if ((yyvsp[(3) - (3)].ival) == 0) {
                        yyerror (& (yylsp[(1) - (3)]), parser,
@@ -2215,8 +2221,8 @@ yyreduce:
 
   case 44:
 
-/* Line 1455 of yacc.c  */
-#line 408 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 406 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(1) - (3)].ival) * (yyvsp[(3) - (3)].ival);
        ;}
@@ -2224,8 +2230,8 @@ yyreduce:
 
   case 45:
 
-/* Line 1455 of yacc.c  */
-#line 411 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 409 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = ! (yyvsp[(2) - (2)].ival);
        ;}
@@ -2233,8 +2239,8 @@ yyreduce:
 
   case 46:
 
-/* Line 1455 of yacc.c  */
-#line 414 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 412 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = ~ (yyvsp[(2) - (2)].ival);
        ;}
@@ -2242,8 +2248,8 @@ yyreduce:
 
   case 47:
 
-/* Line 1455 of yacc.c  */
-#line 417 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 415 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = - (yyvsp[(2) - (2)].ival);
        ;}
@@ -2251,8 +2257,8 @@ yyreduce:
 
   case 48:
 
-/* Line 1455 of yacc.c  */
-#line 420 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 418 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = + (yyvsp[(2) - (2)].ival);
        ;}
@@ -2260,8 +2266,8 @@ yyreduce:
 
   case 49:
 
-/* Line 1455 of yacc.c  */
-#line 423 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 421 "glcpp/glcpp-parse.y"
     {
                (yyval.ival) = (yyvsp[(2) - (3)].ival);
        ;}
@@ -2269,37 +2275,37 @@ yyreduce:
 
   case 50:
 
-/* Line 1455 of yacc.c  */
-#line 429 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 427 "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));
+               ralloc_steal ((yyval.string_list), (yyvsp[(1) - (1)].str));
        ;}
     break;
 
   case 51:
 
-/* Line 1455 of yacc.c  */
-#line 434 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 432 "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));
+               ralloc_steal ((yyval.string_list), (yyvsp[(3) - (3)].str));
        ;}
     break;
 
   case 52:
 
-/* Line 1455 of yacc.c  */
-#line 442 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 440 "glcpp/glcpp-parse.y"
     { (yyval.token_list) = NULL; ;}
     break;
 
   case 54:
 
-/* Line 1455 of yacc.c  */
-#line 447 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 445 "glcpp/glcpp-parse.y"
     {
                yyerror (& (yylsp[(1) - (2)]), parser, "Invalid tokens after #");
        ;}
@@ -2307,15 +2313,15 @@ yyreduce:
 
   case 55:
 
-/* Line 1455 of yacc.c  */
-#line 453 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 451 "glcpp/glcpp-parse.y"
     { (yyval.token_list) = NULL; ;}
     break;
 
   case 58:
 
-/* Line 1455 of yacc.c  */
-#line 459 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 457 "glcpp/glcpp-parse.y"
     {
                glcpp_warning(&(yylsp[(1) - (1)]), parser, "extra tokens at end of directive");
        ;}
@@ -2323,8 +2329,8 @@ yyreduce:
 
   case 59:
 
-/* Line 1455 of yacc.c  */
-#line 466 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 464 "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);
@@ -2333,8 +2339,8 @@ yyreduce:
 
   case 60:
 
-/* Line 1455 of yacc.c  */
-#line 470 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 468 "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);
@@ -2343,53 +2349,49 @@ yyreduce:
 
   case 62:
 
-/* Line 1455 of yacc.c  */
-#line 479 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 477 "glcpp/glcpp-parse.y"
     {
                (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 484 "glcpp/glcpp-parse.y"
+/* Line 1464 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 64:
 
-/* Line 1455 of yacc.c  */
-#line 492 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 488 "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 498 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 493 "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 506 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 500 "glcpp/glcpp-parse.y"
     {
                (yyval.token) = _token_create_str (parser, IDENTIFIER, (yyvsp[(1) - (1)].str));
                (yyval.token)->location = yylloc;
@@ -2398,8 +2400,8 @@ yyreduce:
 
   case 67:
 
-/* Line 1455 of yacc.c  */
-#line 510 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 504 "glcpp/glcpp-parse.y"
     {
                (yyval.token) = _token_create_str (parser, INTEGER_STRING, (yyvsp[(1) - (1)].str));
                (yyval.token)->location = yylloc;
@@ -2408,8 +2410,8 @@ yyreduce:
 
   case 68:
 
-/* Line 1455 of yacc.c  */
-#line 514 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 508 "glcpp/glcpp-parse.y"
     {
                (yyval.token) = _token_create_ival (parser, (yyvsp[(1) - (1)].ival), (yyvsp[(1) - (1)].ival));
                (yyval.token)->location = yylloc;
@@ -2418,8 +2420,8 @@ yyreduce:
 
   case 69:
 
-/* Line 1455 of yacc.c  */
-#line 518 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 512 "glcpp/glcpp-parse.y"
     {
                (yyval.token) = _token_create_str (parser, OTHER, (yyvsp[(1) - (1)].str));
                (yyval.token)->location = yylloc;
@@ -2428,8 +2430,8 @@ yyreduce:
 
   case 70:
 
-/* Line 1455 of yacc.c  */
-#line 522 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 516 "glcpp/glcpp-parse.y"
     {
                (yyval.token) = _token_create_ival (parser, SPACE, SPACE);
                (yyval.token)->location = yylloc;
@@ -2438,225 +2440,225 @@ yyreduce:
 
   case 71:
 
-/* Line 1455 of yacc.c  */
-#line 529 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 523 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '['; ;}
     break;
 
   case 72:
 
-/* Line 1455 of yacc.c  */
-#line 530 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 524 "glcpp/glcpp-parse.y"
     { (yyval.ival) = ']'; ;}
     break;
 
   case 73:
 
-/* Line 1455 of yacc.c  */
-#line 531 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 525 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '('; ;}
     break;
 
   case 74:
 
-/* Line 1455 of yacc.c  */
-#line 532 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 526 "glcpp/glcpp-parse.y"
     { (yyval.ival) = ')'; ;}
     break;
 
   case 75:
 
-/* Line 1455 of yacc.c  */
-#line 533 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 527 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '{'; ;}
     break;
 
   case 76:
 
-/* Line 1455 of yacc.c  */
-#line 534 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 528 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '}'; ;}
     break;
 
   case 77:
 
-/* Line 1455 of yacc.c  */
-#line 535 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 529 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '.'; ;}
     break;
 
   case 78:
 
-/* Line 1455 of yacc.c  */
-#line 536 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 530 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '&'; ;}
     break;
 
   case 79:
 
-/* Line 1455 of yacc.c  */
-#line 537 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 531 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '*'; ;}
     break;
 
   case 80:
 
-/* Line 1455 of yacc.c  */
-#line 538 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 532 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '+'; ;}
     break;
 
   case 81:
 
-/* Line 1455 of yacc.c  */
-#line 539 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 533 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '-'; ;}
     break;
 
   case 82:
 
-/* Line 1455 of yacc.c  */
-#line 540 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 534 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '~'; ;}
     break;
 
   case 83:
 
-/* Line 1455 of yacc.c  */
-#line 541 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 535 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '!'; ;}
     break;
 
   case 84:
 
-/* Line 1455 of yacc.c  */
-#line 542 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 536 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '/'; ;}
     break;
 
   case 85:
 
-/* Line 1455 of yacc.c  */
-#line 543 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 537 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '%'; ;}
     break;
 
   case 86:
 
-/* Line 1455 of yacc.c  */
-#line 544 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 538 "glcpp/glcpp-parse.y"
     { (yyval.ival) = LEFT_SHIFT; ;}
     break;
 
   case 87:
 
-/* Line 1455 of yacc.c  */
-#line 545 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 539 "glcpp/glcpp-parse.y"
     { (yyval.ival) = RIGHT_SHIFT; ;}
     break;
 
   case 88:
 
-/* Line 1455 of yacc.c  */
-#line 546 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 540 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '<'; ;}
     break;
 
   case 89:
 
-/* Line 1455 of yacc.c  */
-#line 547 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 541 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '>'; ;}
     break;
 
   case 90:
 
-/* Line 1455 of yacc.c  */
-#line 548 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 542 "glcpp/glcpp-parse.y"
     { (yyval.ival) = LESS_OR_EQUAL; ;}
     break;
 
   case 91:
 
-/* Line 1455 of yacc.c  */
-#line 549 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 543 "glcpp/glcpp-parse.y"
     { (yyval.ival) = GREATER_OR_EQUAL; ;}
     break;
 
   case 92:
 
-/* Line 1455 of yacc.c  */
-#line 550 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 544 "glcpp/glcpp-parse.y"
     { (yyval.ival) = EQUAL; ;}
     break;
 
   case 93:
 
-/* Line 1455 of yacc.c  */
-#line 551 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 545 "glcpp/glcpp-parse.y"
     { (yyval.ival) = NOT_EQUAL; ;}
     break;
 
   case 94:
 
-/* Line 1455 of yacc.c  */
-#line 552 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 546 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '^'; ;}
     break;
 
   case 95:
 
-/* Line 1455 of yacc.c  */
-#line 553 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 547 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '|'; ;}
     break;
 
   case 96:
 
-/* Line 1455 of yacc.c  */
-#line 554 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 548 "glcpp/glcpp-parse.y"
     { (yyval.ival) = AND; ;}
     break;
 
   case 97:
 
-/* Line 1455 of yacc.c  */
-#line 555 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 549 "glcpp/glcpp-parse.y"
     { (yyval.ival) = OR; ;}
     break;
 
   case 98:
 
-/* Line 1455 of yacc.c  */
-#line 556 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 550 "glcpp/glcpp-parse.y"
     { (yyval.ival) = ';'; ;}
     break;
 
   case 99:
 
-/* Line 1455 of yacc.c  */
-#line 557 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 551 "glcpp/glcpp-parse.y"
     { (yyval.ival) = ','; ;}
     break;
 
   case 100:
 
-/* Line 1455 of yacc.c  */
-#line 558 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 552 "glcpp/glcpp-parse.y"
     { (yyval.ival) = '='; ;}
     break;
 
   case 101:
 
-/* Line 1455 of yacc.c  */
-#line 559 "glcpp/glcpp-parse.y"
+/* Line 1464 of yacc.c  */
+#line 553 "glcpp/glcpp-parse.y"
     { (yyval.ival) = PASTE; ;}
     break;
 
 
 
-/* Line 1455 of yacc.c  */
-#line 2660 "glcpp/glcpp-parse.c"
+/* Line 1464 of yacc.c  */
+#line 2662 "glcpp/glcpp-parse.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2728,7 +2730,7 @@ yyerrlab:
 #endif
     }
 
-  yyerror_range[0] = yylloc;
+  yyerror_range[1] = yylloc;
 
   if (yyerrstatus == 3)
     {
@@ -2765,7 +2767,7 @@ yyerrorlab:
   if (/*CONSTCOND*/ 0)
      goto yyerrorlab;
 
-  yyerror_range[0] = yylsp[1-yylen];
+  yyerror_range[1] = yylsp[1-yylen];
   /* Do not reclaim the symbols of the rule which action triggered
      this YYERROR.  */
   YYPOPSTACK (yylen);
@@ -2799,7 +2801,7 @@ yyerrlab1:
       if (yyssp == yyss)
        YYABORT;
 
-      yyerror_range[0] = *yylsp;
+      yyerror_range[1] = *yylsp;
       yydestruct ("Error: popping",
                  yystos[yystate], yyvsp, yylsp, parser);
       YYPOPSTACK (1);
@@ -2809,10 +2811,10 @@ yyerrlab1:
 
   *++yyvsp = yylval;
 
-  yyerror_range[1] = yylloc;
+  yyerror_range[2] = yylloc;
   /* Using YYLLOC is tempting, but would change the location of
      the lookahead.  YYLOC is available though.  */
-  YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
+  YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
   *++yylsp = yyloc;
 
   /* Shift the error token.  */
@@ -2874,8 +2876,8 @@ yyreturn:
 
 
 
-/* Line 1675 of yacc.c  */
-#line 562 "glcpp/glcpp-parse.y"
+/* Line 1684 of yacc.c  */
+#line 556 "glcpp/glcpp-parse.y"
 
 
 string_list_t *
@@ -2883,7 +2885,7 @@ _string_list_create (void *ctx)
 {
        string_list_t *list;
 
-       list = talloc (ctx, string_list_t);
+       list = ralloc (ctx, string_list_t);
        list->head = NULL;
        list->tail = NULL;
 
@@ -2895,8 +2897,8 @@ _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 = ralloc (list, string_node_t);
+       node->str = ralloc_strdup (node, str);
 
        node->next = NULL;
 
@@ -2974,7 +2976,7 @@ _argument_list_create (void *ctx)
 {
        argument_list_t *list;
 
-       list = talloc (ctx, argument_list_t);
+       list = ralloc (ctx, argument_list_t);
        list->head = NULL;
        list->tail = NULL;
 
@@ -2986,7 +2988,7 @@ _argument_list_append (argument_list_t *list, token_list_t *argument)
 {
        argument_node_t *node;
 
-       node = talloc (list, argument_node_t);
+       node = ralloc (list, argument_node_t);
        node->argument = argument;
 
        node->next = NULL;
@@ -3037,15 +3039,17 @@ _argument_list_member_at (argument_list_t *list, int index)
        return NULL;
 }
 
-/* Note: This function talloc_steal()s the str pointer. */
+/* Note: This function ralloc_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 = ralloc (ctx, token_t);
        token->type = type;
-       token->value.str = talloc_steal (token, str);
+       token->value.str = str;
+
+       ralloc_steal (token, str);
 
        return token;
 }
@@ -3055,7 +3059,7 @@ _token_create_ival (void *ctx, int type, int ival)
 {
        token_t *token;
 
-       token = talloc (ctx, token_t);
+       token = ralloc (ctx, token_t);
        token->type = type;
        token->value.ival = ival;
 
@@ -3067,7 +3071,7 @@ _token_list_create (void *ctx)
 {
        token_list_t *list;
 
-       list = talloc (ctx, token_list_t);
+       list = ralloc (ctx, token_list_t);
        list->head = NULL;
        list->tail = NULL;
        list->non_space_tail = NULL;
@@ -3080,11 +3084,12 @@ _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 = ralloc (list, token_node_t);
+       node->token = token;
        node->next = NULL;
 
+       ralloc_steal (list, token);
+
        if (list->head == NULL) {
                list->head = node;
        } else {
@@ -3122,8 +3127,11 @@ _token_list_copy (void *ctx, token_list_t *other)
                return NULL;
 
        copy = _token_list_create (ctx);
-       for (node = other->head; node; node = node->next)
-               _token_list_append (copy, node->token);
+       for (node = other->head; node; node = node->next) {
+               token_t *new_token = ralloc (copy, token_t);
+               *new_token = *node->token;
+               _token_list_append (copy, new_token);
+       }
 
        return copy;
 }
@@ -3140,13 +3148,13 @@ _token_list_trim_trailing_space (token_list_t *list)
 
                while (tail) {
                        next = tail->next;
-                       talloc_free (tail);
+                       ralloc_free (tail);
                        tail = next;
                }
        }
 }
 
-int
+static int
 _token_list_is_empty_ignoring_space (token_list_t *l)
 {
        token_node_t *n;
@@ -3226,51 +3234,51 @@ static void
 _token_print (char **out, token_t *token)
 {
        if (token->type < 256) {
-               glcpp_printf (*out, "%c", token->type);
+               ralloc_asprintf_append (out, "%c", token->type);
                return;
        }
 
        switch (token->type) {
        case INTEGER:
-               glcpp_printf (*out, "%" PRIiMAX, token->value.ival);
+               ralloc_asprintf_append (out, "%" PRIiMAX, token->value.ival);
                break;
        case IDENTIFIER:
        case INTEGER_STRING:
        case OTHER:
-               glcpp_print (*out, token->value.str);
+               ralloc_strcat (out, token->value.str);
                break;
        case SPACE:
-               glcpp_print (*out, " ");
+               ralloc_strcat (out, " ");
                break;
        case LEFT_SHIFT:
-               glcpp_print (*out, "<<");
+               ralloc_strcat (out, "<<");
                break;
        case RIGHT_SHIFT:
-               glcpp_print (*out, ">>");
+               ralloc_strcat (out, ">>");
                break;
        case LESS_OR_EQUAL:
-               glcpp_print (*out, "<=");
+               ralloc_strcat (out, "<=");
                break;
        case GREATER_OR_EQUAL:
-               glcpp_print (*out, ">=");
+               ralloc_strcat (out, ">=");
                break;
        case EQUAL:
-               glcpp_print (*out, "==");
+               ralloc_strcat (out, "==");
                break;
        case NOT_EQUAL:
-               glcpp_print (*out, "!=");
+               ralloc_strcat (out, "!=");
                break;
        case AND:
-               glcpp_print (*out, "&&");
+               ralloc_strcat (out, "&&");
                break;
        case OR:
-               glcpp_print (*out, "||");
+               ralloc_strcat (out, "||");
                break;
        case PASTE:
-               glcpp_print (*out, "##");
+               ralloc_strcat (out, "##");
                break;
        case COMMA_FINAL:
-               glcpp_print (*out, ",");
+               ralloc_strcat (out, ",");
                break;
        case PLACEHOLDER:
                /* Nothing to print. */
@@ -3281,7 +3289,7 @@ _token_print (char **out, token_t *token)
        }
 }
 
-/* Return a new token (talloc()ed off of 'token') formed by pasting
+/* Return a new token (ralloc()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.
  *
@@ -3352,7 +3360,7 @@ _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
        {
                char *str;
 
-               str = talloc_asprintf (token, "%s%s", token->value.str,
+               str = ralloc_asprintf (token, "%s%s", token->value.str,
                                       other->value.str);
                combined = _token_create_str (token, token->type, str);
                combined->location = token->location;
@@ -3360,11 +3368,11 @@ _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
        }
 
        glcpp_error (&token->location, parser, "");
-       glcpp_print (parser->info_log, "Pasting \"");
+       ralloc_strcat (&parser->info_log, "Pasting \"");
        _token_print (&parser->info_log, token);
-       glcpp_print (parser->info_log, "\" and \"");
+       ralloc_strcat (&parser->info_log, "\" and \"");
        _token_print (&parser->info_log, other);
-       glcpp_print (parser->info_log, "\" does not give a valid preprocessing token.\n");
+       ralloc_strcat (&parser->info_log, "\" does not give a valid preprocessing token.\n");
 
        return token;
 }
@@ -3398,8 +3406,6 @@ static void add_builtin_define(glcpp_parser_t *parser,
    list = _token_list_create(parser);
    _token_list_append(list, tok);
    _define_object_macro(parser, NULL, name, list);
-
-   talloc_unlink(parser, tok);
 }
 
 glcpp_parser_t *
@@ -3408,7 +3414,7 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api)
        glcpp_parser_t *parser;
        int language_version;
 
-       parser = talloc (NULL, glcpp_parser_t);
+       parser = ralloc (NULL, glcpp_parser_t);
 
        glcpp_lex_init_extra (parser, &parser->scanner);
        parser->defines = hash_table_ctor (32, hash_table_string_hash,
@@ -3425,8 +3431,8 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api)
        parser->lex_from_list = NULL;
        parser->lex_from_node = NULL;
 
-       parser->output = talloc_strdup(parser, "");
-       parser->info_log = talloc_strdup(parser, "");
+       parser->output = ralloc_strdup(parser, "");
+       parser->info_log = ralloc_strdup(parser, "");
        parser->error = 0;
 
        /* Add pre-defined macros. */
@@ -3447,6 +3453,8 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api)
 
           if (extensions->ARB_explicit_attrib_location)
              add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1);
+          if (extensions->AMD_conservative_depth)
+             add_builtin_define(parser, "GL_AMD_conservative_depth", 1);
        }
 
        language_version = 110;
@@ -3466,7 +3474,7 @@ glcpp_parser_destroy (glcpp_parser_t *parser)
 {
        glcpp_lex_destroy (parser->scanner);
        hash_table_dtor (parser->defines);
-       talloc_free (parser);
+       ralloc_free (parser);
 }
 
 typedef enum function_status
@@ -3637,7 +3645,7 @@ _glcpp_parser_expand_function (glcpp_parser_t *parser,
 
        /* Replace a macro defined as empty with a SPACE token. */
        if (macro->replacements == NULL) {
-               talloc_free (arguments);
+               ralloc_free (arguments);
                return _token_list_create_with_one_space (parser);
        }
 
@@ -3793,7 +3801,7 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser,
                token_list_t *expansion;
                token_t *final;
 
-               str = talloc_strdup (parser, token->value.str);
+               str = ralloc_strdup (parser, token->value.str);
                final = _token_create_str (parser, OTHER, str);
                expansion = _token_list_create (parser);
                _token_list_append (expansion, final);
@@ -3829,8 +3837,8 @@ _active_list_push (active_list_t *list,
 {
        active_list_t *node;
 
-       node = talloc (list, active_list_t);
-       node->identifier = talloc_strdup (node, identifier);
+       node = ralloc (list, active_list_t);
+       node->identifier = ralloc_strdup (node, identifier);
        node->marker = marker;
        node->next = list;
 
@@ -3846,7 +3854,7 @@ _active_list_pop (active_list_t *list)
                return NULL;
 
        node = list->next;
-       talloc_free (list);
+       ralloc_free (list);
 
        return node;
 }
@@ -3995,17 +4003,18 @@ _define_object_macro (glcpp_parser_t *parser,
        if (loc != NULL)
                _check_for_reserved_macro_name(parser, loc, identifier);
 
-       macro = talloc (parser, macro_t);
+       macro = ralloc (parser, macro_t);
 
        macro->is_function = 0;
        macro->parameters = NULL;
-       macro->identifier = talloc_strdup (macro, identifier);
-       macro->replacements = talloc_steal (macro, replacements);
+       macro->identifier = ralloc_strdup (macro, identifier);
+       macro->replacements = replacements;
+       ralloc_steal (macro, replacements);
 
        previous = hash_table_find (parser->defines, identifier);
        if (previous) {
                if (_macro_equal (macro, previous)) {
-                       talloc_free (macro);
+                       ralloc_free (macro);
                        return;
                }
                glcpp_error (loc, parser, "Redefinition of macro %s\n",
@@ -4026,17 +4035,18 @@ _define_function_macro (glcpp_parser_t *parser,
 
        _check_for_reserved_macro_name(parser, loc, identifier);
 
-       macro = talloc (parser, macro_t);
+       macro = ralloc (parser, macro_t);
+       ralloc_steal (macro, parameters);
+       ralloc_steal (macro, replacements);
 
        macro->is_function = 1;
-       macro->parameters = talloc_steal (macro, parameters);
-       macro->identifier = talloc_strdup (macro, identifier);
-       macro->replacements = talloc_steal (macro, replacements);
-
+       macro->parameters = parameters;
+       macro->identifier = ralloc_strdup (macro, identifier);
+       macro->replacements = replacements;
        previous = hash_table_find (parser->defines, identifier);
        if (previous) {
                if (_macro_equal (macro, previous)) {
-                       talloc_free (macro);
+                       ralloc_free (macro);
                        return;
                }
                glcpp_error (loc, parser, "Redefinition of macro %s\n",
@@ -4112,7 +4122,7 @@ glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
        node = parser->lex_from_node;
 
        if (node == NULL) {
-               talloc_free (parser->lex_from_list);
+               ralloc_free (parser->lex_from_list);
                parser->lex_from_list = NULL;
                return NEWLINE;
        }
@@ -4141,13 +4151,13 @@ glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list)
                _token_list_append (parser->lex_from_list, node->token);
        }
 
-       talloc_free (list);
+       ralloc_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);
+               ralloc_free (parser->lex_from_list);
                parser->lex_from_list = NULL;
        }
 }
@@ -4162,7 +4172,7 @@ _glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
        if (parser->skip_stack)
                current = parser->skip_stack->type;
 
-       node = talloc (parser, skip_node_t);
+       node = ralloc (parser, skip_node_t);
        node->loc = *loc;
 
        if (current == SKIP_NO_SKIP) {
@@ -4207,6 +4217,6 @@ _glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc)
 
        node = parser->skip_stack;
        parser->skip_stack = node->next;
-       talloc_free (node);
+       ralloc_free (node);
 }
 
index e71c0e8b38217bba1379dd04d97b358516cbfe8d..1f6e67fa062239bb828487efb31135b0e55a5a38 100644 (file)
 #include "main/core.h" /* for struct gl_extensions */
 #include "main/mtypes.h" /* for gl_api enum */
 
-#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);
 
@@ -79,7 +75,7 @@ _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. */
+/* Note: This function ralloc_steal()s the str pointer. */
 static token_t *
 _token_create_str (void *ctx, int type, char *str);
 
@@ -89,10 +85,7 @@ _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. */
+/* Note: This function calls ralloc_steal on token. */
 static void
 _token_list_append (token_list_t *list, token_t *token);
 
@@ -192,12 +185,12 @@ input:
 
 line:
        control_line {
-               glcpp_print(parser->output, "\n");
+               ralloc_strcat (&parser->output, "\n");
        }
 |      text_line {
                _glcpp_parser_print_expanded_token_list (parser, $1);
-               glcpp_print(parser->output, "\n");
-               talloc_free ($1);
+               ralloc_strcat (&parser->output, "\n");
+               ralloc_free ($1);
        }
 |      expanded_line
 |      HASH non_directive
@@ -226,9 +219,9 @@ control_line:
                macro_t *macro = hash_table_find (parser->defines, $2);
                if (macro) {
                        hash_table_remove (parser->defines, $2);
-                       talloc_free (macro);
+                       ralloc_free (macro);
                }
-               talloc_free ($2);
+               ralloc_free ($2);
        }
 |      HASH_IF conditional_tokens NEWLINE {
                /* Be careful to only evaluate the 'if' expression if
@@ -261,12 +254,12 @@ control_line:
        }
 |      HASH_IFDEF IDENTIFIER junk NEWLINE {
                macro_t *macro = hash_table_find (parser->defines, $2);
-               talloc_free ($2);
+               ralloc_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);
+               ralloc_free ($2);
                _glcpp_parser_skip_stack_push_if (parser, & @1, macro == NULL);
        }
 |      HASH_ELIF conditional_tokens NEWLINE {
@@ -313,7 +306,7 @@ control_line:
                macro_t *macro = hash_table_find (parser->defines, "__VERSION__");
                if (macro) {
                        hash_table_remove (parser->defines, "__VERSION__");
-                       talloc_free (macro);
+                       ralloc_free (macro);
                }
                add_builtin_define (parser, "__VERSION__", $2);
 
@@ -328,7 +321,7 @@ control_line:
                if ($2 >= 130 || $2 == 100)
                        add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1);
 
-               glcpp_printf(parser->output, "#version %" PRIiMAX, $2);
+               ralloc_asprintf_append (&parser->output, "#version %" PRIiMAX, $2);
        }
 |      HASH NEWLINE
 ;
@@ -395,7 +388,12 @@ expression:
                $$ = $1 + $3;
        }
 |      expression '%' expression {
-               $$ = $1 % $3;
+               if ($3 == 0) {
+                       yyerror (& @1, parser,
+                                "zero modulus in preprocessor directive");
+               } else {
+                       $$ = $1 % $3;
+               }
        }
 |      expression '/' expression {
                if ($3 == 0) {
@@ -429,12 +427,12 @@ identifier_list:
        IDENTIFIER {
                $$ = _string_list_create (parser);
                _string_list_append_item ($$, $1);
-               talloc_steal ($$, $1);
+               ralloc_steal ($$, $1);
        }
 |      identifier_list ',' IDENTIFIER {
                $$ = $1;        
                _string_list_append_item ($$, $3);
-               talloc_steal ($$, $3);
+               ralloc_steal ($$, $3);
        }
 ;
 
@@ -479,12 +477,10 @@ conditional_tokens:
        conditional_token {
                $$ = _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);
        }
 ;
 
@@ -493,12 +489,10 @@ pp_tokens:
                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);
        }
 ;
 
@@ -566,7 +560,7 @@ _string_list_create (void *ctx)
 {
        string_list_t *list;
 
-       list = talloc (ctx, string_list_t);
+       list = ralloc (ctx, string_list_t);
        list->head = NULL;
        list->tail = NULL;
 
@@ -578,8 +572,8 @@ _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 = ralloc (list, string_node_t);
+       node->str = ralloc_strdup (node, str);
 
        node->next = NULL;
 
@@ -657,7 +651,7 @@ _argument_list_create (void *ctx)
 {
        argument_list_t *list;
 
-       list = talloc (ctx, argument_list_t);
+       list = ralloc (ctx, argument_list_t);
        list->head = NULL;
        list->tail = NULL;
 
@@ -669,7 +663,7 @@ _argument_list_append (argument_list_t *list, token_list_t *argument)
 {
        argument_node_t *node;
 
-       node = talloc (list, argument_node_t);
+       node = ralloc (list, argument_node_t);
        node->argument = argument;
 
        node->next = NULL;
@@ -720,15 +714,17 @@ _argument_list_member_at (argument_list_t *list, int index)
        return NULL;
 }
 
-/* Note: This function talloc_steal()s the str pointer. */
+/* Note: This function ralloc_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 = ralloc (ctx, token_t);
        token->type = type;
-       token->value.str = talloc_steal (token, str);
+       token->value.str = str;
+
+       ralloc_steal (token, str);
 
        return token;
 }
@@ -738,7 +734,7 @@ _token_create_ival (void *ctx, int type, int ival)
 {
        token_t *token;
 
-       token = talloc (ctx, token_t);
+       token = ralloc (ctx, token_t);
        token->type = type;
        token->value.ival = ival;
 
@@ -750,7 +746,7 @@ _token_list_create (void *ctx)
 {
        token_list_t *list;
 
-       list = talloc (ctx, token_list_t);
+       list = ralloc (ctx, token_list_t);
        list->head = NULL;
        list->tail = NULL;
        list->non_space_tail = NULL;
@@ -763,11 +759,12 @@ _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 = ralloc (list, token_node_t);
+       node->token = token;
        node->next = NULL;
 
+       ralloc_steal (list, token);
+
        if (list->head == NULL) {
                list->head = node;
        } else {
@@ -805,8 +802,11 @@ _token_list_copy (void *ctx, token_list_t *other)
                return NULL;
 
        copy = _token_list_create (ctx);
-       for (node = other->head; node; node = node->next)
-               _token_list_append (copy, node->token);
+       for (node = other->head; node; node = node->next) {
+               token_t *new_token = ralloc (copy, token_t);
+               *new_token = *node->token;
+               _token_list_append (copy, new_token);
+       }
 
        return copy;
 }
@@ -823,13 +823,13 @@ _token_list_trim_trailing_space (token_list_t *list)
 
                while (tail) {
                        next = tail->next;
-                       talloc_free (tail);
+                       ralloc_free (tail);
                        tail = next;
                }
        }
 }
 
-int
+static int
 _token_list_is_empty_ignoring_space (token_list_t *l)
 {
        token_node_t *n;
@@ -909,51 +909,51 @@ static void
 _token_print (char **out, token_t *token)
 {
        if (token->type < 256) {
-               glcpp_printf (*out, "%c", token->type);
+               ralloc_asprintf_append (out, "%c", token->type);
                return;
        }
 
        switch (token->type) {
        case INTEGER:
-               glcpp_printf (*out, "%" PRIiMAX, token->value.ival);
+               ralloc_asprintf_append (out, "%" PRIiMAX, token->value.ival);
                break;
        case IDENTIFIER:
        case INTEGER_STRING:
        case OTHER:
-               glcpp_print (*out, token->value.str);
+               ralloc_strcat (out, token->value.str);
                break;
        case SPACE:
-               glcpp_print (*out, " ");
+               ralloc_strcat (out, " ");
                break;
        case LEFT_SHIFT:
-               glcpp_print (*out, "<<");
+               ralloc_strcat (out, "<<");
                break;
        case RIGHT_SHIFT:
-               glcpp_print (*out, ">>");
+               ralloc_strcat (out, ">>");
                break;
        case LESS_OR_EQUAL:
-               glcpp_print (*out, "<=");
+               ralloc_strcat (out, "<=");
                break;
        case GREATER_OR_EQUAL:
-               glcpp_print (*out, ">=");
+               ralloc_strcat (out, ">=");
                break;
        case EQUAL:
-               glcpp_print (*out, "==");
+               ralloc_strcat (out, "==");
                break;
        case NOT_EQUAL:
-               glcpp_print (*out, "!=");
+               ralloc_strcat (out, "!=");
                break;
        case AND:
-               glcpp_print (*out, "&&");
+               ralloc_strcat (out, "&&");
                break;
        case OR:
-               glcpp_print (*out, "||");
+               ralloc_strcat (out, "||");
                break;
        case PASTE:
-               glcpp_print (*out, "##");
+               ralloc_strcat (out, "##");
                break;
        case COMMA_FINAL:
-               glcpp_print (*out, ",");
+               ralloc_strcat (out, ",");
                break;
        case PLACEHOLDER:
                /* Nothing to print. */
@@ -964,7 +964,7 @@ _token_print (char **out, token_t *token)
        }
 }
 
-/* Return a new token (talloc()ed off of 'token') formed by pasting
+/* Return a new token (ralloc()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.
  *
@@ -1035,7 +1035,7 @@ _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
        {
                char *str;
 
-               str = talloc_asprintf (token, "%s%s", token->value.str,
+               str = ralloc_asprintf (token, "%s%s", token->value.str,
                                       other->value.str);
                combined = _token_create_str (token, token->type, str);
                combined->location = token->location;
@@ -1043,11 +1043,11 @@ _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
        }
 
        glcpp_error (&token->location, parser, "");
-       glcpp_print (parser->info_log, "Pasting \"");
+       ralloc_strcat (&parser->info_log, "Pasting \"");
        _token_print (&parser->info_log, token);
-       glcpp_print (parser->info_log, "\" and \"");
+       ralloc_strcat (&parser->info_log, "\" and \"");
        _token_print (&parser->info_log, other);
-       glcpp_print (parser->info_log, "\" does not give a valid preprocessing token.\n");
+       ralloc_strcat (&parser->info_log, "\" does not give a valid preprocessing token.\n");
 
        return token;
 }
@@ -1081,8 +1081,6 @@ static void add_builtin_define(glcpp_parser_t *parser,
    list = _token_list_create(parser);
    _token_list_append(list, tok);
    _define_object_macro(parser, NULL, name, list);
-
-   talloc_unlink(parser, tok);
 }
 
 glcpp_parser_t *
@@ -1091,7 +1089,7 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api)
        glcpp_parser_t *parser;
        int language_version;
 
-       parser = talloc (NULL, glcpp_parser_t);
+       parser = ralloc (NULL, glcpp_parser_t);
 
        glcpp_lex_init_extra (parser, &parser->scanner);
        parser->defines = hash_table_ctor (32, hash_table_string_hash,
@@ -1108,8 +1106,8 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api)
        parser->lex_from_list = NULL;
        parser->lex_from_node = NULL;
 
-       parser->output = talloc_strdup(parser, "");
-       parser->info_log = talloc_strdup(parser, "");
+       parser->output = ralloc_strdup(parser, "");
+       parser->info_log = ralloc_strdup(parser, "");
        parser->error = 0;
 
        /* Add pre-defined macros. */
@@ -1130,6 +1128,8 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api)
 
           if (extensions->ARB_explicit_attrib_location)
              add_builtin_define(parser, "GL_ARB_explicit_attrib_location", 1);
+          if (extensions->AMD_conservative_depth)
+             add_builtin_define(parser, "GL_AMD_conservative_depth", 1);
        }
 
        language_version = 110;
@@ -1149,7 +1149,7 @@ glcpp_parser_destroy (glcpp_parser_t *parser)
 {
        glcpp_lex_destroy (parser->scanner);
        hash_table_dtor (parser->defines);
-       talloc_free (parser);
+       ralloc_free (parser);
 }
 
 typedef enum function_status
@@ -1320,7 +1320,7 @@ _glcpp_parser_expand_function (glcpp_parser_t *parser,
 
        /* Replace a macro defined as empty with a SPACE token. */
        if (macro->replacements == NULL) {
-               talloc_free (arguments);
+               ralloc_free (arguments);
                return _token_list_create_with_one_space (parser);
        }
 
@@ -1476,7 +1476,7 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser,
                token_list_t *expansion;
                token_t *final;
 
-               str = talloc_strdup (parser, token->value.str);
+               str = ralloc_strdup (parser, token->value.str);
                final = _token_create_str (parser, OTHER, str);
                expansion = _token_list_create (parser);
                _token_list_append (expansion, final);
@@ -1512,8 +1512,8 @@ _active_list_push (active_list_t *list,
 {
        active_list_t *node;
 
-       node = talloc (list, active_list_t);
-       node->identifier = talloc_strdup (node, identifier);
+       node = ralloc (list, active_list_t);
+       node->identifier = ralloc_strdup (node, identifier);
        node->marker = marker;
        node->next = list;
 
@@ -1529,7 +1529,7 @@ _active_list_pop (active_list_t *list)
                return NULL;
 
        node = list->next;
-       talloc_free (list);
+       ralloc_free (list);
 
        return node;
 }
@@ -1678,17 +1678,18 @@ _define_object_macro (glcpp_parser_t *parser,
        if (loc != NULL)
                _check_for_reserved_macro_name(parser, loc, identifier);
 
-       macro = talloc (parser, macro_t);
+       macro = ralloc (parser, macro_t);
 
        macro->is_function = 0;
        macro->parameters = NULL;
-       macro->identifier = talloc_strdup (macro, identifier);
-       macro->replacements = talloc_steal (macro, replacements);
+       macro->identifier = ralloc_strdup (macro, identifier);
+       macro->replacements = replacements;
+       ralloc_steal (macro, replacements);
 
        previous = hash_table_find (parser->defines, identifier);
        if (previous) {
                if (_macro_equal (macro, previous)) {
-                       talloc_free (macro);
+                       ralloc_free (macro);
                        return;
                }
                glcpp_error (loc, parser, "Redefinition of macro %s\n",
@@ -1709,17 +1710,18 @@ _define_function_macro (glcpp_parser_t *parser,
 
        _check_for_reserved_macro_name(parser, loc, identifier);
 
-       macro = talloc (parser, macro_t);
+       macro = ralloc (parser, macro_t);
+       ralloc_steal (macro, parameters);
+       ralloc_steal (macro, replacements);
 
        macro->is_function = 1;
-       macro->parameters = talloc_steal (macro, parameters);
-       macro->identifier = talloc_strdup (macro, identifier);
-       macro->replacements = talloc_steal (macro, replacements);
-
+       macro->parameters = parameters;
+       macro->identifier = ralloc_strdup (macro, identifier);
+       macro->replacements = replacements;
        previous = hash_table_find (parser->defines, identifier);
        if (previous) {
                if (_macro_equal (macro, previous)) {
-                       talloc_free (macro);
+                       ralloc_free (macro);
                        return;
                }
                glcpp_error (loc, parser, "Redefinition of macro %s\n",
@@ -1795,7 +1797,7 @@ glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
        node = parser->lex_from_node;
 
        if (node == NULL) {
-               talloc_free (parser->lex_from_list);
+               ralloc_free (parser->lex_from_list);
                parser->lex_from_list = NULL;
                return NEWLINE;
        }
@@ -1824,13 +1826,13 @@ glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list)
                _token_list_append (parser->lex_from_list, node->token);
        }
 
-       talloc_free (list);
+       ralloc_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);
+               ralloc_free (parser->lex_from_list);
                parser->lex_from_list = NULL;
        }
 }
@@ -1845,7 +1847,7 @@ _glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, YYLTYPE *loc,
        if (parser->skip_stack)
                current = parser->skip_stack->type;
 
-       node = talloc (parser, skip_node_t);
+       node = ralloc (parser, skip_node_t);
        node->loc = *loc;
 
        if (current == SKIP_NO_SKIP) {
@@ -1890,5 +1892,5 @@ _glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc)
 
        node = parser->skip_stack;
        parser->skip_stack = node->next;
-       talloc_free (node);
+       ralloc_free (node);
 }
index 062eb6b72d4a18100a5f0166e7234ab98c112810..564194caac2a4ebcbd6eedc1725cfc036e8a8aaa 100644 (file)
@@ -54,7 +54,7 @@ load_text_fd (void *ctx, int fd)
        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);
+                       text = reralloc_size (ctx, text, text_size);
                        if (text == NULL) {
                                fprintf (stderr, "Out of memory\n");
                                return NULL;
@@ -64,7 +64,7 @@ load_text_fd (void *ctx, int fd)
                if (bytes < 0) {
                        fprintf (stderr, "Error while reading: %s\n",
                                 strerror (errno));
-                       talloc_free (text);
+                       ralloc_free (text);
                        return NULL;
                }
 
@@ -107,8 +107,8 @@ int
 main (int argc, char *argv[])
 {
        char *filename = NULL;
-       void *ctx = talloc(NULL, void*);
-       char *info_log = talloc_strdup(ctx, "");
+       void *ctx = ralloc(NULL, void*);
+       char *info_log = ralloc_strdup(ctx, "");
        const char *shader;
        int ret;
 
@@ -125,7 +125,7 @@ main (int argc, char *argv[])
        printf("%s", shader);
        fprintf(stderr, "%s", info_log);
 
-       talloc_free(ctx);
+       ralloc_free(ctx);
 
        return ret;
 }
index 7125d325dffdec452fedbc0500284cbec39b5462..dc816e90ee702ba8125d664d1eed563ade0dc04b 100644 (file)
@@ -26,7 +26,7 @@
 
 #include <stdint.h>
 
-#include <talloc.h>
+#include "../ralloc.h"
 
 #include "program/hash_table.h"
 
@@ -189,7 +189,7 @@ void
 glcpp_parser_destroy (glcpp_parser_t *parser);
 
 int
-preprocess(void *talloc_ctx, const char **shader, char **info_log,
+preprocess(void *ralloc_ctx, const char **shader, char **info_log,
           const struct gl_extensions *extensions, int api);
 
 /* Functions for writing to the info log */
index e1a3a88a3e5392dce29f7221cb688cb8ec6eb874..3640896a2c28dcbfac2d3bf0c6db9d0aa233609f 100644 (file)
@@ -33,16 +33,15 @@ 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): "
+       ralloc_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);
+       ralloc_vasprintf_append(&parser->info_log, fmt, ap);
        va_end(ap);
-       parser->info_log = talloc_strdup_append(parser->info_log, "\n");
+       ralloc_strcat(&parser->info_log, "\n");
 }
 
 void
@@ -50,16 +49,15 @@ 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): "
+       ralloc_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);
+       ralloc_vasprintf_append(&parser->info_log, fmt, ap);
        va_end(ap);
-       parser->info_log = talloc_strdup_append(parser->info_log, "\n");
+       ralloc_strcat(&parser->info_log, "\n");
 }
 
 /* Searches backwards for '^ *#' from a given starting point. */
@@ -92,7 +90,7 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
 {
        int in_continued_line = 0;
        int extra_newlines = 0;
-       char *clean = talloc_strdup(ctx, "");
+       char *clean = ralloc_strdup(ctx, "");
        const char *search_start = shader;
        const char *newline;
        while ((newline = strchr(search_start, '\n')) != NULL) {
@@ -122,27 +120,27 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
                        }
                        if (in_continued_line) {
                                /* Copy everything before the \ */
-                               clean = talloc_strndup_append(clean, shader, backslash - shader);
+                               ralloc_strncat(&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);
+                       ralloc_strncat(&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");
+                               ralloc_strcat(&clean, "\n");
                        in_continued_line = 0;
                }
                search_start = newline + 1;
        }
-       clean = talloc_strdup_append(clean, shader);
+       ralloc_strcat(&clean, shader);
        return clean;
 }
 
 int
-preprocess(void *talloc_ctx, const char **shader, char **info_log,
+preprocess(void *ralloc_ctx, const char **shader, char **info_log,
           const struct gl_extensions *extensions, int api)
 {
        int errors;
@@ -156,9 +154,9 @@ preprocess(void *talloc_ctx, const char **shader, char **info_log,
        if (parser->skip_stack)
                glcpp_error (&parser->skip_stack->loc, parser, "Unterminated #if\n");
 
-       *info_log = talloc_strdup_append(*info_log, parser->info_log);
+       ralloc_strcat(info_log, parser->info_log);
 
-       talloc_steal(talloc_ctx, parser->output);
+       ralloc_steal(ralloc_ctx, parser->output);
        *shader = parser->output;
 
        errors = parser->error;
index 7c0a51b99bfc3e2846109aa49fe7ca95465ee87b..40d2294ef8c74e0be70345c7bac73a594316b43c 100644 (file)
@@ -54,6 +54,7 @@ typedef int flex_int32_t;
 typedef unsigned char flex_uint8_t; 
 typedef unsigned short int flex_uint16_t;
 typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
 
 /* Limits of integral types. */
 #ifndef INT8_MIN
@@ -84,8 +85,6 @@ typedef unsigned int flex_uint32_t;
 #define UINT32_MAX             (4294967295U)
 #endif
 
-#endif /* ! C99 */
-
 #endif /* ! FLEXINT_H */
 
 #ifdef __cplusplus
@@ -159,15 +158,7 @@ typedef void* yyscan_t;
 
 /* 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.
@@ -1027,6 +1018,8 @@ static yyconst flex_int16_t yy_chk[1283] =
 #include "glsl_parser_extras.h"
 #include "glsl_parser.h"
 
+static int classify_identifier(struct _mesa_glsl_parse_state *, const char *);
+
 #define YY_USER_ACTION                                         \
    do {                                                                \
       yylloc->source = 0;                                      \
@@ -1062,7 +1055,7 @@ static yyconst flex_int16_t yy_chk[1283] =
         return ERROR_TOK;                                              \
       } else {                                                         \
         yylval->identifier = strdup(yytext);                           \
-        return IDENTIFIER;                                             \
+        return classify_identifier(yyextra, yytext);                   \
       }                                                                        \
    } while (0)
 
@@ -1076,7 +1069,7 @@ static yyconst flex_int16_t yy_chk[1283] =
  */
 #define ES yyextra->es_shader
 
-#line 1080 "glsl_lexer.cpp"
+#line 1073 "glsl_lexer.cpp"
 
 #define INITIAL 0
 #define PP 1
@@ -1163,6 +1156,10 @@ int _mesa_glsl_get_lineno (yyscan_t yyscanner );
 
 void _mesa_glsl_set_lineno (int line_number ,yyscan_t yyscanner );
 
+int _mesa_glsl_get_column  (yyscan_t yyscanner );
+
+void _mesa_glsl_set_column (int column_no ,yyscan_t yyscanner );
+
 YYSTYPE * _mesa_glsl_get_lval (yyscan_t yyscanner );
 
 void _mesa_glsl_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
@@ -1203,12 +1200,7 @@ static int input (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. */
@@ -1227,7 +1219,7 @@ static int input (yyscan_t yyscanner );
        if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
                { \
                int c = '*'; \
-               size_t n; \
+               unsigned n; \
                for ( n = 0; n < max_size && \
                             (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
                        buf[n] = (char) c; \
@@ -1315,10 +1307,10 @@ YY_DECL
        register int yy_act;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
-#line 95 "glsl_lexer.lpp"
+#line 97 "glsl_lexer.lpp"
 
 
-#line 1322 "glsl_lexer.cpp"
+#line 1314 "glsl_lexer.cpp"
 
     yylval = yylval_param;
 
@@ -1404,7 +1396,7 @@ do_action:        /* This label is used only to access EOF actions. */
 
 case 1:
 YY_RULE_SETUP
-#line 97 "glsl_lexer.lpp"
+#line 99 "glsl_lexer.lpp"
 ;
        YY_BREAK
 /* Preprocessor tokens. */ 
@@ -1413,17 +1405,17 @@ case 2:
 yyg->yy_c_buf_p = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
 YY_RULE_SETUP
-#line 100 "glsl_lexer.lpp"
+#line 102 "glsl_lexer.lpp"
 ;
        YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 101 "glsl_lexer.lpp"
+#line 103 "glsl_lexer.lpp"
 { BEGIN PP; return VERSION; }
        YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 102 "glsl_lexer.lpp"
+#line 104 "glsl_lexer.lpp"
 { BEGIN PP; return EXTENSION; }
        YY_BREAK
 case 5:
@@ -1431,7 +1423,7 @@ case 5:
 yyg->yy_c_buf_p = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
 YY_RULE_SETUP
-#line 103 "glsl_lexer.lpp"
+#line 105 "glsl_lexer.lpp"
 {
                                   /* Eat characters until the first digit is
                                    * encountered
@@ -1453,7 +1445,7 @@ case 6:
 yyg->yy_c_buf_p = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
 YY_RULE_SETUP
-#line 118 "glsl_lexer.lpp"
+#line 120 "glsl_lexer.lpp"
 {
                                   /* Eat characters until the first digit is
                                    * encountered
@@ -1471,7 +1463,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 132 "glsl_lexer.lpp"
+#line 134 "glsl_lexer.lpp"
 {
                                  BEGIN PP;
                                  return PRAGMA_DEBUG_ON;
@@ -1479,7 +1471,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 136 "glsl_lexer.lpp"
+#line 138 "glsl_lexer.lpp"
 {
                                  BEGIN PP;
                                  return PRAGMA_DEBUG_OFF;
@@ -1487,7 +1479,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 140 "glsl_lexer.lpp"
+#line 142 "glsl_lexer.lpp"
 {
                                  BEGIN PP;
                                  return PRAGMA_OPTIMIZE_ON;
@@ -1495,7 +1487,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 144 "glsl_lexer.lpp"
+#line 146 "glsl_lexer.lpp"
 {
                                  BEGIN PP;
                                  return PRAGMA_OPTIMIZE_OFF;
@@ -1503,7 +1495,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 148 "glsl_lexer.lpp"
+#line 150 "glsl_lexer.lpp"
 {
                                  BEGIN PP;
                                  return PRAGMA_INVARIANT_ALL;
@@ -1511,38 +1503,38 @@ YY_RULE_SETUP
        YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 152 "glsl_lexer.lpp"
+#line 154 "glsl_lexer.lpp"
 { BEGIN PRAGMA; }
        YY_BREAK
 case 13:
 /* rule 13 can match eol */
 YY_RULE_SETUP
-#line 154 "glsl_lexer.lpp"
+#line 156 "glsl_lexer.lpp"
 { BEGIN 0; yylineno++; yycolumn = 0; }
        YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 155 "glsl_lexer.lpp"
+#line 157 "glsl_lexer.lpp"
 { }
        YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 157 "glsl_lexer.lpp"
+#line 159 "glsl_lexer.lpp"
 { }
        YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 158 "glsl_lexer.lpp"
+#line 160 "glsl_lexer.lpp"
 { }
        YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 159 "glsl_lexer.lpp"
+#line 161 "glsl_lexer.lpp"
 return COLON;
        YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 160 "glsl_lexer.lpp"
+#line 162 "glsl_lexer.lpp"
 {
                                   yylval->identifier = strdup(yytext);
                                   return IDENTIFIER;
@@ -1550,7 +1542,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 164 "glsl_lexer.lpp"
+#line 166 "glsl_lexer.lpp"
 {
                                    yylval->n = strtol(yytext, NULL, 10);
                                    return INTCONSTANT;
@@ -1559,392 +1551,393 @@ YY_RULE_SETUP
 case 20:
 /* rule 20 can match eol */
 YY_RULE_SETUP
-#line 168 "glsl_lexer.lpp"
+#line 170 "glsl_lexer.lpp"
 { BEGIN 0; yylineno++; yycolumn = 0; return EOL; }
        YY_BREAK
 case 21:
 /* rule 21 can match eol */
 YY_RULE_SETUP
-#line 170 "glsl_lexer.lpp"
+#line 172 "glsl_lexer.lpp"
 { yylineno++; yycolumn = 0; }
        YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 172 "glsl_lexer.lpp"
+#line 174 "glsl_lexer.lpp"
 return ATTRIBUTE;
        YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 173 "glsl_lexer.lpp"
+#line 175 "glsl_lexer.lpp"
 return CONST_TOK;
        YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 174 "glsl_lexer.lpp"
+#line 176 "glsl_lexer.lpp"
 return BOOL_TOK;
        YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 175 "glsl_lexer.lpp"
+#line 177 "glsl_lexer.lpp"
 return FLOAT_TOK;
        YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 176 "glsl_lexer.lpp"
+#line 178 "glsl_lexer.lpp"
 return INT_TOK;
        YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 177 "glsl_lexer.lpp"
+#line 179 "glsl_lexer.lpp"
 KEYWORD(130, 130, UINT_TOK);
        YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 179 "glsl_lexer.lpp"
+#line 181 "glsl_lexer.lpp"
 return BREAK;
        YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 180 "glsl_lexer.lpp"
+#line 182 "glsl_lexer.lpp"
 return CONTINUE;
        YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 181 "glsl_lexer.lpp"
+#line 183 "glsl_lexer.lpp"
 return DO;
        YY_BREAK
 case 31:
 YY_RULE_SETUP
-#line 182 "glsl_lexer.lpp"
+#line 184 "glsl_lexer.lpp"
 return WHILE;
        YY_BREAK
 case 32:
 YY_RULE_SETUP
-#line 183 "glsl_lexer.lpp"
+#line 185 "glsl_lexer.lpp"
 return ELSE;
        YY_BREAK
 case 33:
 YY_RULE_SETUP
-#line 184 "glsl_lexer.lpp"
+#line 186 "glsl_lexer.lpp"
 return FOR;
        YY_BREAK
 case 34:
 YY_RULE_SETUP
-#line 185 "glsl_lexer.lpp"
+#line 187 "glsl_lexer.lpp"
 return IF;
        YY_BREAK
 case 35:
 YY_RULE_SETUP
-#line 186 "glsl_lexer.lpp"
+#line 188 "glsl_lexer.lpp"
 return DISCARD;
        YY_BREAK
 case 36:
 YY_RULE_SETUP
-#line 187 "glsl_lexer.lpp"
+#line 189 "glsl_lexer.lpp"
 return RETURN;
        YY_BREAK
 case 37:
 YY_RULE_SETUP
-#line 189 "glsl_lexer.lpp"
+#line 191 "glsl_lexer.lpp"
 return BVEC2;
        YY_BREAK
 case 38:
 YY_RULE_SETUP
-#line 190 "glsl_lexer.lpp"
+#line 192 "glsl_lexer.lpp"
 return BVEC3;
        YY_BREAK
 case 39:
 YY_RULE_SETUP
-#line 191 "glsl_lexer.lpp"
+#line 193 "glsl_lexer.lpp"
 return BVEC4;
        YY_BREAK
 case 40:
 YY_RULE_SETUP
-#line 192 "glsl_lexer.lpp"
+#line 194 "glsl_lexer.lpp"
 return IVEC2;
        YY_BREAK
 case 41:
 YY_RULE_SETUP
-#line 193 "glsl_lexer.lpp"
+#line 195 "glsl_lexer.lpp"
 return IVEC3;
        YY_BREAK
 case 42:
 YY_RULE_SETUP
-#line 194 "glsl_lexer.lpp"
+#line 196 "glsl_lexer.lpp"
 return IVEC4;
        YY_BREAK
 case 43:
 YY_RULE_SETUP
-#line 195 "glsl_lexer.lpp"
+#line 197 "glsl_lexer.lpp"
 KEYWORD(130, 130, UVEC2);
        YY_BREAK
 case 44:
 YY_RULE_SETUP
-#line 196 "glsl_lexer.lpp"
+#line 198 "glsl_lexer.lpp"
 KEYWORD(130, 130, UVEC3);
        YY_BREAK
 case 45:
 YY_RULE_SETUP
-#line 197 "glsl_lexer.lpp"
+#line 199 "glsl_lexer.lpp"
 KEYWORD(130, 130, UVEC4);
        YY_BREAK
 case 46:
 YY_RULE_SETUP
-#line 198 "glsl_lexer.lpp"
+#line 200 "glsl_lexer.lpp"
 return VEC2;
        YY_BREAK
 case 47:
 YY_RULE_SETUP
-#line 199 "glsl_lexer.lpp"
+#line 201 "glsl_lexer.lpp"
 return VEC3;
        YY_BREAK
 case 48:
 YY_RULE_SETUP
-#line 200 "glsl_lexer.lpp"
+#line 202 "glsl_lexer.lpp"
 return VEC4;
        YY_BREAK
 case 49:
 YY_RULE_SETUP
-#line 201 "glsl_lexer.lpp"
+#line 203 "glsl_lexer.lpp"
 return MAT2X2;
        YY_BREAK
 case 50:
 YY_RULE_SETUP
-#line 202 "glsl_lexer.lpp"
+#line 204 "glsl_lexer.lpp"
 return MAT3X3;
        YY_BREAK
 case 51:
 YY_RULE_SETUP
-#line 203 "glsl_lexer.lpp"
+#line 205 "glsl_lexer.lpp"
 return MAT4X4;
        YY_BREAK
 case 52:
 YY_RULE_SETUP
-#line 204 "glsl_lexer.lpp"
+#line 206 "glsl_lexer.lpp"
 KEYWORD(120, 120, MAT2X2);
        YY_BREAK
 case 53:
 YY_RULE_SETUP
-#line 205 "glsl_lexer.lpp"
+#line 207 "glsl_lexer.lpp"
 KEYWORD(120, 120, MAT2X3);
        YY_BREAK
 case 54:
 YY_RULE_SETUP
-#line 206 "glsl_lexer.lpp"
+#line 208 "glsl_lexer.lpp"
 KEYWORD(120, 120, MAT2X4);
        YY_BREAK
 case 55:
 YY_RULE_SETUP
-#line 207 "glsl_lexer.lpp"
+#line 209 "glsl_lexer.lpp"
 KEYWORD(120, 120, MAT3X2);
        YY_BREAK
 case 56:
 YY_RULE_SETUP
-#line 208 "glsl_lexer.lpp"
+#line 210 "glsl_lexer.lpp"
 KEYWORD(120, 120, MAT3X3);
        YY_BREAK
 case 57:
 YY_RULE_SETUP
-#line 209 "glsl_lexer.lpp"
+#line 211 "glsl_lexer.lpp"
 KEYWORD(120, 120, MAT3X4);
        YY_BREAK
 case 58:
 YY_RULE_SETUP
-#line 210 "glsl_lexer.lpp"
+#line 212 "glsl_lexer.lpp"
 KEYWORD(120, 120, MAT4X2);
        YY_BREAK
 case 59:
 YY_RULE_SETUP
-#line 211 "glsl_lexer.lpp"
+#line 213 "glsl_lexer.lpp"
 KEYWORD(120, 120, MAT4X3);
        YY_BREAK
 case 60:
 YY_RULE_SETUP
-#line 212 "glsl_lexer.lpp"
+#line 214 "glsl_lexer.lpp"
 KEYWORD(120, 120, MAT4X4);
        YY_BREAK
 case 61:
 YY_RULE_SETUP
-#line 214 "glsl_lexer.lpp"
+#line 216 "glsl_lexer.lpp"
 return IN_TOK;
        YY_BREAK
 case 62:
 YY_RULE_SETUP
-#line 215 "glsl_lexer.lpp"
+#line 217 "glsl_lexer.lpp"
 return OUT_TOK;
        YY_BREAK
 case 63:
 YY_RULE_SETUP
-#line 216 "glsl_lexer.lpp"
+#line 218 "glsl_lexer.lpp"
 return INOUT_TOK;
        YY_BREAK
 case 64:
 YY_RULE_SETUP
-#line 217 "glsl_lexer.lpp"
+#line 219 "glsl_lexer.lpp"
 return UNIFORM;
        YY_BREAK
 case 65:
 YY_RULE_SETUP
-#line 218 "glsl_lexer.lpp"
+#line 220 "glsl_lexer.lpp"
 return VARYING;
        YY_BREAK
 case 66:
 YY_RULE_SETUP
-#line 219 "glsl_lexer.lpp"
+#line 221 "glsl_lexer.lpp"
 KEYWORD(120, 120, CENTROID);
        YY_BREAK
 case 67:
 YY_RULE_SETUP
-#line 220 "glsl_lexer.lpp"
+#line 222 "glsl_lexer.lpp"
 KEYWORD(120 || ES, 120 || ES, INVARIANT);
        YY_BREAK
 case 68:
 YY_RULE_SETUP
-#line 221 "glsl_lexer.lpp"
+#line 223 "glsl_lexer.lpp"
 KEYWORD(130 || ES, 130, FLAT);
        YY_BREAK
 case 69:
 YY_RULE_SETUP
-#line 222 "glsl_lexer.lpp"
+#line 224 "glsl_lexer.lpp"
 KEYWORD(130, 130, SMOOTH);
        YY_BREAK
 case 70:
 YY_RULE_SETUP
-#line 223 "glsl_lexer.lpp"
+#line 225 "glsl_lexer.lpp"
 KEYWORD(130, 130, NOPERSPECTIVE);
        YY_BREAK
 case 71:
 YY_RULE_SETUP
-#line 225 "glsl_lexer.lpp"
+#line 227 "glsl_lexer.lpp"
 return SAMPLER1D;
        YY_BREAK
 case 72:
 YY_RULE_SETUP
-#line 226 "glsl_lexer.lpp"
+#line 228 "glsl_lexer.lpp"
 return SAMPLER2D;
        YY_BREAK
 case 73:
 YY_RULE_SETUP
-#line 227 "glsl_lexer.lpp"
+#line 229 "glsl_lexer.lpp"
 return SAMPLER3D;
        YY_BREAK
 case 74:
 YY_RULE_SETUP
-#line 228 "glsl_lexer.lpp"
+#line 230 "glsl_lexer.lpp"
 return SAMPLERCUBE;
        YY_BREAK
 case 75:
 YY_RULE_SETUP
-#line 229 "glsl_lexer.lpp"
+#line 231 "glsl_lexer.lpp"
 KEYWORD(130, 130, SAMPLER1DARRAY);
        YY_BREAK
 case 76:
 YY_RULE_SETUP
-#line 230 "glsl_lexer.lpp"
+#line 232 "glsl_lexer.lpp"
 KEYWORD(130, 130, SAMPLER2DARRAY);
        YY_BREAK
 case 77:
 YY_RULE_SETUP
-#line 231 "glsl_lexer.lpp"
+#line 233 "glsl_lexer.lpp"
 return SAMPLER1DSHADOW;
        YY_BREAK
 case 78:
 YY_RULE_SETUP
-#line 232 "glsl_lexer.lpp"
+#line 234 "glsl_lexer.lpp"
 return SAMPLER2DSHADOW;
        YY_BREAK
 case 79:
 YY_RULE_SETUP
-#line 233 "glsl_lexer.lpp"
+#line 235 "glsl_lexer.lpp"
 KEYWORD(130, 130, SAMPLERCUBESHADOW);
        YY_BREAK
 case 80:
 YY_RULE_SETUP
-#line 234 "glsl_lexer.lpp"
+#line 236 "glsl_lexer.lpp"
 KEYWORD(130, 130, SAMPLER1DARRAYSHADOW);
        YY_BREAK
 case 81:
 YY_RULE_SETUP
-#line 235 "glsl_lexer.lpp"
+#line 237 "glsl_lexer.lpp"
 KEYWORD(130, 130, SAMPLER2DARRAYSHADOW);
        YY_BREAK
 case 82:
 YY_RULE_SETUP
-#line 236 "glsl_lexer.lpp"
+#line 238 "glsl_lexer.lpp"
 KEYWORD(130, 130, ISAMPLER1D);
        YY_BREAK
 case 83:
 YY_RULE_SETUP
-#line 237 "glsl_lexer.lpp"
+#line 239 "glsl_lexer.lpp"
 KEYWORD(130, 130, ISAMPLER2D);
        YY_BREAK
 case 84:
 YY_RULE_SETUP
-#line 238 "glsl_lexer.lpp"
+#line 240 "glsl_lexer.lpp"
 KEYWORD(130, 130, ISAMPLER3D);
        YY_BREAK
 case 85:
 YY_RULE_SETUP
-#line 239 "glsl_lexer.lpp"
+#line 241 "glsl_lexer.lpp"
 KEYWORD(130, 130, ISAMPLERCUBE);
        YY_BREAK
 case 86:
 YY_RULE_SETUP
-#line 240 "glsl_lexer.lpp"
+#line 242 "glsl_lexer.lpp"
 KEYWORD(130, 130, ISAMPLER1DARRAY);
        YY_BREAK
 case 87:
 YY_RULE_SETUP
-#line 241 "glsl_lexer.lpp"
+#line 243 "glsl_lexer.lpp"
 KEYWORD(130, 130, ISAMPLER2DARRAY);
        YY_BREAK
 case 88:
 YY_RULE_SETUP
-#line 242 "glsl_lexer.lpp"
+#line 244 "glsl_lexer.lpp"
 KEYWORD(130, 130, USAMPLER1D);
        YY_BREAK
 case 89:
 YY_RULE_SETUP
-#line 243 "glsl_lexer.lpp"
+#line 245 "glsl_lexer.lpp"
 KEYWORD(130, 130, USAMPLER2D);
        YY_BREAK
 case 90:
 YY_RULE_SETUP
-#line 244 "glsl_lexer.lpp"
+#line 246 "glsl_lexer.lpp"
 KEYWORD(130, 130, USAMPLER3D);
        YY_BREAK
 case 91:
 YY_RULE_SETUP
-#line 245 "glsl_lexer.lpp"
+#line 247 "glsl_lexer.lpp"
 KEYWORD(130, 130, USAMPLERCUBE);
        YY_BREAK
 case 92:
 YY_RULE_SETUP
-#line 246 "glsl_lexer.lpp"
+#line 248 "glsl_lexer.lpp"
 KEYWORD(130, 130, USAMPLER1DARRAY);
        YY_BREAK
 case 93:
 YY_RULE_SETUP
-#line 247 "glsl_lexer.lpp"
+#line 249 "glsl_lexer.lpp"
 KEYWORD(130, 130, USAMPLER2DARRAY);
        YY_BREAK
 case 94:
 YY_RULE_SETUP
-#line 250 "glsl_lexer.lpp"
+#line 252 "glsl_lexer.lpp"
 return STRUCT;
        YY_BREAK
 case 95:
 YY_RULE_SETUP
-#line 251 "glsl_lexer.lpp"
+#line 253 "glsl_lexer.lpp"
 return VOID_TOK;
        YY_BREAK
 case 96:
 YY_RULE_SETUP
-#line 253 "glsl_lexer.lpp"
+#line 255 "glsl_lexer.lpp"
 {
                  if ((yyextra->language_version >= 140)
+                     || yyextra->AMD_conservative_depth_enable
                      || yyextra->ARB_explicit_attrib_location_enable
-                     || (yyextra->ARB_fragment_coord_conventions_enable)){
+                     || yyextra->ARB_fragment_coord_conventions_enable) {
                      return LAYOUT_TOK;
                   } else {
                      yylval->identifier = strdup(yytext);
@@ -1954,112 +1947,112 @@ YY_RULE_SETUP
        YY_BREAK
 case 97:
 YY_RULE_SETUP
-#line 264 "glsl_lexer.lpp"
+#line 267 "glsl_lexer.lpp"
 return INC_OP;
        YY_BREAK
 case 98:
 YY_RULE_SETUP
-#line 265 "glsl_lexer.lpp"
+#line 268 "glsl_lexer.lpp"
 return DEC_OP;
        YY_BREAK
 case 99:
 YY_RULE_SETUP
-#line 266 "glsl_lexer.lpp"
+#line 269 "glsl_lexer.lpp"
 return LE_OP;
        YY_BREAK
 case 100:
 YY_RULE_SETUP
-#line 267 "glsl_lexer.lpp"
+#line 270 "glsl_lexer.lpp"
 return GE_OP;
        YY_BREAK
 case 101:
 YY_RULE_SETUP
-#line 268 "glsl_lexer.lpp"
+#line 271 "glsl_lexer.lpp"
 return EQ_OP;
        YY_BREAK
 case 102:
 YY_RULE_SETUP
-#line 269 "glsl_lexer.lpp"
+#line 272 "glsl_lexer.lpp"
 return NE_OP;
        YY_BREAK
 case 103:
 YY_RULE_SETUP
-#line 270 "glsl_lexer.lpp"
+#line 273 "glsl_lexer.lpp"
 return AND_OP;
        YY_BREAK
 case 104:
 YY_RULE_SETUP
-#line 271 "glsl_lexer.lpp"
+#line 274 "glsl_lexer.lpp"
 return OR_OP;
        YY_BREAK
 case 105:
 YY_RULE_SETUP
-#line 272 "glsl_lexer.lpp"
+#line 275 "glsl_lexer.lpp"
 return XOR_OP;
        YY_BREAK
 case 106:
 YY_RULE_SETUP
-#line 273 "glsl_lexer.lpp"
+#line 276 "glsl_lexer.lpp"
 return LEFT_OP;
        YY_BREAK
 case 107:
 YY_RULE_SETUP
-#line 274 "glsl_lexer.lpp"
+#line 277 "glsl_lexer.lpp"
 return RIGHT_OP;
        YY_BREAK
 case 108:
 YY_RULE_SETUP
-#line 276 "glsl_lexer.lpp"
+#line 279 "glsl_lexer.lpp"
 return MUL_ASSIGN;
        YY_BREAK
 case 109:
 YY_RULE_SETUP
-#line 277 "glsl_lexer.lpp"
+#line 280 "glsl_lexer.lpp"
 return DIV_ASSIGN;
        YY_BREAK
 case 110:
 YY_RULE_SETUP
-#line 278 "glsl_lexer.lpp"
+#line 281 "glsl_lexer.lpp"
 return ADD_ASSIGN;
        YY_BREAK
 case 111:
 YY_RULE_SETUP
-#line 279 "glsl_lexer.lpp"
+#line 282 "glsl_lexer.lpp"
 return MOD_ASSIGN;
        YY_BREAK
 case 112:
 YY_RULE_SETUP
-#line 280 "glsl_lexer.lpp"
+#line 283 "glsl_lexer.lpp"
 return LEFT_ASSIGN;
        YY_BREAK
 case 113:
 YY_RULE_SETUP
-#line 281 "glsl_lexer.lpp"
+#line 284 "glsl_lexer.lpp"
 return RIGHT_ASSIGN;
        YY_BREAK
 case 114:
 YY_RULE_SETUP
-#line 282 "glsl_lexer.lpp"
+#line 285 "glsl_lexer.lpp"
 return AND_ASSIGN;
        YY_BREAK
 case 115:
 YY_RULE_SETUP
-#line 283 "glsl_lexer.lpp"
+#line 286 "glsl_lexer.lpp"
 return XOR_ASSIGN;
        YY_BREAK
 case 116:
 YY_RULE_SETUP
-#line 284 "glsl_lexer.lpp"
+#line 287 "glsl_lexer.lpp"
 return OR_ASSIGN;
        YY_BREAK
 case 117:
 YY_RULE_SETUP
-#line 285 "glsl_lexer.lpp"
+#line 288 "glsl_lexer.lpp"
 return SUB_ASSIGN;
        YY_BREAK
 case 118:
 YY_RULE_SETUP
-#line 287 "glsl_lexer.lpp"
+#line 290 "glsl_lexer.lpp"
 {
                            yylval->n = strtol(yytext, NULL, 10);
                            return IS_UINT ? UINTCONSTANT : INTCONSTANT;
@@ -2067,7 +2060,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 119:
 YY_RULE_SETUP
-#line 291 "glsl_lexer.lpp"
+#line 294 "glsl_lexer.lpp"
 {
                            yylval->n = strtol(yytext + 2, NULL, 16);
                            return IS_UINT ? UINTCONSTANT : INTCONSTANT;
@@ -2075,7 +2068,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 120:
 YY_RULE_SETUP
-#line 295 "glsl_lexer.lpp"
+#line 298 "glsl_lexer.lpp"
 {
                            yylval->n = strtol(yytext, NULL, 8);
                            return IS_UINT ? UINTCONSTANT : INTCONSTANT;
@@ -2083,7 +2076,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 121:
 YY_RULE_SETUP
-#line 300 "glsl_lexer.lpp"
+#line 303 "glsl_lexer.lpp"
 {
                            yylval->real = glsl_strtod(yytext, NULL);
                            return FLOATCONSTANT;
@@ -2091,7 +2084,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 122:
 YY_RULE_SETUP
-#line 304 "glsl_lexer.lpp"
+#line 307 "glsl_lexer.lpp"
 {
                            yylval->real = glsl_strtod(yytext, NULL);
                            return FLOATCONSTANT;
@@ -2099,7 +2092,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 123:
 YY_RULE_SETUP
-#line 308 "glsl_lexer.lpp"
+#line 311 "glsl_lexer.lpp"
 {
                            yylval->real = glsl_strtod(yytext, NULL);
                            return FLOATCONSTANT;
@@ -2107,7 +2100,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 124:
 YY_RULE_SETUP
-#line 312 "glsl_lexer.lpp"
+#line 315 "glsl_lexer.lpp"
 {
                            yylval->real = glsl_strtod(yytext, NULL);
                            return FLOATCONSTANT;
@@ -2115,7 +2108,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 125:
 YY_RULE_SETUP
-#line 316 "glsl_lexer.lpp"
+#line 319 "glsl_lexer.lpp"
 {
                            yylval->real = glsl_strtod(yytext, NULL);
                            return FLOATCONSTANT;
@@ -2123,7 +2116,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 126:
 YY_RULE_SETUP
-#line 321 "glsl_lexer.lpp"
+#line 324 "glsl_lexer.lpp"
 {
                            yylval->n = 1;
                            return BOOLCONSTANT;
@@ -2131,7 +2124,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 127:
 YY_RULE_SETUP
-#line 325 "glsl_lexer.lpp"
+#line 328 "glsl_lexer.lpp"
 {
                            yylval->n = 0;
                            return BOOLCONSTANT;
@@ -2140,427 +2133,427 @@ YY_RULE_SETUP
 /* Reserved words in GLSL 1.10. */
 case 128:
 YY_RULE_SETUP
-#line 332 "glsl_lexer.lpp"
+#line 335 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, ASM);
        YY_BREAK
 case 129:
 YY_RULE_SETUP
-#line 333 "glsl_lexer.lpp"
+#line 336 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, CLASS);
        YY_BREAK
 case 130:
 YY_RULE_SETUP
-#line 334 "glsl_lexer.lpp"
+#line 337 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, UNION);
        YY_BREAK
 case 131:
 YY_RULE_SETUP
-#line 335 "glsl_lexer.lpp"
+#line 338 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, ENUM);
        YY_BREAK
 case 132:
 YY_RULE_SETUP
-#line 336 "glsl_lexer.lpp"
+#line 339 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, TYPEDEF);
        YY_BREAK
 case 133:
 YY_RULE_SETUP
-#line 337 "glsl_lexer.lpp"
+#line 340 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, TEMPLATE);
        YY_BREAK
 case 134:
 YY_RULE_SETUP
-#line 338 "glsl_lexer.lpp"
+#line 341 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, THIS);
        YY_BREAK
 case 135:
 YY_RULE_SETUP
-#line 339 "glsl_lexer.lpp"
+#line 342 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, PACKED_TOK);
        YY_BREAK
 case 136:
 YY_RULE_SETUP
-#line 340 "glsl_lexer.lpp"
+#line 343 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, GOTO);
        YY_BREAK
 case 137:
 YY_RULE_SETUP
-#line 341 "glsl_lexer.lpp"
+#line 344 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 130, SWITCH);
        YY_BREAK
 case 138:
 YY_RULE_SETUP
-#line 342 "glsl_lexer.lpp"
+#line 345 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 130, DEFAULT);
        YY_BREAK
 case 139:
 YY_RULE_SETUP
-#line 343 "glsl_lexer.lpp"
+#line 346 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, INLINE_TOK);
        YY_BREAK
 case 140:
 YY_RULE_SETUP
-#line 344 "glsl_lexer.lpp"
+#line 347 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, NOINLINE);
        YY_BREAK
 case 141:
 YY_RULE_SETUP
-#line 345 "glsl_lexer.lpp"
+#line 348 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, VOLATILE);
        YY_BREAK
 case 142:
 YY_RULE_SETUP
-#line 346 "glsl_lexer.lpp"
+#line 349 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, PUBLIC_TOK);
        YY_BREAK
 case 143:
 YY_RULE_SETUP
-#line 347 "glsl_lexer.lpp"
+#line 350 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, STATIC);
        YY_BREAK
 case 144:
 YY_RULE_SETUP
-#line 348 "glsl_lexer.lpp"
+#line 351 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, EXTERN);
        YY_BREAK
 case 145:
 YY_RULE_SETUP
-#line 349 "glsl_lexer.lpp"
+#line 352 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, EXTERNAL);
        YY_BREAK
 case 146:
 YY_RULE_SETUP
-#line 350 "glsl_lexer.lpp"
+#line 353 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, INTERFACE);
        YY_BREAK
 case 147:
 YY_RULE_SETUP
-#line 351 "glsl_lexer.lpp"
+#line 354 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, LONG_TOK);
        YY_BREAK
 case 148:
 YY_RULE_SETUP
-#line 352 "glsl_lexer.lpp"
+#line 355 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, SHORT_TOK);
        YY_BREAK
 case 149:
 YY_RULE_SETUP
-#line 353 "glsl_lexer.lpp"
+#line 356 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 400, DOUBLE_TOK);
        YY_BREAK
 case 150:
 YY_RULE_SETUP
-#line 354 "glsl_lexer.lpp"
+#line 357 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, HALF);
        YY_BREAK
 case 151:
 YY_RULE_SETUP
-#line 355 "glsl_lexer.lpp"
+#line 358 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, FIXED_TOK);
        YY_BREAK
 case 152:
 YY_RULE_SETUP
-#line 356 "glsl_lexer.lpp"
+#line 359 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, UNSIGNED);
        YY_BREAK
 case 153:
 YY_RULE_SETUP
-#line 357 "glsl_lexer.lpp"
+#line 360 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, INPUT_TOK);
        YY_BREAK
 case 154:
 YY_RULE_SETUP
-#line 358 "glsl_lexer.lpp"
+#line 361 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, OUTPUT);
        YY_BREAK
 case 155:
 YY_RULE_SETUP
-#line 359 "glsl_lexer.lpp"
+#line 362 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, HVEC2);
        YY_BREAK
 case 156:
 YY_RULE_SETUP
-#line 360 "glsl_lexer.lpp"
+#line 363 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, HVEC3);
        YY_BREAK
 case 157:
 YY_RULE_SETUP
-#line 361 "glsl_lexer.lpp"
+#line 364 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, HVEC4);
        YY_BREAK
 case 158:
 YY_RULE_SETUP
-#line 362 "glsl_lexer.lpp"
+#line 365 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 400, DVEC2);
        YY_BREAK
 case 159:
 YY_RULE_SETUP
-#line 363 "glsl_lexer.lpp"
+#line 366 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 400, DVEC3);
        YY_BREAK
 case 160:
 YY_RULE_SETUP
-#line 364 "glsl_lexer.lpp"
+#line 367 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 400, DVEC4);
        YY_BREAK
 case 161:
 YY_RULE_SETUP
-#line 365 "glsl_lexer.lpp"
+#line 368 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, FVEC2);
        YY_BREAK
 case 162:
 YY_RULE_SETUP
-#line 366 "glsl_lexer.lpp"
+#line 369 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, FVEC3);
        YY_BREAK
 case 163:
 YY_RULE_SETUP
-#line 367 "glsl_lexer.lpp"
+#line 370 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, FVEC4);
        YY_BREAK
 case 164:
 YY_RULE_SETUP
-#line 368 "glsl_lexer.lpp"
+#line 371 "glsl_lexer.lpp"
 return SAMPLER2DRECT;
        YY_BREAK
 case 165:
 YY_RULE_SETUP
-#line 369 "glsl_lexer.lpp"
+#line 372 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, SAMPLER3DRECT);
        YY_BREAK
 case 166:
 YY_RULE_SETUP
-#line 370 "glsl_lexer.lpp"
+#line 373 "glsl_lexer.lpp"
 return SAMPLER2DRECTSHADOW;
        YY_BREAK
 case 167:
 YY_RULE_SETUP
-#line 371 "glsl_lexer.lpp"
+#line 374 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, SIZEOF);
        YY_BREAK
 case 168:
 YY_RULE_SETUP
-#line 372 "glsl_lexer.lpp"
+#line 375 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, CAST);
        YY_BREAK
 case 169:
 YY_RULE_SETUP
-#line 373 "glsl_lexer.lpp"
+#line 376 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, NAMESPACE);
        YY_BREAK
 case 170:
 YY_RULE_SETUP
-#line 374 "glsl_lexer.lpp"
+#line 377 "glsl_lexer.lpp"
 KEYWORD(110 || ES, 999, USING);
        YY_BREAK
 /* Additional reserved words in GLSL 1.20. */
 case 171:
 YY_RULE_SETUP
-#line 377 "glsl_lexer.lpp"
+#line 380 "glsl_lexer.lpp"
 KEYWORD(120, 130 || ES, LOWP);
        YY_BREAK
 case 172:
 YY_RULE_SETUP
-#line 378 "glsl_lexer.lpp"
+#line 381 "glsl_lexer.lpp"
 KEYWORD(120, 130 || ES, MEDIUMP);
        YY_BREAK
 case 173:
 YY_RULE_SETUP
-#line 379 "glsl_lexer.lpp"
+#line 382 "glsl_lexer.lpp"
 KEYWORD(120, 130 || ES, HIGHP);
        YY_BREAK
 case 174:
 YY_RULE_SETUP
-#line 380 "glsl_lexer.lpp"
+#line 383 "glsl_lexer.lpp"
 KEYWORD(120, 130 || ES, PRECISION);
        YY_BREAK
 /* Additional reserved words in GLSL 1.30. */
 case 175:
 YY_RULE_SETUP
-#line 383 "glsl_lexer.lpp"
+#line 386 "glsl_lexer.lpp"
 KEYWORD(130, 130, CASE);
        YY_BREAK
 case 176:
 YY_RULE_SETUP
-#line 384 "glsl_lexer.lpp"
+#line 387 "glsl_lexer.lpp"
 KEYWORD(130, 999, COMMON);
        YY_BREAK
 case 177:
 YY_RULE_SETUP
-#line 385 "glsl_lexer.lpp"
+#line 388 "glsl_lexer.lpp"
 KEYWORD(130, 999, PARTITION);
        YY_BREAK
 case 178:
 YY_RULE_SETUP
-#line 386 "glsl_lexer.lpp"
+#line 389 "glsl_lexer.lpp"
 KEYWORD(130, 999, ACTIVE);
        YY_BREAK
 case 179:
 YY_RULE_SETUP
-#line 387 "glsl_lexer.lpp"
+#line 390 "glsl_lexer.lpp"
 KEYWORD(130 || ES, 999, SUPERP);
        YY_BREAK
 case 180:
 YY_RULE_SETUP
-#line 388 "glsl_lexer.lpp"
+#line 391 "glsl_lexer.lpp"
 KEYWORD(130, 140, SAMPLERBUFFER);
        YY_BREAK
 case 181:
 YY_RULE_SETUP
-#line 389 "glsl_lexer.lpp"
+#line 392 "glsl_lexer.lpp"
 KEYWORD(130, 999, FILTER);
        YY_BREAK
 case 182:
 YY_RULE_SETUP
-#line 390 "glsl_lexer.lpp"
+#line 393 "glsl_lexer.lpp"
 KEYWORD(130, 999, IMAGE1D);
        YY_BREAK
 case 183:
 YY_RULE_SETUP
-#line 391 "glsl_lexer.lpp"
+#line 394 "glsl_lexer.lpp"
 KEYWORD(130, 999, IMAGE2D);
        YY_BREAK
 case 184:
 YY_RULE_SETUP
-#line 392 "glsl_lexer.lpp"
+#line 395 "glsl_lexer.lpp"
 KEYWORD(130, 999, IMAGE3D);
        YY_BREAK
 case 185:
 YY_RULE_SETUP
-#line 393 "glsl_lexer.lpp"
+#line 396 "glsl_lexer.lpp"
 KEYWORD(130, 999, IMAGECUBE);
        YY_BREAK
 case 186:
 YY_RULE_SETUP
-#line 394 "glsl_lexer.lpp"
+#line 397 "glsl_lexer.lpp"
 KEYWORD(130, 999, IIMAGE1D);
        YY_BREAK
 case 187:
 YY_RULE_SETUP
-#line 395 "glsl_lexer.lpp"
+#line 398 "glsl_lexer.lpp"
 KEYWORD(130, 999, IIMAGE2D);
        YY_BREAK
 case 188:
 YY_RULE_SETUP
-#line 396 "glsl_lexer.lpp"
+#line 399 "glsl_lexer.lpp"
 KEYWORD(130, 999, IIMAGE3D);
        YY_BREAK
 case 189:
 YY_RULE_SETUP
-#line 397 "glsl_lexer.lpp"
+#line 400 "glsl_lexer.lpp"
 KEYWORD(130, 999, IIMAGECUBE);
        YY_BREAK
 case 190:
 YY_RULE_SETUP
-#line 398 "glsl_lexer.lpp"
+#line 401 "glsl_lexer.lpp"
 KEYWORD(130, 999, UIMAGE1D);
        YY_BREAK
 case 191:
 YY_RULE_SETUP
-#line 399 "glsl_lexer.lpp"
+#line 402 "glsl_lexer.lpp"
 KEYWORD(130, 999, UIMAGE2D);
        YY_BREAK
 case 192:
 YY_RULE_SETUP
-#line 400 "glsl_lexer.lpp"
+#line 403 "glsl_lexer.lpp"
 KEYWORD(130, 999, UIMAGE3D);
        YY_BREAK
 case 193:
 YY_RULE_SETUP
-#line 401 "glsl_lexer.lpp"
+#line 404 "glsl_lexer.lpp"
 KEYWORD(130, 999, UIMAGECUBE);
        YY_BREAK
 case 194:
 YY_RULE_SETUP
-#line 402 "glsl_lexer.lpp"
+#line 405 "glsl_lexer.lpp"
 KEYWORD(130, 999, IMAGE1DARRAY);
        YY_BREAK
 case 195:
 YY_RULE_SETUP
-#line 403 "glsl_lexer.lpp"
+#line 406 "glsl_lexer.lpp"
 KEYWORD(130, 999, IMAGE2DARRAY);
        YY_BREAK
 case 196:
 YY_RULE_SETUP
-#line 404 "glsl_lexer.lpp"
+#line 407 "glsl_lexer.lpp"
 KEYWORD(130, 999, IIMAGE1DARRAY);
        YY_BREAK
 case 197:
 YY_RULE_SETUP
-#line 405 "glsl_lexer.lpp"
+#line 408 "glsl_lexer.lpp"
 KEYWORD(130, 999, IIMAGE2DARRAY);
        YY_BREAK
 case 198:
 YY_RULE_SETUP
-#line 406 "glsl_lexer.lpp"
+#line 409 "glsl_lexer.lpp"
 KEYWORD(130, 999, UIMAGE1DARRAY);
        YY_BREAK
 case 199:
 YY_RULE_SETUP
-#line 407 "glsl_lexer.lpp"
+#line 410 "glsl_lexer.lpp"
 KEYWORD(130, 999, UIMAGE2DARRAY);
        YY_BREAK
 case 200:
 YY_RULE_SETUP
-#line 408 "glsl_lexer.lpp"
+#line 411 "glsl_lexer.lpp"
 KEYWORD(130, 999, IMAGE1DSHADOW);
        YY_BREAK
 case 201:
 YY_RULE_SETUP
-#line 409 "glsl_lexer.lpp"
+#line 412 "glsl_lexer.lpp"
 KEYWORD(130, 999, IMAGE2DSHADOW);
        YY_BREAK
 case 202:
 YY_RULE_SETUP
-#line 410 "glsl_lexer.lpp"
+#line 413 "glsl_lexer.lpp"
 KEYWORD(130, 999, IMAGE1DARRAYSHADOW);
        YY_BREAK
 case 203:
 YY_RULE_SETUP
-#line 411 "glsl_lexer.lpp"
+#line 414 "glsl_lexer.lpp"
 KEYWORD(130, 999, IMAGE2DARRAYSHADOW);
        YY_BREAK
 case 204:
 YY_RULE_SETUP
-#line 412 "glsl_lexer.lpp"
+#line 415 "glsl_lexer.lpp"
 KEYWORD(130, 999, IMAGEBUFFER);
        YY_BREAK
 case 205:
 YY_RULE_SETUP
-#line 413 "glsl_lexer.lpp"
+#line 416 "glsl_lexer.lpp"
 KEYWORD(130, 999, IIMAGEBUFFER);
        YY_BREAK
 case 206:
 YY_RULE_SETUP
-#line 414 "glsl_lexer.lpp"
+#line 417 "glsl_lexer.lpp"
 KEYWORD(130, 999, UIMAGEBUFFER);
        YY_BREAK
 case 207:
 YY_RULE_SETUP
-#line 415 "glsl_lexer.lpp"
+#line 418 "glsl_lexer.lpp"
 KEYWORD(130, 999, ROW_MAJOR);
        YY_BREAK
 case 208:
 YY_RULE_SETUP
-#line 417 "glsl_lexer.lpp"
+#line 420 "glsl_lexer.lpp"
 {
                            struct _mesa_glsl_parse_state *state = yyextra;
                            void *ctx = state;  
-                           yylval->identifier = talloc_strdup(ctx, yytext);
-                           return IDENTIFIER;
+                           yylval->identifier = ralloc_strdup(ctx, yytext);
+                           return classify_identifier(state, yytext);
                        }
        YY_BREAK
 case 209:
 YY_RULE_SETUP
-#line 424 "glsl_lexer.lpp"
+#line 427 "glsl_lexer.lpp"
 { return yytext[0]; }
        YY_BREAK
 case 210:
 YY_RULE_SETUP
-#line 426 "glsl_lexer.lpp"
+#line 429 "glsl_lexer.lpp"
 ECHO;
        YY_BREAK
-#line 2564 "glsl_lexer.cpp"
+#line 2557 "glsl_lexer.cpp"
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(PP):
 case YY_STATE_EOF(PRAGMA):
@@ -3296,8 +3289,8 @@ YY_BUFFER_STATE _mesa_glsl__scan_string (yyconst char * yystr , yyscan_t yyscann
 
 /** 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 bytes the byte buffer to scan
+ * @param 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.
  */
@@ -3703,9 +3696,20 @@ void _mesa_glsl_free (void * ptr , yyscan_t yyscanner)
 
 #define YYTABLES_NAME "yytables"
 
-#line 426 "glsl_lexer.lpp"
+#line 429 "glsl_lexer.lpp"
+
 
 
+int
+classify_identifier(struct _mesa_glsl_parse_state *state, const char *name)
+{
+   if (state->symbols->get_variable(name) || state->symbols->get_function(name))
+      return IDENTIFIER;
+   else if (state->symbols->get_type(name))
+      return TYPE_IDENTIFIER;
+   else
+      return NEW_IDENTIFIER;
+}
 
 void
 _mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, const char *string)
index d30759be2b808601c37cefa8986d902ae520ba95..e4c469f9e0af8be3185bb0a64426dafc21b32ab7 100644 (file)
@@ -27,6 +27,8 @@
 #include "glsl_parser_extras.h"
 #include "glsl_parser.h"
 
+static int classify_identifier(struct _mesa_glsl_parse_state *, const char *);
+
 #define YY_USER_ACTION                                         \
    do {                                                                \
       yylloc->source = 0;                                      \
@@ -62,7 +64,7 @@
         return ERROR_TOK;                                              \
       } else {                                                         \
         yylval->identifier = strdup(yytext);                           \
-        return IDENTIFIER;                                             \
+        return classify_identifier(yyextra, yytext);                   \
       }                                                                        \
    } while (0)
 
@@ -252,8 +254,9 @@ void                return VOID_TOK;
 
 layout         {
                  if ((yyextra->language_version >= 140)
+                     || yyextra->AMD_conservative_depth_enable
                      || yyextra->ARB_explicit_attrib_location_enable
-                     || (yyextra->ARB_fragment_coord_conventions_enable)){
+                     || yyextra->ARB_fragment_coord_conventions_enable) {
                      return LAYOUT_TOK;
                   } else {
                      yylval->identifier = strdup(yytext);
@@ -417,14 +420,25 @@ row_major KEYWORD(130, 999, 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;
+                           yylval->identifier = ralloc_strdup(ctx, yytext);
+                           return classify_identifier(state, yytext);
                        }
 
 .                      { return yytext[0]; }
 
 %%
 
+int
+classify_identifier(struct _mesa_glsl_parse_state *state, const char *name)
+{
+   if (state->symbols->get_variable(name) || state->symbols->get_function(name))
+      return IDENTIFIER;
+   else if (state->symbols->get_type(name))
+      return TYPE_IDENTIFIER;
+   else
+      return NEW_IDENTIFIER;
+}
+
 void
 _mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, const char *string)
 {
index 8b196ae7fc64fa9d6bf374eeadb2a93c379961e9..1db7e901a96b9b55f7504d3e6fecccbe649c941a 100644 (file)
      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,
-     PRAGMA_INVARIANT_ALL = 375,
-     LAYOUT_TOK = 376,
-     ASM = 377,
-     CLASS = 378,
-     UNION = 379,
-     ENUM = 380,
-     TYPEDEF = 381,
-     TEMPLATE = 382,
-     THIS = 383,
-     PACKED_TOK = 384,
-     GOTO = 385,
-     INLINE_TOK = 386,
-     NOINLINE = 387,
-     VOLATILE = 388,
-     PUBLIC_TOK = 389,
-     STATIC = 390,
-     EXTERN = 391,
-     EXTERNAL = 392,
-     LONG_TOK = 393,
-     SHORT_TOK = 394,
-     DOUBLE_TOK = 395,
-     HALF = 396,
-     FIXED_TOK = 397,
-     UNSIGNED = 398,
-     INPUT_TOK = 399,
-     OUPTUT = 400,
-     HVEC2 = 401,
-     HVEC3 = 402,
-     HVEC4 = 403,
-     DVEC2 = 404,
-     DVEC3 = 405,
-     DVEC4 = 406,
-     FVEC2 = 407,
-     FVEC3 = 408,
-     FVEC4 = 409,
-     SAMPLER2DRECT = 410,
-     SAMPLER3DRECT = 411,
-     SAMPLER2DRECTSHADOW = 412,
-     SIZEOF = 413,
-     CAST = 414,
-     NAMESPACE = 415,
-     USING = 416,
-     ERROR_TOK = 417,
-     COMMON = 418,
-     PARTITION = 419,
-     ACTIVE = 420,
-     SAMPLERBUFFER = 421,
-     FILTER = 422,
-     IMAGE1D = 423,
-     IMAGE2D = 424,
-     IMAGE3D = 425,
-     IMAGECUBE = 426,
-     IMAGE1DARRAY = 427,
-     IMAGE2DARRAY = 428,
-     IIMAGE1D = 429,
-     IIMAGE2D = 430,
-     IIMAGE3D = 431,
-     IIMAGECUBE = 432,
-     IIMAGE1DARRAY = 433,
-     IIMAGE2DARRAY = 434,
-     UIMAGE1D = 435,
-     UIMAGE2D = 436,
-     UIMAGE3D = 437,
-     UIMAGECUBE = 438,
-     UIMAGE1DARRAY = 439,
-     UIMAGE2DARRAY = 440,
-     IMAGE1DSHADOW = 441,
-     IMAGE2DSHADOW = 442,
-     IMAGEBUFFER = 443,
-     IIMAGEBUFFER = 444,
-     UIMAGEBUFFER = 445,
-     IMAGE1DARRAYSHADOW = 446,
-     IMAGE2DARRAYSHADOW = 447,
-     ROW_MAJOR = 448
+     TYPE_IDENTIFIER = 332,
+     NEW_IDENTIFIER = 333,
+     FLOATCONSTANT = 334,
+     INTCONSTANT = 335,
+     UINTCONSTANT = 336,
+     BOOLCONSTANT = 337,
+     FIELD_SELECTION = 338,
+     LEFT_OP = 339,
+     RIGHT_OP = 340,
+     INC_OP = 341,
+     DEC_OP = 342,
+     LE_OP = 343,
+     GE_OP = 344,
+     EQ_OP = 345,
+     NE_OP = 346,
+     AND_OP = 347,
+     OR_OP = 348,
+     XOR_OP = 349,
+     MUL_ASSIGN = 350,
+     DIV_ASSIGN = 351,
+     ADD_ASSIGN = 352,
+     MOD_ASSIGN = 353,
+     LEFT_ASSIGN = 354,
+     RIGHT_ASSIGN = 355,
+     AND_ASSIGN = 356,
+     XOR_ASSIGN = 357,
+     OR_ASSIGN = 358,
+     SUB_ASSIGN = 359,
+     INVARIANT = 360,
+     LOWP = 361,
+     MEDIUMP = 362,
+     HIGHP = 363,
+     SUPERP = 364,
+     PRECISION = 365,
+     VERSION = 366,
+     EXTENSION = 367,
+     LINE = 368,
+     COLON = 369,
+     EOL = 370,
+     INTERFACE = 371,
+     OUTPUT = 372,
+     PRAGMA_DEBUG_ON = 373,
+     PRAGMA_DEBUG_OFF = 374,
+     PRAGMA_OPTIMIZE_ON = 375,
+     PRAGMA_OPTIMIZE_OFF = 376,
+     PRAGMA_INVARIANT_ALL = 377,
+     LAYOUT_TOK = 378,
+     ASM = 379,
+     CLASS = 380,
+     UNION = 381,
+     ENUM = 382,
+     TYPEDEF = 383,
+     TEMPLATE = 384,
+     THIS = 385,
+     PACKED_TOK = 386,
+     GOTO = 387,
+     INLINE_TOK = 388,
+     NOINLINE = 389,
+     VOLATILE = 390,
+     PUBLIC_TOK = 391,
+     STATIC = 392,
+     EXTERN = 393,
+     EXTERNAL = 394,
+     LONG_TOK = 395,
+     SHORT_TOK = 396,
+     DOUBLE_TOK = 397,
+     HALF = 398,
+     FIXED_TOK = 399,
+     UNSIGNED = 400,
+     INPUT_TOK = 401,
+     OUPTUT = 402,
+     HVEC2 = 403,
+     HVEC3 = 404,
+     HVEC4 = 405,
+     DVEC2 = 406,
+     DVEC3 = 407,
+     DVEC4 = 408,
+     FVEC2 = 409,
+     FVEC3 = 410,
+     FVEC4 = 411,
+     SAMPLER2DRECT = 412,
+     SAMPLER3DRECT = 413,
+     SAMPLER2DRECTSHADOW = 414,
+     SIZEOF = 415,
+     CAST = 416,
+     NAMESPACE = 417,
+     USING = 418,
+     ERROR_TOK = 419,
+     COMMON = 420,
+     PARTITION = 421,
+     ACTIVE = 422,
+     SAMPLERBUFFER = 423,
+     FILTER = 424,
+     IMAGE1D = 425,
+     IMAGE2D = 426,
+     IMAGE3D = 427,
+     IMAGECUBE = 428,
+     IMAGE1DARRAY = 429,
+     IMAGE2DARRAY = 430,
+     IIMAGE1D = 431,
+     IIMAGE2D = 432,
+     IIMAGE3D = 433,
+     IIMAGECUBE = 434,
+     IIMAGE1DARRAY = 435,
+     IIMAGE2DARRAY = 436,
+     UIMAGE1D = 437,
+     UIMAGE2D = 438,
+     UIMAGE3D = 439,
+     UIMAGECUBE = 440,
+     UIMAGE1DARRAY = 441,
+     UIMAGE2DARRAY = 442,
+     IMAGE1DSHADOW = 443,
+     IMAGE2DSHADOW = 444,
+     IMAGEBUFFER = 445,
+     IIMAGEBUFFER = 446,
+     UIMAGEBUFFER = 447,
+     IMAGE1DARRAYSHADOW = 448,
+     IMAGE2DARRAYSHADOW = 449,
+     ROW_MAJOR = 450
    };
 #endif
 
@@ -374,7 +376,7 @@ typedef union YYSTYPE
 
 
 /* Line 214 of yacc.c  */
-#line 378 "glsl_parser.cpp"
+#line 380 "glsl_parser.cpp"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -399,7 +401,7 @@ typedef struct YYLTYPE
 
 
 /* Line 264 of yacc.c  */
-#line 403 "glsl_parser.cpp"
+#line 405 "glsl_parser.cpp"
 
 #ifdef short
 # undef short
@@ -616,20 +618,20 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  5
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   3738
+#define YYLAST   3692
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  218
+#define YYNTOKENS  220
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  87
+#define YYNNTS  93
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  279
+#define YYNRULES  291
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  415
+#define YYNSTATES  434
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   448
+#define YYMAXUTOK   450
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -640,16 +642,16 @@ 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,   202,     2,     2,     2,   206,   209,     2,
-     194,   195,   204,   200,   199,   201,   198,   205,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,   213,   215,
-     207,   214,   208,   212,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,   204,     2,     2,     2,   208,   211,     2,
+     196,   197,   206,   202,   201,   203,   200,   207,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,   215,   217,
+     209,   216,   210,   214,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,   196,     2,   197,   210,     2,     2,     2,     2,     2,
+       2,   198,     2,   199,   212,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,   216,   211,   217,   203,     2,     2,     2,
+       2,     2,     2,   218,   213,   219,   205,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -681,7 +683,8 @@ static const yytype_uint8 yytranslate[] =
      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,   191,   192,   193
+     185,   186,   187,   188,   189,   190,   191,   192,   193,   194,
+     195
 };
 
 #if YYDEBUG
@@ -690,151 +693,158 @@ static const yytype_uint8 yytranslate[] =
 static const yytype_uint16 yyprhs[] =
 {
        0,     0,     3,     4,     9,    10,    14,    17,    20,    23,
-      26,    29,    30,    33,    39,    41,    44,    46,    48,    50,
-      52,    54,    56,    60,    62,    67,    69,    73,    76,    79,
-      81,    83,    85,    89,    92,    95,    98,   100,   103,   107,
-     110,   112,   114,   116,   118,   121,   124,   127,   129,   131,
-     133,   135,   137,   141,   145,   149,   151,   155,   159,   161,
-     165,   169,   171,   175,   179,   183,   187,   189,   193,   197,
-     199,   203,   205,   209,   211,   215,   217,   221,   223,   227,
-     229,   233,   235,   241,   243,   247,   249,   251,   253,   255,
-     257,   259,   261,   263,   265,   267,   269,   271,   275,   277,
-     280,   283,   288,   291,   293,   295,   298,   302,   306,   309,
-     315,   319,   322,   326,   329,   330,   332,   334,   336,   338,
-     340,   344,   350,   357,   365,   374,   380,   382,   385,   390,
-     396,   403,   411,   416,   419,   421,   424,   429,   431,   435,
-     437,   441,   443,   445,   447,   449,   451,   453,   456,   458,
-     461,   464,   468,   470,   472,   474,   476,   479,   481,   483,
-     486,   489,   491,   493,   496,   498,   502,   507,   509,   511,
-     513,   515,   517,   519,   521,   523,   525,   527,   529,   531,
-     533,   535,   537,   539,   541,   543,   545,   547,   549,   551,
-     553,   555,   557,   559,   561,   563,   565,   567,   569,   571,
-     573,   575,   577,   579,   581,   583,   585,   587,   589,   591,
-     593,   595,   597,   599,   601,   603,   605,   607,   609,   611,
-     613,   615,   617,   619,   621,   627,   632,   634,   637,   641,
-     643,   647,   649,   654,   656,   658,   660,   662,   664,   666,
-     668,   670,   672,   674,   676,   679,   683,   685,   687,   690,
-     694,   696,   699,   701,   704,   710,   714,   716,   718,   723,
-     729,   733,   736,   742,   750,   757,   759,   761,   763,   764,
-     767,   771,   774,   777,   780,   784,   787,   789,   791,   793
+      26,    29,    30,    33,    35,    37,    39,    45,    47,    50,
+      52,    54,    56,    58,    60,    62,    64,    68,    70,    75,
+      77,    81,    84,    87,    89,    91,    93,    97,   100,   103,
+     106,   108,   111,   115,   118,   120,   122,   124,   127,   130,
+     133,   135,   138,   142,   145,   147,   150,   153,   156,   158,
+     160,   162,   164,   166,   170,   174,   178,   180,   184,   188,
+     190,   194,   198,   200,   204,   208,   212,   216,   218,   222,
+     226,   228,   232,   234,   238,   240,   244,   246,   250,   252,
+     256,   258,   262,   264,   270,   272,   276,   278,   280,   282,
+     284,   286,   288,   290,   292,   294,   296,   298,   300,   304,
+     306,   309,   312,   317,   320,   322,   324,   327,   331,   335,
+     338,   344,   348,   351,   355,   358,   359,   361,   363,   365,
+     367,   369,   373,   379,   386,   394,   403,   409,   411,   414,
+     419,   425,   432,   440,   445,   448,   450,   453,   458,   460,
+     464,   466,   470,   472,   474,   476,   478,   480,   482,   485,
+     487,   490,   493,   497,   499,   501,   503,   505,   508,   510,
+     512,   515,   518,   520,   522,   525,   527,   531,   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,   608,   610,   612,   614,   616,   618,
+     620,   622,   624,   626,   628,   630,   632,   634,   636,   638,
+     640,   642,   644,   646,   648,   650,   656,   661,   663,   666,
+     670,   672,   676,   678,   683,   685,   687,   689,   691,   693,
+     695,   697,   699,   701,   703,   705,   708,   709,   714,   716,
+     718,   721,   725,   727,   730,   732,   735,   741,   745,   747,
+     749,   754,   760,   764,   767,   773,   781,   788,   790,   792,
+     794,   795,   798,   802,   805,   808,   811,   815,   818,   820,
+     822,   824
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int16 yyrhs[] =
 {
-     219,     0,    -1,    -1,   221,   223,   220,   225,    -1,    -1,
-     109,    78,   113,    -1,   116,   113,    -1,   117,   113,    -1,
-     118,   113,    -1,   119,   113,    -1,   120,   113,    -1,    -1,
-     223,   224,    -1,   110,    76,   112,    76,   113,    -1,   303,
-      -1,   225,   303,    -1,    76,    -1,   226,    -1,    78,    -1,
-      79,    -1,    77,    -1,    80,    -1,   194,   253,   195,    -1,
-     227,    -1,   228,   196,   229,   197,    -1,   230,    -1,   228,
-     198,    76,    -1,   228,    84,    -1,   228,    85,    -1,   253,
-      -1,   231,    -1,   232,    -1,   228,   198,   232,    -1,   234,
-     195,    -1,   233,   195,    -1,   235,    74,    -1,   235,    -1,
-     235,   251,    -1,   234,   199,   251,    -1,   236,   194,    -1,
-     274,    -1,    76,    -1,    81,    -1,   228,    -1,    84,   237,
-      -1,    85,   237,    -1,   238,   237,    -1,   200,    -1,   201,
-      -1,   202,    -1,   203,    -1,   237,    -1,   239,   204,   237,
-      -1,   239,   205,   237,    -1,   239,   206,   237,    -1,   239,
-      -1,   240,   200,   239,    -1,   240,   201,   239,    -1,   240,
-      -1,   241,    82,   240,    -1,   241,    83,   240,    -1,   241,
-      -1,   242,   207,   241,    -1,   242,   208,   241,    -1,   242,
-      86,   241,    -1,   242,    87,   241,    -1,   242,    -1,   243,
-      88,   242,    -1,   243,    89,   242,    -1,   243,    -1,   244,
-     209,   243,    -1,   244,    -1,   245,   210,   244,    -1,   245,
-      -1,   246,   211,   245,    -1,   246,    -1,   247,    90,   246,
-      -1,   247,    -1,   248,    92,   247,    -1,   248,    -1,   249,
-      91,   248,    -1,   249,    -1,   249,   212,   253,   213,   251,
-      -1,   250,    -1,   237,   252,   251,    -1,   214,    -1,    93,
-      -1,    94,    -1,    96,    -1,    95,    -1,   102,    -1,    97,
-      -1,    98,    -1,    99,    -1,   100,    -1,   101,    -1,   251,
-      -1,   253,   199,   251,    -1,   250,    -1,   256,   215,    -1,
-     264,   215,    -1,   108,   278,   275,   215,    -1,   257,   195,
-      -1,   259,    -1,   258,    -1,   259,   261,    -1,   258,   199,
-     261,    -1,   266,    76,   194,    -1,   274,    76,    -1,   274,
-      76,   196,   254,   197,    -1,   271,   262,   260,    -1,   262,
-     260,    -1,   271,   262,   263,    -1,   262,   263,    -1,    -1,
-      33,    -1,    34,    -1,    35,    -1,   274,    -1,   265,    -1,
-     264,   199,    76,    -1,   264,   199,    76,   196,   197,    -1,
-     264,   199,    76,   196,   254,   197,    -1,   264,   199,    76,
-     196,   197,   214,   284,    -1,   264,   199,    76,   196,   254,
-     197,   214,   284,    -1,   264,   199,    76,   214,   284,    -1,
-     266,    -1,   266,    76,    -1,   266,    76,   196,   197,    -1,
-     266,    76,   196,   254,   197,    -1,   266,    76,   196,   197,
-     214,   284,    -1,   266,    76,   196,   254,   197,   214,   284,
-      -1,   266,    76,   214,   284,    -1,   103,    76,    -1,   274,
-      -1,   272,   274,    -1,   121,   194,   268,   195,    -1,   269,
-      -1,   268,   199,   269,    -1,    76,    -1,    76,   214,    78,
-      -1,    40,    -1,    39,    -1,    38,    -1,     4,    -1,   273,
-      -1,   267,    -1,   267,   273,    -1,   270,    -1,   270,   273,
-      -1,   103,   273,    -1,   103,   270,   273,    -1,   103,    -1,
-       4,    -1,     3,    -1,    37,    -1,    32,    37,    -1,    33,
-      -1,    34,    -1,    32,    33,    -1,    32,    34,    -1,    36,
-      -1,   275,    -1,   278,   275,    -1,   276,    -1,   276,   196,
-     197,    -1,   276,   196,   254,   197,    -1,   277,    -1,   279,
-      -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,   155,
-      -1,    52,    -1,    53,    -1,    54,    -1,    55,    -1,   157,
-      -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,   216,   280,   217,    -1,    73,   216,   280,
-     217,    -1,   281,    -1,   280,   281,    -1,   274,   282,   215,
-      -1,   283,    -1,   282,   199,   283,    -1,    76,    -1,    76,
-     196,   254,   197,    -1,   251,    -1,   255,    -1,   288,    -1,
-     287,    -1,   285,    -1,   292,    -1,   293,    -1,   296,    -1,
-     297,    -1,   298,    -1,   302,    -1,   216,   217,    -1,   216,
-     291,   217,    -1,   290,    -1,   287,    -1,   216,   217,    -1,
-     216,   291,   217,    -1,   286,    -1,   291,   286,    -1,   215,
-      -1,   253,   215,    -1,    14,   194,   253,   195,   294,    -1,
-     286,    12,   286,    -1,   286,    -1,   253,    -1,   266,    76,
-     214,   284,    -1,    17,   194,   253,   195,   288,    -1,    18,
-     253,   213,    -1,    19,   213,    -1,    75,   194,   295,   195,
-     289,    -1,    11,   286,    75,   194,   253,   195,   215,    -1,
-      13,   194,   299,   301,   195,   289,    -1,   292,    -1,   285,
-      -1,   295,    -1,    -1,   300,   215,    -1,   300,   215,   253,
-      -1,    10,   215,    -1,     9,   215,    -1,    16,   215,    -1,
-      16,   253,   215,    -1,    15,   215,    -1,   304,    -1,   255,
-      -1,   222,    -1,   256,   290,    -1
+     221,     0,    -1,    -1,   223,   225,   222,   228,    -1,    -1,
+     111,    80,   115,    -1,   118,   115,    -1,   119,   115,    -1,
+     120,   115,    -1,   121,   115,    -1,   122,   115,    -1,    -1,
+     225,   227,    -1,    76,    -1,    77,    -1,    78,    -1,   112,
+     226,   114,   226,   115,    -1,   311,    -1,   228,   311,    -1,
+      76,    -1,    78,    -1,   229,    -1,    80,    -1,    81,    -1,
+      79,    -1,    82,    -1,   196,   260,   197,    -1,   230,    -1,
+     231,   198,   232,   199,    -1,   233,    -1,   231,   200,   226,
+      -1,   231,    86,    -1,   231,    87,    -1,   260,    -1,   234,
+      -1,   235,    -1,   231,   200,   240,    -1,   237,   197,    -1,
+     236,   197,    -1,   238,    74,    -1,   238,    -1,   238,   258,
+      -1,   237,   201,   258,    -1,   239,   196,    -1,   281,    -1,
+     229,    -1,    83,    -1,   242,   197,    -1,   241,   197,    -1,
+     243,    74,    -1,   243,    -1,   243,   258,    -1,   242,   201,
+     258,    -1,   229,   196,    -1,   231,    -1,    86,   244,    -1,
+      87,   244,    -1,   245,   244,    -1,   202,    -1,   203,    -1,
+     204,    -1,   205,    -1,   244,    -1,   246,   206,   244,    -1,
+     246,   207,   244,    -1,   246,   208,   244,    -1,   246,    -1,
+     247,   202,   246,    -1,   247,   203,   246,    -1,   247,    -1,
+     248,    84,   247,    -1,   248,    85,   247,    -1,   248,    -1,
+     249,   209,   248,    -1,   249,   210,   248,    -1,   249,    88,
+     248,    -1,   249,    89,   248,    -1,   249,    -1,   250,    90,
+     249,    -1,   250,    91,   249,    -1,   250,    -1,   251,   211,
+     250,    -1,   251,    -1,   252,   212,   251,    -1,   252,    -1,
+     253,   213,   252,    -1,   253,    -1,   254,    92,   253,    -1,
+     254,    -1,   255,    94,   254,    -1,   255,    -1,   256,    93,
+     255,    -1,   256,    -1,   256,   214,   260,   215,   258,    -1,
+     257,    -1,   244,   259,   258,    -1,   216,    -1,    95,    -1,
+      96,    -1,    98,    -1,    97,    -1,   104,    -1,    99,    -1,
+     100,    -1,   101,    -1,   102,    -1,   103,    -1,   258,    -1,
+     260,   201,   258,    -1,   257,    -1,   263,   217,    -1,   271,
+     217,    -1,   110,   285,   282,   217,    -1,   264,   197,    -1,
+     266,    -1,   265,    -1,   266,   268,    -1,   265,   201,   268,
+      -1,   273,   229,   196,    -1,   281,   226,    -1,   281,   226,
+     198,   261,   199,    -1,   278,   269,   267,    -1,   269,   267,
+      -1,   278,   269,   270,    -1,   269,   270,    -1,    -1,    33,
+      -1,    34,    -1,    35,    -1,   281,    -1,   272,    -1,   271,
+     201,   226,    -1,   271,   201,   226,   198,   199,    -1,   271,
+     201,   226,   198,   261,   199,    -1,   271,   201,   226,   198,
+     199,   216,   291,    -1,   271,   201,   226,   198,   261,   199,
+     216,   291,    -1,   271,   201,   226,   216,   291,    -1,   273,
+      -1,   273,   226,    -1,   273,   226,   198,   199,    -1,   273,
+     226,   198,   261,   199,    -1,   273,   226,   198,   199,   216,
+     291,    -1,   273,   226,   198,   261,   199,   216,   291,    -1,
+     273,   226,   216,   291,    -1,   105,   229,    -1,   281,    -1,
+     279,   281,    -1,   123,   196,   275,   197,    -1,   276,    -1,
+     275,   201,   276,    -1,   226,    -1,   226,   216,    80,    -1,
+      40,    -1,    39,    -1,    38,    -1,     4,    -1,   280,    -1,
+     274,    -1,   274,   280,    -1,   277,    -1,   277,   280,    -1,
+     105,   280,    -1,   105,   277,   280,    -1,   105,    -1,     4,
+      -1,     3,    -1,    37,    -1,    32,    37,    -1,    33,    -1,
+      34,    -1,    32,    33,    -1,    32,    34,    -1,    36,    -1,
+     282,    -1,   285,   282,    -1,   283,    -1,   283,   198,   199,
+      -1,   283,   198,   261,   199,    -1,   284,    -1,   286,    -1,
+      77,    -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,   157,    -1,
+      52,    -1,    53,    -1,    54,    -1,    55,    -1,   159,    -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,   108,    -1,   107,    -1,   106,    -1,
+      73,   226,   218,   287,   219,    -1,    73,   218,   287,   219,
+      -1,   288,    -1,   287,   288,    -1,   281,   289,   217,    -1,
+     290,    -1,   289,   201,   290,    -1,   226,    -1,   226,   198,
+     261,   199,    -1,   258,    -1,   262,    -1,   295,    -1,   294,
+      -1,   292,    -1,   300,    -1,   301,    -1,   304,    -1,   305,
+      -1,   306,    -1,   310,    -1,   218,   219,    -1,    -1,   218,
+     296,   299,   219,    -1,   298,    -1,   294,    -1,   218,   219,
+      -1,   218,   299,   219,    -1,   293,    -1,   299,   293,    -1,
+     217,    -1,   260,   217,    -1,    14,   196,   260,   197,   302,
+      -1,   293,    12,   293,    -1,   293,    -1,   260,    -1,   273,
+     226,   216,   291,    -1,    17,   196,   260,   197,   295,    -1,
+      18,   260,   215,    -1,    19,   215,    -1,    75,   196,   303,
+     197,   297,    -1,    11,   293,    75,   196,   260,   197,   217,
+      -1,    13,   196,   307,   309,   197,   297,    -1,   300,    -1,
+     292,    -1,   303,    -1,    -1,   308,   217,    -1,   308,   217,
+     260,    -1,    10,   217,    -1,     9,   217,    -1,    16,   217,
+      -1,    16,   260,   217,    -1,    15,   217,    -1,   312,    -1,
+     262,    -1,   224,    -1,   263,   298,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   213,   213,   212,   219,   221,   246,   247,   248,   249,
-     250,   262,   264,   268,   277,   285,   296,   300,   307,   314,
-     321,   328,   335,   342,   343,   349,   353,   360,   366,   375,
-     379,   383,   384,   393,   394,   398,   399,   403,   409,   421,
-     425,   431,   438,   449,   450,   456,   462,   472,   473,   474,
-     475,   479,   480,   486,   492,   501,   502,   508,   517,   518,
-     524,   533,   534,   540,   546,   552,   561,   562,   568,   577,
-     578,   587,   588,   597,   598,   607,   608,   617,   618,   627,
-     628,   637,   638,   647,   648,   657,   658,   659,   660,   661,
-     662,   663,   664,   665,   666,   667,   671,   675,   691,   695,
-     699,   703,   712,   716,   717,   721,   726,   734,   745,   755,
-     770,   777,   782,   793,   806,   809,   814,   819,   828,   832,
-     833,   842,   851,   860,   869,   878,   891,   902,   911,   920,
-     929,   938,   947,   956,   970,   977,   988,   995,   996,  1015,
-    1044,  1085,  1090,  1095,  1103,  1111,  1112,  1113,  1118,  1119,
-    1124,  1129,  1135,  1143,  1148,  1153,  1158,  1164,  1169,  1174,
-    1179,  1184,  1192,  1196,  1204,  1205,  1211,  1220,  1226,  1232,
-    1241,  1242,  1243,  1244,  1245,  1246,  1247,  1248,  1249,  1250,
-    1251,  1252,  1253,  1254,  1255,  1256,  1257,  1258,  1259,  1260,
-    1261,  1262,  1263,  1264,  1265,  1266,  1267,  1268,  1269,  1270,
-    1271,  1272,  1273,  1274,  1275,  1276,  1277,  1278,  1279,  1280,
-    1281,  1282,  1283,  1284,  1285,  1286,  1287,  1288,  1289,  1290,
-    1291,  1295,  1305,  1315,  1328,  1334,  1343,  1348,  1356,  1371,
-    1376,  1384,  1390,  1399,  1403,  1409,  1410,  1414,  1415,  1416,
-    1417,  1418,  1419,  1420,  1424,  1430,  1439,  1440,  1444,  1450,
-    1459,  1469,  1481,  1487,  1496,  1505,  1510,  1518,  1522,  1536,
-    1540,  1541,  1545,  1552,  1559,  1569,  1570,  1574,  1576,  1582,
-    1587,  1596,  1602,  1608,  1614,  1620,  1629,  1630,  1631,  1635
+       0,   218,   218,   217,   229,   231,   271,   272,   273,   274,
+     275,   287,   289,   293,   294,   295,   299,   308,   316,   327,
+     328,   332,   339,   346,   353,   360,   367,   374,   375,   381,
+     385,   392,   398,   407,   411,   415,   416,   425,   426,   430,
+     431,   435,   441,   453,   457,   463,   470,   480,   481,   485,
+     486,   490,   496,   508,   519,   520,   526,   532,   542,   543,
+     544,   545,   549,   550,   556,   562,   571,   572,   578,   587,
+     588,   594,   603,   604,   610,   616,   622,   631,   632,   638,
+     647,   648,   657,   658,   667,   668,   677,   678,   687,   688,
+     697,   698,   707,   708,   717,   718,   727,   728,   729,   730,
+     731,   732,   733,   734,   735,   736,   737,   741,   745,   761,
+     765,   770,   774,   783,   787,   788,   792,   797,   805,   819,
+     829,   844,   851,   856,   867,   880,   883,   888,   893,   902,
+     906,   907,   917,   927,   937,   947,   957,   971,   982,   991,
+    1000,  1009,  1018,  1027,  1036,  1050,  1057,  1068,  1075,  1076,
+    1095,  1147,  1188,  1193,  1198,  1206,  1214,  1215,  1216,  1221,
+    1222,  1227,  1232,  1238,  1246,  1251,  1256,  1261,  1267,  1272,
+    1277,  1282,  1287,  1295,  1299,  1307,  1308,  1314,  1323,  1329,
+    1335,  1344,  1345,  1346,  1347,  1348,  1349,  1350,  1351,  1352,
+    1353,  1354,  1355,  1356,  1357,  1358,  1359,  1360,  1361,  1362,
+    1363,  1364,  1365,  1366,  1367,  1368,  1369,  1370,  1371,  1372,
+    1373,  1374,  1375,  1376,  1377,  1378,  1379,  1380,  1381,  1382,
+    1383,  1384,  1385,  1386,  1387,  1388,  1389,  1390,  1391,  1392,
+    1393,  1394,  1398,  1408,  1418,  1431,  1438,  1447,  1452,  1460,
+    1475,  1480,  1488,  1495,  1504,  1508,  1514,  1515,  1519,  1520,
+    1521,  1522,  1523,  1524,  1525,  1529,  1536,  1535,  1549,  1550,
+    1554,  1560,  1569,  1579,  1591,  1597,  1606,  1615,  1620,  1628,
+    1632,  1646,  1650,  1651,  1655,  1662,  1669,  1679,  1680,  1684,
+    1686,  1692,  1697,  1706,  1712,  1718,  1724,  1730,  1739,  1740,
+    1741,  1745
 };
 #endif
 
@@ -857,38 +867,41 @@ static const char *const yytname[] =
   "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", "PRAGMA_INVARIANT_ALL", "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", "IMAGE1DARRAYSHADOW", "IMAGE2DARRAYSHADOW", "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",
+  "TYPE_IDENTIFIER", "NEW_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", "PRAGMA_INVARIANT_ALL",
+  "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", "IMAGE1DARRAYSHADOW",
+  "IMAGE2DARRAYSHADOW", "ROW_MAJOR", "'('", "')'", "'['", "']'", "'.'",
+  "','", "'+'", "'-'", "'!'", "'~'", "'*'", "'/'", "'%'", "'<'", "'>'",
+  "'&'", "'^'", "'|'", "'?'", "':'", "'='", "';'", "'{'", "'}'", "$accept",
+  "translation_unit", "$@1", "version_statement", "pragma_statement",
+  "extension_statement_list", "any_identifier", "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",
+  "function_identifier", "method_call_generic",
+  "method_call_header_no_parameters", "method_call_header_with_parameters",
+  "method_call_header", "unary_expression", "unary_operator",
   "multiplicative_expression", "additive_expression", "shift_expression",
   "relational_expression", "equality_expression", "and_expression",
   "exclusive_or_expression", "inclusive_or_expression",
@@ -907,7 +920,7 @@ static const char *const yytname[] =
   "precision_qualifier", "struct_specifier", "struct_declaration_list",
   "struct_declaration", "struct_declarator_list", "struct_declarator",
   "initializer", "declaration_statement", "statement", "simple_statement",
-  "compound_statement", "statement_no_new_scope",
+  "compound_statement", "$@2", "statement_no_new_scope",
   "compound_statement_no_new_scope", "statement_list",
   "expression_statement", "selection_statement",
   "selection_rest_statement", "condition", "switch_statement",
@@ -941,76 +954,80 @@ static const yytype_uint16 yytoknum[] =
      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,   446,   447,   448,    40,    41,    91,    93,    46,    44,
-      43,    45,    33,   126,    42,    47,    37,    60,    62,    38,
-      94,   124,    63,    58,    61,    59,   123,   125
+     445,   446,   447,   448,   449,   450,    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,   218,   220,   219,   221,   221,   222,   222,   222,   222,
-     222,   223,   223,   224,   225,   225,   226,   227,   227,   227,
-     227,   227,   227,   228,   228,   228,   228,   228,   228,   229,
-     230,   231,   231,   232,   232,   233,   233,   234,   234,   235,
-     236,   236,   236,   237,   237,   237,   237,   238,   238,   238,
-     238,   239,   239,   239,   239,   240,   240,   240,   241,   241,
-     241,   242,   242,   242,   242,   242,   243,   243,   243,   244,
-     244,   245,   245,   246,   246,   247,   247,   248,   248,   249,
-     249,   250,   250,   251,   251,   252,   252,   252,   252,   252,
-     252,   252,   252,   252,   252,   252,   253,   253,   254,   255,
-     255,   255,   256,   257,   257,   258,   258,   259,   260,   260,
-     261,   261,   261,   261,   262,   262,   262,   262,   263,   264,
-     264,   264,   264,   264,   264,   264,   265,   265,   265,   265,
-     265,   265,   265,   265,   266,   266,   267,   268,   268,   269,
-     269,   270,   270,   270,   271,   272,   272,   272,   272,   272,
-     272,   272,   272,   273,   273,   273,   273,   273,   273,   273,
-     273,   273,   274,   274,   275,   275,   275,   276,   276,   276,
-     277,   277,   277,   277,   277,   277,   277,   277,   277,   277,
-     277,   277,   277,   277,   277,   277,   277,   277,   277,   277,
-     277,   277,   277,   277,   277,   277,   277,   277,   277,   277,
-     277,   277,   277,   277,   277,   277,   277,   277,   277,   277,
-     277,   277,   277,   277,   277,   277,   277,   277,   277,   277,
-     277,   278,   278,   278,   279,   279,   280,   280,   281,   282,
-     282,   283,   283,   284,   285,   286,   286,   287,   287,   287,
-     287,   287,   287,   287,   288,   288,   289,   289,   290,   290,
-     291,   291,   292,   292,   293,   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
+       0,   220,   222,   221,   223,   223,   224,   224,   224,   224,
+     224,   225,   225,   226,   226,   226,   227,   228,   228,   229,
+     229,   230,   230,   230,   230,   230,   230,   231,   231,   231,
+     231,   231,   231,   232,   233,   234,   234,   235,   235,   236,
+     236,   237,   237,   238,   239,   239,   239,   240,   240,   241,
+     241,   242,   242,   243,   244,   244,   244,   244,   245,   245,
+     245,   245,   246,   246,   246,   246,   247,   247,   247,   248,
+     248,   248,   249,   249,   249,   249,   249,   250,   250,   250,
+     251,   251,   252,   252,   253,   253,   254,   254,   255,   255,
+     256,   256,   257,   257,   258,   258,   259,   259,   259,   259,
+     259,   259,   259,   259,   259,   259,   259,   260,   260,   261,
+     262,   262,   262,   263,   264,   264,   265,   265,   266,   267,
+     267,   268,   268,   268,   268,   269,   269,   269,   269,   270,
+     271,   271,   271,   271,   271,   271,   271,   272,   272,   272,
+     272,   272,   272,   272,   272,   273,   273,   274,   275,   275,
+     276,   276,   277,   277,   277,   278,   279,   279,   279,   279,
+     279,   279,   279,   279,   280,   280,   280,   280,   280,   280,
+     280,   280,   280,   281,   281,   282,   282,   282,   283,   283,
+     283,   284,   284,   284,   284,   284,   284,   284,   284,   284,
+     284,   284,   284,   284,   284,   284,   284,   284,   284,   284,
+     284,   284,   284,   284,   284,   284,   284,   284,   284,   284,
+     284,   284,   284,   284,   284,   284,   284,   284,   284,   284,
+     284,   284,   284,   284,   284,   284,   284,   284,   284,   284,
+     284,   284,   285,   285,   285,   286,   286,   287,   287,   288,
+     289,   289,   290,   290,   291,   292,   293,   293,   294,   294,
+     294,   294,   294,   294,   294,   295,   296,   295,   297,   297,
+     298,   298,   299,   299,   300,   300,   301,   302,   302,   303,
+     303,   304,   305,   305,   306,   306,   306,   307,   307,   308,
+     308,   309,   309,   310,   310,   310,   310,   310,   311,   311,
+     311,   312
 };
 
 /* 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,
-       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,     4,     1,     3,     1,
-       3,     1,     1,     1,     1,     1,     1,     2,     1,     2,
-       2,     3,     1,     1,     1,     1,     2,     1,     1,     2,
-       2,     1,     1,     2,     1,     3,     4,     1,     1,     1,
+       2,     0,     2,     1,     1,     1,     5,     1,     2,     1,
+       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,     2,     2,     2,
+       1,     2,     3,     2,     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,     4,     1,     3,
+       1,     3,     1,     1,     1,     1,     1,     1,     2,     1,
+       2,     2,     3,     1,     1,     1,     1,     2,     1,     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,     5,     4,     1,     2,     3,     1,
-       3,     1,     4,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     2,     3,     1,     1,     2,     3,
-       1,     2,     1,     2,     5,     3,     1,     1,     4,     5,
-       3,     2,     5,     7,     6,     1,     1,     1,     0,     2,
-       3,     2,     2,     2,     3,     2,     1,     1,     1,     2
+       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,     2,     0,     4,     1,     1,
+       2,     3,     1,     2,     1,     2,     5,     3,     1,     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
@@ -1019,637 +1036,620 @@ static const yytype_uint8 yyr2[] =
 static const yytype_uint16 yydefact[] =
 {
        4,     0,     0,    11,     0,     1,     2,     5,     0,     0,
-      12,     0,   154,   153,   174,   171,   172,   173,   178,   179,
-     180,   181,   182,   183,   184,   185,   186,   175,   176,   177,
-       0,   157,   158,   161,   155,   143,   142,   141,   187,   188,
-     189,   190,   191,   192,   193,   194,   195,   196,   197,   199,
-     200,   201,   202,   204,   205,   206,   207,   208,   209,   210,
-     211,   212,   213,   214,   215,   216,   217,   218,   219,   220,
-       0,   170,   169,   152,   223,   222,   221,     0,     0,     0,
-       0,     0,     0,     0,   198,   203,   278,     3,   277,     0,
-       0,   104,   114,     0,   119,   126,   146,   148,     0,   145,
-     134,   162,   164,   167,     0,   168,    14,   276,     0,   159,
-     160,   156,     0,     0,   133,     0,   150,     0,     6,     7,
-       8,     9,    10,     0,    15,    99,     0,   279,   102,   114,
-     144,   115,   116,   117,   105,     0,   114,     0,   100,   127,
-     147,   149,   135,     0,   163,     0,     0,     0,     0,   226,
-     151,     0,   139,     0,   137,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,    16,    20,    18,    19,
-      21,    42,     0,     0,     0,    47,    48,    49,    50,   252,
-       0,   248,    17,    23,    43,    25,    30,    31,     0,     0,
-      36,     0,    51,     0,    55,    58,    61,    66,    69,    71,
-      73,    75,    77,    79,    81,    83,    96,     0,   234,     0,
-     134,   237,   250,   236,   235,     0,   238,   239,   240,   241,
-     242,   243,   106,   111,   113,   118,     0,   120,   107,     0,
-       0,   165,    51,    98,     0,    40,    13,     0,   231,     0,
-     229,   225,   227,   101,     0,   136,     0,   272,   271,     0,
-       0,     0,   275,   273,     0,     0,     0,   261,     0,    44,
-      45,     0,   244,     0,    27,    28,     0,     0,    34,    33,
-       0,   170,    37,    39,    86,    87,    89,    88,    91,    92,
-      93,    94,    95,    90,    85,     0,    46,     0,     0,     0,
+      12,    13,    14,    15,     0,   165,   164,   185,   182,   183,
+     184,   189,   190,   191,   192,   193,   194,   195,   196,   197,
+     186,   187,   188,     0,   168,   169,   172,   166,   154,   153,
+     152,   198,   199,   200,   201,   202,   203,   204,   205,   206,
+     207,   208,   210,   211,   212,   213,   215,   216,   217,   218,
+     219,   220,   221,   222,   223,   224,   225,   226,   227,   228,
+     229,   230,   231,     0,   181,   180,   163,   234,   233,   232,
+       0,     0,     0,     0,     0,     0,     0,   209,   214,   290,
+       3,   289,     0,     0,   115,   125,     0,   130,   137,   157,
+     159,     0,   156,   145,   173,   175,   178,     0,   179,    17,
+     288,     0,   170,   171,   167,     0,     0,    19,    20,   144,
+       0,   161,     0,     6,     7,     8,     9,    10,     0,    18,
+     110,     0,   291,   113,   125,   155,   126,   127,   128,   116,
+       0,   125,     0,   111,    13,    15,   138,     0,   158,   160,
+     146,     0,   174,     0,     0,     0,   237,     0,   162,     0,
+     150,     0,   148,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    24,    22,    23,    25,    46,     0,
+       0,     0,    58,    59,    60,    61,   264,   256,   260,    21,
+      27,    54,    29,    34,    35,     0,     0,    40,     0,    62,
+       0,    66,    69,    72,    77,    80,    82,    84,    86,    88,
+      90,    92,    94,   107,     0,   245,     0,   145,   248,   262,
+     247,   246,     0,   249,   250,   251,   252,   253,   254,   117,
+     122,   124,   129,     0,   131,     0,     0,   118,   176,    62,
+     109,     0,    44,    16,   242,     0,   240,   236,   238,     0,
+     112,     0,   147,     0,   284,   283,     0,     0,     0,   287,
+     285,     0,     0,     0,   273,     0,    55,    56,     0,   255,
+       0,    31,    32,     0,     0,    38,    37,     0,   181,    41,
+      43,    97,    98,   100,    99,   102,   103,   104,   105,   106,
+     101,    96,     0,    57,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   253,   249,
-     251,   108,   110,   112,     0,     0,   128,     0,   233,   132,
-     166,   224,     0,     0,   228,   140,   138,     0,   266,   265,
-     268,     0,   274,     0,   260,   152,   257,     0,     0,    22,
-     245,     0,    29,    26,    32,    38,    84,    52,    53,    54,
-      56,    57,    59,    60,    64,    65,    62,    63,    67,    68,
-      70,    72,    74,    76,    78,    80,     0,    97,     0,   121,
-       0,   125,     0,   129,     0,   230,     0,   267,     0,     0,
-       0,     0,     0,     0,    24,     0,     0,     0,   122,   130,
-       0,   232,     0,   269,     0,   256,   254,   259,     0,   247,
-     262,   246,    82,   109,   123,     0,   131,     0,   270,   264,
-       0,   258,   124,   263,   255
+       0,     0,     0,     0,     0,   265,   261,   263,   119,   121,
+     123,     0,     0,   139,     0,   244,   143,   177,     0,     0,
+     239,   235,   151,   149,     0,   278,   277,   280,     0,   286,
+       0,   272,   163,   269,     0,     0,    26,     0,     0,    33,
+      30,     0,    36,     0,     0,    50,    42,    95,    63,    64,
+      65,    67,    68,    70,    71,    75,    76,    73,    74,    78,
+      79,    81,    83,    85,    87,    89,    91,     0,   108,     0,
+     132,     0,   136,     0,   140,     0,   241,     0,   279,     0,
+       0,     0,     0,     0,     0,   257,    28,    53,    48,    47,
+       0,   181,    51,     0,     0,     0,   133,   141,     0,   243,
+       0,   281,     0,   268,   266,   271,     0,   259,   274,   258,
+      52,    93,   120,   134,     0,   142,     0,   282,   276,     0,
+     270,   135,   275,   267
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     2,     9,     3,    86,     6,    10,    87,   182,   183,
-     184,   341,   185,   186,   187,   188,   189,   190,   191,   192,
-     193,   194,   195,   196,   197,   198,   199,   200,   201,   202,
-     203,   204,   205,   206,   285,   207,   234,   208,   209,    90,
-      91,    92,   223,   134,   135,   224,    93,    94,    95,    96,
-     153,   154,    97,   136,    98,    99,   235,   101,   102,   103,
-     104,   105,   148,   149,   239,   240,   319,   211,   212,   213,
-     214,   400,   401,   215,   216,   217,   396,   338,   218,   219,
-     220,   330,   378,   379,   221,   106,   107
+      -1,     2,     9,     3,    89,     6,   160,    10,    90,   189,
+     190,   191,   348,   192,   193,   194,   195,   196,   197,   198,
+     352,   353,   354,   355,   199,   200,   201,   202,   203,   204,
+     205,   206,   207,   208,   209,   210,   211,   212,   213,   292,
+     214,   241,   215,   216,    93,    94,    95,   230,   139,   140,
+     231,    96,    97,    98,    99,   161,   162,   100,   141,   101,
+     102,   242,   104,   105,   106,   107,   108,   155,   156,   245,
+     246,   326,   218,   219,   220,   221,   270,   418,   419,   222,
+     223,   224,   414,   345,   225,   226,   227,   337,   389,   390,
+     228,   109,   110
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -321
+#define YYPACT_NINF -366
 static const yytype_int16 yypact[] =
 {
-     -86,   -57,    45,  -321,   -56,  -321,   -50,  -321,   -10,  3320,
-    -321,   -26,  -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,
-    -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,
-      79,  -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,
-    -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,
-    -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,
-    -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,
-     -70,  -321,  -321,    43,  -321,  -321,  -321,    18,   -22,   -12,
-      -5,     2,    25,  -101,  -321,  -321,  -321,  3320,  -321,   -43,
-     -55,   -54,     6,  -148,  -321,    52,   211,   211,  3509,  -321,
-    -321,  -321,   -47,  -321,  3581,  -321,  -321,  -321,   110,  -321,
-    -321,  -321,   -14,  3509,  -321,   211,  -321,  3581,  -321,  -321,
-    -321,  -321,  -321,   131,  -321,  -321,   389,  -321,  -321,    15,
-    -321,  -321,  -321,  -321,  -321,  3509,   109,   136,  -321,  -152,
-    -321,  -321,  -321,  2400,  -321,   105,  3509,   143,  1781,  -321,
-    -321,     7,     9,  -107,  -321,    10,    12,  1249,    27,    36,
-      17,  2015,    40,  2952,    22,    42,   -65,  -321,  -321,  -321,
-    -321,  -321,  2952,  2952,  2952,  -321,  -321,  -321,  -321,  -321,
-     604,  -321,  -321,  -321,   -20,  -321,  -321,  -321,    47,   -92,
-    3136,    46,   -67,  2952,   -24,   -16,   111,   -73,   108,    37,
-      41,    39,   162,   161,   -82,  -321,  -321,  -147,  -321,    44,
-      61,  -321,  -321,  -321,  -321,   819,  -321,  -321,  -321,  -321,
-    -321,  -321,  -321,  -321,  -321,   181,  3509,  -160,  -321,  2584,
-    2952,  -321,  -321,  -321,    63,  -321,  -321,  1898,    62,  -146,
-    -321,  -321,  -321,  -321,   183,  -321,   131,  -321,  -321,   187,
-    1664,  2952,  -321,  -321,  -144,  2952,  -140,  -321,  2216,  -321,
-    -321,   -81,  -321,  1034,  -321,  -321,  2952,  3437,  -321,  -321,
-    2952,    70,  -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,
-    -321,  -321,  -321,  -321,  -321,  2952,  -321,  2952,  2952,  2952,
-    2952,  2952,  2952,  2952,  2952,  2952,  2952,  2952,  2952,  2952,
-    2952,  2952,  2952,  2952,  2952,  2952,  2952,  2952,  -321,  -321,
-    -321,    74,  -321,  -321,  2768,  2952,    64,    69,  -321,  -321,
-    -321,  -321,  2952,   143,  -321,  -321,  -321,    82,  -321,  -321,
-    2216,   -74,  -321,   -68,  -321,   235,    78,   203,    85,  -321,
-    -321,    84,    78,    88,  -321,  -321,  -321,  -321,  -321,  -321,
-     -24,   -24,   -16,   -16,   111,   111,   111,   111,   -73,   -73,
-     108,    37,    41,    39,   162,   161,  -129,  -321,  2952,    71,
-      86,  -321,  2952,    72,    87,  -321,  2952,  -321,    73,    92,
-    1249,    75,    76,  1463,  -321,  2952,    95,  2952,    80,  -321,
-    2952,  -321,   -63,  2952,  1463,   277,  -321,  -321,  2952,  -321,
-    -321,  -321,  -321,  -321,  -321,  2952,  -321,    81,    78,  -321,
-    1249,  -321,  -321,  -321,  -321
+     -57,   -43,    62,  -366,   -50,  -366,   -30,  -366,    67,  3341,
+    -366,  -366,  -366,  -366,    -6,  -366,  -366,  -366,  -366,  -366,
+    -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,
+    -366,  -366,  -366,     8,  -366,  -366,  -366,  -366,  -366,  -366,
+    -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,
+    -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,
+    -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,
+    -366,  -366,  -366,   -65,  -366,  -366,   226,  -366,  -366,  -366,
+      51,   -31,   -28,     6,    13,    15,   -44,  -366,  -366,  -366,
+    3341,  -366,  -183,   -47,   -29,    18,  -169,  -366,   140,    24,
+      24,  3460,  -366,  -366,  -366,   -24,  -366,  3533,  -366,  -366,
+    -366,    67,  -366,  -366,  -366,  3460,   -48,  -366,  -366,  -366,
+      24,  -366,  3533,  -366,  -366,  -366,  -366,  -366,    67,  -366,
+    -366,   408,  -366,  -366,    55,  -366,  -366,  -366,  -366,  -366,
+    3460,   200,    67,  -366,   -20,   -18,  -178,    23,  -366,  -366,
+    -366,  2225,  -366,    72,    67,  1598,  -366,  3460,  -366,     4,
+      10,   -84,  -366,    11,    14,  1059,    40,    42,    29,  1836,
+      43,  2783,    34,    54,  -366,  -366,  -366,  -366,  -366,  2783,
+    2783,  2783,  -366,  -366,  -366,  -366,  -366,    32,  -366,    56,
+    -366,   -71,  -366,  -366,  -366,    57,   -81,  2969,    61,   -27,
+    2783,    35,   -88,   -41,   -70,    33,    60,    41,    59,   181,
+     180,   -89,  -366,  -366,  -168,  -366,    58,    80,  -366,  -366,
+    -366,  -366,   625,  -366,  -366,  -366,  -366,  -366,  -366,  -366,
+    -366,  -366,    67,  3460,  -177,  2411,  2783,  -366,  -366,  -366,
+    -366,    78,  -366,  -366,    81,  -137,  -366,  -366,  -366,  1717,
+    -366,   201,  -366,    67,  -366,  -366,   205,  1478,  2783,  -366,
+    -366,  -134,  2783,  -115,  -366,  2039,  -366,  -366,   -60,  -366,
+    1059,  -366,  -366,  2783,   140,  -366,  -366,  2783,    85,  -366,
+    -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,
+    -366,  -366,  2783,  -366,  2783,  2783,  2783,  2783,  2783,  2783,
+    2783,  2783,  2783,  2783,  2783,  2783,  2783,  2783,  2783,  2783,
+    2783,  2783,  2783,  2783,  2783,  -366,  -366,  -366,    86,  -366,
+    -366,  2597,  2783,    69,    87,  -366,  -366,  -366,  2783,    67,
+    -366,  -366,  -366,  -366,    91,  -366,  -366,  2039,   -59,  -366,
+     -46,  -366,   129,    88,    67,    93,  -366,   842,    89,    88,
+    -366,    95,  -366,    96,   -37,  3155,  -366,  -366,  -366,  -366,
+    -366,    35,    35,   -88,   -88,   -41,   -41,   -41,   -41,   -70,
+     -70,    33,    60,    41,    59,   181,   180,   -96,  -366,  2783,
+      76,    97,  -366,  2783,    79,    98,  -366,  2783,  -366,    77,
+     101,  1059,    83,    90,  1275,  -366,  -366,  -366,  -366,  -366,
+    2783,   102,  -366,  2783,   108,  2783,    94,  -366,  2783,  -366,
+     -26,  2783,  1275,   297,  -366,  -366,  2783,  -366,  -366,  -366,
+    -366,  -366,  -366,  -366,  2783,  -366,   100,    88,  -366,  1059,
+    -366,  -366,  -366,  -366
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,  -321,
-    -321,  -321,  -321,  -321,    26,  -321,  -321,  -321,  -321,  -135,
-    -321,   -91,   -88,  -106,   -90,    -3,    -6,    -4,    -2,    -1,
-       0,  -321,  -139,  -174,  -321,  -156,  -217,    11,    13,  -321,
-    -321,  -321,    83,   170,   164,    89,  -321,  -321,  -243,  -321,
-    -321,    56,   -71,  -321,  -321,   -72,    -9,   -32,  -321,  -321,
-     227,  -321,   160,  -131,  -321,   -15,  -195,    57,  -154,  -320,
-     -69,   -84,   222,   133,    66,  -321,  -321,   -13,  -321,  -321,
-    -321,  -321,  -321,  -321,  -321,   231,  -321
+    -366,  -366,  -366,  -366,  -366,  -366,    -7,  -366,  -366,   -62,
+    -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,  -366,
+    -366,  -366,  -366,  -366,  -101,  -366,  -113,  -109,  -121,   -61,
+       5,     3,     9,    16,     2,     7,  -366,  -142,  -100,  -366,
+    -164,  -225,    21,    22,  -366,  -366,  -366,    82,   186,   173,
+      92,  -366,  -366,  -242,  -366,  -366,    68,   -73,  -366,  -366,
+     -74,    -9,   -67,  -366,  -366,   243,  -366,   170,  -147,  -366,
+       0,  -298,    73,  -159,  -365,   -58,  -366,   -80,   239,    63,
+      84,  -366,  -366,    -2,  -366,  -366,  -366,  -366,  -366,  -366,
+    -366,   246,  -366
 };
 
 /* 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 -170
+#define YYTABLE_NINF -115
 static const yytype_int16 yytable[] =
 {
-     100,   116,   115,   249,   233,   254,   112,   256,   232,   305,
-     130,  -169,   317,   294,   295,   337,   272,   242,   261,   130,
-      88,     4,    89,     1,   140,   141,   274,   275,   276,   277,
-     278,   279,   280,   281,   282,   283,   314,   259,   260,   131,
-     132,   133,   228,   150,   229,     5,    12,    13,   131,   132,
-     133,   137,   307,   323,   315,   307,   318,     7,   286,   307,
-       8,   310,   230,   399,   264,   265,    11,   138,   308,   324,
-     307,   332,   144,   334,   399,    30,    31,    32,   100,    33,
-      34,    35,    36,    37,   385,   151,   108,   337,   245,   142,
-     233,   118,   246,   123,   232,   331,   345,   370,    88,   333,
-      89,   119,   336,   269,   147,   374,   242,   270,   120,   310,
-     342,   346,   109,   110,   339,   121,   111,   210,   307,   114,
-     371,   380,    74,    75,    76,   307,   225,   381,   139,   -41,
-     306,   307,   407,   367,   296,   297,   307,   147,   122,   147,
-     128,   318,   131,   132,   133,   129,   113,   284,   210,   143,
-     366,   386,   347,   348,   349,   232,   232,   232,   232,   232,
-     232,   232,   232,   232,   232,   232,   232,   232,   232,   232,
-     232,   210,   125,   126,   336,   233,   266,   389,   267,   232,
-     287,   288,   289,   233,   290,   291,   145,   232,   354,   355,
-     356,   357,   404,   292,   293,   406,   298,   299,   318,   350,
-     351,  -103,   146,   411,   352,   353,   210,   152,   358,   359,
-     412,   402,   227,   318,    12,    13,   318,   225,   236,   238,
-     392,   250,   243,   244,   318,   247,   395,   248,   147,   233,
-     251,   318,   252,   232,   255,   257,   258,   408,    12,    13,
-     273,   210,   268,    30,    31,    32,   300,    33,    34,   210,
-     302,   301,   303,   304,   210,   -40,   414,   311,   322,   125,
-     320,   325,   327,   116,   115,   -35,   373,    30,    31,    32,
-     368,    33,    34,    35,    36,    37,   376,   307,   372,   382,
-     383,   384,   -41,   388,   391,   387,   390,   394,   393,   410,
-     398,   180,   403,   344,   405,   361,   413,   360,   362,   222,
-     226,   363,   326,   364,   117,   365,   237,   328,   375,   312,
-     409,   127,   397,   263,     0,   313,   329,   377,   124,     0,
-       0,   210,     0,     0,     0,     0,     0,     0,     0,     0,
+     103,    14,   121,   120,   312,   261,   256,   263,   248,   240,
+     324,    11,    12,    13,   119,   271,   272,   268,   301,   302,
+     235,   321,   135,   344,   382,   148,   149,    15,    16,   417,
+      91,    92,   142,   314,   130,   131,   147,     4,   236,   322,
+     152,   112,   113,   299,   300,   114,   158,   417,   143,   315,
+     239,   136,   137,   138,     1,   159,    33,    34,    35,   135,
+      36,    37,     5,   317,   329,     7,   116,   314,   281,   282,
+     283,   284,   285,   286,   287,   288,   289,   290,   266,   267,
+     330,   103,     8,   339,   123,   407,   314,   124,   136,   137,
+     138,   146,   150,   240,   338,   344,   381,   279,   340,   293,
+     341,   343,   248,   385,   153,   314,   154,   423,   111,   349,
+     425,    91,    92,   252,   297,   298,   276,   253,   430,   403,
+     277,   125,   217,   305,   306,   313,   431,   273,   126,   274,
+     127,   232,    15,    16,   239,   234,   325,   346,   391,   303,
+     304,   314,   314,    11,    12,    13,   154,   244,   154,   377,
+     133,   392,   128,   115,   404,   314,   217,    77,    78,    79,
+     399,    33,    34,    35,   400,    36,    37,    38,    39,    40,
+     157,   426,   134,   343,   151,   314,   -19,   356,   -20,   240,
+     365,   366,   367,   368,   361,   362,   240,   243,   317,   291,
+     363,   364,   357,   358,   359,   360,   239,   239,   239,   239,
+     239,   239,   239,   239,   239,   239,   239,   239,   239,   239,
+     239,   239,   351,   217,   378,  -114,   144,    12,   145,   237,
+     239,   250,   325,   410,   232,   318,   251,   239,   254,    15,
+      16,   255,   413,   136,   137,   138,   257,   240,   258,   262,
+     154,   294,   295,   296,   369,   370,   259,   427,   217,   264,
+     265,   269,   -45,   308,   275,   402,   217,   280,    33,    34,
+      35,   217,    36,    37,    38,    39,    40,   350,   121,   120,
+     433,   307,   309,   310,   311,   130,   -44,   327,   239,   328,
+     334,   332,   -39,   325,   379,   383,   384,   387,   396,   314,
+     394,   397,   405,   398,   411,   408,   406,   409,   412,   -49,
+     420,   187,   117,   421,   118,   325,   416,   422,   325,   429,
+     424,   372,   371,   375,   233,   319,   325,   432,   373,   376,
+     229,   333,   244,   122,   325,   320,   374,   249,   217,   386,
+     335,   132,   428,   347,   415,   388,   129,   393,   217,     0,
+       0,   336,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   217,     0,     0,   217,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,   210,     0,     0,   210,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   210,     0,     0,     0,     0,
-       0,     0,    12,    13,    14,    15,    16,    17,   155,   156,
-     157,   210,   158,   159,   160,   161,   162,   163,   164,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,    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,    70,    71,   165,   166,   167,   168,   169,   170,
-     171,     0,     0,   172,   173,     0,     0,     0,     0,     0,
+       0,     0,     0,   217,     0,     0,     0,     0,     0,     0,
+       0,    15,    16,    17,    18,    19,    20,   163,   164,   165,
+     217,   166,   167,   168,   169,   170,   171,   172,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
+      33,    34,    35,     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,    70,    71,
+      72,    73,    74,   173,   117,    75,   118,   174,   175,   176,
+     177,   178,     0,     0,   179,   180,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    73,    74,    75,    76,     0,    77,     0,     0,
+       0,     0,     0,    76,    77,    78,    79,     0,    80,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-      83,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,    86,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    84,     0,    85,     0,     0,     0,
+       0,     0,     0,     0,     0,    87,     0,    88,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   174,     0,     0,     0,     0,     0,   175,
-     176,   177,   178,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   179,   180,   181,    12,    13,    14,
-      15,    16,    17,   155,   156,   157,     0,   158,   159,   160,
-     161,   162,   163,   164,    18,    19,    20,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,    30,    31,    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,    70,    71,   165,
-     166,   167,   168,   169,   170,   171,     0,     0,   172,   173,
+       0,     0,     0,     0,   181,     0,     0,     0,     0,     0,
+     182,   183,   184,   185,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   186,   187,   188,    15,    16,
+      17,    18,    19,    20,   163,   164,   165,     0,   166,   167,
+     168,   169,   170,   171,   172,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
+       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,    70,    71,    72,    73,    74,
+     173,   117,    75,   118,   174,   175,   176,   177,   178,     0,
+       0,   179,   180,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    73,    74,    75,
-      76,     0,    77,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,    83,     0,     0,     0,     0,
+      76,    77,    78,    79,     0,    80,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    86,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,    84,
-       0,    85,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    87,     0,    88,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   174,     0,
-       0,     0,     0,     0,   175,   176,   177,   178,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   179,
-     180,   262,    12,    13,    14,    15,    16,    17,   155,   156,
-     157,     0,   158,   159,   160,   161,   162,   163,   164,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,    32,     0,    33,    34,    35,    36,    37,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   181,     0,     0,     0,     0,     0,   182,   183,   184,
+     185,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   186,   187,   316,    15,    16,    17,    18,    19,
+      20,   163,   164,   165,     0,   166,   167,   168,   169,   170,
+     171,   172,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    32,    33,    34,    35,     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,    70,    71,   165,   166,   167,   168,   169,   170,
-     171,     0,     0,   172,   173,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    73,    74,    75,    76,     0,    77,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-      83,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      68,    69,    70,    71,    72,    73,    74,   173,   117,    75,
+     118,   174,   175,   176,   177,   178,     0,     0,   179,   180,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    76,    77,    78,
+      79,     0,    80,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    86,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    84,     0,    85,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    87,
+       0,    88,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   174,     0,     0,     0,     0,     0,   175,
-     176,   177,   178,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   179,   180,   309,    12,    13,    14,
-      15,    16,    17,   155,   156,   157,     0,   158,   159,   160,
-     161,   162,   163,   164,    18,    19,    20,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,    30,    31,    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,    70,    71,   165,
-     166,   167,   168,   169,   170,   171,     0,     0,   172,   173,
+       0,     0,     0,     0,     0,     0,     0,     0,   181,     0,
+       0,     0,     0,     0,   182,   183,   184,   185,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   186,
+     187,   395,    15,    16,    17,    18,    19,    20,   163,   164,
+     165,     0,   166,   167,   168,   169,   170,   171,   172,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    33,    34,    35,     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,    70,
+      71,    72,    73,    74,   173,   117,    75,   118,   174,   175,
+     176,   177,   178,     0,     0,   179,   180,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    73,    74,    75,
-      76,     0,    77,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,    83,     0,     0,     0,     0,
+       0,     0,     0,     0,    76,    77,    78,    79,     0,    80,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    86,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,    84,
-       0,    85,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    87,     0,    88,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   174,     0,
-       0,     0,     0,     0,   175,   176,   177,   178,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   179,
-     180,   340,    12,    13,    14,    15,    16,    17,   155,   156,
-     157,     0,   158,   159,   160,   161,   162,   163,   164,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,    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,    70,    71,   165,   166,   167,   168,   169,   170,
-     171,     0,     0,   172,   173,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    73,    74,    75,    76,     0,    77,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-      83,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   181,     0,     0,     0,     0,
+       0,   182,   183,   184,   185,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   186,   187,    15,    16,
+      17,    18,    19,    20,   163,   164,   165,     0,   166,   167,
+     168,   169,   170,   171,   172,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
+       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,    70,    71,    72,    73,    74,
+     173,   117,    75,   118,   174,   175,   176,   177,   178,     0,
+       0,   179,   180,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      76,    77,    78,    79,     0,    80,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    86,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    84,     0,    85,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    87,     0,    88,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   174,     0,     0,     0,     0,     0,   175,
-     176,   177,   178,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   179,   180,    12,    13,    14,    15,
-      16,    17,   155,   156,   157,     0,   158,   159,   160,   161,
-     162,   163,   164,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    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,    70,    71,   165,   166,
-     167,   168,   169,   170,   171,     0,     0,   172,   173,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,    73,    74,    75,    76,
-       0,    77,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    83,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   181,     0,     0,     0,     0,     0,   182,   183,   184,
+     185,    15,    16,    17,    18,    19,    20,     0,     0,     0,
+       0,     0,   186,   131,     0,     0,     0,     0,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
+      33,    34,    35,     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,    70,    71,
+      72,    73,    74,     0,   117,    75,   118,   174,   175,   176,
+     177,   178,     0,     0,   179,   180,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    84,     0,
-      85,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    76,    77,    78,    79,     0,    80,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,    86,     0,    17,    18,    19,    20,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
+       0,     0,     0,     0,     0,    87,     0,    88,     0,    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,     0,   181,    75,     0,     0,     0,     0,
+     182,   183,   184,   185,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   186,     0,     0,     0,     0,
+       0,     0,     0,     0,    77,    78,    79,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,   174,     0,     0,
-       0,     0,     0,   175,   176,   177,   178,    12,    13,    14,
-      15,    16,    17,     0,     0,     0,     0,     0,   179,   126,
-       0,     0,     0,     0,    18,    19,    20,    21,    22,    23,
+       0,     0,    17,    18,    19,    20,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    21,    22,    23,
       24,    25,    26,    27,    28,    29,    30,    31,    32,     0,
-      33,    34,    35,    36,    37,    38,    39,    40,    41,    42,
+       0,     0,     0,     0,     0,    87,     0,    88,    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,     0,
-     166,   167,   168,   169,   170,   171,     0,     0,   172,   173,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    73,    74,    75,
-      76,     0,    77,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,    83,    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,    84,
-       0,    85,    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,     0,    72,   174,     0,
-       0,     0,     0,     0,   175,   176,   177,   178,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   179,
-       0,     0,     0,     0,     0,    74,    75,    76,     0,     0,
+      63,    64,    65,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,     0,     0,    75,     0,     0,     0,     0,     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,    84,     0,    85,    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,     0,    72,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   247,     0,     0,
+       0,     0,     0,    77,    78,    79,     0,     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,    74,    75,    76,     0,     0,     0,     0,     0,
+       0,    17,    18,    19,    20,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,     0,     0,
+       0,     0,     0,     0,    87,     0,    88,    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,     0,   117,    75,   118,   174,   175,   176,   177,   178,
+       0,     0,   179,   180,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   331,     0,     0,     0,
+       0,     0,    77,    78,    79,     0,     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,    84,     0,    85,    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,
-       0,   166,   167,   168,   169,   170,   171,     0,     0,   172,
-     173,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   321,     0,     0,     0,    74,
-      75,    76,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    87,     0,    88,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-      84,     0,    85,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   174,
-       0,     0,     0,     0,     0,   175,   176,   177,   178,    12,
-      13,    14,    15,    16,    17,     0,     0,     0,     0,     0,
-     253,     0,     0,     0,     0,     0,    18,    19,    20,    21,
+       0,     0,   181,     0,     0,     0,     0,     0,   182,   183,
+     184,   185,    15,    16,    17,    18,    19,    20,     0,     0,
+       0,     0,     0,   260,     0,     0,     0,     0,     0,    21,
       22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
-      32,     0,    33,    34,    35,    36,    37,    38,    39,    40,
+      32,    33,    34,    35,     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,    70,
-      71,     0,   166,   167,   168,   169,   170,   171,     0,     0,
-     172,   173,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   335,
-      74,    75,    76,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    83,     0,     0,
+      71,    72,    73,    74,     0,   117,    75,   118,   174,   175,
+     176,   177,   178,     0,     0,   179,   180,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   342,    77,    78,    79,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    86,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,    84,     0,    85,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    87,     0,    88,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,    14,    15,    16,    17,     0,
-     174,     0,     0,     0,     0,     0,   175,   176,   177,   178,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,    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,     0,   166,   167,   168,   169,
-     170,   171,     0,     0,   172,   173,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    74,    75,    76,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      17,    18,    19,    20,     0,   181,     0,     0,     0,     0,
+       0,   182,   183,   184,   185,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    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,
+       0,   117,    75,   118,   174,   175,   176,   177,   178,     0,
+       0,   179,   180,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,    77,    78,    79,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,    84,     0,    85,     0,     0,
        0,     0,     0,     0,     0,     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,   174,     0,     0,   231,     0,     0,
-     175,   176,   177,   178,    18,    19,    20,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,    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,     0,
-     166,   167,   168,   169,   170,   171,     0,     0,   172,   173,
+       0,     0,    87,     0,    88,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    74,    75,
-      76,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    17,    18,    19,    20,
+       0,   181,     0,     0,   238,     0,     0,   182,   183,   184,
+     185,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    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,     0,   117,    75,   118,
+     174,   175,   176,   177,   178,     0,     0,   179,   180,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    77,    78,    79,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,    84,
-       0,    85,     0,     0,     0,     0,     0,     0,     0,     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,   174,     0,
-       0,   316,     0,     0,   175,   176,   177,   178,    18,    19,
-      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,    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,     0,   166,   167,   168,   169,   170,   171,
-       0,     0,   172,   173,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    74,    75,    76,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    87,     0,
+      88,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    17,    18,    19,    20,     0,   181,     0,     0,
+     323,     0,     0,   182,   183,   184,   185,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    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,     0,   117,    75,   118,   174,   175,   176,   177,
+     178,     0,     0,   179,   180,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    77,    78,    79,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    84,     0,    85,     0,     0,     0,     0,
        0,     0,     0,     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,   174,     0,     0,   369,     0,     0,   175,   176,
-     177,   178,    18,    19,    20,    21,    22,    23,    24,    25,
-      26,    27,    28,    29,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    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,     0,   166,   167,
-     168,   169,   170,   171,     0,     0,   172,   173,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,    74,    75,    76,     0,
+       0,     0,     0,     0,    87,     0,    88,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    17,    18,
+      19,    20,     0,   181,     0,     0,   380,     0,     0,   182,
+     183,   184,   185,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    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,     0,   117,
+      75,   118,   174,   175,   176,   177,   178,     0,     0,   179,
+     180,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    77,
+      78,    79,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    84,     0,    85,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      87,     0,    88,     0,     0,     0,     0,     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,   174,     0,     0,     0,
-       0,     0,   175,   176,   177,   178,    18,    19,    20,    21,
-      22,    23,    24,    25,    26,    27,    28,    29,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    38,    39,    40,
+       0,     0,     0,     0,    17,    18,    19,    20,     0,   181,
+       0,     0,     0,     0,     0,   182,   183,   184,   185,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,     0,     0,     0,     0,     0,     0,     0,     0,     0,
       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,
-     271,     0,   166,   167,   168,   169,   170,   171,     0,     0,
-     172,   173,     0,     0,     0,     0,     0,     0,     0,     0,
+      71,    72,    73,   278,     0,   117,    75,   118,   174,   175,
+     176,   177,   178,     0,     0,   179,   180,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-      74,    75,    76,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    77,    78,    79,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,    84,     0,    85,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    87,     0,    88,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    12,    13,    14,    15,    16,    17,     0,
-     174,     0,     0,     0,     0,     0,   175,   176,   177,   178,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    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,    70,    71,     0,    72,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      17,    18,    19,    20,     0,   181,     0,     0,     0,     0,
+       0,   182,   183,   184,   185,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    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,   401,
+       0,   117,    75,   118,   174,   175,   176,   177,   178,     0,
+       0,   179,   180,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    73,    74,    75,    76,     0,    77,     0,
-       0,     0,     0,     0,     0,     0,    78,    79,    80,    81,
-      82,    83,    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,    84,     0,    85,    38,    39,
-      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
+       0,    77,    78,    79,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    87,     0,    88,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    15,    16,    17,    18,    19,    20,
+       0,   181,     0,     0,     0,     0,     0,   182,   183,   184,
+     185,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    33,    34,    35,     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,    70,    71,    72,    73,    74,     0,     0,    75,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    76,    77,    78,    79,
+       0,    80,     0,     0,     0,     0,     0,     0,     0,    81,
+      82,    83,    84,    85,    86,    17,    18,    19,    20,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,    32,     0,     0,     0,     0,     0,     0,    87,     0,
+      88,    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,     0,   343,    14,    15,    16,    17,   171,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    74,    75,    76,     0,     0,     0,     0,     0,     0,
-      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,     0,    72,    14,    15,    16,    17,
-       0,     0,    84,     0,    85,     0,     0,     0,     0,     0,
-       0,    18,    19,    20,    21,    22,    23,    24,    25,    26,
-      27,    28,    29,    74,    75,    76,     0,     0,     0,     0,
-       0,     0,    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,     0,    72,     0,     0,
-       0,     0,     0,     0,    84,     0,    85,     0,     0,     0,
+      70,    71,    72,    73,    74,     0,     0,    75,    17,    18,
+      19,    20,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,     0,    77,    78,    79,     0,
+       0,     0,     0,     0,    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,     0,     0,
+      75,     0,     0,     0,     0,     0,     0,    87,     0,    88,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,    84,     0,    85
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      87,     0,    88
 };
 
 static const yytype_int16 yycheck[] =
 {
-       9,    73,    73,   157,   143,   161,    76,   163,   143,    91,
-       4,    76,   229,    86,    87,   258,   190,   148,   174,     4,
-       9,    78,     9,   109,    96,    97,    93,    94,    95,    96,
-      97,    98,    99,   100,   101,   102,   196,   172,   173,    33,
-      34,    35,   194,   115,   196,     0,     3,     4,    33,    34,
-      35,   199,   199,   199,   214,   199,   230,   113,   193,   199,
-     110,   215,   214,   383,    84,    85,    76,   215,   215,   215,
-     199,   215,   104,   213,   394,    32,    33,    34,    87,    36,
-      37,    38,    39,    40,   213,   117,   112,   330,   195,    98,
-     229,   113,   199,   194,   229,   251,   270,   314,    87,   255,
-      87,   113,   258,   195,   113,   322,   237,   199,   113,   263,
-     266,   285,    33,    34,   195,   113,    37,   126,   199,    76,
-     315,   195,   104,   105,   106,   199,   135,   195,    76,   194,
-     212,   199,   195,   307,   207,   208,   199,   146,   113,   148,
-     195,   315,    33,    34,    35,   199,   216,   214,   157,   196,
-     306,   368,   287,   288,   289,   290,   291,   292,   293,   294,
-     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
-     305,   180,   215,   216,   330,   314,   196,   372,   198,   314,
-     204,   205,   206,   322,   200,   201,    76,   322,   294,   295,
-     296,   297,   387,    82,    83,   390,    88,    89,   372,   290,
-     291,   195,   216,   398,   292,   293,   215,    76,   298,   299,
-     405,   385,    76,   387,     3,     4,   390,   226,   113,    76,
-     376,   194,   215,   214,   398,   215,   380,   215,   237,   368,
-     194,   405,   215,   368,   194,   213,   194,   393,     3,     4,
-     194,   250,   195,    32,    33,    34,   209,    36,    37,   258,
-     211,   210,    90,    92,   263,   194,   410,    76,   196,   215,
-     197,    78,    75,   335,   335,   195,   197,    32,    33,    34,
-     196,    36,    37,    38,    39,    40,   194,   199,   214,    76,
-     195,   197,   194,   197,   197,   214,   214,   195,   215,    12,
-     214,   216,   197,   267,   214,   301,   215,   300,   302,   129,
-     136,   303,   246,   304,    77,   305,   146,   250,   323,   226,
-     394,    89,   381,   180,    -1,   226,   250,   330,    87,    -1,
-      -1,   330,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,   380,    -1,    -1,   383,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,   394,    -1,    -1,    -1,    -1,
-      -1,    -1,     3,     4,     5,     6,     7,     8,     9,    10,
-      11,   410,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
-      31,    32,    33,    34,    -1,    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,    -1,    -1,    84,    85,    -1,    -1,    -1,    -1,    -1,
+       9,     8,    76,    76,    93,   169,   165,   171,   155,   151,
+     235,    76,    77,    78,    76,    86,    87,   181,    88,    89,
+     198,   198,     4,   265,   322,    99,   100,     3,     4,   394,
+       9,     9,   201,   201,   217,   218,    98,    80,   216,   216,
+     107,    33,    34,    84,    85,    37,   120,   412,   217,   217,
+     151,    33,    34,    35,   111,   122,    32,    33,    34,     4,
+      36,    37,     0,   222,   201,   115,    73,   201,    95,    96,
+      97,    98,    99,   100,   101,   102,   103,   104,   179,   180,
+     217,    90,   112,   217,   115,   383,   201,   115,    33,    34,
+      35,    98,   101,   235,   258,   337,   321,   197,   262,   200,
+     215,   265,   249,   328,   111,   201,   115,   405,   114,   273,
+     408,    90,    90,   197,   202,   203,   197,   201,   416,   215,
+     201,   115,   131,    90,    91,   214,   424,   198,   115,   200,
+     115,   140,     3,     4,   235,   142,   236,   197,   197,   209,
+     210,   201,   201,    76,    77,    78,   155,   154,   157,   313,
+     197,   197,   196,   218,   379,   201,   165,   106,   107,   108,
+     197,    32,    33,    34,   201,    36,    37,    38,    39,    40,
+     218,   197,   201,   337,   198,   201,   196,   277,   196,   321,
+     301,   302,   303,   304,   297,   298,   328,   115,   347,   216,
+     299,   300,   292,   294,   295,   296,   297,   298,   299,   300,
+     301,   302,   303,   304,   305,   306,   307,   308,   309,   310,
+     311,   312,   274,   222,   314,   197,    76,    77,    78,   196,
+     321,   217,   322,   387,   233,   232,   216,   328,   217,     3,
+       4,   217,   391,    33,    34,    35,   196,   379,   196,   196,
+     249,   206,   207,   208,   305,   306,   217,   411,   257,   215,
+     196,   219,   196,   212,   197,   355,   265,   196,    32,    33,
+      34,   270,    36,    37,    38,    39,    40,   274,   342,   342,
+     429,   211,   213,    92,    94,   217,   196,   199,   379,   198,
+      75,    80,   197,   383,   198,   216,   199,   196,   199,   201,
+     197,   196,   216,   197,   217,   216,   199,   199,   197,   197,
+     400,   218,    76,   403,    78,   405,   216,   199,   408,    12,
+     216,   308,   307,   311,   141,   233,   416,   217,   309,   312,
+     134,   253,   329,    80,   424,   233,   310,   157,   337,   329,
+     257,    92,   412,   270,   392,   337,    90,   344,   347,    -1,
+      -1,   257,    -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,    -1,    -1,    -1,    -1,    -1,
-     121,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   391,    -1,    -1,   394,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,   155,    -1,   157,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   412,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+     429,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    33,    34,    -1,    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,    -1,    -1,    86,    87,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   105,   106,   107,   108,    -1,   110,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   194,    -1,    -1,    -1,    -1,    -1,   200,
-     201,   202,   203,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,   215,   216,   217,     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,    33,    34,    -1,
-      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,    -1,    -1,    84,    85,
+      -1,   123,    -1,    -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,
-      -1,    -1,    -1,    -1,    -1,   121,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   157,    -1,   159,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   155,
-      -1,   157,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   194,    -1,
-      -1,    -1,    -1,    -1,   200,   201,   202,   203,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   215,
-     216,   217,     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,    33,    34,    -1,    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,    -1,    -1,    84,    85,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   196,    -1,    -1,    -1,    -1,    -1,
+     202,   203,   204,   205,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   217,   218,   219,     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,    33,    34,
+      -1,    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,    -1,
+      -1,    86,    87,    -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,
+     105,   106,   107,   108,    -1,   110,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   123,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-     121,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,   155,    -1,   157,    -1,    -1,    -1,
+      -1,    -1,   157,    -1,   159,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   194,    -1,    -1,    -1,    -1,    -1,   200,
-     201,   202,   203,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,   215,   216,   217,     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,    33,    34,    -1,
-      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,    -1,    -1,    84,    85,
+      -1,   196,    -1,    -1,    -1,    -1,    -1,   202,   203,   204,
+     205,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   217,   218,   219,     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,    33,    34,    -1,    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,    -1,    -1,    86,    87,
       -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,    -1,   121,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   105,   106,   107,
+     108,    -1,   110,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   123,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   155,
-      -1,   157,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   157,
+      -1,   159,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   194,    -1,
-      -1,    -1,    -1,    -1,   200,   201,   202,   203,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   215,
-     216,   217,     3,     4,     5,     6,     7,     8,     9,    10,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   196,    -1,
+      -1,    -1,    -1,    -1,   202,   203,   204,   205,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   217,
+     218,   219,     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,    33,    34,    -1,    36,    37,    38,    39,    40,
@@ -1657,295 +1657,312 @@ static const yytype_int16 yycheck[] =
       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,
+      81,    82,    83,    -1,    -1,    86,    87,    -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,   105,   106,   107,   108,    -1,   110,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-     121,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   123,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,   155,    -1,   157,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   157,    -1,   159,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   194,    -1,    -1,    -1,    -1,    -1,   200,
-     201,   202,   203,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,   215,   216,     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,    33,    34,    -1,    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,    -1,    -1,    84,    85,    -1,
+      -1,    -1,    -1,    -1,    -1,   196,    -1,    -1,    -1,    -1,
+      -1,   202,   203,   204,   205,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   217,   218,     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,    33,    34,
+      -1,    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,    -1,
+      -1,    86,    87,    -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,    -1,
-      -1,    -1,    -1,    -1,   121,    -1,    -1,    -1,    -1,    -1,
+     105,   106,   107,   108,    -1,   110,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   123,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   155,    -1,
-     157,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   157,    -1,   159,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,   194,    -1,    -1,
-      -1,    -1,    -1,   200,   201,   202,   203,     3,     4,     5,
-       6,     7,     8,    -1,    -1,    -1,    -1,    -1,   215,   216,
-      -1,    -1,    -1,    -1,    20,    21,    22,    23,    24,    25,
-      26,    27,    28,    29,    30,    31,    32,    33,    34,    -1,
-      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,    -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,    -1,   121,     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,   155,
-      -1,   157,    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,   194,    -1,
-      -1,    -1,    -1,    -1,   200,   201,   202,   203,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   215,
-      -1,    -1,    -1,    -1,    -1,   104,   105,   106,    -1,    -1,
+      -1,   196,    -1,    -1,    -1,    -1,    -1,   202,   203,   204,
+     205,     3,     4,     5,     6,     7,     8,    -1,    -1,    -1,
+      -1,    -1,   217,   218,    -1,    -1,    -1,    -1,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    33,    34,    -1,    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,    -1,    76,    77,    78,    79,    80,    81,
+      82,    83,    -1,    -1,    86,    87,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   105,   106,   107,   108,    -1,   110,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,     5,     6,     7,     8,    -1,    -1,    -1,
+      -1,   123,    -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,   155,    -1,   157,    41,
+      -1,    -1,    -1,    -1,    -1,   157,    -1,   159,    -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,
+      72,    73,    74,    -1,   196,    77,    -1,    -1,    -1,    -1,
+     202,   203,   204,   205,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   217,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   106,   107,   108,    -1,    -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,   157,    -1,   159,    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,    -1,    77,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   219,    -1,    -1,
+      -1,    -1,    -1,   106,   107,   108,    -1,    -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,   157,    -1,   159,    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,    82,    83,
+      -1,    -1,    86,    87,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   219,    -1,    -1,    -1,
+      -1,    -1,   106,   107,   108,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   217,    -1,
-      -1,    -1,   104,   105,   106,    -1,    -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,
+      -1,    -1,    -1,   157,    -1,   159,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   196,    -1,    -1,    -1,    -1,    -1,   202,   203,
+     204,   205,     3,     4,     5,     6,     7,     8,    -1,    -1,
+      -1,    -1,    -1,   217,    -1,    -1,    -1,    -1,    -1,    20,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,    32,    33,    34,    -1,    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,    -1,    76,    77,    78,    79,    80,
+      81,    82,    83,    -1,    -1,    86,    87,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   105,   106,   107,   108,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   123,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   157,    -1,   159,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -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,   196,    -1,    -1,    -1,    -1,
+      -1,   202,   203,   204,   205,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    -1,    -1,    -1,
-      -1,    -1,    -1,   155,    -1,   157,    41,    42,    43,    44,
+      -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,   217,    -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,    76,    77,    78,    79,    80,    81,    82,    83,    -1,
+      -1,    86,    87,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   106,   107,   108,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-     155,    -1,   157,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   194,
-      -1,    -1,    -1,    -1,    -1,   200,   201,   202,   203,     3,
-       4,     5,     6,     7,     8,    -1,    -1,    -1,    -1,    -1,
-     215,    -1,    -1,    -1,    -1,    -1,    20,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
-      34,    -1,    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,    -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,    -1,   121,    -1,    -1,
+      -1,    -1,   157,    -1,   159,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -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,   196,    -1,    -1,   199,    -1,    -1,   202,   203,   204,
+     205,    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,    82,    83,    -1,    -1,    86,    87,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,   155,    -1,   157,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   106,   107,   108,
       -1,    -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,
-     194,    -1,    -1,    -1,    -1,    -1,   200,   201,   202,   203,
-      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,   157,    -1,
+     159,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -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,   196,    -1,    -1,
+     199,    -1,    -1,   202,   203,   204,   205,    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,    82,
+      83,    -1,    -1,    86,    87,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,   155,    -1,   157,    -1,    -1,
+      -1,    -1,    -1,   106,   107,   108,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -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,   194,    -1,    -1,   197,    -1,    -1,
-     200,   201,   202,   203,    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,   157,    -1,   159,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   155,
-      -1,   157,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,     5,     6,
+       7,     8,    -1,   196,    -1,    -1,   199,    -1,    -1,   202,
+     203,   204,   205,    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,    82,    83,    -1,    -1,    86,
+      87,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   106,
+     107,   108,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -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,   194,    -1,
-      -1,   197,    -1,    -1,   200,   201,   202,   203,    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,
+     157,    -1,   159,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -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,   196,
+      -1,    -1,    -1,    -1,    -1,   202,   203,   204,   205,    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,    82,    83,    -1,    -1,    86,    87,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   155,    -1,   157,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   106,   107,   108,    -1,    -1,
       -1,    -1,    -1,    -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,   194,    -1,    -1,   197,    -1,    -1,   200,   201,
-     202,   203,    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,   157,    -1,   159,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,   155,    -1,   157,
+       5,     6,     7,     8,    -1,   196,    -1,    -1,    -1,    -1,
+      -1,   202,   203,   204,   205,    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,    82,    83,    -1,
+      -1,    86,    87,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   106,   107,   108,    -1,    -1,    -1,    -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,   194,    -1,    -1,    -1,
-      -1,    -1,   200,   201,   202,   203,    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,   157,    -1,   159,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,     3,     4,     5,     6,     7,     8,
+      -1,   196,    -1,    -1,    -1,    -1,    -1,   202,   203,   204,
+     205,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    32,    33,    34,    -1,    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,    -1,    -1,    77,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,   155,    -1,   157,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   105,   106,   107,   108,
+      -1,   110,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   118,
+     119,   120,   121,   122,   123,     5,     6,     7,     8,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,     3,     4,     5,     6,     7,     8,    -1,
-     194,    -1,    -1,    -1,    -1,    -1,   200,   201,   202,   203,
       20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    33,    34,    -1,    36,    37,    38,    39,
-      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
+      30,    31,    -1,    -1,    -1,    -1,    -1,    -1,   157,    -1,
+     159,    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,
+      70,    71,    72,    73,    74,    -1,    -1,    77,     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,   106,   107,   108,    -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,    -1,
+      77,    -1,    -1,    -1,    -1,    -1,    -1,   157,    -1,   159,
       -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,   121,     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,   155,    -1,   157,    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,    -1,   155,    -1,   157,    -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,    -1,   155,    -1,   157,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,   155,    -1,   157
+     157,    -1,   159
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint16 yystos[] =
 {
-       0,   109,   219,   221,    78,     0,   223,   113,   110,   220,
-     224,    76,     3,     4,     5,     6,     7,     8,    20,    21,
-      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
-      32,    33,    34,    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,    76,   103,   104,   105,   106,   108,   116,   117,
-     118,   119,   120,   121,   155,   157,   222,   225,   255,   256,
-     257,   258,   259,   264,   265,   266,   267,   270,   272,   273,
-     274,   275,   276,   277,   278,   279,   303,   304,   112,    33,
-      34,    37,    76,   216,    76,   270,   273,   278,   113,   113,
-     113,   113,   113,   194,   303,   215,   216,   290,   195,   199,
-       4,    33,    34,    35,   261,   262,   271,   199,   215,    76,
-     273,   273,   274,   196,   275,    76,   216,   274,   280,   281,
-     273,   275,    76,   268,   269,     9,    10,    11,    13,    14,
-      15,    16,    17,    18,    19,    75,    76,    77,    78,    79,
-      80,    81,    84,    85,   194,   200,   201,   202,   203,   215,
-     216,   217,   226,   227,   228,   230,   231,   232,   233,   234,
-     235,   236,   237,   238,   239,   240,   241,   242,   243,   244,
-     245,   246,   247,   248,   249,   250,   251,   253,   255,   256,
-     274,   285,   286,   287,   288,   291,   292,   293,   296,   297,
-     298,   302,   261,   260,   263,   274,   262,    76,   194,   196,
-     214,   197,   237,   250,   254,   274,   113,   280,    76,   282,
-     283,   217,   281,   215,   214,   195,   199,   215,   215,   286,
-     194,   194,   215,   215,   253,   194,   253,   213,   194,   237,
-     237,   253,   217,   291,    84,    85,   196,   198,   195,   195,
-     199,    74,   251,   194,    93,    94,    95,    96,    97,    98,
-      99,   100,   101,   102,   214,   252,   237,   204,   205,   206,
-     200,   201,    82,    83,    86,    87,   207,   208,    88,    89,
-     209,   210,   211,    90,    92,    91,   212,   199,   215,   217,
-     286,    76,   260,   263,   196,   214,   197,   254,   251,   284,
-     197,   217,   196,   199,   215,    78,   269,    75,   285,   292,
-     299,   253,   215,   253,   213,   103,   253,   266,   295,   195,
-     217,   229,   253,    76,   232,   251,   251,   237,   237,   237,
-     239,   239,   240,   240,   241,   241,   241,   241,   242,   242,
-     243,   244,   245,   246,   247,   248,   253,   251,   196,   197,
-     254,   284,   214,   197,   254,   283,   194,   295,   300,   301,
-     195,   195,    76,   195,   197,   213,   254,   214,   197,   284,
-     214,   197,   253,   215,   195,   286,   294,   288,   214,   287,
-     289,   290,   251,   197,   284,   214,   284,   195,   253,   289,
-      12,   284,   284,   215,   286
+       0,   111,   221,   223,    80,     0,   225,   115,   112,   222,
+     227,    76,    77,    78,   226,     3,     4,     5,     6,     7,
+       8,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    32,    33,    34,    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,    77,   105,   106,   107,   108,
+     110,   118,   119,   120,   121,   122,   123,   157,   159,   224,
+     228,   262,   263,   264,   265,   266,   271,   272,   273,   274,
+     277,   279,   280,   281,   282,   283,   284,   285,   286,   311,
+     312,   114,    33,    34,    37,   218,   226,    76,    78,   229,
+     277,   280,   285,   115,   115,   115,   115,   115,   196,   311,
+     217,   218,   298,   197,   201,     4,    33,    34,    35,   268,
+     269,   278,   201,   217,    76,    78,   226,   229,   280,   280,
+     281,   198,   282,   226,   281,   287,   288,   218,   280,   282,
+     226,   275,   276,     9,    10,    11,    13,    14,    15,    16,
+      17,    18,    19,    75,    79,    80,    81,    82,    83,    86,
+      87,   196,   202,   203,   204,   205,   217,   218,   219,   229,
+     230,   231,   233,   234,   235,   236,   237,   238,   239,   244,
+     245,   246,   247,   248,   249,   250,   251,   252,   253,   254,
+     255,   256,   257,   258,   260,   262,   263,   281,   292,   293,
+     294,   295,   299,   300,   301,   304,   305,   306,   310,   268,
+     267,   270,   281,   269,   226,   198,   216,   196,   199,   244,
+     257,   261,   281,   115,   226,   289,   290,   219,   288,   287,
+     217,   216,   197,   201,   217,   217,   293,   196,   196,   217,
+     217,   260,   196,   260,   215,   196,   244,   244,   260,   219,
+     296,    86,    87,   198,   200,   197,   197,   201,    74,   258,
+     196,    95,    96,    97,    98,    99,   100,   101,   102,   103,
+     104,   216,   259,   244,   206,   207,   208,   202,   203,    84,
+      85,    88,    89,   209,   210,    90,    91,   211,   212,   213,
+      92,    94,    93,   214,   201,   217,   219,   293,   226,   267,
+     270,   198,   216,   199,   261,   258,   291,   199,   198,   201,
+     217,   219,    80,   276,    75,   292,   300,   307,   260,   217,
+     260,   215,   105,   260,   273,   303,   197,   299,   232,   260,
+     226,   229,   240,   241,   242,   243,   258,   258,   244,   244,
+     244,   246,   246,   247,   247,   248,   248,   248,   248,   249,
+     249,   250,   251,   252,   253,   254,   255,   260,   258,   198,
+     199,   261,   291,   216,   199,   261,   290,   196,   303,   308,
+     309,   197,   197,   226,   197,   219,   199,   196,   197,   197,
+     201,    74,   258,   215,   261,   216,   199,   291,   216,   199,
+     260,   217,   197,   293,   302,   295,   216,   294,   297,   298,
+     258,   258,   199,   291,   216,   291,   197,   260,   297,    12,
+     291,   291,   217,   293
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -2636,7 +2653,7 @@ YYLTYPE yylloc;
 }
 
 /* Line 1251 of yacc.c  */
-#line 2640 "glsl_parser.cpp"
+#line 2657 "glsl_parser.cpp"
   yylsp[0] = yylloc;
 
   goto yysetstate;
@@ -2824,43 +2841,69 @@ yyreduce:
         case 2:
 
 /* Line 1464 of yacc.c  */
-#line 213 "glsl_parser.ypp"
+#line 218 "glsl_parser.ypp"
     {
           _mesa_glsl_initialize_types(state);
        ;}
     break;
 
-  case 5:
+  case 3:
 
 /* Line 1464 of yacc.c  */
 #line 222 "glsl_parser.ypp"
     {
+          delete state->symbols;
+          state->symbols = new(ralloc_parent(state)) glsl_symbol_table;
+          _mesa_glsl_initialize_types(state);
+       ;}
+    break;
+
+  case 5:
+
+/* Line 1464 of yacc.c  */
+#line 232 "glsl_parser.ypp"
+    {
+          bool supported = false;
+
           switch ((yyvsp[(2) - (3)].n)) {
           case 100:
              state->es_shader = true;
+             supported = state->Const.GLSL_100ES;
+             break;
           case 110:
+             supported = state->Const.GLSL_110;
+             break;
           case 120:
+             supported = state->Const.GLSL_120;
+             break;
           case 130:
-             /* FINISHME: Check against implementation support versions. */
-             state->language_version = (yyvsp[(2) - (3)].n);
-             state->version_string =
-                talloc_asprintf(state, "GLSL%s %d.%02d",
-                                state->es_shader ? " ES" : "",
-                                state->language_version / 100,
-                                state->language_version % 100);
+             supported = state->Const.GLSL_130;
              break;
           default:
-             _mesa_glsl_error(& (yylsp[(2) - (3)]), state, "Shading language version"
-                              "%u is not supported\n", (yyvsp[(2) - (3)].n));
+             supported = false;
              break;
           }
+
+          state->language_version = (yyvsp[(2) - (3)].n);
+          state->version_string =
+             ralloc_asprintf(state, "GLSL%s %d.%02d",
+                             state->es_shader ? " ES" : "",
+                             state->language_version / 100,
+                             state->language_version % 100);
+
+          if (!supported) {
+             _mesa_glsl_error(& (yylsp[(2) - (3)]), state, "%s is not supported. "
+                              "Supported versions are: %s\n",
+                              state->version_string,
+                              state->supported_version_string);
+          }
        ;}
     break;
 
   case 10:
 
 /* Line 1464 of yacc.c  */
-#line 251 "glsl_parser.ypp"
+#line 276 "glsl_parser.ypp"
     {
           if (state->language_version < 120) {
              _mesa_glsl_warning(& (yylsp[(1) - (2)]), state,
@@ -2872,10 +2915,10 @@ yyreduce:
        ;}
     break;
 
-  case 13:
+  case 16:
 
 /* Line 1464 of yacc.c  */
-#line 269 "glsl_parser.ypp"
+#line 300 "glsl_parser.ypp"
     {
           if (!_mesa_glsl_process_extension((yyvsp[(2) - (5)].identifier), & (yylsp[(2) - (5)]), (yyvsp[(4) - (5)].identifier), & (yylsp[(4) - (5)]), state)) {
              YYERROR;
@@ -2883,10 +2926,10 @@ yyreduce:
        ;}
     break;
 
-  case 14:
+  case 17:
 
 /* Line 1464 of yacc.c  */
-#line 278 "glsl_parser.ypp"
+#line 309 "glsl_parser.ypp"
     {
           /* FINISHME: The NULL test is required because pragmas are set to
            * FINISHME: NULL. (See production rule for external_declaration.)
@@ -2896,10 +2939,10 @@ yyreduce:
        ;}
     break;
 
-  case 15:
+  case 18:
 
 /* Line 1464 of yacc.c  */
-#line 286 "glsl_parser.ypp"
+#line 317 "glsl_parser.ypp"
     {
           /* FINISHME: The NULL test is required because pragmas are set to
            * FINISHME: NULL. (See production rule for external_declaration.)
@@ -2909,10 +2952,10 @@ yyreduce:
        ;}
     break;
 
-  case 17:
+  case 21:
 
 /* Line 1464 of yacc.c  */
-#line 301 "glsl_parser.ypp"
+#line 333 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression(ast_identifier, NULL, NULL, NULL);
@@ -2921,10 +2964,10 @@ yyreduce:
        ;}
     break;
 
-  case 18:
+  case 22:
 
 /* Line 1464 of yacc.c  */
-#line 308 "glsl_parser.ypp"
+#line 340 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression(ast_int_constant, NULL, NULL, NULL);
@@ -2933,10 +2976,10 @@ yyreduce:
        ;}
     break;
 
-  case 19:
+  case 23:
 
 /* Line 1464 of yacc.c  */
-#line 315 "glsl_parser.ypp"
+#line 347 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression(ast_uint_constant, NULL, NULL, NULL);
@@ -2945,10 +2988,10 @@ yyreduce:
        ;}
     break;
 
-  case 20:
+  case 24:
 
 /* Line 1464 of yacc.c  */
-#line 322 "glsl_parser.ypp"
+#line 354 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression(ast_float_constant, NULL, NULL, NULL);
@@ -2957,10 +3000,10 @@ yyreduce:
        ;}
     break;
 
-  case 21:
+  case 25:
 
 /* Line 1464 of yacc.c  */
-#line 329 "glsl_parser.ypp"
+#line 361 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression(ast_bool_constant, NULL, NULL, NULL);
@@ -2969,19 +3012,19 @@ yyreduce:
        ;}
     break;
 
-  case 22:
+  case 26:
 
 /* Line 1464 of yacc.c  */
-#line 336 "glsl_parser.ypp"
+#line 368 "glsl_parser.ypp"
     {
           (yyval.expression) = (yyvsp[(2) - (3)].expression);
        ;}
     break;
 
-  case 24:
+  case 28:
 
 /* Line 1464 of yacc.c  */
-#line 344 "glsl_parser.ypp"
+#line 376 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression(ast_array_index, (yyvsp[(1) - (4)].expression), (yyvsp[(3) - (4)].expression), NULL);
@@ -2989,19 +3032,19 @@ yyreduce:
        ;}
     break;
 
-  case 25:
+  case 29:
 
 /* Line 1464 of yacc.c  */
-#line 350 "glsl_parser.ypp"
+#line 382 "glsl_parser.ypp"
     {
           (yyval.expression) = (yyvsp[(1) - (1)].expression);
        ;}
     break;
 
-  case 26:
+  case 30:
 
 /* Line 1464 of yacc.c  */
-#line 354 "glsl_parser.ypp"
+#line 386 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression(ast_field_selection, (yyvsp[(1) - (3)].expression), NULL, NULL);
@@ -3010,10 +3053,10 @@ yyreduce:
        ;}
     break;
 
-  case 27:
+  case 31:
 
 /* Line 1464 of yacc.c  */
-#line 361 "glsl_parser.ypp"
+#line 393 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression(ast_post_inc, (yyvsp[(1) - (2)].expression), NULL, NULL);
@@ -3021,10 +3064,10 @@ yyreduce:
        ;}
     break;
 
-  case 28:
+  case 32:
 
 /* Line 1464 of yacc.c  */
-#line 367 "glsl_parser.ypp"
+#line 399 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression(ast_post_dec, (yyvsp[(1) - (2)].expression), NULL, NULL);
@@ -3032,10 +3075,10 @@ yyreduce:
        ;}
     break;
 
-  case 32:
+  case 36:
 
 /* Line 1464 of yacc.c  */
-#line 385 "glsl_parser.ypp"
+#line 417 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression(ast_field_selection, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression), NULL);
@@ -3043,10 +3086,10 @@ yyreduce:
        ;}
     break;
 
-  case 37:
+  case 41:
 
 /* Line 1464 of yacc.c  */
-#line 404 "glsl_parser.ypp"
+#line 436 "glsl_parser.ypp"
     {
           (yyval.expression) = (yyvsp[(1) - (2)].expression);
           (yyval.expression)->set_location(yylloc);
@@ -3054,10 +3097,10 @@ yyreduce:
        ;}
     break;
 
-  case 38:
+  case 42:
 
 /* Line 1464 of yacc.c  */
-#line 410 "glsl_parser.ypp"
+#line 442 "glsl_parser.ypp"
     {
           (yyval.expression) = (yyvsp[(1) - (3)].expression);
           (yyval.expression)->set_location(yylloc);
@@ -3065,10 +3108,10 @@ yyreduce:
        ;}
     break;
 
-  case 40:
+  case 44:
 
 /* Line 1464 of yacc.c  */
-#line 426 "glsl_parser.ypp"
+#line 458 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_function_expression((yyvsp[(1) - (1)].type_specifier));
@@ -3076,10 +3119,10 @@ yyreduce:
        ;}
     break;
 
-  case 41:
+  case 45:
 
 /* Line 1464 of yacc.c  */
-#line 432 "glsl_parser.ypp"
+#line 464 "glsl_parser.ypp"
     {
           void *ctx = state;
           ast_expression *callee = new(ctx) ast_expression((yyvsp[(1) - (1)].identifier));
@@ -3088,10 +3131,10 @@ yyreduce:
        ;}
     break;
 
-  case 42:
+  case 46:
 
 /* Line 1464 of yacc.c  */
-#line 439 "glsl_parser.ypp"
+#line 471 "glsl_parser.ypp"
     {
           void *ctx = state;
           ast_expression *callee = new(ctx) ast_expression((yyvsp[(1) - (1)].identifier));
@@ -3100,10 +3143,44 @@ yyreduce:
        ;}
     break;
 
-  case 44:
+  case 51:
+
+/* Line 1464 of yacc.c  */
+#line 491 "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 52:
 
 /* Line 1464 of yacc.c  */
-#line 451 "glsl_parser.ypp"
+#line 497 "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 53:
+
+/* Line 1464 of yacc.c  */
+#line 509 "glsl_parser.ypp"
+    {
+          void *ctx = state;
+          ast_expression *callee = new(ctx) ast_expression((yyvsp[(1) - (2)].identifier));
+          (yyval.expression) = new(ctx) ast_function_expression(callee);
+          (yyval.expression)->set_location(yylloc);
+       ;}
+    break;
+
+  case 55:
+
+/* Line 1464 of yacc.c  */
+#line 521 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression(ast_pre_inc, (yyvsp[(2) - (2)].expression), NULL, NULL);
@@ -3111,10 +3188,10 @@ yyreduce:
        ;}
     break;
 
-  case 45:
+  case 56:
 
 /* Line 1464 of yacc.c  */
-#line 457 "glsl_parser.ypp"
+#line 527 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression(ast_pre_dec, (yyvsp[(2) - (2)].expression), NULL, NULL);
@@ -3122,10 +3199,10 @@ yyreduce:
        ;}
     break;
 
-  case 46:
+  case 57:
 
 /* Line 1464 of yacc.c  */
-#line 463 "glsl_parser.ypp"
+#line 533 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression((yyvsp[(1) - (2)].n), (yyvsp[(2) - (2)].expression), NULL, NULL);
@@ -3133,38 +3210,38 @@ yyreduce:
        ;}
     break;
 
-  case 47:
+  case 58:
 
 /* Line 1464 of yacc.c  */
-#line 472 "glsl_parser.ypp"
+#line 542 "glsl_parser.ypp"
     { (yyval.n) = ast_plus; ;}
     break;
 
-  case 48:
+  case 59:
 
 /* Line 1464 of yacc.c  */
-#line 473 "glsl_parser.ypp"
+#line 543 "glsl_parser.ypp"
     { (yyval.n) = ast_neg; ;}
     break;
 
-  case 49:
+  case 60:
 
 /* Line 1464 of yacc.c  */
-#line 474 "glsl_parser.ypp"
+#line 544 "glsl_parser.ypp"
     { (yyval.n) = ast_logic_not; ;}
     break;
 
-  case 50:
+  case 61:
 
 /* Line 1464 of yacc.c  */
-#line 475 "glsl_parser.ypp"
+#line 545 "glsl_parser.ypp"
     { (yyval.n) = ast_bit_not; ;}
     break;
 
-  case 52:
+  case 63:
 
 /* Line 1464 of yacc.c  */
-#line 481 "glsl_parser.ypp"
+#line 551 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_mul, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3172,10 +3249,10 @@ yyreduce:
        ;}
     break;
 
-  case 53:
+  case 64:
 
 /* Line 1464 of yacc.c  */
-#line 487 "glsl_parser.ypp"
+#line 557 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_div, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3183,10 +3260,10 @@ yyreduce:
        ;}
     break;
 
-  case 54:
+  case 65:
 
 /* Line 1464 of yacc.c  */
-#line 493 "glsl_parser.ypp"
+#line 563 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_mod, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3194,10 +3271,10 @@ yyreduce:
        ;}
     break;
 
-  case 56:
+  case 67:
 
 /* Line 1464 of yacc.c  */
-#line 503 "glsl_parser.ypp"
+#line 573 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_add, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3205,10 +3282,10 @@ yyreduce:
        ;}
     break;
 
-  case 57:
+  case 68:
 
 /* Line 1464 of yacc.c  */
-#line 509 "glsl_parser.ypp"
+#line 579 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_sub, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3216,10 +3293,10 @@ yyreduce:
        ;}
     break;
 
-  case 59:
+  case 70:
 
 /* Line 1464 of yacc.c  */
-#line 519 "glsl_parser.ypp"
+#line 589 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_lshift, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3227,10 +3304,10 @@ yyreduce:
        ;}
     break;
 
-  case 60:
+  case 71:
 
 /* Line 1464 of yacc.c  */
-#line 525 "glsl_parser.ypp"
+#line 595 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_rshift, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3238,10 +3315,10 @@ yyreduce:
        ;}
     break;
 
-  case 62:
+  case 73:
 
 /* Line 1464 of yacc.c  */
-#line 535 "glsl_parser.ypp"
+#line 605 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_less, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3249,10 +3326,10 @@ yyreduce:
        ;}
     break;
 
-  case 63:
+  case 74:
 
 /* Line 1464 of yacc.c  */
-#line 541 "glsl_parser.ypp"
+#line 611 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_greater, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3260,10 +3337,10 @@ yyreduce:
        ;}
     break;
 
-  case 64:
+  case 75:
 
 /* Line 1464 of yacc.c  */
-#line 547 "glsl_parser.ypp"
+#line 617 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_lequal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3271,10 +3348,10 @@ yyreduce:
        ;}
     break;
 
-  case 65:
+  case 76:
 
 /* Line 1464 of yacc.c  */
-#line 553 "glsl_parser.ypp"
+#line 623 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_gequal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3282,10 +3359,10 @@ yyreduce:
        ;}
     break;
 
-  case 67:
+  case 78:
 
 /* Line 1464 of yacc.c  */
-#line 563 "glsl_parser.ypp"
+#line 633 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_equal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3293,10 +3370,10 @@ yyreduce:
        ;}
     break;
 
-  case 68:
+  case 79:
 
 /* Line 1464 of yacc.c  */
-#line 569 "glsl_parser.ypp"
+#line 639 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_nequal, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3304,10 +3381,10 @@ yyreduce:
        ;}
     break;
 
-  case 70:
+  case 81:
 
 /* Line 1464 of yacc.c  */
-#line 579 "glsl_parser.ypp"
+#line 649 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_bit_and, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3315,10 +3392,10 @@ yyreduce:
        ;}
     break;
 
-  case 72:
+  case 83:
 
 /* Line 1464 of yacc.c  */
-#line 589 "glsl_parser.ypp"
+#line 659 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_bit_xor, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3326,10 +3403,10 @@ yyreduce:
        ;}
     break;
 
-  case 74:
+  case 85:
 
 /* Line 1464 of yacc.c  */
-#line 599 "glsl_parser.ypp"
+#line 669 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_bit_or, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3337,10 +3414,10 @@ yyreduce:
        ;}
     break;
 
-  case 76:
+  case 87:
 
 /* Line 1464 of yacc.c  */
-#line 609 "glsl_parser.ypp"
+#line 679 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_logic_and, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3348,10 +3425,10 @@ yyreduce:
        ;}
     break;
 
-  case 78:
+  case 89:
 
 /* Line 1464 of yacc.c  */
-#line 619 "glsl_parser.ypp"
+#line 689 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_logic_xor, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3359,10 +3436,10 @@ yyreduce:
        ;}
     break;
 
-  case 80:
+  case 91:
 
 /* Line 1464 of yacc.c  */
-#line 629 "glsl_parser.ypp"
+#line 699 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.expression) = new(ctx) ast_expression_bin(ast_logic_or, (yyvsp[(1) - (3)].expression), (yyvsp[(3) - (3)].expression));
@@ -3370,10 +3447,10 @@ yyreduce:
        ;}
     break;
 
-  case 82:
+  case 93:
 
 /* Line 1464 of yacc.c  */
-#line 639 "glsl_parser.ypp"
+#line 709 "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));
@@ -3381,10 +3458,10 @@ yyreduce:
        ;}
     break;
 
-  case 84:
+  case 95:
 
 /* Line 1464 of yacc.c  */
-#line 649 "glsl_parser.ypp"
+#line 719 "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);
@@ -3392,96 +3469,96 @@ yyreduce:
        ;}
     break;
 
-  case 85:
+  case 96:
 
 /* Line 1464 of yacc.c  */
-#line 657 "glsl_parser.ypp"
+#line 727 "glsl_parser.ypp"
     { (yyval.n) = ast_assign; ;}
     break;
 
-  case 86:
+  case 97:
 
 /* Line 1464 of yacc.c  */
-#line 658 "glsl_parser.ypp"
+#line 728 "glsl_parser.ypp"
     { (yyval.n) = ast_mul_assign; ;}
     break;
 
-  case 87:
+  case 98:
 
 /* Line 1464 of yacc.c  */
-#line 659 "glsl_parser.ypp"
+#line 729 "glsl_parser.ypp"
     { (yyval.n) = ast_div_assign; ;}
     break;
 
-  case 88:
+  case 99:
 
 /* Line 1464 of yacc.c  */
-#line 660 "glsl_parser.ypp"
+#line 730 "glsl_parser.ypp"
     { (yyval.n) = ast_mod_assign; ;}
     break;
 
-  case 89:
+  case 100:
 
 /* Line 1464 of yacc.c  */
-#line 661 "glsl_parser.ypp"
+#line 731 "glsl_parser.ypp"
     { (yyval.n) = ast_add_assign; ;}
     break;
 
-  case 90:
+  case 101:
 
 /* Line 1464 of yacc.c  */
-#line 662 "glsl_parser.ypp"
+#line 732 "glsl_parser.ypp"
     { (yyval.n) = ast_sub_assign; ;}
     break;
 
-  case 91:
+  case 102:
 
 /* Line 1464 of yacc.c  */
-#line 663 "glsl_parser.ypp"
+#line 733 "glsl_parser.ypp"
     { (yyval.n) = ast_ls_assign; ;}
     break;
 
-  case 92:
+  case 103:
 
 /* Line 1464 of yacc.c  */
-#line 664 "glsl_parser.ypp"
+#line 734 "glsl_parser.ypp"
     { (yyval.n) = ast_rs_assign; ;}
     break;
 
-  case 93:
+  case 104:
 
 /* Line 1464 of yacc.c  */
-#line 665 "glsl_parser.ypp"
+#line 735 "glsl_parser.ypp"
     { (yyval.n) = ast_and_assign; ;}
     break;
 
-  case 94:
+  case 105:
 
 /* Line 1464 of yacc.c  */
-#line 666 "glsl_parser.ypp"
+#line 736 "glsl_parser.ypp"
     { (yyval.n) = ast_xor_assign; ;}
     break;
 
-  case 95:
+  case 106:
 
 /* Line 1464 of yacc.c  */
-#line 667 "glsl_parser.ypp"
+#line 737 "glsl_parser.ypp"
     { (yyval.n) = ast_or_assign; ;}
     break;
 
-  case 96:
+  case 107:
 
 /* Line 1464 of yacc.c  */
-#line 672 "glsl_parser.ypp"
+#line 742 "glsl_parser.ypp"
     {
           (yyval.expression) = (yyvsp[(1) - (1)].expression);
        ;}
     break;
 
-  case 97:
+  case 108:
 
 /* Line 1464 of yacc.c  */
-#line 676 "glsl_parser.ypp"
+#line 746 "glsl_parser.ypp"
     {
           void *ctx = state;
           if ((yyvsp[(1) - (3)].expression)->oper != ast_sequence) {
@@ -3496,28 +3573,29 @@ yyreduce:
        ;}
     break;
 
-  case 99:
+  case 110:
 
 /* Line 1464 of yacc.c  */
-#line 696 "glsl_parser.ypp"
+#line 766 "glsl_parser.ypp"
     {
+          state->symbols->pop_scope();
           (yyval.node) = (yyvsp[(1) - (2)].function);
        ;}
     break;
 
-  case 100:
+  case 111:
 
 /* Line 1464 of yacc.c  */
-#line 700 "glsl_parser.ypp"
+#line 771 "glsl_parser.ypp"
     {
           (yyval.node) = (yyvsp[(1) - (2)].declarator_list);
        ;}
     break;
 
-  case 101:
+  case 112:
 
 /* Line 1464 of yacc.c  */
-#line 704 "glsl_parser.ypp"
+#line 775 "glsl_parser.ypp"
     {
           (yyvsp[(3) - (4)].type_specifier)->precision = (yyvsp[(2) - (4)].n);
           (yyvsp[(3) - (4)].type_specifier)->is_precision_statement = true;
@@ -3525,43 +3603,46 @@ yyreduce:
        ;}
     break;
 
-  case 105:
+  case 116:
 
 /* Line 1464 of yacc.c  */
-#line 722 "glsl_parser.ypp"
+#line 793 "glsl_parser.ypp"
     {
           (yyval.function) = (yyvsp[(1) - (2)].function);
           (yyval.function)->parameters.push_tail(& (yyvsp[(2) - (2)].parameter_declarator)->link);
        ;}
     break;
 
-  case 106:
+  case 117:
 
 /* Line 1464 of yacc.c  */
-#line 727 "glsl_parser.ypp"
+#line 798 "glsl_parser.ypp"
     {
           (yyval.function) = (yyvsp[(1) - (3)].function);
           (yyval.function)->parameters.push_tail(& (yyvsp[(3) - (3)].parameter_declarator)->link);
        ;}
     break;
 
-  case 107:
+  case 118:
 
 /* Line 1464 of yacc.c  */
-#line 735 "glsl_parser.ypp"
+#line 806 "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);
+
+          state->symbols->add_function(new(state) ir_function((yyvsp[(2) - (3)].identifier)));
+          state->symbols->push_scope();
        ;}
     break;
 
-  case 108:
+  case 119:
 
 /* Line 1464 of yacc.c  */
-#line 746 "glsl_parser.ypp"
+#line 820 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.parameter_declarator) = new(ctx) ast_parameter_declarator();
@@ -3573,10 +3654,10 @@ yyreduce:
        ;}
     break;
 
-  case 109:
+  case 120:
 
 /* Line 1464 of yacc.c  */
-#line 756 "glsl_parser.ypp"
+#line 830 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.parameter_declarator) = new(ctx) ast_parameter_declarator();
@@ -3590,10 +3671,10 @@ yyreduce:
        ;}
     break;
 
-  case 110:
+  case 121:
 
 /* Line 1464 of yacc.c  */
-#line 771 "glsl_parser.ypp"
+#line 845 "glsl_parser.ypp"
     {
           (yyvsp[(1) - (3)].type_qualifier).flags.i |= (yyvsp[(2) - (3)].type_qualifier).flags.i;
 
@@ -3602,20 +3683,20 @@ yyreduce:
        ;}
     break;
 
-  case 111:
+  case 122:
 
 /* Line 1464 of yacc.c  */
-#line 778 "glsl_parser.ypp"
+#line 852 "glsl_parser.ypp"
     {
           (yyval.parameter_declarator) = (yyvsp[(2) - (2)].parameter_declarator);
           (yyval.parameter_declarator)->type->qualifier = (yyvsp[(1) - (2)].type_qualifier);
        ;}
     break;
 
-  case 112:
+  case 123:
 
 /* Line 1464 of yacc.c  */
-#line 783 "glsl_parser.ypp"
+#line 857 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyvsp[(1) - (3)].type_qualifier).flags.i |= (yyvsp[(2) - (3)].type_qualifier).flags.i;
@@ -3628,10 +3709,10 @@ yyreduce:
        ;}
     break;
 
-  case 113:
+  case 124:
 
 /* Line 1464 of yacc.c  */
-#line 794 "glsl_parser.ypp"
+#line 868 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.parameter_declarator) = new(ctx) ast_parameter_declarator();
@@ -3642,39 +3723,39 @@ yyreduce:
        ;}
     break;
 
-  case 114:
+  case 125:
 
 /* Line 1464 of yacc.c  */
-#line 806 "glsl_parser.ypp"
+#line 880 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
        ;}
     break;
 
-  case 115:
+  case 126:
 
 /* Line 1464 of yacc.c  */
-#line 810 "glsl_parser.ypp"
+#line 884 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.in = 1;
        ;}
     break;
 
-  case 116:
+  case 127:
 
 /* Line 1464 of yacc.c  */
-#line 815 "glsl_parser.ypp"
+#line 889 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.out = 1;
        ;}
     break;
 
-  case 117:
+  case 128:
 
 /* Line 1464 of yacc.c  */
-#line 820 "glsl_parser.ypp"
+#line 894 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.in = 1;
@@ -3682,10 +3763,10 @@ yyreduce:
        ;}
     break;
 
-  case 120:
+  case 131:
 
 /* Line 1464 of yacc.c  */
-#line 834 "glsl_parser.ypp"
+#line 908 "glsl_parser.ypp"
     {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (3)].identifier), false, NULL, NULL);
@@ -3693,13 +3774,14 @@ yyreduce:
 
           (yyval.declarator_list) = (yyvsp[(1) - (3)].declarator_list);
           (yyval.declarator_list)->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, (yyvsp[(3) - (3)].identifier), ir_var_auto));
        ;}
     break;
 
-  case 121:
+  case 132:
 
 /* Line 1464 of yacc.c  */
-#line 843 "glsl_parser.ypp"
+#line 918 "glsl_parser.ypp"
     {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (5)].identifier), true, NULL, NULL);
@@ -3707,13 +3789,14 @@ yyreduce:
 
           (yyval.declarator_list) = (yyvsp[(1) - (5)].declarator_list);
           (yyval.declarator_list)->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, (yyvsp[(3) - (5)].identifier), ir_var_auto));
        ;}
     break;
 
-  case 122:
+  case 133:
 
 /* Line 1464 of yacc.c  */
-#line 852 "glsl_parser.ypp"
+#line 928 "glsl_parser.ypp"
     {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (6)].identifier), true, (yyvsp[(5) - (6)].expression), NULL);
@@ -3721,13 +3804,14 @@ yyreduce:
 
           (yyval.declarator_list) = (yyvsp[(1) - (6)].declarator_list);
           (yyval.declarator_list)->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, (yyvsp[(3) - (6)].identifier), ir_var_auto));
        ;}
     break;
 
-  case 123:
+  case 134:
 
 /* Line 1464 of yacc.c  */
-#line 861 "glsl_parser.ypp"
+#line 938 "glsl_parser.ypp"
     {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (7)].identifier), true, NULL, (yyvsp[(7) - (7)].expression));
@@ -3735,13 +3819,14 @@ yyreduce:
 
           (yyval.declarator_list) = (yyvsp[(1) - (7)].declarator_list);
           (yyval.declarator_list)->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, (yyvsp[(3) - (7)].identifier), ir_var_auto));
        ;}
     break;
 
-  case 124:
+  case 135:
 
 /* Line 1464 of yacc.c  */
-#line 870 "glsl_parser.ypp"
+#line 948 "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));
@@ -3749,13 +3834,14 @@ yyreduce:
 
           (yyval.declarator_list) = (yyvsp[(1) - (8)].declarator_list);
           (yyval.declarator_list)->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, (yyvsp[(3) - (8)].identifier), ir_var_auto));
        ;}
     break;
 
-  case 125:
+  case 136:
 
 /* Line 1464 of yacc.c  */
-#line 879 "glsl_parser.ypp"
+#line 958 "glsl_parser.ypp"
     {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(3) - (5)].identifier), false, NULL, (yyvsp[(5) - (5)].expression));
@@ -3763,13 +3849,14 @@ yyreduce:
 
           (yyval.declarator_list) = (yyvsp[(1) - (5)].declarator_list);
           (yyval.declarator_list)->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, (yyvsp[(3) - (5)].identifier), ir_var_auto));
        ;}
     break;
 
-  case 126:
+  case 137:
 
 /* Line 1464 of yacc.c  */
-#line 892 "glsl_parser.ypp"
+#line 972 "glsl_parser.ypp"
     {
           void *ctx = state;
           if ((yyvsp[(1) - (1)].fully_specified_type)->specifier->type_specifier != ast_struct) {
@@ -3782,10 +3869,10 @@ yyreduce:
        ;}
     break;
 
-  case 127:
+  case 138:
 
 /* Line 1464 of yacc.c  */
-#line 903 "glsl_parser.ypp"
+#line 983 "glsl_parser.ypp"
     {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (2)].identifier), false, NULL, NULL);
@@ -3796,10 +3883,10 @@ yyreduce:
        ;}
     break;
 
-  case 128:
+  case 139:
 
 /* Line 1464 of yacc.c  */
-#line 912 "glsl_parser.ypp"
+#line 992 "glsl_parser.ypp"
     {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (4)].identifier), true, NULL, NULL);
@@ -3810,10 +3897,10 @@ yyreduce:
        ;}
     break;
 
-  case 129:
+  case 140:
 
 /* Line 1464 of yacc.c  */
-#line 921 "glsl_parser.ypp"
+#line 1001 "glsl_parser.ypp"
     {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (5)].identifier), true, (yyvsp[(4) - (5)].expression), NULL);
@@ -3824,10 +3911,10 @@ yyreduce:
        ;}
     break;
 
-  case 130:
+  case 141:
 
 /* Line 1464 of yacc.c  */
-#line 930 "glsl_parser.ypp"
+#line 1010 "glsl_parser.ypp"
     {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (6)].identifier), true, NULL, (yyvsp[(6) - (6)].expression));
@@ -3838,10 +3925,10 @@ yyreduce:
        ;}
     break;
 
-  case 131:
+  case 142:
 
 /* Line 1464 of yacc.c  */
-#line 939 "glsl_parser.ypp"
+#line 1019 "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));
@@ -3852,10 +3939,10 @@ yyreduce:
        ;}
     break;
 
-  case 132:
+  case 143:
 
 /* Line 1464 of yacc.c  */
-#line 948 "glsl_parser.ypp"
+#line 1028 "glsl_parser.ypp"
     {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (4)].identifier), false, NULL, (yyvsp[(4) - (4)].expression));
@@ -3866,10 +3953,10 @@ yyreduce:
        ;}
     break;
 
-  case 133:
+  case 144:
 
 /* Line 1464 of yacc.c  */
-#line 957 "glsl_parser.ypp"
+#line 1037 "glsl_parser.ypp"
     {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (2)].identifier), false, NULL, NULL);
@@ -3882,10 +3969,10 @@ yyreduce:
        ;}
     break;
 
-  case 134:
+  case 145:
 
 /* Line 1464 of yacc.c  */
-#line 971 "glsl_parser.ypp"
+#line 1051 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.fully_specified_type) = new(ctx) ast_fully_specified_type();
@@ -3894,10 +3981,10 @@ yyreduce:
        ;}
     break;
 
-  case 135:
+  case 146:
 
 /* Line 1464 of yacc.c  */
-#line 978 "glsl_parser.ypp"
+#line 1058 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.fully_specified_type) = new(ctx) ast_fully_specified_type();
@@ -3907,19 +3994,19 @@ yyreduce:
        ;}
     break;
 
-  case 136:
+  case 147:
 
 /* Line 1464 of yacc.c  */
-#line 989 "glsl_parser.ypp"
+#line 1069 "glsl_parser.ypp"
     {
          (yyval.type_qualifier) = (yyvsp[(3) - (4)].type_qualifier);
        ;}
     break;
 
-  case 138:
+  case 149:
 
 /* Line 1464 of yacc.c  */
-#line 997 "glsl_parser.ypp"
+#line 1077 "glsl_parser.ypp"
     {
           if (((yyvsp[(1) - (3)].type_qualifier).flags.i & (yyvsp[(3) - (3)].type_qualifier).flags.i) != 0) {
              _mesa_glsl_error(& (yylsp[(3) - (3)]), state,
@@ -3937,16 +4024,17 @@ yyreduce:
        ;}
     break;
 
-  case 139:
+  case 150:
 
 /* Line 1464 of yacc.c  */
-#line 1016 "glsl_parser.ypp"
+#line 1096 "glsl_parser.ypp"
     {
           bool got_one = false;
 
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
 
-          if (state->ARB_fragment_coord_conventions_enable) {
+          /* Layout qualifiers for ARB_fragment_coord_conventions. */
+          if (!got_one && state->ARB_fragment_coord_conventions_enable) {
              if (strcmp((yyvsp[(1) - (1)].identifier), "origin_upper_left") == 0) {
                 got_one = true;
                 (yyval.type_qualifier).flags.q.origin_upper_left = 1;
@@ -3954,27 +4042,49 @@ yyreduce:
                 got_one = true;
                 (yyval.type_qualifier).flags.q.pixel_center_integer = 1;
              }
+
+             if (got_one && state->ARB_fragment_coord_conventions_warn) {
+                _mesa_glsl_warning(& (yylsp[(1) - (1)]), state,
+                                   "GL_ARB_fragment_coord_conventions layout "
+                                   "identifier `%s' used\n", (yyvsp[(1) - (1)].identifier));
+             }
+          }
+
+          /* Layout qualifiers for AMD_conservative_depth. */
+          if (!got_one && state->AMD_conservative_depth_enable) {
+             if (strcmp((yyvsp[(1) - (1)].identifier), "depth_any") == 0) {
+                got_one = true;
+                (yyval.type_qualifier).flags.q.depth_any = 1;
+             } else if (strcmp((yyvsp[(1) - (1)].identifier), "depth_greater") == 0) {
+                got_one = true;
+                (yyval.type_qualifier).flags.q.depth_greater = 1;
+             } else if (strcmp((yyvsp[(1) - (1)].identifier), "depth_less") == 0) {
+                got_one = true;
+                (yyval.type_qualifier).flags.q.depth_less = 1;
+             } else if (strcmp((yyvsp[(1) - (1)].identifier), "depth_unchanged") == 0) {
+                got_one = true;
+                (yyval.type_qualifier).flags.q.depth_unchanged = 1;
+             }
+       
+             if (got_one && state->AMD_conservative_depth_warn) {
+                _mesa_glsl_warning(& (yylsp[(1) - (1)]), state,
+                                   "GL_AMD_conservative_depth "
+                                   "layout qualifier `%s' is used\n", (yyvsp[(1) - (1)].identifier));
+             }
           }
 
-          /* If the identifier didn't match any known layout identifiers,
-           * emit an error.
-           */
           if (!got_one) {
              _mesa_glsl_error(& (yylsp[(1) - (1)]), state, "unrecognized layout identifier "
                               "`%s'\n", (yyvsp[(1) - (1)].identifier));
              YYERROR;
-          } else if (state->ARB_fragment_coord_conventions_warn) {
-             _mesa_glsl_warning(& (yylsp[(1) - (1)]), state,
-                                "GL_ARB_fragment_coord_conventions layout "
-                                "identifier `%s' used\n", (yyvsp[(1) - (1)].identifier));
           }
        ;}
     break;
 
-  case 140:
+  case 151:
 
 /* Line 1464 of yacc.c  */
-#line 1045 "glsl_parser.ypp"
+#line 1148 "glsl_parser.ypp"
     {
           bool got_one = false;
 
@@ -4014,80 +4124,80 @@ yyreduce:
        ;}
     break;
 
-  case 141:
+  case 152:
 
 /* Line 1464 of yacc.c  */
-#line 1086 "glsl_parser.ypp"
+#line 1189 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.smooth = 1;
        ;}
     break;
 
-  case 142:
+  case 153:
 
 /* Line 1464 of yacc.c  */
-#line 1091 "glsl_parser.ypp"
+#line 1194 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.flat = 1;
        ;}
     break;
 
-  case 143:
+  case 154:
 
 /* Line 1464 of yacc.c  */
-#line 1096 "glsl_parser.ypp"
+#line 1199 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.noperspective = 1;
        ;}
     break;
 
-  case 144:
+  case 155:
 
 /* Line 1464 of yacc.c  */
-#line 1104 "glsl_parser.ypp"
+#line 1207 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.constant = 1;
        ;}
     break;
 
-  case 147:
+  case 158:
 
 /* Line 1464 of yacc.c  */
-#line 1114 "glsl_parser.ypp"
+#line 1217 "glsl_parser.ypp"
     {
           (yyval.type_qualifier) = (yyvsp[(1) - (2)].type_qualifier);
           (yyval.type_qualifier).flags.i |= (yyvsp[(2) - (2)].type_qualifier).flags.i;
        ;}
     break;
 
-  case 149:
+  case 160:
 
 /* Line 1464 of yacc.c  */
-#line 1120 "glsl_parser.ypp"
+#line 1223 "glsl_parser.ypp"
     {
           (yyval.type_qualifier) = (yyvsp[(1) - (2)].type_qualifier);
           (yyval.type_qualifier).flags.i |= (yyvsp[(2) - (2)].type_qualifier).flags.i;
        ;}
     break;
 
-  case 150:
+  case 161:
 
 /* Line 1464 of yacc.c  */
-#line 1125 "glsl_parser.ypp"
+#line 1228 "glsl_parser.ypp"
     {
           (yyval.type_qualifier) = (yyvsp[(2) - (2)].type_qualifier);
           (yyval.type_qualifier).flags.q.invariant = 1;
        ;}
     break;
 
-  case 151:
+  case 162:
 
 /* Line 1464 of yacc.c  */
-#line 1130 "glsl_parser.ypp"
+#line 1233 "glsl_parser.ypp"
     {
           (yyval.type_qualifier) = (yyvsp[(2) - (3)].type_qualifier);
           (yyval.type_qualifier).flags.i |= (yyvsp[(3) - (3)].type_qualifier).flags.i;
@@ -4095,50 +4205,50 @@ yyreduce:
        ;}
     break;
 
-  case 152:
+  case 163:
 
 /* Line 1464 of yacc.c  */
-#line 1136 "glsl_parser.ypp"
+#line 1239 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.invariant = 1;
        ;}
     break;
 
-  case 153:
+  case 164:
 
 /* Line 1464 of yacc.c  */
-#line 1144 "glsl_parser.ypp"
+#line 1247 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.constant = 1;
        ;}
     break;
 
-  case 154:
+  case 165:
 
 /* Line 1464 of yacc.c  */
-#line 1149 "glsl_parser.ypp"
+#line 1252 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.attribute = 1;
        ;}
     break;
 
-  case 155:
+  case 166:
 
 /* Line 1464 of yacc.c  */
-#line 1154 "glsl_parser.ypp"
+#line 1257 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.varying = 1;
        ;}
     break;
 
-  case 156:
+  case 167:
 
 /* Line 1464 of yacc.c  */
-#line 1159 "glsl_parser.ypp"
+#line 1262 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.centroid = 1;
@@ -4146,79 +4256,79 @@ yyreduce:
        ;}
     break;
 
-  case 157:
+  case 168:
 
 /* Line 1464 of yacc.c  */
-#line 1165 "glsl_parser.ypp"
+#line 1268 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.in = 1;
        ;}
     break;
 
-  case 158:
+  case 169:
 
 /* Line 1464 of yacc.c  */
-#line 1170 "glsl_parser.ypp"
+#line 1273 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.out = 1;
        ;}
     break;
 
-  case 159:
+  case 170:
 
 /* Line 1464 of yacc.c  */
-#line 1175 "glsl_parser.ypp"
+#line 1278 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.centroid = 1; (yyval.type_qualifier).flags.q.in = 1;
        ;}
     break;
 
-  case 160:
+  case 171:
 
 /* Line 1464 of yacc.c  */
-#line 1180 "glsl_parser.ypp"
+#line 1283 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.centroid = 1; (yyval.type_qualifier).flags.q.out = 1;
        ;}
     break;
 
-  case 161:
+  case 172:
 
 /* Line 1464 of yacc.c  */
-#line 1185 "glsl_parser.ypp"
+#line 1288 "glsl_parser.ypp"
     {
           memset(& (yyval.type_qualifier), 0, sizeof((yyval.type_qualifier)));
           (yyval.type_qualifier).flags.q.uniform = 1;
        ;}
     break;
 
-  case 162:
+  case 173:
 
 /* Line 1464 of yacc.c  */
-#line 1193 "glsl_parser.ypp"
+#line 1296 "glsl_parser.ypp"
     {
           (yyval.type_specifier) = (yyvsp[(1) - (1)].type_specifier);
        ;}
     break;
 
-  case 163:
+  case 174:
 
 /* Line 1464 of yacc.c  */
-#line 1197 "glsl_parser.ypp"
+#line 1300 "glsl_parser.ypp"
     {
           (yyval.type_specifier) = (yyvsp[(2) - (2)].type_specifier);
           (yyval.type_specifier)->precision = (yyvsp[(1) - (2)].n);
        ;}
     break;
 
-  case 165:
+  case 176:
 
 /* Line 1464 of yacc.c  */
-#line 1206 "glsl_parser.ypp"
+#line 1309 "glsl_parser.ypp"
     {
           (yyval.type_specifier) = (yyvsp[(1) - (3)].type_specifier);
           (yyval.type_specifier)->is_array = true;
@@ -4226,10 +4336,10 @@ yyreduce:
        ;}
     break;
 
-  case 166:
+  case 177:
 
 /* Line 1464 of yacc.c  */
-#line 1212 "glsl_parser.ypp"
+#line 1315 "glsl_parser.ypp"
     {
           (yyval.type_specifier) = (yyvsp[(1) - (4)].type_specifier);
           (yyval.type_specifier)->is_array = true;
@@ -4237,10 +4347,10 @@ yyreduce:
        ;}
     break;
 
-  case 167:
+  case 178:
 
 /* Line 1464 of yacc.c  */
-#line 1221 "glsl_parser.ypp"
+#line 1324 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.type_specifier) = new(ctx) ast_type_specifier((yyvsp[(1) - (1)].n));
@@ -4248,10 +4358,10 @@ yyreduce:
        ;}
     break;
 
-  case 168:
+  case 179:
 
 /* Line 1464 of yacc.c  */
-#line 1227 "glsl_parser.ypp"
+#line 1330 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.type_specifier) = new(ctx) ast_type_specifier((yyvsp[(1) - (1)].struct_specifier));
@@ -4259,10 +4369,10 @@ yyreduce:
        ;}
     break;
 
-  case 169:
+  case 180:
 
 /* Line 1464 of yacc.c  */
-#line 1233 "glsl_parser.ypp"
+#line 1336 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.type_specifier) = new(ctx) ast_type_specifier((yyvsp[(1) - (1)].identifier));
@@ -4270,367 +4380,367 @@ yyreduce:
        ;}
     break;
 
-  case 170:
+  case 181:
 
 /* Line 1464 of yacc.c  */
-#line 1241 "glsl_parser.ypp"
+#line 1344 "glsl_parser.ypp"
     { (yyval.n) = ast_void; ;}
     break;
 
-  case 171:
+  case 182:
 
 /* Line 1464 of yacc.c  */
-#line 1242 "glsl_parser.ypp"
+#line 1345 "glsl_parser.ypp"
     { (yyval.n) = ast_float; ;}
     break;
 
-  case 172:
+  case 183:
 
 /* Line 1464 of yacc.c  */
-#line 1243 "glsl_parser.ypp"
+#line 1346 "glsl_parser.ypp"
     { (yyval.n) = ast_int; ;}
     break;
 
-  case 173:
+  case 184:
 
 /* Line 1464 of yacc.c  */
-#line 1244 "glsl_parser.ypp"
+#line 1347 "glsl_parser.ypp"
     { (yyval.n) = ast_uint; ;}
     break;
 
-  case 174:
+  case 185:
 
 /* Line 1464 of yacc.c  */
-#line 1245 "glsl_parser.ypp"
+#line 1348 "glsl_parser.ypp"
     { (yyval.n) = ast_bool; ;}
     break;
 
-  case 175:
+  case 186:
 
 /* Line 1464 of yacc.c  */
-#line 1246 "glsl_parser.ypp"
+#line 1349 "glsl_parser.ypp"
     { (yyval.n) = ast_vec2; ;}
     break;
 
-  case 176:
+  case 187:
 
 /* Line 1464 of yacc.c  */
-#line 1247 "glsl_parser.ypp"
+#line 1350 "glsl_parser.ypp"
     { (yyval.n) = ast_vec3; ;}
     break;
 
-  case 177:
+  case 188:
 
 /* Line 1464 of yacc.c  */
-#line 1248 "glsl_parser.ypp"
+#line 1351 "glsl_parser.ypp"
     { (yyval.n) = ast_vec4; ;}
     break;
 
-  case 178:
+  case 189:
 
 /* Line 1464 of yacc.c  */
-#line 1249 "glsl_parser.ypp"
+#line 1352 "glsl_parser.ypp"
     { (yyval.n) = ast_bvec2; ;}
     break;
 
-  case 179:
+  case 190:
 
 /* Line 1464 of yacc.c  */
-#line 1250 "glsl_parser.ypp"
+#line 1353 "glsl_parser.ypp"
     { (yyval.n) = ast_bvec3; ;}
     break;
 
-  case 180:
+  case 191:
 
 /* Line 1464 of yacc.c  */
-#line 1251 "glsl_parser.ypp"
+#line 1354 "glsl_parser.ypp"
     { (yyval.n) = ast_bvec4; ;}
     break;
 
-  case 181:
+  case 192:
 
 /* Line 1464 of yacc.c  */
-#line 1252 "glsl_parser.ypp"
+#line 1355 "glsl_parser.ypp"
     { (yyval.n) = ast_ivec2; ;}
     break;
 
-  case 182:
+  case 193:
 
 /* Line 1464 of yacc.c  */
-#line 1253 "glsl_parser.ypp"
+#line 1356 "glsl_parser.ypp"
     { (yyval.n) = ast_ivec3; ;}
     break;
 
-  case 183:
+  case 194:
 
 /* Line 1464 of yacc.c  */
-#line 1254 "glsl_parser.ypp"
+#line 1357 "glsl_parser.ypp"
     { (yyval.n) = ast_ivec4; ;}
     break;
 
-  case 184:
+  case 195:
 
 /* Line 1464 of yacc.c  */
-#line 1255 "glsl_parser.ypp"
+#line 1358 "glsl_parser.ypp"
     { (yyval.n) = ast_uvec2; ;}
     break;
 
-  case 185:
+  case 196:
 
 /* Line 1464 of yacc.c  */
-#line 1256 "glsl_parser.ypp"
+#line 1359 "glsl_parser.ypp"
     { (yyval.n) = ast_uvec3; ;}
     break;
 
-  case 186:
+  case 197:
 
 /* Line 1464 of yacc.c  */
-#line 1257 "glsl_parser.ypp"
+#line 1360 "glsl_parser.ypp"
     { (yyval.n) = ast_uvec4; ;}
     break;
 
-  case 187:
+  case 198:
 
 /* Line 1464 of yacc.c  */
-#line 1258 "glsl_parser.ypp"
+#line 1361 "glsl_parser.ypp"
     { (yyval.n) = ast_mat2; ;}
     break;
 
-  case 188:
+  case 199:
 
 /* Line 1464 of yacc.c  */
-#line 1259 "glsl_parser.ypp"
+#line 1362 "glsl_parser.ypp"
     { (yyval.n) = ast_mat2x3; ;}
     break;
 
-  case 189:
+  case 200:
 
 /* Line 1464 of yacc.c  */
-#line 1260 "glsl_parser.ypp"
+#line 1363 "glsl_parser.ypp"
     { (yyval.n) = ast_mat2x4; ;}
     break;
 
-  case 190:
+  case 201:
 
 /* Line 1464 of yacc.c  */
-#line 1261 "glsl_parser.ypp"
+#line 1364 "glsl_parser.ypp"
     { (yyval.n) = ast_mat3x2; ;}
     break;
 
-  case 191:
+  case 202:
 
 /* Line 1464 of yacc.c  */
-#line 1262 "glsl_parser.ypp"
+#line 1365 "glsl_parser.ypp"
     { (yyval.n) = ast_mat3; ;}
     break;
 
-  case 192:
+  case 203:
 
 /* Line 1464 of yacc.c  */
-#line 1263 "glsl_parser.ypp"
+#line 1366 "glsl_parser.ypp"
     { (yyval.n) = ast_mat3x4; ;}
     break;
 
-  case 193:
+  case 204:
 
 /* Line 1464 of yacc.c  */
-#line 1264 "glsl_parser.ypp"
+#line 1367 "glsl_parser.ypp"
     { (yyval.n) = ast_mat4x2; ;}
     break;
 
-  case 194:
+  case 205:
 
 /* Line 1464 of yacc.c  */
-#line 1265 "glsl_parser.ypp"
+#line 1368 "glsl_parser.ypp"
     { (yyval.n) = ast_mat4x3; ;}
     break;
 
-  case 195:
+  case 206:
 
 /* Line 1464 of yacc.c  */
-#line 1266 "glsl_parser.ypp"
+#line 1369 "glsl_parser.ypp"
     { (yyval.n) = ast_mat4; ;}
     break;
 
-  case 196:
+  case 207:
 
 /* Line 1464 of yacc.c  */
-#line 1267 "glsl_parser.ypp"
+#line 1370 "glsl_parser.ypp"
     { (yyval.n) = ast_sampler1d; ;}
     break;
 
-  case 197:
+  case 208:
 
 /* Line 1464 of yacc.c  */
-#line 1268 "glsl_parser.ypp"
+#line 1371 "glsl_parser.ypp"
     { (yyval.n) = ast_sampler2d; ;}
     break;
 
-  case 198:
+  case 209:
 
 /* Line 1464 of yacc.c  */
-#line 1269 "glsl_parser.ypp"
+#line 1372 "glsl_parser.ypp"
     { (yyval.n) = ast_sampler2drect; ;}
     break;
 
-  case 199:
+  case 210:
 
 /* Line 1464 of yacc.c  */
-#line 1270 "glsl_parser.ypp"
+#line 1373 "glsl_parser.ypp"
     { (yyval.n) = ast_sampler3d; ;}
     break;
 
-  case 200:
+  case 211:
 
 /* Line 1464 of yacc.c  */
-#line 1271 "glsl_parser.ypp"
+#line 1374 "glsl_parser.ypp"
     { (yyval.n) = ast_samplercube; ;}
     break;
 
-  case 201:
+  case 212:
 
 /* Line 1464 of yacc.c  */
-#line 1272 "glsl_parser.ypp"
+#line 1375 "glsl_parser.ypp"
     { (yyval.n) = ast_sampler1dshadow; ;}
     break;
 
-  case 202:
+  case 213:
 
 /* Line 1464 of yacc.c  */
-#line 1273 "glsl_parser.ypp"
+#line 1376 "glsl_parser.ypp"
     { (yyval.n) = ast_sampler2dshadow; ;}
     break;
 
-  case 203:
+  case 214:
 
 /* Line 1464 of yacc.c  */
-#line 1274 "glsl_parser.ypp"
+#line 1377 "glsl_parser.ypp"
     { (yyval.n) = ast_sampler2drectshadow; ;}
     break;
 
-  case 204:
+  case 215:
 
 /* Line 1464 of yacc.c  */
-#line 1275 "glsl_parser.ypp"
+#line 1378 "glsl_parser.ypp"
     { (yyval.n) = ast_samplercubeshadow; ;}
     break;
 
-  case 205:
+  case 216:
 
 /* Line 1464 of yacc.c  */
-#line 1276 "glsl_parser.ypp"
+#line 1379 "glsl_parser.ypp"
     { (yyval.n) = ast_sampler1darray; ;}
     break;
 
-  case 206:
+  case 217:
 
 /* Line 1464 of yacc.c  */
-#line 1277 "glsl_parser.ypp"
+#line 1380 "glsl_parser.ypp"
     { (yyval.n) = ast_sampler2darray; ;}
     break;
 
-  case 207:
+  case 218:
 
 /* Line 1464 of yacc.c  */
-#line 1278 "glsl_parser.ypp"
+#line 1381 "glsl_parser.ypp"
     { (yyval.n) = ast_sampler1darrayshadow; ;}
     break;
 
-  case 208:
+  case 219:
 
 /* Line 1464 of yacc.c  */
-#line 1279 "glsl_parser.ypp"
+#line 1382 "glsl_parser.ypp"
     { (yyval.n) = ast_sampler2darrayshadow; ;}
     break;
 
-  case 209:
+  case 220:
 
 /* Line 1464 of yacc.c  */
-#line 1280 "glsl_parser.ypp"
+#line 1383 "glsl_parser.ypp"
     { (yyval.n) = ast_isampler1d; ;}
     break;
 
-  case 210:
+  case 221:
 
 /* Line 1464 of yacc.c  */
-#line 1281 "glsl_parser.ypp"
+#line 1384 "glsl_parser.ypp"
     { (yyval.n) = ast_isampler2d; ;}
     break;
 
-  case 211:
+  case 222:
 
 /* Line 1464 of yacc.c  */
-#line 1282 "glsl_parser.ypp"
+#line 1385 "glsl_parser.ypp"
     { (yyval.n) = ast_isampler3d; ;}
     break;
 
-  case 212:
+  case 223:
 
 /* Line 1464 of yacc.c  */
-#line 1283 "glsl_parser.ypp"
+#line 1386 "glsl_parser.ypp"
     { (yyval.n) = ast_isamplercube; ;}
     break;
 
-  case 213:
+  case 224:
 
 /* Line 1464 of yacc.c  */
-#line 1284 "glsl_parser.ypp"
+#line 1387 "glsl_parser.ypp"
     { (yyval.n) = ast_isampler1darray; ;}
     break;
 
-  case 214:
+  case 225:
 
 /* Line 1464 of yacc.c  */
-#line 1285 "glsl_parser.ypp"
+#line 1388 "glsl_parser.ypp"
     { (yyval.n) = ast_isampler2darray; ;}
     break;
 
-  case 215:
+  case 226:
 
 /* Line 1464 of yacc.c  */
-#line 1286 "glsl_parser.ypp"
+#line 1389 "glsl_parser.ypp"
     { (yyval.n) = ast_usampler1d; ;}
     break;
 
-  case 216:
+  case 227:
 
 /* Line 1464 of yacc.c  */
-#line 1287 "glsl_parser.ypp"
+#line 1390 "glsl_parser.ypp"
     { (yyval.n) = ast_usampler2d; ;}
     break;
 
-  case 217:
+  case 228:
 
 /* Line 1464 of yacc.c  */
-#line 1288 "glsl_parser.ypp"
+#line 1391 "glsl_parser.ypp"
     { (yyval.n) = ast_usampler3d; ;}
     break;
 
-  case 218:
+  case 229:
 
 /* Line 1464 of yacc.c  */
-#line 1289 "glsl_parser.ypp"
+#line 1392 "glsl_parser.ypp"
     { (yyval.n) = ast_usamplercube; ;}
     break;
 
-  case 219:
+  case 230:
 
 /* Line 1464 of yacc.c  */
-#line 1290 "glsl_parser.ypp"
+#line 1393 "glsl_parser.ypp"
     { (yyval.n) = ast_usampler1darray; ;}
     break;
 
-  case 220:
+  case 231:
 
 /* Line 1464 of yacc.c  */
-#line 1291 "glsl_parser.ypp"
+#line 1394 "glsl_parser.ypp"
     { (yyval.n) = ast_usampler2darray; ;}
     break;
 
-  case 221:
+  case 232:
 
 /* Line 1464 of yacc.c  */
-#line 1295 "glsl_parser.ypp"
+#line 1398 "glsl_parser.ypp"
     {
                     if (!state->es_shader && state->language_version < 130)
                        _mesa_glsl_error(& (yylsp[(1) - (1)]), state,
@@ -4643,10 +4753,10 @@ yyreduce:
                  ;}
     break;
 
-  case 222:
+  case 233:
 
 /* Line 1464 of yacc.c  */
-#line 1305 "glsl_parser.ypp"
+#line 1408 "glsl_parser.ypp"
     {
                     if (!state->es_shader && state->language_version < 130)
                        _mesa_glsl_error(& (yylsp[(1) - (1)]), state,
@@ -4659,10 +4769,10 @@ yyreduce:
                  ;}
     break;
 
-  case 223:
+  case 234:
 
 /* Line 1464 of yacc.c  */
-#line 1315 "glsl_parser.ypp"
+#line 1418 "glsl_parser.ypp"
     {
                     if (!state->es_shader && state->language_version < 130)
                        _mesa_glsl_error(& (yylsp[(1) - (1)]), state,
@@ -4675,21 +4785,22 @@ yyreduce:
                  ;}
     break;
 
-  case 224:
+  case 235:
 
 /* Line 1464 of yacc.c  */
-#line 1329 "glsl_parser.ypp"
+#line 1432 "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);
+          state->symbols->add_type((yyvsp[(2) - (5)].identifier), glsl_type::void_type);
        ;}
     break;
 
-  case 225:
+  case 236:
 
 /* Line 1464 of yacc.c  */
-#line 1335 "glsl_parser.ypp"
+#line 1439 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.struct_specifier) = new(ctx) ast_struct_specifier(NULL, (yyvsp[(3) - (4)].node));
@@ -4697,30 +4808,30 @@ yyreduce:
        ;}
     break;
 
-  case 226:
+  case 237:
 
 /* Line 1464 of yacc.c  */
-#line 1344 "glsl_parser.ypp"
+#line 1448 "glsl_parser.ypp"
     {
           (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].declarator_list);
           (yyvsp[(1) - (1)].declarator_list)->link.self_link();
        ;}
     break;
 
-  case 227:
+  case 238:
 
 /* Line 1464 of yacc.c  */
-#line 1349 "glsl_parser.ypp"
+#line 1453 "glsl_parser.ypp"
     {
           (yyval.node) = (ast_node *) (yyvsp[(1) - (2)].node);
           (yyval.node)->link.insert_before(& (yyvsp[(2) - (2)].declarator_list)->link);
        ;}
     break;
 
-  case 228:
+  case 239:
 
 /* Line 1464 of yacc.c  */
-#line 1357 "glsl_parser.ypp"
+#line 1461 "glsl_parser.ypp"
     {
           void *ctx = state;
           ast_fully_specified_type *type = new(ctx) ast_fully_specified_type();
@@ -4734,41 +4845,42 @@ yyreduce:
        ;}
     break;
 
-  case 229:
+  case 240:
 
 /* Line 1464 of yacc.c  */
-#line 1372 "glsl_parser.ypp"
+#line 1476 "glsl_parser.ypp"
     {
           (yyval.declaration) = (yyvsp[(1) - (1)].declaration);
           (yyvsp[(1) - (1)].declaration)->link.self_link();
        ;}
     break;
 
-  case 230:
+  case 241:
 
 /* Line 1464 of yacc.c  */
-#line 1377 "glsl_parser.ypp"
+#line 1481 "glsl_parser.ypp"
     {
           (yyval.declaration) = (yyvsp[(1) - (3)].declaration);
           (yyval.declaration)->link.insert_before(& (yyvsp[(3) - (3)].declaration)->link);
        ;}
     break;
 
-  case 231:
+  case 242:
 
 /* Line 1464 of yacc.c  */
-#line 1385 "glsl_parser.ypp"
+#line 1489 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.declaration) = new(ctx) ast_declaration((yyvsp[(1) - (1)].identifier), false, NULL, NULL);
           (yyval.declaration)->set_location(yylloc);
+          state->symbols->add_variable(new(state) ir_variable(NULL, (yyvsp[(1) - (1)].identifier), ir_var_auto));
        ;}
     break;
 
-  case 232:
+  case 243:
 
 /* Line 1464 of yacc.c  */
-#line 1391 "glsl_parser.ypp"
+#line 1496 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.declaration) = new(ctx) ast_declaration((yyvsp[(1) - (4)].identifier), true, (yyvsp[(3) - (4)].expression), NULL);
@@ -4776,31 +4888,31 @@ yyreduce:
        ;}
     break;
 
-  case 235:
+  case 246:
 
 /* Line 1464 of yacc.c  */
-#line 1409 "glsl_parser.ypp"
+#line 1514 "glsl_parser.ypp"
     { (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].compound_statement); ;}
     break;
 
-  case 240:
+  case 251:
 
 /* Line 1464 of yacc.c  */
-#line 1417 "glsl_parser.ypp"
+#line 1522 "glsl_parser.ypp"
     { (yyval.node) = NULL; ;}
     break;
 
-  case 241:
+  case 252:
 
 /* Line 1464 of yacc.c  */
-#line 1418 "glsl_parser.ypp"
+#line 1523 "glsl_parser.ypp"
     { (yyval.node) = NULL; ;}
     break;
 
-  case 244:
+  case 255:
 
 /* Line 1464 of yacc.c  */
-#line 1425 "glsl_parser.ypp"
+#line 1530 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.compound_statement) = new(ctx) ast_compound_statement(true, NULL);
@@ -4808,28 +4920,38 @@ yyreduce:
        ;}
     break;
 
-  case 245:
+  case 256:
+
+/* Line 1464 of yacc.c  */
+#line 1536 "glsl_parser.ypp"
+    {
+          state->symbols->push_scope();
+       ;}
+    break;
+
+  case 257:
 
 /* Line 1464 of yacc.c  */
-#line 1431 "glsl_parser.ypp"
+#line 1540 "glsl_parser.ypp"
     {
           void *ctx = state;
-          (yyval.compound_statement) = new(ctx) ast_compound_statement(true, (yyvsp[(2) - (3)].node));
+          (yyval.compound_statement) = new(ctx) ast_compound_statement(true, (yyvsp[(3) - (4)].node));
           (yyval.compound_statement)->set_location(yylloc);
+          state->symbols->pop_scope();
        ;}
     break;
 
-  case 246:
+  case 258:
 
 /* Line 1464 of yacc.c  */
-#line 1439 "glsl_parser.ypp"
+#line 1549 "glsl_parser.ypp"
     { (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].compound_statement); ;}
     break;
 
-  case 248:
+  case 260:
 
 /* Line 1464 of yacc.c  */
-#line 1445 "glsl_parser.ypp"
+#line 1555 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.compound_statement) = new(ctx) ast_compound_statement(false, NULL);
@@ -4837,10 +4959,10 @@ yyreduce:
        ;}
     break;
 
-  case 249:
+  case 261:
 
 /* Line 1464 of yacc.c  */
-#line 1451 "glsl_parser.ypp"
+#line 1561 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.compound_statement) = new(ctx) ast_compound_statement(false, (yyvsp[(2) - (3)].node));
@@ -4848,10 +4970,10 @@ yyreduce:
        ;}
     break;
 
-  case 250:
+  case 262:
 
 /* Line 1464 of yacc.c  */
-#line 1460 "glsl_parser.ypp"
+#line 1570 "glsl_parser.ypp"
     {
           if ((yyvsp[(1) - (1)].node) == NULL) {
              _mesa_glsl_error(& (yylsp[(1) - (1)]), state, "<nil> statement\n");
@@ -4863,10 +4985,10 @@ yyreduce:
        ;}
     break;
 
-  case 251:
+  case 263:
 
 /* Line 1464 of yacc.c  */
-#line 1470 "glsl_parser.ypp"
+#line 1580 "glsl_parser.ypp"
     {
           if ((yyvsp[(2) - (2)].node) == NULL) {
              _mesa_glsl_error(& (yylsp[(2) - (2)]), state, "<nil> statement\n");
@@ -4877,10 +4999,10 @@ yyreduce:
        ;}
     break;
 
-  case 252:
+  case 264:
 
 /* Line 1464 of yacc.c  */
-#line 1482 "glsl_parser.ypp"
+#line 1592 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.node) = new(ctx) ast_expression_statement(NULL);
@@ -4888,10 +5010,10 @@ yyreduce:
        ;}
     break;
 
-  case 253:
+  case 265:
 
 /* Line 1464 of yacc.c  */
-#line 1488 "glsl_parser.ypp"
+#line 1598 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.node) = new(ctx) ast_expression_statement((yyvsp[(1) - (2)].expression));
@@ -4899,10 +5021,10 @@ yyreduce:
        ;}
     break;
 
-  case 254:
+  case 266:
 
 /* Line 1464 of yacc.c  */
-#line 1497 "glsl_parser.ypp"
+#line 1607 "glsl_parser.ypp"
     {
           (yyval.node) = new(state) ast_selection_statement((yyvsp[(3) - (5)].expression), (yyvsp[(5) - (5)].selection_rest_statement).then_statement,
                                                   (yyvsp[(5) - (5)].selection_rest_statement).else_statement);
@@ -4910,39 +5032,39 @@ yyreduce:
        ;}
     break;
 
-  case 255:
+  case 267:
 
 /* Line 1464 of yacc.c  */
-#line 1506 "glsl_parser.ypp"
+#line 1616 "glsl_parser.ypp"
     {
           (yyval.selection_rest_statement).then_statement = (yyvsp[(1) - (3)].node);
           (yyval.selection_rest_statement).else_statement = (yyvsp[(3) - (3)].node);
        ;}
     break;
 
-  case 256:
+  case 268:
 
 /* Line 1464 of yacc.c  */
-#line 1511 "glsl_parser.ypp"
+#line 1621 "glsl_parser.ypp"
     {
           (yyval.selection_rest_statement).then_statement = (yyvsp[(1) - (1)].node);
           (yyval.selection_rest_statement).else_statement = NULL;
        ;}
     break;
 
-  case 257:
+  case 269:
 
 /* Line 1464 of yacc.c  */
-#line 1519 "glsl_parser.ypp"
+#line 1629 "glsl_parser.ypp"
     {
           (yyval.node) = (ast_node *) (yyvsp[(1) - (1)].expression);
        ;}
     break;
 
-  case 258:
+  case 270:
 
 /* Line 1464 of yacc.c  */
-#line 1523 "glsl_parser.ypp"
+#line 1633 "glsl_parser.ypp"
     {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration((yyvsp[(2) - (4)].identifier), false, NULL, (yyvsp[(4) - (4)].expression));
@@ -4955,10 +5077,10 @@ yyreduce:
        ;}
     break;
 
-  case 262:
+  case 274:
 
 /* Line 1464 of yacc.c  */
-#line 1546 "glsl_parser.ypp"
+#line 1656 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.node) = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_while,
@@ -4967,10 +5089,10 @@ yyreduce:
        ;}
     break;
 
-  case 263:
+  case 275:
 
 /* Line 1464 of yacc.c  */
-#line 1553 "glsl_parser.ypp"
+#line 1663 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.node) = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_do_while,
@@ -4979,10 +5101,10 @@ yyreduce:
        ;}
     break;
 
-  case 264:
+  case 276:
 
 /* Line 1464 of yacc.c  */
-#line 1560 "glsl_parser.ypp"
+#line 1670 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.node) = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_for,
@@ -4991,39 +5113,39 @@ yyreduce:
        ;}
     break;
 
-  case 268:
+  case 280:
 
 /* Line 1464 of yacc.c  */
-#line 1576 "glsl_parser.ypp"
+#line 1686 "glsl_parser.ypp"
     {
           (yyval.node) = NULL;
        ;}
     break;
 
-  case 269:
+  case 281:
 
 /* Line 1464 of yacc.c  */
-#line 1583 "glsl_parser.ypp"
+#line 1693 "glsl_parser.ypp"
     {
           (yyval.for_rest_statement).cond = (yyvsp[(1) - (2)].node);
           (yyval.for_rest_statement).rest = NULL;
        ;}
     break;
 
-  case 270:
+  case 282:
 
 /* Line 1464 of yacc.c  */
-#line 1588 "glsl_parser.ypp"
+#line 1698 "glsl_parser.ypp"
     {
           (yyval.for_rest_statement).cond = (yyvsp[(1) - (3)].node);
           (yyval.for_rest_statement).rest = (yyvsp[(3) - (3)].expression);
        ;}
     break;
 
-  case 271:
+  case 283:
 
 /* Line 1464 of yacc.c  */
-#line 1597 "glsl_parser.ypp"
+#line 1707 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_continue, NULL);
@@ -5031,10 +5153,10 @@ yyreduce:
        ;}
     break;
 
-  case 272:
+  case 284:
 
 /* Line 1464 of yacc.c  */
-#line 1603 "glsl_parser.ypp"
+#line 1713 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_break, NULL);
@@ -5042,10 +5164,10 @@ yyreduce:
        ;}
     break;
 
-  case 273:
+  case 285:
 
 /* Line 1464 of yacc.c  */
-#line 1609 "glsl_parser.ypp"
+#line 1719 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, NULL);
@@ -5053,10 +5175,10 @@ yyreduce:
        ;}
     break;
 
-  case 274:
+  case 286:
 
 /* Line 1464 of yacc.c  */
-#line 1615 "glsl_parser.ypp"
+#line 1725 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, (yyvsp[(2) - (3)].expression));
@@ -5064,10 +5186,10 @@ yyreduce:
        ;}
     break;
 
-  case 275:
+  case 287:
 
 /* Line 1464 of yacc.c  */
-#line 1621 "glsl_parser.ypp"
+#line 1731 "glsl_parser.ypp"
     {
           void *ctx = state;
           (yyval.node) = new(ctx) ast_jump_statement(ast_jump_statement::ast_discard, NULL);
@@ -5075,44 +5197,46 @@ yyreduce:
        ;}
     break;
 
-  case 276:
+  case 288:
 
 /* Line 1464 of yacc.c  */
-#line 1629 "glsl_parser.ypp"
+#line 1739 "glsl_parser.ypp"
     { (yyval.node) = (yyvsp[(1) - (1)].function_definition); ;}
     break;
 
-  case 277:
+  case 289:
 
 /* Line 1464 of yacc.c  */
-#line 1630 "glsl_parser.ypp"
+#line 1740 "glsl_parser.ypp"
     { (yyval.node) = (yyvsp[(1) - (1)].node); ;}
     break;
 
-  case 278:
+  case 290:
 
 /* Line 1464 of yacc.c  */
-#line 1631 "glsl_parser.ypp"
+#line 1741 "glsl_parser.ypp"
     { (yyval.node) = NULL; ;}
     break;
 
-  case 279:
+  case 291:
 
 /* Line 1464 of yacc.c  */
-#line 1636 "glsl_parser.ypp"
+#line 1746 "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);
+
+          state->symbols->pop_scope();
        ;}
     break;
 
 
 
 /* Line 1464 of yacc.c  */
-#line 5116 "glsl_parser.cpp"
+#line 5240 "glsl_parser.cpp"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
index 1bf3b3538c7157c01192c01a3d9407b6ebace217..7f36492f7a1e8cc328aef51b9da01e1222a7ab56 100644 (file)
      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,
-     PRAGMA_INVARIANT_ALL = 375,
-     LAYOUT_TOK = 376,
-     ASM = 377,
-     CLASS = 378,
-     UNION = 379,
-     ENUM = 380,
-     TYPEDEF = 381,
-     TEMPLATE = 382,
-     THIS = 383,
-     PACKED_TOK = 384,
-     GOTO = 385,
-     INLINE_TOK = 386,
-     NOINLINE = 387,
-     VOLATILE = 388,
-     PUBLIC_TOK = 389,
-     STATIC = 390,
-     EXTERN = 391,
-     EXTERNAL = 392,
-     LONG_TOK = 393,
-     SHORT_TOK = 394,
-     DOUBLE_TOK = 395,
-     HALF = 396,
-     FIXED_TOK = 397,
-     UNSIGNED = 398,
-     INPUT_TOK = 399,
-     OUPTUT = 400,
-     HVEC2 = 401,
-     HVEC3 = 402,
-     HVEC4 = 403,
-     DVEC2 = 404,
-     DVEC3 = 405,
-     DVEC4 = 406,
-     FVEC2 = 407,
-     FVEC3 = 408,
-     FVEC4 = 409,
-     SAMPLER2DRECT = 410,
-     SAMPLER3DRECT = 411,
-     SAMPLER2DRECTSHADOW = 412,
-     SIZEOF = 413,
-     CAST = 414,
-     NAMESPACE = 415,
-     USING = 416,
-     ERROR_TOK = 417,
-     COMMON = 418,
-     PARTITION = 419,
-     ACTIVE = 420,
-     SAMPLERBUFFER = 421,
-     FILTER = 422,
-     IMAGE1D = 423,
-     IMAGE2D = 424,
-     IMAGE3D = 425,
-     IMAGECUBE = 426,
-     IMAGE1DARRAY = 427,
-     IMAGE2DARRAY = 428,
-     IIMAGE1D = 429,
-     IIMAGE2D = 430,
-     IIMAGE3D = 431,
-     IIMAGECUBE = 432,
-     IIMAGE1DARRAY = 433,
-     IIMAGE2DARRAY = 434,
-     UIMAGE1D = 435,
-     UIMAGE2D = 436,
-     UIMAGE3D = 437,
-     UIMAGECUBE = 438,
-     UIMAGE1DARRAY = 439,
-     UIMAGE2DARRAY = 440,
-     IMAGE1DSHADOW = 441,
-     IMAGE2DSHADOW = 442,
-     IMAGEBUFFER = 443,
-     IIMAGEBUFFER = 444,
-     UIMAGEBUFFER = 445,
-     IMAGE1DARRAYSHADOW = 446,
-     IMAGE2DARRAYSHADOW = 447,
-     ROW_MAJOR = 448
+     TYPE_IDENTIFIER = 332,
+     NEW_IDENTIFIER = 333,
+     FLOATCONSTANT = 334,
+     INTCONSTANT = 335,
+     UINTCONSTANT = 336,
+     BOOLCONSTANT = 337,
+     FIELD_SELECTION = 338,
+     LEFT_OP = 339,
+     RIGHT_OP = 340,
+     INC_OP = 341,
+     DEC_OP = 342,
+     LE_OP = 343,
+     GE_OP = 344,
+     EQ_OP = 345,
+     NE_OP = 346,
+     AND_OP = 347,
+     OR_OP = 348,
+     XOR_OP = 349,
+     MUL_ASSIGN = 350,
+     DIV_ASSIGN = 351,
+     ADD_ASSIGN = 352,
+     MOD_ASSIGN = 353,
+     LEFT_ASSIGN = 354,
+     RIGHT_ASSIGN = 355,
+     AND_ASSIGN = 356,
+     XOR_ASSIGN = 357,
+     OR_ASSIGN = 358,
+     SUB_ASSIGN = 359,
+     INVARIANT = 360,
+     LOWP = 361,
+     MEDIUMP = 362,
+     HIGHP = 363,
+     SUPERP = 364,
+     PRECISION = 365,
+     VERSION = 366,
+     EXTENSION = 367,
+     LINE = 368,
+     COLON = 369,
+     EOL = 370,
+     INTERFACE = 371,
+     OUTPUT = 372,
+     PRAGMA_DEBUG_ON = 373,
+     PRAGMA_DEBUG_OFF = 374,
+     PRAGMA_OPTIMIZE_ON = 375,
+     PRAGMA_OPTIMIZE_OFF = 376,
+     PRAGMA_INVARIANT_ALL = 377,
+     LAYOUT_TOK = 378,
+     ASM = 379,
+     CLASS = 380,
+     UNION = 381,
+     ENUM = 382,
+     TYPEDEF = 383,
+     TEMPLATE = 384,
+     THIS = 385,
+     PACKED_TOK = 386,
+     GOTO = 387,
+     INLINE_TOK = 388,
+     NOINLINE = 389,
+     VOLATILE = 390,
+     PUBLIC_TOK = 391,
+     STATIC = 392,
+     EXTERN = 393,
+     EXTERNAL = 394,
+     LONG_TOK = 395,
+     SHORT_TOK = 396,
+     DOUBLE_TOK = 397,
+     HALF = 398,
+     FIXED_TOK = 399,
+     UNSIGNED = 400,
+     INPUT_TOK = 401,
+     OUPTUT = 402,
+     HVEC2 = 403,
+     HVEC3 = 404,
+     HVEC4 = 405,
+     DVEC2 = 406,
+     DVEC3 = 407,
+     DVEC4 = 408,
+     FVEC2 = 409,
+     FVEC3 = 410,
+     FVEC4 = 411,
+     SAMPLER2DRECT = 412,
+     SAMPLER3DRECT = 413,
+     SAMPLER2DRECTSHADOW = 414,
+     SIZEOF = 415,
+     CAST = 416,
+     NAMESPACE = 417,
+     USING = 418,
+     ERROR_TOK = 419,
+     COMMON = 420,
+     PARTITION = 421,
+     ACTIVE = 422,
+     SAMPLERBUFFER = 423,
+     FILTER = 424,
+     IMAGE1D = 425,
+     IMAGE2D = 426,
+     IMAGE3D = 427,
+     IMAGECUBE = 428,
+     IMAGE1DARRAY = 429,
+     IMAGE2DARRAY = 430,
+     IIMAGE1D = 431,
+     IIMAGE2D = 432,
+     IIMAGE3D = 433,
+     IIMAGECUBE = 434,
+     IIMAGE1DARRAY = 435,
+     IIMAGE2DARRAY = 436,
+     UIMAGE1D = 437,
+     UIMAGE2D = 438,
+     UIMAGE3D = 439,
+     UIMAGECUBE = 440,
+     UIMAGE1DARRAY = 441,
+     UIMAGE2DARRAY = 442,
+     IMAGE1DSHADOW = 443,
+     IMAGE2DSHADOW = 444,
+     IMAGEBUFFER = 445,
+     IIMAGEBUFFER = 446,
+     UIMAGEBUFFER = 447,
+     IMAGE1DARRAYSHADOW = 448,
+     IMAGE2DARRAYSHADOW = 449,
+     ROW_MAJOR = 450
    };
 #endif
 
@@ -272,7 +274,7 @@ typedef union YYSTYPE
 
 
 /* Line 1685 of yacc.c  */
-#line 276 "glsl_parser.h"
+#line 278 "glsl_parser.h"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
index 3982167c4827709585dbeed2ac5cb59e65c160ee..2c0498ece7a946a357ffc01d6e40a3b90d2a3faf 100644 (file)
@@ -93,7 +93,8 @@
 %token ISAMPLER1DARRAY ISAMPLER2DARRAY USAMPLER1D USAMPLER2D USAMPLER3D
 %token USAMPLERCUBE USAMPLER1DARRAY USAMPLER2DARRAY
 %token STRUCT VOID_TOK WHILE
-%token <identifier> IDENTIFIER
+%token <identifier> IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER
+%type <identifier> any_identifier
 %token <real> FLOATCONSTANT
 %token <n> INTCONSTANT UINTCONSTANT BOOLCONSTANT
 %token <identifier> FIELD_SELECTION
 %type <expression> function_call_generic
 %type <expression> function_call_or_method
 %type <expression> function_call
+%type <expression> method_call_generic
+%type <expression> method_call_header_with_parameters
+%type <expression> method_call_header_no_parameters
+%type <expression> method_call_header
 %type <n> assignment_operator
 %type <n> unary_operator
 %type <expression> function_identifier
@@ -214,31 +219,51 @@ translation_unit:
           _mesa_glsl_initialize_types(state);
        }
        external_declaration_list
+       {
+          delete state->symbols;
+          state->symbols = new(ralloc_parent(state)) glsl_symbol_table;
+          _mesa_glsl_initialize_types(state);
+       }
        ;
 
 version_statement:
        /* blank - no #version specified: defaults are already set */
        | VERSION INTCONSTANT EOL
        {
+          bool supported = false;
+
           switch ($2) {
           case 100:
              state->es_shader = true;
+             supported = state->Const.GLSL_100ES;
+             break;
           case 110:
+             supported = state->Const.GLSL_110;
+             break;
           case 120:
+             supported = state->Const.GLSL_120;
+             break;
           case 130:
-             /* FINISHME: Check against implementation support versions. */
-             state->language_version = $2;
-             state->version_string =
-                talloc_asprintf(state, "GLSL%s %d.%02d",
-                                state->es_shader ? " ES" : "",
-                                state->language_version / 100,
-                                state->language_version % 100);
+             supported = state->Const.GLSL_130;
              break;
           default:
-             _mesa_glsl_error(& @2, state, "Shading language version"
-                              "%u is not supported\n", $2);
+             supported = false;
              break;
           }
+
+          state->language_version = $2;
+          state->version_string =
+             ralloc_asprintf(state, "GLSL%s %d.%02d",
+                             state->es_shader ? " ES" : "",
+                             state->language_version / 100,
+                             state->language_version % 100);
+
+          if (!supported) {
+             _mesa_glsl_error(& @2, state, "%s is not supported. "
+                              "Supported versions are: %s\n",
+                              state->version_string,
+                              state->supported_version_string);
+          }
        }
        ;
 
@@ -264,8 +289,14 @@ extension_statement_list:
        | extension_statement_list extension_statement
        ;
 
+any_identifier:
+       IDENTIFIER
+       | TYPE_IDENTIFIER
+       | NEW_IDENTIFIER
+       ;
+
 extension_statement:
-       EXTENSION IDENTIFIER COLON IDENTIFIER EOL
+       EXTENSION any_identifier COLON any_identifier EOL
        {
           if (!_mesa_glsl_process_extension($2, & @2, $4, & @4, state)) {
              YYERROR;
@@ -294,6 +325,7 @@ external_declaration_list:
 
 variable_identifier:
        IDENTIFIER
+       | NEW_IDENTIFIER
        ;
 
 primary_expression:
@@ -350,7 +382,7 @@ postfix_expression:
        {
           $$ = $1;
        }
-       | postfix_expression '.' IDENTIFIER
+       | postfix_expression '.' any_identifier
        {
           void *ctx = state;
           $$ = new(ctx) ast_expression(ast_field_selection, $1, NULL, NULL);
@@ -381,7 +413,7 @@ function_call:
 
 function_call_or_method:
        function_call_generic
-       | postfix_expression '.' function_call_generic
+       | postfix_expression '.' method_call_generic
        {
           void *ctx = state;
           $$ = new(ctx) ast_expression(ast_field_selection, $1, $3, NULL);
@@ -428,7 +460,7 @@ function_identifier:
           $$ = new(ctx) ast_function_expression($1);
           $$->set_location(yylloc);
        }
-       | IDENTIFIER
+       | variable_identifier
        {
           void *ctx = state;
           ast_expression *callee = new(ctx) ast_expression($1);
@@ -444,6 +476,44 @@ function_identifier:
        }
        ;
 
+method_call_generic:
+       method_call_header_with_parameters ')'
+       | method_call_header_no_parameters ')'
+       ;
+
+method_call_header_no_parameters:
+       method_call_header VOID_TOK
+       | method_call_header
+       ;
+
+method_call_header_with_parameters:
+       method_call_header assignment_expression
+       {
+          $$ = $1;
+          $$->set_location(yylloc);
+          $$->expressions.push_tail(& $2->link);
+       }
+       | method_call_header_with_parameters ',' assignment_expression
+       {
+          $$ = $1;
+          $$->set_location(yylloc);
+          $$->expressions.push_tail(& $3->link);
+       }
+       ;
+
+       // Grammar Note: Constructors look like methods, but lexical 
+       // analysis recognized most of them as keywords. They are now
+       // recognized through "type_specifier".
+method_call_header:
+       variable_identifier '('
+       {
+          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
@@ -694,6 +764,7 @@ constant_expression:
 declaration:
        function_prototype ';'
        {
+          state->symbols->pop_scope();
           $$ = $1;
        }
        | init_declarator_list ';'
@@ -731,18 +802,21 @@ function_header_with_parameters:
        ;
 
 function_header:
-       fully_specified_type IDENTIFIER '('
+       fully_specified_type variable_identifier '('
        {
           void *ctx = state;
           $$ = new(ctx) ast_function();
           $$->set_location(yylloc);
           $$->return_type = $1;
           $$->identifier = $2;
+
+          state->symbols->add_function(new(state) ir_function($2));
+          state->symbols->push_scope();
        }
        ;
 
 parameter_declarator:
-       type_specifier IDENTIFIER
+       type_specifier any_identifier
        {
           void *ctx = state;
           $$ = new(ctx) ast_parameter_declarator();
@@ -752,7 +826,7 @@ parameter_declarator:
           $$->type->specifier = $1;
           $$->identifier = $2;
        }
-       | type_specifier IDENTIFIER '[' constant_expression ']'
+       | type_specifier any_identifier '[' constant_expression ']'
        {
           void *ctx = state;
           $$ = new(ctx) ast_parameter_declarator();
@@ -830,7 +904,7 @@ parameter_type_specifier:
 
 init_declarator_list:
        single_declaration
-       | init_declarator_list ',' IDENTIFIER
+       | init_declarator_list ',' any_identifier
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($3, false, NULL, NULL);
@@ -838,8 +912,9 @@ init_declarator_list:
 
           $$ = $1;
           $$->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
        }
-       | init_declarator_list ',' IDENTIFIER '[' ']'
+       | init_declarator_list ',' any_identifier '[' ']'
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, NULL);
@@ -847,8 +922,9 @@ init_declarator_list:
 
           $$ = $1;
           $$->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
        }
-       | init_declarator_list ',' IDENTIFIER '[' constant_expression ']'
+       | init_declarator_list ',' any_identifier '[' constant_expression ']'
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, NULL);
@@ -856,8 +932,9 @@ init_declarator_list:
 
           $$ = $1;
           $$->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
        }
-       | init_declarator_list ',' IDENTIFIER '[' ']' '=' initializer
+       | init_declarator_list ',' any_identifier '[' ']' '=' initializer
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, $7);
@@ -865,8 +942,9 @@ init_declarator_list:
 
           $$ = $1;
           $$->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
        }
-       | init_declarator_list ',' IDENTIFIER '[' constant_expression ']' '=' initializer
+       | init_declarator_list ',' any_identifier '[' constant_expression ']' '=' initializer
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, $8);
@@ -874,8 +952,9 @@ init_declarator_list:
 
           $$ = $1;
           $$->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
        }
-       | init_declarator_list ',' IDENTIFIER '=' initializer
+       | init_declarator_list ',' any_identifier '=' initializer
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($3, false, NULL, $5);
@@ -883,6 +962,7 @@ init_declarator_list:
 
           $$ = $1;
           $$->declarations.push_tail(&decl->link);
+          state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto));
        }
        ;
 
@@ -899,7 +979,7 @@ single_declaration:
              $$->set_location(yylloc);
           }
        }
-       | fully_specified_type IDENTIFIER
+       | fully_specified_type any_identifier
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, NULL);
@@ -908,7 +988,7 @@ single_declaration:
           $$->set_location(yylloc);
           $$->declarations.push_tail(&decl->link);
        }
-       | fully_specified_type IDENTIFIER '[' ']'
+       | fully_specified_type any_identifier '[' ']'
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, NULL);
@@ -917,7 +997,7 @@ single_declaration:
           $$->set_location(yylloc);
           $$->declarations.push_tail(&decl->link);
        }
-       | fully_specified_type IDENTIFIER '[' constant_expression ']'
+       | fully_specified_type any_identifier '[' constant_expression ']'
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, NULL);
@@ -926,7 +1006,7 @@ single_declaration:
           $$->set_location(yylloc);
           $$->declarations.push_tail(&decl->link);
        }
-       | fully_specified_type IDENTIFIER '[' ']' '=' initializer
+       | fully_specified_type any_identifier '[' ']' '=' initializer
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, $6);
@@ -935,7 +1015,7 @@ single_declaration:
           $$->set_location(yylloc);
           $$->declarations.push_tail(&decl->link);
        }
-       | fully_specified_type IDENTIFIER '[' constant_expression ']' '=' initializer
+       | fully_specified_type any_identifier '[' constant_expression ']' '=' initializer
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, $7);
@@ -944,7 +1024,7 @@ single_declaration:
           $$->set_location(yylloc);
           $$->declarations.push_tail(&decl->link);
        }
-       | fully_specified_type IDENTIFIER '=' initializer
+       | fully_specified_type any_identifier '=' initializer
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, $4);
@@ -953,7 +1033,7 @@ single_declaration:
           $$->set_location(yylloc);
           $$->declarations.push_tail(&decl->link);
        }
-       | INVARIANT IDENTIFIER // Vertex only.
+       | INVARIANT variable_identifier // Vertex only.
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, NULL);
@@ -1012,13 +1092,14 @@ layout_qualifier_id_list:
        ;
 
 layout_qualifier_id:
-       IDENTIFIER
+       any_identifier
        {
           bool got_one = false;
 
           memset(& $$, 0, sizeof($$));
 
-          if (state->ARB_fragment_coord_conventions_enable) {
+          /* Layout qualifiers for ARB_fragment_coord_conventions. */
+          if (!got_one && state->ARB_fragment_coord_conventions_enable) {
              if (strcmp($1, "origin_upper_left") == 0) {
                 got_one = true;
                 $$.flags.q.origin_upper_left = 1;
@@ -1026,22 +1107,44 @@ layout_qualifier_id:
                 got_one = true;
                 $$.flags.q.pixel_center_integer = 1;
              }
+
+             if (got_one && state->ARB_fragment_coord_conventions_warn) {
+                _mesa_glsl_warning(& @1, state,
+                                   "GL_ARB_fragment_coord_conventions layout "
+                                   "identifier `%s' used\n", $1);
+             }
+          }
+
+          /* Layout qualifiers for AMD_conservative_depth. */
+          if (!got_one && state->AMD_conservative_depth_enable) {
+             if (strcmp($1, "depth_any") == 0) {
+                got_one = true;
+                $$.flags.q.depth_any = 1;
+             } else if (strcmp($1, "depth_greater") == 0) {
+                got_one = true;
+                $$.flags.q.depth_greater = 1;
+             } else if (strcmp($1, "depth_less") == 0) {
+                got_one = true;
+                $$.flags.q.depth_less = 1;
+             } else if (strcmp($1, "depth_unchanged") == 0) {
+                got_one = true;
+                $$.flags.q.depth_unchanged = 1;
+             }
+       
+             if (got_one && state->AMD_conservative_depth_warn) {
+                _mesa_glsl_warning(& @1, state,
+                                   "GL_AMD_conservative_depth "
+                                   "layout qualifier `%s' is used\n", $1);
+             }
           }
 
-          /* If the identifier didn't match any known layout identifiers,
-           * emit an error.
-           */
           if (!got_one) {
              _mesa_glsl_error(& @1, state, "unrecognized layout identifier "
                               "`%s'\n", $1);
              YYERROR;
-          } else if (state->ARB_fragment_coord_conventions_warn) {
-             _mesa_glsl_warning(& @1, state,
-                                "GL_ARB_fragment_coord_conventions layout "
-                                "identifier `%s' used\n", $1);
           }
        }
-       | IDENTIFIER '=' INTCONSTANT
+       | any_identifier '=' INTCONSTANT
        {
           bool got_one = false;
 
@@ -1229,7 +1332,7 @@ type_specifier_nonarray:
           $$ = new(ctx) ast_type_specifier($1);
           $$->set_location(yylloc);
        }
-       | IDENTIFIER
+       | TYPE_IDENTIFIER
        {
           void *ctx = state;
           $$ = new(ctx) ast_type_specifier($1);
@@ -1325,11 +1428,12 @@ precision_qualifier:
        ;
 
 struct_specifier:
-       STRUCT IDENTIFIER '{' struct_declaration_list '}'
+       STRUCT any_identifier '{' struct_declaration_list '}'
        {
           void *ctx = state;
           $$ = new(ctx) ast_struct_specifier($2, $4);
           $$->set_location(yylloc);
+          state->symbols->add_type($2, glsl_type::void_type);
        }
        | STRUCT '{' struct_declaration_list '}'
        {
@@ -1381,13 +1485,14 @@ struct_declarator_list:
        ;
 
 struct_declarator:
-       IDENTIFIER
+       any_identifier
        {
           void *ctx = state;
           $$ = new(ctx) ast_declaration($1, false, NULL, NULL);
           $$->set_location(yylloc);
+          state->symbols->add_variable(new(state) ir_variable(NULL, $1, ir_var_auto));
        }
-       | IDENTIFIER '[' constant_expression ']'
+       | any_identifier '[' constant_expression ']'
        {
           void *ctx = state;
           $$ = new(ctx) ast_declaration($1, true, $3, NULL);
@@ -1427,11 +1532,16 @@ compound_statement:
           $$ = new(ctx) ast_compound_statement(true, NULL);
           $$->set_location(yylloc);
        }
-       | '{' statement_list '}'
+       | '{'
+       {
+          state->symbols->push_scope();
+       }
+       statement_list '}'
        {
           void *ctx = state;
-          $$ = new(ctx) ast_compound_statement(true, $2);
+          $$ = new(ctx) ast_compound_statement(true, $3);
           $$->set_location(yylloc);
+          state->symbols->pop_scope();
        }
        ;
 
@@ -1519,7 +1629,7 @@ condition:
        {
           $$ = (ast_node *) $1;
        }
-       | fully_specified_type IDENTIFIER '=' initializer
+       | fully_specified_type any_identifier '=' initializer
        {
           void *ctx = state;
           ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, $4);
@@ -1639,5 +1749,7 @@ function_definition:
           $$->set_location(yylloc);
           $$->prototype = $1;
           $$->body = $2;
+
+          state->symbols->pop_scope();
        }
        ;
index 77885d4e1e37f28923ea5767e4d554608d681ace..d7a37aef46dbe2240cde78282d351d6d2485cc39 100644 (file)
 #include <assert.h>
 
 extern "C" {
-#include <talloc.h>
 #include "main/core.h" /* for struct gl_context */
 }
 
+#include "ralloc.h"
 #include "ast.h"
 #include "glsl_parser_extras.h"
 #include "glsl_parser.h"
@@ -48,7 +48,7 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *ctx,
    this->scanner = NULL;
    this->translation_unit.make_empty();
    this->symbols = new(mem_ctx) glsl_symbol_table;
-   this->info_log = talloc_strdup(mem_ctx, "");
+   this->info_log = ralloc_strdup(mem_ctx, "");
    this->error = false;
    this->loop_or_switch_nesting = NULL;
 
@@ -79,6 +79,38 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *ctx,
    this->Const.MaxFragmentUniformComponents = ctx->Const.FragmentProgram.MaxUniformComponents;
 
    this->Const.MaxDrawBuffers = ctx->Const.MaxDrawBuffers;
+
+   /* Note: Once the OpenGL 3.0 'forward compatible' context or the OpenGL 3.2
+    * Core context is supported, this logic will need change.  Older versions of
+    * GLSL are no longer supported outside the compatibility contexts of 3.x.
+    */
+   this->Const.GLSL_100ES = (ctx->API == API_OPENGLES2)
+      || ctx->Extensions.ARB_ES2_compatibility;
+   this->Const.GLSL_110 = (ctx->API == API_OPENGL);
+   this->Const.GLSL_120 = (ctx->API == API_OPENGL)
+      && (ctx->Const.GLSLVersion >= 120);
+   this->Const.GLSL_130 = (ctx->API == API_OPENGL)
+      && (ctx->Const.GLSLVersion >= 130);
+
+   const unsigned lowest_version =
+      (ctx->API == API_OPENGLES2) || ctx->Extensions.ARB_ES2_compatibility
+      ? 100 : 110;
+   const unsigned highest_version =
+      (ctx->API == API_OPENGL) ? ctx->Const.GLSLVersion : 100;
+   char *supported = ralloc_strdup(this, "");
+
+   for (unsigned ver = lowest_version; ver <= highest_version; ver += 10) {
+      const char *const prefix = (ver == lowest_version)
+        ? ""
+        : ((ver == highest_version) ? ", and " : ", ");
+
+      ralloc_asprintf_append(& supported, "%s%d.%02d%s",
+                            prefix,
+                            ver / 100, ver % 100,
+                            (ver == 100) ? " ES" : "");
+   }
+
+   this->supported_version_string = supported;
 }
 
 const char *
@@ -104,15 +136,14 @@ _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
    state->error = true;
 
    assert(state->info_log != NULL);
-   state->info_log = talloc_asprintf_append(state->info_log,
-                                           "%u:%u(%u): error: ",
+   ralloc_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);
+   ralloc_vasprintf_append(&state->info_log, fmt, ap);
    va_end(ap);
-   state->info_log = talloc_strdup_append(state->info_log, "\n");
+   ralloc_strcat(&state->info_log, "\n");
 }
 
 
@@ -123,15 +154,14 @@ _mesa_glsl_warning(const YYLTYPE *locp, _mesa_glsl_parse_state *state,
    va_list ap;
 
    assert(state->info_log != NULL);
-   state->info_log = talloc_asprintf_append(state->info_log,
-                                           "%u:%u(%u): warning: ",
+   ralloc_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);
+   ralloc_vasprintf_append(&state->info_log, fmt, ap);
    va_end(ap);
-   state->info_log = talloc_strdup_append(state->info_log, "\n");
+   ralloc_strcat(&state->info_log, "\n");
 }
 
 
@@ -219,6 +249,13 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
         state->ARB_shader_stencil_export_warn = (ext_mode == extension_warn);
         unsupported = !state->extensions->ARB_shader_stencil_export;
       }
+   } else if (strcmp(name, "GL_AMD_conservative_depth") == 0) {
+      /* The AMD_conservative spec does not forbid requiring the extension in
+       * the vertex shader.
+       */
+      state->AMD_conservative_depth_enable = (ext_mode != extension_disable);
+      state->AMD_conservative_depth_warn = (ext_mode == extension_warn);
+      unsupported = !state->extensions->AMD_conservative_depth;
    } else {
       unsupported = true;
    }
@@ -705,7 +742,7 @@ ast_struct_specifier::ast_struct_specifier(char *identifier,
 {
    if (identifier == NULL) {
       static unsigned anon_count = 1;
-      identifier = talloc_asprintf(this, "#anon_struct_%04x", anon_count);
+      identifier = ralloc_asprintf(this, "#anon_struct_%04x", anon_count);
       anon_count++;
    }
    name = identifier;
@@ -727,6 +764,7 @@ do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iteration
    progress = do_if_simplification(ir) || progress;
    progress = do_discard_simplification(ir) || progress;
    progress = do_copy_propagation(ir) || progress;
+   /*progress = do_copy_propagation_elements(ir) || progress;*/
    if (linked)
       progress = do_dead_code(ir) || progress;
    else
index 030d27a2627f056c303b564c6fc24f6bb17836c8..10cb673c694a6b0b67eee0bc78c5bf372ff55dd3 100644 (file)
@@ -31,7 +31,7 @@
 #ifdef __cplusplus
 
 
-#include <cstdlib>
+#include <stdlib.h>
 #include "glsl_symbol_table.h"
 
 enum _mesa_glsl_parser_targets {
@@ -46,21 +46,21 @@ struct _mesa_glsl_parse_state {
    _mesa_glsl_parse_state(struct gl_context *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). */
+   /* Callers of this ralloc-based new need not call delete. It's
+    * easier to just ralloc_free 'ctx' (or any of its ancestors). */
    static void* operator new(size_t size, void *ctx)
    {
-      void *mem = talloc_zero_size(ctx, size);
+      void *mem = rzalloc_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. */
+    * ralloc_free in that case. */
    static void operator delete(void *mem)
    {
-      talloc_free(mem);
+      ralloc_free(mem);
    }
 
    void *scanner;
@@ -72,6 +72,16 @@ struct _mesa_glsl_parse_state {
    const char *version_string;
    enum _mesa_glsl_parser_targets target;
 
+   /**
+    * Printable list of GLSL versions supported by the current context
+    *
+    * \note
+    * This string should probably be generated per-context instead of per
+    * invokation of the compiler.  This should be changed when the method of
+    * tracking supported GLSL versions changes.
+    */
+   const char *supported_version_string;
+
    /**
     * Implementation defined limits that affect built-in variables, etc.
     *
@@ -93,6 +103,22 @@ struct _mesa_glsl_parse_state {
 
       /* ARB_draw_buffers */
       unsigned MaxDrawBuffers;
+
+      /**
+       * Set of GLSL versions supported by the current context
+       *
+       * Knowing that version X is supported doesn't mean that versions before
+       * X are also supported.  Version 1.00 is only supported in an ES2
+       * context or when GL_ARB_ES2_compatibility is supported.  In an OpenGL
+       * 3.0 "forward compatible" context, GLSL 1.10 and 1.20 are \b not
+       * supported.
+       */
+      /*@{*/
+      unsigned GLSL_100ES:1;
+      unsigned GLSL_110:1;
+      unsigned GLSL_120:1;
+      unsigned GLSL_130:1;
+      /*@}*/
    } Const;
 
    /**
@@ -144,6 +170,8 @@ struct _mesa_glsl_parse_state {
    unsigned EXT_texture_array_warn:1;
    unsigned ARB_shader_stencil_export_enable:1;
    unsigned ARB_shader_stencil_export_warn:1;
+   unsigned AMD_conservative_depth_enable:1;
+   unsigned AMD_conservative_depth_warn:1;
    /*@}*/
 
    /** Extensions supported by the OpenGL implementation. */
index 6fcfe07b9c2184a439920ea62c6c32d232a32d86..2f291d4f97fe95e8a9c33b1aa085a611e8bbf695 100644 (file)
 
 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). */
+   /* Callers of this ralloc-based new need not call delete. It's
+    * easier to just ralloc_free 'ctx' (or any of its ancestors). */
    static void* operator new(size_t size, void *ctx)
    {
-      void *entry = talloc_size(ctx, size);
+      void *entry = ralloc_size(ctx, size);
       assert(entry != NULL);
       return entry;
    }
 
-   /* If the user *does* call delete, that's OK, we will just talloc_free. */
+   /* If the user *does* call delete, that's OK, we will just ralloc_free. */
    static void operator delete(void *entry)
    {
-      talloc_free(entry);
+      ralloc_free(entry);
    }
 
    symbol_table_entry(ir_variable *v)                     : v(v), f(0), t(0) {}
@@ -54,13 +54,13 @@ glsl_symbol_table::glsl_symbol_table()
 {
    this->language_version = 120;
    this->table = _mesa_symbol_table_ctor();
-   this->mem_ctx = talloc_init("symbol table entries");
+   this->mem_ctx = ralloc_context(NULL);
 }
 
 glsl_symbol_table::~glsl_symbol_table()
 {
    _mesa_symbol_table_dtor(table);
-   talloc_free(mem_ctx);
+   ralloc_free(mem_ctx);
 }
 
 void glsl_symbol_table::push_scope()
index 28a44ebe91c24fa065755136f1bfd30d1efad338..637bc033b9353fe9160b14720baf691746438b3e 100644 (file)
@@ -44,36 +44,34 @@ class symbol_table_entry;
  */
 struct glsl_symbol_table {
 private:
-   static int
+   static void
    _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). */
+   /* Callers of this ralloc-based new need not call delete. It's
+    * easier to just ralloc_free 'ctx' (or any of its ancestors). */
    static void* operator new(size_t size, void *ctx)
    {
       void *table;
 
-      table = talloc_size(ctx, size);
+      table = ralloc_size(ctx, size);
       assert(table != NULL);
 
-      talloc_set_destructor(table, (int (*)(void*)) _glsl_symbol_table_destructor);
+      ralloc_set_destructor(table, (void (*)(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. */
+    * ralloc_free in that case. Here, C++ will have already called the
+    * destructor so tell ralloc not to do that again. */
    static void operator delete(void *table)
    {
-      talloc_set_destructor(table, NULL);
-      talloc_free(table);
+      ralloc_set_destructor(table, NULL);
+      ralloc_free(table);
    }
    
    glsl_symbol_table();
index 95b859264821b389a9654372f3d0ae2e401f760f..76b4f3e4cb0e20008413ccf5524d39440d935205 100644 (file)
@@ -21,7 +21,7 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-#include <cstdio>
+#include <stdio.h>
 #include <stdlib.h>
 #include "main/core.h" /* for Elements */
 #include "glsl_symbol_table.h"
@@ -37,10 +37,10 @@ hash_table *glsl_type::record_types = NULL;
 void *glsl_type::mem_ctx = NULL;
 
 void
-glsl_type::init_talloc_type_ctx(void)
+glsl_type::init_ralloc_type_ctx(void)
 {
    if (glsl_type::mem_ctx == NULL) {
-      glsl_type::mem_ctx = talloc_autofree_context();
+      glsl_type::mem_ctx = ralloc_autofree_context();
       assert(glsl_type::mem_ctx != NULL);
    }
 }
@@ -55,8 +55,8 @@ glsl_type::glsl_type(GLenum gl_type,
    vector_elements(vector_elements), matrix_columns(matrix_columns),
    length(0)
 {
-   init_talloc_type_ctx();
-   this->name = talloc_strdup(this->mem_ctx, name);
+   init_ralloc_type_ctx();
+   this->name = ralloc_strdup(this->mem_ctx, name);
    /* Neither dimension is zero or both dimensions are zero.
     */
    assert((vector_elements == 0) == (matrix_columns == 0));
@@ -73,8 +73,8 @@ glsl_type::glsl_type(GLenum gl_type,
    vector_elements(0), matrix_columns(0),
    length(0)
 {
-   init_talloc_type_ctx();
-   this->name = talloc_strdup(this->mem_ctx, name);
+   init_ralloc_type_ctx();
+   this->name = ralloc_strdup(this->mem_ctx, name);
    memset(& fields, 0, sizeof(fields));
 }
 
@@ -88,13 +88,13 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned 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,
+   init_ralloc_type_ctx();
+   this->name = ralloc_strdup(this->mem_ctx, name);
+   this->fields.structure = ralloc_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,
+      this->fields.structure[i].name = ralloc_strdup(this->fields.structure,
                                                     fields[i].name);
    }
 }
@@ -264,7 +264,7 @@ glsl_type::glsl_type(const glsl_type *array, unsigned length) :
     * NUL.
     */
    const unsigned name_length = strlen(array->name) + 10 + 3;
-   char *const n = (char *) talloc_size(this->mem_ctx, name_length);
+   char *const n = (char *) ralloc_size(this->mem_ctx, name_length);
 
    if (length == 0)
       snprintf(n, name_length, "%s[]", array->name);
@@ -354,7 +354,7 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
    if (t == NULL) {
       t = new glsl_type(base, array_size);
 
-      hash_table_insert(array_types, (void *) t, talloc_strdup(mem_ctx, key));
+      hash_table_insert(array_types, (void *) t, ralloc_strdup(mem_ctx, key));
    }
 
    assert(t->base_type == GLSL_TYPE_ARRAY);
index 57e7b09d98c57f7efe2464e11ce9e9ea56bc0eb1..61bf5e0cfd24779fee3913817214bf6fd13d1abd 100644 (file)
 #ifndef GLSL_TYPES_H
 #define GLSL_TYPES_H
 
-#include <cstring>
-#include <cassert>
+#include <string.h>
+#include <assert.h>
 
 extern "C" {
 #include "GL/gl.h"
-#include <talloc.h>
 }
 
+#include "ralloc.h"
+
 struct _mesa_glsl_parse_state;
 struct glsl_symbol_table;
 
@@ -77,28 +78,28 @@ struct glsl_type {
                                * 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). */
+   /* Callers of this ralloc-based new need not call delete. It's
+    * easier to just ralloc_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");
+        glsl_type::mem_ctx = ralloc_context(NULL);
         assert(glsl_type::mem_ctx != NULL);
       }
 
       void *type;
 
-      type = talloc_size(glsl_type::mem_ctx, size);
+      type = ralloc_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. */
+    * ralloc_free in that case. */
    static void operator delete(void *type)
    {
-      talloc_free(type);
+      ralloc_free(type);
    }
 
    /**
@@ -386,13 +387,13 @@ struct glsl_type {
 
 private:
    /**
-    * talloc context for all glsl_type allocations
+    * ralloc 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);
+   void init_ralloc_type_ctx(void);
 
    /** Constructor for vector and matrix types */
    glsl_type(GLenum gl_type,
index 460d43b02e1361f2532ea3db63ebdb794d0d54b4..fc356ba52752dac3a6ee9e8e74b0362c1c3fd904 100644 (file)
@@ -472,6 +472,22 @@ const char *ir_expression::operator_string()
    return operator_string(this->operation);
 }
 
+const char*
+depth_layout_string(ir_depth_layout layout)
+{
+   switch(layout) {
+   case ir_depth_layout_none:      return "";
+   case ir_depth_layout_any:       return "depth_any";
+   case ir_depth_layout_greater:   return "depth_greater";
+   case ir_depth_layout_less:      return "depth_less";
+   case ir_depth_layout_unchanged: return "depth_unchanged";
+
+   default:
+      assert(0);
+      return "";
+   }
+}
+
 ir_expression_operation
 ir_expression::get_operator(const char *str)
 {
@@ -562,7 +578,7 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
          || type->is_record() || type->is_array());
 
    if (type->is_array()) {
-      this->array_elements = talloc_array(this, ir_constant *, type->length);
+      this->array_elements = ralloc_array(this, ir_constant *, type->length);
       unsigned i = 0;
       foreach_list(node, value_list) {
         ir_constant *value = (ir_constant *) node;
@@ -1020,7 +1036,7 @@ ir_dereference_array::ir_dereference_array(ir_rvalue *value,
 ir_dereference_array::ir_dereference_array(ir_variable *var,
                                           ir_rvalue *array_index)
 {
-   void *ctx = talloc_parent(var);
+   void *ctx = ralloc_parent(var);
 
    this->ir_type = ir_type_dereference_array;
    this->array_index = array_index;
@@ -1053,7 +1069,7 @@ ir_dereference_record::ir_dereference_record(ir_rvalue *value,
 {
    this->ir_type = ir_type_dereference_record;
    this->record = value;
-   this->field = talloc_strdup(this, field);
+   this->field = ralloc_strdup(this, field);
    this->type = (this->record != NULL)
       ? this->record->type->field_type(field) : glsl_type::error_type;
 }
@@ -1062,11 +1078,11 @@ ir_dereference_record::ir_dereference_record(ir_rvalue *value,
 ir_dereference_record::ir_dereference_record(ir_variable *var,
                                             const char *field)
 {
-   void *ctx = talloc_parent(var);
+   void *ctx = ralloc_parent(var);
 
    this->ir_type = ir_type_dereference_record;
    this->record = new(ctx) ir_dereference_variable(var);
-   this->field = talloc_strdup(this, field);
+   this->field = ralloc_strdup(this, field);
    this->type = (this->record != NULL)
       ? this->record->type->field_type(field) : glsl_type::error_type;
 }
@@ -1229,7 +1245,7 @@ ir_swizzle::ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask)
 ir_swizzle *
 ir_swizzle::create(ir_rvalue *val, const char *str, unsigned vector_length)
 {
-   void *ctx = talloc_parent(val);
+   void *ctx = ralloc_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
@@ -1318,13 +1334,14 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name,
 {
    this->ir_type = ir_type_variable;
    this->type = type;
-   this->name = talloc_strdup(this, name);
+   this->name = ralloc_strdup(this, name);
    this->explicit_location = false;
    this->location = -1;
    this->warn_extension = NULL;
    this->constant_value = NULL;
    this->origin_upper_left = false;
    this->pixel_center_integer = false;
+   this->depth_layout = ir_depth_layout_none;
    this->used = false;
 
    if (type && type->base_type == GLSL_TYPE_SAMPLER)
@@ -1362,6 +1379,21 @@ ir_function_signature::ir_function_signature(const glsl_type *return_type)
 }
 
 
+static bool
+modes_match(unsigned a, unsigned b)
+{
+   if (a == b)
+      return true;
+
+   /* Accept "in" vs. "const in" */
+   if ((a == ir_var_const_in && b == ir_var_in) ||
+       (b == ir_var_const_in && a == ir_var_in))
+      return true;
+
+   return false;
+}
+
+
 const char *
 ir_function_signature::qualifiers_match(exec_list *params)
 {
@@ -1374,7 +1406,7 @@ ir_function_signature::qualifiers_match(exec_list *params)
       ir_variable *b = (ir_variable *)iter_b.get();
 
       if (a->read_only != b->read_only ||
-         a->mode != b->mode ||
+         !modes_match(a->mode, b->mode) ||
          a->interpolation != b->interpolation ||
          a->centroid != b->centroid) {
 
@@ -1409,7 +1441,7 @@ ir_function_signature::replace_parameters(exec_list *new_params)
 ir_function::ir_function(const char *name)
 {
    this->ir_type = ir_type_function;
-   this->name = talloc_strdup(this, name);
+   this->name = ralloc_strdup(this, name);
 }
 
 
@@ -1475,7 +1507,7 @@ steal_memory(ir_instruction *ir, void *new_ctx)
       }
    }
 
-   talloc_steal(new_ctx, ir);
+   ralloc_steal(new_ctx, ir);
 }
 
 
index 7b83c2836ee92e257dbfc703e1c060a39985d437..f2f902c0a775939a89e915cef913d909ece30134 100644 (file)
 #ifndef IR_H
 #define IR_H
 
-#include <cstdio>
-#include <cstdlib>
-
-extern "C" {
-#include <talloc.h>
-}
+#include <stdio.h>
+#include <stdlib.h>
 
+#include "ralloc.h"
 #include "glsl_types.h"
 #include "list.h"
 #include "ir_visitor.h"
@@ -225,6 +222,7 @@ enum ir_variable_mode {
    ir_var_in,
    ir_var_out,
    ir_var_inout,
+   ir_var_const_in,    /**< "in" param that must be a constant expression */
    ir_var_system_value, /**< Ex: front-face, instance-id, etc. */
    ir_var_temporary    /**< Temporary variable generated during compilation. */
 };
@@ -235,6 +233,25 @@ enum ir_variable_interpolation {
    ir_var_noperspective
 };
 
+/**
+ * \brief Layout qualifiers for gl_FragDepth.
+ *
+ * The AMD_conservative_depth extension allows gl_FragDepth to be redeclared
+ * with a layout qualifier.
+ */
+enum ir_depth_layout {
+    ir_depth_layout_none, /**< No depth layout is specified. */
+    ir_depth_layout_any,
+    ir_depth_layout_greater,
+    ir_depth_layout_less,
+    ir_depth_layout_unchanged
+};
+
+/**
+ * \brief Convert depth layout qualifier to string.
+ */
+const char*
+depth_layout_string(ir_depth_layout layout);
 
 class ir_variable : public ir_instruction {
 public:
@@ -334,6 +351,14 @@ public:
    unsigned pixel_center_integer:1;
    /*@}*/
 
+   /**
+    * \brief Layout qualifier for gl_FragDepth.
+    *
+    * This is not equal to \c ir_depth_layout_none if and only if this
+    * variable is \c gl_FragDepth and a layout qualifier is specified.
+    */
+   ir_depth_layout depth_layout;
+
    /**
     * Was the location explicitly set in the shader?
     *
@@ -959,7 +984,7 @@ public:
    /**
     * Get a generic ir_call object when an error occurs
     *
-    * Any allocation will be performed with 'ctx' as talloc owner.
+    * Any allocation will be performed with 'ctx' as ralloc owner.
     */
    static ir_call *get_error_instruction(void *ctx);
 
@@ -1166,21 +1191,21 @@ enum ir_texture_opcode {
  * 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))
+ *                             Texel offset (0 or an expression)
+ *                             | Projection divisor
+ *                             | |  Shadow comparitor
+ *                             | |  |
+ *                             v v  v
+ * (tex <sampler> <coordinate> 0 1 ( ))
+ * (txb <sampler> <coordinate> 0 1 ( ) <bias>)
+ * (txl <sampler> <coordinate> 0 1 ( ) <lod>)
+ * (txd <sampler> <coordinate> 0 1 ( ) (dPdx dPdy))
+ * (txf <sampler> <coordinate> 0       <lod>)
  */
 class ir_texture : public ir_rvalue {
 public:
    ir_texture(enum ir_texture_opcode op)
-      : op(op), projector(NULL), shadow_comparitor(NULL)
+      : op(op), projector(NULL), shadow_comparitor(NULL), offset(NULL)
    {
       this->ir_type = ir_type_texture;
    }
@@ -1234,8 +1259,8 @@ public:
     */
    ir_rvalue *shadow_comparitor;
 
-   /** Explicit texel offsets. */
-   signed char offsets[3];
+   /** Texel offset. */
+   ir_rvalue *offset;
 
    union {
       ir_rvalue *lod;          /**< Floating point LOD */
index 1522af682bb5d46ad0f185eb90d8cb36a214ac65..2c0574dc6bf9bb5059808856cff23a12f191f6f9 100644 (file)
@@ -217,8 +217,8 @@ ir_texture::clone(void *mem_ctx, struct hash_table *ht) const
       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];
+   if (this->offset != NULL)
+      new_tex->offset = this->offset->clone(mem_ctx, ht);
 
    switch (this->op) {
    case ir_tex:
@@ -346,7 +346,7 @@ ir_constant::clone(void *mem_ctx, struct hash_table *ht) const
       ir_constant *c = new(mem_ctx) ir_constant;
 
       c->type = this->type;
-      c->array_elements = talloc_array(c, ir_constant *, this->type->length);
+      c->array_elements = ralloc_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);
       }
index 4fd6d09a3afbf6dc7191a4bc106c984481d8d69e..2a3084896569eaecb9ee734ad6698d53cc15661b 100644 (file)
@@ -86,7 +86,7 @@ ir_expression::constant_expression_value()
       components = op[1]->type->components();
    }
 
-   void *ctx = talloc_parent(this);
+   void *ctx = ralloc_parent(this);
 
    /* Handle array operations here, rather than below. */
    if (op[0]->type->is_array()) {
@@ -507,6 +507,7 @@ ir_expression::constant_expression_value()
 
       break;
    case ir_binop_div:
+      /* FINISHME: Emit warning when division-by-zero is detected. */
       assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
       for (unsigned c = 0, c0 = 0, c1 = 0;
           c < components;
@@ -514,10 +515,18 @@ ir_expression::constant_expression_value()
 
         switch (op[0]->type->base_type) {
         case GLSL_TYPE_UINT:
-           data.u[c] = op[0]->value.u[c0] / op[1]->value.u[c1];
+           if (op[1]->value.u[c1] == 0) {
+              data.u[c] = 0;
+           } else {
+              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];
+           if (op[1]->value.i[c1] == 0) {
+              data.i[c] = 0;
+           } else {
+              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];
@@ -529,6 +538,7 @@ ir_expression::constant_expression_value()
 
       break;
    case ir_binop_mod:
+      /* FINISHME: Emit warning when division-by-zero is detected. */
       assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
       for (unsigned c = 0, c0 = 0, c1 = 0;
           c < components;
@@ -536,10 +546,18 @@ ir_expression::constant_expression_value()
 
         switch (op[0]->type->base_type) {
         case GLSL_TYPE_UINT:
-           data.u[c] = op[0]->value.u[c0] % op[1]->value.u[c1];
+           if (op[1]->value.u[c1] == 0) {
+              data.u[c] = 0;
+           } else {
+              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];
+           if (op[1]->value.i[c1] == 0) {
+              data.i[c] = 0;
+           } else {
+              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
@@ -845,7 +863,7 @@ ir_swizzle::constant_expression_value()
         }
       }
 
-      void *ctx = talloc_parent(this);
+      void *ctx = ralloc_parent(this);
       return new(ctx) ir_constant(this->type, &data);
    }
    return NULL;
@@ -868,7 +886,7 @@ ir_dereference_variable::constant_expression_value()
    if (!var->constant_value)
       return NULL;
 
-   return var->constant_value->clone(talloc_parent(var), NULL);
+   return var->constant_value->clone(ralloc_parent(var), NULL);
 }
 
 
@@ -879,7 +897,7 @@ ir_dereference_array::constant_expression_value()
    ir_constant *idx = this->array_index->constant_expression_value();
 
    if ((array != NULL) && (idx != NULL)) {
-      void *ctx = talloc_parent(this);
+      void *ctx = ralloc_parent(this);
       if (array->type->is_matrix()) {
         /* Array access of a matrix results in a vector.
          */
@@ -984,7 +1002,7 @@ ir_call::constant_expression_value()
     * - Fill "data" with appopriate constant data
     * - Return an ir_constant directly.
     */
-   void *mem_ctx = talloc_parent(this);
+   void *mem_ctx = ralloc_parent(this);
    ir_expression *expr = NULL;
 
    ir_constant_data data;
index 7b1b8dbfef1a3d097a3c59df270ad6f20b6c150b..0b7c537bd8aafcb555317f0df91b0f46b5bff66c 100644 (file)
@@ -78,7 +78,7 @@ ir_expression_flattening_visitor::handle_rvalue(ir_rvalue **rvalue)
    if (!ir || !this->predicate(ir))
       return;
 
-   void *ctx = talloc_parent(ir);
+   void *ctx = ralloc_parent(ir);
 
    var = new(ctx) ir_variable(ir->type, "flattening_tmp", ir_var_temporary);
    base_ir->insert_before(var);
index 8db70119ec21c0f94c7e2a3d3642044446be65b6..caee9296af9e5c042a9aa8df80ee2de6bd5b6726 100644 (file)
@@ -123,6 +123,7 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
         assert(0);
         return -1;
 
+      case ir_var_const_in:
       case ir_var_in:
         score = type_compare(param->type, actual->type);
         break;
index be8b36a7cf8f5315c287493829354c648a6e0a53..4a607dc87499b800df7a6fff5c09b09fb49822be 100644 (file)
@@ -187,6 +187,12 @@ ir_texture::accept(ir_hierarchical_visitor *v)
         return (s == visit_continue_with_parent) ? visit_continue : s;
    }
 
+   if (this->offset) {
+      s = this->offset->accept(v);
+      if (s != visit_continue)
+        return (s == visit_continue_with_parent) ? visit_continue : s;
+   }
+
    switch (this->op) {
    case ir_tex:
       break;
index 4e0b30aa90e155ee4ee4bf4430bb23c7b69e47eb..3585bf6b24bfd2e7a7b20e528a0a5ee1bdf112d2 100644 (file)
@@ -27,7 +27,6 @@
  *
  * \author Ian Romanick
  */
-#include <cstdio>
 #include "ir.h"
 #include "glsl_symbol_table.h"
 
@@ -109,7 +108,7 @@ private:
  * \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
+ * \param mem_ctx  ralloc memory context used for new allocations
  */
 void
 import_prototypes(const exec_list *source, exec_list *dest,
index dbc9f4ab975d462b4eb75884bd165ef0f9420aad..dd265673c55ba24db0209e5afe5a5c8a58a7b98a 100644 (file)
@@ -43,6 +43,7 @@ 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_copy_propagation_elements(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);
index c56bafd00c5430fd019614d6267df9145d0ea3ef..82ccc722fa28762f4fe4fd60345450306fca9385 100644 (file)
@@ -97,7 +97,7 @@ void ir_print_visitor::visit(ir_variable *ir)
    const char *const cent = (ir->centroid) ? "centroid " : "";
    const char *const inv = (ir->invariant) ? "invariant " : "";
    const char *const mode[] = { "", "uniform ", "in ", "out ", "inout ",
-                               "temporary " };
+                               "const_in ", "sys ", "temporary " };
    const char *const interp[] = { "", "flat", "noperspective" };
 
    printf("(%s%s%s%s) ",
@@ -192,7 +192,15 @@ void ir_print_visitor::visit(ir_texture *ir)
 
    ir->coordinate->accept(this);
 
-   printf(" (%d %d %d) ", ir->offsets[0], ir->offsets[1], ir->offsets[2]);
+   printf(" ");
+
+   if (ir->offset != NULL) {
+      ir->offset->accept(this);
+   } else {
+      printf("0");
+   }
+
+   printf(" ");
 
    if (ir->op != ir_txf) {
       if (ir->projector)
index 40901dc6c92ea0cd16350dbd789aaf63f41d7644..af85e06ae0e4a2cda026c84b5aca30b7476d2373 100644 (file)
  * DEALINGS IN THE SOFTWARE.
  */
 
-extern "C" {
-#include <talloc.h>
-}
-
 #include "ir_reader.h"
 #include "glsl_parser_extras.h"
 #include "glsl_types.h"
@@ -96,7 +92,7 @@ ir_reader::read(exec_list *instructions, const char *src, bool scan_for_protos)
    }
 
    read_instructions(instructions, expr, NULL);
-   talloc_free(expr);
+   ralloc_free(expr);
 
    if (debug)
       validate_ir_tree(instructions);
@@ -110,21 +106,19 @@ ir_reader::ir_read_error(s_expression *expr, const char *fmt, ...)
    state->error = true;
 
    if (state->current_function != NULL)
-      state->info_log = talloc_asprintf_append(state->info_log,
-                          "In function %s:\n",
-                          state->current_function->function_name());
-   state->info_log = talloc_strdup_append(state->info_log, "error: ");
+      ralloc_asprintf_append(&state->info_log, "In function %s:\n",
+                            state->current_function->function_name());
+   ralloc_strcat(&state->info_log, "error: ");
 
    va_start(ap, fmt);
-   state->info_log = talloc_vasprintf_append(state->info_log, fmt, ap);
+   ralloc_vasprintf_append(&state->info_log, fmt, ap);
    va_end(ap);
-   state->info_log = talloc_strdup_append(state->info_log, "\n");
+   ralloc_strcat(&state->info_log, "\n");
 
    if (expr != NULL) {
-      state->info_log = talloc_strdup_append(state->info_log,
-                                            "...in this context:\n   ");
+      ralloc_strcat(&state->info_log, "...in this context:\n   ");
       expr->print();
-      state->info_log = talloc_strdup_append(state->info_log, "\n\n");
+      ralloc_strcat(&state->info_log, "\n\n");
    }
 }
 
@@ -403,6 +397,8 @@ ir_reader::read_declaration(s_expression *expr)
         var->mode = ir_var_auto;
       } else if (strcmp(qualifier->value(), "in") == 0) {
         var->mode = ir_var_in;
+      } else if (strcmp(qualifier->value(), "const_in") == 0) {
+        var->mode = ir_var_const_in;
       } else if (strcmp(qualifier->value(), "out") == 0) {
         var->mode = ir_var_out;
       } else if (strcmp(qualifier->value(), "inout") == 0) {
@@ -875,12 +871,12 @@ ir_reader::read_texture(s_expression *expr)
    s_symbol *tag = NULL;
    s_expression *s_sampler = NULL;
    s_expression *s_coord = NULL;
-   s_list *s_offset = NULL;
+   s_expression *s_offset = NULL;
    s_expression *s_proj = NULL;
    s_list *s_shadow = NULL;
    s_expression *s_lod = NULL;
 
-   ir_texture_opcode op;
+   ir_texture_opcode op = ir_tex; /* silence warning */
 
    s_pattern tex_pattern[] =
       { "tex", s_sampler, s_coord, s_offset, s_proj, s_shadow };
@@ -897,6 +893,9 @@ ir_reader::read_texture(s_expression *expr)
       op = ir_texture::get_opcode(tag->value());
       if (op == -1)
         return NULL;
+   } else {
+      ir_read_error(NULL, "unexpected texture pattern");
+      return NULL;
    }
 
    ir_texture *tex = new(mem_ctx) ir_texture(op);
@@ -918,18 +917,15 @@ ir_reader::read_texture(s_expression *expr)
       return NULL;
    }
 
-   // Read texel offset, i.e. (0 0 0)
-   s_int *offset_x;
-   s_int *offset_y;
-   s_int *offset_z;
-   s_pattern offset_pat[] = { offset_x, offset_y, offset_z };
-   if (!MATCH(s_offset, offset_pat)) {
-      ir_read_error(s_offset, "expected (<int> <int> <int>)");
-      return NULL;
+   // Read texel offset - either 0 or an rvalue.
+   s_int *si_offset = SX_AS_INT(s_offset);
+   if (si_offset == NULL || si_offset->value() != 0) {
+      tex->offset = read_rvalue(s_offset);
+      if (tex->offset == NULL) {
+        ir_read_error(s_offset, "expected 0 or an expression");
+        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_int *proj_as_int = SX_AS_INT(s_proj);
index 773bfcfa3ec9425d20fa82e29b586cdb4d6924e9..ed6c7cb6a1a088e6fb1b2d31a5d15324a72983a9 100644 (file)
@@ -53,6 +53,7 @@ ir_rvalue_visitor::visit_leave(ir_texture *ir)
    handle_rvalue(&ir->coordinate);
    handle_rvalue(&ir->projector);
    handle_rvalue(&ir->shadow_comparitor);
+   handle_rvalue(&ir->offset);
 
    switch (ir->op) {
    case ir_tex:
index 5b055f64d3867e18a2525dd163f6d4a8da898c0d..44d7549ea285bda27b48cbf88b3fd012d565d241 100644 (file)
@@ -179,7 +179,7 @@ ir_validate::visit_enter(ir_function *ir)
 ir_visitor_status
 ir_validate::visit_leave(ir_function *ir)
 {
-   assert(talloc_parent(ir->name) == ir);
+   assert(ralloc_parent(ir->name) == ir);
 
    this->current_function = NULL;
    return visit_continue;
@@ -450,7 +450,7 @@ ir_validate::visit(ir_variable *ir)
     * declared before it is dereferenced.
     */
    if (ir->name)
-      assert(talloc_parent(ir->name) == ir);
+      assert(ralloc_parent(ir->name) == ir);
 
    hash_table_insert(ht, ir, ir);
    return visit_continue;
index 73da28faf4f8e664e64699590b410fdc0a95728f..18a3e0fb0d9e120c0d2f1f0537708bd2c91e739b 100644 (file)
@@ -45,6 +45,7 @@ add_variable(const char *name, enum ir_variable_mode mode, int slot,
    switch (var->mode) {
    case ir_var_auto:
    case ir_var_in:
+   case ir_var_const_in:
    case ir_var_uniform:
    case ir_var_system_value:
       var->read_only = true;
index 8b43bad71f84f38bb74a1c267260d4c7387a258e..906135a9e1e370ad2d7bf64c65e864ccb58ec221 100644 (file)
@@ -54,13 +54,13 @@ class ir_variable_refcount_visitor : public ir_hierarchical_visitor {
 public:
    ir_variable_refcount_visitor(void)
    {
-      this->mem_ctx = talloc_new(NULL);
+      this->mem_ctx = ralloc_context(NULL);
       this->variable_list.make_empty();
    }
 
    ~ir_variable_refcount_visitor(void)
    {
-      talloc_free(this->mem_ctx);
+      ralloc_free(this->mem_ctx);
    }
 
    virtual ir_visitor_status visit(ir_variable *);
index 05930edb80e93241dda5509e4e4e7b41292a8e4c..5851c14d624ca9b5cda61a5a2876df39562bed94 100644 (file)
  * 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"
@@ -185,6 +177,18 @@ public:
            var = ir->var->clone(linked, NULL);
            linked->symbols->add_variable(var);
            linked->ir->push_head(var);
+        } else if (var->type->is_array()) {
+           /* It is possible to have a global array declared in multiple
+            * shaders without a size.  The array is implicitly sized by the
+            * maximal access to it in *any* shader.  Because of this, we
+            * need to track the maximal access to the array as linking pulls
+            * more functions in that access the array.
+            */
+           var->max_array_access =
+              MAX2(var->max_array_access, ir->var->max_array_access);
+
+           if (var->type->length == 0 && ir->var->type->length != 0)
+              var->type = ir->var->type;
         }
 
         ir->var = var;
index c906d7442127dadb9c2f073134ea01a09aeab042..7db5c5e8d5313b4c5040bad5caeb53b51862c235 100644 (file)
  *
  * \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"
@@ -176,9 +168,9 @@ linker_error_printf(gl_shader_program *prog, const char *fmt, ...)
 {
    va_list ap;
 
-   prog->InfoLog = talloc_strdup_append(prog->InfoLog, "error: ");
+   ralloc_strcat(&prog->InfoLog, "error: ");
    va_start(ap, fmt);
-   prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, ap);
+   ralloc_vasprintf_append(&prog->InfoLog, fmt, ap);
    va_end(ap);
 }
 
@@ -303,6 +295,7 @@ mode_string(const ir_variable *var)
    case ir_var_out:     return "shader output";
    case ir_var_inout:   return "shader inout";
 
+   case ir_var_const_in:
    case ir_var_temporary:
    default:
       assert(!"Should not get here.");
@@ -360,11 +353,8 @@ cross_validate_globals(struct gl_shader_program *prog,
                   && (var->type->fields.array == existing->type->fields.array)
                   && ((var->type->length == 0)
                       || (existing->type->length == 0))) {
-                 if (existing->type->length == 0) {
+                 if (var->type->length != 0) {
                     existing->type = var->type;
-                    existing->max_array_access =
-                       MAX2(existing->max_array_access,
-                            var->max_array_access);
                  }
               } else {
                  linker_error_printf(prog, "%s `%s' declared as type "
@@ -389,6 +379,32 @@ cross_validate_globals(struct gl_shader_program *prog,
               existing->explicit_location = true;
            }
 
+        /* Validate layout qualifiers for gl_FragDepth.
+         *
+         * From the AMD_conservative_depth spec:
+         *    "If gl_FragDepth is redeclared in any fragment shader in
+         *    a program, it must be redeclared in all fragment shaders in that
+         *    program that have static assignments to gl_FragDepth. All
+         *    redeclarations of gl_FragDepth in all fragment shaders in
+         *    a single program must have the same set of qualifiers."
+         */
+        if (strcmp(var->name, "gl_FragDepth") == 0) {
+           bool layout_declared = var->depth_layout != ir_depth_layout_none;
+           bool layout_differs = var->depth_layout != existing->depth_layout;
+           if (layout_declared && layout_differs) {
+              linker_error_printf(prog,
+                 "All redeclarations of gl_FragDepth in all fragment shaders "
+                 "in a single program must have the same set of qualifiers.");
+           }
+           if (var->used && layout_differs) {
+              linker_error_printf(prog,
+                    "If gl_FragDepth is redeclared with a layout qualifier in"
+                    "any fragment shader, it must be redeclared with the same"
+                    "layout qualifier in all fragment shaders that have"
+                    "assignments to gl_FragDepth");
+           }
+        }
+
            /* FINISHME: Handle non-constant initializers.
             */
            if (var->constant_value != NULL) {
@@ -413,7 +429,7 @@ cross_validate_globals(struct gl_shader_program *prog,
                   * FINISHME: will fail.
                   */
                  existing->constant_value =
-                    var->constant_value->clone(talloc_parent(existing), NULL);
+                    var->constant_value->clone(ralloc_parent(existing), NULL);
            }
 
            if (existing->invariant != var->invariant) {
@@ -894,30 +910,29 @@ link_intrastage_shaders(void *mem_ctx,
 
    free(linking_shaders);
 
-   /* Make a pass over all global variables to ensure that arrays with
+   /* Make a pass over all variable declarations to ensure that arrays with
     * unspecified sizes have a size specified.  The size is inferred from the
     * max_array_access field.
     */
    if (linked != NULL) {
-      foreach_list(node, linked->ir) {
-        ir_variable *const var = ((ir_instruction *) node)->as_variable();
-
-        if (var == NULL)
-           continue;
-
-        if ((var->mode != ir_var_auto) && (var->mode != ir_var_temporary))
-           continue;
-
-        if (!var->type->is_array() || (var->type->length != 0))
-           continue;
+      class array_sizing_visitor : public ir_hierarchical_visitor {
+      public:
+        virtual ir_visitor_status visit(ir_variable *var)
+        {
+           if (var->type->is_array() && (var->type->length == 0)) {
+              const glsl_type *type =
+                 glsl_type::get_array_instance(var->type->fields.array,
+                                               var->max_array_access + 1);
+
+              assert(type != NULL);
+              var->type = type;
+           }
 
-        const glsl_type *type =
-           glsl_type::get_array_instance(var->type->fields.array,
-                                         var->max_array_access);
+           return visit_continue;
+        }
+      } v;
 
-        assert(type != NULL);
-        var->type = type;
-      }
+      v.run(linked->ir);
    }
 
    return linked;
@@ -997,7 +1012,7 @@ add_uniform(void *mem_ctx, exec_list *uniforms, struct hash_table *ht,
    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,
+        char *field_name = ralloc_asprintf(mem_ctx, "%s.%s", name,
                                            type->fields.structure[i].name);
 
         add_uniform(mem_ctx, uniforms, ht, field_name, field_type,
@@ -1013,7 +1028,7 @@ add_uniform(void *mem_ctx, exec_list *uniforms, struct hash_table *ht,
         /* 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);
+              char *elem_name = ralloc_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);
            }
@@ -1075,7 +1090,7 @@ assign_uniform_locations(struct gl_shader_program *prog)
    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);
+   void *mem_ctx = ralloc_context(NULL);
 
    for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
       if (prog->_LinkedShaders[i] == NULL)
@@ -1104,7 +1119,7 @@ assign_uniform_locations(struct gl_shader_program *prog)
       }
    }
 
-   talloc_free(mem_ctx);
+   ralloc_free(mem_ctx);
 
    gl_uniform_list *ul = (gl_uniform_list *)
       calloc(1, sizeof(gl_uniform_list));
@@ -1472,16 +1487,16 @@ assign_varying_locations(struct gl_shader_program *prog,
 void
 link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
 {
-   void *mem_ctx = talloc_init("temporary linker context");
+   void *mem_ctx = ralloc_context(NULL); // temporary linker context
 
    prog->LinkStatus = false;
    prog->Validated = false;
    prog->_Used = false;
 
    if (prog->InfoLog != NULL)
-      talloc_free(prog->InfoLog);
+      ralloc_free(prog->InfoLog);
 
-   prog->InfoLog = talloc_strdup(NULL, "");
+   prog->InfoLog = ralloc_strdup(NULL, "");
 
    /* Separate the shaders into groups based on their type.
     */
@@ -1663,6 +1678,20 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
       demote_shader_inputs_and_outputs(sh, ir_var_in);
    }
 
+   /* OpenGL ES requires that a vertex shader and a fragment shader both be
+    * present in a linked program.  By checking for use of shading language
+    * version 1.00, we also catch the GL_ARB_ES2_compatibility case.
+    */
+   if (ctx->API == API_OPENGLES2 || prog->Version == 100) {
+      if (prog->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
+        linker_error_printf(prog, "program lacks a vertex shader\n");
+        prog->LinkStatus = false;
+      } else if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) {
+        linker_error_printf(prog, "program lacks a fragment shader\n");
+        prog->LinkStatus = false;
+      }
+   }
+
    /* FINISHME: Assign fragment shader output locations. */
 
 done:
@@ -1676,5 +1705,5 @@ done:
       reparent_ir(prog->_LinkedShaders[i]->ir, prog->_LinkedShaders[i]->ir);
    }
 
-   talloc_free(mem_ctx);
+   ralloc_free(mem_ctx);
 }
index 3197b03cf2832a51fd9044e72f9debb55f33cb8f..1d46365faec6d931d68c0314f1459d45230690ed 100644 (file)
 
 #ifndef __cplusplus
 #include <stddef.h>
-#include <talloc.h>
-#else
-extern "C" {
-#include <talloc.h>
-}
 #endif
-
 #include <assert.h>
 
+#include "ralloc.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). */
+   /* Callers of this ralloc-based new need not call delete. It's
+    * easier to just ralloc_free 'ctx' (or any of its ancestors). */
    static void* operator new(size_t size, void *ctx)
    {
       void *node;
 
-      node = talloc_size(ctx, size);
+      node = ralloc_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. */
+    * ralloc_free in that case. */
    static void operator delete(void *node)
    {
-      talloc_free(node);
+      ralloc_free(node);
    }
 
    exec_node() : next(NULL), prev(NULL)
@@ -289,23 +285,23 @@ struct exec_list {
    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). */
+   /* Callers of this ralloc-based new need not call delete. It's
+    * easier to just ralloc_free 'ctx' (or any of its ancestors). */
    static void* operator new(size_t size, void *ctx)
    {
       void *node;
 
-      node = talloc_size(ctx, size);
+      node = ralloc_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. */
+    * ralloc_free in that case. */
    static void operator delete(void *node)
    {
-      talloc_free(node);
+      ralloc_free(node);
    }
 
    exec_list()
index 3cf86ebaa38dd854ae3ce37d8fab7d6088d2b717..9bba6a97c488ac198482b7512ca198d71a3bbb61 100644 (file)
@@ -37,7 +37,7 @@ loop_state::loop_state()
 {
    this->ht = hash_table_ctor(0, hash_table_pointer_hash,
                              hash_table_pointer_compare);
-   this->mem_ctx = talloc_init("loop state");
+   this->mem_ctx = ralloc_context(NULL);
    this->loop_found = false;
 }
 
@@ -45,7 +45,7 @@ loop_state::loop_state()
 loop_state::~loop_state()
 {
    hash_table_dtor(this->ht);
-   talloc_free(this->mem_ctx);
+   ralloc_free(this->mem_ctx);
 }
 
 
@@ -78,8 +78,8 @@ loop_variable_state::get(const ir_variable *ir)
 loop_variable *
 loop_variable_state::insert(ir_variable *var)
 {
-   void *mem_ctx = talloc_parent(this);
-   loop_variable *lv = talloc_zero(mem_ctx, loop_variable);
+   void *mem_ctx = ralloc_parent(this);
+   loop_variable *lv = rzalloc(mem_ctx, loop_variable);
 
    lv->var = var;
 
@@ -93,8 +93,8 @@ loop_variable_state::insert(ir_variable *var)
 loop_terminator *
 loop_variable_state::insert(ir_if *if_stmt)
 {
-   void *mem_ctx = talloc_parent(this);
-   loop_terminator *t = talloc_zero(mem_ctx, loop_terminator);
+   void *mem_ctx = ralloc_parent(this);
+   loop_terminator *t = rzalloc(mem_ctx, loop_terminator);
 
    t->ir = if_stmt;
    this->terminators.push_tail(t);
@@ -450,7 +450,7 @@ get_basic_induction_increment(ir_assignment *ir, hash_table *var_hash)
    }
 
    if ((inc != NULL) && (rhs->operation == ir_binop_sub)) {
-      void *mem_ctx = talloc_parent(ir);
+      void *mem_ctx = ralloc_parent(ir);
 
       inc = new(mem_ctx) ir_expression(ir_unop_neg,
                                       inc->type,
index b528810f40d928a41b1e29688e6e04874b7f20a2..9acbadc50ea58f7d980ee3eaa62729c776fcb2c2 100644 (file)
@@ -21,7 +21,7 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-#include <climits>
+#include <limits.h>
 #include "main/compiler.h"
 #include "glsl_types.h"
 #include "loop_analysis.h"
@@ -88,7 +88,7 @@ calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment,
    if (from == NULL || to == NULL || increment == NULL)
       return -1;
 
-   void *mem_ctx = talloc_init("%s", __func__);
+   void *mem_ctx = ralloc_context(NULL);
 
    ir_expression *const sub =
       new(mem_ctx) ir_expression(ir_binop_sub, from->type, to, from);
@@ -147,7 +147,7 @@ calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment,
       }
    }
 
-   talloc_free(mem_ctx);
+   ralloc_free(mem_ctx);
    return (valid_loop) ? iter_value : -1;
 }
 
index 46000524ba105fdc56358d32261b44dc952711d5..5b84e101477ea328ff5f895a3addbc20563670aa 100644 (file)
@@ -150,7 +150,7 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
           */
          break_ir->remove();
 
-         void *const mem_ctx = talloc_parent(ir);
+         void *const mem_ctx = ralloc_parent(ir);
          ir_instruction *ir_to_replace = ir;
 
          for (int i = 0; i < iterations; i++) {
@@ -182,7 +182,7 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
       }
    }
 
-   void *const mem_ctx = talloc_parent(ir);
+   void *const mem_ctx = ralloc_parent(ir);
 
    for (int i = 0; i < iterations; i++) {
       exec_list copy_list;
index b95313df8c817e943a77081a80b9af783889ad63..cafd2dd3b44defdeb46a5c75b97f6db0473b147a 100644 (file)
@@ -170,7 +170,7 @@ lower_discard_visitor::visit_leave(ir_if *ir)
    if (then_discard == NULL && else_discard == NULL)
       return visit_continue;
 
-   void *mem_ctx = talloc_parent(ir);
+   void *mem_ctx = ralloc_parent(ir);
 
    ir_variable *temp = new(mem_ctx) ir_variable(glsl_type::bool_type,
                                                "discard_cond_temp",
index 40ffc45c86c0575743dc43c5f5d68ba7f4a6b950..e3a1065d9963e5026df7af2745c33450f87f4e71 100644 (file)
@@ -171,7 +171,7 @@ ir_if_to_cond_assign_visitor::visit_leave(ir_if *ir)
    if (found_control_flow)
       return visit_continue;
 
-   void *mem_ctx = talloc_parent(ir);
+   void *mem_ctx = ralloc_parent(ir);
 
    /* Store the condition to a variable so the assignment conditions are
     * simpler.
index 7065fdec35f6bd259b8f68315385fcd958930013..8cbbfa713c9c448ac1b2fdbe29e1881b7ef17980 100644 (file)
@@ -368,7 +368,7 @@ ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *orig_assign)
 
    assert(orig_expr->get_num_operands() <= 2);
 
-   mem_ctx = talloc_parent(orig_assign);
+   mem_ctx = ralloc_parent(orig_assign);
 
    ir_dereference_variable *lhs_deref =
       orig_assign->lhs->as_dereference_variable();
index cb32d28348629288e20824c2addbb2e85bfb711c..85f59b675e0469663a3d950fb57de49f6c2cd796 100644 (file)
@@ -51,7 +51,7 @@ public:
        * that implements noise.  No hardware has a noise instruction.
        */
       if (expr->operation == ir_unop_noise) {
-        *rvalue = ir_constant::zero(talloc_parent(expr), expr->type);
+        *rvalue = ir_constant::zero(ralloc_parent(expr), expr->type);
         this->progress = true;
       }
    }
index 1fd26a7a2b5d1f65dff9670441ac868912a8aa09..6e3aaecceee49096513dae9183775ea7da83a18a 100644 (file)
@@ -55,7 +55,7 @@ lower_texture_projection_visitor::visit_leave(ir_texture *ir)
    if (!ir->projector)
       return visit_continue;
 
-   void *mem_ctx = talloc_parent(ir);
+   void *mem_ctx = ralloc_parent(ir);
 
    ir_variable *var = new(mem_ctx) ir_variable(ir->projector->type,
                                               "projector", ir_var_auto);
index 7b4e4ad07cbf496b6f5469d5620c4c6a6bd0de24..8eb1612f0a0da921fb6e3ee30b8bd56e211b4ef5 100644 (file)
@@ -54,7 +54,7 @@ struct assignment_generator
       /* Just clone the rest of the deref chain when trying to get at the
        * underlying variable.
        */
-      void *mem_ctx = talloc_parent(base_ir);
+      void *mem_ctx = ralloc_parent(base_ir);
       ir_dereference *element =
         new(mem_ctx) ir_dereference_array(this->array->clone(mem_ctx, NULL),
                                           new(mem_ctx) ir_constant(i));
@@ -91,7 +91,7 @@ struct switch_generator
        linear_sequence_max_length(linear_sequence_max_length),
        condition_components(condition_components)
    {
-      this->mem_ctx = talloc_parent(index);
+      this->mem_ctx = ralloc_parent(index);
    }
 
    void linear_sequence(unsigned begin, unsigned end, exec_list *list)
@@ -255,6 +255,7 @@ public:
       case ir_var_uniform:
         return this->lower_uniforms;
       case ir_var_in:
+      case ir_var_const_in:
         return (var->location == -1) ? this->lower_temps : this->lower_inputs;
       case ir_var_out:
         return (var->location == -1) ? this->lower_temps : this->lower_outputs;
@@ -275,7 +276,7 @@ public:
          ? orig_deref->array->type->length
          : orig_deref->array->type->matrix_columns;
 
-      void *const mem_ctx = talloc_parent(base_ir);
+      void *const mem_ctx = ralloc_parent(base_ir);
 
       /* Temporary storage for either the result of the dereference of
        * the array, or the RHS that's being assigned into the
@@ -342,7 +343,7 @@ public:
       if (needs_lowering(orig_deref)) {
          ir_variable* var = convert_dereference_array(orig_deref, 0);
          assert(var);
-         *pir = new(talloc_parent(base_ir)) ir_dereference_variable(var);
+         *pir = new(ralloc_parent(base_ir)) ir_dereference_variable(var);
          this->progress = true;
       }
    }
index f8011a16e5ba1286ef00c74619f491aca7bb3829..3c4d93201d2b46e5d64e5c407cc9b38a0beb2a80 100644 (file)
@@ -82,7 +82,7 @@ ir_vec_index_to_cond_assign_visitor::convert_vec_index_to_cond_assign(ir_rvalue
        orig_deref->array->type->is_array())
       return ir;
 
-   void *mem_ctx = talloc_parent(ir);
+   void *mem_ctx = ralloc_parent(ir);
 
    assert(orig_deref->array_index->type->base_type == GLSL_TYPE_INT);
 
@@ -167,7 +167,7 @@ ir_vec_index_to_cond_assign_visitor::visit_leave(ir_assignment *ir)
        orig_deref->array->type->is_array())
       return visit_continue;
 
-   void *mem_ctx = talloc_parent(ir);
+   void *mem_ctx = ralloc_parent(ir);
 
    assert(orig_deref->array_index->type->base_type == GLSL_TYPE_INT);
 
index 9ae43c0db17955c7ce4c58002e1e7905e6e54da4..c7630c28a83ef99b3a36146bb04811400e7253cb 100644 (file)
@@ -74,7 +74,7 @@ ir_vec_index_to_swizzle_visitor::convert_vec_index_to_swizzle(ir_rvalue *ir)
    if (!ir_constant)
       return ir;
 
-   void *ctx = talloc_parent(ir);
+   void *ctx = ralloc_parent(ir);
    this->progress = true;
    return new(ctx) ir_swizzle(deref->array,
                              ir_constant->value.i[0], 0, 0, 0, 1);
index 93c37638bbd4eb7397cbcc61a49b65ac45169ce0..57963a121addf487224a7562453d2f65bda6e597 100644 (file)
@@ -125,7 +125,7 @@ lower_vector_visitor::handle_rvalue(ir_rvalue **rvalue)
    if (this->dont_lower_swz && is_extended_swizzle(expr))
       return;
 
-   /* FINISHME: Is this the right thing to use for the talloc context?
+   /* FINISHME: Is this the right thing to use for the ralloc context?
     */
    void *const mem_ctx = expr;
 
index 9b041aafe42caa7112d99321432705241d4ae04b..096da93dcef7480e1ccaaff6dba8635be9c8698f 100644 (file)
@@ -20,8 +20,6 @@
  * 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 "ast.h"
@@ -56,7 +54,7 @@ _mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type)
    (void) ctx;
 
    assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
-   shader = talloc_zero(NULL, struct gl_shader);
+   shader = rzalloc(NULL, struct gl_shader);
    if (shader) {
       shader->Type = type;
       shader->Name = name;
@@ -72,12 +70,18 @@ initialize_context(struct gl_context *ctx, gl_api api)
 
    ctx->API = api;
 
+   ctx->Extensions.ARB_ES2_compatibility = GL_TRUE;
    ctx->Extensions.ARB_draw_buffers = GL_TRUE;
    ctx->Extensions.ARB_draw_instanced = GL_TRUE;
    ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
    ctx->Extensions.EXT_texture_array = GL_TRUE;
    ctx->Extensions.NV_texture_rectangle = GL_TRUE;
 
+   /* GLSL 1.30 isn't fully supported, but we need to advertise 1.30 so that
+    * the built-in functions for 1.30 can be built.
+    */
+   ctx->Const.GLSLVersion = 130;
+
    /* 1.10 minimums. */
    ctx->Const.MaxLights = 8;
    ctx->Const.MaxClipPlanes = 8;
@@ -101,7 +105,7 @@ initialize_context(struct gl_context *ctx, gl_api api)
    ctx->Driver.NewShader = _mesa_new_shader;
 }
 
-/* Returned string will have 'ctx' as its talloc owner. */
+/* Returned string will have 'ctx' as its ralloc owner. */
 static char *
 load_text_file(void *ctx, const char *file_name)
 {
@@ -118,7 +122,7 @@ load_text_file(void *ctx, const char *file_name)
        size = ftell(fp);
        fseek(fp, 0L, SEEK_SET);
 
-       text = (char *) talloc_size(ctx, size + 1);
+       text = (char *) ralloc_size(ctx, size + 1);
        if (text != NULL) {
                do {
                        size_t bytes = fread(text + total_read,
@@ -236,14 +240,14 @@ compile_shader(struct gl_context *ctx, struct gl_shader *shader)
    shader->num_builtins_to_link = state->num_builtins_to_link;
 
    if (shader->InfoLog)
-      talloc_free(shader->InfoLog);
+      ralloc_free(shader->InfoLog);
 
    shader->InfoLog = state->info_log;
 
    /* Retain any live IR, but trash the rest. */
    reparent_ir(shader->ir, shader);
 
-   talloc_free(state);
+   ralloc_free(state);
 
    return;
 }
@@ -268,16 +272,16 @@ main(int argc, char **argv)
 
    struct gl_shader_program *whole_program;
 
-   whole_program = talloc_zero (NULL, struct gl_shader_program);
+   whole_program = rzalloc (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);
+      whole_program->Shaders =
+        reralloc(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);
+      struct gl_shader *shader = rzalloc(whole_program, gl_shader);
 
       whole_program->Shaders[whole_program->NumShaders] = shader;
       whole_program->NumShaders++;
@@ -320,9 +324,9 @@ main(int argc, char **argv)
    }
 
    for (unsigned i = 0; i < MESA_SHADER_TYPES; i++)
-      talloc_free(whole_program->_LinkedShaders[i]);
+      ralloc_free(whole_program->_LinkedShaders[i]);
 
-   talloc_free(whole_program);
+   ralloc_free(whole_program);
    _mesa_glsl_release_types();
    _mesa_glsl_release_functions();
 
index 20f6159f0e689449352917e311224e5696a51e4e..cade9611dbbe2428bd44ad16d7029579b33a0e5d 100644 (file)
@@ -191,7 +191,7 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
    }
 
    if (this->mem_ctx == NULL)
-      this->mem_ctx = talloc_parent(ir);
+      this->mem_ctx = ralloc_parent(ir);
 
    switch (ir->operation) {
    case ir_unop_logic_not: {
index d69ca75fe03090f9a27f960040eddad40baa1397..599b21525de8a4c94b76b47ac929fd0d35b138bc 100644 (file)
@@ -122,7 +122,7 @@ ir_constant_folding_visitor::visit_enter(ir_call *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) {
+      if (sig_param->mode == ir_var_in || sig_param->mode == ir_var_const_in) {
         ir_rvalue *new_param = param_rval;
 
         handle_rvalue(&new_param);
index 6719fc818638f11e0de1a64c7ea3986874402332..4425f4211934a0dd5f913e1048a2365f24419fda 100644 (file)
@@ -78,13 +78,13 @@ public:
    ir_constant_propagation_visitor()
    {
       progress = false;
-      mem_ctx = talloc_new(0);
+      mem_ctx = ralloc_context(0);
       this->acp = new(mem_ctx) exec_list;
       this->kills = new(mem_ctx) exec_list;
    }
    ~ir_constant_propagation_visitor()
    {
-      talloc_free(mem_ctx);
+      ralloc_free(mem_ctx);
    }
 
    virtual ir_visitor_status visit_enter(class ir_loop *);
@@ -195,7 +195,7 @@ ir_constant_propagation_visitor::handle_rvalue(ir_rvalue **rvalue)
       }
    }
 
-   *rvalue = new(talloc_parent(deref)) ir_constant(type, &data);
+   *rvalue = new(ralloc_parent(deref)) ir_constant(type, &data);
    this->progress = true;
 }
 
@@ -398,11 +398,8 @@ 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->condition)
+      return;
 
    if (!ir->write_mask)
       return;
index 8068d0c1435fba86a2e09f2f48249a05285419d1..3fa7c3badc804c4ae5aa6d55d67876bffb18fc1d 100644 (file)
@@ -104,11 +104,8 @@ ir_constant_variable_visitor::visit_enter(ir_assignment *ir)
    /* 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;
-   }
+   if (ir->condition)
+      return visit_continue;
 
    ir_variable *var = ir->whole_variable_written();
    if (!var)
index 8d07fefbfd097e94124e6438600f1130a94656ff..efa3afda35aefe40f19e45bc8fe208b499aee1bc 100644 (file)
@@ -71,13 +71,13 @@ public:
    ir_copy_propagation_visitor()
    {
       progress = false;
-      mem_ctx = talloc_new(0);
+      mem_ctx = ralloc_context(0);
       this->acp = new(mem_ctx) exec_list;
       this->kills = new(mem_ctx) exec_list;
    }
    ~ir_copy_propagation_visitor()
    {
-      talloc_free(mem_ctx);
+      ralloc_free(mem_ctx);
    }
 
    virtual ir_visitor_status visit(class ir_dereference_variable *);
@@ -191,7 +191,7 @@ ir_copy_propagation_visitor::visit_enter(ir_call *ir)
       sig_param_iter.next();
    }
 
-   /* Since we're unlinked, we don't (necssarily) know the side effects of
+   /* Since we're unlinked, we don't (necessarily) know the side effects of
     * this call.  So kill all copies.
     */
    acp->make_empty();
@@ -309,11 +309,8 @@ 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;
-   }
+   if (ir->condition)
+      return;
 
    ir_variable *lhs_var = ir->whole_variable_written();
    ir_variable *rhs_var = ir->rhs->whole_variable_referenced();
@@ -325,7 +322,7 @@ ir_copy_propagation_visitor::add_copy(ir_assignment *ir)
          * 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);
+        ir->condition = new(ralloc_parent(ir)) ir_constant(false);
         this->progress = true;
       } else {
         entry = new(this->mem_ctx) acp_entry(lhs_var, rhs_var);
diff --git a/src/glsl/opt_copy_propagation_elements.cpp b/src/glsl/opt_copy_propagation_elements.cpp
new file mode 100644 (file)
index 0000000..8541d9a
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+ * 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 opt_copy_propagation_elements.cpp
+ *
+ * Replaces usage of recently-copied components of variables with the
+ * previous copy of the variable.
+ *
+ * This pass can be compared with opt_copy_propagation, which operands
+ * on arbitrary whole-variable copies.  However, in order to handle
+ * the copy propagation of swizzled variables or writemasked writes,
+ * we want to track things on a channel-wise basis.  I found that
+ * trying to mix the swizzled/writemasked support here with the
+ * whole-variable stuff in opt_copy_propagation.cpp just made a mess,
+ * so this is separate despite the ACP handling being somewhat
+ * similar.
+ *
+ * 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_rvalue_visitor.h"
+#include "ir_basic_block.h"
+#include "ir_optimization.h"
+#include "glsl_types.h"
+
+static bool debug = false;
+
+class acp_entry : public exec_node
+{
+public:
+   acp_entry(ir_variable *lhs, ir_variable *rhs, int write_mask, int swizzle[4])
+   {
+      this->lhs = lhs;
+      this->rhs = rhs;
+      this->write_mask = write_mask;
+      memcpy(this->swizzle, swizzle, sizeof(this->swizzle));
+   }
+
+   acp_entry(acp_entry *a)
+   {
+      this->lhs = a->lhs;
+      this->rhs = a->rhs;
+      this->write_mask = a->write_mask;
+      memcpy(this->swizzle, a->swizzle, sizeof(this->swizzle));
+   }
+
+   ir_variable *lhs;
+   ir_variable *rhs;
+   unsigned int write_mask;
+   int swizzle[4];
+};
+
+
+class kill_entry : public exec_node
+{
+public:
+   kill_entry(ir_variable *var, int write_mask)
+   {
+      this->var = var;
+      this->write_mask = write_mask;
+   }
+
+   ir_variable *var;
+   unsigned int write_mask;
+};
+
+class ir_copy_propagation_elements_visitor : public ir_rvalue_visitor {
+public:
+   ir_copy_propagation_elements_visitor()
+   {
+      this->progress = false;
+      this->mem_ctx = ralloc_context(NULL);
+      this->shader_mem_ctx = NULL;
+      this->acp = new(mem_ctx) exec_list;
+      this->kills = new(mem_ctx) exec_list;
+   }
+   ~ir_copy_propagation_elements_visitor()
+   {
+      ralloc_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_leave(class ir_assignment *);
+   virtual ir_visitor_status visit_enter(class ir_call *);
+   virtual ir_visitor_status visit_enter(class ir_if *);
+
+   void handle_rvalue(ir_rvalue **rvalue);
+
+   void add_copy(ir_assignment *ir);
+   void kill(kill_entry *k);
+   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;
+
+   /* Context for our local data structures. */
+   void *mem_ctx;
+   /* Context for allocating new shader nodes. */
+   void *shader_mem_ctx;
+};
+
+ir_visitor_status
+ir_copy_propagation_elements_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_elements_visitor::visit_leave(ir_assignment *ir)
+{
+   ir_dereference_variable *lhs = ir->lhs->as_dereference_variable();
+
+   if (lhs && (lhs->type->is_scalar() || lhs->type->is_vector())) {
+      kill_entry *k = new(mem_ctx) kill_entry(lhs->var, ir->write_mask);
+      kill(k);
+   }
+
+   add_copy(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!
+ */
+void
+ir_copy_propagation_elements_visitor::handle_rvalue(ir_rvalue **ir)
+{
+   int swizzle_chan[4];
+   ir_dereference_variable *deref_var;
+   ir_variable *source[4] = {NULL, NULL, NULL, NULL};
+   int source_chan[4];
+   int chans;
+
+   if (!*ir)
+      return;
+
+   ir_swizzle *swizzle = (*ir)->as_swizzle();
+   if (swizzle) {
+      deref_var = swizzle->val->as_dereference_variable();
+      if (!deref_var)
+        return;
+
+      swizzle_chan[0] = swizzle->mask.x;
+      swizzle_chan[1] = swizzle->mask.y;
+      swizzle_chan[2] = swizzle->mask.z;
+      swizzle_chan[3] = swizzle->mask.w;
+      chans = swizzle->type->vector_elements;
+   } else {
+      deref_var = (*ir)->as_dereference_variable();
+      if (!deref_var)
+        return;
+
+      swizzle_chan[0] = 0;
+      swizzle_chan[1] = 1;
+      swizzle_chan[2] = 2;
+      swizzle_chan[3] = 3;
+      chans = deref_var->type->vector_elements;
+   }
+
+   if (this->in_assignee)
+      return;
+
+   ir_variable *var = deref_var->var;
+
+   /* Try to find ACP entries covering swizzle_chan[], hoping they're
+    * the same source variable.
+    */
+   foreach_iter(exec_list_iterator, iter, *this->acp) {
+      acp_entry *entry = (acp_entry *)iter.get();
+
+      if (var == entry->lhs) {
+        for (int c = 0; c < chans; c++) {
+           if (entry->write_mask & (1 << swizzle_chan[c])) {
+              source[c] = entry->rhs;
+              source_chan[c] = entry->swizzle[swizzle_chan[c]];
+           }
+        }
+      }
+   }
+
+   /* Make sure all channels are copying from the same source variable. */
+   if (!source[0])
+      return;
+   for (int c = 1; c < chans; c++) {
+      if (source[c] != source[0])
+        return;
+   }
+
+   if (!shader_mem_ctx)
+      shader_mem_ctx = ralloc_parent(deref_var);
+
+   if (debug) {
+      printf("Copy propagation from:\n");
+      (*ir)->print();
+   }
+
+   deref_var = new(shader_mem_ctx) ir_dereference_variable(source[0]);
+   *ir = new(shader_mem_ctx) ir_swizzle(deref_var,
+                                       source_chan[0],
+                                       source_chan[1],
+                                       source_chan[2],
+                                       source_chan[3],
+                                       chans);
+
+   if (debug) {
+      printf("to:\n");
+      (*ir)->print();
+      printf("\n");
+   }
+}
+
+
+ir_visitor_status
+ir_copy_propagation_elements_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 (necessarily) 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_elements_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));
+   }
+
+   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;
+
+   /* Move the new kills into the parent block's list, removing them
+    * from the parent's ACP list in the process.
+    */
+   foreach_list_safe(node, new_kills) {
+      kill_entry *k = (kill_entry *)node;
+      kill(k);
+   }
+}
+
+ir_visitor_status
+ir_copy_propagation_elements_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_elements_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_list_safe(node, new_kills) {
+      kill_entry *k = (kill_entry *)node;
+      kill(k);
+   }
+
+   /* already descended into the children. */
+   return visit_continue_with_parent;
+}
+
+/* Remove any entries currently in the ACP for this kill. */
+void
+ir_copy_propagation_elements_visitor::kill(kill_entry *k)
+{
+   foreach_list_safe(node, acp) {
+      acp_entry *entry = (acp_entry *)node;
+
+      if (entry->lhs == k->var) {
+        entry->write_mask = entry->write_mask & ~k->write_mask;
+        if (entry->write_mask == 0)
+           entry->remove();
+      }
+      if (entry->rhs == k->var) {
+        entry->remove();
+      }
+   }
+
+   /* If we were on a list, remove ourselves before inserting */
+   if (k->next)
+      k->remove();
+
+   this->kills->push_tail(k);
+}
+
+/**
+ * Adds directly-copied channels between vector variables to the available
+ * copy propagation list.
+ */
+void
+ir_copy_propagation_elements_visitor::add_copy(ir_assignment *ir)
+{
+   acp_entry *entry;
+   int orig_swizzle[4] = {0, 1, 2, 3};
+   int swizzle[4];
+
+   if (ir->condition)
+      return;
+
+   ir_dereference_variable *lhs = ir->lhs->as_dereference_variable();
+   if (!lhs || !(lhs->type->is_scalar() || lhs->type->is_vector()))
+      return;
+
+   ir_dereference_variable *rhs = ir->rhs->as_dereference_variable();
+   if (!rhs) {
+      ir_swizzle *swiz = ir->rhs->as_swizzle();
+      if (!swiz)
+        return;
+
+      rhs = swiz->val->as_dereference_variable();
+      if (!rhs)
+        return;
+
+      orig_swizzle[0] = swiz->mask.x;
+      orig_swizzle[1] = swiz->mask.y;
+      orig_swizzle[2] = swiz->mask.z;
+      orig_swizzle[3] = swiz->mask.w;
+   }
+
+   /* Move the swizzle channels out to the positions they match in the
+    * destination.  We don't want to have to rewrite the swizzle[]
+    * array every time we clear a bit of the write_mask.
+    */
+   int j = 0;
+   for (int i = 0; i < 4; i++) {
+      if (ir->write_mask & (1 << i))
+        swizzle[i] = orig_swizzle[j++];
+   }
+
+   entry = new(this->mem_ctx) acp_entry(lhs->var, rhs->var, ir->write_mask,
+                                       swizzle);
+   this->acp->push_tail(entry);
+}
+
+bool
+do_copy_propagation_elements(exec_list *instructions)
+{
+   ir_copy_propagation_elements_visitor v;
+
+   visit_list_elements(&v, instructions);
+
+   return v.progress;
+}
index 5689e7d20db70f5a1a4ba628ec3f350122f409fc..39962bd602ef8ba89a2ad34eba903d82cdbdc437 100644 (file)
@@ -129,15 +129,8 @@ process_assignment(void *ctx, ir_assignment *ir, exec_list *assignments)
    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)) {
+   if (!ir->condition && (ir->whole_variable_written() != NULL)) {
       /* We did a whole-variable assignment.  So, any instruction in
        * the assignment list with the same LHS is dead.
        */
@@ -190,7 +183,7 @@ dead_code_local_basic_block(ir_instruction *first,
    bool *out_progress = (bool *)data;
    bool progress = false;
 
-   void *ctx = talloc_new(NULL);
+   void *ctx = ralloc_context(NULL);
    /* Safe looping, since process_assignment */
    for (ir = first, ir_next = (ir_instruction *)first->next;;
        ir = ir_next, ir_next = (ir_instruction *)ir->next) {
@@ -212,7 +205,7 @@ dead_code_local_basic_block(ir_instruction *first,
         break;
    }
    *out_progress = progress;
-   talloc_free(ctx);
+   ralloc_free(ctx);
 }
 
 /**
index cf91cb6d368858bccc6c9292b8471236c4585866..ceb79080a75213a481320e083f594b134252ec2d 100644 (file)
  public:
     ir_dead_functions_visitor()
     {
-       this->mem_ctx = talloc_new(NULL);
+       this->mem_ctx = ralloc_context(NULL);
     }
 
     ~ir_dead_functions_visitor()
     {
-       talloc_free(this->mem_ctx);
+       ralloc_free(this->mem_ctx);
     }
 
     virtual ir_visitor_status visit_enter(ir_function_signature *);
index 169fd8268825f59de3bb656ab801cc5f61367ffc..2e7831dcbdbe6b4b75bb6c501351e0e98176e326 100644 (file)
@@ -89,7 +89,7 @@ do_function_inlining(exec_list *instructions)
 static void
 replace_return_with_assignment(ir_instruction *ir, void *data)
 {
-   void *ctx = talloc_parent(ir);
+   void *ctx = ralloc_parent(ir);
    ir_variable *retval = (ir_variable *)data;
    ir_return *ret = ir->as_return();
 
@@ -110,7 +110,7 @@ replace_return_with_assignment(ir_instruction *ir, void *data)
 ir_rvalue *
 ir_call::generate_inline(ir_instruction *next_ir)
 {
-   void *ctx = talloc_parent(this);
+   void *ctx = ralloc_parent(this);
    ir_variable **parameters;
    int num_parameters;
    int i;
@@ -165,6 +165,7 @@ ir_call::generate_inline(ir_instruction *next_ir)
 
       /* 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_const_in ||
                            sig_param->mode == ir_var_inout)) {
         ir_assignment *assign;
 
@@ -357,7 +358,7 @@ 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);
+      *deref = this->deref->clone(ralloc_parent(*deref), NULL);
    }
 }
 
index d6191002c2f05d0fccc22ee6126cb11137504e08..014407c0be2f5ba30e4a5941e188964e09b1420a 100644 (file)
@@ -65,7 +65,7 @@ public:
 
    ir_variable **components;
 
-   /** talloc_parent(this->var) -- the shader's talloc context. */
+   /** ralloc_parent(this->var) -- the shader's ralloc context. */
    void *mem_ctx;
 };
 
@@ -74,13 +74,13 @@ class ir_structure_reference_visitor : public ir_hierarchical_visitor {
 public:
    ir_structure_reference_visitor(void)
    {
-      this->mem_ctx = talloc_new(NULL);
+      this->mem_ctx = ralloc_context(NULL);
       this->variable_list.make_empty();
    }
 
    ~ir_structure_reference_visitor(void)
    {
-      talloc_free(mem_ctx);
+      ralloc_free(mem_ctx);
    }
 
    virtual ir_visitor_status visit(ir_variable *);
@@ -322,7 +322,7 @@ do_structure_splitting(exec_list *instructions)
    if (refs.variable_list.is_empty())
       return false;
 
-   void *mem_ctx = talloc_new(NULL);
+   void *mem_ctx = ralloc_context(NULL);
 
    /* Replace the decls of the structures to be split with their split
     * components.
@@ -331,14 +331,14 @@ do_structure_splitting(exec_list *instructions)
       variable_entry2 *entry = (variable_entry2 *)iter.get();
       const struct glsl_type *type = entry->var->type;
 
-      entry->mem_ctx = talloc_parent(entry->var);
+      entry->mem_ctx = ralloc_parent(entry->var);
 
-      entry->components = talloc_array(mem_ctx,
+      entry->components = ralloc_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",
+        const char *name = ralloc_asprintf(mem_ctx, "%s_%s",
                                            entry->var->name,
                                            type->fields.structure[i].name);
 
@@ -355,7 +355,7 @@ do_structure_splitting(exec_list *instructions)
    ir_structure_splitting_visitor split(&refs.variable_list);
    visit_list_elements(&split, instructions);
 
-   talloc_free(mem_ctx);
+   ralloc_free(mem_ctx);
 
    return true;
 }
index 9917c045b1db607e0f38f981c44bb34295549b14..1ef940f9c72bc31cf72bac01783a36042650d58b 100644 (file)
@@ -195,7 +195,7 @@ ir_tree_grafting_visitor::visit_enter(ir_call *ir)
       ir_rvalue *ir = (ir_rvalue *)iter.get();
       ir_rvalue *new_ir = ir;
 
-      if (sig_param->mode != ir_var_in)
+      if (sig_param->mode != ir_var_in && sig_param->mode != ir_var_const_in)
         continue;
 
       if (do_graft(&new_ir)) {
@@ -245,6 +245,7 @@ ir_tree_grafting_visitor::visit_enter(ir_texture *ir)
 {
    if (do_graft(&ir->coordinate) ||
        do_graft(&ir->projector) ||
+       do_graft(&ir->offset) ||
        do_graft(&ir->shadow_comparitor))
         return visit_stop;
 
diff --git a/src/glsl/ralloc.c b/src/glsl/ralloc.c
new file mode 100644 (file)
index 0000000..6a5eac6
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+ * 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 <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "ralloc.h"
+
+#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
+
+#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
+
+#define CANARY 0x5A1106
+
+struct ralloc_header
+{
+   /* A canary value used to determine whether a pointer is ralloc'd. */
+   unsigned canary;
+
+   struct ralloc_header *parent;
+
+   /* The first child (head of a linked list) */
+   struct ralloc_header *child;
+
+   /* Linked list of siblings */
+   struct ralloc_header *prev;
+   struct ralloc_header *next;
+
+   void (*destructor)(void *);
+};
+
+typedef struct ralloc_header ralloc_header;
+
+static void unlink_block(ralloc_header *info);
+static void unsafe_free(ralloc_header *info);
+
+static ralloc_header *
+get_header(const void *ptr)
+{
+   ralloc_header *info = (ralloc_header *) (((char *) ptr) -
+                                           sizeof(ralloc_header));
+   assert(info->canary == CANARY);
+   return info;
+}
+
+#define PTR_FROM_HEADER(info) (((char *) info) + sizeof(ralloc_header))
+
+static void
+add_child(ralloc_header *parent, ralloc_header *info)
+{
+   if (parent != NULL) {
+      info->parent = parent;
+      info->next = parent->child;
+      parent->child = info;
+
+      if (info->next != NULL)
+        info->next->prev = info;
+   }
+}
+
+void *
+ralloc_context(const void *ctx)
+{
+   return ralloc_size(ctx, 0);
+}
+
+void *
+ralloc_size(const void *ctx, size_t size)
+{
+   void *block = calloc(1, size + sizeof(ralloc_header));
+
+   ralloc_header *info = (ralloc_header *) block;
+   ralloc_header *parent = ctx != NULL ? get_header(ctx) : NULL;
+
+   add_child(parent, info);
+
+   info->canary = CANARY;
+
+   return PTR_FROM_HEADER(info);
+}
+
+void *
+rzalloc_size(const void *ctx, size_t size)
+{
+   void *ptr = ralloc_size(ctx, size);
+   if (likely(ptr != NULL))
+      memset(ptr, 0, size);
+   return ptr;
+}
+
+/* helper function - assumes ptr != NULL */
+static void *
+resize(void *ptr, size_t size)
+{
+   ralloc_header *child, *old, *info;
+
+   old = get_header(ptr);
+   info = realloc(old, size + sizeof(ralloc_header));
+
+   if (info == NULL)
+      return NULL;
+
+   /* Update parent and sibling's links to the reallocated node. */
+   if (info != old && info->parent != NULL) {
+      if (info->parent->child == old)
+        info->parent->child = info;
+
+      if (info->prev != NULL)
+        info->prev->next = info;
+
+      if (info->next != NULL)
+        info->next->prev = info;
+   }
+
+   /* Update child->parent links for all children */
+   for (child = info->child; child != NULL; child = child->next)
+      child->parent = info;
+
+   return PTR_FROM_HEADER(info);
+}
+
+void *
+reralloc_size(const void *ctx, void *ptr, size_t size)
+{
+   if (unlikely(ptr == NULL))
+      return ralloc_size(ctx, size);
+
+   assert(ralloc_parent(ptr) == ctx);
+   return resize(ptr, size);
+}
+
+void *
+ralloc_array_size(const void *ctx, size_t size, unsigned count)
+{
+   if (count > SIZE_MAX/size)
+      return NULL;
+
+   return ralloc_size(ctx, size * count);
+}
+
+void *
+rzalloc_array_size(const void *ctx, size_t size, unsigned count)
+{
+   if (count > SIZE_MAX/size)
+      return NULL;
+
+   return rzalloc_size(ctx, size * count);
+}
+
+void *
+reralloc_array_size(const void *ctx, void *ptr, size_t size, unsigned count)
+{
+   if (count > SIZE_MAX/size)
+      return NULL;
+
+   return reralloc_size(ctx, ptr, size * count);
+}
+
+void
+ralloc_free(void *ptr)
+{
+   ralloc_header *info;
+
+   if (ptr == NULL)
+      return;
+
+   info = get_header(ptr);
+   unlink_block(info);
+   unsafe_free(info);
+}
+
+static void
+unlink_block(ralloc_header *info)
+{
+   /* Unlink from parent & siblings */
+   if (info->parent != NULL) {
+      if (info->parent->child == info)
+        info->parent->child = info->next;
+
+      if (info->prev != NULL)
+        info->prev->next = info->next;
+
+      if (info->next != NULL)
+        info->next->prev = info->prev;
+   }
+   info->parent = NULL;
+   info->prev = NULL;
+   info->next = NULL;
+}
+
+static void
+unsafe_free(ralloc_header *info)
+{
+   /* Recursively free any children...don't waste time unlinking them. */
+   ralloc_header *temp;
+   while (info->child != NULL) {
+      temp = info->child;
+      info->child = temp->next;
+      unsafe_free(temp);
+   }
+
+   /* Free the block itself.  Call the destructor first, if any. */
+   if (info->destructor != NULL)
+      info->destructor(PTR_FROM_HEADER(info));
+
+   free(info);
+}
+
+void
+ralloc_steal(const void *new_ctx, void *ptr)
+{
+   ralloc_header *info, *parent;
+
+   if (unlikely(ptr == NULL))
+      return;
+
+   info = get_header(ptr);
+   parent = get_header(new_ctx);
+
+   unlink_block(info);
+
+   add_child(parent, info);
+}
+
+void *
+ralloc_parent(const void *ptr)
+{
+   ralloc_header *info;
+
+   if (unlikely(ptr == NULL))
+      return NULL;
+
+   info = get_header(ptr);
+   return PTR_FROM_HEADER(info->parent);
+}
+
+static void *autofree_context = NULL;
+
+static void
+autofree(void)
+{
+   ralloc_free(autofree_context);
+}
+
+void *
+ralloc_autofree_context(void)
+{
+   if (unlikely(autofree_context == NULL)) {
+      autofree_context = ralloc_context(NULL);
+      atexit(autofree);
+   }
+   return autofree_context;
+}
+
+void
+ralloc_set_destructor(const void *ptr, void(*destructor)(void *))
+{
+   ralloc_header *info = get_header(ptr);
+   info->destructor = destructor;
+}
+
+char *
+ralloc_strdup(const void *ctx, const char *str)
+{
+   size_t n;
+   char *ptr;
+
+   if (unlikely(str == NULL))
+      return NULL;
+
+   n = strlen(str);
+   ptr = ralloc_array(ctx, char, n + 1);
+   memcpy(ptr, str, n);
+   ptr[n] = '\0';
+   return ptr;
+}
+
+char *
+ralloc_strndup(const void *ctx, const char *str, size_t max)
+{
+   size_t n;
+   char *ptr;
+
+   if (unlikely(str == NULL))
+      return NULL;
+
+   n = strlen(str);
+   if (n > max)
+      n = max;
+
+   ptr = ralloc_array(ctx, char, n + 1);
+   memcpy(ptr, str, n);
+   ptr[n] = '\0';
+   return ptr;
+}
+
+/* helper routine for strcat/strncat - n is the exact amount to copy */
+static bool
+cat(char **dest, const char *str, size_t n)
+{
+   char *both;
+   size_t existing_length;
+   assert(dest != NULL && *dest != NULL);
+
+   existing_length = strlen(*dest);
+   both = resize(*dest, existing_length + n + 1);
+   if (unlikely(both == NULL))
+      return false;
+
+   memcpy(both + existing_length, str, n);
+   both[existing_length + n] = '\0';
+
+   *dest = both;
+   return true;
+}
+
+
+bool
+ralloc_strcat(char **dest, const char *str)
+{
+   return cat(dest, str, strlen(str));
+}
+
+bool
+ralloc_strncat(char **dest, const char *str, size_t n)
+{
+   /* Clamp n to the string length */
+   size_t str_length = strlen(str);
+   if (str_length < n)
+      n = str_length;
+
+   return cat(dest, str, n);
+}
+
+char *
+ralloc_asprintf(const void *ctx, const char *fmt, ...)
+{
+   char *ptr;
+   va_list args;
+   va_start(args, fmt);
+   ptr = ralloc_vasprintf(ctx, fmt, args);
+   va_end(args);
+   return ptr;
+}
+
+/* Return the length of the string that would be generated by a printf-style
+ * format and argument list, not including the \0 byte.
+ */
+static size_t
+printf_length(const char *fmt, va_list untouched_args)
+{
+   int size;
+   char junk;
+
+   /* Make a copy of the va_list so the original caller can still use it */
+   va_list args;
+   va_copy(args, untouched_args);
+
+#ifdef _MSC_VER
+   /* We need to use _vcsprintf to calculate the size as vsnprintf returns -1
+    * if the number of characters to write is greater than count.
+    */
+   size = _vscprintf(fmt, args);
+   (void)junk;
+#else
+   size = vsnprintf(&junk, 1, fmt, args);
+#endif
+   assert(size >= 0);
+
+   va_end(args);
+
+   return size;
+}
+
+char *
+ralloc_vasprintf(const void *ctx, const char *fmt, va_list args)
+{
+   size_t size = printf_length(fmt, args) + 1;
+
+   char *ptr = ralloc_size(ctx, size);
+   if (ptr != NULL)
+      vsnprintf(ptr, size, fmt, args);
+
+   return ptr;
+}
+
+bool
+ralloc_asprintf_append(char **str, const char *fmt, ...)
+{
+   bool success;
+   va_list args;
+   va_start(args, fmt);
+   success = ralloc_vasprintf_append(str, fmt, args);
+   va_end(args);
+   return success;
+}
+
+bool
+ralloc_vasprintf_append(char **str, const char *fmt, va_list args)
+{
+   size_t existing_length, new_length;
+   char *ptr;
+
+   assert(str != NULL);
+
+   if (unlikely(*str == NULL)) {
+      // Assuming a NULL context is probably bad, but it's expected behavior.
+      *str = ralloc_vasprintf(NULL, fmt, args);
+      return true;
+   }
+
+   existing_length = strlen(*str);
+   new_length = printf_length(fmt, args);
+
+   ptr = resize(*str, existing_length + new_length + 1);
+   if (unlikely(ptr == NULL))
+      return false;
+
+   vsnprintf(ptr + existing_length, new_length + 1, fmt, args);
+   *str = ptr;
+   return true;
+}
diff --git a/src/glsl/ralloc.h b/src/glsl/ralloc.h
new file mode 100644 (file)
index 0000000..d533815
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * 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 ralloc.h
+ *
+ * ralloc: a recursive memory allocator
+ *
+ * The ralloc memory allocator creates a hierarchy of allocated
+ * objects. Every allocation is in reference to some parent, and
+ * every allocated object can in turn be used as the parent of a
+ * subsequent allocation. This allows for extremely convenient
+ * discarding of an entire tree/sub-tree of allocations by calling
+ * ralloc_free on any particular object to free it and all of its
+ * children.
+ *
+ * The conceptual working of ralloc was directly inspired by Andrew
+ * Tridgell's talloc, but ralloc is an independent implementation
+ * released under the MIT license and tuned for Mesa.
+ *
+ * The talloc implementation is available under the GNU Lesser
+ * General Public License (GNU LGPL), version 3 or later. It is
+ * more sophisticated than ralloc in that it includes reference
+ * counting and debugging features. See: http://talloc.samba.org/
+ */
+
+#ifndef RALLOC_H
+#define RALLOC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdbool.h>
+
+/**
+ * \def ralloc(ctx, type)
+ * Allocate a new object chained off of the given context.
+ *
+ * This is equivalent to:
+ * \code
+ * ((type *) ralloc_size(ctx, sizeof(type))
+ * \endcode
+ */
+#define ralloc(ctx, type)  ((type *) ralloc_size(ctx, sizeof(type)))
+
+/**
+ * \def rzalloc(ctx, type)
+ * Allocate a new object out of the given context and initialize it to zero.
+ *
+ * This is equivalent to:
+ * \code
+ * ((type *) rzalloc_size(ctx, sizeof(type))
+ * \endcode
+ */
+#define rzalloc(ctx, type) ((type *) rzalloc_size(ctx, sizeof(type)))
+
+/**
+ * Allocate a new ralloc context.
+ *
+ * While any ralloc'd pointer can be used as a context, sometimes it is useful
+ * to simply allocate a context with no associated memory.
+ *
+ * It is equivalent to:
+ * \code
+ * ((type *) ralloc_size(ctx, 0)
+ * \endcode
+ */
+void *ralloc_context(const void *ctx);
+
+/**
+ * Allocate memory chained off of the given context.
+ *
+ * This is the core allocation routine which is used by all others.  It
+ * simply allocates storage for \p size bytes and returns the pointer,
+ * similar to \c malloc.
+ */
+void *ralloc_size(const void *ctx, size_t size);
+
+/**
+ * Allocate zero-initialized memory chained off of the given context.
+ *
+ * This is similar to \c calloc with a size of 1.
+ */
+void *rzalloc_size(const void *ctx, size_t size);
+
+/**
+ * Resize a piece of ralloc-managed memory, preserving data.
+ *
+ * Similar to \c realloc.  Unlike C89, passing 0 for \p size does not free the
+ * memory.  Instead, it resizes it to a 0-byte ralloc context, just like
+ * calling ralloc_size(ctx, 0).  This is different from talloc.
+ *
+ * \param ctx  The context to use for new allocation.  If \p ptr != NULL,
+ *             it must be the same as ralloc_parent(\p ptr).
+ * \param ptr  Pointer to the memory to be resized.  May be NULL.
+ * \param size The amount of memory to allocate, in bytes.
+ */
+void *reralloc_size(const void *ctx, void *ptr, size_t size);
+
+/// \defgroup array Array Allocators @{
+
+/**
+ * \def ralloc_array(ctx, type, count)
+ * Allocate an array of objects chained off the given context.
+ *
+ * Similar to \c calloc, but does not initialize the memory to zero.
+ *
+ * More than a convenience function, this also checks for integer overflow when
+ * multiplying \c sizeof(type) and \p count.  This is necessary for security.
+ *
+ * This is equivalent to:
+ * \code
+ * ((type *) ralloc_array_size(ctx, sizeof(type), count)
+ * \endcode
+ */
+#define ralloc_array(ctx, type, count) \
+   ((type *) ralloc_array_size(ctx, sizeof(type), count))
+
+/**
+ * \def rzalloc_array(ctx, type, count)
+ * Allocate a zero-initialized array chained off the given context.
+ *
+ * Similar to \c calloc.
+ *
+ * More than a convenience function, this also checks for integer overflow when
+ * multiplying \c sizeof(type) and \p count.  This is necessary for security.
+ *
+ * This is equivalent to:
+ * \code
+ * ((type *) rzalloc_array_size(ctx, sizeof(type), count)
+ * \endcode
+ */
+#define rzalloc_array(ctx, type, count) \
+   ((type *) rzalloc_array_size(ctx, sizeof(type), count))
+
+/**
+ * \def reralloc(ctx, ptr, type, count)
+ * Resize a ralloc-managed array, preserving data.
+ *
+ * Similar to \c realloc.  Unlike C89, passing 0 for \p size does not free the
+ * memory.  Instead, it resizes it to a 0-byte ralloc context, just like
+ * calling ralloc_size(ctx, 0).  This is different from talloc.
+ *
+ * More than a convenience function, this also checks for integer overflow when
+ * multiplying \c sizeof(type) and \p count.  This is necessary for security.
+ *
+ * \param ctx   The context to use for new allocation.  If \p ptr != NULL,
+ *              it must be the same as ralloc_parent(\p ptr).
+ * \param ptr   Pointer to the array to be resized.  May be NULL.
+ * \param type  The element type.
+ * \param count The number of elements to allocate.
+ */
+#define reralloc(ctx, ptr, type, count) \
+   ((type *) reralloc_array_size(ctx, ptr, sizeof(type), count))
+
+/**
+ * Allocate memory for an array chained off the given context.
+ *
+ * Similar to \c calloc, but does not initialize the memory to zero.
+ *
+ * More than a convenience function, this also checks for integer overflow when
+ * multiplying \p size and \p count.  This is necessary for security.
+ */
+void *ralloc_array_size(const void *ctx, size_t size, unsigned count);
+
+/**
+ * Allocate a zero-initialized array chained off the given context.
+ *
+ * Similar to \c calloc.
+ *
+ * More than a convenience function, this also checks for integer overflow when
+ * multiplying \p size and \p count.  This is necessary for security.
+ */
+void *rzalloc_array_size(const void *ctx, size_t size, unsigned count);
+
+/**
+ * Resize a ralloc-managed array, preserving data.
+ *
+ * Similar to \c realloc.  Unlike C89, passing 0 for \p size does not free the
+ * memory.  Instead, it resizes it to a 0-byte ralloc context, just like
+ * calling ralloc_size(ctx, 0).  This is different from talloc.
+ *
+ * More than a convenience function, this also checks for integer overflow when
+ * multiplying \c sizeof(type) and \p count.  This is necessary for security.
+ *
+ * \param ctx   The context to use for new allocation.  If \p ptr != NULL,
+ *              it must be the same as ralloc_parent(\p ptr).
+ * \param ptr   Pointer to the array to be resized.  May be NULL.
+ * \param size  The size of an individual element.
+ * \param count The number of elements to allocate.
+ *
+ * \return True unless allocation failed.
+ */
+void *reralloc_array_size(const void *ctx, void *ptr, size_t size,
+                         unsigned count);
+/// @}
+
+/**
+ * Free a piece of ralloc-managed memory.
+ *
+ * This will also free the memory of any children allocated this context.
+ */
+void ralloc_free(void *ptr);
+
+/**
+ * "Steal" memory from one context, changing it to another.
+ *
+ * This changes \p ptr's context to \p new_ctx.  This is quite useful if
+ * memory is allocated out of a temporary context.
+ */
+void ralloc_steal(const void *new_ctx, void *ptr);
+
+/**
+ * Return the given pointer's ralloc context.
+ */
+void *ralloc_parent(const void *ptr);
+
+/**
+ * Return a context whose memory will be automatically freed at program exit.
+ *
+ * The first call to this function creates a context and registers a handler
+ * to free it using \c atexit.  This may cause trouble if used in a library
+ * loaded with \c dlopen.
+ */
+void *ralloc_autofree_context(void);
+
+/**
+ * Set a callback to occur just before an object is freed.
+ */
+void ralloc_set_destructor(const void *ptr, void(*destructor)(void *));
+
+/// \defgroup array String Functions @{
+/**
+ * Duplicate a string, allocating the memory from the given context.
+ */
+char *ralloc_strdup(const void *ctx, const char *str);
+
+/**
+ * Duplicate a string, allocating the memory from the given context.
+ *
+ * Like \c strndup, at most \p n characters are copied.  If \p str is longer
+ * than \p n characters, \p n are copied, and a termining \c '\0' byte is added.
+ */
+char *ralloc_strndup(const void *ctx, const char *str, size_t n);
+
+/**
+ * Concatenate two strings, allocating the necessary space.
+ *
+ * This appends \p str to \p *dest, similar to \c strcat, using ralloc_resize
+ * to expand \p *dest to the appropriate size.  \p dest will be updated to the
+ * new pointer unless allocation fails.
+ *
+ * The result will always be null-terminated.
+ *
+ * \return True unless allocation failed.
+ */
+bool ralloc_strcat(char **dest, const char *str);
+
+/**
+ * Concatenate two strings, allocating the necessary space.
+ *
+ * This appends at most \p n bytes of \p str to \p *dest, using ralloc_resize
+ * to expand \p *dest to the appropriate size.  \p dest will be updated to the
+ * new pointer unless allocation fails.
+ *
+ * The result will always be null-terminated; \p str does not need to be null
+ * terminated if it is longer than \p n.
+ *
+ * \return True unless allocation failed.
+ */
+bool ralloc_strncat(char **dest, const char *str, size_t n);
+
+/**
+ * Print to a string.
+ *
+ * This is analogous to \c sprintf, but allocates enough space (using \p ctx
+ * as the context) for the resulting string.
+ *
+ * \return The newly allocated string.
+ */
+char *ralloc_asprintf (const void *ctx, const char *fmt, ...);
+
+/**
+ * Print to a string, given a va_list.
+ *
+ * This is analogous to \c vsprintf, but allocates enough space (using \p ctx
+ * as the context) for the resulting string.
+ *
+ * \return The newly allocated string.
+ */
+char *ralloc_vasprintf(const void *ctx, const char *fmt, va_list args);
+
+/**
+ * Append formatted text to the supplied string.
+ *
+ * \sa ralloc_asprintf
+ * \sa ralloc_strcat
+ *
+ * \p str will be updated to the new pointer unless allocation fails.
+ *
+ * \return True unless allocation failed.
+ */
+bool ralloc_asprintf_append (char **str, const char *fmt, ...);
+
+/**
+ * Append formatted text to the supplied string, given a va_list.
+ *
+ * \sa ralloc_vasprintf
+ * \sa ralloc_strcat
+ *
+ * \p str will be updated to the new pointer unless allocation fails.
+ *
+ * \return True unless allocation failed.
+ */
+bool ralloc_vasprintf_append(char **str, const char *fmt, va_list args);
+/// @}
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif
index 6edbf62e488bc64731ba364240d1ef9eb7bfa785..a922a50d3b9dc1f03cafc2c2c3fd6510d75a7452 100644 (file)
  * 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);
+   this->str = ralloc_strndup (this, tmp, n);
    assert(this->str != NULL);
 }
 
index 795f3fccea78a4f0b7b416add8061a5fc0dbc3d6..c9dc676b3191a15b565927caa8a2867df20db703 100644 (file)
@@ -57,7 +57,7 @@ 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.
+    * Any allocation will be performed with 'ctx' as the ralloc owner.
     */
    static s_expression *read_expression(void *ctx, const char *&src);
 
index 75b1a103f0145b9c1af51ea842e1e9774a0cec83..a275ba5b9fe534f9df23c5b636911af1585204cd 100644 (file)
@@ -804,11 +804,16 @@ dri2CreateScreen(int screen, struct glx_display * priv)
       return NULL;
 
    memset(psc, 0, sizeof *psc);
-   if (!glx_screen_init(&psc->base, screen, priv))
-       return NULL;
+   psc->fd = -1;
+
+   if (!glx_screen_init(&psc->base, screen, priv)) {
+      Xfree(psc);
+      return NULL;
+   }
 
    if (!DRI2Connect(priv->dpy, RootWindow(priv->dpy, screen),
                    &driverName, &deviceName)) {
+      glx_screen_cleanup(&psc->base);
       XFree(psc);
       return NULL;
    }
@@ -918,12 +923,15 @@ dri2CreateScreen(int screen, struct glx_display * priv)
    return &psc->base;
 
 handle_error:
+   if (psc->fd >= 0)
+      close(psc->fd);
+   if (psc->driver)
+      dlclose(psc->driver);
    Xfree(driverName);
    Xfree(deviceName);
+   glx_screen_cleanup(&psc->base);
    XFree(psc);
 
-   /* FIXME: clean up here */
-
    return NULL;
 }
 
index 42b263c6377b090ff7fac055195fe93fecc6f868..ff027dc9e9c2df0fb8e99aaa2b3a86d22f115a74 100644 (file)
@@ -836,26 +836,24 @@ driCreateScreen(int screen, struct glx_display *priv)
       return NULL;
 
    memset(psc, 0, sizeof *psc);
-   if (!glx_screen_init(&psc->base, screen, priv))
-       return NULL;
-
-   if (!driGetDriverName(priv->dpy, screen, &driverName)) {
+   if (!glx_screen_init(&psc->base, screen, priv)) {
       Xfree(psc);
       return NULL;
    }
 
+   if (!driGetDriverName(priv->dpy, screen, &driverName)) {
+      goto cleanup;
+   }
+
    psc->driver = driOpenDriver(driverName);
    Xfree(driverName);
-   if (psc->driver == NULL) {
-      Xfree(psc);
-      return NULL;
-   }
+   if (psc->driver == NULL)
+      goto cleanup;
 
    extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
    if (extensions == NULL) {
       ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
-      Xfree(psc);
-      return NULL;
+      goto cleanup;
    }
 
    for (i = 0; extensions[i]; i++) {
@@ -865,19 +863,14 @@ driCreateScreen(int screen, struct glx_display *priv)
         psc->legacy = (__DRIlegacyExtension *) extensions[i];
    }
 
-   if (psc->core == NULL || psc->legacy == NULL) {
-      Xfree(psc);
-      return NULL;
-   }
+   if (psc->core == NULL || psc->legacy == NULL)
+      goto cleanup;
 
    pdp = (struct dri_display *) priv->driDisplay;
    psc->driScreen =
       CallCreateNewScreen(psc->base.dpy, screen, psc, pdp);
-   if (psc->driScreen == NULL) {
-      dlclose(psc->driver);
-      Xfree(psc);
-      return NULL;
-   }
+   if (psc->driScreen == NULL)
+      goto cleanup;
 
    extensions = psc->core->getExtensions(psc->driScreen);
    driBindExtensions(psc, extensions);
@@ -902,6 +895,14 @@ driCreateScreen(int screen, struct glx_display *priv)
    psp->getSwapInterval = driGetSwapInterval;
 
    return &psc->base;
+
+cleanup:
+   if (psc->driver)
+      dlclose(psc->driver);
+   glx_screen_cleanup(&psc->base);
+   Xfree(psc);
+
+   return NULL;
 }
 
 /* Called from __glXFreeDisplayPrivate.
index 237ce1761765b60d8b92baeafe1e31a6fdec1cd0..5c7f40cdffac3b919f666fbc74f9c2a1225f3b8a 100644 (file)
@@ -452,8 +452,10 @@ driCreateScreen(int screen, struct glx_display *priv)
       return NULL;
 
    memset(psc, 0, sizeof *psc);
-   if (!glx_screen_init(&psc->base, screen, priv))
-       return NULL;
+   if (!glx_screen_init(&psc->base, screen, priv)) {
+      Xfree(psc);
+      return NULL;
+   }
 
    psc->driver = driOpenSwrast();
    if (psc->driver == NULL)
@@ -504,6 +506,7 @@ driCreateScreen(int screen, struct glx_display *priv)
  handle_error:
    if (psc->driver)
       dlclose(psc->driver);
+   glx_screen_cleanup(&psc->base);
    Xfree(psc);
 
    ErrorMessageF("reverting to indirect rendering\n");
index 34892e8b1a2bcb34573dbfbc1651254a30c05066..5f91bc623a971309ff27b57846f2777f23dec628 100644 (file)
@@ -106,7 +106,7 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable,
    if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
       xGLXChangeDrawableAttributesReq *req;
 
-      GetReqExtra(GLXChangeDrawableAttributes, 8 + (8 * num_attribs), req);
+      GetReqExtra(GLXChangeDrawableAttributes, 8 * num_attribs, req);
       output = (CARD32 *) (req + 1);
 
       req->reqType = opcode;
@@ -117,7 +117,7 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable,
    else {
       xGLXVendorPrivateWithReplyReq *vpreq;
 
-      GetReqExtra(GLXVendorPrivateWithReply, 4 + (8 * num_attribs), vpreq);
+      GetReqExtra(GLXVendorPrivateWithReply, 8 + (8 * num_attribs), vpreq);
       output = (CARD32 *) (vpreq + 1);
 
       vpreq->reqType = opcode;
@@ -125,7 +125,8 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable,
       vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX;
 
       output[0] = (CARD32) drawable;
-      output++;
+      output[1] = num_attribs;
+      output += 2;
    }
 
    (void) memcpy(output, attribs, sizeof(CARD32) * 2 * num_attribs);
@@ -297,7 +298,7 @@ GetDrawableAttribute(Display * dpy, GLXDrawable drawable,
    if (use_glx_1_3) {
       xGLXGetDrawableAttributesReq *req;
 
-      GetReqExtra(GLXGetDrawableAttributes, 4, req);
+      GetReq(GLXGetDrawableAttributes, req);
       req->reqType = opcode;
       req->glxCode = X_GLXGetDrawableAttributes;
       req->drawable = drawable;
@@ -435,7 +436,7 @@ DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode)
 
    LockDisplay(dpy);
 
-   GetReqExtra(GLXDestroyPbuffer, 4, req);
+   GetReq(GLXDestroyPbuffer, req);
    req->reqType = opcode;
    req->glxCode = glxCode;
    req->pbuffer = (GLXPbuffer) drawable;
index 36a0808c048a05c2ae07435cd359bd0881460709..fdcef8075a89a92ebc355fd3b584e16e0f1da3a1 100644 (file)
@@ -585,6 +585,8 @@ struct glx_display
 extern int
 glx_screen_init(struct glx_screen *psc,
                int screen, struct glx_display * priv);
+extern void
+glx_screen_cleanup(struct glx_screen *psc);
 
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
 extern __GLXDRIdrawable *
index d12ff9684e2579b8d29473d3ecb3645e28f70630..80eaf72b7d504b7abb1181d8c23e57ee0ac0a4c6 100644 (file)
@@ -215,12 +215,16 @@ CreateContext(Display * dpy, int generic_id,
               Bool allowDirect,
              unsigned code, int renderType, int screen)
 {
-   struct glx_context *gc = NULL;
-   struct glx_screen *const psc = GetGLXScreenConfigs(dpy, screen);
+   struct glx_context *gc;
+   struct glx_screen *psc;
    struct glx_context *shareList = (struct glx_context *) shareList_user;
    if (dpy == NULL)
       return NULL;
 
+   psc = GetGLXScreenConfigs(dpy, screen);
+   if (psc == NULL)
+      return NULL;
+
    if (generic_id == None)
       return NULL;
 
index c5e9d0510b68ff61aaafdbe5af4fb912f7df0932..25d266e18e137bcf6bd4150296dd10a6c62d92fb 100644 (file)
@@ -194,17 +194,7 @@ FreeScreenConfigs(struct glx_display * priv)
    screens = ScreenCount(priv->dpy);
    for (i = 0; i < screens; i++) {
       psc = priv->screens[i];
-      if (psc->configs) {
-        glx_config_destroy_list(psc->configs);
-         if (psc->effectiveGLXexts)
-            Xfree(psc->effectiveGLXexts);
-         psc->configs = NULL;   /* NOTE: just for paranoia */
-      }
-      if (psc->visuals) {
-        glx_config_destroy_list(psc->visuals);
-        psc->visuals = NULL;   /* NOTE: just for paranoia */
-      }
-      Xfree((char *) psc->serverGLXexts);
+      glx_screen_cleanup(psc);
 
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
       if (psc->driScreen) {
@@ -688,7 +678,7 @@ static GLboolean
    }
    else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
       GetReqExtra(GLXVendorPrivateWithReply,
-                  sz_xGLXGetFBConfigsSGIXReq +
+                  sz_xGLXGetFBConfigsSGIXReq -
                   sz_xGLXVendorPrivateWithReplyReq, vpreq);
       sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
       sgi_req->reqType = priv->majorOpcode;
@@ -728,6 +718,22 @@ glx_screen_init(struct glx_screen *psc,
    return GL_TRUE;
 }
 
+_X_HIDDEN void
+glx_screen_cleanup(struct glx_screen *psc)
+{
+   if (psc->configs) {
+      glx_config_destroy_list(psc->configs);
+      if (psc->effectiveGLXexts)
+          Xfree(psc->effectiveGLXexts);
+      psc->configs = NULL;   /* NOTE: just for paranoia */
+   }
+   if (psc->visuals) {
+      glx_config_destroy_list(psc->visuals);
+      psc->visuals = NULL;   /* NOTE: just for paranoia */
+   }
+   Xfree((char *) psc->serverGLXexts);
+}
+
 /*
 ** Allocate the memory for the per screen configs for each screen.
 ** If that works then fetch the per screen configs data.
index 7c9ca37247b42be3b3ad105338e989599c72cb99..b21f1d14c6f5cfad08878be5788e648ff1a8a93b 100644 (file)
@@ -1,3 +1,4 @@
+glapi_mapi_tmp.h
 glapi-stamp
 glapi
 main
index 4fa68e5c39d04e5335e781e1d6527b6271c541d9..aef694866c2144ccafe1753a30ae779acdcde749 100644 (file)
@@ -124,10 +124,15 @@ install: default install-headers install-pc
        $(MINSTALL) $(TOP)/$(LIB_DIR)/$(esapi_LIB_GLOB) \
                $(DESTDIR)$(INSTALL_LIB_DIR)
 
+# workaround a bug in makedepend
+makedepend_CPPFLAGS := \
+       $(filter-out -DMAPI_ABI_HEADER=%, $(esapi_CPPFLAGS))
+$(esapi_OBJECTS): glapi_mapi_tmp.h
+
 depend: $(esapi_SOURCES)
        @echo "running $(MKDEP)"
        @touch depend
-       @$(MKDEP) $(MKDEP_OPTIONS) -f- $(DEFINES) $(esapi_CPPFLAGS) \
+       @$(MKDEP) $(MKDEP_OPTIONS) -f- $(DEFINES) $(makedepend_CPPFLAGS) \
                $(esapi_SOURCES) 2>/dev/null | \
                sed -e 's,^$(GLAPI)/,,' -e 's,^$(MAPI)/,,' > depend
 
index 7c9ca37247b42be3b3ad105338e989599c72cb99..b21f1d14c6f5cfad08878be5788e648ff1a8a93b 100644 (file)
@@ -1,3 +1,4 @@
+glapi_mapi_tmp.h
 glapi-stamp
 glapi
 main
index 203a8abd018323c101575530c7dffd29f0d97827..bb4ed6585d9df62aabfb8ab4803934ae27373847 100644 (file)
@@ -13,11 +13,12 @@ include $(MAPI)/sources.mak
 glapi_CPPFLAGS := \
        -I$(TOP)/include \
        -I$(TOP)/src/mapi \
-       -I$(TOP)/src/mesa \
-       -DMAPI_ABI_HEADER=\"glapi/glapi_mapi_tmp.h\"
+       -I$(TOP)/src/mesa
 
 ifeq ($(SHARED_GLAPI),1)
-glapi_CPPFLAGS += -DMAPI_MODE_BRIDGE
+glapi_CPPFLAGS += \
+       -DMAPI_MODE_BRIDGE \
+       -DMAPI_ABI_HEADER=\"glapi/glapi_mapi_tmp.h\"
 glapi_SOURCES := $(addprefix $(MAPI)/, $(MAPI_BRIDGE_SOURCES))
 
 glapi_GLAPI_OBJECTS :=
@@ -58,10 +59,19 @@ clean:
        -rm -f lib$(TARGET).a
        -rm -f depend depend.bak
 
+ifeq ($(SHARED_GLAPI),1)
+# workaround a bug in makedepend
+makedepend_CPPFLAGS := \
+       $(filter-out -DMAPI_ABI_HEADER=%, $(glapi_CPPFLAGS))
+$(glapi_OBJECTS): glapi_mapi_tmp.h
+else
+makedepend_CPPFLAGS := $(glapi_CPPFLAGS)
+endif
+
 depend: $(glapi_SOURCES)
        @ echo "running $(MKDEP)"
        @ touch depend
-       @$(MKDEP) $(MKDEP_OPTIONS) -f- $(DEFINES) $(glapi_CPPFLAGS) \
+       @$(MKDEP) $(MKDEP_OPTIONS) -f- $(DEFINES) $(makedepend_CPPFLAGS) \
                $(glapi_SOURCES) 2>/dev/null | sed -e 's,^$(MAPI)/,,' > depend
 
 -include depend
index 4057991ec8da935d1b0b7f3a5810c561a36978fa..276b2160246cbbf561b4706965c3871ca462f1be 100644 (file)
@@ -17,6 +17,11 @@ if env['platform'] != 'winddk':
             '_GDI32_', # prevent gl* being declared __declspec(dllimport) in MS headers
             'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers
         ])
+        if env['gles']:
+            env.Append(CPPDEFINES = ['_GLAPI_DLL_EXPORTS'])
+        else:
+            # prevent _glapi_* from being declared __declspec(dllimport)
+            env.Append(CPPDEFINES = ['_GLAPI_NO_EXPORTS'])
 
     env.Append(CPPPATH = [
         '#/src/mapi',
index 2fa140dc308c3de7b6517226db6c9be4bfad806e..11cd9af40618dbd075d95fd70da64679a04c8ec2 100644 (file)
@@ -166,7 +166,8 @@ class PrintGenericStubs(gl_XML.gl_print_base):
                print ''
                print '\t.p2align\t4,,15'
                print '_x86_64_get_dispatch:'
-               print '\tmovq\t_gl_DispatchTSD(%rip), %rdi'
+               print '\tmovq\t_gl_DispatchTSD@GOTPCREL(%rip), %rax'
+               print '\tmovl\t(%rax), %edi'
                print '\tjmp\tpthread_getspecific@PLT'
                print ''
                print '#elif defined(THREADS)'
index 21996a394214d758efb0ac1b9ec7e66ee2f4093e..4ef4acb564e35cad76b1ef86400bc73c1e3f0409 100644 (file)
@@ -73,7 +73,7 @@ class PrintGenericStubs(gl_XML.gl_print_base):
                print '#define GL_OFFSET(x) CODEPTR(REGOFF(4 * x, EAX))'
                print ''
                print '#if defined(GNU_ASSEMBLER) && !defined(__DJGPP__) && !defined(__MINGW32__) && !defined(__APPLE__)'
-               print '#define GLOBL_FN(x) GLOBL x ; .type x, function'
+               print '#define GLOBL_FN(x) GLOBL x ; .type x, @function'
                print '#else'
                print '#define GLOBL_FN(x) GLOBL x'
                print '#endif'
index 8cca50487c4bc529624e5ab50165209980f068d1..e909cf892ab1ced271ee71bda6c9491df3bd25f4 100644 (file)
 #define _GLAPI_H
 
 
-/* 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 */
index 469fac31ae6be26a19da3c7ab28f4d9bdeab6c16..c42646f0165d116275d440f75f3776d0fde153fc 100644 (file)
@@ -73,7 +73,8 @@ _x86_64_get_dispatch:
 
        .p2align        4,,15
 _x86_64_get_dispatch:
-       movq    _gl_DispatchTSD(%rip), %rdi
+       movq    _gl_DispatchTSD@GOTPCREL(%rip), %rax
+       movl    (%rax), %edi
        jmp     pthread_getspecific@PLT
 
 #elif defined(THREADS)
index fa448c1704f800b361c15ab2c6dd6d94aa732e4c..8d85f61ce009e42657ff04f7832dec48f0456f31 100644 (file)
@@ -46,7 +46,7 @@
 #define GL_OFFSET(x) CODEPTR(REGOFF(4 * x, EAX))
 
 #if defined(GNU_ASSEMBLER) && !defined(__DJGPP__) && !defined(__MINGW32__) && !defined(__APPLE__)
-#define GLOBL_FN(x) GLOBL x ; .type x, function
+#define GLOBL_FN(x) GLOBL x ; .type x, @function
 #else
 #define GLOBL_FN(x) GLOBL x
 #endif
index f378ccfda95f5c15d19de1e7ba72c07f58a9db41..3d9168a724399a4600261da6ab8d6703bd7585c6 100644 (file)
@@ -37,7 +37,7 @@
 #ifdef MAPI_MODE_BRIDGE
 #define ENTRY_CURRENT_TABLE_GET "_glapi_get_dispatch"
 #else
-#define ENTRY_CURRENT_TABLE_GET "u_current_get_internal"
+#define ENTRY_CURRENT_TABLE_GET U_STRINGIFY(u_current_get_internal)
 #endif
 
 #if defined(USE_X86_ASM) && defined(__GNUC__)
diff --git a/src/mapi/shared-glapi/.gitignore b/src/mapi/shared-glapi/.gitignore
new file mode 100644 (file)
index 0000000..c3e0647
--- /dev/null
@@ -0,0 +1,2 @@
+glapi_mapi_tmp.h
+
index ee937bd681b9c42c4679b99d54333ba7a9b77bfe..c928f822c813a1ec8e0b10c275d5999d6e7e44b5 100644 (file)
@@ -51,10 +51,15 @@ install:
        $(MINSTALL) $(TOP)/$(LIB_DIR)/$(GLAPI_LIB_GLOB) \
                $(DESTDIR)$(INSTALL_LIB_DIR)
 
+# workaround a bug in makedepend
+makedepend_CPPFLAGS := \
+       $(filter-out -DMAPI_ABI_HEADER=%, $(glapi_CPPFLAGS))
+$(glapi_OBJECTS): glapi_mapi_tmp.h
+
 depend: $(glapi_SOURCES)
        @echo "running $(MKDEP)"
        @touch depend
-       @$(MKDEP) $(MKDEP_OPTIONS) -f- $(DEFINES) $(glapi_CPPFLAGS) \
+       @$(MKDEP) $(MKDEP_OPTIONS) -f- $(DEFINES) $(makedepend_CPPFLAGS) \
                $(glapi_SOURCES) 2>/dev/null | sed -e 's,^$(MAPI)/,,' \
                > depend
 
diff --git a/src/mapi/shared-glapi/SConscript b/src/mapi/shared-glapi/SConscript
new file mode 100644 (file)
index 0000000..b7c43a7
--- /dev/null
@@ -0,0 +1,116 @@
+#######################################################################
+# SConscript for shared-glapi/es1api/es2api
+
+from sys import executable as python_cmd
+
+Import('*')
+
+def mapi_objects(env, printer, mode):
+    """Return mapi objects built for the given printer and mode."""
+    mapi_sources = {
+        'glapi': ['entry.c', 'mapi_glapi.c', 'stub.c', 'table.c',
+                  'u_current.c', 'u_execmem.c', 'u_thread.c'],
+        'bridge': ['entry.c'],
+    }
+    mapi_defines = {
+        'glapi': ['MAPI_MODE_GLAPI'],
+        'bridge': ['MAPI_MODE_BRIDGE'],
+    }
+
+    header_name = '%s-tmp.h' % (printer)
+
+    # generate ABI header
+    header = env.CodeGenerate(
+        target = header_name,
+        script = '../mapi/mapi_abi.py',
+        source = '../glapi/gen/gl_and_es_API.xml',
+        command = python_cmd + ' $SCRIPT ' + \
+                '--printer %s --mode lib $SOURCE > $TARGET' % (printer),
+    )
+
+    cpppath = [
+        header[0].dir,
+        '#/include',
+        '#/src/mapi',
+    ]
+    
+    cppdefines = mapi_defines[mode] + [
+        'MAPI_ABI_HEADER=\\"%s\\"' % (header_name),
+    ]
+
+    if env['platform'] == 'windows':
+        if mode == 'glapi':
+            cppdefines += [
+                '_GLAPI_DLL_EXPORTS', # declare _glapi_* as __declspec(dllexport) in glapi.h
+            ]
+        else:
+            cppdefines += [
+                '_GDI32_', # prevent gl* being declared __declspec(dllimport) in MS headers
+                'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers
+            ]
+
+    objects = []
+    for s in mapi_sources[mode]:
+        o = env.SharedObject(
+            target = '%s-%s' % (printer, s[:-2]),
+            source = '../mapi/' + s,
+            CPPPATH = cpppath,
+            CPPDEFINES = cppdefines,
+        )
+        objects.append(o[0])
+
+    env.Depends(objects, header)
+
+    return objects
+
+if env['platform'] != 'winddk':
+    env = env.Clone()
+
+    env['SHLIBPREFIX'] = 'lib'
+    env['LIBPREFIX'] = 'lib'
+
+    shared_glapi_objects = mapi_objects(env, 'shared-glapi', 'glapi')
+    shared_glapi = env.SharedLibrary(
+        target = 'glapi',
+        source = shared_glapi_objects,
+    )
+
+    # manually add LIBPREFIX on windows
+    if env['platform'] == 'windows':
+        libs = ['libglapi']
+    else:
+        libs = ['glapi']
+
+    es1api_objects = mapi_objects(env, 'es1api', 'bridge')
+    es1api = env.SharedLibrary(
+        target = 'GLESv1_CM',
+        source = es1api_objects,
+        LIBPATH = ['.'],
+        LIBS = libs,
+    )
+
+    es2api_objects = mapi_objects(env, 'es2api', 'bridge')
+    es2api = env.SharedLibrary(
+        target = 'GLESv2',
+        source = es2api_objects,
+        LIBPATH = ['.'],
+        LIBS = libs,
+    )
+
+    env.InstallSharedLibrary(shared_glapi, version=(0, 0, 0))
+    env.InstallSharedLibrary(es1api, version=(1, 0, 0))
+    env.InstallSharedLibrary(es2api, version=(2, 0, 0))
+
+    if env['platform'] == 'windows':
+        shared_glapi = env.FindIxes(shared_glapi, 'LIBPREFIX', 'LIBSUFFIX')
+    else:
+        shared_glapi = env.FindIxes(shared_glapi, 'SHLIBPREFIX', 'SHLIBSUFFIX')
+
+    # build glapi bridge as a convenience libarary for libgl-xlib/libgl-gdi
+    bridge_glapi_objects = mapi_objects(env, 'glapi', 'bridge')
+    bridge_glapi = env.ConvenienceLibrary(
+        target = 'glapi_bridge',
+        source = bridge_glapi_objects,
+    )
+
+    Export(['shared_glapi', 'bridge_glapi'])
index e239e20987e7d80ba720f623fd1c39cab1ef15f6..68cf26e83c370d22539e1c06ee443085408ff592 100644 (file)
@@ -81,11 +81,14 @@ install: default install-headers install-pc
        $(MINSTALL) $(TOP)/$(LIB_DIR)/$(VG_LIB_GLOB) \
                $(DESTDIR)$(INSTALL_LIB_DIR)
 
+# due to a bug in makedepend, cannot pass VGAPI_CPPFLAGS to it
+$(VGAPI_OBJECTS): vgapi_tmp.h
+
 depend: $(VGAPI_SOURCES)
        @echo "running $(MKDEP)"
        @touch depend
        @$(MKDEP) $(MKDEP_OPTIONS) -f- $(DEFINES) $(INCLUDE_DIRS) \
-               $(VGAPI_CPPFLAGS) $(VGAPI_SOURCES) 2>/dev/null | \
+               $(VGAPI_SOURCES) 2>/dev/null | \
                sed -e 's,^$(MAPI)/,,' > depend
 
 -include depend
index 25e7cce425cdea4195060b26d49896bd609f2ea5..48f79a5d550937003a29ad382db1da8622d25a62 100644 (file)
@@ -7,7 +7,7 @@ MESA_LIBS := libmesa.a libmesagallium.a
 DEPENDS := depend
 
 MESA_OBJ_DIR := .
-
+DRICORE_OBJ_DIR := objs-dricore
 
 include sources.mak
 
@@ -15,27 +15,35 @@ include sources.mak
 MESA_OBJECTS := $(addprefix $(MESA_OBJ_DIR)/, $(MESA_OBJECTS))
 MESA_GALLIUM_OBJECTS := $(addprefix $(MESA_OBJ_DIR)/, $(MESA_GALLIUM_OBJECTS))
 
+DRICORE_OBJECTS := $(addprefix $(DRICORE_OBJ_DIR)/, $(MESA_OBJECTS))
+
 # define preprocessor flags
 MESA_CPPFLAGS := $(API_DEFINES) $(DEFINES)
 
 # append include dirs
-MESA_CPPFLAGS += $(INCLUDE_DIRS) $(TALLOC_CFLAGS)
+MESA_CPPFLAGS += $(INCLUDE_DIRS)
+
+DRICORE_CPPFLAGS = $(MESA_CPPFLAGS)
 
 # tidy compiler flags
 CFLAGS := $(filter-out $(DEFINES), $(CFLAGS))
 CXXFLAGS := $(filter-out $(DEFINES), $(CXXFLAGS))
 
 # LLVM is needed for the state tracker
-MESA_CFLAGS := $(LLVM_CFLAGS)
+MESA_CFLAGS := $(LLVM_CFLAGS) $(CFLAGS)
+DRICORE_CFLAGS := $(LLVM_CFLAGS) $(DRI_CFLAGS)
+
+MESA_CXXFLAGS := $(LLVM_CFLAGS) $(CXXFLAGS)
+DRICORE_CXXFLAGS := $(LLVM_CFLAGS) $(DRI_CXXFLAGS)
 
 define mesa-cc-c
        @mkdir -p $(dir $@)
-       $(CC) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_CFLAGS) $(CFLAGS)
+       $(CC) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_CFLAGS)
 endef
 
 define mesa-cxx-c
        @mkdir -p $(dir $@)
-       $(CXX) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_CFLAGS) $(CXXFLAGS)
+       $(CXX) -c -o $@ $< $($(1)_CPPFLAGS) $($(1)_CFLAGS) $($(1)_CXXFLAGS)
 endef
 
 $(MESA_OBJ_DIR)/%.o: %.c
@@ -47,9 +55,18 @@ $(MESA_OBJ_DIR)/%.o: %.cpp
 $(MESA_OBJ_DIR)/%.o: %.S
        $(call mesa-cc-c,MESA)
 
+$(DRICORE_OBJ_DIR)/%.o: %.c
+       $(call mesa-cc-c,DRICORE)
+
+$(DRICORE_OBJ_DIR)/%.o: %.cpp
+       $(call mesa-cxx-c,DRICORE)
+
+$(DRICORE_OBJ_DIR)/%.o: %.S
+       $(call mesa-cc-c,DRICORE)
+
 # Default: build dependencies, then asm_subdirs, GLSL built-in lib,
 # then convenience libs (.a) and finally the device drivers:
-default: $(DEPENDS) asm_subdirs $(MESA_LIBS) driver_subdirs
+default: $(DEPENDS) asm_subdirs $(MESA_LIBS) $(DRICORE_LIBS) driver_subdirs
 
 main/api_exec_es1.c: main/APIspec.xml main/es_generator.py main/APIspecutil.py main/APIspec.py
        $(PYTHON2) $(PYTHON_FLAGS) main/es_generator.py -S main/APIspec.xml -V GLES1.1 > $@
@@ -64,13 +81,20 @@ main/api_exec_es2.c: main/APIspec.xml main/es_generator.py main/APIspecutil.py m
 libmesa.a: $(MESA_OBJECTS) $(GLSL_LIBS)
        @ $(MKLIB) -o mesa -static $(MESA_OBJECTS) $(GLSL_LIBS)
 
+# Shared dricore library for classic DRI drivers
+$(TOP)/$(LIB_DIR)/libdricore.so: $(DRICORE_OBJECTS) $(DRICORE_GLSL_LIBS)
+       @$(MKLIB) -o $@ -linker '$(CXX)' -ldflags '$(LDFLAGS)' \
+               -cplusplus -noprefix \
+               -install $(TOP)/$(LIB_DIR) -id $(DRI_DRIVER_INSTALL_DIR)/$@.dylib \
+               $(DRICORE_LIB_DEPS) $(DRICORE_OBJECTS)
+
 # Make archive of subset of core mesa object files for gallium
 libmesagallium.a: $(MESA_GALLIUM_OBJECTS) $(GLSL_LIBS)
        @ $(MKLIB) -o mesagallium -static $(MESA_GALLIUM_OBJECTS) $(GLSL_LIBS)
 
 ######################################################################
 # Device drivers
-driver_subdirs: $(MESA_LIBS)
+driver_subdirs: $(MESA_LIBS) $(DRICORE_LIBS)
        @ (cd drivers && $(MAKE))
 
 
@@ -102,9 +126,12 @@ depend: $(ALL_SOURCES)
 new_install:
        (cd drivers && $(MAKE) install)
 
+ifneq (,$(DRICORE_LIBS))
+DRICORE_INSTALL_TARGET = install-dricore
+endif
 
 # XXX replace this with new_install above someday
-install: default
+install: default $(DRICORE_INSTALL_TARGET)
        @for driver in $(DRIVER_DIRS) ; do \
          case "$$driver" in \
            osmesa) if [ "$(DRIVER_DIRS)" = osmesa ]; then \
@@ -166,13 +193,22 @@ install-osmesa: default osmesa.pc
 install-dri: default
        cd drivers/dri && $(MAKE) install
 
+# We don't need MINSTALL here because we're not installing symbolic links
+install-dricore: default
+       $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+       $(INSTALL) -m 755 $(DRICORE_LIBS) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
 
 
 # Emacs tags
 tags:
        etags `find . -name \*.[ch]` $(TOP)/include/GL/*.h
 
-clean:
+clean-dricore:
+       -rm -f libdricore.so
+       -rm -f $(DRICORE_LIBS)
+       -rm -rf $(DRICORE_OBJ_DIR)
+
+clean: clean-dricore
        -rm -f */*.o
        -rm -f */*/*.o
        -rm -f depend depend.bak libmesa.a libmesagallium.a
index cc4ad09fa339050288c80e891e211d521fd68813..ea04fb1a0ee0cf0ce6d4350c5317ebea8c47dac2 100644 (file)
@@ -12,12 +12,18 @@ env.Append(CPPPATH = [
     '#/src/mesa',
 ])
 
+env.Append(CPPDEFINES = [
+    'FEATURE_GL=1',
+])
+
 if env['platform'] == 'windows':
     env.Append(CPPDEFINES = [
         '_GDI32_', # prevent gl* being declared __declspec(dllimport) in MS headers
         'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers
     ])
-    env.Prepend(CPPPATH = ['#src/talloc'])
+    if not env['gles']:
+        # prevent _glapi_* from being declared __declspec(dllimport)
+        env.Append(CPPDEFINES = ['_GLAPI_NO_EXPORTS'])
 else:
     env.Append(CPPDEFINES = [
         'IN_DRI_DRIVER', # enable the remap table (for DRI drivers)
@@ -240,6 +246,61 @@ mesa_sources = (
     statetracker_sources
 )
 
+if env['gles']:
+    from sys import executable as python_cmd
+
+    env.Append(CPPDEFINES = ['FEATURE_ES1=1', 'FEATURE_ES2=1'])
+
+    # generate GLES sources
+    gles_sources = []
+    gles_sources += env.CodeGenerate(
+        target = 'main/api_exec_es1.c',
+        script = 'main/es_generator.py',
+        source = 'main/APIspec.xml',
+        command = python_cmd + ' $SCRIPT -S $SOURCE -V GLES1.1 > $TARGET'
+    )
+    gles_sources += env.CodeGenerate(
+        target = 'main/api_exec_es2.c',
+        script = 'main/es_generator.py',
+        source = 'main/APIspec.xml',
+        command = python_cmd + ' $SCRIPT -S $SOURCE -V GLES2.0 > $TARGET'
+    )
+
+    # generate GLES headers
+    GLAPI = '#src/mapi/glapi/'
+    gles_headers = []
+    gles_headers += env.CodeGenerate(
+        target = 'es1api/main/glapidispatch.h',
+        script = GLAPI + 'gen/gl_table.py',
+        source = GLAPI + 'gen-es/es1_API.xml',
+        command = python_cmd + ' $SCRIPT -c -m remap_table -f $SOURCE > $TARGET',
+    )
+    gles_headers += env.CodeGenerate(
+        target = 'es1api/main/remap_helper.h',
+        script = GLAPI + 'gen/remap_helper.py',
+        source = GLAPI + 'gen-es/es1_API.xml',
+        command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET',
+    )
+    gles_headers += env.CodeGenerate(
+        target = 'es2api/main/glapidispatch.h',
+        script = GLAPI + 'gen/gl_table.py',
+        source = GLAPI + 'gen-es/es2_API.xml',
+        command = python_cmd + ' $SCRIPT -c -m remap_table -f $SOURCE > $TARGET',
+    )
+    gles_headers += env.CodeGenerate(
+        target = 'es2api/main/remap_helper.h',
+        script = GLAPI + 'gen/remap_helper.py',
+        source = GLAPI + 'gen-es/es2_API.xml',
+        command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET',
+    )
+
+    env.Depends(gles_sources, gles_headers)
+
+    # gles_sources #include gles_headers with full path
+    env.Append(CPPPATH = [gles_headers[0].dir.up().up()])
+
+    mesa_sources += gles_sources
+
 #
 # Assembly sources
 #
index ee3415b3d1a6bcf87df51ed949416bf8ae62300b..57c4614f32d008ca441d070583fc511d48c849d4 100644 (file)
@@ -50,7 +50,6 @@ extern "C" {
 #include "swrast/s_depth.h"
 #include "swrast/s_lines.h"
 #include "swrast/s_triangle.h"
-#include "swrast/s_trispan.h"
 #include "tnl/tnl.h"
 #include "tnl/t_context.h"
 #include "tnl/t_pipeline.h"
@@ -319,7 +318,8 @@ BGLView::BGLView(BRect rect, char *name,
         functions.Viewport      = md->Viewport;
 
        // create core context
-       struct gl_context *ctx = _mesa_create_context(visual, NULL, &functions, md);
+       struct gl_context *ctx = _mesa_create_context(API_OPENGL, visual,
+                                                      NULL, &functions, md);
        if (! ctx) {
          _mesa_destroy_visual(visual);
          delete md;
index 3c6ecb83f0aa18cbc1f7dd78da0160e8a2a19784..5389a500111aa40939ad2fa5445ca6a3855970f7 100644 (file)
@@ -184,6 +184,7 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
    driver->RenderTexture = _mesa_render_texture;
    driver->FinishRenderTexture = _mesa_finish_render_texture;
    driver->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer;
+   driver->ValidateFramebuffer = _mesa_validate_framebuffer;
 
    driver->BlitFramebuffer = _swrast_BlitFramebuffer;
 
index 4ecddbc04834d0fe8a08f521a3c67039fdc6dfe1..d1a119379ed5060f9e8846b29d4020823c24ce35 100644 (file)
@@ -1,7 +1,5 @@
 # -*-makefile-*-
 
-MESA_MODULES = $(TOP)/src/mesa/libmesa.a
-
 COMMON_GALLIUM_SOURCES = \
         ../common/utils.c \
         ../common/vblank.c \
@@ -11,8 +9,7 @@ COMMON_GALLIUM_SOURCES = \
 COMMON_SOURCES = $(COMMON_GALLIUM_SOURCES) \
         ../../common/driverfuncs.c \
         ../common/texmem.c \
-        ../common/drirenderbuffer.c \
-       ../common/dri_metaops.c
+        ../common/drirenderbuffer.c
 
 INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES)
 
@@ -39,13 +36,13 @@ CXXFLAGS += $(API_DEFINES)
 ##### RULES #####
 
 .c.o:
-       $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
+       $(CC) -c $(INCLUDES) $(DRI_CFLAGS) $(DRIVER_DEFINES) $< -o $@
 
 .cpp.o:
-       $(CC) -c $(INCLUDES) $(CXXFLAGS) $(DRIVER_DEFINES) $< -o $@
+       $(CC) -c $(INCLUDES) $(DRI_CXXFLAGS) $(DRIVER_DEFINES) $< -o $@
 
 .S.o:
-       $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
+       $(CC) -c $(INCLUDES) $(DRI_CFLAGS) $(DRIVER_DEFINES) $< -o $@
 
 
 ##### TARGETS #####
@@ -57,10 +54,10 @@ default: subdirs lib
 lib: symlinks subdirs depend
        @$(MAKE) $(LIBNAME) $(TOP)/$(LIB_DIR)/$(LIBNAME)
 
-$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) Makefile \
+$(LIBNAME): $(OBJECTS) $(EXTRA_MODULES) $(MESA_MODULES) Makefile \
                $(TOP)/src/mesa/drivers/dri/Makefile.template $(TOP)/src/mesa/drivers/dri/common/dri_test.o
        $(MKLIB) -o $@.tmp -noprefix -linker '$(CXX)' -ldflags '$(LDFLAGS)' \
-               $(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) $(DRI_LIB_DEPS)
+               $(OBJECTS) $(EXTRA_MODULES) $(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_metaops.c b/src/mesa/drivers/dri/common/dri_metaops.c
deleted file mode 100644 (file)
index e0bc3b8..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
- * Copyright 2009 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 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 "main/arbprogram.h"
-#include "main/arrayobj.h"
-#include "main/bufferobj.h"
-#include "main/context.h"
-#include "main/enable.h"
-#include "main/matrix.h"
-#include "main/texstate.h"
-#include "main/varray.h"
-#include "main/viewport.h"
-#include "program/program.h"
-#include "dri_metaops.h"
-
-void
-meta_set_passthrough_transform(struct dri_metaops *meta)
-{
-   struct gl_context *ctx = meta->ctx;
-
-   meta->saved_vp_x = ctx->Viewport.X;
-   meta->saved_vp_y = ctx->Viewport.Y;
-   meta->saved_vp_width = ctx->Viewport.Width;
-   meta->saved_vp_height = ctx->Viewport.Height;
-   meta->saved_matrix_mode = ctx->Transform.MatrixMode;
-
-   meta->internal_viewport_call = GL_TRUE;
-   _mesa_Viewport(0, 0, ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
-   meta->internal_viewport_call = GL_FALSE;
-
-   _mesa_MatrixMode(GL_PROJECTION);
-   _mesa_PushMatrix();
-   _mesa_LoadIdentity();
-   _mesa_Ortho(0, ctx->DrawBuffer->Width, 0, ctx->DrawBuffer->Height, 1, -1);
-
-   _mesa_MatrixMode(GL_MODELVIEW);
-   _mesa_PushMatrix();
-   _mesa_LoadIdentity();
-}
-
-void
-meta_restore_transform(struct dri_metaops *meta)
-{
-   _mesa_MatrixMode(GL_PROJECTION);
-   _mesa_PopMatrix();
-   _mesa_MatrixMode(GL_MODELVIEW);
-   _mesa_PopMatrix();
-
-   _mesa_MatrixMode(meta->saved_matrix_mode);
-
-   meta->internal_viewport_call = GL_TRUE;
-   _mesa_Viewport(meta->saved_vp_x, meta->saved_vp_y,
-                 meta->saved_vp_width, meta->saved_vp_height);
-   meta->internal_viewport_call = GL_FALSE;
-}
-
-
-/**
- * Set up a vertex program to pass through the position and first texcoord
- * for pixel path.
- */
-void
-meta_set_passthrough_vertex_program(struct dri_metaops *meta)
-{
-   struct gl_context *ctx = meta->ctx;
-   static const char *vp =
-      "!!ARBvp1.0\n"
-      "TEMP vertexClip;\n"
-      "DP4 vertexClip.x, state.matrix.mvp.row[0], vertex.position;\n"
-      "DP4 vertexClip.y, state.matrix.mvp.row[1], vertex.position;\n"
-      "DP4 vertexClip.z, state.matrix.mvp.row[2], vertex.position;\n"
-      "DP4 vertexClip.w, state.matrix.mvp.row[3], vertex.position;\n"
-      "MOV result.position, vertexClip;\n"
-      "MOV result.texcoord[0], vertex.texcoord[0];\n"
-      "MOV result.color, vertex.color;\n"
-      "END\n";
-
-   assert(meta->saved_vp == NULL);
-
-   _mesa_reference_vertprog(ctx, &meta->saved_vp,
-                           ctx->VertexProgram.Current);
-   if (meta->passthrough_vp == NULL) {
-      GLuint prog_name;
-      _mesa_GenPrograms(1, &prog_name);
-      _mesa_BindProgram(GL_VERTEX_PROGRAM_ARB, prog_name);
-      _mesa_ProgramStringARB(GL_VERTEX_PROGRAM_ARB,
-                            GL_PROGRAM_FORMAT_ASCII_ARB,
-                            strlen(vp), (const GLubyte *)vp);
-      _mesa_reference_vertprog(ctx, &meta->passthrough_vp,
-                              ctx->VertexProgram.Current);
-      _mesa_DeletePrograms(1, &prog_name);
-   }
-
-   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
-   _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
-                           meta->passthrough_vp);
-   ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
-                          &meta->passthrough_vp->Base);
-
-   meta->saved_vp_enable = ctx->VertexProgram.Enabled;
-   _mesa_Enable(GL_VERTEX_PROGRAM_ARB);
-}
-
-/**
- * Restores the previous vertex program after
- * meta_set_passthrough_vertex_program()
- */
-void
-meta_restore_vertex_program(struct dri_metaops *meta)
-{
-   struct gl_context *ctx = meta->ctx;
-
-   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
-   _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
-                           meta->saved_vp);
-   _mesa_reference_vertprog(ctx, &meta->saved_vp, NULL);
-   ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
-                          &ctx->VertexProgram.Current->Base);
-
-   if (!meta->saved_vp_enable)
-      _mesa_Disable(GL_VERTEX_PROGRAM_ARB);
-}
-
-/**
- * Binds the given program string to GL_FRAGMENT_PROGRAM_ARB, caching the
- * program object.
- */
-void
-meta_set_fragment_program(struct dri_metaops *meta,
-                         struct gl_fragment_program **prog,
-                         const char *prog_string)
-{
-   struct gl_context *ctx = meta->ctx;
-   assert(meta->saved_fp == NULL);
-
-   _mesa_reference_fragprog(ctx, &meta->saved_fp,
-                           ctx->FragmentProgram.Current);
-   if (*prog == NULL) {
-      GLuint prog_name;
-      _mesa_GenPrograms(1, &prog_name);
-      _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, prog_name);
-      _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
-                            GL_PROGRAM_FORMAT_ASCII_ARB,
-                            strlen(prog_string), (const GLubyte *)prog_string);
-      _mesa_reference_fragprog(ctx, prog, ctx->FragmentProgram.Current);
-      /* Note that DeletePrograms unbinds the program on us */
-      _mesa_DeletePrograms(1, &prog_name);
-   }
-
-   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
-   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, *prog);
-   ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, &((*prog)->Base));
-
-   meta->saved_fp_enable = ctx->FragmentProgram.Enabled;
-   _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB);
-}
-
-/**
- * Restores the previous fragment program after
- * meta_set_fragment_program()
- */
-void
-meta_restore_fragment_program(struct dri_metaops *meta)
-{
-   struct gl_context *ctx = meta->ctx;
-
-   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
-   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
-                           meta->saved_fp);
-   _mesa_reference_fragprog(ctx, &meta->saved_fp, NULL);
-   ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
-                          &ctx->FragmentProgram.Current->Base);
-
-   if (!meta->saved_fp_enable)
-      _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB);
-}
-
-static const float default_texcoords[4][2] = { { 0.0, 0.0 },
-                                              { 1.0, 0.0 },
-                                              { 1.0, 1.0 },
-                                              { 0.0, 1.0 } };
-
-void
-meta_set_default_texrect(struct dri_metaops *meta)
-{
-   struct gl_context *ctx = meta->ctx;
-   struct gl_client_array *old_texcoord_array;
-
-   meta->saved_active_texture = ctx->Texture.CurrentUnit;
-   if (meta->saved_array_vbo == NULL) {
-      _mesa_reference_buffer_object(ctx, &meta->saved_array_vbo,
-                                   ctx->Array.ArrayBufferObj);
-   }
-
-   old_texcoord_array = &ctx->Array.ArrayObj->TexCoord[0];
-   meta->saved_texcoord_type = old_texcoord_array->Type;
-   meta->saved_texcoord_size = old_texcoord_array->Size;
-   meta->saved_texcoord_stride = old_texcoord_array->Stride;
-   meta->saved_texcoord_enable = old_texcoord_array->Enabled;
-   meta->saved_texcoord_ptr = old_texcoord_array->Ptr;
-   _mesa_reference_buffer_object(ctx, &meta->saved_texcoord_vbo,
-                                old_texcoord_array->BufferObj);
-
-   _mesa_ClientActiveTextureARB(GL_TEXTURE0);
-
-   if (meta->texcoord_vbo == NULL) {
-      GLuint vbo_name;
-
-      _mesa_GenBuffersARB(1, &vbo_name);
-      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_name);
-      _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(default_texcoords),
-                         default_texcoords, GL_STATIC_DRAW_ARB);
-      _mesa_reference_buffer_object(ctx, &meta->texcoord_vbo,
-                                   ctx->Array.ArrayBufferObj);
-   } else {
-      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
-                         meta->texcoord_vbo->Name);
-   }
-   _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), NULL);
-
-   _mesa_Enable(GL_TEXTURE_COORD_ARRAY);
-}
-
-void
-meta_restore_texcoords(struct dri_metaops *meta)
-{
-   struct gl_context *ctx = meta->ctx;
-
-   /* Restore the old TexCoordPointer */
-   if (meta->saved_texcoord_vbo) {
-      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
-                         meta->saved_texcoord_vbo->Name);
-      _mesa_reference_buffer_object(ctx, &meta->saved_texcoord_vbo, NULL);
-   } else {
-      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
-   }
-
-   _mesa_TexCoordPointer(meta->saved_texcoord_size,
-                        meta->saved_texcoord_type,
-                        meta->saved_texcoord_stride,
-                        meta->saved_texcoord_ptr);
-   if (!meta->saved_texcoord_enable)
-      _mesa_Disable(GL_TEXTURE_COORD_ARRAY);
-
-   _mesa_ClientActiveTextureARB(GL_TEXTURE0 +
-                               meta->saved_active_texture);
-
-   if (meta->saved_array_vbo) {
-      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
-                         meta->saved_array_vbo->Name);
-      _mesa_reference_buffer_object(ctx, &meta->saved_array_vbo, NULL);
-   } else {
-      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
-   }
-}
-
-
-void meta_init_metaops(struct gl_context *ctx, struct dri_metaops *meta)
-{
-   meta->ctx = ctx;
-}
-
-void meta_destroy_metaops(struct dri_metaops *meta)
-{
-
-}
diff --git a/src/mesa/drivers/dri/common/dri_metaops.h b/src/mesa/drivers/dri/common/dri_metaops.h
deleted file mode 100644 (file)
index aa7d4ba..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
- * Copyright 2009 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 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 DRI_METAOPS_H
-#define DRI_METAOPS_H
-
-
-struct dri_metaops {
-    struct gl_context *ctx;
-    GLboolean internal_viewport_call;
-    struct gl_fragment_program *bitmap_fp;
-    struct gl_vertex_program *passthrough_vp;
-    struct gl_buffer_object *texcoord_vbo;
-    
-    struct gl_fragment_program *saved_fp;
-    GLboolean saved_fp_enable;
-    struct gl_vertex_program *saved_vp;
-    GLboolean saved_vp_enable;
-
-    struct gl_fragment_program *tex2d_fp;
-    
-    GLboolean saved_texcoord_enable;
-    struct gl_buffer_object *saved_array_vbo, *saved_texcoord_vbo;
-    GLenum saved_texcoord_type;
-    GLsizei saved_texcoord_size, saved_texcoord_stride;
-    const void *saved_texcoord_ptr;
-    int saved_active_texture;
-
-    GLint saved_vp_x, saved_vp_y;
-    GLsizei saved_vp_width, saved_vp_height;
-    GLenum saved_matrix_mode;
-};
-
-
-void meta_set_passthrough_transform(struct dri_metaops *meta);
-
-void meta_restore_transform(struct dri_metaops *meta);
-
-void meta_set_passthrough_vertex_program(struct dri_metaops *meta);
-
-void meta_restore_vertex_program(struct dri_metaops *meta);
-
-void meta_set_fragment_program(struct dri_metaops *meta,
-                         struct gl_fragment_program **prog,
-                         const char *prog_string);
-
-void meta_restore_fragment_program(struct dri_metaops *meta);
-
-void meta_set_default_texrect(struct dri_metaops *meta);
-
-void meta_restore_texcoords(struct dri_metaops *meta);
-
-void meta_init_metaops(struct gl_context *ctx, struct dri_metaops *meta);
-void meta_destroy_metaops(struct dri_metaops *meta);
-
-#endif
index bf8cf6eec07e312529346b5a6790293d33771943..82638fa72079a06f0990f9d017448cc652248e00 100644 (file)
@@ -481,6 +481,22 @@ dri2CreateNewDrawable(__DRIscreen *screen,
     return pdraw;
 }
 
+static __DRIbuffer *
+dri2AllocateBuffer(__DRIscreen *screen,
+                  unsigned int attachment, unsigned int format,
+                  int width, int height)
+{
+    return (*screen->DriverAPI.AllocateBuffer)(screen, attachment, format,
+                                              width, height);
+}
+
+static void
+dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
+{
+   (*screen->DriverAPI.ReleaseBuffer)(screen, buffer);
+}
+
+
 static int
 dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val)
 {
@@ -930,7 +946,9 @@ const __DRIdri2Extension driDRI2Extension = {
     dri2CreateNewDrawable,
     dri2CreateNewContext,
     dri2GetAPIMask,
-    dri2CreateNewContextForAPI
+    dri2CreateNewContextForAPI,
+    dri2AllocateBuffer,
+    dri2ReleaseBuffer
 };
 
 const __DRI2configQueryExtension dri2ConfigQueryExtension = {
index ffffb99b30147802bdf20320dcbbf0fff08690d2..3d3d5c9cd24267f816bf2988d6cd67cb69554b0a 100644 (file)
@@ -223,6 +223,12 @@ struct __DriverAPIRec {
 
     /* DRI2 Entry point */
     const __DRIconfig **(*InitScreen2) (__DRIscreen * priv);
+
+    __DRIbuffer *(*AllocateBuffer) (__DRIscreen *screenPrivate,
+                                   unsigned int attachment,
+                                   unsigned int format,
+                                   int width, int height);
+    void (*ReleaseBuffer) (__DRIscreen *screenPrivate, __DRIbuffer *buffer);
 };
 
 extern const struct __DriverAPIRec driDriverAPI;
index 1529c23b16d0187b32f50f75ac9b04be5140690d..1bdb6d8939ed5f5b9ca4a3428ffe6801d4c77ecc 100644 (file)
@@ -121,6 +121,48 @@ driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config,
     return pcp;
 }
 
+static __DRIcontext *
+driCreateNewContextForAPI(__DRIscreen *psp, int api,
+                          const __DRIconfig *config,
+                          __DRIcontext *shared, void *data)
+{
+    __DRIcontext *pcp;
+    void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
+    gl_api mesa_api;
+
+    switch (api) {
+    case __DRI_API_OPENGL:
+            mesa_api = API_OPENGL;
+            break;
+    case __DRI_API_GLES:
+            mesa_api = API_OPENGLES;
+            break;
+    case __DRI_API_GLES2:
+            mesa_api = API_OPENGLES2;
+            break;
+    default:
+            return NULL;
+    }
+
+    pcp = CALLOC_STRUCT(__DRIcontextRec);
+    if (!pcp)
+        return NULL;
+
+    pcp->loaderPrivate = data;
+
+    pcp->driScreenPriv = psp;
+    pcp->driDrawablePriv = NULL;
+    pcp->driReadablePriv = NULL;
+
+    if (!driDriverAPI.CreateContext(mesa_api,
+                            &config->modes, pcp, shareCtx)) {
+        FREE(pcp);
+        return NULL;
+    }
+
+    return pcp;
+}
+
 static void
 driDestroyContext(__DRIcontext *pcp)
 {
@@ -269,5 +311,6 @@ const __DRIcoreExtension driCoreExtension = {
 const __DRIswrastExtension driSWRastExtension = {
     { __DRI_SWRAST, __DRI_SWRAST_VERSION },
     driCreateNewScreen,
-    driCreateNewDrawable
+    driCreateNewDrawable,
+    driCreateNewContextForAPI
 };
index dc58e91e8c11f8debaf236d025941f15c1d980e9..90dbb6bbe80b3cb7ae7904fc665ecacd5e0e7d4c 100644 (file)
@@ -204,7 +204,7 @@ i810CreateContext( gl_api api,
       shareCtx = ((i810ContextPtr) sharedContextPrivate)->glCtx;
    else
       shareCtx = NULL;
-   imesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
+   imesa->glCtx = _mesa_create_context(API_OPENGL, mesaVis, shareCtx,
                                        &functions, (void*) imesa);
    if (!imesa->glCtx) {
       FREE(imesa);
index ebdefeac87447b1edcba855af8a81af4460c58bf..19f0807759941b3477226165f7fbba700fb2ff78 100644 (file)
@@ -364,7 +364,7 @@ i830_emit_invarient_state(struct intel_context *intel)
 
 
 #define emit( intel, state, size )                     \
-   intel_batchbuffer_data(intel->batch, state, size, false)
+   intel_batchbuffer_data(intel, state, size, false)
 
 static GLuint
 get_dirty(struct i830_hw_state *state)
@@ -428,7 +428,7 @@ i830_emit_state(struct intel_context *intel)
     * scheduling is allowed, rather than assume that it is whenever a
     * batchbuffer fills up.
     */
-   intel_batchbuffer_require_space(intel->batch,
+   intel_batchbuffer_require_space(intel,
                                   get_state_size(state) + INTEL_PRIM_EMIT_SIZE,
                                   false);
    count = 0;
@@ -436,7 +436,7 @@ i830_emit_state(struct intel_context *intel)
    aper_count = 0;
    dirty = get_dirty(state);
 
-   aper_array[aper_count++] = intel->batch->buf;
+   aper_array[aper_count++] = intel->batch.bo;
    if (dirty & I830_UPLOAD_BUFFERS) {
       aper_array[aper_count++] = state->draw_region->buffer;
       if (state->depth_region)
@@ -453,7 +453,7 @@ i830_emit_state(struct intel_context *intel)
    if (dri_bufmgr_check_aperture_space(aper_array, aper_count)) {
        if (count == 0) {
           count++;
-          intel_batchbuffer_flush(intel->batch);
+          intel_batchbuffer_flush(intel);
           goto again;
        } else {
           _mesa_error(ctx, GL_OUT_OF_MEMORY, "i830 emit state");
@@ -556,9 +556,7 @@ i830_emit_state(struct intel_context *intel)
       }
    }
 
-   intel->batch->dirty_state &= ~dirty;
    assert(get_dirty(state) == 0);
-   assert((intel->batch->dirty_state & (1<<1)) == 0);
 }
 
 static void
index 474252b640d0aa4bab106b5a98465f544d220974..7389a1d57a90750b54eaa2153290b43fa629ca80 100644 (file)
@@ -188,9 +188,17 @@ i915CreateContext(int api,
     * FINISHME: vertex shaders?
     */
    ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].EmitCondCodes = GL_TRUE;
-   ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT].EmitNoIfs = GL_TRUE;
-   ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT].EmitNoNoise = GL_TRUE;
-   ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT].EmitNoPow = GL_TRUE;
+
+   struct gl_shader_compiler_options *const fs_options =
+      & ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT];
+   fs_options->EmitNoIfs = GL_TRUE;
+   fs_options->EmitNoNoise = GL_TRUE;
+   fs_options->EmitNoPow = GL_TRUE;
+   fs_options->EmitNoMainReturn = GL_TRUE;
+   fs_options->EmitNoIndirectInput = GL_TRUE;
+   fs_options->EmitNoIndirectOutput = GL_TRUE;
+   fs_options->EmitNoIndirectUniform = GL_TRUE;
+   fs_options->EmitNoIndirectTemp = GL_TRUE;
 
    ctx->Const.MaxDrawBuffers = 1;
 
index 2c80ded075b83c6f756f8be71dc5b3ee496ad672..601620275f46d0d19ad0ccd8ba7bcb098a3aa5d3 100644 (file)
@@ -29,7 +29,6 @@
 #define I915CONTEXT_INC
 
 #include "intel_context.h"
-#include "i915_reg.h"
 
 #define I915_FALLBACK_TEXTURE           0x1000
 #define I915_FALLBACK_COLORMASK                 0x2000
@@ -51,6 +50,7 @@
 #define I915_UPLOAD_INVARIENT        0x40
 #define I915_UPLOAD_DEFAULTS         0x80
 #define I915_UPLOAD_RASTER_RULES     0x100
+#define I915_UPLOAD_BLEND            0x200
 #define I915_UPLOAD_TEX(i)           (0x00010000<<(i))
 #define I915_UPLOAD_TEX_ALL          (0x00ff0000)
 #define I915_UPLOAD_TEX_0_SHIFT      16
 #define I915_DEST_SETUP_SIZE 18
 
 #define I915_CTXREG_STATE4             0
-#define I915_CTXREG_LI                 1
-#define I915_CTXREG_LIS2                       2
-#define I915_CTXREG_LIS4                       3
-#define I915_CTXREG_LIS5                       4
-#define I915_CTXREG_LIS6                       5
-#define I915_CTXREG_IAB                6
-#define I915_CTXREG_BLENDCOLOR0                7
-#define I915_CTXREG_BLENDCOLOR1                8
-#define I915_CTXREG_BF_STENCIL_OPS     9
-#define I915_CTXREG_BF_STENCIL_MASKS   10
-#define I915_CTX_SETUP_SIZE            11
+#define I915_CTXREG_LI                 1
+#define I915_CTXREG_LIS2               2
+#define I915_CTXREG_LIS4               3
+#define I915_CTXREG_LIS5               4
+#define I915_CTXREG_LIS6               5
+#define I915_CTXREG_BF_STENCIL_OPS     6
+#define I915_CTXREG_BF_STENCIL_MASKS   7
+#define I915_CTX_SETUP_SIZE            8
+
+#define I915_BLENDREG_IAB              0
+#define I915_BLENDREG_BLENDCOLOR0      1
+#define I915_BLENDREG_BLENDCOLOR1      2
+#define I915_BLEND_SETUP_SIZE          3
 
 #define I915_FOGREG_COLOR              0
 #define I915_FOGREG_MODE0              1
@@ -123,6 +125,12 @@ enum {
 #define I915_MAX_CONSTANT      32
 #define I915_CONSTANT_SIZE     (2+(4*I915_MAX_CONSTANT))
 
+#define I915_MAX_TEX_INDIRECT 4
+#define I915_MAX_TEX_INSN     32
+#define I915_MAX_ALU_INSN     64
+#define I915_MAX_DECL_INSN    27
+#define I915_MAX_TEMPORARY    16
+
 #define I915_MAX_INSN          (I915_MAX_DECL_INSN + \
                                I915_MAX_TEX_INSN + \
                                I915_MAX_ALU_INSN)
@@ -216,6 +224,7 @@ struct i915_fragment_program
 struct i915_hw_state
 {
    GLuint Ctx[I915_CTX_SETUP_SIZE];
+   GLuint Blend[I915_BLEND_SETUP_SIZE];
    GLuint Buffer[I915_DEST_SETUP_SIZE];
    GLuint Stipple[I915_STP_SETUP_SIZE];
    GLuint Fog[I915_FOG_SETUP_SIZE];
@@ -260,8 +269,12 @@ struct i915_context
 
    struct i915_fragment_program *current_program;
 
+   drm_intel_bo *current_vb_bo;
+   unsigned int current_vertex_size;
+
    struct i915_hw_state state;
    uint32_t last_draw_offset;
+   GLuint last_sampler;
 };
 
 
index 1c6e9845172083c5f274f288ff7c69d0a7026f4d..25f4fc3c8b1da7ddf7e871695df8c2ef846c0995 100644 (file)
@@ -306,6 +306,7 @@ static void calc_live_regs( struct i915_fragment_program *p )
 {
     const struct gl_fragment_program *program = p->ctx->FragmentProgram._Current;
     GLuint regsUsed = 0xffff0000;
+    uint8_t live_components[16] = { 0, };
     GLint i;
    
     for (i = program->Base.NumInstructions - 1; i >= 0; i--) {
@@ -314,13 +315,26 @@ static void calc_live_regs( struct i915_fragment_program *p )
         int a;
 
         /* Register is written to: unmark as live for this and preceeding ops */ 
-        if (inst->DstReg.File == PROGRAM_TEMPORARY)
-            regsUsed &= ~(1 << inst->DstReg.Index);
+        if (inst->DstReg.File == PROGRAM_TEMPORARY) {
+            live_components[inst->DstReg.Index] &= ~inst->DstReg.WriteMask;
+            if (live_components[inst->DstReg.Index] == 0)
+                regsUsed &= ~(1 << inst->DstReg.Index);
+        }
 
         for (a = 0; a < opArgs; a++) {
             /* Register is read from: mark as live for this and preceeding ops */ 
-            if (inst->SrcReg[a].File == PROGRAM_TEMPORARY)
+            if (inst->SrcReg[a].File == PROGRAM_TEMPORARY) {
+                unsigned c;
+
                 regsUsed |= 1 << inst->SrcReg[a].Index;
+
+                for (c = 0; c < 4; c++) {
+                    const unsigned field = GET_SWZ(inst->SrcReg[a].Swizzle, c);
+
+                    if (field <= SWIZZLE_W)
+                        live_components[inst->SrcReg[a].Index] |= (1U << field);
+                }
+            }
         }
 
         p->usedRegs[i] = regsUsed;
@@ -795,18 +809,18 @@ upload_program(struct i915_fragment_program *p)
         flags = get_result_flags(inst);
         dst = get_result_vector(p, inst);
 
-        /* dst = src1 >= src2 */
+        /* tmp = src1 >= src2 */
         i915_emit_arith(p,
                         A0_SGE,
-                        dst,
+                        tmp,
                         flags, 0,
                         src_vector(p, &inst->SrcReg[0], program),
                         src_vector(p, &inst->SrcReg[1], program),
                         0);
-        /* tmp = src1 <= src2 */
+        /* dst = src1 <= src2 */
         i915_emit_arith(p,
                         A0_SGE,
-                        tmp,
+                        dst,
                         flags, 0,
                         negate(src_vector(p, &inst->SrcReg[0], program),
                                1, 1, 1, 1),
@@ -944,18 +958,18 @@ upload_program(struct i915_fragment_program *p)
         flags = get_result_flags(inst);
         dst = get_result_vector(p, inst);
 
-        /* dst = src1 < src2 */
+        /* tmp = src1 < src2 */
         i915_emit_arith(p,
                         A0_SLT,
-                        dst,
+                        tmp,
                         flags, 0,
                         src_vector(p, &inst->SrcReg[0], program),
                         src_vector(p, &inst->SrcReg[1], program),
                         0);
-        /* tmp = src1 > src2 */
+        /* dst = src1 > src2 */
         i915_emit_arith(p,
                         A0_SLT,
-                        tmp,
+                        dst,
                         flags, 0,
                         negate(src_vector(p, &inst->SrcReg[0], program),
                                1, 1, 1, 1),
@@ -1408,6 +1422,10 @@ i915ValidateFragmentProgram(struct i915_context *i915)
                                               intel->vertex_attr_count,
                                               intel->ViewportMatrix.m, 0);
 
+      assert(intel->prim.current_offset == intel->prim.start_offset);
+      intel->prim.start_offset = (intel->prim.current_offset + intel->vertex_size-1) / intel->vertex_size * intel->vertex_size;
+      intel->prim.current_offset = intel->prim.start_offset;
+
       intel->vertex_size >>= 2;
 
       i915->state.Ctx[I915_CTXREG_LIS2] = s2;
index ca1949b223e558190c8a93e34603cdc458cf8ca7..507adf1d3dca0560e2fa63ced4212c61ace5261f 100644 (file)
@@ -538,6 +538,7 @@ i915_upload_program(struct i915_context *i915,
 {
    GLuint program_size = p->csr - p->program;
    GLuint decl_size = p->decl - p->declarations;
+   GLuint nr;
 
    if (p->error)
       return;
@@ -554,32 +555,32 @@ i915_upload_program(struct i915_context *i915,
       i915->state.ProgramSize = decl_size + program_size;
    }
 
-   /* Always seemed to get a failure if I used memcmp() to
-    * shortcircuit this state upload.  Needs further investigation?
-    */
-   if (p->nr_constants) {
-      GLuint nr = p->nr_constants;
-
-      I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 1);
-      I915_STATECHANGE(i915, I915_UPLOAD_CONSTANTS);
-
-      i915->state.Constant[0] = _3DSTATE_PIXEL_SHADER_CONSTANTS | ((nr) * 4);
-      i915->state.Constant[1] = (1 << (nr - 1)) | ((1 << (nr - 1)) - 1);
-
-      memcpy(&i915->state.Constant[2], p->constant, 4 * sizeof(int) * (nr));
-      i915->state.ConstantSize = 2 + (nr) * 4;
-
-      if (0) {
-         GLuint i;
-         for (i = 0; i < nr; i++) {
-            fprintf(stderr, "const[%d]: %f %f %f %f\n", i,
-                    p->constant[i][0],
-                    p->constant[i][1], p->constant[i][2], p->constant[i][3]);
-         }
+   nr = p->nr_constants;
+   if (i915->state.ConstantSize != 2 + nr*4 ||
+       memcmp(i915->state.Constant + 2,
+             p->constant, 4*sizeof(int)*nr)) {
+      if (nr) {
+        I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 1);
+        I915_STATECHANGE(i915, I915_UPLOAD_CONSTANTS);
+
+        i915->state.Constant[0] = _3DSTATE_PIXEL_SHADER_CONSTANTS | (nr * 4);
+        i915->state.Constant[1] = (1 << nr) -1;
+
+        memcpy(&i915->state.Constant[2], p->constant, 4 * sizeof(int) * nr);
+        i915->state.ConstantSize = 2 + nr * 4;
+
+        if (0) {
+           GLuint i;
+           for (i = 0; i < nr; i++) {
+              fprintf(stderr, "const[%d]: %f %f %f %f\n", i,
+                      p->constant[i][0],
+                      p->constant[i][1], p->constant[i][2], p->constant[i][3]);
+           }
+        }
+      }
+      else {
+        I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 0);
       }
-   }
-   else {
-      I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 0);
    }
 
    p->on_hardware = 1;
index 7f31ff674f24c478357b38ba807e1de1027d3a79..766547a4c6a0eeaac2a607ad1afa2f596cd3defc 100644 (file)
 /* p222 */
 
 
-#define I915_MAX_TEX_INDIRECT 4
-#define I915_MAX_TEX_INSN     32
-#define I915_MAX_ALU_INSN     64
-#define I915_MAX_DECL_INSN    27
-#define I915_MAX_TEMPORARY    16
-
-
 /* Each instruction is 3 dwords long, though most don't require all
  * this space.  Maximum of 123 instructions.  Smaller maxes per insn
  * type.
index 63c6e78ebe979af0a9c0ec64859d27fa59517ad3..58d4f5daffd68f2c3c3dac23a971d173ca8420da 100644 (file)
@@ -56,8 +56,7 @@ i915_update_stencil(struct gl_context * ctx)
    GLenum front_func, front_fail, front_pass_z_fail, front_pass_z_pass;
    GLuint back_ref, back_writemask, back_mask;
    GLenum back_func, back_fail, back_pass_z_fail, back_pass_z_pass;
-
-   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+   GLuint dirty = 0;
 
    /* The 915 considers CW to be "front" for two-sided stencil, so choose
     * appropriately.
@@ -94,56 +93,68 @@ i915_update_stencil(struct gl_context * ctx)
       back_pass_z_fail = ctx->Stencil.ZFailFunc[0];
       back_pass_z_pass = ctx->Stencil.ZPassFunc[0];
    }
+#define set_ctx_bits(reg, mask, set) do{ \
+   GLuint dw = i915->state.Ctx[reg]; \
+   dw &= ~(mask); \
+   dw |= (set); \
+   dirty |= dw != i915->state.Ctx[reg]; \
+   i915->state.Ctx[reg] = dw; \
+} while(0)
 
    /* Set front state. */
-   i915->state.Ctx[I915_CTXREG_STATE4] &= ~(MODE4_ENABLE_STENCIL_TEST_MASK |
-                                           MODE4_ENABLE_STENCIL_WRITE_MASK);
-   i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
-                                          ENABLE_STENCIL_WRITE_MASK |
-                                          STENCIL_TEST_MASK(front_mask) |
-                                          STENCIL_WRITE_MASK(front_writemask));
-
-   i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_REF_MASK |
-                                         S5_STENCIL_TEST_FUNC_MASK |
-                                         S5_STENCIL_FAIL_MASK |
-                                         S5_STENCIL_PASS_Z_FAIL_MASK |
-                                         S5_STENCIL_PASS_Z_PASS_MASK);
-
-   i915->state.Ctx[I915_CTXREG_LIS5] |=
-      (front_ref << S5_STENCIL_REF_SHIFT) |
-      (intel_translate_compare_func(front_func) << S5_STENCIL_TEST_FUNC_SHIFT) |
-      (intel_translate_stencil_op(front_fail) << S5_STENCIL_FAIL_SHIFT) |
-      (intel_translate_stencil_op(front_pass_z_fail) <<
-       S5_STENCIL_PASS_Z_FAIL_SHIFT) |
-      (intel_translate_stencil_op(front_pass_z_pass) <<
-       S5_STENCIL_PASS_Z_PASS_SHIFT);
+   set_ctx_bits(I915_CTXREG_STATE4,
+                MODE4_ENABLE_STENCIL_TEST_MASK |
+                MODE4_ENABLE_STENCIL_WRITE_MASK,
+                ENABLE_STENCIL_TEST_MASK |
+                ENABLE_STENCIL_WRITE_MASK |
+                STENCIL_TEST_MASK(front_mask) |
+                STENCIL_WRITE_MASK(front_writemask));
+
+   set_ctx_bits(I915_CTXREG_LIS5,
+                S5_STENCIL_REF_MASK |
+                S5_STENCIL_TEST_FUNC_MASK |
+                S5_STENCIL_FAIL_MASK |
+                S5_STENCIL_PASS_Z_FAIL_MASK |
+                S5_STENCIL_PASS_Z_PASS_MASK,
+                (front_ref << S5_STENCIL_REF_SHIFT) |
+                (intel_translate_compare_func(front_func) << S5_STENCIL_TEST_FUNC_SHIFT) |
+                (intel_translate_stencil_op(front_fail) << S5_STENCIL_FAIL_SHIFT) |
+                (intel_translate_stencil_op(front_pass_z_fail) <<
+                 S5_STENCIL_PASS_Z_FAIL_SHIFT) |
+                (intel_translate_stencil_op(front_pass_z_pass) <<
+                 S5_STENCIL_PASS_Z_PASS_SHIFT));
 
    /* Set back state if different from front. */
    if (ctx->Stencil._TestTwoSide) {
-      i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] &=
-        ~(BFO_STENCIL_REF_MASK |
-          BFO_STENCIL_TEST_MASK |
-          BFO_STENCIL_FAIL_MASK |
-          BFO_STENCIL_PASS_Z_FAIL_MASK |
-          BFO_STENCIL_PASS_Z_PASS_MASK);
-      i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] |= BFO_STENCIL_TWO_SIDE |
-        (back_ref << BFO_STENCIL_REF_SHIFT) |
-        (intel_translate_compare_func(back_func) << BFO_STENCIL_TEST_SHIFT) |
-        (intel_translate_stencil_op(back_fail) << BFO_STENCIL_FAIL_SHIFT) |
-        (intel_translate_stencil_op(back_pass_z_fail) <<
-         BFO_STENCIL_PASS_Z_FAIL_SHIFT) |
-        (intel_translate_stencil_op(back_pass_z_pass) <<
-         BFO_STENCIL_PASS_Z_PASS_SHIFT);
-
-      i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] &=
-        ~(BFM_STENCIL_TEST_MASK_MASK |
-          BFM_STENCIL_WRITE_MASK_MASK);
-      i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] |=
-        BFM_STENCIL_TEST_MASK(back_mask) |
-        BFM_STENCIL_WRITE_MASK(back_writemask);
+      set_ctx_bits(I915_CTXREG_BF_STENCIL_OPS,
+                   BFO_STENCIL_REF_MASK |
+                   BFO_STENCIL_TEST_MASK |
+                   BFO_STENCIL_FAIL_MASK |
+                   BFO_STENCIL_PASS_Z_FAIL_MASK |
+                   BFO_STENCIL_PASS_Z_PASS_MASK,
+                   BFO_STENCIL_TWO_SIDE |
+                   (back_ref << BFO_STENCIL_REF_SHIFT) |
+                   (intel_translate_compare_func(back_func) << BFO_STENCIL_TEST_SHIFT) |
+                   (intel_translate_stencil_op(back_fail) << BFO_STENCIL_FAIL_SHIFT) |
+                   (intel_translate_stencil_op(back_pass_z_fail) <<
+                    BFO_STENCIL_PASS_Z_FAIL_SHIFT) |
+                   (intel_translate_stencil_op(back_pass_z_pass) <<
+                    BFO_STENCIL_PASS_Z_PASS_SHIFT));
+
+      set_ctx_bits(I915_CTXREG_BF_STENCIL_MASKS,
+                   BFM_STENCIL_TEST_MASK_MASK |
+                   BFM_STENCIL_WRITE_MASK_MASK,
+                   BFM_STENCIL_TEST_MASK(back_mask) |
+                   BFM_STENCIL_WRITE_MASK(back_writemask));
    } else {
-      i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] &= ~BFO_STENCIL_TWO_SIDE;
+      set_ctx_bits(I915_CTXREG_BF_STENCIL_OPS,
+                   BFO_STENCIL_TWO_SIDE, 0);
    }
+
+#undef set_ctx_bits
+
+   if (dirty)
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
 }
 
 static void
@@ -169,15 +180,18 @@ i915AlphaFunc(struct gl_context * ctx, GLenum func, GLfloat ref)
    struct i915_context *i915 = I915_CONTEXT(ctx);
    int test = intel_translate_compare_func(func);
    GLubyte refByte;
+   GLuint dw;
 
    UNCLAMPED_FLOAT_TO_UBYTE(refByte, ref);
 
-   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
-   i915->state.Ctx[I915_CTXREG_LIS6] &= ~(S6_ALPHA_TEST_FUNC_MASK |
-                                          S6_ALPHA_REF_MASK);
-   i915->state.Ctx[I915_CTXREG_LIS6] |= ((test << S6_ALPHA_TEST_FUNC_SHIFT) |
-                                         (((GLuint) refByte) <<
-                                          S6_ALPHA_REF_SHIFT));
+   dw = i915->state.Ctx[I915_CTXREG_LIS6];
+   dw &= ~(S6_ALPHA_TEST_FUNC_MASK | S6_ALPHA_REF_MASK);
+   dw |= ((test << S6_ALPHA_TEST_FUNC_SHIFT) |
+         (((GLuint) refByte) << S6_ALPHA_REF_SHIFT));
+   if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) {
+      i915->state.Ctx[I915_CTXREG_LIS6] = dw;
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+   }
 }
 
 /* This function makes sure that the proper enables are
@@ -190,23 +204,32 @@ static void
 i915EvalLogicOpBlendState(struct gl_context * ctx)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
+   GLuint dw0, dw1;
 
-   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+   dw0 = i915->state.Ctx[I915_CTXREG_LIS5];
+   dw1 = i915->state.Ctx[I915_CTXREG_LIS6];
 
    if (RGBA_LOGICOP_ENABLED(ctx)) {
-      i915->state.Ctx[I915_CTXREG_LIS5] |= S5_LOGICOP_ENABLE;
-      i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE;
+      dw0 |= S5_LOGICOP_ENABLE;
+      dw1 &= ~S6_CBUF_BLEND_ENABLE;
    }
    else {
-      i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_LOGICOP_ENABLE;
+      dw0 &= ~S5_LOGICOP_ENABLE;
 
       if (ctx->Color.BlendEnabled) {
-         i915->state.Ctx[I915_CTXREG_LIS6] |= S6_CBUF_BLEND_ENABLE;
+         dw1 |= S6_CBUF_BLEND_ENABLE;
       }
       else {
-         i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE;
+         dw1 &= ~S6_CBUF_BLEND_ENABLE;
       }
    }
+   if (dw0 != i915->state.Ctx[I915_CTXREG_LIS5] ||
+       dw1 != i915->state.Ctx[I915_CTXREG_LIS6]) {
+      i915->state.Ctx[I915_CTXREG_LIS5] = dw0;
+      i915->state.Ctx[I915_CTXREG_LIS6] = dw1;
+
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+   }
 }
 
 static void
@@ -214,6 +237,7 @@ i915BlendColor(struct gl_context * ctx, const GLfloat color[4])
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
    GLubyte r, g, b, a;
+   GLuint dw;
 
    DBG("%s\n", __FUNCTION__);
    
@@ -222,9 +246,11 @@ i915BlendColor(struct gl_context * ctx, const GLfloat color[4])
    UNCLAMPED_FLOAT_TO_UBYTE(b, color[BCOMP]);
    UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]);
 
-   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
-   i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] =
-      (a << 24) | (r << 16) | (g << 8) | b;
+   dw = (a << 24) | (r << 16) | (g << 8) | b;
+   if (dw != i915->state.Blend[I915_BLENDREG_BLENDCOLOR1]) {
+      i915->state.Blend[I915_BLENDREG_BLENDCOLOR1] = dw;
+      I915_STATECHANGE(i915, I915_UPLOAD_BLEND);
+   }
 }
 
 
@@ -258,7 +284,7 @@ static void
 i915UpdateBlendState(struct gl_context * ctx)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
-   GLuint iab = (i915->state.Ctx[I915_CTXREG_IAB] &
+   GLuint iab = (i915->state.Blend[I915_BLENDREG_IAB] &
                  ~(IAB_SRC_FACTOR_MASK |
                    IAB_DST_FACTOR_MASK |
                    (BLENDFUNC_MASK << IAB_FUNC_SHIFT) | IAB_ENABLE));
@@ -293,11 +319,13 @@ i915UpdateBlendState(struct gl_context * ctx)
    if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB)
       iab |= IAB_ENABLE;
 
-   if (iab != i915->state.Ctx[I915_CTXREG_IAB] ||
-       lis6 != i915->state.Ctx[I915_CTXREG_LIS6]) {
-      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
-      i915->state.Ctx[I915_CTXREG_IAB] = iab;
+   if (iab != i915->state.Blend[I915_BLENDREG_IAB]) {
+      i915->state.Blend[I915_BLENDREG_IAB] = iab;
+      I915_STATECHANGE(i915, I915_UPLOAD_BLEND);
+   }
+   if (lis6 != i915->state.Ctx[I915_CTXREG_LIS6]) {
       i915->state.Ctx[I915_CTXREG_LIS6] = lis6;
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
    }
 
    /* This will catch a logicop blend equation */
@@ -325,27 +353,36 @@ i915DepthFunc(struct gl_context * ctx, GLenum func)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
    int test = intel_translate_compare_func(func);
+   GLuint dw;
 
    DBG("%s\n", __FUNCTION__);
    
-   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
-   i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_FUNC_MASK;
-   i915->state.Ctx[I915_CTXREG_LIS6] |= test << S6_DEPTH_TEST_FUNC_SHIFT;
+   dw = i915->state.Ctx[I915_CTXREG_LIS6];
+   dw &= ~S6_DEPTH_TEST_FUNC_MASK;
+   dw |= test << S6_DEPTH_TEST_FUNC_SHIFT;
+   if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) {
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      i915->state.Ctx[I915_CTXREG_LIS6] = dw;
+   }
 }
 
 static void
 i915DepthMask(struct gl_context * ctx, GLboolean flag)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
+   GLuint dw;
 
    DBG("%s flag (%d)\n", __FUNCTION__, flag);
-   
-   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
 
+   dw = i915->state.Ctx[I915_CTXREG_LIS6];
    if (flag && ctx->Depth.Test)
-      i915->state.Ctx[I915_CTXREG_LIS6] |= S6_DEPTH_WRITE_ENABLE;
+      dw |= S6_DEPTH_WRITE_ENABLE;
    else
-      i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_WRITE_ENABLE;
+      dw &= ~S6_DEPTH_WRITE_ENABLE;
+   if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) {
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      i915->state.Ctx[I915_CTXREG_LIS6] = dw;
+   }
 }
 
 
@@ -532,7 +569,7 @@ static void
 i915CullFaceFrontFace(struct gl_context * ctx, GLenum unused)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
-   GLuint mode;
+   GLuint mode, dw;
 
    DBG("%s %d\n", __FUNCTION__,
        ctx->DrawBuffer ? ctx->DrawBuffer->Name : 0);
@@ -554,9 +591,13 @@ i915CullFaceFrontFace(struct gl_context * ctx, GLenum unused)
       mode = S4_CULLMODE_BOTH;
    }
 
-   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
-   i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_CULLMODE_MASK;
-   i915->state.Ctx[I915_CTXREG_LIS4] |= mode;
+   dw = i915->state.Ctx[I915_CTXREG_LIS4];
+   dw &= ~S4_CULLMODE_MASK;
+   dw |= mode;
+   if (dw != i915->state.Ctx[I915_CTXREG_LIS4]) {
+      i915->state.Ctx[I915_CTXREG_LIS4] = dw;
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+   }
 }
 
 static void
@@ -690,6 +731,7 @@ i915_update_fog(struct gl_context * ctx)
    GLenum mode;
    GLboolean enabled;
    GLboolean try_pixel_fog;
+   GLuint dw;
 
    if (ctx->FragmentProgram._Current) {
       /* Pull in static fog state from program */
@@ -765,12 +807,16 @@ i915_update_fog(struct gl_context * ctx)
       i915->vertex_fog = I915_FOG_VERTEX;
    }
 
-   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
    I915_ACTIVESTATE(i915, I915_UPLOAD_FOG, enabled);
+   dw = i915->state.Ctx[I915_CTXREG_LIS5];
    if (enabled)
-      i915->state.Ctx[I915_CTXREG_LIS5] |= S5_FOG_ENABLE;
+      dw |= S5_FOG_ENABLE;
    else
-      i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_FOG_ENABLE;
+      dw &= ~S5_FOG_ENABLE;
+   if (dw != i915->state.Ctx[I915_CTXREG_LIS5]) {
+      i915->state.Ctx[I915_CTXREG_LIS5] = dw;
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+   }
 
    /* Always enable pixel fog.  Vertex fog using fog coord will conflict
     * with fog code appended onto fragment program.
@@ -837,6 +883,7 @@ static void
 i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
+   GLuint dw;
 
    switch (cap) {
    case GL_TEXTURE_2D:
@@ -848,11 +895,15 @@ i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state)
       break;
 
    case GL_ALPHA_TEST:
-      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      dw = i915->state.Ctx[I915_CTXREG_LIS6];
       if (state)
-         i915->state.Ctx[I915_CTXREG_LIS6] |= S6_ALPHA_TEST_ENABLE;
+         dw |= S6_ALPHA_TEST_ENABLE;
       else
-         i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_ALPHA_TEST_ENABLE;
+         dw &= ~S6_ALPHA_TEST_ENABLE;
+      if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) {
+        i915->state.Ctx[I915_CTXREG_LIS6] = dw;
+        I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      }
       break;
 
    case GL_BLEND:
@@ -872,19 +923,27 @@ i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state)
       break;
 
    case GL_DITHER:
-      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      dw = i915->state.Ctx[I915_CTXREG_LIS5];
       if (state)
-         i915->state.Ctx[I915_CTXREG_LIS5] |= S5_COLOR_DITHER_ENABLE;
+         dw |= S5_COLOR_DITHER_ENABLE;
       else
-         i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_COLOR_DITHER_ENABLE;
+         dw &= ~S5_COLOR_DITHER_ENABLE;
+      if (dw != i915->state.Ctx[I915_CTXREG_LIS5]) {
+        i915->state.Ctx[I915_CTXREG_LIS5] = dw;
+        I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      }
       break;
 
    case GL_DEPTH_TEST:
-      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      dw = i915->state.Ctx[I915_CTXREG_LIS6];
       if (state)
-         i915->state.Ctx[I915_CTXREG_LIS6] |= S6_DEPTH_TEST_ENABLE;
+         dw |= S6_DEPTH_TEST_ENABLE;
       else
-         i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_ENABLE;
+         dw &= ~S6_DEPTH_TEST_ENABLE;
+      if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) {
+        i915->state.Ctx[I915_CTXREG_LIS6] = dw;
+        I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      }
 
       i915DepthMask(ctx, ctx->Depth.Mask);
       break;
@@ -900,11 +959,15 @@ i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state)
       break;
 
    case GL_LINE_SMOOTH:
-      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      dw = i915->state.Ctx[I915_CTXREG_LIS4];
       if (state)
-         i915->state.Ctx[I915_CTXREG_LIS4] |= S4_LINE_ANTIALIAS_ENABLE;
+         dw |= S4_LINE_ANTIALIAS_ENABLE;
       else
-         i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_LINE_ANTIALIAS_ENABLE;
+         dw &= ~S4_LINE_ANTIALIAS_ENABLE;
+      if (dw != i915->state.Ctx[I915_CTXREG_LIS4]) {
+        i915->state.Ctx[I915_CTXREG_LIS4] = dw;
+        I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      }
       break;
 
    case GL_FOG:
@@ -923,13 +986,15 @@ i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state)
             hw_stencil = (irbStencil && irbStencil->region);
          }
          if (hw_stencil) {
-            I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+           dw = i915->state.Ctx[I915_CTXREG_LIS5];
             if (state)
-               i915->state.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE |
-                                                     S5_STENCIL_WRITE_ENABLE);
+               dw |= (S5_STENCIL_TEST_ENABLE | S5_STENCIL_WRITE_ENABLE);
             else
-               i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |
-                                                      S5_STENCIL_WRITE_ENABLE);
+               dw &= ~(S5_STENCIL_TEST_ENABLE | S5_STENCIL_WRITE_ENABLE);
+           if (dw != i915->state.Ctx[I915_CTXREG_LIS5]) {
+              i915->state.Ctx[I915_CTXREG_LIS5] = dw;
+              I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+           }
          }
          else {
             FALLBACK(&i915->intel, I915_FALLBACK_STENCIL, state);
@@ -959,11 +1024,15 @@ i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state)
       /* This state change is handled in i915_reduced_primitive_state because
        * the hardware bit should only be set when rendering points.
        */
-      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+        dw = i915->state.Ctx[I915_CTXREG_LIS4];
       if (state)
-        i915->state.Ctx[I915_CTXREG_LIS4] |= S4_SPRITE_POINT_ENABLE;
+        dw |= S4_SPRITE_POINT_ENABLE;
       else
-        i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_SPRITE_POINT_ENABLE;
+        dw &= ~S4_SPRITE_POINT_ENABLE;
+      if (dw != i915->state.Ctx[I915_CTXREG_LIS4]) {
+        i915->state.Ctx[I915_CTXREG_LIS4] = dw;
+        I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      }
       break;
 
    case GL_POINT_SMOOTH:
@@ -984,6 +1053,7 @@ i915_init_packets(struct i915_context *i915)
 
    {
       I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      I915_STATECHANGE(i915, I915_UPLOAD_BLEND);
       /* Probably don't want to upload all this stuff every time one 
        * piece changes.
        */
@@ -1010,13 +1080,13 @@ i915_init_packets(struct i915_context *i915)
                                              ENABLE_STENCIL_WRITE_MASK |
                                              STENCIL_WRITE_MASK(0xff));
 
-      i915->state.Ctx[I915_CTXREG_IAB] =
+      i915->state.Blend[I915_BLENDREG_IAB] =
          (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | IAB_MODIFY_ENABLE |
           IAB_MODIFY_FUNC | IAB_MODIFY_SRC_FACTOR | IAB_MODIFY_DST_FACTOR);
 
-      i915->state.Ctx[I915_CTXREG_BLENDCOLOR0] =
+      i915->state.Blend[I915_BLENDREG_BLENDCOLOR0] =
          _3DSTATE_CONST_BLEND_COLOR_CMD;
-      i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = 0;
+      i915->state.Blend[I915_BLENDREG_BLENDCOLOR1] = 0;
 
       i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] =
         _3DSTATE_BACKFACE_STENCIL_MASKS |
@@ -1087,6 +1157,7 @@ i915_init_packets(struct i915_context *i915)
    i915->state.active = (I915_UPLOAD_PROGRAM |
                          I915_UPLOAD_STIPPLE |
                          I915_UPLOAD_CTX |
+                         I915_UPLOAD_BLEND |
                          I915_UPLOAD_BUFFERS |
                         I915_UPLOAD_INVARIENT |
                         I915_UPLOAD_RASTER_RULES);
index a94b957127563295ea0308242278bec2a91107f1..921183b81dff7db3ef8520fe716a2036fc9aad72 100644 (file)
@@ -217,7 +217,7 @@ i915_emit_invarient_state(struct intel_context *intel)
 
 
 #define emit(intel, state, size )                   \
-   intel_batchbuffer_data(intel->batch, state, size, false)
+   intel_batchbuffer_data(intel, state, size, false)
 
 static GLuint
 get_dirty(struct i915_hw_state *state)
@@ -251,6 +251,9 @@ get_state_size(struct i915_hw_state *state)
    if (dirty & I915_UPLOAD_CTX)
       sz += sizeof(state->Ctx);
 
+   if (dirty & I915_UPLOAD_BLEND)
+      sz += sizeof(state->Blend);
+
    if (dirty & I915_UPLOAD_BUFFERS)
       sz += sizeof(state->Buffer);
 
@@ -299,7 +302,7 @@ i915_emit_state(struct intel_context *intel)
     * scheduling is allowed, rather than assume that it is whenever a
     * batchbuffer fills up.
     */
-   intel_batchbuffer_require_space(intel->batch,
+   intel_batchbuffer_require_space(intel,
                                   get_state_size(state) + INTEL_PRIM_EMIT_SIZE,
                                   false);
    count = 0;
@@ -307,7 +310,7 @@ i915_emit_state(struct intel_context *intel)
    aper_count = 0;
    dirty = get_dirty(state);
 
-   aper_array[aper_count++] = intel->batch->buf;
+   aper_array[aper_count++] = intel->batch.bo;
    if (dirty & I915_UPLOAD_BUFFERS) {
       aper_array[aper_count++] = state->draw_region->buffer;
       if (state->depth_region)
@@ -327,7 +330,7 @@ i915_emit_state(struct intel_context *intel)
    if (dri_bufmgr_check_aperture_space(aper_array, aper_count)) {
        if (count == 0) {
           count++;
-          intel_batchbuffer_flush(intel->batch);
+          intel_batchbuffer_flush(intel);
           goto again;
        } else {
           _mesa_error(ctx, GL_OUT_OF_MEMORY, "i915 emit state");
@@ -366,6 +369,13 @@ i915_emit_state(struct intel_context *intel)
       emit(intel, state->Ctx, sizeof(state->Ctx));
    }
 
+   if (dirty & I915_UPLOAD_BLEND) {
+      if (INTEL_DEBUG & DEBUG_STATE)
+         fprintf(stderr, "I915_UPLOAD_BLEND:\n");
+
+      emit(intel, state->Blend, sizeof(state->Blend));
+   }
+
    if (dirty & I915_UPLOAD_BUFFERS) {
       GLuint count;
 
@@ -426,6 +436,7 @@ i915_emit_state(struct intel_context *intel)
     */
    if (dirty & I915_UPLOAD_TEX_ALL) {
       int nr = 0;
+      GLuint unwind;
 
       for (i = 0; i < I915_TEX_UNITS; i++)
          if (dirty & I915_UPLOAD_TEX(i))
@@ -445,6 +456,7 @@ i915_emit_state(struct intel_context *intel)
          }
       ADVANCE_BATCH();
 
+      unwind = intel->batch.used;
       BEGIN_BATCH(2 + nr * 3);
       OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * nr));
       OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT);
@@ -455,6 +467,13 @@ i915_emit_state(struct intel_context *intel)
             OUT_BATCH(state->Tex[i][I915_TEXREG_SS4]);
          }
       ADVANCE_BATCH();
+      if (i915->last_sampler &&
+         memcmp(intel->batch.map + i915->last_sampler,
+                intel->batch.map + unwind,
+                (2 + nr*3)*sizeof(int)) == 0)
+         intel->batch.used = unwind;
+      else
+         i915->last_sampler = unwind;
    }
 
    if (dirty & I915_UPLOAD_CONSTANTS) {
@@ -476,9 +495,7 @@ i915_emit_state(struct intel_context *intel)
       }
    }
 
-   intel->batch->dirty_state &= ~dirty;
    assert(get_dirty(state) == 0);
-   assert((intel->batch->dirty_state & (1<<1)) == 0);
 }
 
 static void
@@ -660,6 +677,10 @@ i915_new_batch(struct intel_context *intel)
     */
    i915->state.emitted = 0;
    i915->last_draw_offset = 0;
+   i915->last_sampler = 0;
+
+   i915->current_vb_bo = NULL;
+   i915->current_vertex_size = 0;
 }
 
 static void 
index 0d8ab4b507e37888835380666d865dc7bd280d42..2d361ca0a9aa7f947b794b35b5d145a5f7042487 100644 (file)
@@ -124,7 +124,7 @@ static INLINE GLuint intel_get_vb_max(struct intel_context *intel)
    GLuint ret;
 
    if (intel->intelScreen->no_vbo)
-      ret = intel->batch->size - 1500;
+      ret = sizeof(intel->batch.map) - 1500;
    else
       ret = INTEL_VB_SIZE;
    ret /= (intel->vertex_size * 4);
index b9a8aeb12f29787e5c6e24c3e04e0c3d66ff0196..cf9291cdfca14775704d3e3c3db9ac15c7662be4 100644 (file)
@@ -54,6 +54,7 @@
 #include "intel_span.h"
 #include "i830_context.h"
 #include "i830_reg.h"
+#include "i915_context.h"
 
 static void intelRenderPrimitive(struct gl_context * ctx, GLenum prim);
 static void intelRasterPrimitive(struct gl_context * ctx, GLenum rprim,
@@ -62,22 +63,22 @@ static void intelRasterPrimitive(struct gl_context * ctx, GLenum rprim,
 static void
 intel_flush_inline_primitive(struct intel_context *intel)
 {
-   GLuint used = intel->batch->ptr - intel->prim.start_ptr;
+   GLuint used = intel->batch.used - intel->prim.start_ptr;
 
    assert(intel->prim.primitive != ~0);
 
 /*    printf("/\n"); */
 
-   if (used < 8)
+   if (used < 2)
       goto do_discard;
 
-   *(int *) intel->prim.start_ptr = (_3DPRIMITIVE |
-                                     intel->prim.primitive | (used / 4 - 2));
+   intel->batch.map[intel->prim.start_ptr] =
+      _3DPRIMITIVE | intel->prim.primitive | (used - 2);
 
    goto finished;
 
  do_discard:
-   intel->batch->ptr -= used;
+   intel->batch.used = intel->prim.start_ptr;
 
  finished:
    intel->prim.primitive = ~0;
@@ -100,9 +101,7 @@ static void intel_start_inline(struct intel_context *intel, uint32_t prim)
     */
    BEGIN_BATCH(1);
 
-   assert((intel->batch->dirty_state & (1<<1)) == 0);
-
-   intel->prim.start_ptr = intel->batch->ptr;
+   intel->prim.start_ptr = intel->batch.used;
    intel->prim.primitive = prim;
    intel->prim.flush = intel_flush_inline_primitive;
 
@@ -118,26 +117,25 @@ static void intel_wrap_inline(struct intel_context *intel)
    GLuint prim = intel->prim.primitive;
 
    intel_flush_inline_primitive(intel);
-   intel_batchbuffer_flush(intel->batch);
+   intel_batchbuffer_flush(intel);
    intel_start_inline(intel, prim);  /* ??? */
 }
 
 static GLuint *intel_extend_inline(struct intel_context *intel, GLuint dwords)
 {
-   GLuint sz = dwords * sizeof(GLuint);
    GLuint *ptr;
 
    assert(intel->prim.flush == intel_flush_inline_primitive);
 
-   if (intel_batchbuffer_space(intel->batch) < sz)
+   if (intel_batchbuffer_space(intel) < dwords * sizeof(GLuint))
       intel_wrap_inline(intel);
 
 /*    printf("."); */
 
    intel->vtbl.assert_not_dirty(intel);
 
-   ptr = (GLuint *) intel->batch->ptr;
-   intel->batch->ptr += sz;
+   ptr = intel->batch.map + intel->batch.used;
+   intel->batch.used += dwords;
 
    return ptr;
 }
@@ -218,15 +216,15 @@ void intel_flush_prim(struct intel_context *intel)
    offset = intel->prim.start_offset;
    intel->prim.start_offset = intel->prim.current_offset;
    if (intel->gen < 3)
-      intel->prim.start_offset = ALIGN(intel->prim.start_offset, 128);
+      intel->prim.current_offset = intel->prim.start_offset = ALIGN(intel->prim.start_offset, 128);
    intel->prim.flush = NULL;
 
    intel->vtbl.emit_state(intel);
 
-   aper_array[0] = intel->batch->buf;
+   aper_array[0] = intel->batch.bo;
    aper_array[1] = vb_bo;
    if (dri_bufmgr_check_aperture_space(aper_array, 2)) {
-      intel_batchbuffer_flush(intel->batch);
+      intel_batchbuffer_flush(intel);
       intel->vtbl.emit_state(intel);
    }
 
@@ -236,11 +234,6 @@ void intel_flush_prim(struct intel_context *intel)
     */
    intel->no_batch_wrap = GL_TRUE;
 
-   /* Check that we actually emitted the state into this batch, using the
-    * UPLOAD_CTX bit as the signal.
-    */
-   assert((intel->batch->dirty_state & (1<<1)) == 0);
-
 #if 0
    printf("emitting %d..%d=%d vertices size %d\n", offset,
          intel->prim.current_offset, count,
@@ -248,20 +241,39 @@ void intel_flush_prim(struct intel_context *intel)
 #endif
 
    if (intel->gen >= 3) {
-      BEGIN_BATCH(5);
-      OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
-               I1_LOAD_S(0) | I1_LOAD_S(1) | 1);
-      assert((offset & ~S0_VB_OFFSET_MASK) == 0);
-      OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, offset);
-      OUT_BATCH((intel->vertex_size << S1_VERTEX_WIDTH_SHIFT) |
-               (intel->vertex_size << S1_VERTEX_PITCH_SHIFT));
+      struct i915_context *i915 = i915_context(&intel->ctx);
+      unsigned int cmd = 0, len = 0;
 
+      if (vb_bo != i915->current_vb_bo) {
+        cmd |= I1_LOAD_S(0);
+        len++;
+      }
+
+      if (intel->vertex_size != i915->current_vertex_size) {
+        cmd |= I1_LOAD_S(1);
+        len++;
+      }
+      if (len)
+        len++;
+
+      BEGIN_BATCH(2+len);
+      if (cmd)
+        OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | cmd | (len - 2));
+      if (vb_bo != i915->current_vb_bo) {
+        OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, 0);
+        i915->current_vb_bo = vb_bo;
+      }
+      if (intel->vertex_size != i915->current_vertex_size) {
+        OUT_BATCH((intel->vertex_size << S1_VERTEX_WIDTH_SHIFT) |
+                  (intel->vertex_size << S1_VERTEX_PITCH_SHIFT));
+        i915->current_vertex_size = intel->vertex_size;
+      }
       OUT_BATCH(_3DPRIMITIVE |
                PRIM_INDIRECT |
                PRIM_INDIRECT_SEQUENTIAL |
                intel->prim.primitive |
                count);
-      OUT_BATCH(0); /* Beginning vertex index */
+      OUT_BATCH(offset / (intel->vertex_size * 4));
       ADVANCE_BATCH();
    } else {
       struct i830_context *i830 = i830_context(&intel->ctx);
index c986970a757d9ab9aa4906140d0ed2040a1f79d4..412d82ab3ca90cbfb46311efab8518fcaeb67e8a 100644 (file)
@@ -35,6 +35,7 @@
 #include "brw_defines.h"
 #include "brw_util.h"
 #include "main/macros.h"
+#include "intel_batchbuffer.h"
 
 void
 brw_update_cc_vp(struct brw_context *brw)
@@ -92,54 +93,54 @@ static void upload_cc_unit(struct brw_context *brw)
 {
    struct intel_context *intel = &brw->intel;
    struct gl_context *ctx = &brw->intel.ctx;
-   struct brw_cc_unit_state cc;
-   void *map;
+   struct brw_cc_unit_state *cc;
 
-   memset(&cc, 0, sizeof(cc));
+   cc = brw_state_batch(brw, sizeof(*cc), 64, &brw->cc.state_offset);
+   memset(cc, 0, sizeof(*cc));
 
    /* _NEW_STENCIL */
    if (ctx->Stencil._Enabled) {
       const unsigned back = ctx->Stencil._BackFace;
 
-      cc.cc0.stencil_enable = 1;
-      cc.cc0.stencil_func =
+      cc->cc0.stencil_enable = 1;
+      cc->cc0.stencil_func =
         intel_translate_compare_func(ctx->Stencil.Function[0]);
-      cc.cc0.stencil_fail_op =
+      cc->cc0.stencil_fail_op =
         intel_translate_stencil_op(ctx->Stencil.FailFunc[0]);
-      cc.cc0.stencil_pass_depth_fail_op =
+      cc->cc0.stencil_pass_depth_fail_op =
         intel_translate_stencil_op(ctx->Stencil.ZFailFunc[0]);
-      cc.cc0.stencil_pass_depth_pass_op =
+      cc->cc0.stencil_pass_depth_pass_op =
         intel_translate_stencil_op(ctx->Stencil.ZPassFunc[0]);
-      cc.cc1.stencil_ref = ctx->Stencil.Ref[0];
-      cc.cc1.stencil_write_mask = ctx->Stencil.WriteMask[0];
-      cc.cc1.stencil_test_mask = ctx->Stencil.ValueMask[0];
+      cc->cc1.stencil_ref = ctx->Stencil.Ref[0];
+      cc->cc1.stencil_write_mask = ctx->Stencil.WriteMask[0];
+      cc->cc1.stencil_test_mask = ctx->Stencil.ValueMask[0];
 
       if (ctx->Stencil._TestTwoSide) {
-        cc.cc0.bf_stencil_enable = 1;
-        cc.cc0.bf_stencil_func =
+        cc->cc0.bf_stencil_enable = 1;
+        cc->cc0.bf_stencil_func =
            intel_translate_compare_func(ctx->Stencil.Function[back]);
-        cc.cc0.bf_stencil_fail_op =
+        cc->cc0.bf_stencil_fail_op =
            intel_translate_stencil_op(ctx->Stencil.FailFunc[back]);
-        cc.cc0.bf_stencil_pass_depth_fail_op =
+        cc->cc0.bf_stencil_pass_depth_fail_op =
            intel_translate_stencil_op(ctx->Stencil.ZFailFunc[back]);
-        cc.cc0.bf_stencil_pass_depth_pass_op =
+        cc->cc0.bf_stencil_pass_depth_pass_op =
            intel_translate_stencil_op(ctx->Stencil.ZPassFunc[back]);
-        cc.cc1.bf_stencil_ref = ctx->Stencil.Ref[back];
-        cc.cc2.bf_stencil_write_mask = ctx->Stencil.WriteMask[back];
-        cc.cc2.bf_stencil_test_mask = ctx->Stencil.ValueMask[back];
+        cc->cc1.bf_stencil_ref = ctx->Stencil.Ref[back];
+        cc->cc2.bf_stencil_write_mask = ctx->Stencil.WriteMask[back];
+        cc->cc2.bf_stencil_test_mask = ctx->Stencil.ValueMask[back];
       }
 
       /* Not really sure about this:
        */
       if (ctx->Stencil.WriteMask[0] ||
          (ctx->Stencil._TestTwoSide && ctx->Stencil.WriteMask[back]))
-        cc.cc0.stencil_write_enable = 1;
+        cc->cc0.stencil_write_enable = 1;
    }
 
    /* _NEW_COLOR */
    if (ctx->Color._LogicOpEnabled && ctx->Color.LogicOp != GL_COPY) {
-      cc.cc2.logicop_enable = 1;
-      cc.cc5.logicop_func = intel_translate_logic_op(ctx->Color.LogicOp);
+      cc->cc2.logicop_enable = 1;
+      cc->cc5.logicop_func = intel_translate_logic_op(ctx->Color.LogicOp);
    } else if (ctx->Color.BlendEnabled) {
       GLenum eqRGB = ctx->Color.Blend[0].EquationRGB;
       GLenum eqA = ctx->Color.Blend[0].EquationA;
@@ -167,58 +168,55 @@ static void upload_cc_unit(struct brw_context *brw)
         srcA = dstA = GL_ONE;
       }
 
-      cc.cc6.dest_blend_factor = brw_translate_blend_factor(dstRGB);
-      cc.cc6.src_blend_factor = brw_translate_blend_factor(srcRGB);
-      cc.cc6.blend_function = brw_translate_blend_equation(eqRGB);
+      cc->cc6.dest_blend_factor = brw_translate_blend_factor(dstRGB);
+      cc->cc6.src_blend_factor = brw_translate_blend_factor(srcRGB);
+      cc->cc6.blend_function = brw_translate_blend_equation(eqRGB);
 
-      cc.cc5.ia_dest_blend_factor = brw_translate_blend_factor(dstA);
-      cc.cc5.ia_src_blend_factor = brw_translate_blend_factor(srcA);
-      cc.cc5.ia_blend_function = brw_translate_blend_equation(eqA);
+      cc->cc5.ia_dest_blend_factor = brw_translate_blend_factor(dstA);
+      cc->cc5.ia_src_blend_factor = brw_translate_blend_factor(srcA);
+      cc->cc5.ia_blend_function = brw_translate_blend_equation(eqA);
 
-      cc.cc3.blend_enable = 1;
-      cc.cc3.ia_blend_enable = (srcA != srcRGB ||
+      cc->cc3.blend_enable = 1;
+      cc->cc3.ia_blend_enable = (srcA != srcRGB ||
                                dstA != dstRGB ||
                                eqA != eqRGB);
    }
 
    if (ctx->Color.AlphaEnabled) {
-      cc.cc3.alpha_test = 1;
-      cc.cc3.alpha_test_func =
+      cc->cc3.alpha_test = 1;
+      cc->cc3.alpha_test_func =
         intel_translate_compare_func(ctx->Color.AlphaFunc);
-      cc.cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8;
+      cc->cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8;
 
-      UNCLAMPED_FLOAT_TO_UBYTE(cc.cc7.alpha_ref.ub[0], ctx->Color.AlphaRef);
+      UNCLAMPED_FLOAT_TO_UBYTE(cc->cc7.alpha_ref.ub[0], ctx->Color.AlphaRef);
    }
 
    if (ctx->Color.DitherFlag) {
-      cc.cc5.dither_enable = 1;
-      cc.cc6.y_dither_offset = 0;
-      cc.cc6.x_dither_offset = 0;
+      cc->cc5.dither_enable = 1;
+      cc->cc6.y_dither_offset = 0;
+      cc->cc6.x_dither_offset = 0;
    }
 
    /* _NEW_DEPTH */
    if (ctx->Depth.Test) {
-      cc.cc2.depth_test = 1;
-      cc.cc2.depth_test_function =
+      cc->cc2.depth_test = 1;
+      cc->cc2.depth_test_function =
         intel_translate_compare_func(ctx->Depth.Func);
-      cc.cc2.depth_write_enable = ctx->Depth.Mask;
+      cc->cc2.depth_write_enable = ctx->Depth.Mask;
    }
 
    if (intel->stats_wm || unlikely(INTEL_DEBUG & DEBUG_STATS))
-      cc.cc5.statistics_enable = 1;
+      cc->cc5.statistics_enable = 1;
 
    /* CACHE_NEW_CC_VP */
-   cc.cc4.cc_viewport_state_offset = brw->cc.vp_bo->offset >> 5; /* reloc */
+   cc->cc4.cc_viewport_state_offset = brw->cc.vp_bo->offset >> 5; /* reloc */
 
-   map = brw_state_batch(brw, sizeof(cc), 64,
-                        &brw->cc.state_bo, &brw->cc.state_offset);
-   memcpy(map, &cc, sizeof(cc));
    brw->state.dirty.cache |= CACHE_NEW_CC_UNIT;
 
    /* Emit CC viewport relocation */
-   drm_intel_bo_emit_reloc(brw->cc.state_bo, (brw->cc.state_offset +
-                                             offsetof(struct brw_cc_unit_state,
-                                                      cc4)),
+   drm_intel_bo_emit_reloc(brw->intel.batch.bo,
+                          (brw->cc.state_offset +
+                           offsetof(struct brw_cc_unit_state, cc4)),
                           brw->cc.vp_bo, 0,
                           I915_GEM_DOMAIN_INSTRUCTION, 0);
 }
@@ -235,18 +233,16 @@ const struct brw_tracked_state brw_cc_unit = {
 
 static void upload_blend_constant_color(struct brw_context *brw)
 {
-   struct gl_context *ctx = &brw->intel.ctx;
-   struct brw_blend_constant_color bcc;
-
-   memset(&bcc, 0, sizeof(bcc));
-   bcc.header.opcode = _3DSTATE_BLEND_CONSTANT_COLOR;
-   bcc.header.length = sizeof(bcc)/4-2;
-   bcc.blend_constant_color[0] = ctx->Color.BlendColor[0];
-   bcc.blend_constant_color[1] = ctx->Color.BlendColor[1];
-   bcc.blend_constant_color[2] = ctx->Color.BlendColor[2];
-   bcc.blend_constant_color[3] = ctx->Color.BlendColor[3];
-
-   BRW_CACHED_BATCH_STRUCT(brw, &bcc);
+   struct intel_context *intel = &brw->intel;
+   struct gl_context *ctx = &intel->ctx;
+
+   BEGIN_BATCH(5);
+   OUT_BATCH(_3DSTATE_BLEND_CONSTANT_COLOR << 16 | (5-2));
+   OUT_BATCH_F(ctx->Color.BlendColor[0]);
+   OUT_BATCH_F(ctx->Color.BlendColor[1]);
+   OUT_BATCH_F(ctx->Color.BlendColor[2]);
+   OUT_BATCH_F(ctx->Color.BlendColor[3]);
+   CACHED_BATCH();
 }
 
 const struct brw_tracked_state brw_blend_constant_color = {
index 7069724466ab5f4e7693eac4757849143df8657a..3e52304f6abd1c9205ec97cf5f441aeeadbba2cd 100644 (file)
@@ -145,7 +145,7 @@ struct brw_context;
 #define BRW_NEW_NR_VS_SURFACES         0x80000
 #define BRW_NEW_INDEX_BUFFER           0x100000
 #define BRW_NEW_VS_CONSTBUF            0x200000
-#define BRW_NEW_WM_CONSTBUF            0x200000
+#define BRW_NEW_WM_CONSTBUF            0x400000
 
 struct brw_state_flags {
    /** State update flags signalled by mesa internals */
@@ -408,21 +408,26 @@ struct brw_cached_batch_item {
  */
 #define ATTRIB_BIT_DWORDS  ((VERT_ATTRIB_MAX+31)/32)
 
+struct brw_vertex_buffer {
+   /** Buffer object containing the uploaded vertex data */
+   drm_intel_bo *bo;
+   uint32_t offset;
+   /** Byte stride between elements in the uploaded array */
+   GLuint stride;
+};
 struct brw_vertex_element {
    const struct gl_client_array *glarray;
 
+   int buffer;
+
    /** The corresponding Mesa vertex attribute */
    gl_vert_attrib attrib;
    /** Size of a complete element */
    GLuint element_size;
    /** Number of uploaded elements for this input. */
    GLuint count;
-   /** Byte stride between elements in the uploaded array */
-   GLuint stride;
    /** Offset of the first element within the buffer object */
    unsigned int offset;
-   /** Buffer object containing the uploaded vertex data */
-   drm_intel_bo *bo;
 };
 
 
@@ -461,8 +466,6 @@ struct brw_context
    struct {
       struct brw_state_flags dirty;
 
-      GLuint nr_color_regions;
-      struct intel_region *color_regions[MAX_DRAW_BUFFERS];
       struct intel_region *depth_region;
 
       /**
@@ -485,23 +488,27 @@ struct brw_context
 
    struct {
       struct brw_vertex_element inputs[VERT_ATTRIB_MAX];
+      struct brw_vertex_buffer buffers[VERT_ATTRIB_MAX];
+      struct {
+             uint32_t handle;
+             uint32_t offset;
+             uint32_t stride;
+      } current_buffers[VERT_ATTRIB_MAX];
 
       struct brw_vertex_element *enabled[VERT_ATTRIB_MAX];
       GLuint nr_enabled;
-
-#define BRW_NR_UPLOAD_BUFS 17
-#define BRW_UPLOAD_INIT_SIZE (128*1024)
-
-      struct {
-        drm_intel_bo *bo;
-        GLuint offset;
-      } upload;
+      GLuint nr_buffers, nr_current_buffers;
 
       /* Summary of size and varying of active arrays, so we can check
        * for changes to this state:
        */
       struct brw_vertex_info info;
       unsigned int min_index, max_index;
+
+      /* Offset from start of vertex buffer so we can avoid redefining
+       * the same VB packed over and over again.
+       */
+      unsigned int start_vertex_bias;
    } vb;
 
    struct {
@@ -515,7 +522,7 @@ struct brw_context
       /* Updates to these fields are signaled by BRW_NEW_INDEX_BUFFER. */
       drm_intel_bo *bo;
       unsigned int offset;
-      unsigned int size;
+
       /* Offset to index buffer index to use in CMD_3D_PRIM so that we can
        * avoid re-uploading the IB packet over and over if we're actually
        * referencing the same index buffer.
@@ -528,11 +535,6 @@ struct brw_context
    const struct gl_vertex_program *vertex_program;
    const struct gl_fragment_program *fragment_program;
 
-
-   /* For populating the gtt:
-    */
-   GLuint next_free_page;
-
    /* hw-dependent 3DSTATE_VF_STATISTICS opcode */
    uint32_t CMD_VF_STATISTICS;
    /* hw-dependent 3DSTATE_PIPELINE_SELECT opcode */
@@ -612,9 +614,7 @@ struct brw_context
       drm_intel_bo *const_bo;
 
       /** Binding table of pointers to surf_bo entries */
-      drm_intel_bo *bind_bo;
       uint32_t bind_bo_offset;
-      drm_intel_bo *surf_bo[BRW_VS_MAX_SURF];
       uint32_t surf_offset[BRW_VS_MAX_SURF];
       GLuint nr_surfaces;      
    } vs;
@@ -666,9 +666,7 @@ struct brw_context
       drm_intel_bo *sampler_bo;
 
       /** Binding table of pointers to surf_bo entries */
-      drm_intel_bo *bind_bo;
       uint32_t bind_bo_offset;
-      drm_intel_bo *surf_bo[BRW_WM_MAX_SURF];
       uint32_t surf_offset[BRW_WM_MAX_SURF];
 
       drm_intel_bo *prog_bo;
@@ -693,7 +691,6 @@ struct brw_context
       drm_intel_bo *depth_stencil_state_bo;
       drm_intel_bo *color_calc_state_bo;
 
-      drm_intel_bo *state_bo;
       uint32_t state_offset;
    } cc;
 
@@ -841,4 +838,3 @@ float convert_param(enum param_conversion conversion, float param)
 GLboolean brw_do_cubemap_normalize(struct exec_list *instructions);
 
 #endif
-
index 35bea681214d63f35ad3f631137e9ec2eb0a713e..8574169e472634bffa9f6214ff02412350f538fe 100644 (file)
@@ -51,7 +51,7 @@ brw_cubemap_normalize_visitor::visit_leave(ir_texture *ir)
    if (ir->sampler->type->sampler_dimensionality != GLSL_SAMPLER_DIM_CUBE)
       return visit_continue;
 
-   void *mem_ctx = talloc_parent(ir);
+   void *mem_ctx = ralloc_parent(ir);
 
    ir_variable *var = new(mem_ctx) ir_variable(ir->coordinate->type,
                                               "coordinate", ir_var_auto);
index 877b22fec19ad165ae29a67ca8448e698f8aa442..ae11c487a2c7d949f7d0be9c9f6e01888a7c9aa0 100644 (file)
@@ -146,22 +146,24 @@ const struct brw_tracked_state brw_curbe_offsets = {
  */
 void brw_upload_cs_urb_state(struct brw_context *brw)
 {
-   struct brw_cs_urb_state cs_urb;
-   memset(&cs_urb, 0, sizeof(cs_urb));
+   struct intel_context *intel = &brw->intel;
 
+   BEGIN_BATCH(2);
    /* It appears that this is the state packet for the CS unit, ie. the
     * urb entries detailed here are housed in the CS range from the
     * URB_FENCE command.
     */
-   cs_urb.header.opcode = CMD_CS_URB_STATE;
-   cs_urb.header.length = sizeof(cs_urb)/4 - 2;
+   OUT_BATCH(CMD_CS_URB_STATE << 16 | (2-2));
 
    /* BRW_NEW_URB_FENCE */
-   cs_urb.bits0.nr_urb_entries = brw->urb.nr_cs_entries;
-   cs_urb.bits0.urb_entry_size = brw->urb.csize - 1;
-
-   assert(brw->urb.nr_cs_entries);
-   BRW_CACHED_BATCH_STRUCT(brw, &cs_urb);
+   if (brw->urb.csize == 0) {
+      OUT_BATCH(0);
+   } else {
+      /* BRW_NEW_URB_FENCE */
+      assert(brw->urb.nr_cs_entries);
+      OUT_BATCH((brw->urb.csize - 1) << 4 | brw->urb.nr_cs_entries);
+   }
+   CACHED_BATCH();
 }
 
 static GLfloat fixed_plane[6][4] = {
index 2f7dcc2dda7fd8c600a98f334f05119b66edc15f..a413c02b5731b0729c4cf9fcd95b2f212510a676 100644 (file)
 #define CMD_PIPELINE_SELECT_965       0x6104
 #define CMD_PIPELINE_SELECT_GM45      0x6904
 
-#define CMD_PIPELINED_STATE_POINTERS  0x7800
-#define CMD_BINDING_TABLE_PTRS        0x7801
+#define _3DSTATE_PIPELINED_POINTERS            0x7800
+#define _3DSTATE_BINDING_TABLE_POINTERS                0x7801
 # define GEN6_BINDING_TABLE_MODIFY_VS  (1 << 8)
 # define GEN6_BINDING_TABLE_MODIFY_GS  (1 << 9)
 # define GEN6_BINDING_TABLE_MODIFY_PS  (1 << 12)
index 7eb16b71f4af1623ca2abc670e21352bb714ff63..f5abe021c433d73e3f78bb586db3a014bed65851 100644 (file)
@@ -145,9 +145,14 @@ static void brw_emit_prim(struct brw_context *brw,
    prim_packet.start_vert_location = prim->start;
    if (prim->indexed)
       prim_packet.start_vert_location += brw->ib.start_vertex_offset;
+   else
+      prim_packet.start_vert_location += brw->vb.start_vertex_bias;
    prim_packet.instance_count = 1;
    prim_packet.start_instance_location = 0;
    prim_packet.base_vert_location = prim->basevertex;
+   if (prim->indexed)
+      prim_packet.base_vert_location += brw->vb.start_vertex_bias;
+
 
    /* If we're set to always flush, do it before and after the primitive emit.
     * We want to catch both missed flushes that hurt instruction/state cache
@@ -155,14 +160,14 @@ static void brw_emit_prim(struct brw_context *brw,
     * the besides the draw code.
     */
    if (intel->always_flush_cache) {
-      intel_batchbuffer_emit_mi_flush(intel->batch);
+      intel_batchbuffer_emit_mi_flush(intel);
    }
    if (prim_packet.verts_per_instance) {
-      intel_batchbuffer_data( brw->intel.batch, &prim_packet,
+      intel_batchbuffer_data(&brw->intel, &prim_packet,
                              sizeof(prim_packet), false);
    }
    if (intel->always_flush_cache) {
-      intel_batchbuffer_emit_mi_flush(intel->batch);
+      intel_batchbuffer_emit_mi_flush(intel);
    }
 }
 
@@ -172,13 +177,16 @@ static void brw_merge_inputs( struct brw_context *brw,
    struct brw_vertex_info old = brw->vb.info;
    GLuint i;
 
-   for (i = 0; i < VERT_ATTRIB_MAX; i++)
-      drm_intel_bo_unreference(brw->vb.inputs[i].bo);
+   for (i = 0; i < brw->vb.nr_buffers; i++) {
+      drm_intel_bo_unreference(brw->vb.buffers[i].bo);
+      brw->vb.buffers[i].bo = NULL;
+   }
+   brw->vb.nr_buffers = 0;
 
-   memset(&brw->vb.inputs, 0, sizeof(brw->vb.inputs));
    memset(&brw->vb.info, 0, sizeof(brw->vb.info));
 
    for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+      brw->vb.inputs[i].buffer = -1;
       brw->vb.inputs[i].glarray = arrays[i];
       brw->vb.inputs[i].attrib = (gl_vert_attrib) i;
 
@@ -303,7 +311,6 @@ static GLboolean brw_try_draw_prims( struct gl_context *ctx,
    struct brw_context *brw = brw_context(ctx);
    GLboolean retval = GL_FALSE;
    GLboolean warn = GL_FALSE;
-   GLboolean first_time = GL_TRUE;
    GLuint i;
 
    if (ctx->NewState)
@@ -351,14 +358,10 @@ static GLboolean brw_try_draw_prims( struct gl_context *ctx,
        * an upper bound of how much we might emit in a single
        * brw_try_draw_prims().
        */
-      intel_batchbuffer_require_space(intel->batch, intel->batch->size / 4,
-                                     false);
+      intel_batchbuffer_require_space(intel, 1024, false);
 
       hw_prim = brw_set_prim(brw, &prim[i]);
-
-      if (first_time || (brw->state.dirty.brw & BRW_NEW_PRIMITIVE)) {
-        first_time = GL_FALSE;
-
+      if (brw->state.dirty.brw) {
         brw_validate_state(brw);
 
         /* Various fallback checks:  */
@@ -371,7 +374,7 @@ static GLboolean brw_try_draw_prims( struct gl_context *ctx,
         if (dri_bufmgr_check_aperture_space(brw->state.validated_bos,
                                             brw->state.validated_bo_count)) {
            static GLboolean warned;
-           intel_batchbuffer_flush(intel->batch);
+           intel_batchbuffer_flush(intel);
 
            /* Validate the state after we flushed the batch (which would have
             * changed the set of dirty state).  If we still fail to
@@ -400,7 +403,7 @@ static GLboolean brw_try_draw_prims( struct gl_context *ctx,
    }
 
    if (intel->always_flush_batch)
-      intel_batchbuffer_flush(intel->batch);
+      intel_batchbuffer_flush(intel);
  out:
 
    brw_state_cache_check_size(brw);
@@ -461,25 +464,32 @@ void brw_draw_init( struct brw_context *brw )
 {
    struct gl_context *ctx = &brw->intel.ctx;
    struct vbo_context *vbo = vbo_context(ctx);
+   int i;
 
    /* Register our drawing function: 
     */
    vbo->draw_prims = brw_draw_prims;
+
+   for (i = 0; i < VERT_ATTRIB_MAX; i++)
+      brw->vb.inputs[i].buffer = -1;
+   brw->vb.nr_buffers = 0;
+   brw->vb.nr_enabled = 0;
 }
 
 void brw_draw_destroy( struct brw_context *brw )
 {
    int i;
 
-   if (brw->vb.upload.bo != NULL) {
-      drm_intel_bo_unreference(brw->vb.upload.bo);
-      brw->vb.upload.bo = NULL;
+   for (i = 0; i < brw->vb.nr_buffers; i++) {
+      drm_intel_bo_unreference(brw->vb.buffers[i].bo);
+      brw->vb.buffers[i].bo = NULL;
    }
+   brw->vb.nr_buffers = 0;
 
-   for (i = 0; i < VERT_ATTRIB_MAX; i++) {
-      drm_intel_bo_unreference(brw->vb.inputs[i].bo);
-      brw->vb.inputs[i].bo = NULL;
+   for (i = 0; i < brw->vb.nr_enabled; i++) {
+      brw->vb.enabled[i]->buffer = -1;
    }
+   brw->vb.nr_enabled = 0;
 
    drm_intel_bo_unreference(brw->ib.bo);
    brw->ib.bo = NULL;
index 2cefe614dd2cf2fac78ba724444cafe725f11803..7234ce210b530caf5e1e39a8dddcdca252415960 100644 (file)
@@ -25,6 +25,7 @@
  * 
  **************************************************************************/
 
+#undef NDEBUG
 
 #include "main/glheader.h"
 #include "main/bufferobj.h"
@@ -238,76 +239,31 @@ static GLuint get_index_type(GLenum type)
    }
 }
 
-static void wrap_buffers( struct brw_context *brw,
-                         GLuint size )
-{
-   if (size < BRW_UPLOAD_INIT_SIZE)
-      size = BRW_UPLOAD_INIT_SIZE;
-
-   brw->vb.upload.offset = 0;
-
-   if (brw->vb.upload.bo != NULL)
-      drm_intel_bo_unreference(brw->vb.upload.bo);
-   brw->vb.upload.bo = drm_intel_bo_alloc(brw->intel.bufmgr, "temporary VBO",
-                                         size, 1);
-}
-
-static void get_space( struct brw_context *brw,
-                      GLuint size,
-                      drm_intel_bo **bo_return,
-                      GLuint *offset_return )
-{
-   size = ALIGN(size, 64);
-
-   if (brw->vb.upload.bo == NULL ||
-       brw->vb.upload.offset + size > brw->vb.upload.bo->size) {
-      wrap_buffers(brw, size);
-   }
-
-   assert(*bo_return == NULL);
-   drm_intel_bo_reference(brw->vb.upload.bo);
-   *bo_return = brw->vb.upload.bo;
-   *offset_return = brw->vb.upload.offset;
-   brw->vb.upload.offset += size;
-}
-
 static void
 copy_array_to_vbo_array( struct brw_context *brw,
                         struct brw_vertex_element *element,
+                        struct brw_vertex_buffer *buffer,
                         GLuint dst_stride)
 {
    GLuint size = element->count * dst_stride;
 
-   get_space(brw, size, &element->bo, &element->offset);
-
-   if (element->glarray->StrideB == 0) {
-      assert(element->count == 1);
-      element->stride = 0;
-   } else {
-      element->stride = dst_stride;
-   }
-
+   buffer->stride = dst_stride;
    if (dst_stride == element->glarray->StrideB) {
-      drm_intel_gem_bo_map_gtt(element->bo);
-      memcpy((char *)element->bo->virtual + element->offset,
-            element->glarray->Ptr, size);
-      drm_intel_gem_bo_unmap_gtt(element->bo);
+      intel_upload_data(&brw->intel, element->glarray->Ptr, size, dst_stride,
+                       &buffer->bo, &buffer->offset);
    } else {
-      char *dest;
       const unsigned char *src = element->glarray->Ptr;
+      char *map = intel_upload_map(&brw->intel, size, dst_stride);
+      char *dst = map;
       int i;
 
-      drm_intel_gem_bo_map_gtt(element->bo);
-      dest = element->bo->virtual;
-      dest += element->offset;
-
       for (i = 0; i < element->count; i++) {
-        memcpy(dest, src, dst_stride);
+        memcpy(dst, src, dst_stride);
         src += element->glarray->StrideB;
-        dest += dst_stride;
+        dst += dst_stride;
       }
-
-      drm_intel_gem_bo_unmap_gtt(element->bo);
+      intel_upload_unmap(&brw->intel, map, size, dst_stride,
+                        &buffer->bo, &buffer->offset);
    }
 }
 
@@ -316,11 +272,11 @@ static void brw_prepare_vertices(struct brw_context *brw)
    struct gl_context *ctx = &brw->intel.ctx;
    struct intel_context *intel = intel_context(ctx);
    GLbitfield vs_inputs = brw->vs.prog_data->inputs_read; 
-   GLuint i;
    const unsigned char *ptr = NULL;
-   GLuint interleave = 0;
+   GLuint interleaved = 0, total_size = 0, count = -1;
    unsigned int min_index = brw->vb.min_index;
    unsigned int max_index = brw->vb.max_index;
+   int i, j;
 
    struct brw_vertex_element *upload[VERT_ATTRIB_MAX];
    GLuint nr_uploads = 0;
@@ -340,6 +296,12 @@ static void brw_prepare_vertices(struct brw_context *brw)
       brw->vb.enabled[brw->vb.nr_enabled++] = input;
    }
 
+   if (brw->vb.nr_enabled == 0)
+      return;
+
+   if (brw->vb.nr_buffers)
+      goto validate;
+
    /* XXX: In the rare cases where this happens we fallback all
     * the way to software rasterization, although a tnl fallback
     * would be sufficient.  I don't know of *any* real world
@@ -351,23 +313,43 @@ static void brw_prepare_vertices(struct brw_context *brw)
       return;
    }
 
-   for (i = 0; i < brw->vb.nr_enabled; i++) {
+   for (i = j = 0; i < brw->vb.nr_enabled; i++) {
       struct brw_vertex_element *input = brw->vb.enabled[i];
+      const struct gl_client_array *glarray = input->glarray;
+      int type_size = get_size(glarray->Type);
 
-      input->element_size = get_size(input->glarray->Type) * input->glarray->Size;
+      input->element_size = type_size * glarray->Size;
 
-      if (_mesa_is_bufferobj(input->glarray->BufferObj)) {
+      if (_mesa_is_bufferobj(glarray->BufferObj)) {
         struct intel_buffer_object *intel_buffer =
-           intel_buffer_object(input->glarray->BufferObj);
-
-        /* Named buffer object: Just reference its contents directly. */
-        drm_intel_bo_unreference(input->bo);
-        input->bo = intel_bufferobj_buffer(intel, intel_buffer,
-                                           INTEL_READ);
-        drm_intel_bo_reference(input->bo);
-        input->offset = (unsigned long)input->glarray->Ptr;
-        input->stride = input->glarray->StrideB;
-        input->count = input->glarray->_MaxElement;
+           intel_buffer_object(glarray->BufferObj);
+        int k;
+
+        for (k = 0; k < i; k++) {
+           const struct gl_client_array *other = brw->vb.enabled[k]->glarray;
+           if (glarray->BufferObj == other->BufferObj &&
+               glarray->StrideB == other->StrideB &&
+               (uintptr_t)(glarray->Ptr - other->Ptr) < glarray->StrideB)
+           {
+              input->buffer = brw->vb.enabled[k]->buffer;
+              input->offset = glarray->Ptr - other->Ptr;
+              break;
+           }
+        }
+        if (k == i) {
+           struct brw_vertex_buffer *buffer = &brw->vb.buffers[j];
+
+           /* Named buffer object: Just reference its contents directly. */
+           buffer->bo = intel_bufferobj_source(intel, intel_buffer,
+                                               &buffer->offset);
+           drm_intel_bo_reference(buffer->bo);
+           buffer->offset += (uintptr_t)glarray->Ptr;
+           buffer->stride = glarray->StrideB;
+
+           input->buffer = j++;
+           input->offset = 0;
+        }
+        input->count = glarray->_MaxElement;
 
         /* This is a common place to reach if the user mistakenly supplies
          * a pointer in place of a VBO offset.  If we just let it go through,
@@ -381,71 +363,138 @@ static void brw_prepare_vertices(struct brw_context *brw)
          * probably a service to the poor programmer to do so rather than
          * trying to just not render.
          */
-        assert(input->offset < input->bo->size);
+        assert(input->offset < brw->vb.buffers[input->buffer].bo->size);
       } else {
-        input->count = input->glarray->StrideB ? max_index + 1 : 1;
-        if (input->bo != NULL) {
-           /* Already-uploaded vertex data is present from a previous
-            * prepare_vertices, but we had to re-validate state due to
-            * check_aperture failing and a new batch being produced.
-            */
-           continue;
-        }
+        input->count = glarray->StrideB ? max_index + 1 : 1;
 
         /* Queue the buffer object up to be uploaded in the next pass,
          * when we've decided if we're doing interleaved or not.
          */
-        if (input->attrib == VERT_ATTRIB_POS) {
+        if (nr_uploads == 0) {
            /* Position array not properly enabled:
             */
-            if (input->glarray->StrideB == 0) {
+           if (input->attrib == VERT_ATTRIB_POS && glarray->StrideB == 0) {
                intel->Fallback = GL_TRUE; /* boolean, not bitfield */
                return;
             }
 
-           interleave = input->glarray->StrideB;
-           ptr = input->glarray->Ptr;
+           interleaved = glarray->StrideB;
+           ptr = glarray->Ptr;
         }
-        else if (interleave != input->glarray->StrideB ||
-                 (const unsigned char *)input->glarray->Ptr - ptr < 0 ||
-                 (const unsigned char *)input->glarray->Ptr - ptr > interleave)
+        else if (interleaved != glarray->StrideB ||
+                 (uintptr_t)(glarray->Ptr - ptr) > interleaved)
         {
-           interleave = 0;
+           interleaved = 0;
         }
+        else if (total_size & (type_size -1))
+        {
+           /* enforce natural alignment (for doubles) */
+           interleaved = 0;
+        }
+
+        if (count > input->count)
+           count = input->count;
 
         upload[nr_uploads++] = input;
+        total_size += input->element_size;
       }
    }
 
    /* Handle any arrays to be uploaded. */
-   if (nr_uploads > 1 && interleave && interleave <= 256) {
-      /* All uploads are interleaved, so upload the arrays together as
-       * interleaved.  First, upload the contents and set up upload[0].
-       */
-      copy_array_to_vbo_array(brw, upload[0], interleave);
-
-      for (i = 1; i < nr_uploads; i++) {
-        /* Then, just point upload[i] at upload[0]'s buffer. */
-        upload[i]->stride = interleave;
-        upload[i]->offset = upload[0]->offset +
-           ((const unsigned char *)upload[i]->glarray->Ptr - ptr);
-        upload[i]->bo = upload[0]->bo;
-        drm_intel_bo_reference(upload[i]->bo);
+   if (nr_uploads > 1) {
+      if (interleaved && interleaved <= 2*total_size) {
+        /* All uploads are interleaved, so upload the arrays together as
+         * interleaved.  First, upload the contents and set up upload[0].
+         */
+        upload[0]->count = count; /* trim the upload over all arrays */
+        copy_array_to_vbo_array(brw,
+                                upload[0], &brw->vb.buffers[j],
+                                interleaved);
+
+        for (i = 0; i < nr_uploads; i++) {
+           /* Then, just point upload[i] at upload[0]'s buffer. */
+           upload[i]->offset =
+              ((const unsigned char *)upload[i]->glarray->Ptr - ptr);
+           upload[i]->buffer = j;
+        }
+        j++;
+
+        nr_uploads = 0;
       }
-   }
-   else {
-      /* Upload non-interleaved arrays */
-      for (i = 0; i < nr_uploads; i++) {
-          copy_array_to_vbo_array(brw, upload[i], upload[i]->element_size);
+      else if (total_size < 2048) {
+        /* Upload non-interleaved arrays into a single interleaved array */
+        struct brw_vertex_buffer *buffer = &brw->vb.buffers[j];
+        int count = upload[0]->count, offset;
+        char *map;
+
+        map = intel_upload_map(&brw->intel, total_size * count, total_size);
+        for (i = offset = 0; i < nr_uploads; i++) {
+           const unsigned char *src = upload[i]->glarray->Ptr;
+           int size = upload[i]->element_size;
+           int stride = upload[i]->glarray->StrideB;
+           char *dst = map + offset;
+           int n;
+
+           for (n = 0; n < count; n++) {
+              memcpy(dst, src, size);
+              src += stride;
+              dst += total_size;
+           }
+
+           upload[i]->offset = offset;
+           upload[i]->buffer = j;
+
+           offset += size;
+        }
+        intel_upload_unmap(&brw->intel, map, total_size * count, total_size,
+                           &buffer->bo, &buffer->offset);
+        buffer->stride = offset;
+        j++;
+
+        nr_uploads = 0;
       }
    }
+   /* Upload non-interleaved arrays */
+   for (i = 0; i < nr_uploads; i++) {
+      copy_array_to_vbo_array(brw,
+                             upload[i], &brw->vb.buffers[j],
+                             upload[i]->element_size);
+      upload[i]->buffer = j++;
+      upload[i]->offset = 0;
+   }
 
-   brw_prepare_query_begin(brw);
+   /* can we simply extend the current vb? */
+   brw->vb.start_vertex_bias = 0;
+   if (j == brw->vb.nr_current_buffers) {
+      int delta = 0;
+      for (i = 0; i < j; i++) {
+        int d;
+
+        if (brw->vb.current_buffers[i].handle != brw->vb.buffers[i].bo->handle ||
+            brw->vb.current_buffers[i].stride != brw->vb.buffers[i].stride)
+           break;
+
+        d = brw->vb.buffers[i].offset - brw->vb.current_buffers[i].offset;
+        if (delta == 0)
+           delta = d / brw->vb.current_buffers[i].stride;
+        if (delta * brw->vb.current_buffers[i].stride != d)
+           break;
+      }
 
-   for (i = 0; i < brw->vb.nr_enabled; i++) {
-      struct brw_vertex_element *input = brw->vb.enabled[i];
+      if (i == j) {
+        brw->vb.start_vertex_bias = delta;
+        while (--j >= 0)
+           drm_intel_bo_unreference(brw->vb.buffers[j].bo);
+        j = 0;
+      }
+   }
 
-      brw_add_validated_bo(brw, input->bo);
+   brw->vb.nr_buffers = j;
+
+validate:
+   brw_prepare_query_begin(brw);
+   for (i = 0; i < brw->vb.nr_buffers; i++) {
+      brw_add_validated_bo(brw, brw->vb.buffers[i].bo);
    }
 }
 
@@ -482,49 +531,44 @@ static void brw_emit_vertices(struct brw_context *brw)
                (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) |
                (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) |
                (BRW_VE1_COMPONENT_STORE_1_FLT << BRW_VE1_COMPONENT_3_SHIFT));
-      ADVANCE_BATCH();
+      CACHED_BATCH();
       return;
    }
 
    /* Now emit VB and VEP state packets.
-    *
-    * This still defines a hardware VB for each input, even if they
-    * are interleaved or from the same VBO.  TBD if this makes a
-    * performance difference.
     */
-   BEGIN_BATCH(1 + brw->vb.nr_enabled * 4);
-   OUT_BATCH((CMD_VERTEX_BUFFER << 16) |
-            ((1 + brw->vb.nr_enabled * 4) - 2));
 
-   for (i = 0; i < brw->vb.nr_enabled; i++) {
-      struct brw_vertex_element *input = brw->vb.enabled[i];
-      uint32_t dw0;
+   if (brw->vb.nr_buffers) {
+      BEGIN_BATCH(1 + 4*brw->vb.nr_buffers);
+      OUT_BATCH((CMD_VERTEX_BUFFER << 16) | (4*brw->vb.nr_buffers - 1));
+      for (i = 0; i < brw->vb.nr_buffers; i++) {
+        struct brw_vertex_buffer *buffer = &brw->vb.buffers[i];
+        uint32_t dw0;
+
+        if (intel->gen >= 6) {
+           dw0 = GEN6_VB0_ACCESS_VERTEXDATA | (i << GEN6_VB0_INDEX_SHIFT);
+        } else {
+           dw0 = BRW_VB0_ACCESS_VERTEXDATA | (i << BRW_VB0_INDEX_SHIFT);
+        }
 
-      if (intel->gen >= 6) {
-        dw0 = GEN6_VB0_ACCESS_VERTEXDATA |
-           (i << GEN6_VB0_INDEX_SHIFT);
-      } else {
-        dw0 = BRW_VB0_ACCESS_VERTEXDATA |
-           (i << BRW_VB0_INDEX_SHIFT);
+        OUT_BATCH(dw0 | (buffer->stride << BRW_VB0_PITCH_SHIFT));
+        OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->offset);
+        if (intel->gen >= 5) {
+           OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->bo->size - 1);
+        } else
+           OUT_BATCH(buffer->bo->size / buffer->stride);
+        OUT_BATCH(0); /* Instance data step rate */
+
+        brw->vb.current_buffers[i].handle = buffer->bo->handle;
+        brw->vb.current_buffers[i].offset = buffer->offset;
+        brw->vb.current_buffers[i].stride = buffer->stride;
       }
-
-      OUT_BATCH(dw0 |
-               (input->stride << BRW_VB0_PITCH_SHIFT));
-      OUT_RELOC(input->bo,
-               I915_GEM_DOMAIN_VERTEX, 0,
-               input->offset);
-      if (intel->gen >= 5) {
-        OUT_RELOC(input->bo,
-                  I915_GEM_DOMAIN_VERTEX, 0,
-                  input->bo->size - 1);
-      } else
-          OUT_BATCH(input->stride ? input->count : 0);
-      OUT_BATCH(0); /* Instance data step rate */
+      brw->vb.nr_current_buffers = i;
+      ADVANCE_BATCH();
    }
-   ADVANCE_BATCH();
 
    BEGIN_BATCH(1 + brw->vb.nr_enabled * 2);
-   OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | ((1 + brw->vb.nr_enabled * 2) - 2));
+   OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | (2*brw->vb.nr_enabled - 1));
    for (i = 0; i < brw->vb.nr_enabled; i++) {
       struct brw_vertex_element *input = brw->vb.enabled[i];
       uint32_t format = get_surface_type(input->glarray->Type,
@@ -545,15 +589,15 @@ static void brw_emit_vertices(struct brw_context *brw)
       }
 
       if (intel->gen >= 6) {
-        OUT_BATCH((i << GEN6_VE0_INDEX_SHIFT) |
+        OUT_BATCH((input->buffer << GEN6_VE0_INDEX_SHIFT) |
                   GEN6_VE0_VALID |
                   (format << BRW_VE0_FORMAT_SHIFT) |
-                  (0 << BRW_VE0_SRC_OFFSET_SHIFT));
+                  (input->offset << BRW_VE0_SRC_OFFSET_SHIFT));
       } else {
-        OUT_BATCH((i << BRW_VE0_INDEX_SHIFT) |
+        OUT_BATCH((input->buffer << BRW_VE0_INDEX_SHIFT) |
                   BRW_VE0_VALID |
                   (format << BRW_VE0_FORMAT_SHIFT) |
-                  (0 << BRW_VE0_SRC_OFFSET_SHIFT));
+                  (input->offset << BRW_VE0_SRC_OFFSET_SHIFT));
       }
 
       if (intel->gen >= 5)
@@ -568,7 +612,7 @@ static void brw_emit_vertices(struct brw_context *brw)
                     (comp3 << BRW_VE1_COMPONENT_3_SHIFT) |
                     ((i * 4) << BRW_VE1_DST_OFFSET_SHIFT));
    }
-   ADVANCE_BATCH();
+   CACHED_BATCH();
 }
 
 const struct brw_tracked_state brw_vertices = {
@@ -597,25 +641,20 @@ static void brw_prepare_indices(struct brw_context *brw)
 
    ib_type_size = get_size(index_buffer->type);
    ib_size = ib_type_size * index_buffer->count;
-   bufferobj = index_buffer->obj;;
+   bufferobj = index_buffer->obj;
 
    /* Turn into a proper VBO:
     */
    if (!_mesa_is_bufferobj(bufferobj)) {
-      brw->ib.start_vertex_offset = 0;
 
       /* Get new bufferobj, offset:
        */
-      get_space(brw, ib_size, &bo, &offset);
-
-      /* Straight upload
-       */
-      drm_intel_gem_bo_map_gtt(bo);
-      memcpy((char *)bo->virtual + offset, index_buffer->ptr, ib_size);
-      drm_intel_gem_bo_unmap_gtt(bo);
+      intel_upload_data(&brw->intel, index_buffer->ptr, ib_size, ib_type_size,
+                       &bo, &offset);
+      brw->ib.start_vertex_offset = offset / ib_type_size;
+      offset = 0;
    } else {
       offset = (GLuint) (unsigned long) index_buffer->ptr;
-      brw->ib.start_vertex_offset = 0;
 
       /* If the index buffer isn't aligned to its element size, we have to
        * rebase it into a temporary.
@@ -627,41 +666,35 @@ static void brw_prepare_indices(struct brw_context *brw)
                                                 bufferobj);
            map += offset;
 
-          get_space(brw, ib_size, &bo, &offset);
-
-          drm_intel_bo_subdata(bo, offset, ib_size, map);
+          intel_upload_data(&brw->intel, map, ib_size, ib_type_size,
+                            &bo, &offset);
+          brw->ib.start_vertex_offset = offset / ib_type_size;
+          offset = 0;
 
            ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobj);
        } else {
-         bo = intel_bufferobj_buffer(intel, intel_buffer_object(bufferobj),
-                                     INTEL_READ);
-         drm_intel_bo_reference(bo);
-
          /* Use CMD_3D_PRIM's start_vertex_offset to avoid re-uploading
           * the index buffer state when we're just moving the start index
           * of our drawing.
           */
          brw->ib.start_vertex_offset = offset / ib_type_size;
-         offset = 0;
-         ib_size = bo->size;
+
+         bo = intel_bufferobj_source(intel, intel_buffer_object(bufferobj),
+                                     &offset);
+         drm_intel_bo_reference(bo);
        }
    }
 
-   if (brw->ib.bo != bo ||
-       brw->ib.offset != offset ||
-       brw->ib.size != ib_size)
-   {
+   if (brw->ib.bo != bo || brw->ib.offset != offset) {
       drm_intel_bo_unreference(brw->ib.bo);
       brw->ib.bo = bo;
       brw->ib.offset = offset;
-      brw->ib.size = ib_size;
 
+      brw_add_validated_bo(brw, brw->ib.bo);
       brw->state.dirty.brw |= BRW_NEW_INDEX_BUFFER;
    } else {
       drm_intel_bo_unreference(bo);
    }
-
-   brw_add_validated_bo(brw, brw->ib.bo);
 }
 
 const struct brw_tracked_state brw_indices = {
@@ -681,29 +714,18 @@ static void brw_emit_index_buffer(struct brw_context *brw)
    if (index_buffer == NULL)
       return;
 
-   /* Emit the indexbuffer packet:
-    */
-   {
-      struct brw_indexbuffer ib;
-
-      memset(&ib, 0, sizeof(ib));
-
-      ib.header.bits.opcode = CMD_INDEX_BUFFER;
-      ib.header.bits.length = sizeof(ib)/4 - 2;
-      ib.header.bits.index_format = get_index_type(index_buffer->type);
-      ib.header.bits.cut_index_enable = 0;
-
-      BEGIN_BATCH(4);
-      OUT_BATCH( ib.header.dword );
-      OUT_RELOC(brw->ib.bo,
-               I915_GEM_DOMAIN_VERTEX, 0,
-               brw->ib.offset);
-      OUT_RELOC(brw->ib.bo,
-               I915_GEM_DOMAIN_VERTEX, 0,
-               brw->ib.offset + brw->ib.size - 1);
-      OUT_BATCH( 0 );
-      ADVANCE_BATCH();
-   }
+   BEGIN_BATCH(3);
+   OUT_BATCH(CMD_INDEX_BUFFER << 16 |
+             /* cut index enable << 10 */
+             get_index_type(index_buffer->type) << 8 |
+             1);
+   OUT_RELOC(brw->ib.bo,
+             I915_GEM_DOMAIN_VERTEX, 0,
+             brw->ib.offset);
+   OUT_RELOC(brw->ib.bo,
+             I915_GEM_DOMAIN_VERTEX, 0,
+            brw->ib.bo->size - 1);
+   ADVANCE_BATCH();
 }
 
 const struct brw_tracked_state brw_index_buffer = {
index 9a71e5377dfe5faf2dd065f04242c2ef83520266..30e3bd544693490fea9cfdcd6f39a2b2999ab71e 100644 (file)
@@ -41,7 +41,6 @@ extern "C" {
 #include "brw_context.h"
 #include "brw_eu.h"
 #include "brw_wm.h"
-#include "talloc.h"
 }
 #include "brw_fs.h"
 #include "../glsl/glsl_types.h"
@@ -56,7 +55,7 @@ brw_new_shader(struct gl_context *ctx, GLuint name, GLuint type)
 {
    struct brw_shader *shader;
 
-   shader = talloc_zero(NULL, struct brw_shader);
+   shader = rzalloc(NULL, struct brw_shader);
    if (shader) {
       shader->base.Type = type;
       shader->base.Name = name;
@@ -70,7 +69,7 @@ struct gl_shader_program *
 brw_new_shader_program(struct gl_context *ctx, GLuint name)
 {
    struct brw_shader_program *prog;
-   prog = talloc_zero(NULL, struct brw_shader_program);
+   prog = rzalloc(NULL, struct brw_shader_program);
    if (prog) {
       prog->base.Name = name;
       _mesa_init_shader_program(ctx, &prog->base);
@@ -96,11 +95,11 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
    struct brw_shader *shader =
       (struct brw_shader *)prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
    if (shader != NULL) {
-      void *mem_ctx = talloc_new(NULL);
+      void *mem_ctx = ralloc_context(NULL);
       bool progress;
 
       if (shader->ir)
-        talloc_free(shader->ir);
+        ralloc_free(shader->ir);
       shader->ir = new(shader) exec_list;
       clone_ir_list(mem_ctx, shader->ir, shader->base.ir);
 
@@ -150,7 +149,7 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
       validate_ir_tree(shader->ir);
 
       reparent_ir(shader->ir, shader->ir);
-      talloc_free(mem_ctx);
+      ralloc_free(mem_ctx);
    }
 
    if (!_mesa_ir_link_shader(ctx, prog))
@@ -237,8 +236,8 @@ fs_visitor::virtual_grf_alloc(int size)
         virtual_grf_array_size = 16;
       else
         virtual_grf_array_size *= 2;
-      virtual_grf_sizes = talloc_realloc(mem_ctx, virtual_grf_sizes,
-                                        int, virtual_grf_array_size);
+      virtual_grf_sizes = reralloc(mem_ctx, virtual_grf_sizes, int,
+                                  virtual_grf_array_size);
 
       /* This slot is always unused. */
       virtual_grf_sizes[0] = 0;
@@ -495,7 +494,7 @@ fs_visitor::emit_fragcoord_interpolation(ir_variable *ir)
    wpos.reg_offset++;
 
    /* gl_FragCoord.w: Already set up in emit_interpolation */
-   emit(fs_inst(BRW_OPCODE_MOV, wpos, this->wpos_w));
+   emit(fs_inst(BRW_OPCODE_MOV, wpos, this->pixel_w));
 
    return reg;
 }
@@ -662,14 +661,18 @@ fs_visitor::emit_math(fs_opcodes opcode, fs_reg dst, fs_reg src0, fs_reg src1)
    assert(opcode == FS_OPCODE_POW);
 
    if (intel->gen >= 6) {
-      /* Can't do hstride == 0 args to gen6 math, so expand it out. */
-      if (src0.file == UNIFORM) {
+      /* Can't do hstride == 0 args to gen6 math, so expand it out.
+       *
+       * The hardware ignores source modifiers (negate and abs) on math
+       * instructions, so we also move to a temp to set those up.
+       */
+      if (src0.file == UNIFORM || src0.abs || src0.negate) {
         fs_reg expanded = fs_reg(this, glsl_type::float_type);
         emit(fs_inst(BRW_OPCODE_MOV, expanded, src0));
         src0 = expanded;
       }
 
-      if (src1.file == UNIFORM) {
+      if (src1.file == UNIFORM || src1.abs || src1.negate) {
         fs_reg expanded = fs_reg(this, glsl_type::float_type);
         emit(fs_inst(BRW_OPCODE_MOV, expanded, src1));
         src1 = expanded;
@@ -1338,6 +1341,37 @@ fs_visitor::visit(ir_texture *ir)
    ir->coordinate->accept(this);
    fs_reg coordinate = this->result;
 
+   if (ir->offset != NULL) {
+      ir_constant *offset = ir->offset->as_constant();
+      assert(offset != NULL);
+
+      signed char offsets[3];
+      for (unsigned i = 0; i < ir->offset->type->vector_elements; i++)
+        offsets[i] = (signed char) offset->value.i[i];
+
+      /* Combine all three offsets into a single unsigned dword:
+       *
+       *    bits 11:8 - U Offset (X component)
+       *    bits  7:4 - V Offset (Y component)
+       *    bits  3:0 - R Offset (Z component)
+       */
+      unsigned offset_bits = 0;
+      for (unsigned i = 0; i < ir->offset->type->vector_elements; i++) {
+        const unsigned shift = 4 * (2 - i);
+        offset_bits |= (offsets[i] << shift) & (0xF << shift);
+      }
+
+      /* Explicitly set up the message header by copying g0 to msg reg m1. */
+      emit(fs_inst(BRW_OPCODE_MOV, fs_reg(MRF, 1, BRW_REGISTER_TYPE_UD),
+                                  fs_reg(GRF, 0, BRW_REGISTER_TYPE_UD)));
+
+      /* Then set the offset bits in DWord 2 of the message header. */
+      emit(fs_inst(BRW_OPCODE_MOV,
+                  fs_reg(retype(brw_vec1_reg(BRW_MESSAGE_REGISTER_FILE, 1, 2),
+                                BRW_REGISTER_TYPE_UD)),
+                  fs_reg(brw_imm_uw(offset_bits))));
+   }
+
    /* Should be lowered by do_lower_texture_projection */
    assert(!ir->projector);
 
@@ -1398,6 +1432,14 @@ fs_visitor::visit(ir_texture *ir)
       inst = emit_texture_gen5(ir, dst, coordinate);
    }
 
+   /* If there's an offset, we already set up m1.  To avoid the implied move,
+    * use the null register.  Otherwise, we want an implied move from g0.
+    */
+   if (ir->offset != NULL)
+      inst->src[0] = fs_reg(brw_null_reg());
+   else
+      inst->src[0] = fs_reg(retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW));
+
    inst->sampler = sampler;
 
    this->result = dst;
@@ -2066,7 +2108,7 @@ fs_visitor::emit_fb_writes()
    }
 
    for (int target = 0; target < c->key.nr_color_regions; target++) {
-      this->current_annotation = talloc_asprintf(this->mem_ctx,
+      this->current_annotation = ralloc_asprintf(this->mem_ctx,
                                                 "FB write target %d",
                                                 target);
       if (this->frag_color || this->frag_data) {
@@ -2244,7 +2286,7 @@ fs_visitor::generate_math(fs_inst *inst,
 }
 
 void
-fs_visitor::generate_tex(fs_inst *inst, struct brw_reg dst)
+fs_visitor::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src)
 {
    int msg_type = -1;
    int rlen = 4;
@@ -2302,7 +2344,7 @@ fs_visitor::generate_tex(fs_inst *inst, struct brw_reg dst)
    brw_SAMPLE(p,
              retype(dst, BRW_REGISTER_TYPE_UW),
              inst->base_mrf,
-             retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW),
+             src,
               SURF_INDEX_TEXTURE(inst->sampler),
              inst->sampler,
              WRITEMASK_XYZW,
@@ -2756,8 +2798,8 @@ void
 fs_visitor::calculate_live_intervals()
 {
    int num_vars = this->virtual_grf_next;
-   int *def = talloc_array(mem_ctx, int, num_vars);
-   int *use = talloc_array(mem_ctx, int, num_vars);
+   int *def = ralloc_array(mem_ctx, int, num_vars);
+   int *use = ralloc_array(mem_ctx, int, num_vars);
    int loop_depth = 0;
    int loop_start = 0;
    int bb_header_ip = 0;
@@ -2840,8 +2882,8 @@ fs_visitor::calculate_live_intervals()
       }
    }
 
-   talloc_free(this->virtual_grf_def);
-   talloc_free(this->virtual_grf_use);
+   ralloc_free(this->virtual_grf_def);
+   ralloc_free(this->virtual_grf_use);
    this->virtual_grf_def = def;
    this->virtual_grf_use = use;
 
@@ -3017,6 +3059,8 @@ fs_visitor::register_coalesce()
          inst->dst.type != inst->src[0].type)
         continue;
 
+      bool has_source_modifiers = inst->src[0].abs || inst->src[0].negate;
+
       /* Found a move of a GRF to a GRF.  Let's see if we can coalesce
        * them: check for no writes to either one until the exit of the
        * program.
@@ -3041,6 +3085,14 @@ fs_visitor::register_coalesce()
               break;
            }
         }
+
+        /* The gen6 MATH instruction can't handle source modifiers, so avoid
+         * coalescing those for now.  We should do something more specific.
+         */
+        if (intel->gen == 6 && scan_inst->is_math() && has_source_modifiers) {
+           interfered = true;
+           break;
+        }
       }
       if (interfered) {
         continue;
@@ -3358,20 +3410,25 @@ void
 fs_visitor::generate_code()
 {
    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];
    const char *last_annotation_string = NULL;
    ir_instruction *last_annotation_ir = NULL;
 
+   int if_stack_array_size = 16;
+   int loop_stack_array_size = 16;
+   int if_stack_depth = 0, loop_stack_depth = 0;
+   brw_instruction **if_stack =
+      rzalloc_array(this->mem_ctx, brw_instruction *, if_stack_array_size);
+   brw_instruction **loop_stack =
+      rzalloc_array(this->mem_ctx, brw_instruction *, loop_stack_array_size);
+   int *if_depth_in_loop =
+      rzalloc_array(this->mem_ctx, int, loop_stack_array_size);
+
+
    if (unlikely(INTEL_DEBUG & DEBUG_WM)) {
       printf("Native code for fragment shader %d:\n",
             ctx->Shader.CurrentFragmentProgram->Name);
    }
 
-   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;
@@ -3455,7 +3512,6 @@ fs_visitor::generate_code()
         break;
 
       case BRW_OPCODE_IF:
-        assert(if_stack_depth < 16);
         if (inst->src[0].file != BAD_FILE) {
            assert(intel->gen >= 6);
            if_stack[if_stack_depth] = brw_IF_gen6(p, inst->conditional_mod, src[0], src[1]);
@@ -3464,6 +3520,11 @@ fs_visitor::generate_code()
         }
         if_depth_in_loop[loop_stack_depth]++;
         if_stack_depth++;
+        if (if_stack_array_size <= if_stack_depth) {
+           if_stack_array_size *= 2;
+           if_stack = reralloc(this->mem_ctx, if_stack, brw_instruction *,
+                               if_stack_array_size);
+        }
         break;
 
       case BRW_OPCODE_ELSE:
@@ -3478,6 +3539,13 @@ fs_visitor::generate_code()
 
       case BRW_OPCODE_DO:
         loop_stack[loop_stack_depth++] = brw_DO(p, BRW_EXECUTE_8);
+        if (loop_stack_array_size <= loop_stack_depth) {
+           loop_stack_array_size *= 2;
+           loop_stack = reralloc(this->mem_ctx, loop_stack, brw_instruction *,
+                                 loop_stack_array_size);
+           if_depth_in_loop = reralloc(this->mem_ctx, if_depth_in_loop, int,
+                                       loop_stack_array_size);
+        }
         if_depth_in_loop[loop_stack_depth] = 0;
         break;
 
@@ -3540,7 +3608,7 @@ fs_visitor::generate_code()
       case FS_OPCODE_TEX:
       case FS_OPCODE_TXB:
       case FS_OPCODE_TXL:
-        generate_tex(inst, dst);
+        generate_tex(inst, dst, src[0]);
         break;
       case FS_OPCODE_DISCARD_NOT:
         generate_discard_not(inst, dst);
@@ -3596,6 +3664,10 @@ fs_visitor::generate_code()
       last_native_inst = p->nr_insn;
    }
 
+   ralloc_free(if_stack);
+   ralloc_free(loop_stack);
+   ralloc_free(if_depth_in_loop);
+
    brw_set_uip_jip(p);
 
    /* OK, while the INTEL_DEBUG=wm above is very nice for debugging FS
index f0497957bc4527627e49ba4da52f3d43994b1812..8352760acf7e9d07f499b2ead06967bb5dd2edaf 100644 (file)
@@ -41,7 +41,6 @@ extern "C" {
 #include "brw_context.h"
 #include "brw_eu.h"
 #include "brw_wm.h"
-#include "talloc.h"
 }
 #include "../glsl/glsl_types.h"
 #include "../glsl/ir.h"
@@ -83,13 +82,13 @@ enum fs_opcodes {
 
 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). */
+   /* Callers of this ralloc-based new need not call delete. It's
+    * easier to just ralloc_free 'ctx' (or any of its ancestors). */
    static void* operator new(size_t size, void *ctx)
    {
       void *node;
 
-      node = talloc_size(ctx, size);
+      node = ralloc_size(ctx, size);
       assert(node != NULL);
 
       return node;
@@ -193,13 +192,13 @@ static const fs_reg reg_null_d(ARF, BRW_ARF_NULL, BRW_REGISTER_TYPE_D);
 
 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). */
+   /* Callers of this ralloc-based new need not call delete. It's
+    * easier to just ralloc_free 'ctx' (or any of its ancestors). */
    static void* operator new(size_t size, void *ctx)
    {
       void *node;
 
-      node = talloc_zero_size(ctx, size);
+      node = rzalloc_size(ctx, size);
       assert(node != NULL);
 
       return node;
@@ -361,7 +360,7 @@ public:
       this->fp = brw->fragment_program;
       this->intel = &brw->intel;
       this->ctx = &intel->ctx;
-      this->mem_ctx = talloc_new(NULL);
+      this->mem_ctx = ralloc_context(NULL);
       this->shader = shader;
       this->fail = false;
       this->variable_ht = hash_table_ctor(0,
@@ -405,7 +404,7 @@ public:
 
    ~fs_visitor()
    {
-      talloc_free(this->mem_ctx);
+      ralloc_free(this->mem_ctx);
       hash_table_dtor(this->variable_ht);
    }
 
@@ -454,7 +453,7 @@ public:
    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);
+   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_not(fs_inst *inst, struct brw_reg temp);
    void generate_discard_and(fs_inst *inst, struct brw_reg temp);
index 20bfa4c3ea372ccd7f07aef72b07b852891c223b..7f3f52854d23fbf2e21cc9639effc9c2838c9093 100644 (file)
@@ -141,7 +141,7 @@ ir_channel_expressions_visitor::visit_leave(ir_assignment *ir)
       return visit_continue;
 
    if (!this->mem_ctx)
-      this->mem_ctx = talloc_parent(ir);
+      this->mem_ctx = ralloc_parent(ir);
 
    for (i = 0; i < expr->get_num_operands(); i++) {
       if (expr->operands[i]->type->is_vector()) {
index 078a349abdf1466c7d397a72c6f89264f91b86d8..f0277423170cd41cbe4c3db82725ae8efc64e45d 100644 (file)
@@ -41,7 +41,6 @@ extern "C" {
 #include "brw_context.h"
 #include "brw_eu.h"
 #include "brw_wm.h"
-#include "talloc.h"
 }
 #include "brw_fs.h"
 #include "../glsl/glsl_types.h"
@@ -234,8 +233,8 @@ fs_visitor::assign_regs()
       }
 
 
-      talloc_free(g);
-      talloc_free(regs);
+      ralloc_free(g);
+      ralloc_free(regs);
 
       return false;
    }
@@ -273,8 +272,8 @@ fs_visitor::assign_regs()
 
    this->grf_used = last_grf + 1;
 
-   talloc_free(g);
-   talloc_free(regs);
+   ralloc_free(g);
+   ralloc_free(regs);
 
    return true;
 }
index c8f0b27b76f1062e28f7d7512dfdc5ab2593e7c9..bff8f82f3f7d90331de394abf942a5e6efe18369 100644 (file)
@@ -39,7 +39,6 @@ extern "C" {
 #include "brw_context.h"
 #include "brw_eu.h"
 #include "brw_wm.h"
-#include "talloc.h"
 }
 #include "brw_fs.h"
 #include "../glsl/glsl_types.h"
@@ -129,7 +128,7 @@ public:
    instruction_scheduler(fs_visitor *v, void *mem_ctx, int virtual_grf_count)
    {
       this->v = v;
-      this->mem_ctx = talloc_new(mem_ctx);
+      this->mem_ctx = ralloc_context(mem_ctx);
       this->virtual_grf_count = virtual_grf_count;
       this->instructions.make_empty();
       this->instructions_to_schedule = 0;
@@ -137,7 +136,7 @@ public:
 
    ~instruction_scheduler()
    {
-      talloc_free(this->mem_ctx);
+      ralloc_free(this->mem_ctx);
    }
    void add_barrier_deps(schedule_node *n);
    void add_dep(schedule_node *before, schedule_node *after, int latency);
@@ -196,11 +195,11 @@ instruction_scheduler::add_dep(schedule_node *before, schedule_node *after,
       else
         before->child_array_size *= 2;
 
-      before->children = talloc_realloc(mem_ctx, before->children,
-                                       schedule_node *,
-                                       before->child_array_size);
-      before->child_latency = talloc_realloc(mem_ctx, before->child_latency,
-                                            int, before->child_array_size);
+      before->children = reralloc(mem_ctx, before->children,
+                                 schedule_node *,
+                                 before->child_array_size);
+      before->child_latency = reralloc(mem_ctx, before->child_latency,
+                                      int, before->child_array_size);
    }
 
    before->children[before->child_count] = after;
index 2be6b08b5c7a26b0c7688e087e5b967f68cea2c0..530ffa2658049e0d9e997f52ad766ed099620bdc 100644 (file)
@@ -69,7 +69,7 @@ public:
 
    ir_variable *components[4];
 
-   /** talloc_parent(this->var) -- the shader's talloc context. */
+   /** ralloc_parent(this->var) -- the shader's ralloc context. */
    void *mem_ctx;
 };
 
@@ -77,13 +77,13 @@ class ir_vector_reference_visitor : public ir_hierarchical_visitor {
 public:
    ir_vector_reference_visitor(void)
    {
-      this->mem_ctx = talloc_new(NULL);
+      this->mem_ctx = ralloc_context(NULL);
       this->variable_list.make_empty();
    }
 
    ~ir_vector_reference_visitor(void)
    {
-      talloc_free(mem_ctx);
+      ralloc_free(mem_ctx);
    }
 
    virtual ir_visitor_status visit(ir_variable *);
@@ -358,7 +358,7 @@ brw_do_vector_splitting(exec_list *instructions)
    if (refs.variable_list.is_empty())
       return false;
 
-   void *mem_ctx = talloc_new(NULL);
+   void *mem_ctx = ralloc_context(NULL);
 
    /* Replace the decls of the vectors to be split with their split
     * components.
@@ -368,10 +368,10 @@ brw_do_vector_splitting(exec_list *instructions)
       const struct glsl_type *type;
       type = glsl_type::get_instance(entry->var->type->base_type, 1, 1);
 
-      entry->mem_ctx = talloc_parent(entry->var);
+      entry->mem_ctx = ralloc_parent(entry->var);
 
       for (unsigned int i = 0; i < entry->var->type->vector_elements; i++) {
-        const char *name = talloc_asprintf(mem_ctx, "%s_%c",
+        const char *name = ralloc_asprintf(mem_ctx, "%s_%c",
                                            entry->var->name,
                                            "xyzw"[i]);
 
@@ -386,7 +386,7 @@ brw_do_vector_splitting(exec_list *instructions)
    ir_vector_splitting_visitor split(&refs.variable_list);
    visit_list_elements(&split, instructions);
 
-   talloc_free(mem_ctx);
+   ralloc_free(mem_ctx);
 
    return true;
 }
index 79afe19deba04d51ae1dfc694f1966fc54aa2c17..c768be23fa745df7e12213aa4911949e5fbac7b8 100644 (file)
@@ -74,7 +74,7 @@ static void upload_binding_table_pointers(struct brw_context *brw)
    struct intel_context *intel = &brw->intel;
 
    BEGIN_BATCH(6);
-   OUT_BATCH(CMD_BINDING_TABLE_PTRS << 16 | (6 - 2));
+   OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS << 16 | (6 - 2));
    OUT_BATCH(brw->vs.bind_bo_offset);
    OUT_BATCH(0); /* gs */
    OUT_BATCH(0); /* clip */
@@ -104,7 +104,7 @@ static void upload_gen6_binding_table_pointers(struct brw_context *brw)
    struct intel_context *intel = &brw->intel;
 
    BEGIN_BATCH(4);
-   OUT_BATCH(CMD_BINDING_TABLE_PTRS << 16 |
+   OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS << 16 |
             GEN6_BINDING_TABLE_MODIFY_VS |
             GEN6_BINDING_TABLE_MODIFY_GS |
             GEN6_BINDING_TABLE_MODIFY_PS |
@@ -142,7 +142,7 @@ static void upload_pipelined_state_pointers(struct brw_context *brw )
    }
 
    BEGIN_BATCH(7);
-   OUT_BATCH(CMD_PIPELINED_STATE_POINTERS << 16 | (7 - 2));
+   OUT_BATCH(_3DSTATE_PIPELINED_POINTERS << 16 | (7 - 2));
    OUT_RELOC(brw->vs.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
    if (brw->gs.prog_active)
       OUT_RELOC(brw->gs.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1);
@@ -151,7 +151,7 @@ static void upload_pipelined_state_pointers(struct brw_context *brw )
    OUT_RELOC(brw->clip.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1);
    OUT_RELOC(brw->sf.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
    OUT_RELOC(brw->wm.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
-   OUT_RELOC(brw->cc.state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
+   OUT_RELOC(brw->intel.batch.bo, I915_GEM_DOMAIN_INSTRUCTION, 0,
             brw->cc.state_offset);
    ADVANCE_BATCH();
 
@@ -301,16 +301,15 @@ const struct brw_tracked_state brw_depthbuffer = {
 
 static void upload_polygon_stipple(struct brw_context *brw)
 {
+   struct intel_context *intel = &brw->intel;
    struct gl_context *ctx = &brw->intel.ctx;
-   struct brw_polygon_stipple bps;
    GLuint i;
 
    if (!ctx->Polygon.StippleFlag)
       return;
 
-   memset(&bps, 0, sizeof(bps));
-   bps.header.opcode = _3DSTATE_POLY_STIPPLE_PATTERN;
-   bps.header.length = sizeof(bps)/4-2;
+   BEGIN_BATCH(33);
+   OUT_BATCH(_3DSTATE_POLY_STIPPLE_PATTERN << 16 | (33 - 2));
 
    /* Polygon stipple is provided in OpenGL order, i.e. bottom
     * row first.  If we're rendering to a window (i.e. the
@@ -321,14 +320,13 @@ static void upload_polygon_stipple(struct brw_context *brw)
     */
    if (ctx->DrawBuffer->Name == 0) {
       for (i = 0; i < 32; i++)
-         bps.stipple[i] = ctx->PolygonStipple[31 - i]; /* invert */
+         OUT_BATCH(ctx->PolygonStipple[31 - i]); /* invert */
    }
    else {
       for (i = 0; i < 32; i++)
-         bps.stipple[i] = ctx->PolygonStipple[i]; /* don't invert */
+        OUT_BATCH(ctx->PolygonStipple[i]);
    }
-
-   BRW_CACHED_BATCH_STRUCT(brw, &bps);
+   CACHED_BATCH();
 }
 
 const struct brw_tracked_state brw_polygon_stipple = {
@@ -347,15 +345,14 @@ const struct brw_tracked_state brw_polygon_stipple = {
 
 static void upload_polygon_stipple_offset(struct brw_context *brw)
 {
+   struct intel_context *intel = &brw->intel;
    struct gl_context *ctx = &brw->intel.ctx;
-   struct brw_polygon_stipple_offset bpso;
 
    if (!ctx->Polygon.StippleFlag)
       return;
 
-   memset(&bpso, 0, sizeof(bpso));
-   bpso.header.opcode = _3DSTATE_POLY_STIPPLE_OFFSET;
-   bpso.header.length = sizeof(bpso)/4-2;
+   BEGIN_BATCH(2);
+   OUT_BATCH(_3DSTATE_POLY_STIPPLE_OFFSET << 16 | (2-2));
 
    /* If we're drawing to a system window (ctx->DrawBuffer->Name == 0),
     * we have to invert the Y axis in order to match the OpenGL
@@ -365,16 +362,11 @@ static void upload_polygon_stipple_offset(struct brw_context *brw)
     * system works just fine, and there's no window system to
     * worry about.
     */
-   if (brw->intel.ctx.DrawBuffer->Name == 0) {
-      bpso.bits0.x_offset = 0;
-      bpso.bits0.y_offset = (32 - (ctx->DrawBuffer->Height & 31)) & 31;
-   }
-   else {
-      bpso.bits0.y_offset = 0;
-      bpso.bits0.x_offset = 0;
-   }
-
-   BRW_CACHED_BATCH_STRUCT(brw, &bpso);
+   if (brw->intel.ctx.DrawBuffer->Name == 0)
+      OUT_BATCH((32 - (ctx->DrawBuffer->Height & 31)) & 31);
+   else
+      OUT_BATCH(0);
+   CACHED_BATCH();
 }
 
 #define _NEW_WINDOW_POS 0x40000000
@@ -393,18 +385,17 @@ const struct brw_tracked_state brw_polygon_stipple_offset = {
  */
 static void upload_aa_line_parameters(struct brw_context *brw)
 {
+   struct intel_context *intel = &brw->intel;
    struct gl_context *ctx = &brw->intel.ctx;
-   struct brw_aa_line_parameters balp;
 
    if (!ctx->Line.SmoothFlag || !brw->has_aa_line_parameters)
       return;
 
+   OUT_BATCH(_3DSTATE_AA_LINE_PARAMETERS << 16 | (3 - 2));
    /* use legacy aa line coverage computation */
-   memset(&balp, 0, sizeof(balp));
-   balp.header.opcode = _3DSTATE_AA_LINE_PARAMETERS;
-   balp.header.length = sizeof(balp) / 4 - 2;
-   
-   BRW_CACHED_BATCH_STRUCT(brw, &balp);
+   OUT_BATCH(0);
+   OUT_BATCH(0);
+   CACHED_BATCH();
 }
 
 const struct brw_tracked_state brw_aa_line_parameters = {
@@ -422,28 +413,21 @@ const struct brw_tracked_state brw_aa_line_parameters = {
 
 static void upload_line_stipple(struct brw_context *brw)
 {
+   struct intel_context *intel = &brw->intel;
    struct gl_context *ctx = &brw->intel.ctx;
-   struct brw_line_stipple bls;
    GLfloat tmp;
    GLint tmpi;
 
    if (!ctx->Line.StippleFlag)
       return;
 
-   memset(&bls, 0, sizeof(bls));
-   bls.header.opcode = _3DSTATE_LINE_STIPPLE_PATTERN;
-   bls.header.length = sizeof(bls)/4 - 2;
-
-   bls.bits0.pattern = ctx->Line.StipplePattern;
-   bls.bits1.repeat_count = ctx->Line.StippleFactor;
-
+   BEGIN_BATCH(3);
+   OUT_BATCH(_3DSTATE_LINE_STIPPLE_PATTERN << 16 | (3 - 2));
+   OUT_BATCH(ctx->Line.StipplePattern);
    tmp = 1.0 / (GLfloat) ctx->Line.StippleFactor;
    tmpi = tmp * (1<<13);
-
-
-   bls.bits1.inverse_repeat_count = tmpi;
-
-   BRW_CACHED_BATCH_STRUCT(brw, &bls);
+   OUT_BATCH(tmpi << 16 | ctx->Line.StippleFactor);
+   CACHED_BATCH();
 }
 
 const struct brw_tracked_state brw_line_stipple = {
@@ -565,7 +549,7 @@ static void upload_state_base_address( struct brw_context *brw )
        BEGIN_BATCH(10);
        OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (10 - 2));
        OUT_BATCH(1); /* General state base address */
-       OUT_RELOC(intel->batch->buf, I915_GEM_DOMAIN_SAMPLER, 0,
+       OUT_RELOC(intel->batch.bo, I915_GEM_DOMAIN_SAMPLER, 0,
                 1); /* Surface state base address */
        OUT_BATCH(1); /* Dynamic state base address */
        OUT_BATCH(1); /* Indirect object base address */
@@ -579,7 +563,7 @@ static void upload_state_base_address( struct brw_context *brw )
        BEGIN_BATCH(8);
        OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (8 - 2));
        OUT_BATCH(1); /* General state base address */
-       OUT_RELOC(intel->batch->buf, I915_GEM_DOMAIN_SAMPLER, 0,
+       OUT_RELOC(intel->batch.bo, I915_GEM_DOMAIN_SAMPLER, 0,
                 1); /* Surface state base address */
        OUT_BATCH(1); /* Indirect object base address */
        OUT_BATCH(1); /* Instruction base address */
@@ -591,7 +575,7 @@ static void upload_state_base_address( struct brw_context *brw )
        BEGIN_BATCH(6);
        OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (6 - 2));
        OUT_BATCH(1); /* General state base address */
-       OUT_RELOC(intel->batch->buf, I915_GEM_DOMAIN_SAMPLER, 0,
+       OUT_RELOC(intel->batch.bo, I915_GEM_DOMAIN_SAMPLER, 0,
                 1); /* Surface state base address */
        OUT_BATCH(1); /* Indirect object base address */
        OUT_BATCH(1); /* General state upper bound */
index 94efa79109187bb5a8ff77e1a0717145111cc0e4..7d653327e301f63a5efd6d6ac4a97ca608d00c3e 100644 (file)
@@ -36,7 +36,7 @@
 #include "program/program.h"
 #include "program/programopt.h"
 #include "tnl/tnl.h"
-#include "talloc.h"
+#include "../glsl/ralloc.h"
 
 #include "brw_context.h"
 #include "brw_wm.h"
@@ -115,7 +115,7 @@ shader_error(struct gl_context *ctx, struct gl_program *prog, const char *msg)
    shader = _mesa_lookup_shader_program(ctx, prog->Id);
 
    if (shader) {
-      shader->InfoLog = talloc_strdup_append(shader->InfoLog, msg);
+      ralloc_strcat(&shader->InfoLog, msg);
       shader->LinkStatus = GL_FALSE;
    }
 }
index 656aad630a19024d84ef99a4b5197b986c6ea683..b41d05dd438adb07f0350543d153b72f1d9cbacc 100644 (file)
@@ -177,7 +177,7 @@ brw_end_query(struct gl_context *ctx, struct gl_query_object *q)
          ADVANCE_BATCH();
       }
 
-      intel_batchbuffer_flush(intel->batch);
+      intel_batchbuffer_flush(intel);
    } else {
       /* Flush the batchbuffer in case it has writes to our query BO.
        * Have later queries write to a new query BO so that further rendering
@@ -185,7 +185,7 @@ brw_end_query(struct gl_context *ctx, struct gl_query_object *q)
        */
       if (query->bo) {
         brw_emit_query_end(brw);
-        intel_batchbuffer_flush(intel->batch);
+        intel_batchbuffer_flush(intel);
 
         drm_intel_bo_unreference(brw->query.bo);
         brw->query.bo = NULL;
index 4bb93e73369ee287c01211dbb313ba81bdd686bf..86b0caa4a4ec90eb59eb5401e0ecb2391feb176b 100644 (file)
@@ -164,26 +164,18 @@ void brw_destroy_caches( struct brw_context *brw );
 /***********************************************************************
  * brw_state_batch.c
  */
-#define BRW_BATCH_STRUCT(brw, s) intel_batchbuffer_data(brw->intel.batch, (s), \
+#define BRW_BATCH_STRUCT(brw, s) intel_batchbuffer_data(&brw->intel, (s), \
                                                        sizeof(*(s)), false)
-#define BRW_CACHED_BATCH_STRUCT(brw, s) brw_cached_batch_struct( brw, (s), sizeof(*(s)) )
 
-GLboolean brw_cached_batch_struct( struct brw_context *brw,
-                                  const void *data,
-                                  GLuint sz );
-void brw_destroy_batch_cache( struct brw_context *brw );
-void brw_clear_batch_cache( struct brw_context *brw );
 void *brw_state_batch(struct brw_context *brw,
                      int size,
                      int alignment,
-                     drm_intel_bo **out_bo,
                      uint32_t *out_offset);
 
 /* brw_wm_surface_state.c */
 void brw_create_constant_surface(struct brw_context *brw,
                                 drm_intel_bo *bo,
                                 int width,
-                                drm_intel_bo **out_bo,
                                 uint32_t *out_offset);
 
 #endif
index a21af13caa328b3c9388407bc3488e98a08fbdff..213c7a38d8c732ac637e6f167eb200315af75f82 100644 (file)
   *   Keith Whitwell <keith@tungstengraphics.com>
   */
      
-
-
 #include "brw_state.h"
 #include "intel_batchbuffer.h"
 #include "main/imports.h"
 
-
-
-/* A facility similar to the data caching code above, which aims to
- * prevent identical commands being issued repeatedly.
- */
-GLboolean brw_cached_batch_struct( struct brw_context *brw,
-                                  const void *data,
-                                  GLuint sz )
-{
-   struct brw_cached_batch_item *item = brw->cached_batch_items;
-   struct header *newheader = (struct header *)data;
-
-   if (brw->emit_state_always) {
-      intel_batchbuffer_data(brw->intel.batch, data, sz, false);
-      return GL_TRUE;
-   }
-
-   while (item) {
-      if (item->header->opcode == newheader->opcode) {
-        if (item->sz == sz && memcmp(item->header, newheader, sz) == 0)
-           return GL_FALSE;
-        if (item->sz != sz) {
-           free(item->header);
-           item->header = malloc(sz);
-           item->sz = sz;
-        }
-        goto emit;
-      }
-      item = item->next;
-   }
-
-   assert(!item);
-   item = CALLOC_STRUCT(brw_cached_batch_item);
-   item->header = malloc(sz);
-   item->sz = sz;
-   item->next = brw->cached_batch_items;
-   brw->cached_batch_items = item;
-
- emit:
-   memcpy(item->header, newheader, sz);
-   intel_batchbuffer_data(brw->intel.batch, data, sz, false);
-   return GL_TRUE;
-}
-
-void brw_clear_batch_cache( struct brw_context *brw )
-{
-   struct brw_cached_batch_item *item = brw->cached_batch_items;
-
-   while (item) {
-      struct brw_cached_batch_item *next = item->next;
-      free((void *)item->header);
-      free(item);
-      item = next;
-   }
-
-   brw->cached_batch_items = NULL;
-}
-
-void brw_destroy_batch_cache( struct brw_context *brw )
-{
-   brw_clear_batch_cache(brw);
-}
-
 /**
  * Allocates a block of space in the batchbuffer for indirect state.
  *
@@ -116,13 +51,12 @@ void *
 brw_state_batch(struct brw_context *brw,
                int size,
                int alignment,
-               drm_intel_bo **out_bo,
                uint32_t *out_offset)
 {
-   struct intel_batchbuffer *batch = brw->intel.batch;
+   struct intel_batchbuffer *batch = &brw->intel.batch;
    uint32_t offset;
 
-   assert(size < batch->buf->size);
+   assert(size < batch->bo->size);
    offset = ROUND_DOWN_TO(batch->state_batch_offset - size, alignment);
 
    /* If allocating from the top would wrap below the batchbuffer, or
@@ -130,19 +64,13 @@ brw_state_batch(struct brw_context *brw,
     * space, then flush and try again.
     */
    if (batch->state_batch_offset < size ||
-       offset < batch->ptr - batch->map + batch->reserved_space) {
-      intel_batchbuffer_flush(batch);
+       offset < 4*batch->used + batch->reserved_space) {
+      intel_batchbuffer_flush(&brw->intel);
       offset = ROUND_DOWN_TO(batch->state_batch_offset - size, alignment);
    }
 
    batch->state_batch_offset = offset;
 
-   if (*out_bo != batch->buf) {
-      drm_intel_bo_unreference(*out_bo);
-      drm_intel_bo_reference(batch->buf);
-      *out_bo = batch->buf;
-   }
-
    *out_offset = offset;
-   return batch->map + offset;
+   return batch->map + (offset>>2);
 }
index 7045888ad4a034ae44ed7b0bdfd0d959cbab62e1..01eeb19a6842a64223f55ff209c243c5c49f25e1 100644 (file)
@@ -431,8 +431,6 @@ brw_clear_cache(struct brw_context *brw, struct brw_cache *cache)
 void
 brw_state_cache_check_size(struct brw_context *brw)
 {
-   DBG("%s (n_items=%d)\n", __FUNCTION__, brw->cache.n_items);
-
    /* un-tuned guess.  Each object is generally a page, so 1000 of them is 4 MB of
     * state cache.
     */
index e26288747123966204db5359b8d3e3664d3ad543..fdce79da2f4a0ba72bdbcc9fde44cfcc4980fc91 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include "main/mtypes.h"
+#include "intel_batchbuffer.h"
 
 #include "brw_context.h"
 #include "brw_defines.h"
@@ -54,7 +55,8 @@ state_out(const char *name, void *data, uint32_t hw_offset, int index,
 
 /** Generic, undecoded state buffer debug printout */
 static void
-state_struct_out(const char *name, drm_intel_bo *buffer, unsigned int state_size)
+state_struct_out(const char *name, drm_intel_bo *buffer,
+                unsigned int offset, unsigned int size)
 {
    int i;
 
@@ -62,8 +64,8 @@ state_struct_out(const char *name, drm_intel_bo *buffer, unsigned int state_size
       return;
 
    drm_intel_bo_map(buffer, GL_FALSE);
-   for (i = 0; i < state_size / 4; i++) {
-      state_out(name, buffer->virtual, buffer->offset, i,
+   for (i = 0; i < size / 4; i++) {
+      state_out(name, buffer->virtual + offset, buffer->offset + offset, i,
                "dword %d\n", i);
    }
    drm_intel_bo_unmap(buffer);
@@ -98,21 +100,25 @@ get_965_surface_format(unsigned int surface_format)
 
 static void dump_wm_surface_state(struct brw_context *brw)
 {
+   dri_bo *bo;
+   GLubyte *base;
    int i;
 
+   bo = brw->intel.batch.bo;
+   drm_intel_bo_map(bo, GL_FALSE);
+   base = bo->virtual;
+
    for (i = 0; i < brw->wm.nr_surfaces; i++) {
-      drm_intel_bo *surf_bo = brw->wm.surf_bo[i];
       unsigned int surfoff;
       struct brw_surface_state *surf;
       char name[20];
 
-      if (surf_bo == NULL) {
+      if (brw->wm.surf_offset[i] == 0) {
         fprintf(stderr, "WM SURF%d: NULL\n", i);
         continue;
       }
-      drm_intel_bo_map(surf_bo, GL_FALSE);
-      surfoff = surf_bo->offset + brw->wm.surf_offset[i];
-      surf = (struct brw_surface_state *)(surf_bo->virtual + brw->wm.surf_offset[i]);
+      surfoff = bo->offset + brw->wm.surf_offset[i];
+      surf = (struct brw_surface_state *)(base + brw->wm.surf_offset[i]);
 
       sprintf(name, "WM SURF%d", i);
       state_out(name, surf, surfoff, 0, "%s %s\n",
@@ -127,9 +133,8 @@ static void dump_wm_surface_state(struct brw_context *brw)
                surf->ss4.min_lod);
       state_out(name, surf, surfoff, 5, "x,y offset: %d,%d\n",
                surf->ss5.x_offset, surf->ss5.y_offset);
-
-      drm_intel_bo_unmap(surf_bo);
    }
+   drm_intel_bo_unmap(bo);
 }
 
 
@@ -280,13 +285,14 @@ static void dump_cc_state(struct brw_context *brw)
    const char *name = "CC";
    struct gen6_color_calc_state *cc;
    uint32_t cc_off;
+   dri_bo *bo = brw->intel.batch.bo;
 
-   if (brw->cc.state_bo == NULL)
+   if (brw->cc.state_offset == 0)
        return;
 
-   drm_intel_bo_map(brw->cc.state_bo, GL_FALSE);
-   cc = brw->cc.state_bo->virtual;
-   cc_off = brw->cc.state_bo->offset;
+   drm_intel_bo_map(bo, GL_FALSE);
+   cc = bo->virtual;
+   cc_off = bo->offset;
 
    state_out(name, cc, cc_off, 0, "alpha test format %s, round disable %d, stencil ref %d,"
                "bf stencil ref %d\n",
@@ -300,7 +306,7 @@ static void dump_cc_state(struct brw_context *brw)
    state_out(name, cc, cc_off, 4, "constant blue %f\n", cc->constant_b);
    state_out(name, cc, cc_off, 5, "constant alpha %f\n", cc->constant_a);
    
-   drm_intel_bo_unmap(brw->cc.state_bo);
+   drm_intel_bo_unmap(bo);
 
 }
 
@@ -369,26 +375,29 @@ void brw_debug_batch(struct intel_context *intel)
 {
    struct brw_context *brw = brw_context(&intel->ctx);
 
-   state_struct_out("WM bind", brw->wm.bind_bo, 4 * brw->wm.nr_surfaces);
+   state_struct_out("WM bind",
+                   brw->intel.batch.bo,
+                   brw->wm.bind_bo_offset,
+                   4 * brw->wm.nr_surfaces);
    dump_wm_surface_state(brw);
    dump_wm_sampler_state(brw);
 
    if (intel->gen < 6)
-       state_struct_out("VS", brw->vs.state_bo, sizeof(struct brw_vs_unit_state));
+       state_struct_out("VS", brw->vs.state_bo, 0, sizeof(struct brw_vs_unit_state));
    brw_debug_prog("VS prog", brw->vs.prog_bo);
 
    if (intel->gen < 6)
-       state_struct_out("GS", brw->gs.state_bo, sizeof(struct brw_gs_unit_state));
+       state_struct_out("GS", brw->gs.state_bo, 0, sizeof(struct brw_gs_unit_state));
    brw_debug_prog("GS prog", brw->gs.prog_bo);
 
    if (intel->gen < 6) {
-       state_struct_out("SF", brw->sf.state_bo, sizeof(struct brw_sf_unit_state));
+       state_struct_out("SF", brw->sf.state_bo, 0, sizeof(struct brw_sf_unit_state));
        brw_debug_prog("SF prog", brw->sf.prog_bo);
    }
    dump_sf_viewport_state(brw);
 
    if (intel->gen < 6)
-       state_struct_out("WM", brw->wm.state_bo, sizeof(struct brw_wm_unit_state));
+       state_struct_out("WM", brw->wm.state_bo, 0, sizeof(struct brw_wm_unit_state));
    brw_debug_prog("WM prog", brw->wm.prog_bo);
 
    if (intel->gen >= 6) {
index eba4411ca702a77e369cc80df47b7bd30260dfef..2d6fb37355dc1a9914489bac5305cfa69e2efa9f 100644 (file)
@@ -176,17 +176,16 @@ void brw_init_state( struct brw_context *brw )
 void brw_destroy_state( struct brw_context *brw )
 {
    brw_destroy_caches(brw);
-   brw_destroy_batch_cache(brw);
 }
 
 /***********************************************************************
  */
 
-static GLboolean check_state( const struct brw_state_flags *a,
-                             const struct brw_state_flags *b )
+static GLuint check_state( const struct brw_state_flags *a,
+                          const struct brw_state_flags *b )
 {
-   return ((a->mesa & b->mesa) ||
-          (a->brw & b->brw) ||
+   return ((a->mesa & b->mesa) |
+          (a->brw & b->brw) |
           (a->cache & b->cache));
 }
 
@@ -233,7 +232,6 @@ static struct dirty_bit_map mesa_bits[] = {
    DEFINE_BIT(_NEW_MODELVIEW),
    DEFINE_BIT(_NEW_PROJECTION),
    DEFINE_BIT(_NEW_TEXTURE_MATRIX),
-   DEFINE_BIT(_NEW_ACCUM),
    DEFINE_BIT(_NEW_COLOR),
    DEFINE_BIT(_NEW_DEPTH),
    DEFINE_BIT(_NEW_EVAL),
@@ -279,6 +277,10 @@ static struct dirty_bit_map brw_bits[] = {
    DEFINE_BIT(BRW_NEW_VERTICES),
    DEFINE_BIT(BRW_NEW_BATCH),
    DEFINE_BIT(BRW_NEW_DEPTH_BUFFER),
+   DEFINE_BIT(BRW_NEW_NR_WM_SURFACES),
+   DEFINE_BIT(BRW_NEW_NR_VS_SURFACES),
+   DEFINE_BIT(BRW_NEW_VS_CONSTBUF),
+   DEFINE_BIT(BRW_NEW_WM_CONSTBUF),
    {0, 0, 0}
 };
 
@@ -349,7 +351,7 @@ void brw_validate_state( struct brw_context *brw )
    state->mesa |= brw->intel.NewGLState;
    brw->intel.NewGLState = 0;
 
-   brw_add_validated_bo(brw, intel->batch->buf);
+   brw_add_validated_bo(brw, intel->batch.bo);
 
    if (intel->gen >= 6) {
       atoms = gen6_atoms;
@@ -375,14 +377,9 @@ void brw_validate_state( struct brw_context *brw )
       brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM;
    }
 
-   if (state->mesa == 0 &&
-       state->cache == 0 &&
-       state->brw == 0)
+   if ((state->mesa | state->cache | state->brw) == 0)
       return;
 
-   if (brw->state.dirty.brw & BRW_NEW_CONTEXT)
-      brw_clear_batch_cache(brw);
-
    brw->intel.Fallback = GL_FALSE; /* boolean, not bitfield */
 
    /* do prepare stage for all atoms */
index e878da3850dba165d97080fe2529fb5794e2569b..d28d9abcb3362af0f4afc64b73624705c656ed6d 100644 (file)
 #include "brw_util.h"
 #include "brw_defines.h"
 
-GLuint brw_count_bits(uint64_t val)
-{
-   GLuint i;
-   for (i = 0; val ; val >>= 1)
-      if (val & 1)
-        i++;
-   return i;
-}
-
-
 GLuint brw_translate_blend_equation( GLenum mode )
 {
    switch (mode) {
index 04f3175d3e1b0e8bfc60547d49c3f3ce43c66da6..940a871550295e37c63286893e3fb08acb33f510 100644 (file)
 
 #include "main/mtypes.h"
 
-extern GLuint brw_count_bits(uint64_t val);
+#ifdef __GNUC__
+#define brw_count_bits(v) __builtin_popcount(v)
+#else
+static inline GLuint brw_count_bits(uint64_t v)
+{
+       return _mesa_popcount(v>>32) + _mesa_popcount(v&0xffffffff);
+}
+#endif
 extern GLuint brw_parameter_list_state_flags(struct gl_program_parameter_list *paramList);
 extern GLuint brw_translate_blend_factor( GLenum factor );
 extern GLuint brw_translate_blend_equation( GLenum mode );
index b0b05445eb980292fb263391cdb0d5ed41fa7fb7..48cf265e51bc13a53eebca859a9791d46afcdf23 100644 (file)
@@ -124,13 +124,11 @@ brw_update_vs_constant_surface( struct gl_context *ctx,
     * it.
     */
    if (brw->vs.const_bo == NULL) {
-      drm_intel_bo_unreference(brw->vs.surf_bo[surf]);
-      brw->vs.surf_bo[surf] = NULL;
+      brw->vs.surf_offset[surf] = 0;
       return;
    }
 
    brw_create_constant_surface(brw, brw->vs.const_bo, params->NumParameters,
-                              &brw->vs.surf_bo[surf],
                               &brw->vs.surf_offset[surf]);
 }
 
@@ -166,11 +164,10 @@ static void upload_vs_surfaces(struct brw_context *brw)
 
    /* BRW_NEW_NR_VS_SURFACES */
    if (brw->vs.nr_surfaces == 0) {
-      if (brw->vs.bind_bo) {
-        drm_intel_bo_unreference(brw->vs.bind_bo);
-        brw->vs.bind_bo = NULL;
+      if (brw->vs.bind_bo_offset) {
         brw->state.dirty.brw |= BRW_NEW_BINDING_TABLE;
       }
+      brw->vs.bind_bo_offset = 0;
       return;
    }
 
@@ -180,15 +177,11 @@ static void upload_vs_surfaces(struct brw_context *brw)
     * space for the binding table. (once we have vs samplers)
     */
    bind = brw_state_batch(brw, sizeof(uint32_t) * BRW_VS_MAX_SURF,
-                         32, &brw->vs.bind_bo, &brw->vs.bind_bo_offset);
+                         32, &brw->vs.bind_bo_offset);
 
    for (i = 0; i < BRW_VS_MAX_SURF; i++) {
       /* BRW_NEW_VS_CONSTBUF */
-      if (brw->vs.surf_bo[i]) {
-        bind[i] = brw->vs.surf_offset[i];
-      } else {
-        bind[i] = 0;
-      }
+      bind[i] = brw->vs.surf_offset[i];
    }
 
    brw->state.dirty.brw |= BRW_NEW_BINDING_TABLE;
index 100a21b59d723b0830c8bb7a32dbf5af9bc4d603..152ee141568d6ad7062c27ec0da7ba4a06fc4595 100644 (file)
@@ -73,15 +73,11 @@ static void brw_destroy_context( struct intel_context *intel )
       free(brw->wm.compile_data);
    }
 
-   for (i = 0; i < brw->state.nr_color_regions; i++)
-      intel_region_release(&brw->state.color_regions[i]);
-   brw->state.nr_color_regions = 0;
    intel_region_release(&brw->state.depth_region);
 
    dri_bo_release(&brw->curbe.curbe_bo);
    dri_bo_release(&brw->vs.prog_bo);
    dri_bo_release(&brw->vs.state_bo);
-   dri_bo_release(&brw->vs.bind_bo);
    dri_bo_release(&brw->vs.const_bo);
    dri_bo_release(&brw->gs.prog_bo);
    dri_bo_release(&brw->gs.state_bo);
@@ -93,16 +89,12 @@ static void brw_destroy_context( struct intel_context *intel )
    dri_bo_release(&brw->sf.vp_bo);
    for (i = 0; i < BRW_MAX_TEX_UNIT; i++)
       dri_bo_release(&brw->wm.sdc_bo[i]);
-   dri_bo_release(&brw->wm.bind_bo);
-   for (i = 0; i < BRW_WM_MAX_SURF; i++)
-      dri_bo_release(&brw->wm.surf_bo[i]);
    dri_bo_release(&brw->wm.sampler_bo);
    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);
    dri_bo_release(&brw->cc.blend_state_bo);
    dri_bo_release(&brw->cc.depth_stencil_state_bo);
@@ -122,20 +114,14 @@ static void brw_set_draw_region( struct intel_context *intel,
                                  GLuint num_color_regions)
 {
    struct brw_context *brw = brw_context(&intel->ctx);
-   GLuint i;
 
    /* release old color/depth regions */
    if (brw->state.depth_region != depth_region)
       brw->state.dirty.brw |= BRW_NEW_DEPTH_BUFFER;
-   for (i = 0; i < brw->state.nr_color_regions; i++)
-       intel_region_release(&brw->state.color_regions[i]);
    intel_region_release(&brw->state.depth_region);
 
    /* reference new color/depth regions */
-   for (i = 0; i < num_color_regions; i++)
-       intel_region_reference(&brw->state.color_regions[i], color_regions[i]);
    intel_region_reference(&brw->state.depth_region, depth_region);
-   brw->state.nr_color_regions = num_color_regions;
 }
 
 
@@ -173,14 +159,7 @@ static void brw_new_batch( struct intel_context *intel )
    brw->state.dirty.brw |= ~0;
    brw->state.dirty.cache |= ~0;
 
-   /* Move to the end of the current upload buffer so that we'll force choosing
-    * a new buffer next time.
-    */
-   if (brw->vb.upload.bo != NULL) {
-      drm_intel_bo_unreference(brw->vb.upload.bo);
-      brw->vb.upload.bo = NULL;
-      brw->vb.upload.offset = 0;
-   }
+   brw->vb.nr_current_buffers = 0;
 }
 
 static void brw_invalidate_state( struct intel_context *intel, GLuint new_state )
index 656501b4f79c33993bf7325ece53056be0c10595..ee8212f6f1641139e0406f5b0263780810afd321 100644 (file)
@@ -431,7 +431,8 @@ static void brw_wm_populate_key( struct brw_context *brw,
       key->render_to_fbo = ctx->DrawBuffer->Name != 0;
    }
 
-   key->nr_color_regions = brw->state.nr_color_regions;
+   /* _NEW_BUFFERS */
+   key->nr_color_regions = ctx->DrawBuffer->_NumColorDrawBuffers;
 
    /* CACHE_NEW_VS_PROG */
    key->vp_outputs_written = brw->vs.prog_data->outputs_written;
index e9ef635bca2d2489da2bad8d009edfe8df0054b3..5b5afc4626b5b02c7f665bfdd6d761f27ef9e522 100644 (file)
@@ -47,7 +47,6 @@ struct brw_wm_unit_key {
    unsigned int dispatch_grf_start_reg;
 
    unsigned int curbe_offset;
-   unsigned int urb_size;
 
    unsigned int nr_surfaces, sampler_count;
    GLboolean uses_depth, computes_depth, uses_kill, is_glsl;
@@ -98,9 +97,6 @@ wm_unit_populate_key(struct brw_context *brw, struct brw_wm_unit_key *key)
    key->dispatch_grf_start_reg = brw->wm.prog_data->first_curbe_grf;
    key->total_scratch = brw->wm.prog_data->total_scratch;
 
-   /* BRW_NEW_URB_FENCE */
-   key->urb_size = brw->urb.vsize;
-
    /* BRW_NEW_CURBE_OFFSETS */
    key->curbe_offset = brw->curbe.wm_start;
 
index a372554555c4c669e04311cd38de1012fa53deae..1010d9f6f9c23781ef374554e00eee3d07d4a5d0 100644 (file)
@@ -188,47 +188,43 @@ brw_update_texture_surface( struct gl_context *ctx, GLuint unit )
    struct intel_texture_object *intelObj = intel_texture_object(tObj);
    struct gl_texture_image *firstImage = tObj->Image[0][tObj->BaseLevel];
    const GLuint surf_index = SURF_INDEX_TEXTURE(unit);
-   struct brw_surface_state surf;
-   void *map;
+   struct brw_surface_state *surf;
 
-   memset(&surf, 0, sizeof(surf));
+   surf = brw_state_batch(brw, sizeof(*surf), 32,
+                        &brw->wm.surf_offset[surf_index]);
+   memset(surf, 0, sizeof(*surf));
 
-   surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
-   surf.ss0.surface_type = translate_tex_target(tObj->Target);
-   surf.ss0.surface_format = translate_tex_format(firstImage->TexFormat,
+   surf->ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
+   surf->ss0.surface_type = translate_tex_target(tObj->Target);
+   surf->ss0.surface_format = translate_tex_format(firstImage->TexFormat,
                                                  firstImage->InternalFormat,
                                                  tObj->DepthMode, tObj->sRGBDecode);
 
    /* This is ok for all textures with channel width 8bit or less:
     */
-/*    surf.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */
-   surf.ss1.base_addr = intelObj->mt->region->buffer->offset; /* reloc */
+/*    surf->ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */
+   surf->ss1.base_addr = intelObj->mt->region->buffer->offset; /* reloc */
 
-   surf.ss2.mip_count = intelObj->_MaxLevel - tObj->BaseLevel;
-   surf.ss2.width = firstImage->Width - 1;
-   surf.ss2.height = firstImage->Height - 1;
-   brw_set_surface_tiling(&surf, intelObj->mt->region->tiling);
-   surf.ss3.pitch = (intelObj->mt->region->pitch * intelObj->mt->cpp) - 1;
-   surf.ss3.depth = firstImage->Depth - 1;
+   surf->ss2.mip_count = intelObj->_MaxLevel - tObj->BaseLevel;
+   surf->ss2.width = firstImage->Width - 1;
+   surf->ss2.height = firstImage->Height - 1;
+   brw_set_surface_tiling(surf, intelObj->mt->region->tiling);
+   surf->ss3.pitch = (intelObj->mt->region->pitch * intelObj->mt->cpp) - 1;
+   surf->ss3.depth = firstImage->Depth - 1;
 
-   surf.ss4.min_lod = 0;
+   surf->ss4.min_lod = 0;
  
    if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
-      surf.ss0.cube_pos_x = 1;
-      surf.ss0.cube_pos_y = 1;
-      surf.ss0.cube_pos_z = 1;
-      surf.ss0.cube_neg_x = 1;
-      surf.ss0.cube_neg_y = 1;
-      surf.ss0.cube_neg_z = 1;
+      surf->ss0.cube_pos_x = 1;
+      surf->ss0.cube_pos_y = 1;
+      surf->ss0.cube_pos_z = 1;
+      surf->ss0.cube_neg_x = 1;
+      surf->ss0.cube_neg_y = 1;
+      surf->ss0.cube_neg_z = 1;
    }
 
-   map = brw_state_batch(brw, sizeof(surf), 32,
-                        &brw->wm.surf_bo[surf_index],
-                        &brw->wm.surf_offset[surf_index]);
-   memcpy(map, &surf, sizeof(surf));
-
    /* Emit relocation to surface contents */
-   drm_intel_bo_emit_reloc(brw->wm.surf_bo[surf_index],
+   drm_intel_bo_emit_reloc(brw->intel.batch.bo,
                           brw->wm.surf_offset[surf_index] +
                           offsetof(struct brw_surface_state, ss1),
                           intelObj->mt->region->buffer, 0,
@@ -243,41 +239,38 @@ void
 brw_create_constant_surface(struct brw_context *brw,
                            drm_intel_bo *bo,
                            int width,
-                           drm_intel_bo **out_bo,
                            uint32_t *out_offset)
 {
    struct intel_context *intel = &brw->intel;
    const GLint w = width - 1;
-   struct brw_surface_state surf;
-   void *map;
+   struct brw_surface_state *surf;
 
-   memset(&surf, 0, sizeof(surf));
+   surf = brw_state_batch(brw, sizeof(*surf), 32, out_offset);
+   memset(surf, 0, sizeof(*surf));
 
-   surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
-   surf.ss0.surface_type = BRW_SURFACE_BUFFER;
-   surf.ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT;
+   surf->ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
+   surf->ss0.surface_type = BRW_SURFACE_BUFFER;
+   surf->ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT;
 
    if (intel->gen >= 6)
-      surf.ss0.render_cache_read_write = 1;
+      surf->ss0.render_cache_read_write = 1;
 
    assert(bo);
-   surf.ss1.base_addr = bo->offset; /* reloc */
-
-   surf.ss2.width = w & 0x7f;            /* bits 6:0 of size or width */
-   surf.ss2.height = (w >> 7) & 0x1fff;  /* bits 19:7 of size or width */
-   surf.ss3.depth = (w >> 20) & 0x7f;    /* bits 26:20 of size or width */
-   surf.ss3.pitch = (width * 16) - 1; /* ignored?? */
-   brw_set_surface_tiling(&surf, I915_TILING_NONE); /* tiling now allowed */
+   surf->ss1.base_addr = bo->offset; /* reloc */
 
-   map = brw_state_batch(brw, sizeof(surf), 32, out_bo, out_offset);
-   memcpy(map, &surf, sizeof(surf));
+   surf->ss2.width = w & 0x7f;            /* bits 6:0 of size or width */
+   surf->ss2.height = (w >> 7) & 0x1fff;  /* bits 19:7 of size or width */
+   surf->ss3.depth = (w >> 20) & 0x7f;    /* bits 26:20 of size or width */
+   surf->ss3.pitch = (width * 16) - 1; /* ignored?? */
+   brw_set_surface_tiling(surf, I915_TILING_NONE); /* tiling now allowed */
 
    /* Emit relocation to surface contents.  Section 5.1.1 of the gen4
     * bspec ("Data Cache") says that the data cache does not exist as
     * a separate cache and is just the sampler cache.
     */
-   drm_intel_bo_emit_reloc(*out_bo, (*out_offset +
-                                    offsetof(struct brw_surface_state, ss1)),
+   drm_intel_bo_emit_reloc(brw->intel.batch.bo,
+                          (*out_offset +
+                           offsetof(struct brw_surface_state, ss1)),
                           bo, 0,
                           I915_GEM_DOMAIN_SAMPLER, 0);
 }
@@ -356,16 +349,14 @@ static void upload_wm_constant_surface(struct brw_context *brw )
     * it.
     */
    if (brw->wm.const_bo == 0) {
-      if (brw->wm.surf_bo[surf] != NULL) {
-        drm_intel_bo_unreference(brw->wm.surf_bo[surf]);
-        brw->wm.surf_bo[surf] = NULL;
+      if (brw->wm.surf_offset[surf]) {
         brw->state.dirty.brw |= BRW_NEW_WM_SURFACES;
+        brw->wm.surf_offset[surf] = 0;
       }
       return;
    }
 
    brw_create_constant_surface(brw, brw->wm.const_bo, params->NumParameters,
-                              &brw->wm.surf_bo[surf],
                               &brw->wm.surf_offset[surf]);
    brw->state.dirty.brw |= BRW_NEW_WM_SURFACES;
 }
@@ -384,33 +375,23 @@ static void
 brw_update_null_renderbuffer_surface(struct brw_context *brw, unsigned int unit)
 {
    struct intel_context *intel = &brw->intel;
-   struct brw_surface_state surf;
-   void *map;
+   struct brw_surface_state *surf;
 
-   memset(&surf, 0, sizeof(surf));
-
-   surf.ss0.surface_type = BRW_SURFACE_NULL;
-   surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
-   surf.ss1.base_addr = 0;
+   surf = brw_state_batch(brw, sizeof(*surf), 32,
+                        &brw->wm.surf_offset[unit]);
+   memset(surf, 0, sizeof(*surf));
 
-   surf.ss2.width = 0;
-   surf.ss2.height = 0;
-   brw_set_surface_tiling(&surf, I915_TILING_NONE);
-   surf.ss3.pitch = 0;
+   surf->ss0.surface_type = BRW_SURFACE_NULL;
+   surf->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
 
    if (intel->gen < 6) {
       /* _NEW_COLOR */
-      surf.ss0.color_blend = 0;
-      surf.ss0.writedisable_red =   1;
-      surf.ss0.writedisable_green = 1;
-      surf.ss0.writedisable_blue =  1;
-      surf.ss0.writedisable_alpha = 1;
+      surf->ss0.color_blend = 0;
+      surf->ss0.writedisable_red =   1;
+      surf->ss0.writedisable_green = 1;
+      surf->ss0.writedisable_blue =  1;
+      surf->ss0.writedisable_alpha = 1;
    }
-
-   map = brw_state_batch(brw, sizeof(surf), 32,
-                        &brw->wm.surf_bo[unit],
-                        &brw->wm.surf_offset[unit]);
-   memcpy(map, &surf, sizeof(surf));
 }
 
 /**
@@ -427,10 +408,11 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
    struct gl_context *ctx = &intel->ctx;
    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
    struct intel_region *region = irb->region;
-   struct brw_surface_state surf;
-   void *map;
+   struct brw_surface_state *surf;
 
-   memset(&surf, 0, sizeof(surf));
+   surf = brw_state_batch(brw, sizeof(*surf), 32,
+                         &brw->wm.surf_offset[unit]);
+   memset(surf, 0, sizeof(*surf));
 
    switch (irb->Base.Format) {
    case MESA_FORMAT_XRGB8888:
@@ -441,21 +423,24 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
        * cases where GL_DST_ALPHA (or GL_ONE_MINUS_DST_ALPHA) is
        * used.
        */
-      surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+      surf->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
       break;
    case MESA_FORMAT_SARGB8:
       /* without GL_EXT_framebuffer_sRGB we shouldn't bind sRGB
         surfaces to the blend/update as sRGB */
-      surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+      if (ctx->Color.sRGBEnabled)
+        surf->ss0.surface_format = brw_format_for_mesa_format[irb->Base.Format];
+      else
+        surf->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
       break;
    default:
-      surf.ss0.surface_format = brw_format_for_mesa_format[irb->Base.Format];
-      assert(surf.ss0.surface_format != 0);
+      surf->ss0.surface_format = brw_format_for_mesa_format[irb->Base.Format];
+      assert(surf->ss0.surface_format != 0);
    }
 
-   surf.ss0.surface_type = BRW_SURFACE_2D;
+   surf->ss0.surface_type = BRW_SURFACE_2D;
    if (region->tiling == I915_TILING_NONE) {
-      surf.ss1.base_addr = (region->draw_x +
+      surf->ss1.base_addr = (region->draw_x +
                            region->draw_y * region->pitch) * region->cpp;
    } else {
       uint32_t tile_base, tile_x, tile_y;
@@ -479,43 +464,38 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
       /* Note that the low bits of these fields are missing, so
        * there's the possibility of getting in trouble.
        */
-      surf.ss1.base_addr = tile_base;
-      surf.ss5.x_offset = tile_x / 4;
-      surf.ss5.y_offset = tile_y / 2;
+      surf->ss1.base_addr = tile_base;
+      surf->ss5.x_offset = tile_x / 4;
+      surf->ss5.y_offset = tile_y / 2;
    }
-   surf.ss1.base_addr += region->buffer->offset; /* reloc */
+   surf->ss1.base_addr += region->buffer->offset; /* reloc */
 
-   surf.ss2.width = rb->Width - 1;
-   surf.ss2.height = rb->Height - 1;
-   brw_set_surface_tiling(&surf, region->tiling);
-   surf.ss3.pitch = (region->pitch * region->cpp) - 1;
+   surf->ss2.width = rb->Width - 1;
+   surf->ss2.height = rb->Height - 1;
+   brw_set_surface_tiling(surf, region->tiling);
+   surf->ss3.pitch = (region->pitch * region->cpp) - 1;
 
    if (intel->gen < 6) {
       /* _NEW_COLOR */
-      surf.ss0.color_blend = (!ctx->Color._LogicOpEnabled &&
+      surf->ss0.color_blend = (!ctx->Color._LogicOpEnabled &&
                              (ctx->Color.BlendEnabled & (1 << unit)));
-      surf.ss0.writedisable_red =   !ctx->Color.ColorMask[unit][0];
-      surf.ss0.writedisable_green = !ctx->Color.ColorMask[unit][1];
-      surf.ss0.writedisable_blue =  !ctx->Color.ColorMask[unit][2];
+      surf->ss0.writedisable_red =   !ctx->Color.ColorMask[unit][0];
+      surf->ss0.writedisable_green = !ctx->Color.ColorMask[unit][1];
+      surf->ss0.writedisable_blue =  !ctx->Color.ColorMask[unit][2];
       /* As mentioned above, disable writes to the alpha component when the
        * renderbuffer is XRGB.
        */
       if (ctx->DrawBuffer->Visual.alphaBits == 0)
-        surf.ss0.writedisable_alpha = 1;
+        surf->ss0.writedisable_alpha = 1;
       else
-        surf.ss0.writedisable_alpha = !ctx->Color.ColorMask[unit][3];
+        surf->ss0.writedisable_alpha = !ctx->Color.ColorMask[unit][3];
    }
 
-   map = brw_state_batch(brw, sizeof(surf), 32,
-                        &brw->wm.surf_bo[unit],
-                        &brw->wm.surf_offset[unit]);
-   memcpy(map, &surf, sizeof(surf));
-
-   drm_intel_bo_emit_reloc(brw->wm.surf_bo[unit],
+   drm_intel_bo_emit_reloc(brw->intel.batch.bo,
                           brw->wm.surf_offset[unit] +
                           offsetof(struct brw_surface_state, ss1),
                           region->buffer,
-                          surf.ss1.base_addr - region->buffer->offset,
+                          surf->ss1.base_addr - region->buffer->offset,
                           I915_GEM_DOMAIN_RENDER,
                           I915_GEM_DOMAIN_RENDER);
 }
@@ -533,6 +513,11 @@ prepare_wm_surfaces(struct brw_context *brw)
         struct intel_renderbuffer *irb = intel_renderbuffer(rb);
         struct intel_region *region = irb ? irb->region : NULL;
 
+        if (region == NULL || region->buffer == NULL) {
+           brw->intel.Fallback = GL_TRUE; /* boolean, not bitfield */
+           return;
+        }
+
         brw_add_validated_bo(brw, region->buffer);
         nr_surfaces = SURF_INDEX_DRAW(i) + 1;
       }
@@ -598,8 +583,7 @@ upload_wm_surfaces(struct brw_context *brw)
       if (texUnit->_ReallyEnabled) {
         brw_update_texture_surface(ctx, i);
       } else {
-         drm_intel_bo_unreference(brw->wm.surf_bo[surf]);
-         brw->wm.surf_bo[surf] = NULL;
+         brw->wm.surf_offset[surf] = 0;
       }
    }
 
@@ -632,16 +616,11 @@ brw_wm_upload_binding_table(struct brw_context *brw)
     * space for the binding table.
     */
    bind = brw_state_batch(brw, sizeof(uint32_t) * BRW_WM_MAX_SURF,
-                         32, &brw->wm.bind_bo, &brw->wm.bind_bo_offset);
+                         32, &brw->wm.bind_bo_offset);
 
    for (i = 0; i < BRW_WM_MAX_SURF; i++) {
       /* BRW_NEW_WM_SURFACES */
       bind[i] = brw->wm.surf_offset[i];
-      if (brw->wm.surf_bo[i]) {
-        bind[i] = brw->wm.surf_offset[i];
-      } else {
-        bind[i] = 0;
-      }
    }
 
    brw->state.dirty.brw |= BRW_NEW_BINDING_TABLE;
index f51afa40716d4675038775fc4ad84d54070289d5..d1648a102d4690f63f2f63dd191159db67699c24 100644 (file)
@@ -254,14 +254,14 @@ prepare_color_calc_state(struct brw_context *brw)
 
    color_calc_state_populate_key(brw, &key);
 
-   drm_intel_bo_unreference(brw->cc.state_bo);
-   brw->cc.state_bo = brw_search_cache(&brw->cache, BRW_COLOR_CALC_STATE,
+   drm_intel_bo_unreference(brw->cc.color_calc_state_bo);
+   brw->cc.color_calc_state_bo = brw_search_cache(&brw->cache, BRW_COLOR_CALC_STATE,
                                       &key, sizeof(key),
                                       NULL, 0,
                                       NULL);
 
-   if (brw->cc.state_bo == NULL)
-      brw->cc.state_bo = color_calc_state_create_from_key(brw, &key);
+   if (brw->cc.color_calc_state_bo == NULL)
+      brw->cc.color_calc_state_bo = color_calc_state_create_from_key(brw, &key);
 }
 
 const struct brw_tracked_state gen6_color_calc_state = {
@@ -281,14 +281,14 @@ static void upload_cc_state_pointers(struct brw_context *brw)
    OUT_BATCH(_3DSTATE_CC_STATE_POINTERS << 16 | (4 - 2));
    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);
+   OUT_RELOC(brw->cc.color_calc_state_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 1);
    ADVANCE_BATCH();
 }
 
 
 static void prepare_cc_state_pointers(struct brw_context *brw)
 {
-   brw_add_validated_bo(brw, brw->cc.state_bo);
+   brw_add_validated_bo(brw, brw->cc.color_calc_state_bo);
    brw_add_validated_bo(brw, brw->cc.blend_state_bo);
    brw_add_validated_bo(brw, brw->cc.depth_stencil_state_bo);
 }
index f27782935d42ac3930dfe5401d205891a90263b3..50a5ad38c6fcb1d936a4030ff7e2a6fa62dc275c 100644 (file)
@@ -54,6 +54,8 @@ get_attr_override(struct brw_context *brw, int fs_attr, int two_side_color)
     * be FRAG_ATTRIB_*.
     */
    for (i = 1; i < vs_attr; i++) {
+      if (i == VERT_RESULT_PSIZ)
+        continue;
       if (brw->vs.prog_data->outputs_written & BITFIELD64_BIT(i))
         attr_index++;
    }
@@ -207,7 +209,7 @@ upload_sf_state(struct brw_context *brw)
         ctx->Point._Attenuated))
       dw4 |= GEN6_SF_USE_STATE_POINT_WIDTH;
 
-   dw4 |= U_FIXED(CLAMP(ctx->Point.Size, 0.125, 225.875), 3) <<
+   dw4 |= U_FIXED(CLAMP(ctx->Point.Size, 0.125, 255.875), 3) <<
       GEN6_SF_POINT_WIDTH_SHIFT;
    if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT)
       dw1 |= GEN6_SF_POINT_SPRITE_LOWERLEFT;
index 67ce8a4da026dcbda6d06aca81b34784c02da8bd..42b4f923e0cbb0df6d39d03352ce849b63e56c56 100644 (file)
 
 #include "intel_context.h"
 #include "intel_batchbuffer.h"
+#include "intel_buffer_objects.h"
 #include "intel_decode.h"
 #include "intel_reg.h"
 #include "intel_bufmgr.h"
 #include "intel_buffers.h"
 
-void
-intel_batchbuffer_reset(struct intel_batchbuffer *batch)
+struct cached_batch_item {
+   struct cached_batch_item *next;
+   uint16_t header;
+   uint16_t size;
+};
+
+static void clear_cache( struct intel_context *intel )
 {
-   struct intel_context *intel = batch->intel;
+   struct cached_batch_item *item = intel->batch.cached_items;
 
-   if (batch->buf != NULL) {
-      drm_intel_bo_unreference(batch->buf);
-      batch->buf = NULL;
+   while (item) {
+      struct cached_batch_item *next = item->next;
+      free(item);
+      item = next;
    }
 
-   batch->buf = drm_intel_bo_alloc(intel->bufmgr, "batchbuffer",
-                                  intel->maxBatchSize, 4096);
-   drm_intel_gem_bo_map_gtt(batch->buf);
-   batch->map = batch->buf->virtual;
-
-   batch->size = intel->maxBatchSize;
-   batch->ptr = batch->map;
-   batch->reserved_space = BATCH_RESERVED;
-   batch->dirty_state = ~0;
-   batch->state_batch_offset = batch->size;
+   intel->batch.cached_items = NULL;
 }
 
-struct intel_batchbuffer *
-intel_batchbuffer_alloc(struct intel_context *intel)
+void
+intel_batchbuffer_reset(struct intel_context *intel)
 {
-   struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1);
+   if (intel->batch.bo != NULL) {
+      drm_intel_bo_unreference(intel->batch.bo);
+      intel->batch.bo = NULL;
+   }
+   clear_cache(intel);
 
-   batch->intel = intel;
-   intel_batchbuffer_reset(batch);
+   intel->batch.bo = drm_intel_bo_alloc(intel->bufmgr, "batchbuffer",
+                                       intel->maxBatchSize, 4096);
 
-   return batch;
+   intel->batch.reserved_space = BATCH_RESERVED;
+   intel->batch.state_batch_offset = intel->batch.bo->size;
+   intel->batch.used = 0;
 }
 
 void
-intel_batchbuffer_free(struct intel_batchbuffer *batch)
+intel_batchbuffer_free(struct intel_context *intel)
 {
-   if (batch->map) {
-      drm_intel_gem_bo_unmap_gtt(batch->buf);
-      batch->map = NULL;
-   }
-   dri_bo_unreference(batch->buf);
-   batch->buf = NULL;
-   free(batch);
+   drm_intel_bo_unreference(intel->batch.bo);
+   clear_cache(intel);
 }
 
 
-
 /* TODO: Push this whole function into bufmgr.
  */
 static void
-do_flush_locked(struct intel_batchbuffer *batch, GLuint used)
+do_flush_locked(struct intel_context *intel)
 {
-   struct intel_context *intel = batch->intel;
+   struct intel_batchbuffer *batch = &intel->batch;
    int ret = 0;
-   int x_off = 0, y_off = 0;
-
-   drm_intel_gem_bo_unmap_gtt(batch->buf);
-
-   batch->ptr = NULL;
 
    if (!intel->intelScreen->no_hw) {
       int ring;
 
-      if (intel->gen < 6 || !intel->batch->is_blit) {
+      if (intel->gen < 6 || !batch->is_blit) {
         ring = I915_EXEC_RENDER;
       } else {
         ring = I915_EXEC_BLT;
       }
 
-      drm_intel_bo_mrb_exec(batch->buf, used, NULL, 0,
-                           (x_off & 0xffff) | (y_off << 16), ring);
+      ret = drm_intel_bo_subdata(batch->bo, 0, 4*batch->used, batch->map);
+      if (ret == 0 && batch->state_batch_offset != batch->bo->size) {
+        ret = drm_intel_bo_subdata(batch->bo,
+                                   batch->state_batch_offset,
+                                   batch->bo->size - batch->state_batch_offset,
+                                   (char *)batch->map + batch->state_batch_offset);
+      }
+
+      if (ret == 0)
+        ret = drm_intel_bo_mrb_exec(batch->bo, 4*batch->used, NULL, 0, 0, ring);
    }
 
    if (unlikely(INTEL_DEBUG & DEBUG_BATCH)) {
-      drm_intel_bo_map(batch->buf, GL_FALSE);
-      intel_decode(batch->buf->virtual, used / 4, batch->buf->offset,
+      intel_decode(batch->map, batch->used,
+                  batch->bo->offset,
                   intel->intelScreen->deviceID, GL_TRUE);
-      drm_intel_bo_unmap(batch->buf);
 
       if (intel->vtbl.debug_batch != NULL)
         intel->vtbl.debug_batch(intel);
@@ -122,80 +122,54 @@ do_flush_locked(struct intel_batchbuffer *batch, GLuint used)
 }
 
 void
-_intel_batchbuffer_flush(struct intel_batchbuffer *batch, const char *file,
-                        int line)
+_intel_batchbuffer_flush(struct intel_context *intel,
+                        const char *file, int line)
 {
-   struct intel_context *intel = batch->intel;
-   GLuint used = batch->ptr - batch->map;
-
-   if (intel->first_post_swapbuffers_batch == NULL) {
-      intel->first_post_swapbuffers_batch = intel->batch->buf;
-      drm_intel_bo_reference(intel->first_post_swapbuffers_batch);
-   }
-
-   if (used == 0)
+   if (intel->batch.used == 0)
       return;
 
    if (unlikely(INTEL_DEBUG & DEBUG_BATCH))
       fprintf(stderr, "%s:%d: Batchbuffer flush with %db used\n", file, line,
-             used);
+             4*intel->batch.used);
 
-   batch->reserved_space = 0;
+   intel->batch.reserved_space = 0;
 
    if (intel->always_flush_cache) {
-      intel_batchbuffer_emit_mi_flush(batch);
-      used = batch->ptr - batch->map;
-   }
-
-   /* Round batchbuffer usage to 2 DWORDs. */
-
-   if ((used & 4) == 0) {
-      *(GLuint *) (batch->ptr) = 0; /* noop */
-      batch->ptr += 4;
-      used = batch->ptr - batch->map;
+      intel_batchbuffer_emit_mi_flush(intel);
    }
 
    /* Mark the end of the buffer. */
-   *(GLuint *) (batch->ptr) = MI_BATCH_BUFFER_END;
-   batch->ptr += 4;
-   used = batch->ptr - batch->map;
-   assert (used <= batch->buf->size);
-
-   /* Workaround for recursive batchbuffer flushing: If the window is
-    * moved, we can get into a case where we try to flush during a
-    * flush.  What happens is that when we try to grab the lock for
-    * the first flush, we detect that the window moved which then
-    * causes another flush (from the intel_draw_buffer() call in
-    * intelUpdatePageFlipping()).  To work around this we reset the
-    * batchbuffer tail pointer before trying to get the lock.  This
-    * prevent the nested buffer flush, but a better fix would be to
-    * avoid that in the first place. */
-   batch->ptr = batch->map;
+   intel_batchbuffer_emit_dword(intel, MI_BATCH_BUFFER_END);
+   if (intel->batch.used & 1) {
+      /* Round batchbuffer usage to 2 DWORDs. */
+      intel_batchbuffer_emit_dword(intel, MI_NOOP);
+   }
 
    if (intel->vtbl.finish_batch)
       intel->vtbl.finish_batch(intel);
 
+   intel_upload_finish(intel);
+
    /* Check that we didn't just wrap our batchbuffer at a bad time. */
    assert(!intel->no_batch_wrap);
 
-   do_flush_locked(batch, used);
+   do_flush_locked(intel);
 
    if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) {
       fprintf(stderr, "waiting for idle\n");
-      drm_intel_bo_map(batch->buf, GL_TRUE);
-      drm_intel_bo_unmap(batch->buf);
+      drm_intel_bo_wait_rendering(intel->batch.bo);
    }
 
    /* Reset the buffer:
     */
-   intel_batchbuffer_reset(batch);
+   intel_batchbuffer_reset(intel);
 }
 
 
 /*  This is the only way buffers get added to the validate list.
  */
 GLboolean
-intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
+intel_batchbuffer_emit_reloc(struct intel_context *intel,
                              drm_intel_bo *buffer,
                              uint32_t read_domains, uint32_t write_domain,
                             uint32_t delta)
@@ -204,58 +178,98 @@ intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
 
    assert(delta < buffer->size);
 
-   if (batch->ptr - batch->map > batch->buf->size)
-    printf ("bad relocation ptr %p map %p offset %d size %lu\n",
-           batch->ptr, batch->map, batch->ptr - batch->map, batch->buf->size);
-   ret = drm_intel_bo_emit_reloc(batch->buf, batch->ptr - batch->map,
+   ret = drm_intel_bo_emit_reloc(intel->batch.bo, 4*intel->batch.used,
                                 buffer, delta,
                                 read_domains, write_domain);
+   assert(ret == 0);
+   (void)ret;
 
    /*
     * Using the old buffer offset, write in what the right data would be, in case
     * the buffer doesn't move and we can short-circuit the relocation processing
     * in the kernel
     */
-   intel_batchbuffer_emit_dword (batch, buffer->offset + delta);
+   intel_batchbuffer_emit_dword(intel, buffer->offset + delta);
 
    return GL_TRUE;
 }
 
 GLboolean
-intel_batchbuffer_emit_reloc_fenced(struct intel_batchbuffer *batch,
+intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel,
                                    drm_intel_bo *buffer,
-                                   uint32_t read_domains, uint32_t write_domain,
+                                   uint32_t read_domains,
+                                   uint32_t write_domain,
                                    uint32_t delta)
 {
    int ret;
 
    assert(delta < buffer->size);
 
-   if (batch->ptr - batch->map > batch->buf->size)
-    printf ("bad relocation ptr %p map %p offset %d size %lu\n",
-           batch->ptr, batch->map, batch->ptr - batch->map, batch->buf->size);
-   ret = drm_intel_bo_emit_reloc_fence(batch->buf, batch->ptr - batch->map,
+   ret = drm_intel_bo_emit_reloc_fence(intel->batch.bo, 4*intel->batch.used,
                                       buffer, delta,
                                       read_domains, write_domain);
+   assert(ret == 0);
+   (void)ret;
 
    /*
     * Using the old buffer offset, write in what the right data would
     * be, in case the buffer doesn't move and we can short-circuit the
     * relocation processing in the kernel
     */
-   intel_batchbuffer_emit_dword (batch, buffer->offset + delta);
+   intel_batchbuffer_emit_dword(intel, buffer->offset + delta);
 
    return GL_TRUE;
 }
 
 void
-intel_batchbuffer_data(struct intel_batchbuffer *batch,
+intel_batchbuffer_data(struct intel_context *intel,
                        const void *data, GLuint bytes, bool is_blit)
 {
    assert((bytes & 3) == 0);
-   intel_batchbuffer_require_space(batch, bytes, is_blit);
-   __memcpy(batch->ptr, data, bytes);
-   batch->ptr += bytes;
+   intel_batchbuffer_require_space(intel, bytes, is_blit);
+   __memcpy(intel->batch.map + intel->batch.used, data, bytes);
+   intel->batch.used += bytes >> 2;
+}
+
+void
+intel_batchbuffer_cached_advance(struct intel_context *intel)
+{
+   struct cached_batch_item **prev = &intel->batch.cached_items, *item;
+   uint32_t sz = (intel->batch.used - intel->batch.emit) * sizeof(uint32_t);
+   uint32_t *start = intel->batch.map + intel->batch.emit;
+   uint16_t op = *start >> 16;
+
+   while (*prev) {
+      uint32_t *old;
+
+      item = *prev;
+      old = intel->batch.map + item->header;
+      if (op == *old >> 16) {
+        if (item->size == sz && memcmp(old, start, sz) == 0) {
+           if (prev != &intel->batch.cached_items) {
+              *prev = item->next;
+              item->next = intel->batch.cached_items;
+              intel->batch.cached_items = item;
+           }
+           intel->batch.used = intel->batch.emit;
+           return;
+        }
+
+        goto emit;
+      }
+      prev = &item->next;
+   }
+
+   item = malloc(sizeof(struct cached_batch_item));
+   if (item == NULL)
+      return;
+
+   item->next = intel->batch.cached_items;
+   intel->batch.cached_items = item;
+
+emit:
+   item->size = sz;
+   item->header = intel->batch.emit;
 }
 
 /* Emit a pipelined flush to either flush render and texture cache for
@@ -265,12 +279,10 @@ intel_batchbuffer_data(struct intel_batchbuffer *batch,
  * This is also used for the always_flush_cache driconf debug option.
  */
 void
-intel_batchbuffer_emit_mi_flush(struct intel_batchbuffer *batch)
+intel_batchbuffer_emit_mi_flush(struct intel_context *intel)
 {
-   struct intel_context *intel = batch->intel;
-
    if (intel->gen >= 6) {
-      if (intel->batch->is_blit) {
+      if (intel->batch.is_blit) {
         BEGIN_BATCH_BLT(4);
         OUT_BATCH(MI_FLUSH_DW);
         OUT_BATCH(0);
index 635708587a6af9f81ae9b699e9041498d2af88f3..a0a5c9841c6a854e063a4ae73c2fc4ed5549d917 100644 (file)
@@ -7,71 +7,37 @@
 #include "intel_bufmgr.h"
 #include "intel_reg.h"
 
-#define BATCH_SZ 16384
 #define BATCH_RESERVED 16
 
+void intel_batchbuffer_reset(struct intel_context *intel);
+void intel_batchbuffer_free(struct intel_context *intel);
 
-struct intel_batchbuffer
-{
-   struct intel_context *intel;
-
-   drm_intel_bo *buf;
-
-   GLubyte *map;
-   GLubyte *ptr;
-
-   GLuint size;
-   uint32_t state_batch_offset;
-
-#ifdef DEBUG
-   /** Tracking of BEGIN_BATCH()/OUT_BATCH()/ADVANCE_BATCH() debugging */
-   struct {
-      GLuint total;
-      GLubyte *start_ptr;
-   } emit;
-#endif
-
-   bool is_blit;
-   GLuint dirty_state;
-   GLuint reserved_space;
-};
-
-struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context
-                                                  *intel);
-
-void intel_batchbuffer_free(struct intel_batchbuffer *batch);
-
-
-void _intel_batchbuffer_flush(struct intel_batchbuffer *batch,
+void _intel_batchbuffer_flush(struct intel_context *intel,
                              const char *file, int line);
 
-#define intel_batchbuffer_flush(batch) \
-       _intel_batchbuffer_flush(batch, __FILE__, __LINE__)
+#define intel_batchbuffer_flush(intel) \
+       _intel_batchbuffer_flush(intel, __FILE__, __LINE__)
 
-void intel_batchbuffer_reset(struct intel_batchbuffer *batch);
 
 
 /* Unlike bmBufferData, this currently requires the buffer be mapped.
  * Consider it a convenience function wrapping multple
  * intel_buffer_dword() calls.
  */
-void intel_batchbuffer_data(struct intel_batchbuffer *batch,
+void intel_batchbuffer_data(struct intel_context *intel,
                             const void *data, GLuint bytes, bool is_blit);
 
-void intel_batchbuffer_release_space(struct intel_batchbuffer *batch,
-                                     GLuint bytes);
-
-GLboolean intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
+GLboolean intel_batchbuffer_emit_reloc(struct intel_context *intel,
                                        drm_intel_bo *buffer,
                                       uint32_t read_domains,
                                       uint32_t write_domain,
                                       uint32_t offset);
-GLboolean intel_batchbuffer_emit_reloc_fenced(struct intel_batchbuffer *batch,
+GLboolean intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel,
                                              drm_intel_bo *buffer,
                                              uint32_t read_domains,
                                              uint32_t write_domain,
                                              uint32_t offset);
-void intel_batchbuffer_emit_mi_flush(struct intel_batchbuffer *batch);
+void intel_batchbuffer_emit_mi_flush(struct intel_context *intel);
 
 static INLINE uint32_t float_as_int(float f)
 {
@@ -90,93 +56,93 @@ static INLINE uint32_t float_as_int(float f)
  * work...
  */
 static INLINE GLint
-intel_batchbuffer_space(struct intel_batchbuffer *batch)
+intel_batchbuffer_space(struct intel_context *intel)
 {
-   return (batch->state_batch_offset - batch->reserved_space) -
-      (batch->ptr - batch->map);
+   return (intel->batch.state_batch_offset - intel->batch.reserved_space) - intel->batch.used*4;
 }
 
 
 static INLINE void
-intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, GLuint dword)
+intel_batchbuffer_emit_dword(struct intel_context *intel, GLuint dword)
 {
 #ifdef DEBUG
-   assert(intel_batchbuffer_space(batch) >= 4);
+   assert(intel_batchbuffer_space(intel) >= 4);
 #endif
-   *(GLuint *) (batch->ptr) = dword;
-   batch->ptr += 4;
+   intel->batch.map[intel->batch.used++] = dword;
 }
 
 static INLINE void
-intel_batchbuffer_emit_float(struct intel_batchbuffer *batch, float f)
+intel_batchbuffer_emit_float(struct intel_context *intel, float f)
 {
-   intel_batchbuffer_emit_dword(batch, float_as_int(f));
+   intel_batchbuffer_emit_dword(intel, float_as_int(f));
 }
 
 static INLINE void
-intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
+intel_batchbuffer_require_space(struct intel_context *intel,
                                 GLuint sz, int is_blit)
 {
 
-   if (batch->intel->gen >= 6 && batch->is_blit != is_blit &&
-       batch->ptr != batch->map) {
-      intel_batchbuffer_flush(batch);
+   if (intel->gen >= 6 &&
+       intel->batch.is_blit != is_blit && intel->batch.used) {
+      intel_batchbuffer_flush(intel);
    }
 
-   batch->is_blit = is_blit;
+   intel->batch.is_blit = is_blit;
 
 #ifdef DEBUG
-   assert(sz < batch->size - 8);
+   assert(sz < sizeof(intel->batch.map) - BATCH_RESERVED);
 #endif
-   if (intel_batchbuffer_space(batch) < sz)
-      intel_batchbuffer_flush(batch);
+   if (intel_batchbuffer_space(intel) < sz)
+      intel_batchbuffer_flush(intel);
 }
 
 static INLINE void
-intel_batchbuffer_begin(struct intel_batchbuffer *batch, int n, bool is_blit)
+intel_batchbuffer_begin(struct intel_context *intel, int n, bool is_blit)
 {
-   intel_batchbuffer_require_space(batch, n * 4, is_blit);
+   intel_batchbuffer_require_space(intel, n * 4, is_blit);
 
+   intel->batch.emit = intel->batch.used;
 #ifdef DEBUG
-   assert(batch->map);
-   assert(batch->emit.start_ptr == NULL);
-   batch->emit.total = n * 4;
-   batch->emit.start_ptr = batch->ptr;
+   intel->batch.total = n;
 #endif
 }
 
 static INLINE void
-intel_batchbuffer_advance(struct intel_batchbuffer *batch)
+intel_batchbuffer_advance(struct intel_context *intel)
 {
 #ifdef DEBUG
-   unsigned int _n = batch->ptr - batch->emit.start_ptr;
-   assert(batch->emit.start_ptr != NULL);
-   if (_n != batch->emit.total) {
+   struct intel_batchbuffer *batch = &intel->batch;
+   unsigned int _n = batch->used - batch->emit;
+   assert(batch->total != 0);
+   if (_n != batch->total) {
       fprintf(stderr, "ADVANCE_BATCH: %d of %d dwords emitted\n",
-             _n, batch->emit.total);
+             _n, batch->total);
       abort();
    }
-   batch->emit.start_ptr = NULL;
+   batch->total = 0;
 #endif
 }
 
+void intel_batchbuffer_cached_advance(struct intel_context *intel);
+
 /* Here are the crusty old macros, to be removed:
  */
 #define BATCH_LOCALS
 
-#define BEGIN_BATCH(n) intel_batchbuffer_begin(intel->batch, n, false)
-#define BEGIN_BATCH_BLT(n) intel_batchbuffer_begin(intel->batch, n, true)
-#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d)
-#define OUT_BATCH_F(f) intel_batchbuffer_emit_float(intel->batch,f)
+#define BEGIN_BATCH(n) intel_batchbuffer_begin(intel, n, false)
+#define BEGIN_BATCH_BLT(n) intel_batchbuffer_begin(intel, n, true)
+#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel, d)
+#define OUT_BATCH_F(f) intel_batchbuffer_emit_float(intel,f)
 #define OUT_RELOC(buf, read_domains, write_domain, delta) do {         \
-   intel_batchbuffer_emit_reloc(intel->batch, buf,                     \
+   intel_batchbuffer_emit_reloc(intel, buf,                    \
                                read_domains, write_domain, delta);     \
 } while (0)
 #define OUT_RELOC_FENCED(buf, read_domains, write_domain, delta) do {  \
-   intel_batchbuffer_emit_reloc_fenced(intel->batch, buf,              \
+   intel_batchbuffer_emit_reloc_fenced(intel, buf,             \
                                       read_domains, write_domain, delta); \
 } while (0)
 
-#define ADVANCE_BATCH() intel_batchbuffer_advance(intel->batch);
+#define ADVANCE_BATCH() intel_batchbuffer_advance(intel);
+#define CACHED_BATCH() intel_batchbuffer_cached_advance(intel);
 
 #endif
index 6232e479cb6ef4ba86c38bd7d421ce4f2295714c..e1ab7f163718f0208cdaa463d0a370c519490c56 100644 (file)
@@ -123,12 +123,12 @@ intelEmitCopyBlit(struct intel_context *intel,
 
    /* do space check before going any further */
    do {
-       aper_array[0] = intel->batch->buf;
+       aper_array[0] = intel->batch.bo;
        aper_array[1] = dst_buffer;
        aper_array[2] = src_buffer;
 
        if (dri_bufmgr_check_aperture_space(aper_array, 3) != 0) {
-           intel_batchbuffer_flush(intel->batch);
+           intel_batchbuffer_flush(intel);
            pass++;
        } else
            break;
@@ -137,7 +137,7 @@ intelEmitCopyBlit(struct intel_context *intel,
    if (pass >= 2)
       return GL_FALSE;
 
-   intel_batchbuffer_require_space(intel->batch, 8 * 4, true);
+   intel_batchbuffer_require_space(intel, 8 * 4, true);
    DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
        __FUNCTION__,
        src_buffer, src_pitch, src_offset, src_x, src_y,
@@ -193,7 +193,7 @@ intelEmitCopyBlit(struct intel_context *intel,
                    src_offset);
    ADVANCE_BATCH();
 
-   intel_batchbuffer_emit_mi_flush(intel->batch);
+   intel_batchbuffer_emit_mi_flush(intel);
 
    return GL_TRUE;
 }
@@ -343,12 +343,12 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
       assert(y1 < y2);
 
       /* do space check before going any further */
-      aper_array[0] = intel->batch->buf;
+      aper_array[0] = intel->batch.bo;
       aper_array[1] = write_buffer;
 
       if (drm_intel_bufmgr_check_aperture_space(aper_array,
                                                ARRAY_SIZE(aper_array)) != 0) {
-        intel_batchbuffer_flush(intel->batch);
+        intel_batchbuffer_flush(intel);
       }
 
       BEGIN_BATCH_BLT(6);
@@ -363,7 +363,7 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
       ADVANCE_BATCH();
 
       if (intel->always_flush_cache)
-        intel_batchbuffer_emit_mi_flush(intel->batch);
+        intel_batchbuffer_emit_mi_flush(intel);
 
       if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL)
         mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
@@ -410,10 +410,10 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel,
        __FUNCTION__,
        dst_buffer, dst_pitch, dst_offset, x, y, w, h, src_size, dwords);
 
-   intel_batchbuffer_require_space( intel->batch,
-                                   (8 * 4) +
-                                   (3 * 4) +
-                                   dwords * 4, true);
+   intel_batchbuffer_require_space(intel,
+                                  (8 * 4) +
+                                  (3 * 4) +
+                                  dwords * 4, true);
 
    opcode = XY_SETUP_BLT_CMD;
    if (cpp == 4)
@@ -449,11 +449,9 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel,
    OUT_BATCH(((y + h) << 16) | (x + w));
    ADVANCE_BATCH();
 
-   intel_batchbuffer_data(intel->batch,
-                         src_bits,
-                         dwords * 4, true);
+   intel_batchbuffer_data(intel, src_bits, dwords * 4, true);
 
-   intel_batchbuffer_emit_mi_flush(intel->batch);
+   intel_batchbuffer_emit_mi_flush(intel);
 
    return GL_TRUE;
 }
@@ -543,10 +541,10 @@ intel_set_teximage_alpha_to_one(struct gl_context *ctx,
 
    DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
        __FUNCTION__,
-       intel_image->mt->region->buffer, (pitch * region->cpp),
+       intel_image->mt->region->buffer, (pitch * cpp),
        x1, y1, x2 - x1, y2 - y1);
 
-   BR13 = br13_for_cpp(region->cpp) | 0xf0 << 16;
+   BR13 = br13_for_cpp(cpp) | 0xf0 << 16;
    CMD = XY_COLOR_BLT_CMD;
    CMD |= XY_BLT_WRITE_ALPHA;
 
@@ -558,15 +556,15 @@ intel_set_teximage_alpha_to_one(struct gl_context *ctx,
       pitch /= 4;
    }
 #endif
-   BR13 |= (pitch * region->cpp);
+   BR13 |= (pitch * cpp);
 
    /* do space check before going any further */
-   aper_array[0] = intel->batch->buf;
+   aper_array[0] = intel->batch.bo;
    aper_array[1] = region->buffer;
 
    if (drm_intel_bufmgr_check_aperture_space(aper_array,
                                             ARRAY_SIZE(aper_array)) != 0) {
-      intel_batchbuffer_flush(intel->batch);
+      intel_batchbuffer_flush(intel);
    }
 
    BEGIN_BATCH_BLT(6);
@@ -580,5 +578,5 @@ intel_set_teximage_alpha_to_one(struct gl_context *ctx,
    OUT_BATCH(0xffffffff); /* white, but only alpha gets written */
    ADVANCE_BATCH();
 
-   intel_batchbuffer_emit_mi_flush(intel->batch);
+   intel_batchbuffer_emit_mi_flush(intel);
 }
index d917161c4be3c41f9c3be6616cac62c321dbf440..2f750a768af0f12c1d6eeaf5b8cf3a95de3eed51 100644 (file)
@@ -53,6 +53,15 @@ intel_bufferobj_alloc_buffer(struct intel_context *intel,
                                          intel_obj->Base.Size, 64);
 }
 
+static void
+release_buffer(struct intel_buffer_object *intel_obj)
+{
+   drm_intel_bo_unreference(intel_obj->buffer);
+   intel_obj->buffer = NULL;
+   intel_obj->offset = 0;
+   intel_obj->source = 0;
+}
+
 /**
  * There is some duplication between mesa's bufferobjects and our
  * bufmgr buffers.  Both have an integer handle and a hashtable to
@@ -81,8 +90,7 @@ intel_bufferobj_release_region(struct intel_context *intel,
    intel_obj->region->pbo = NULL;
    intel_obj->region = NULL;
 
-   drm_intel_bo_unreference(intel_obj->buffer);
-   intel_obj->buffer = NULL;
+   release_buffer(intel_obj);
 }
 
 /* Break the COW tie to the region.  Both the pbo and the region end
@@ -120,10 +128,8 @@ intel_bufferobj_free(struct gl_context * ctx, struct gl_buffer_object *obj)
    if (intel_obj->region) {
       intel_bufferobj_release_region(intel, intel_obj);
    }
-   else if (intel_obj->buffer) {
-      drm_intel_bo_unreference(intel_obj->buffer);
-   }
 
+   drm_intel_bo_unreference(intel_obj->buffer);
    free(intel_obj);
 }
 
@@ -154,19 +160,22 @@ intel_bufferobj_data(struct gl_context * ctx,
    if (intel_obj->region)
       intel_bufferobj_release_region(intel, intel_obj);
 
-   if (intel_obj->buffer != NULL) {
-      drm_intel_bo_unreference(intel_obj->buffer);
-      intel_obj->buffer = NULL;
-   }
+   if (intel_obj->buffer != NULL)
+      release_buffer(intel_obj);
+
    free(intel_obj->sys_buffer);
    intel_obj->sys_buffer = NULL;
 
    if (size != 0) {
+      if (usage == GL_DYNAMIC_DRAW
 #ifdef I915
-      /* On pre-965, stick VBOs in system memory, as we're always doing swtnl
-       * with their contents anyway.
-       */
-      if (target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER) {
+         /* On pre-965, stick VBOs in system memory, as we're always doing
+          * swtnl with their contents anyway.
+          */
+         || target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER
+#endif
+        )
+      {
         intel_obj->sys_buffer = malloc(size);
         if (intel_obj->sys_buffer != NULL) {
            if (data != NULL)
@@ -174,7 +183,6 @@ intel_bufferobj_data(struct gl_context * ctx,
            return GL_TRUE;
         }
       }
-#endif
       intel_bufferobj_alloc_buffer(intel, intel_obj);
       if (!intel_obj->buffer)
          return GL_FALSE;
@@ -202,6 +210,7 @@ intel_bufferobj_subdata(struct gl_context * ctx,
 {
    struct intel_context *intel = intel_context(ctx);
    struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
+   bool busy;
 
    if (size == 0)
       return;
@@ -211,34 +220,53 @@ intel_bufferobj_subdata(struct gl_context * ctx,
    if (intel_obj->region)
       intel_bufferobj_cow(intel, intel_obj);
 
-   if (intel_obj->sys_buffer)
-      memcpy((char *)intel_obj->sys_buffer + offset, data, size);
-   else {
-      /* Flush any existing batchbuffer that might reference this data. */
-      if (intel->gen < 6) {
-        if (drm_intel_bo_busy(intel_obj->buffer) ||
-            drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) {
-           drm_intel_bo *temp_bo;
+   /* If we have a single copy in system memory, update that */
+   if (intel_obj->sys_buffer) {
+      if (intel_obj->source)
+        release_buffer(intel_obj);
 
-           temp_bo = drm_intel_bo_alloc(intel->bufmgr, "subdata temp", size, 64);
+      if (intel_obj->buffer == NULL) {
+        memcpy((char *)intel_obj->sys_buffer + offset, data, size);
+        return;
+      }
 
-           drm_intel_bo_subdata(temp_bo, 0, size, data);
+      free(intel_obj->sys_buffer);
+      intel_obj->sys_buffer = NULL;
+   }
 
-           intel_emit_linear_blit(intel,
-                                  intel_obj->buffer, offset,
-                                  temp_bo, 0,
-                                  size);
+   /* Otherwise we need to update the copy in video memory. */
+   busy =
+      drm_intel_bo_busy(intel_obj->buffer) ||
+      drm_intel_bo_references(intel->batch.bo, intel_obj->buffer);
 
-           drm_intel_bo_unreference(temp_bo);
-        } else {
-           drm_intel_bo_subdata(intel_obj->buffer, offset, size, data);
-        }
+   /* replace the current busy bo with fresh data */
+   if (busy && size == intel_obj->Base.Size) {
+      drm_intel_bo_unreference(intel_obj->buffer);
+      intel_bufferobj_alloc_buffer(intel, intel_obj);
+      drm_intel_bo_subdata(intel_obj->buffer, 0, size, data);
+   } else if (intel->gen < 6) {
+      if (busy) {
+        drm_intel_bo *temp_bo;
+
+        temp_bo = drm_intel_bo_alloc(intel->bufmgr, "subdata temp", size, 64);
+
+        drm_intel_bo_subdata(temp_bo, 0, size, data);
+
+        intel_emit_linear_blit(intel,
+                               intel_obj->buffer, offset,
+                               temp_bo, 0,
+                               size);
+
+        drm_intel_bo_unreference(temp_bo);
       } else {
-        if (drm_intel_bo_references(intel->batch->buf, intel_obj->buffer)) {
-           intel_batchbuffer_flush(intel->batch);
-        }
         drm_intel_bo_subdata(intel_obj->buffer, offset, size, data);
       }
+   } else {
+      /* Can't use the blit to modify the buffer in the middle of batch. */
+      if (drm_intel_bo_references(intel->batch.bo, intel_obj->buffer)) {
+        intel_batchbuffer_flush(intel);
+      }
+      drm_intel_bo_subdata(intel_obj->buffer, offset, size, data);
    }
 }
 
@@ -280,14 +308,23 @@ intel_bufferobj_map(struct gl_context * ctx,
    assert(intel_obj);
 
    if (intel_obj->sys_buffer) {
-      obj->Pointer = intel_obj->sys_buffer;
-      obj->Length = obj->Size;
-      obj->Offset = 0;
-      return obj->Pointer;
+      if (!read_only && intel_obj->source) {
+        release_buffer(intel_obj);
+      }
+
+      if (!intel_obj->buffer || intel_obj->source) {
+        obj->Pointer = intel_obj->sys_buffer;
+        obj->Length = obj->Size;
+        obj->Offset = 0;
+        return obj->Pointer;
+      }
+
+      free(intel_obj->sys_buffer);
+      intel_obj->sys_buffer = NULL;
    }
 
    /* Flush any existing batchbuffer that might reference this data. */
-   if (drm_intel_bo_references(intel->batch->buf, intel_obj->buffer))
+   if (drm_intel_bo_references(intel->batch.bo, intel_obj->buffer))
       intel_flush(ctx);
 
    if (intel_obj->region)
@@ -336,6 +373,7 @@ intel_bufferobj_map_range(struct gl_context * ctx,
 {
    struct intel_context *intel = intel_context(ctx);
    struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
+   GLboolean read_only = (access == GL_READ_ONLY_ARB);
 
    assert(intel_obj);
 
@@ -347,8 +385,16 @@ intel_bufferobj_map_range(struct gl_context * ctx,
    obj->AccessFlags = access;
 
    if (intel_obj->sys_buffer) {
-      obj->Pointer = intel_obj->sys_buffer + offset;
-      return obj->Pointer;
+      if (!read_only && intel_obj->source)
+        release_buffer(intel_obj);
+
+      if (!intel_obj->buffer || intel_obj->source) {
+        obj->Pointer = intel_obj->sys_buffer + offset;
+        return obj->Pointer;
+      }
+
+      free(intel_obj->sys_buffer);
+      intel_obj->sys_buffer = NULL;
    }
 
    if (intel_obj->region)
@@ -359,7 +405,7 @@ intel_bufferobj_map_range(struct gl_context * ctx,
     * syncing.
     */
    if (!(access & GL_MAP_UNSYNCHRONIZED_BIT) &&
-       drm_intel_bo_references(intel->batch->buf, intel_obj->buffer))
+       drm_intel_bo_references(intel->batch.bo, intel_obj->buffer))
       intel_flush(ctx);
 
    if (intel_obj->buffer == NULL) {
@@ -374,8 +420,7 @@ intel_bufferobj_map_range(struct gl_context * ctx,
        (access & GL_MAP_INVALIDATE_BUFFER_BIT) &&
        drm_intel_bo_busy(intel_obj->buffer)) {
       drm_intel_bo_unreference(intel_obj->buffer);
-      intel_obj->buffer = drm_intel_bo_alloc(intel->bufmgr, "bufferobj",
-                                            intel_obj->Base.Size, 64);
+      intel_bufferobj_alloc_buffer(intel, intel_obj);
    }
 
    /* If the user is mapping a range of an active buffer object but
@@ -473,7 +518,7 @@ intel_bufferobj_unmap(struct gl_context * ctx,
        * flush.  Once again, we wish for a domain tracker in libdrm to cover
        * usage inside of a batchbuffer.
        */
-      intel_batchbuffer_emit_mi_flush(intel->batch);
+      intel_batchbuffer_emit_mi_flush(intel);
       free(intel_obj->range_map_buffer);
       intel_obj->range_map_buffer = NULL;
    } else if (intel_obj->range_map_bo != NULL) {
@@ -493,7 +538,7 @@ intel_bufferobj_unmap(struct gl_context * ctx,
        * flush.  Once again, we wish for a domain tracker in libdrm to cover
        * usage inside of a batchbuffer.
        */
-      intel_batchbuffer_emit_mi_flush(intel->batch);
+      intel_batchbuffer_emit_mi_flush(intel);
 
       drm_intel_bo_unreference(intel_obj->range_map_bo);
       intel_obj->range_map_bo = NULL;
@@ -513,7 +558,8 @@ intel_bufferobj_unmap(struct gl_context * ctx,
 
 drm_intel_bo *
 intel_bufferobj_buffer(struct intel_context *intel,
-                       struct intel_buffer_object *intel_obj, GLuint flag)
+                       struct intel_buffer_object *intel_obj,
+                      GLuint flag)
 {
    if (intel_obj->region) {
       if (flag == INTEL_WRITE_PART)
@@ -524,23 +570,169 @@ intel_bufferobj_buffer(struct intel_context *intel,
       }
    }
 
-   if (intel_obj->buffer == NULL) {
-      void *sys_buffer = intel_obj->sys_buffer;
+   if (intel_obj->source)
+      release_buffer(intel_obj);
 
-      /* only one of buffer and sys_buffer could be non-NULL */
+   if (intel_obj->buffer == NULL) {
       intel_bufferobj_alloc_buffer(intel, intel_obj);
-      intel_obj->sys_buffer = NULL;
+      drm_intel_bo_subdata(intel_obj->buffer,
+                          0, intel_obj->Base.Size,
+                          intel_obj->sys_buffer);
 
-      intel_bufferobj_subdata(&intel->ctx,
-                             GL_ARRAY_BUFFER_ARB,
-                             0,
-                             intel_obj->Base.Size,
-                             sys_buffer,
-                             &intel_obj->Base);
-      free(sys_buffer);
+      free(intel_obj->sys_buffer);
       intel_obj->sys_buffer = NULL;
+      intel_obj->offset = 0;
+   }
+
+   return intel_obj->buffer;
+}
+
+#define INTEL_UPLOAD_SIZE (64*1024)
+
+void
+intel_upload_finish(struct intel_context *intel)
+{
+   if (!intel->upload.bo)
+          return;
+
+   if (intel->upload.buffer_len) {
+          drm_intel_bo_subdata(intel->upload.bo,
+                               intel->upload.buffer_offset,
+                               intel->upload.buffer_len,
+                               intel->upload.buffer);
+          intel->upload.buffer_len = 0;
+   }
+
+   drm_intel_bo_unreference(intel->upload.bo);
+   intel->upload.bo = NULL;
+}
+
+static void wrap_buffers(struct intel_context *intel, GLuint size)
+{
+   intel_upload_finish(intel);
+
+   if (size < INTEL_UPLOAD_SIZE)
+      size = INTEL_UPLOAD_SIZE;
+
+   intel->upload.bo = drm_intel_bo_alloc(intel->bufmgr, "upload", size, 0);
+   intel->upload.offset = 0;
+}
+
+void intel_upload_data(struct intel_context *intel,
+                      const void *ptr, GLuint size, GLuint align,
+                      drm_intel_bo **return_bo,
+                      GLuint *return_offset)
+{
+   GLuint base, delta;
+
+   base = (intel->upload.offset + align - 1) / align * align;
+   if (intel->upload.bo == NULL || base + size > intel->upload.bo->size) {
+      wrap_buffers(intel, size);
+      base = 0;
+   }
+
+   drm_intel_bo_reference(intel->upload.bo);
+   *return_bo = intel->upload.bo;
+   *return_offset = base;
+
+   delta = base - intel->upload.offset;
+   if (intel->upload.buffer_len &&
+       intel->upload.buffer_len + delta + size > sizeof(intel->upload.buffer))
+   {
+      drm_intel_bo_subdata(intel->upload.bo,
+                          intel->upload.buffer_offset,
+                          intel->upload.buffer_len,
+                          intel->upload.buffer);
+      intel->upload.buffer_len = 0;
+   }
+
+   if (size < sizeof(intel->upload.buffer))
+   {
+      if (intel->upload.buffer_len == 0)
+        intel->upload.buffer_offset = base;
+      else
+        intel->upload.buffer_len += delta;
+
+      memcpy(intel->upload.buffer + intel->upload.buffer_len, ptr, size);
+      intel->upload.buffer_len += size;
+   }
+   else
+   {
+      drm_intel_bo_subdata(intel->upload.bo, base, size, ptr);
+   }
+
+   intel->upload.offset = base + size;
+}
+
+void *intel_upload_map(struct intel_context *intel, GLuint size, GLuint align)
+{
+   GLuint base, delta;
+   char *ptr;
+
+   base = (intel->upload.offset + align - 1) / align * align;
+   if (intel->upload.bo == NULL || base + size > intel->upload.bo->size) {
+      wrap_buffers(intel, size);
+      base = 0;
+   }
+
+   delta = base - intel->upload.offset;
+   if (intel->upload.buffer_len &&
+       intel->upload.buffer_len + delta + size > sizeof(intel->upload.buffer))
+   {
+      drm_intel_bo_subdata(intel->upload.bo,
+                          intel->upload.buffer_offset,
+                          intel->upload.buffer_len,
+                          intel->upload.buffer);
+      intel->upload.buffer_len = 0;
+   }
+
+   if (size <= sizeof(intel->upload.buffer)) {
+      if (intel->upload.buffer_len == 0)
+        intel->upload.buffer_offset = base;
+      else
+        intel->upload.buffer_len += delta;
+
+      ptr = intel->upload.buffer + intel->upload.buffer_len;
+      intel->upload.buffer_len += size;
+   } else
+      ptr = malloc(size);
+
+   return ptr;
+}
+
+void intel_upload_unmap(struct intel_context *intel,
+                       const void *ptr, GLuint size, GLuint align,
+                       drm_intel_bo **return_bo,
+                       GLuint *return_offset)
+{
+   GLuint base;
+
+   base = (intel->upload.offset + align - 1) / align * align;
+   if (size > sizeof(intel->upload.buffer)) {
+      drm_intel_bo_subdata(intel->upload.bo, base, size, ptr);
+      free((void*)ptr);
+   }
+
+   drm_intel_bo_reference(intel->upload.bo);
+   *return_bo = intel->upload.bo;
+   *return_offset = base;
+
+   intel->upload.offset = base + size;
+}
+
+drm_intel_bo *
+intel_bufferobj_source(struct intel_context *intel,
+                       struct intel_buffer_object *intel_obj,
+                      GLuint *offset)
+{
+   if (intel_obj->buffer == NULL) {
+      intel_upload_data(intel,
+                       intel_obj->sys_buffer, intel_obj->Base.Size, 64,
+                       &intel_obj->buffer, &intel_obj->offset);
+      intel_obj->source = 1;
    }
 
+   *offset = intel_obj->offset;
    return intel_obj->buffer;
 }
 
@@ -555,6 +747,7 @@ intel_bufferobj_copy_subdata(struct gl_context *ctx,
    struct intel_buffer_object *intel_src = intel_buffer_object(src);
    struct intel_buffer_object *intel_dst = intel_buffer_object(dst);
    drm_intel_bo *src_bo, *dst_bo;
+   GLuint src_offset;
 
    if (size == 0)
       return;
@@ -567,7 +760,7 @@ intel_bufferobj_copy_subdata(struct gl_context *ctx,
       if (src == dst) {
         char *ptr = intel_bufferobj_map(ctx, GL_COPY_WRITE_BUFFER,
                                         GL_READ_WRITE, dst);
-        memcpy(ptr + write_offset, ptr + read_offset, size);
+        memmove(ptr + write_offset, ptr + read_offset, size);
         intel_bufferobj_unmap(ctx, GL_COPY_WRITE_BUFFER, dst);
       } else {
         const char *src_ptr;
@@ -589,18 +782,18 @@ intel_bufferobj_copy_subdata(struct gl_context *ctx,
    /* Otherwise, we have real BOs, so blit them. */
 
    dst_bo = intel_bufferobj_buffer(intel, intel_dst, INTEL_WRITE_PART);
-   src_bo = intel_bufferobj_buffer(intel, intel_src, INTEL_READ);
+   src_bo = intel_bufferobj_source(intel, intel_src, &src_offset);
 
    intel_emit_linear_blit(intel,
                          dst_bo, write_offset,
-                         src_bo, read_offset, size);
+                         src_bo, read_offset + src_offset, size);
 
    /* Since we've emitted some blits to buffers that will (likely) be used
     * in rendering operations in other cache domains in this batch, emit a
     * flush.  Once again, we wish for a domain tracker in libdrm to cover
     * usage inside of a batchbuffer.
     */
-   intel_batchbuffer_emit_mi_flush(intel->batch);
+   intel_batchbuffer_emit_mi_flush(intel);
 }
 
 #if FEATURE_APPLE_object_purgeable
index b15c1921061c19c4936ad7082848fe5194943257..3ec3a521382d1c4546a7e12216c7ac2e8c6955d9 100644 (file)
@@ -42,6 +42,8 @@ struct intel_buffer_object
 {
    struct gl_buffer_object Base;
    drm_intel_bo *buffer;     /* the low-level buffer manager's buffer handle */
+   GLuint offset;            /* any offset into that buffer */
+
    /** System memory buffer data, if not using a BO to store the data. */
    void *sys_buffer;
 
@@ -55,6 +57,7 @@ struct intel_buffer_object
    GLsizei range_map_size;
 
    GLboolean mapped_gtt;
+   GLboolean source;
 };
 
 
@@ -63,8 +66,25 @@ struct intel_buffer_object
 drm_intel_bo *intel_bufferobj_buffer(struct intel_context *intel,
                                     struct intel_buffer_object *obj,
                                     GLuint flag);
+drm_intel_bo *intel_bufferobj_source(struct intel_context *intel,
+                                    struct intel_buffer_object *obj,
+                                    GLuint *offset);
+
+void intel_upload_data(struct intel_context *intel,
+                      const void *ptr, GLuint size, GLuint align,
+                      drm_intel_bo **return_bo,
+                      GLuint *return_offset);
+
+void *intel_upload_map(struct intel_context *intel,
+                      GLuint size, GLuint align);
+void intel_upload_unmap(struct intel_context *intel,
+                       const void *ptr, GLuint size, GLuint align,
+                       drm_intel_bo **return_bo,
+                       GLuint *return_offset);
+
+void intel_upload_finish(struct intel_context *intel);
 
-/* Hook the bufferobject implementation into mesa: 
+/* Hook the bufferobject implementation into mesa:
  */
 void intelInitBufferObjectFuncs(struct dd_function_table *functions);
 
index 2a5029964befbf805aa928d993acb2627b103255..c2e2a98af5e26db8e6b7df4bf06725271293f706 100644 (file)
@@ -470,11 +470,9 @@ intel_prepare_render(struct intel_context *intel)
     * the swap, and getting our hands on that doesn't seem worth it,
     * so we just us the first batch we emitted after the last swap.
     */
-   if (intel->need_throttle && intel->first_post_swapbuffers_batch) {
-      drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch);
-      drm_intel_bo_unreference(intel->first_post_swapbuffers_batch);
-      intel->first_post_swapbuffers_batch = NULL;
-      intel->need_throttle = GL_FALSE;
+   if (intel->need_throttle) {
+       drmCommandNone(intel->driFd, DRM_I915_GEM_THROTTLE);
+       intel->need_throttle = GL_FALSE;
    }
 }
 
@@ -487,7 +485,7 @@ intel_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
     if (intel->saved_viewport)
        intel->saved_viewport(ctx, x, y, w, h);
 
-    if (!intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) {
+    if (ctx->DrawBuffer->Name == 0) {
        dri2InvalidateDrawable(driContext->driDrawablePriv);
        dri2InvalidateDrawable(driContext->driReadablePriv);
     }
@@ -554,8 +552,8 @@ intel_flush(struct gl_context *ctx)
    if (intel->gen < 4)
       INTEL_FIREVERTICES(intel);
 
-   if (intel->batch->map != intel->batch->ptr)
-      intel_batchbuffer_flush(intel->batch);
+   if (intel->batch.used)
+      intel_batchbuffer_flush(intel);
 }
 
 static void
@@ -583,7 +581,7 @@ intelFinish(struct gl_context * ctx)
 
        irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]);
 
-       if (irb && irb->region)
+       if (irb && irb->region && irb->region->buffer)
          drm_intel_bo_wait_rendering(irb->region->buffer);
    }
    if (fb->_DepthBuffer) {
@@ -644,8 +642,8 @@ intelInitContext(struct intel_context *intel,
       mesaVis = &visual;
    }
 
-   if (!_mesa_initialize_context_for_api(&intel->ctx, api, mesaVis, shareCtx,
-                                        functions, (void *) intel)) {
+   if (!_mesa_initialize_context(&intel->ctx, api, mesaVis, shareCtx,
+                                 functions, (void *) intel)) {
       printf("%s: failed to init mesa context\n", __FUNCTION__);
       return GL_FALSE;
    }
@@ -748,10 +746,10 @@ intelInitContext(struct intel_context *intel,
 
    driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache,
                        sPriv->myNum, (intel->gen >= 4) ? "i965" : "i915");
-   if (intelScreen->deviceID == PCI_CHIP_I865_G)
+   if (intel->gen < 4)
       intel->maxBatchSize = 4096;
    else
-      intel->maxBatchSize = BATCH_SZ;
+      intel->maxBatchSize = sizeof(intel->batch.map);
 
    intel->bufmgr = intelScreen->bufmgr;
 
@@ -805,8 +803,8 @@ intelInitContext(struct intel_context *intel,
     */
    _mesa_init_point(ctx);
 
-   meta_init_metaops(ctx, &intel->meta);
    if (intel->gen >= 4) {
+      ctx->Const.sRGBCapable = GL_TRUE;
       if (MAX_WIDTH > 8192)
         ctx->Const.MaxRenderbufferSize = 8192;
    } else {
@@ -863,7 +861,7 @@ intelInitContext(struct intel_context *intel,
    if (INTEL_DEBUG & DEBUG_BUFMGR)
       dri_bufmgr_set_debug(intel->bufmgr, GL_TRUE);
 
-   intel->batch = intel_batchbuffer_alloc(intel);
+   intel_batchbuffer_reset(intel);
 
    intel_fbo_init(intel);
 
@@ -911,8 +909,6 @@ intelDestroyContext(__DRIcontext * driContextPriv)
 
       _mesa_meta_free(&intel->ctx);
 
-      meta_destroy_metaops(&intel->meta);
-
       intel->vtbl.destroy(intel);
 
       _swsetup_DestroyContext(&intel->ctx);
@@ -922,15 +918,12 @@ intelDestroyContext(__DRIcontext * driContextPriv)
       _swrast_DestroyContext(&intel->ctx);
       intel->Fallback = 0x0;      /* don't call _swrast_Flush later */
 
-      intel_batchbuffer_free(intel->batch);
-      intel->batch = NULL;
+      intel_batchbuffer_free(intel);
 
       free(intel->prim.vb);
       intel->prim.vb = NULL;
       drm_intel_bo_unreference(intel->prim.vb_bo);
       intel->prim.vb_bo = NULL;
-      drm_intel_bo_unreference(intel->first_post_swapbuffers_batch);
-      intel->first_post_swapbuffers_batch = NULL;
 
       driDestroyOptionCache(&intel->optionCache);
 
index fd3c3ba58fcb77a1534a7c2940ef643331db8bc9..772b2fba5a83512fd1448411ea40dd93320bdc34 100644 (file)
@@ -32,7 +32,6 @@
 #include <stdbool.h>
 #include "main/mtypes.h"
 #include "main/mm.h"
-#include "dri_metaops.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -152,8 +151,6 @@ struct intel_context
       bool (*render_target_supported)(gl_format format);
    } vtbl;
 
-   struct dri_metaops meta;
-
    GLbitfield Fallback;  /**< mask of INTEL_FALLBACK_x bits */
    GLuint NewGLState;
 
@@ -172,17 +169,28 @@ struct intel_context
 
    int urb_size;
 
-   struct intel_batchbuffer *batch;
-   drm_intel_bo *first_post_swapbuffers_batch;
+   struct intel_batchbuffer {
+      drm_intel_bo *bo;
+      struct cached_batch_item *cached_items;
+
+      uint16_t emit, total;
+      uint16_t used, reserved_space;
+      uint32_t map[8192];
+#define BATCH_SZ (8192*sizeof(uint32_t))
+
+      uint32_t state_batch_offset;
+      bool is_blit;
+   } batch;
+
    GLboolean need_throttle;
    GLboolean no_batch_wrap;
 
    struct
    {
       GLuint id;
+      uint32_t start_ptr; /**< for i8xx */
       uint32_t primitive;      /**< Current hardware primitive type */
       void (*flush) (struct intel_context *);
-      GLubyte *start_ptr; /**< for i8xx */
       drm_intel_bo *vb_bo;
       uint8_t *vb;
       unsigned int start_offset; /**< Byte offset of primitive sequence */
@@ -190,6 +198,14 @@ struct intel_context
       unsigned int count;      /**< Number of vertices in current primitive */
    } prim;
 
+   struct {
+      drm_intel_bo *bo;
+      GLuint offset;
+      uint32_t buffer_len;
+      uint32_t buffer_offset;
+      char buffer[4096];
+   } upload;
+
    GLuint stats_wm;
 
    /* Offsets of fields within the current vertex:
index 747e9dcb7171aeed871601159046408c633a68c4..febc1d4f859d8112256f42ae562c8e9aa755244f 100644 (file)
@@ -175,6 +175,7 @@ static const struct dri_extension brw_extensions[] = {
    { "GL_ARB_texture_non_power_of_two",   NULL },
    { "GL_ARB_texture_rg",                 NULL },
    { "GL_EXT_draw_buffers2",              GL_EXT_draw_buffers2_functions },
+   { "GL_EXT_framebuffer_sRGB",           NULL },
    { "GL_EXT_shadow_funcs",               NULL },
    { "GL_EXT_stencil_two_side",           GL_EXT_stencil_two_side_functions },
    { "GL_EXT_texture_sRGB",              NULL },
index 0db5a491c8fa3cb493fb43f39ebee31165e03cd0..8b57eb19f562fb9b11837cfb2519b091fc127d32 100644 (file)
@@ -34,6 +34,7 @@
 #include "main/framebuffer.h"
 #include "main/renderbuffer.h"
 #include "main/context.h"
+#include "main/teximage.h"
 #include "main/texrender.h"
 #include "drivers/common/meta.h"
 
@@ -580,7 +581,7 @@ intel_finish_render_texture(struct gl_context * ctx,
     * batch.  Once again, we wish for a domain tracker in libdrm to cover
     * usage inside of a batchbuffer like GEM does in the kernel.
     */
-   intel_batchbuffer_emit_mi_flush(intel->batch);
+   intel_batchbuffer_emit_mi_flush(intel);
 }
 
 /**
@@ -647,6 +648,84 @@ intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
    }
 }
 
+/**
+ * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
+ * We can do this when the dst renderbuffer is actually a texture and
+ * there is no scaling, mirroring or scissoring.
+ *
+ * \return new buffer mask indicating the buffers left to blit using the
+ *         normal path.
+ */
+static GLbitfield
+intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
+                                          GLint srcX0, GLint srcY0,
+                                          GLint srcX1, GLint srcY1,
+                                          GLint dstX0, GLint dstY0,
+                                          GLint dstX1, GLint dstY1,
+                                          GLbitfield mask, GLenum filter)
+{
+   if (mask & GL_COLOR_BUFFER_BIT) {
+      const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
+      const struct gl_framebuffer *readFb = ctx->ReadBuffer;
+      const struct gl_renderbuffer_attachment *drawAtt =
+         &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
+
+      /* If the source and destination are the same size with no
+         mirroring, the rectangles are within the size of the
+         texture and there is no scissor then we can use
+         glCopyTexSubimage2D to implement the blit. This will end
+         up as a fast hardware blit on some drivers */
+      if (drawAtt && drawAtt->Texture &&
+          srcX0 - srcX1 == dstX0 - dstX1 &&
+          srcY0 - srcY1 == dstY0 - dstY1 &&
+          srcX1 >= srcX0 &&
+          srcY1 >= srcY0 &&
+          srcX0 >= 0 && srcX1 <= readFb->Width &&
+          srcY0 >= 0 && srcY1 <= readFb->Height &&
+          dstX0 >= 0 && dstX1 <= drawFb->Width &&
+          dstY0 >= 0 && dstY1 <= drawFb->Height &&
+          !ctx->Scissor.Enabled) {
+         const struct gl_texture_object *texObj = drawAtt->Texture;
+         const GLuint dstLevel = drawAtt->TextureLevel;
+         const GLenum target = texObj->Target;
+
+         struct gl_texture_image *texImage =
+            _mesa_select_tex_image(ctx, texObj, target, dstLevel);
+         GLenum internalFormat = texImage->InternalFormat;
+
+         if (intel_copy_texsubimage(intel_context(ctx), target,
+                                    intel_texture_image(texImage),
+                                    internalFormat,
+                                    dstX0, dstY0,
+                                    srcX0, srcY0,
+                                    srcX1 - srcX0, /* width */
+                                    srcY1 - srcY0))
+            mask &= ~GL_COLOR_BUFFER_BIT;
+      }
+   }
+
+   return mask;
+}
+
+static void
+intel_blit_framebuffer(struct gl_context *ctx,
+                       GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                       GLbitfield mask, GLenum filter)
+{
+   /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
+   mask = intel_blit_framebuffer_copy_tex_sub_image(ctx,
+                                                    srcX0, srcY0, srcX1, srcY1,
+                                                    dstX0, dstY0, dstX1, dstY1,
+                                                    mask, filter);
+   if (mask == 0x0)
+      return;
+
+   _mesa_meta_BlitFramebuffer(ctx,
+                              srcX0, srcY0, srcX1, srcY1,
+                              dstX0, dstY0, dstX1, dstY1,
+                              mask, filter);
+}
 
 /**
  * Do one-time context initializations related to GL_EXT_framebuffer_object.
@@ -663,7 +742,7 @@ intel_fbo_init(struct intel_context *intel)
    intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
    intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
    intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
-   intel->ctx.Driver.BlitFramebuffer = _mesa_meta_BlitFramebuffer;
+   intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
 
 #if FEATURE_OES_EGL_image
    intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
index e7356a6da0d325f41073020fa84e306c8fdfcc5f..d7561ee689dddc061126f8427c06757fcdbaa150 100644 (file)
@@ -285,7 +285,7 @@ do_blit_bitmap( struct gl_context *ctx,
 out:
 
    if (unlikely(INTEL_DEBUG & DEBUG_SYNC))
-      intel_batchbuffer_flush(intel->batch);
+      intel_batchbuffer_flush(intel);
 
    if (_mesa_is_bufferobj(unpack->BufferObj)) {
       /* done with PBO so unmap it now */
index 54da29236d252cec46dd7780231c4afd10b3d5b6..b2e77c7986a90b681385fc66164cd6d73fddd986 100644 (file)
@@ -80,6 +80,7 @@ do_blit_readpixels(struct gl_context * ctx,
    drm_intel_bo *dst_buffer;
    GLboolean all;
    GLint dst_x, dst_y;
+   GLuint dirty;
 
    DBG("%s\n", __FUNCTION__);
 
@@ -129,7 +130,9 @@ do_blit_readpixels(struct gl_context * ctx,
       return GL_TRUE;
    }
 
+   dirty = intel->front_buffer_dirty;
    intel_prepare_render(intel);
+   intel->front_buffer_dirty = dirty;
 
    all = (width * height * src->cpp == dst->Base.Size &&
          x == 0 && dst_offset == 0);
@@ -138,8 +141,8 @@ do_blit_readpixels(struct gl_context * ctx,
    dst_y = 0;
 
    dst_buffer = intel_bufferobj_buffer(intel, dst,
-                                              all ? INTEL_WRITE_FULL :
-                                              INTEL_WRITE_PART);
+                                      all ? INTEL_WRITE_FULL :
+                                      INTEL_WRITE_PART);
 
    if (ctx->ReadBuffer->Name == 0)
       y = ctx->ReadBuffer->Height - (y + height);
@@ -171,6 +174,10 @@ intelReadPixels(struct gl_context * ctx,
 
    DBG("%s\n", __FUNCTION__);
 
+   if (do_blit_readpixels
+       (ctx, x, y, width, height, format, type, pack, pixels))
+      return;
+
    intel_flush(ctx);
 
    /* glReadPixels() wont dirty the front buffer, so reset the dirty
@@ -179,10 +186,6 @@ intelReadPixels(struct gl_context * ctx,
    intel_prepare_render(intel);
    intel->front_buffer_dirty = dirty;
 
-   if (do_blit_readpixels
-       (ctx, x, y, width, height, format, type, pack, pixels))
-      return;
-
    fallback_debug("%s: fallback to swrast\n", __FUNCTION__);
 
    /* Update Mesa state before calling down into _swrast_ReadPixels, as
index e87e29462c38934794bad322af12160ceb4b5d60..0857fa8ad70f6d6706bf88cad3b24b8de2e8ce61 100644 (file)
@@ -491,7 +491,7 @@ intel_region_cow(struct intel_context *intel, struct intel_region *region)
 
    assert(region->cpp * region->pitch * region->height == pbo->Base.Size);
 
-   _DBG("%s %p (%d bytes)\n", __FUNCTION__, region, pbo->Base.Size);
+   _DBG("%s %p (%d bytes)\n", __FUNCTION__, region, (int)pbo->Base.Size);
 
    /* Now blit from the texture buffer to the new buffer: 
     */
index 5d14bcd34c082574af1343f9d9420f90c53d7022..356d5f72d89f1e56c53d5cd1c03303e1ec01a255 100644 (file)
@@ -111,8 +111,8 @@ intelDRI2Flush(__DRIdrawable *drawable)
 
    intel->need_throttle = GL_TRUE;
 
-   if (intel->batch->map != intel->batch->ptr)
-      intel_batchbuffer_flush(intel->batch);
+   if (intel->batch.used)
+      intel_batchbuffer_flush(intel);
 }
 
 static const struct __DRI2flushExtensionRec intelFlushExtension = {
@@ -634,6 +634,51 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp)
    return (const __DRIconfig **)configs;
 }
 
+struct intel_buffer {
+   __DRIbuffer base;
+   struct intel_region *region;
+};
+
+static __DRIbuffer *
+intelAllocateBuffer(__DRIscreen *screen,
+                   unsigned attachment, unsigned format,
+                   int width, int height)
+{
+   struct intel_buffer *intelBuffer;
+   struct intel_screen *intelScreen = screen->private;
+
+   intelBuffer = CALLOC(sizeof *intelBuffer);
+   if (intelBuffer == NULL)
+      return NULL;
+
+   intelBuffer->region = intel_region_alloc(intelScreen, I915_TILING_NONE,
+                                           format / 8, width, height, GL_TRUE);
+   
+   if (intelBuffer->region == NULL) {
+          FREE(intelBuffer);
+          return NULL;
+   }
+   
+   intel_region_flink(intelBuffer->region, &intelBuffer->base.name);
+
+   intelBuffer->base.attachment = attachment;
+   intelBuffer->base.cpp = intelBuffer->region->cpp;
+   intelBuffer->base.pitch =
+         intelBuffer->region->pitch * intelBuffer->region->cpp;
+
+   return &intelBuffer->base;
+}
+
+static void
+intelReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
+{
+   struct intel_buffer *intelBuffer = (struct intel_buffer *) buffer;
+
+   intel_region_release(&intelBuffer->region);
+   free(intelBuffer);
+}
+
+
 const struct __DriverAPIRec driDriverAPI = {
    .DestroyScreen       = intelDestroyScreen,
    .CreateContext       = intelCreateContext,
@@ -643,6 +688,8 @@ const struct __DriverAPIRec driDriverAPI = {
    .MakeCurrent                 = intelMakeCurrent,
    .UnbindContext       = intelUnbindContext,
    .InitScreen2                 = intelInitScreen2,
+   .AllocateBuffer       = intelAllocateBuffer,
+   .ReleaseBuffer        = intelReleaseBuffer
 };
 
 /* This is the table of extensions that the loader will dlsym() for. */
index bbfac74b6054179838c08969b281a86c11f3788c..b303ea84dd8a25d277d57c64fa6fb88ca87e8396 100644 (file)
@@ -72,9 +72,9 @@ intel_fence_sync(struct gl_context *ctx, struct gl_sync_object *s,
    struct intel_sync_object *sync = (struct intel_sync_object *)s;
 
    assert(condition == GL_SYNC_GPU_COMMANDS_COMPLETE);
-   intel_batchbuffer_emit_mi_flush(intel->batch);
+   intel_batchbuffer_emit_mi_flush(intel);
 
-   sync->bo = intel->batch->buf;
+   sync->bo = intel->batch.bo;
    drm_intel_bo_reference(sync->bo);
 
    intel_flush(ctx);
index 6552ed0d332afb78926bc1bdf0ebae56d6972ddb..52462f39d54893252b967e83818bf336b9b60450 100644 (file)
@@ -65,4 +65,12 @@ void intel_tex_unmap_images(struct intel_context *intel,
 
 int intel_compressed_num_bytes(GLuint mesaFormat);
 
+GLboolean intel_copy_texsubimage(struct intel_context *intel,
+                                 GLenum target,
+                                 struct intel_texture_image *intelImage,
+                                 GLenum internalFormat,
+                                 GLint dstx, GLint dsty,
+                                 GLint x, GLint y,
+                                 GLsizei width, GLsizei height);
+
 #endif
index a40011ab40c396aad71a2873a2cb62ae2e4f4e0b..136d8e1d0a9e718a2fe15b163ead2c71bd12ee65 100644 (file)
@@ -67,13 +67,13 @@ get_teximage_readbuffer(struct intel_context *intel, GLenum internalFormat)
 }
 
 
-static GLboolean
-do_copy_texsubimage(struct intel_context *intel,
-                   GLenum target,
-                    struct intel_texture_image *intelImage,
-                    GLenum internalFormat,
-                    GLint dstx, GLint dsty,
-                    GLint x, GLint y, GLsizei width, GLsizei height)
+GLboolean
+intel_copy_texsubimage(struct intel_context *intel,
+                       GLenum target,
+                       struct intel_texture_image *intelImage,
+                       GLenum internalFormat,
+                       GLint dstx, GLint dsty,
+                       GLint x, GLint y, GLsizei width, GLsizei height)
 {
    struct gl_context *ctx = &intel->ctx;
    struct intel_renderbuffer *irb;
@@ -191,9 +191,9 @@ intelCopyTexImage1D(struct gl_context * ctx, GLenum target, GLint level,
                                   &width, &height))
       return;
 
-   if (!do_copy_texsubimage(intel_context(ctx), target,
-                            intel_texture_image(texImage),
-                            internalFormat, 0, 0, x, y, width, height))
+   if (!intel_copy_texsubimage(intel_context(ctx), target,
+                               intel_texture_image(texImage),
+                               internalFormat, 0, 0, x, y, width, height))
       goto fail;
 
    return;
@@ -239,9 +239,9 @@ intelCopyTexImage2D(struct gl_context * ctx, GLenum target, GLint level,
                                   &width, &height))
       return;
 
-   if (!do_copy_texsubimage(intel_context(ctx), target,
-                            intel_texture_image(texImage),
-                            internalFormat, 0, 0, x, y, width, height))
+   if (!intel_copy_texsubimage(intel_context(ctx), target,
+                               intel_texture_image(texImage),
+                               internalFormat, 0, 0, x, y, width, height))
       goto fail;
 
    return;
@@ -269,9 +269,9 @@ intelCopyTexSubImage1D(struct gl_context * ctx, GLenum target, GLint level,
    /* Need to check texture is compatible with source format. 
     */
 
-   if (!do_copy_texsubimage(intel_context(ctx), target,
-                            intel_texture_image(texImage),
-                            internalFormat, xoffset, 0, x, y, width, 1)) {
+   if (!intel_copy_texsubimage(intel_context(ctx), target,
+                               intel_texture_image(texImage),
+                               internalFormat, xoffset, 0, x, y, width, 1)) {
       fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
       _mesa_meta_CopyTexSubImage1D(ctx, target, level, xoffset, x, y, width);
    }
@@ -293,11 +293,10 @@ intelCopyTexSubImage2D(struct gl_context * ctx, GLenum target, GLint level,
    /* Need to check texture is compatible with source format. 
     */
 
-   if (!do_copy_texsubimage(intel_context(ctx), target,
-                            intel_texture_image(texImage),
-                            internalFormat,
-                            xoffset, yoffset, x, y, width, height)) {
-
+   if (!intel_copy_texsubimage(intel_context(ctx), target,
+                               intel_texture_image(texImage),
+                               internalFormat,
+                               xoffset, yoffset, x, y, width, height)) {
       fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
       _mesa_meta_CopyTexSubImage2D(ctx, target, level,
                                    xoffset, yoffset, x, y, width, height);
index cd8c4c22e5aa9ab5023ee1f65b293afa1c7aacee..9dba529c58d0aba26fc6a57a47ff77b8d13512d1 100644 (file)
@@ -231,15 +231,17 @@ try_pbo_upload(struct intel_context *intel,
 
    dst_stride = intelImage->mt->region->pitch;
 
-   if (drm_intel_bo_references(intel->batch->buf, dst_buffer))
+   if (drm_intel_bo_references(intel->batch.bo, dst_buffer))
       intel_flush(&intel->ctx);
 
    {
-      drm_intel_bo *src_buffer = intel_bufferobj_buffer(intel, pbo, INTEL_READ);
+      GLuint offset;
+      drm_intel_bo *src_buffer = intel_bufferobj_source(intel, pbo, &offset);
 
       if (!intelEmitCopyBlit(intel,
                             intelImage->mt->cpp,
-                            src_stride, src_buffer, src_offset, GL_FALSE,
+                            src_stride, src_buffer,
+                            src_offset + offset, GL_FALSE,
                             dst_stride, dst_buffer, 0,
                             intelImage->mt->region->tiling,
                             0, 0, dst_x, dst_y, width, height,
@@ -429,7 +431,7 @@ intelTexImage(struct gl_context * ctx,
    if (intelImage->mt) {
       if (pixels != NULL) {
         /* Flush any queued rendering with the texture before mapping. */
-        if (drm_intel_bo_references(intel->batch->buf,
+        if (drm_intel_bo_references(intel->batch.bo,
                                     intelImage->mt->region->buffer)) {
            intel_flush(ctx);
         }
index 7c989df5ec0e6b39108ccbf11c8cc60eca7bbfd1..35b01a97402409aa8b7e16cad003f42ef58d69da 100644 (file)
@@ -120,7 +120,7 @@ GLboolean mach64CreateContext( gl_api api,
       shareCtx = ((mach64ContextPtr) sharedContextPrivate)->glCtx;
    else 
       shareCtx = NULL;
-   mmesa->glCtx = _mesa_create_context(glVisual, shareCtx, 
+   mmesa->glCtx = _mesa_create_context(API_OPENGL, glVisual, shareCtx, 
                                        &functions, (void *)mmesa);
    if (!mmesa->glCtx) {
       FREE(mmesa);
index d1b281a2c0506d1fac512f5e1dab08727b8550ab..eb7df9785c19a32fa1b04e9a9f5485ae29ca1bb0 100644 (file)
@@ -457,7 +457,7 @@ mgaCreateContext( gl_api api,
       shareCtx = ((mgaContextPtr) sharedContextPrivate)->glCtx;
    else 
       shareCtx = NULL;
-   mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
+   mmesa->glCtx = _mesa_create_context(API_OPENGL, mesaVis, shareCtx,
                                        &functions, (void *) mmesa);
    if (!mmesa->glCtx) {
       FREE(mmesa);
index 53a121420d3af2bc4baf10342b92f4f2664219f6..71dde413873b42845232a99f3d17cb63bf032e70 100644 (file)
@@ -115,7 +115,8 @@ nouveau_context_init(struct gl_context *ctx, struct nouveau_screen *screen,
        nouveau_fbo_functions_init(&functions);
 
        /* Initialize the mesa context. */
-       _mesa_initialize_context(ctx, visual, share_ctx, &functions, NULL);
+       _mesa_initialize_context(ctx, API_OPENGL, visual,
+                                 share_ctx, &functions, NULL);
 
        nouveau_state_init(ctx);
        nouveau_bo_state_init(ctx);
index 274108005f3716c2ea849a6555662bcd3d8afa5c..247d86ca008c807a7cf2b8ea898dfd3bf57c13fc 100644 (file)
@@ -128,7 +128,7 @@ GLboolean r128CreateContext( gl_api api,
       shareCtx = ((r128ContextPtr) sharedContextPrivate)->glCtx;
    else 
       shareCtx = NULL;
-   rmesa->glCtx = _mesa_create_context(glVisual, shareCtx,
+   rmesa->glCtx = _mesa_create_context(API_OPENGL, glVisual, shareCtx,
                                        &functions, (void *) rmesa);
    if (!rmesa->glCtx) {
       FREE(rmesa);
index 5d69012a81ff5b2dc86f397b1a469d7525b2d414..63e03b0e0c725c457718f8813516afe630cb4b63 100644 (file)
@@ -438,7 +438,7 @@ static GLboolean r200_translate_vertex_program(struct gl_context *ctx, struct r2
       (1 << VERT_RESULT_TEX5) | (1 << VERT_RESULT_PSIZ))) != 0) {
       if (R200_DEBUG & RADEON_FALLBACKS) {
         fprintf(stderr, "can't handle vert prog outputs 0x%llx\n",
-           mesa_vp->Base.OutputsWritten);
+                 (unsigned long long) mesa_vp->Base.OutputsWritten);
       }
       return GL_FALSE;
    }
index 782671bac0156810f89448c73eeb997ec8beb824..deba9ca834d01c5a41be5628f9c1c7a948ed0308 100644 (file)
@@ -49,6 +49,11 @@ static void presub_string(char out[10], unsigned int inst)
        }
 }
 
+static int get_msb(unsigned int bit, unsigned int r400_ext_addr)
+{
+       return (r400_ext_addr & bit) ? 1 << 5 : 0;
+}
+
 /* just some random things... */
 void r300FragmentProgramDump(struct radeon_compiler *c, void *user)
 {
@@ -61,16 +66,21 @@ void r300FragmentProgramDump(struct radeon_compiler *c, void *user)
 
        fprintf(stderr, "Hardware program\n");
        fprintf(stderr, "----------------\n");
+       if (c->is_r400) {
+               fprintf(stderr, "code_offset_ext: %08x\n", code->r400_code_offset_ext);
+       }
 
        for (n = 0; n <= (code->config & 3); n++) {
                uint32_t code_addr = code->code_addr[3 - (code->config & 3) + n];
-               int alu_offset = (code_addr & R300_ALU_START_MASK) >> R300_ALU_START_SHIFT;
-               int alu_end = (code_addr & R300_ALU_SIZE_MASK) >> R300_ALU_SIZE_SHIFT;
+               unsigned int alu_offset = ((code_addr & R300_ALU_START_MASK) >> R300_ALU_START_SHIFT) +
+                               (((code->r400_code_offset_ext >> (24 - (n * 6))) & 0x7) << 6);
+               unsigned int alu_end = ((code_addr & R300_ALU_SIZE_MASK) >> R300_ALU_SIZE_SHIFT) +
+                               (((code->r400_code_offset_ext >> (27 - (n * 6))) & 0x7) << 6);
                int tex_offset = (code_addr & R300_TEX_START_MASK) >> R300_TEX_START_SHIFT;
                int tex_end = (code_addr & R300_TEX_SIZE_MASK) >> R300_TEX_SIZE_SHIFT;
 
-               fprintf(stderr, "NODE %d: alu_offset: %d, tex_offset: %d, "
-                       "alu_end: %d, tex_end: %d  (code_addr: %08x)\n", n,
+               fprintf(stderr, "NODE %d: alu_offset: %u, tex_offset: %d, "
+                       "alu_end: %u, tex_end: %d  (code_addr: %08x)\n", n,
                        alu_offset, tex_offset, alu_end, tex_end, code_addr);
 
                if (n > 0 || (code->config & R300_PFS_CNTL_FIRST_NODE_HAS_TEX)) {
@@ -125,11 +135,15 @@ void r300FragmentProgramDump(struct radeon_compiler *c, void *user)
                        for (j = 0; j < 3; ++j) {
                                int regc = code->alu.inst[i].rgb_addr >> (j * 6);
                                int rega = code->alu.inst[i].alpha_addr >> (j * 6);
+                               int msbc = get_msb(R400_ADDR_EXT_RGB_MSB_BIT(j),
+                                       code->alu.inst[i].r400_ext_addr);
+                               int msba = get_msb(R400_ADDR_EXT_A_MSB_BIT(j),
+                                       code->alu.inst[i].r400_ext_addr);
 
                                sprintf(srcc[j], "%c%i",
-                                       (regc & 32) ? 'c' : 't', regc & 31);
+                                       (regc & 32) ? 'c' : 't', (regc & 31) | msbc);
                                sprintf(srca[j], "%c%i",
-                                       (rega & 32) ? 'c' : 't', rega & 31);
+                                       (rega & 32) ? 'c' : 't', (rega & 31) | msba);
                        }
 
                        dstc[0] = 0;
@@ -141,9 +155,14 @@ void r300FragmentProgramDump(struct radeon_compiler *c, void *user)
                                (code->alu.inst[i].
                                 rgb_addr & R300_ALU_DSTC_REG_Z) ? "z" : "");
                        if (flags[0] != 0) {
+                               unsigned int msb = get_msb(
+                                       R400_ADDRD_EXT_RGB_MSB_BIT,
+                                       code->alu.inst[i].r400_ext_addr);
+
                                sprintf(dstc, "t%i.%s ",
-                                       (code->alu.inst[i].
-                                        rgb_addr >> R300_ALU_DSTC_SHIFT) & 31,
+                                       ((code->alu.inst[i].
+                                        rgb_addr >> R300_ALU_DSTC_SHIFT)
+                                        & 31) | msb,
                                        flags);
                        }
                        sprintf(flags, "%s%s%s",
@@ -166,9 +185,13 @@ void r300FragmentProgramDump(struct radeon_compiler *c, void *user)
 
                        dsta[0] = 0;
                        if (code->alu.inst[i].alpha_addr & R300_ALU_DSTA_REG) {
+                               unsigned int msb = get_msb(
+                                       R400_ADDRD_EXT_A_MSB_BIT,
+                                       code->alu.inst[i].r400_ext_addr);
                                sprintf(dsta, "t%i.w ",
-                                       (code->alu.inst[i].
-                                        alpha_addr >> R300_ALU_DSTA_SHIFT) & 31);
+                                       ((code->alu.inst[i].
+                                        alpha_addr >> R300_ALU_DSTA_SHIFT) & 31)
+                                        | msb);
                        }
                        if (code->alu.inst[i].alpha_addr & R300_ALU_DSTA_OUTPUT) {
                                sprintf(tmp, "o%i.w ",
index 1db8678e890e23c718eaab589bdc8c3ba67e848e..28d132a5fe3ec42b1a2e73152d09c7fdd8ee6c3f 100644 (file)
@@ -64,6 +64,20 @@ struct r300_emit_state {
                        __FILE__, __FUNCTION__, ##args);        \
        } while(0)
 
+static unsigned int get_msbs_alu(unsigned int bits)
+{
+       return (bits >> 6) & 0x7;
+}
+
+/**
+ * @param lsbs The number of least significant bits
+ */
+static unsigned int get_msbs_tex(unsigned int bits, unsigned int lsbs)
+{
+       return (bits >> lsbs) & 0x15;
+}
+
+#define R400_EXT_GET_MSBS(x, lsbs, mask) (((x) >> lsbs) & mask)
 
 /**
  * Mark a temporary register as used.
@@ -83,7 +97,7 @@ static unsigned int use_source(struct r300_fragment_program_code* code, struct r
                return src.Index | (1 << 5);
        } else if (src.File == RC_FILE_TEMPORARY) {
                use_temporary(code, src.Index);
-               return src.Index;
+               return src.Index & 0x1f;
        }
 
        return 0;
@@ -151,11 +165,19 @@ static int emit_alu(struct r300_emit_state * emit, struct rc_pair_instruction* i
        code->alu.inst[ip].alpha_inst = translate_alpha_opcode(c, inst->Alpha.Opcode);
 
        for(j = 0; j < 3; ++j) {
+               /* Set the RGB address */
                unsigned int src = use_source(code, inst->RGB.Src[j]);
                unsigned int arg;
+               if (inst->RGB.Src[j].Index >= R300_PFS_NUM_TEMP_REGS)
+                       code->alu.inst[ip].r400_ext_addr |= R400_ADDR_EXT_RGB_MSB_BIT(j);
+
                code->alu.inst[ip].rgb_addr |= src << (6*j);
 
+               /* Set the Alpha address */
                src = use_source(code, inst->Alpha.Src[j]);
+               if (inst->Alpha.Src[j].Index >= R300_PFS_NUM_TEMP_REGS)
+                       code->alu.inst[ip].r400_ext_addr |= R400_ADDR_EXT_A_MSB_BIT(j);
+
                code->alu.inst[ip].alpha_addr |= src << (6*j);
 
                arg = r300FPTranslateRGBSwizzle(inst->RGB.Arg[j].Source, inst->RGB.Arg[j].Swizzle);
@@ -223,8 +245,10 @@ static int emit_alu(struct r300_emit_state * emit, struct rc_pair_instruction* i
 
        if (inst->RGB.WriteMask) {
                use_temporary(code, inst->RGB.DestIndex);
+               if (inst->RGB.DestIndex >= R300_PFS_NUM_TEMP_REGS)
+                       code->alu.inst[ip].r400_ext_addr |= R400_ADDRD_EXT_RGB_MSB_BIT;
                code->alu.inst[ip].rgb_addr |=
-                       (inst->RGB.DestIndex << R300_ALU_DSTC_SHIFT) |
+                       ((inst->RGB.DestIndex & 0x1f) << R300_ALU_DSTC_SHIFT) |
                        (inst->RGB.WriteMask << R300_ALU_DSTC_REG_MASK_SHIFT);
        }
        if (inst->RGB.OutputWriteMask) {
@@ -236,8 +260,10 @@ static int emit_alu(struct r300_emit_state * emit, struct rc_pair_instruction* i
 
        if (inst->Alpha.WriteMask) {
                use_temporary(code, inst->Alpha.DestIndex);
+               if (inst->Alpha.DestIndex >= R300_PFS_NUM_TEMP_REGS)
+                       code->alu.inst[ip].r400_ext_addr |= R400_ADDRD_EXT_A_MSB_BIT;
                code->alu.inst[ip].alpha_addr |=
-                       (inst->Alpha.DestIndex << R300_ALU_DSTA_SHIFT) |
+                       ((inst->Alpha.DestIndex & 0x1f) << R300_ALU_DSTA_SHIFT) |
                        R300_ALU_DSTA_REG;
        }
        if (inst->Alpha.OutputWriteMask) {
@@ -269,6 +295,8 @@ static int finish_node(struct r300_emit_state * emit)
        unsigned tex_offset;
        unsigned tex_end;
 
+       unsigned int alu_offset_msbs, alu_end_msbs;
+
        if (code->alu.length == emit->node_first_alu) {
                /* Generate a single NOP for this node */
                struct rc_pair_instruction inst;
@@ -301,13 +329,48 @@ static int finish_node(struct r300_emit_state * emit)
         *
         * Also note that the register specification from AMD is slightly
         * incorrect in its description of this register. */
-       code->code_addr[emit->current_node] =
-                       (alu_offset << R300_ALU_START_SHIFT) |
-                       (alu_end << R300_ALU_SIZE_SHIFT) |
-                       (tex_offset << R300_TEX_START_SHIFT) |
-                       (tex_end << R300_TEX_SIZE_SHIFT) |
-                       emit->node_flags;
-
+       code->code_addr[emit->current_node]  =
+                       ((alu_offset << R300_ALU_START_SHIFT)
+                               & R300_ALU_START_MASK)
+                       | ((alu_end << R300_ALU_SIZE_SHIFT)
+                               & R300_ALU_SIZE_MASK)
+                       | ((tex_offset << R300_TEX_START_SHIFT)
+                               & R300_TEX_START_MASK)
+                       | ((tex_end << R300_TEX_SIZE_SHIFT)
+                               & R300_TEX_SIZE_MASK)
+                       | emit->node_flags
+                       | (get_msbs_tex(tex_offset, 5)
+                               << R400_TEX_START_MSB_SHIFT)
+                       | (get_msbs_tex(tex_end, 5)
+                               << R400_TEX_SIZE_MSB_SHIFT)
+                       ;
+
+       /* Write r400 extended instruction fields.  These will be ignored on
+        * r300 cards.  */
+       alu_offset_msbs = get_msbs_alu(alu_offset);
+       alu_end_msbs = get_msbs_alu(alu_end);
+       switch(emit->current_node) {
+       case 0:
+               code->r400_code_offset_ext |=
+                       alu_offset_msbs << R400_ALU_START3_MSB_SHIFT
+                       | alu_end_msbs << R400_ALU_SIZE3_MSB_SHIFT;
+               break;
+       case 1:
+               code->r400_code_offset_ext |=
+                       alu_offset_msbs << R400_ALU_START2_MSB_SHIFT
+                       | alu_end_msbs << R400_ALU_SIZE2_MSB_SHIFT;
+               break;
+       case 2:
+               code->r400_code_offset_ext |=
+                       alu_offset_msbs << R400_ALU_START1_MSB_SHIFT
+                       | alu_end_msbs << R400_ALU_SIZE1_MSB_SHIFT;
+               break;
+       case 3:
+               code->r400_code_offset_ext |=
+                       alu_offset_msbs << R400_ALU_START0_MSB_SHIFT
+                       | alu_end_msbs << R400_ALU_SIZE0_MSB_SHIFT;
+               break;
+       }
        return 1;
 }
 
@@ -348,7 +411,7 @@ static int emit_tex(struct r300_emit_state * emit, struct rc_instruction * inst)
        unsigned int opcode;
        PROG_CODE;
 
-       if (code->tex.length >= R300_PFS_MAX_TEX_INST) {
+       if (code->tex.length >= emit->compiler->Base.max_tex_insts) {
                error("Too many TEX instructions");
                return 0;
        }
@@ -376,10 +439,17 @@ static int emit_tex(struct r300_emit_state * emit, struct rc_instruction * inst)
        use_temporary(code, inst->U.I.SrcReg[0].Index);
 
        code->tex.inst[code->tex.length++] =
-               (inst->U.I.SrcReg[0].Index << R300_SRC_ADDR_SHIFT) |
-               (dest << R300_DST_ADDR_SHIFT) |
-               (unit << R300_TEX_ID_SHIFT) |
-               (opcode << R300_TEX_INST_SHIFT);
+               ((inst->U.I.SrcReg[0].Index << R300_SRC_ADDR_SHIFT)
+                       & R300_SRC_ADDR_MASK)
+               | ((dest << R300_DST_ADDR_SHIFT)
+                       & R300_DST_ADDR_MASK)
+               | (unit << R300_TEX_ID_SHIFT)
+               | (opcode << R300_TEX_INST_SHIFT)
+               | (inst->U.I.SrcReg[0].Index >= R300_PFS_NUM_TEMP_REGS ?
+                       R400_SRC_ADDR_EXT_BIT : 0)
+               | (dest >= R300_PFS_NUM_TEMP_REGS ?
+                       R400_DST_ADDR_EXT_BIT : 0)
+               ;
        return 1;
 }
 
@@ -393,6 +463,7 @@ void r300BuildFragmentProgramHwCode(struct radeon_compiler *c, void *user)
        struct r300_fragment_program_compiler *compiler = (struct r300_fragment_program_compiler*)c;
        struct r300_emit_state emit;
        struct r300_fragment_program_code *code = &compiler->code->code.r300;
+       unsigned int tex_end;
 
        memset(&emit, 0, sizeof(emit));
        emit.compiler = compiler;
@@ -424,11 +495,28 @@ void r300BuildFragmentProgramHwCode(struct radeon_compiler *c, void *user)
        finish_node(&emit);
 
        code->config |= emit.current_node; /* FIRST_NODE_HAS_TEX set by finish_node */
+
+       /* Set r400 extended instruction fields.  These values will be ignored
+        * on r300 cards. */
+       code->r400_code_offset_ext |=
+               (get_msbs_alu(0)
+                               << R400_ALU_OFFSET_MSB_SHIFT)
+               | (get_msbs_alu(code->alu.length - 1)
+                               << R400_ALU_SIZE_MSB_SHIFT);
+
+       tex_end = code->tex.length ? code->tex.length - 1 : 0;
        code->code_offset =
-               (0 << R300_PFS_CNTL_ALU_OFFSET_SHIFT) |
-               ((code->alu.length-1) << R300_PFS_CNTL_ALU_END_SHIFT) |
-               (0 << R300_PFS_CNTL_TEX_OFFSET_SHIFT) |
-               ((code->tex.length ? code->tex.length-1 : 0) << R300_PFS_CNTL_TEX_END_SHIFT);
+               ((0 << R300_PFS_CNTL_ALU_OFFSET_SHIFT)
+                       & R300_PFS_CNTL_ALU_OFFSET_MASK)
+               | (((code->alu.length - 1) << R300_PFS_CNTL_ALU_END_SHIFT)
+                       & R300_PFS_CNTL_ALU_END_MASK)
+               | ((0 << R300_PFS_CNTL_TEX_OFFSET_SHIFT)
+                       & R300_PFS_CNTL_TEX_OFFSET_MASK)
+               | ((tex_end << R300_PFS_CNTL_TEX_END_SHIFT)
+                       & R300_PFS_CNTL_TEX_END_MASK)
+               | (get_msbs_tex(0, 5) << R400_TEX_START_MSB_SHIFT)
+               | (get_msbs_tex(tex_end, 6) << R400_TEX_SIZE_MSB_SHIFT)
+               ;
 
        if (emit.current_node < 3) {
                int shift = 3 - emit.current_node;
@@ -438,4 +526,11 @@ void r300BuildFragmentProgramHwCode(struct radeon_compiler *c, void *user)
                for(i = 0; i < shift; ++i)
                        code->code_addr[i] = 0;
        }
+
+       if (code->pixsize >= R300_PFS_NUM_TEMP_REGS
+           || code->alu.length > R300_PFS_MAX_ALU_INST
+           || code->tex.length > R300_PFS_MAX_TEX_INST) {
+
+               code->r390_mode = 1;
+       }
 }
index 05d3da8a10d2e018eef0ea970b92be49f18c4161..fa906f2fddef94647fb13ca3bdd262ee029d1829 100644 (file)
@@ -222,13 +222,14 @@ unsigned int r300FPTranslateRGBSwizzle(unsigned int src, unsigned int swizzle)
  */
 unsigned int r300FPTranslateAlphaSwizzle(unsigned int src, unsigned int swizzle)
 {
+       unsigned int swz = GET_SWZ(swizzle, 0);
        if (src == RC_PAIR_PRESUB_SRC) {
-               return R300_ALU_ARGA_SRCP_X + swizzle;
+               return R300_ALU_ARGA_SRCP_X + swz;
        }
-       if (swizzle < 3)
-               return swizzle + 3*src;
+       if (swz < 3)
+               return swz + 3*src;
 
-       switch(swizzle) {
+       switch(swz) {
        case RC_SWIZZLE_W: return R300_ALU_ARGA_SRC0A + src;
        case RC_SWIZZLE_ONE: return R300_ALU_ARGA_ONE;
        case RC_SWIZZLE_ZERO: return R300_ALU_ARGA_ZERO;
index e0d349b98ce147b33c17cd3b61b5857a6785b99d..1616306afbd4c6b29e0b7099f2596443213e64ed 100644 (file)
@@ -124,7 +124,7 @@ void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c)
                /* This pass makes it easier for the scheduler to group TEX
                 * instructions and reduces the chances of creating too
                 * many texture indirections.*/
-               {"register rename",             1, !is_r500 || opt, rc_rename_regs,             NULL},
+               {"register rename",             1, !is_r500,    rc_rename_regs,                 NULL},
                {"pair translate",              1, 1,           rc_pair_translate,              NULL},
                {"pair scheduling",             1, 1,           rc_pair_schedule,               NULL},
                {"register allocation",         1, opt,         rc_pair_regalloc,               NULL},
index 472029f63d0758d2b0b8d7c5f508da794edc8d34..8ad2175eadf25615ca5c3fd04d7269b1738367e8 100644 (file)
@@ -490,13 +490,6 @@ static void translate_vertex_program(struct radeon_compiler *c, void *user)
                        continue;
 
                if (info->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 "
@@ -668,7 +661,6 @@ static void allocate_temporary_registers(struct radeon_compiler *c, void *user)
        char hwtemps[RC_REGISTER_MAX_INDEX];
        struct temporary_allocation * ta;
        unsigned int i, j;
-       struct rc_instruction *last_inst_src_reladdr = NULL;
 
        memset(hwtemps, 0, sizeof(hwtemps));
 
@@ -693,28 +685,11 @@ static void allocate_temporary_registers(struct radeon_compiler *c, void *user)
                }
        }
 
-       /* Pass 2: If there is relative addressing of dst temporaries, we cannot change register indices. Give up.
-        * For src temporaries, save the last instruction which uses relative addressing. */
-       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) {
-                               last_inst_src_reladdr = inst;
-                       }
-               }
-       }
-
        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 3: Determine original temporary lifetimes */
+       /* Pass 2: 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
@@ -744,41 +719,22 @@ static void allocate_temporary_registers(struct radeon_compiler *c, void *user)
 
                for (i = 0; i < opcode->NumSrcRegs; ++i) {
                        if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY) {
-                               struct rc_instruction *last_read;
-
-                               /* From "last_inst_src_reladdr", "end_loop", and "inst",
-                                * select the instruction with the highest instruction index (IP).
-                                * Note that "end_loop", if available, has always a higher index than "inst". */
-                               if (last_inst_src_reladdr) {
-                                       if (end_loop) {
-                                               last_read = last_inst_src_reladdr->IP > end_loop->IP ?
-                                                           last_inst_src_reladdr : end_loop;
-                                       } else {
-                                               last_read = last_inst_src_reladdr->IP > inst->IP ?
-                                                           last_inst_src_reladdr : inst;
-                                       }
-                               } else {
-                                       last_read = end_loop ? end_loop : inst;
-                               }
-
-                               ta[inst->U.I.SrcReg[i].Index].LastRead = last_read;
+                               ta[inst->U.I.SrcReg[i].Index].LastRead = end_loop ? end_loop : inst;
                        }
                }
        }
 
-       /* Pass 4: Register allocation */
+       /* Pass 3: 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);
 
-               if (!last_inst_src_reladdr || last_inst_src_reladdr->IP < inst->IP) {
-                       for (i = 0; i < opcode->NumSrcRegs; ++i) {
-                               if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY) {
-                                       unsigned int orig = inst->U.I.SrcReg[i].Index;
-                                       inst->U.I.SrcReg[i].Index = ta[orig].HwTemp;
+               for (i = 0; i < opcode->NumSrcRegs; ++i) {
+                       if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY) {
+                               unsigned int orig = inst->U.I.SrcReg[i].Index;
+                               inst->U.I.SrcReg[i].Index = ta[orig].HwTemp;
 
-                                       if (ta[orig].Allocated && inst == ta[orig].LastRead)
-                                               hwtemps[ta[orig].HwTemp] = 0;
-                               }
+                               if (ta[orig].Allocated && inst == ta[orig].LastRead)
+                                       hwtemps[ta[orig].HwTemp] = 0;
                        }
                }
 
@@ -792,12 +748,7 @@ static void allocate_temporary_registers(struct radeon_compiler *c, void *user)
                                                        break;
                                        }
                                        ta[orig].Allocated = 1;
-                                       if (last_inst_src_reladdr &&
-                                           last_inst_src_reladdr->IP > inst->IP) {
-                                               ta[orig].HwTemp = orig;
-                                       } else {
-                                               ta[orig].HwTemp = j;
-                                       }
+                                       ta[orig].HwTemp = j;
                                        hwtemps[ta[orig].HwTemp] = 1;
                                }
 
index 5da82d90f6716a117a092af86ed1b3a49d32452f..1febc19cc2d0ff7533ba92d0d771abfcae1bbeca 100644 (file)
@@ -170,7 +170,7 @@ static unsigned int translate_arg_rgb(struct rc_pair_instruction *inst, int arg)
 static unsigned int translate_arg_alpha(struct rc_pair_instruction *inst, int i)
 {
        unsigned int t = inst->Alpha.Arg[i].Source;
-       t |= fix_hw_swizzle(inst->Alpha.Arg[i].Swizzle) << 2;
+       t |= fix_hw_swizzle(GET_SWZ(inst->Alpha.Arg[i].Swizzle, 0)) << 2;
        t |= inst->Alpha.Arg[i].Negate << 5;
        t |= inst->Alpha.Arg[i].Abs << 6;
        return t;
index b69e81698ae9cf3bdb29e54131bae11d23227b82..d14516689472308eb848e5b67fc436356fe630b6 100644 (file)
@@ -31,6 +31,9 @@
 #define R300_PFS_NUM_TEMP_REGS    32
 #define R300_PFS_NUM_CONST_REGS   32
 
+#define R400_PFS_MAX_ALU_INST     512
+#define R400_PFS_MAX_TEX_INST     512
+
 #define R500_PFS_MAX_INST         512
 #define R500_PFS_NUM_TEMP_REGS    128
 #define R500_PFS_NUM_CONST_REGS   256
@@ -187,24 +190,29 @@ struct r300_fragment_program_node {
  */
 struct r300_fragment_program_code {
        struct {
-               int length; /**< total # of texture instructions used */
-               uint32_t inst[R300_PFS_MAX_TEX_INST];
+               unsigned int length; /**< total # of texture instructions used */
+               uint32_t inst[R400_PFS_MAX_TEX_INST];
        } tex;
 
        struct {
-               int length; /**< total # of ALU instructions used */
+               unsigned int length; /**< total # of ALU instructions used */
                struct {
                        uint32_t rgb_inst;
                        uint32_t rgb_addr;
                        uint32_t alpha_inst;
                        uint32_t alpha_addr;
-               } inst[R300_PFS_MAX_ALU_INST];
+                       uint32_t r400_ext_addr;
+               } inst[R400_PFS_MAX_ALU_INST];
        } alu;
 
        uint32_t config; /* US_CONFIG */
        uint32_t pixsize; /* US_PIXSIZE */
        uint32_t code_offset; /* US_CODE_OFFSET */
+       uint32_t r400_code_offset_ext; /* US_CODE_EXT */
        uint32_t code_addr[4]; /* US_CODE_ADDR */
+       /*US_CODE_BANK.R390_MODE: Enables 512 instructions and 64 temporaries
+        * for r400 cards */
+       unsigned int r390_mode:1;
 };
 
 
index 65548604bcca832c25abca83ae7dc0cedd8fb590..79cd7996f78aaa56b64f4b8772460bf0535aae36 100644 (file)
@@ -373,9 +373,11 @@ void rc_get_stats(struct radeon_compiler *c, struct rc_program_stats *s)
                const struct rc_opcode_info * info;
                rc_for_all_reads_mask(tmp, reg_count_callback, &max_reg);
                if (tmp->Type == RC_INSTRUCTION_NORMAL) {
+                       info = rc_get_opcode_info(tmp->U.I.Opcode);
+                       if (info->Opcode == RC_OPCODE_BEGIN_TEX)
+                               continue;
                        if (tmp->U.I.PreSub.Opcode != RC_PRESUB_NONE)
                                s->num_presub_ops++;
-                       info = rc_get_opcode_info(tmp->U.I.Opcode);
                } else {
                        if (tmp->U.P.RGB.Src[RC_PAIR_PRESUB_SRC].Used)
                                s->num_presub_ops++;
@@ -402,11 +404,11 @@ static void print_stats(struct radeon_compiler * c)
 {
        struct rc_program_stats s;
 
-       rc_get_stats(c, &s);
-
-       if (s.num_insts < 4)
+       if (c->initial_num_insts <= 5)
                return;
 
+       rc_get_stats(c, &s);
+
        switch (c->type) {
        case RC_VERTEX_PROGRAM:
                fprintf(stderr,"~~~~~~~~~ VERTEX PROGRAM ~~~~~~~~\n"
@@ -461,6 +463,11 @@ void rc_run_compiler_passes(struct radeon_compiler *c, struct radeon_compiler_pa
 /* Executes a list of compiler passes given in the parameter 'list'. */
 void rc_run_compiler(struct radeon_compiler *c, struct radeon_compiler_pass *list)
 {
+       struct rc_program_stats s;
+
+       rc_get_stats(c, &s);
+       c->initial_num_insts = s.num_insts;
+
        if (c->Debug & RC_DBG_LOG) {
                fprintf(stderr, "%s: before compilation\n", shader_name[c->type]);
                rc_print_program(&c->Program);
index e6633395895b7dbb2a0fe7ef3878b04a9ec2b436..2d8e415f35035cffc87017e2bc562414e7d3d887 100644 (file)
@@ -50,6 +50,7 @@ struct radeon_compiler {
        char * ErrorMsg;
 
        /* Hardware specification. */
+       unsigned is_r400:1;
        unsigned is_r500:1;
        unsigned has_half_swizzles:1;
        unsigned has_presub:1;
@@ -57,6 +58,7 @@ struct radeon_compiler {
        unsigned max_temp_regs;
        unsigned max_constants;
        int max_alu_insts;
+       unsigned max_tex_insts;
 
        /* Whether to remove unused constants and empty holes in constant space. */
        unsigned remove_unused_constants:1;
@@ -70,6 +72,8 @@ struct radeon_compiler {
        /*@}*/
 
        struct emulate_loop_state loop_state;
+
+       unsigned initial_num_insts; /* Number of instructions at start. */
 };
 
 void rc_init(struct radeon_compiler * c);
index 2482fc68bebf9bd92c4d0e289d6535c864d3af10..15ec4418cb87594f0a628ad557afc17f3527cf5b 100644 (file)
@@ -55,6 +55,24 @@ rc_swizzle get_swz(unsigned int swz, rc_swizzle idx)
        return GET_SWZ(swz, idx);
 }
 
+/**
+ * The purpose of this function is to standardize the number channels used by
+ * swizzles.  All swizzles regardless of what instruction they are a part of
+ * should have 4 channels initialized with values.
+ * @param channels The number of channels in initial_value that have a
+ * meaningful value.
+ * @return An initialized swizzle that has all of the unused channels set to
+ * RC_SWIZZLE_UNUSED.
+ */
+unsigned int rc_init_swizzle(unsigned int initial_value, unsigned int channels)
+{
+       unsigned int i;
+       for (i = channels; i < 4; i++) {
+               SET_SWZ(initial_value, i, RC_SWIZZLE_UNUSED);
+       }
+       return initial_value;
+}
+
 unsigned int combine_swizzles4(unsigned int src,
                rc_swizzle swz_x, rc_swizzle swz_y, rc_swizzle swz_z, rc_swizzle swz_w)
 {
@@ -147,13 +165,17 @@ unsigned int rc_src_reads_dst_mask(
        return dst_mask & rc_swizzle_to_writemask(src_swz);
 }
 
-unsigned int rc_source_type_swz(unsigned int swizzle, unsigned int channels)
+/**
+ * @return A bit mask specifying whether this swizzle will select from an RGB
+ * source, an Alpha source, or both.
+ */
+unsigned int rc_source_type_swz(unsigned int swizzle)
 {
        unsigned int chan;
        unsigned int swz = RC_SWIZZLE_UNUSED;
        unsigned int ret = RC_SOURCE_NONE;
 
-       for(chan = 0; chan < channels; chan++) {
+       for(chan = 0; chan < 4; chan++) {
                swz = GET_SWZ(swizzle, chan);
                if (swz == RC_SWIZZLE_W) {
                        ret |= RC_SOURCE_ALPHA;
@@ -202,7 +224,7 @@ static void can_use_presub_read_cb(
                if (d->RemoveSrcs[i].File == file
                    && d->RemoveSrcs[i].Index == index) {
                        src_type &=
-                               ~rc_source_type_swz(d->RemoveSrcs[i].Swizzle, 4);
+                               ~rc_source_type_swz(d->RemoveSrcs[i].Swizzle);
                }
        }
 
index 461ab9ffb10676484bfe5870ddd4ee4072475468..dd0f6c66156ce7e5d69e73344ac2aacc60625be8 100644 (file)
@@ -10,6 +10,8 @@ unsigned int rc_swizzle_to_writemask(unsigned int swz);
 
 rc_swizzle get_swz(unsigned int swz, rc_swizzle idx);
 
+unsigned int rc_init_swizzle(unsigned int initial_value, unsigned int channels);
+
 unsigned int combine_swizzles4(unsigned int src,
                               rc_swizzle swz_x, rc_swizzle swz_y,
                               rc_swizzle swz_z, rc_swizzle swz_w);
@@ -32,7 +34,7 @@ unsigned int rc_src_reads_dst_mask(
                unsigned int dst_idx,
                unsigned int dst_mask);
 
-unsigned int rc_source_type_swz(unsigned int swizzle, unsigned int channels);
+unsigned int rc_source_type_swz(unsigned int swizzle);
 
 unsigned int rc_source_type_mask(unsigned int mask);
 
index d0a64d936e055fdab01db8fa3e0b0fead73b6172..c080d5aecc6eb9c99fad7cd34f8aa6632309d0f0 100644 (file)
@@ -140,14 +140,8 @@ static void pair_sub_for_all_args(
 
        for(i = 0; i < info->NumSrcRegs; i++) {
                unsigned int src_type;
-               unsigned int channels = 0;
-               if (&fullinst->U.P.RGB == sub)
-                       channels = 3;
-               else if (&fullinst->U.P.Alpha == sub)
-                       channels = 1;
-
-               assert(channels > 0);
-               src_type = rc_source_type_swz(sub->Arg[i].Swizzle, channels);
+
+               src_type = rc_source_type_swz(sub->Arg[i].Swizzle);
 
                if (src_type == RC_SOURCE_NONE)
                        continue;
index 87906f37b121eaaf55d1bfd1400d34a5fc28386a..678e1475883b8f2408880a21d6b3c70380aa676b 100644 (file)
@@ -160,12 +160,8 @@ 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;
-                       if (!inst->U.I.DstReg.RelAddr)
-                               *pused &= ~usedmask;
+                       *pused &= ~usedmask;
                }
-
-               if (inst->U.I.DstReg.RelAddr)
-                       mark_used(s, RC_FILE_ADDRESS, 0, RC_MASK_X);
        }
 
        insts->WriteMask |= usedmask;
@@ -219,22 +215,9 @@ void rc_dataflow_deadcode(struct radeon_compiler * c, void *user)
 {
        struct deadcode_state s;
        unsigned int nr_instructions;
-       unsigned has_temp_reladdr_src = 0;
        rc_dataflow_mark_outputs_fn dce = (rc_dataflow_mark_outputs_fn)user;
        unsigned int ip;
 
-       /* Give up if there is relative addressing of destination operands. */
-       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);
-               if (opcode->HasDstReg &&
-                   inst->U.I.DstReg.WriteMask &&
-                   inst->U.I.DstReg.RelAddr) {
-                       return;
-               }
-       }
-
        memset(&s, 0, sizeof(s));
        s.C = c;
 
@@ -321,32 +304,6 @@ void rc_dataflow_deadcode(struct radeon_compiler * c, void *user)
                                        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) {
-                                                       opcode = rc_get_opcode_info(ptr->U.I.Opcode);
-                                                       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;
-                                               break;
-                                       }
-                               }
-                       }
                }
 
                update_instruction(&s, inst);
index 44f4c0fbdc74b4a119bcdcdfff1e5f225deb3149..5caff91b00e21090775304d923be6868b759cc8b 100644 (file)
@@ -139,7 +139,6 @@ static void copy_propagate(struct radeon_compiler * c, struct rc_instruction * i
        unsigned int i;
 
        if (inst_mov->U.I.DstReg.File != RC_FILE_TEMPORARY ||
-           inst_mov->U.I.DstReg.RelAddr ||
            inst_mov->U.I.WriteALUResult ||
            inst_mov->U.I.SaturateMode)
                return;
index 9beb5d6357996c9651796742c6e3fba6ea55ecdb..8e10813ff069745cb1ed6c525690db83828b5acb 100644 (file)
@@ -365,8 +365,8 @@ static int merge_presub_sources(
                for(arg = 0; arg < info->NumSrcRegs; arg++) {
                        /*If this arg does not read from an rgb source,
                         * do nothing. */
-                       if (!(rc_source_type_swz(dst_full->RGB.Arg[arg].Swizzle,
-                                                               3) & type)) {
+                       if (!(rc_source_type_swz(dst_full->RGB.Arg[arg].Swizzle)
+                                                               & type)) {
                                continue;
                        }
 
@@ -423,11 +423,11 @@ static int destructive_merge_instructions(
                unsigned int index = 0;
                int source;
 
-               if (alpha->Alpha.Arg[arg].Swizzle < 3) {
+               if (GET_SWZ(alpha->Alpha.Arg[arg].Swizzle, 0) < 3) {
                        srcrgb = 1;
                        file = alpha->RGB.Src[oldsrc].File;
                        index = alpha->RGB.Src[oldsrc].Index;
-               } else if (alpha->Alpha.Arg[arg].Swizzle < 4) {
+               } else if (GET_SWZ(alpha->Alpha.Arg[arg].Swizzle, 0) < 4) {
                        srcalpha = 1;
                        file = alpha->Alpha.Src[oldsrc].File;
                        index = alpha->Alpha.Src[oldsrc].Index;
@@ -544,18 +544,12 @@ static void rgb_to_alpha_remap (
 {
        int new_src_index;
        unsigned int i;
-       struct rc_pair_instruction_source * old_src =
-                                       rc_pair_get_src(&inst->U.P, arg);
-       if (!old_src) {
-               return;
-       }
 
        for (i = 0; i < 3; i++) {
                if (get_swz(arg->Swizzle, i) == old_swz) {
                        SET_SWZ(arg->Swizzle, i, RC_SWIZZLE_W);
                }
        }
-       memset(old_src, 0, sizeof(struct rc_pair_instruction_source));
        new_src_index = rc_pair_alloc_source(&inst->U.P, 0, 1,
                                                        old_file, new_index);
        /* This conversion is not possible, we must have made a mistake in
@@ -728,7 +722,8 @@ static int convert_rgb_to_alpha(
                for (j = 0; j < 3; j++) {
                        unsigned int swz = get_swz(pair_inst->Alpha.Arg[i].Swizzle, j);
                        if (swz != RC_SWIZZLE_UNUSED) {
-                               pair_inst->Alpha.Arg[i].Swizzle = swz;
+                               pair_inst->Alpha.Arg[i].Swizzle =
+                                                       rc_init_swizzle(swz, 1);
                                break;
                        }
                }
index fc05366f50ee3d8bfb45af2991dbe90696a8e295..6d7263b4ab62402b57170dde2aa656a34371d144 100644 (file)
@@ -28,6 +28,7 @@
 #include "radeon_program_pair.h"
 
 #include "radeon_compiler.h"
+#include "radeon_compiler_util.h"
 
 
 /**
@@ -232,7 +233,8 @@ static void set_pair_instruction(struct r300_fragment_program_compiler *c,
                                return;
                        }
                        pair->RGB.Arg[i].Source = source;
-                       pair->RGB.Arg[i].Swizzle = inst->SrcReg[i].Swizzle & 0x1ff;
+                       pair->RGB.Arg[i].Swizzle =
+                               rc_init_swizzle(inst->SrcReg[i].Swizzle, 3);
                        pair->RGB.Arg[i].Abs = inst->SrcReg[i].Abs;
                        pair->RGB.Arg[i].Negate = !!(inst->SrcReg[i].Negate & (RC_MASK_X | RC_MASK_Y | RC_MASK_Z));
                }
@@ -252,7 +254,7 @@ static void set_pair_instruction(struct r300_fragment_program_compiler *c,
                                return;
                        }
                        pair->Alpha.Arg[i].Source = source;
-                       pair->Alpha.Arg[i].Swizzle = swz;
+                       pair->Alpha.Arg[i].Swizzle = rc_init_swizzle(swz, 1);
                        pair->Alpha.Arg[i].Abs = inst->SrcReg[i].Abs;
                        pair->Alpha.Arg[i].Negate = !!(inst->SrcReg[i].Negate & RC_MASK_W);
                }
@@ -302,12 +304,6 @@ static void check_opcode_support(struct r300_fragment_program_compiler *c,
        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;
index df6c94b35f9ba07bbd1ef0aa76b1028ad3adb113..a07f6b63c6ee11dd4e1f845a2ac04ba646fea5b0 100644 (file)
@@ -56,11 +56,7 @@ struct rc_src_register {
 
 struct rc_dst_register {
        unsigned int File:3;
-
-       /** Negative values may be used for relative addressing. */
-       signed int Index:(RC_REGISTER_INDEX_BITS+1);
-       unsigned int RelAddr:1;
-
+       unsigned int Index:RC_REGISTER_INDEX_BITS;
        unsigned int WriteMask:4;
 };
 
index c8063171b81e7c95ed93b8f727a53553d21fee38..9fc991166a3aa712bb1f063729c52613174ed37e 100644 (file)
@@ -91,7 +91,6 @@ static struct rc_dst_register dstregtmpmask(int index, int mask)
        dst.File = RC_FILE_TEMPORARY;
        dst.Index = index;
        dst.WriteMask = mask;
-       dst.RelAddr = 0;
        return dst;
 }
 
index 5905d26e521b087550dd1b8fe32d01037a17ffc4..68874795b8ac1a94ab9fb64a11e88366731d9089 100644 (file)
@@ -211,27 +211,9 @@ struct rc_pair_instruction_source * rc_pair_get_src(
        struct rc_pair_instruction * pair_inst,
        struct rc_pair_instruction_arg * arg)
 {
-       unsigned int i, type;
-       unsigned int channels = 0;
+       unsigned int type;
 
-       for(i = 0; i < 3; i++) {
-               if (arg == pair_inst->RGB.Arg + i) {
-                       channels = 3;
-                       break;
-               }
-       }
-
-       if (channels == 0) {
-               for (i = 0; i < 3; i++) {
-                       if (arg == pair_inst->Alpha.Arg + i) {
-                               channels = 1;
-                               break;
-                       }
-               }
-       }
-
-       assert(channels > 0);
-       type = rc_source_type_swz(arg->Swizzle, channels);
+       type = rc_source_type_swz(arg->Swizzle);
 
        if (type & RC_SOURCE_RGB) {
                return &pair_inst->RGB.Src[arg->Source];
index ccf7a0070cdae07ebd7e6f845216e5c257c9a49f..6708b16d29a560b63577f1c0fe67e2f6672d3d4d 100644 (file)
@@ -63,7 +63,7 @@ struct rc_pair_instruction_source {
 
 struct rc_pair_instruction_arg {
        unsigned int Source:2;
-       unsigned int Swizzle:9;
+       unsigned int Swizzle:12;
        unsigned int Abs:1;
        unsigned int Negate:1;
 };
index ae13f6742f881a4e53533fc471ea3321e0f758de..390d1319460beb2a51a232df77c905150fabd01c 100644 (file)
@@ -110,7 +110,7 @@ static void rc_print_mask(FILE * f, unsigned int mask)
 
 static void rc_print_dst_register(FILE * f, struct rc_dst_register dst)
 {
-       rc_print_register(f, dst.File, dst.Index, dst.RelAddr);
+       rc_print_register(f, dst.File, dst.Index, 0);
        if (dst.WriteMask != RC_MASK_XYZW) {
                fprintf(f, ".");
                rc_print_mask(f, dst.WriteMask);
@@ -379,7 +379,7 @@ static void rc_print_pair_instruction(FILE * f, struct rc_instruction * fullinst
                        else
                                fprintf(f,"%d", inst->Alpha.Arg[arg].Source);
                        fprintf(f,".%c%s",
-                               rc_swizzle_char(inst->Alpha.Arg[arg].Swizzle), abs);
+                               rc_swizzle_char(GET_SWZ(inst->Alpha.Arg[arg].Swizzle, 0)), abs);
                }
                fprintf(f, "\n");
        }
index 9fd8e8fde5fbd6ce4088012a5017b4ed9d2f54da..14e60866d93d07c4acf48a3d53496711dc07a888 100644 (file)
@@ -63,7 +63,6 @@ static void create_vertex_program(struct r300_context *r300)
     inst->U.I.Opcode = RC_OPCODE_MOV;
     inst->U.I.DstReg.File = RC_FILE_OUTPUT;
     inst->U.I.DstReg.Index = VERT_RESULT_HPOS;
-    inst->U.I.DstReg.RelAddr = 0;
     inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
     inst->U.I.SrcReg[0].Abs = 0;
     inst->U.I.SrcReg[0].File = RC_FILE_INPUT;
@@ -76,7 +75,6 @@ static void create_vertex_program(struct r300_context *r300)
     inst->U.I.Opcode = RC_OPCODE_MOV;
     inst->U.I.DstReg.File = RC_FILE_OUTPUT;
     inst->U.I.DstReg.Index = VERT_RESULT_TEX0;
-    inst->U.I.DstReg.RelAddr = 0;
     inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
     inst->U.I.SrcReg[0].Abs = 0;
     inst->U.I.SrcReg[0].File = RC_FILE_INPUT;
@@ -131,6 +129,7 @@ static void create_fragment_program(struct r300_context *r300)
     compiler.Base.max_temp_regs = (compiler.Base.is_r500) ? 128 : 32;
     compiler.Base.max_constants = compiler.Base.is_r500 ? 256 : 32;
     compiler.Base.max_alu_insts = compiler.Base.is_r500 ? 512 : 64;
+    compiler.Base.max_tex_insts = compiler.Base.is_r500 ? 512 : 32;
     compiler.code = &r300->blit.fp_code;
     compiler.AllocateHwInputs = fp_allocate_hw_inputs;
 
index 4e457b51ebae165d2bf5a2d78d1c8d1122d0f480..a0a26f1b38d732b2d3207a9c8361ee2a606d274a 100644 (file)
@@ -226,6 +226,7 @@ static void translate_fragment_program(struct gl_context *ctx, struct r300_fragm
        compiler.Base.max_temp_regs = (compiler.Base.is_r500) ? 128 : 32;
        compiler.Base.max_constants = compiler.Base.is_r500 ? 256 : 32;
        compiler.Base.max_alu_insts = compiler.Base.is_r500 ? 512 : 64;
+       compiler.Base.max_tex_insts = compiler.Base.is_r500 ? 512 : 32;
        compiler.OutputDepth = FRAG_RESULT_DEPTH;
        memset(compiler.OutputColor, 0, 4 * sizeof(unsigned));
        compiler.OutputColor[0] = FRAG_RESULT_COLOR;
index f7705b0f6fe2ffe94a9bc576f787ded207351570..2b9d85fae8b82312b496d0fb2eb1a44d4c527331 100644 (file)
@@ -1658,6 +1658,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #       define R300_PFS_CNTL_TEX_OFFSET_MASK     (31 << 13)
 #       define R300_PFS_CNTL_TEX_END_SHIFT       18
 #       define R300_PFS_CNTL_TEX_END_MASK        (31 << 18)
+#       define R400_PFS_CNTL_TEX_OFFSET_MSB_SHIFT 24
+#       define R400_PFS_CNTL_TEX_OFFSET_MSB_MASK (0xf << 24)
+#       define R400_PFS_CNTL_TEX_END_MSB_SHIFT   28
+#       define R400_PFS_CNTL_TEX_END_MSB_MASK    (0xf << 28)
 
 /* gap */
 
@@ -1682,6 +1686,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #       define R300_TEX_SIZE_MASK           (31 << 17)
 #      define R300_RGBA_OUT                (1 << 22)
 #      define R300_W_OUT                   (1 << 23)
+#       define R400_TEX_START_MSB_SHIFT     24
+#       define R400_TEX_START_MSG_MASK      (0xf << 24)
+#       define R400_TEX_SIZE_MSB_SHIFT      28
+#       define R400_TEX_SIZE_MSG_MASK       (0xf << 28)
 
 /* TEX
  * As far as I can tell, texture instructions cannot write into output
@@ -1702,6 +1710,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #              define R300_TEX_OP_TXP          3
 #              define R300_TEX_OP_TXB          4
 #      define R300_TEX_INST_MASK               (7 << 15)
+#      define R400_SRC_ADDR_EXT_BIT         (1 << 19)
+#      define R400_DST_ADDR_EXT_BIT         (1 << 20)
 
 /* Output format from the unfied shader */
 #define R300_US_OUT_FMT                     0x46A4
@@ -1979,6 +1989,40 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #       define R300_ALU_OUTA_CLAMP              (1 << 30)
 /* END: Fragment program instruction set */
 
+/* R4xx extended fragment shader registers. */
+#define R400_US_ALU_EXT_ADDR_0              0x4ac0 /* up to 63 (0x4bbc) */
+#   define R400_ADDR_EXT_RGB_MSB_BIT(x)     (1 << (x))
+#   define R400_ADDRD_EXT_RGB_MSB_BIT       0x08
+#   define R400_ADDR_EXT_A_MSB_BIT(x)       (1 << ((x) + 4))
+#   define R400_ADDRD_EXT_A_MSB_BIT         0x80
+
+#define R400_US_CODE_BANK                   0x46b8
+#   define R400_BANK_SHIFT                  0
+#   define R400_BANK_MASK                   0xf
+#   define R400_R390_MODE_ENABLE            (1 << 4)
+#define R400_US_CODE_EXT                    0x46bc
+#   define R400_ALU_OFFSET_MSB_SHIFT        0
+#   define R400_ALU_OFFSET_MSB_MASK         (0x7 << 0)
+#   define R400_ALU_SIZE_MSB_SHIFT          3
+#   define R400_ALU_SIZE_MSB_MASK           (0x7 << 3)
+#   define R400_ALU_START0_MSB_SHIFT        6
+#   define R400_ALU_START0_MSB_MASK         (0x7 << 6)
+#   define R400_ALU_SIZE0_MSB_SHIFT         9
+#   define R400_ALU_SIZE0_MSB_MASK          (0x7 << 9)
+#   define R400_ALU_START1_MSB_SHIFT        12
+#   define R400_ALU_START1_MSB_MASK         (0x7 << 12)
+#   define R400_ALU_SIZE1_MSB_SHIFT         15
+#   define R400_ALU_SIZE1_MSB_MASK          (0x7 << 15)
+#   define R400_ALU_START2_MSB_SHIFT        18
+#   define R400_ALU_START2_MSB_MASK         (0x7 << 18)
+#   define R400_ALU_SIZE2_MSB_SHIFT         21
+#   define R400_ALU_SIZE2_MSB_MASK          (0x7 << 21)
+#   define R400_ALU_START3_MSB_SHIFT        24
+#   define R400_ALU_START3_MSB_MASK         (0x7 << 24)
+#   define R400_ALU_SIZE3_MSB_SHIFT         27
+#   define R400_ALU_SIZE3_MSB_MASK          (0x7 << 27)
+/* END: R4xx extended fragment shader registers. */
+
 /* Fog: Fog Blending Enable */
 #define R300_FG_FOG_BLEND                             0x4bc0
 #       define R300_FG_FOG_BLEND_DISABLE              (0 << 0)
index 471a3723cb904aa2a86dde0649dd107be5cb7ef2..232603ece5983c8db495984fc72c1bd24ccef023 100644 (file)
@@ -128,7 +128,6 @@ static void translate_dstreg(struct rc_dst_register * dest, struct prog_dst_regi
 {
        dest->File = translate_register_file(src->File);
        dest->Index = src->Index;
-       dest->RelAddr = src->RelAddr;
        dest->WriteMask = src->WriteMask;
 }
 
index cfb923efdd542f90cc1ad6841539f447fd30d2fc..e527c379b6203448818a6e3a33608ae67abd3016 100644 (file)
@@ -624,10 +624,7 @@ GLboolean evergreenSetupFragmentProgram(struct gl_context * ctx)
             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);
+            CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
     }
 
     unBit = 1 << VERT_RESULT_COL0;
@@ -663,10 +660,7 @@ GLboolean evergreenSetupFragmentProgram(struct gl_context * ctx)
             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);
+            CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
     }
 
     for(i=0; i<8; i++)
@@ -694,10 +688,7 @@ GLboolean evergreenSetupFragmentProgram(struct gl_context * ctx)
             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);
+            CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
     }
     unBit = 1 << FRAG_ATTRIB_PNTC;
     if(mesa_fp->Base.InputsRead & unBit)
@@ -706,10 +697,7 @@ GLboolean evergreenSetupFragmentProgram(struct gl_context * ctx)
             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);
+            CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
             SETbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, PT_SPRITE_TEX_bit);
     }
 
@@ -725,10 +713,7 @@ GLboolean evergreenSetupFragmentProgram(struct gl_context * ctx)
             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);
+            CLEARbit(evergreen->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
         }
     }
 
index 0323e32d70537236ee32bc3d497a2a609ccccf38..40494cd6af087f9297de0c532b7779147e9c0ad0 100644 (file)
@@ -657,10 +657,7 @@ GLboolean r700SetupFragmentProgram(struct gl_context * ctx)
             SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit);
             SETfield(r700->SPI_PS_INPUT_CNTL[ui].u32All, ui,
                      SEMANTIC_shift, SEMANTIC_mask);
-            if (r700->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit)
-                    SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
-            else
-                    CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+            CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
     }
 
     unBit = 1 << VERT_RESULT_COL0;
@@ -696,10 +693,7 @@ GLboolean r700SetupFragmentProgram(struct gl_context * ctx)
             SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit);
             SETfield(r700->SPI_PS_INPUT_CNTL[ui].u32All, ui,
                      SEMANTIC_shift, SEMANTIC_mask);
-            if (r700->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit)
-                    SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
-            else
-                    CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+            CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
     }
 
     for(i=0; i<8; i++)
@@ -728,10 +722,7 @@ GLboolean r700SetupFragmentProgram(struct gl_context * ctx)
             SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit);
             SETfield(r700->SPI_PS_INPUT_CNTL[ui].u32All, ui,
                      SEMANTIC_shift, SEMANTIC_mask);
-            if (r700->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit)
-                    SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
-            else
-                    CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+            CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
     }
     unBit = 1 << FRAG_ATTRIB_PNTC;
     if(mesa_fp->Base.InputsRead & unBit)
@@ -759,10 +750,7 @@ GLboolean r700SetupFragmentProgram(struct gl_context * ctx)
             SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, SEL_CENTROID_bit);
             SETfield(r700->SPI_PS_INPUT_CNTL[ui].u32All, ui,
                             SEMANTIC_shift, SEMANTIC_mask);
-            if (r700->SPI_INTERP_CONTROL_0.u32All & FLAT_SHADE_ENA_bit)
-                       SETbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
-            else
-                       CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
+            CLEARbit(r700->SPI_PS_INPUT_CNTL[ui].u32All, FLAT_SHADE_bit);
         }
     }
 
index 399052cbcbd08ef315b79b15d3472d8226863882..bd6f1c79504663c9bff1fe855d6c8f64131b4b00 100644 (file)
@@ -34,7 +34,6 @@
 #define PCI_CHIP_RV350_AV               0x4156
 #define PCI_CHIP_RS250_4237            0x4237
 #define PCI_CHIP_R200_BB               0x4242
-#define PCI_CHIP_R200_BC               0x4243
 #define PCI_CHIP_RS100_4336            0x4336
 #define PCI_CHIP_RS200_4337            0x4337
 #define PCI_CHIP_RS250_4437            0x4437
index 7361adffcf7f60ad8501955813ed612afe7c83da..0d73c0e3b1ba49404d46f8a86860f9ae78c6a5f8 100644 (file)
@@ -905,7 +905,7 @@ void radeon_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GL
        if (!driContext->driScreenPriv->dri2.enabled)
                return;
 
-       if (!radeon->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) {
+       if (ctx->DrawBuffer->Name == 0) {
                if (radeon->is_front_buffer_rendering) {
                        ctx->Driver.Flush(ctx);
                }
index 819d9dd5750fc1a61669097cdf97b9800044d910..405aecb19ecd242d70fedad113b82c8f2dd89253 100644 (file)
@@ -204,7 +204,7 @@ GLboolean radeonInitContext(radeonContextPtr radeon,
                shareCtx = ((radeonContextPtr)sharedContextPrivate)->glCtx;
        else
                shareCtx = NULL;
-       radeon->glCtx = _mesa_create_context(glVisual, shareCtx,
+       radeon->glCtx = _mesa_create_context(API_OPENGL, glVisual, shareCtx,
                                            functions, (void *)radeon);
        if (!radeon->glCtx)
                return GL_FALSE;
@@ -212,8 +212,6 @@ GLboolean radeonInitContext(radeonContextPtr radeon,
        ctx = radeon->glCtx;
        driContextPriv->driverPrivate = radeon;
 
-       meta_init_metaops(ctx, &radeon->meta);
-
        _mesa_meta_init(ctx);
 
        /* DRI fields */
@@ -320,7 +318,6 @@ void radeonDestroyContext(__DRIcontext *driContextPriv )
 
        radeonFreeDmaRegions(radeon);
        radeonReleaseArrays(radeon->glCtx, ~0);
-       meta_destroy_metaops(&radeon->meta);
        if (radeon->vtbl.free_context)
                radeon->vtbl.free_context(radeon->glCtx);
        _swsetup_DestroyContext( radeon->glCtx );
index c62913afd0c97ead3a3a87762a531879b75e6267..3895ab8c4d8a9b66365ebb384467011454e70a11 100644 (file)
@@ -14,7 +14,6 @@
 #include "dri_util.h"
 #include "tnl/t_vertex.h"
 
-#include "dri_metaops.h"
 struct radeon_context;
 
 #include "radeon_bocs_wrapper.h"
@@ -509,8 +508,6 @@ struct radeon_context {
     */
    GLboolean is_front_buffer_reading;
 
-   struct dri_metaops meta;
-
    struct {
        struct radeon_query_object *current;
        struct radeon_state_atom queryobj;
index 6656d391e0966b2ba020001209ffd428486b63d8..d3c9257fb6611c0828ac94cdf44172718a10a330 100644 (file)
@@ -485,6 +485,8 @@ radeon_update_wrapper(struct gl_context *ctx, struct radeon_renderbuffer *rrb,
                case MESA_FORMAT_S8_Z24:
                        rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
                        break;
+               default:
+                       _mesa_problem(ctx, "Unexpected texture format in radeon_update_wrapper()");
        }
                
        rrb->cpp = _mesa_get_format_bytes(texImage->TexFormat);
index a35fcfe9d7faffe700524eecc06bd6db27656619..56c5959b0aa12fb97da5ac610700add65842c15a 100644 (file)
@@ -628,7 +628,6 @@ static int radeon_set_screen_flags(radeonScreenPtr screen, int device_id)
       break;
 
    case PCI_CHIP_R200_BB:
-   case PCI_CHIP_R200_BC:
    case PCI_CHIP_R200_QH:
    case PCI_CHIP_R200_QL:
    case PCI_CHIP_R200_QM:
index 92fb4f44884b6c11d6d77d89c792f2f94a88c97e..681ed9aae34b053771f286f7af44e4433e930aad 100644 (file)
@@ -314,7 +314,7 @@ savageCreateContext( gl_api api,
       shareCtx = ((savageContextPtr) sharedContextPrivate)->glCtx;
    else 
       shareCtx = NULL;
-   ctx = _mesa_create_context(mesaVis, shareCtx, &functions, imesa);
+   ctx = _mesa_create_context(api, mesaVis, shareCtx, &functions, imesa);
    if (!ctx) {
       free(imesa);
       return GL_FALSE;
index c5a9fdfb2a039b701a0cdb66d9673fe43028d15e..26ecfc463caf8e882890ff7276630107d3c5d211 100644 (file)
@@ -186,7 +186,7 @@ sisCreateContext( gl_api api,
       shareCtx = ((sisContextPtr)sharedContextPrivate)->glCtx;
    else 
       shareCtx = NULL;
-   smesa->glCtx = _mesa_create_context( glVisual, shareCtx,
+   smesa->glCtx = _mesa_create_context( API_OPENGL, glVisual, shareCtx,
                                         &functions, (void *) smesa);
    if (!smesa->glCtx) {
       FREE(smesa);
index c7940e9c0da0aa273351e08b6b13c5684fe76879..719b406ec05feeef79ff22f8dace5ba3230d3954 100644 (file)
@@ -561,6 +561,60 @@ swrast_init_driver_functions(struct dd_function_table *driver)
     driver->ChooseTextureFormat = swrastChooseTextureFormat;
 }
 
+static const char *es2_extensions[] = {
+   /* Used by mesa internally (cf all_mesa_extensions in ../common/utils.c) */
+   "GL_ARB_draw_buffers",
+   "GL_ARB_multisample",
+   "GL_ARB_texture_compression",
+   "GL_ARB_transpose_matrix",
+   "GL_ARB_vertex_buffer_object",
+   "GL_ARB_window_pos",
+   "GL_EXT_blend_func_separate",
+   "GL_EXT_compiled_vertex_array",
+   "GL_EXT_framebuffer_blit",
+   "GL_EXT_multi_draw_arrays",
+   "GL_EXT_polygon_offset",
+   "GL_EXT_texture_object",
+   "GL_EXT_vertex_array",
+   "GL_IBM_multimode_draw_arrays",
+   "GL_MESA_window_pos",
+   "GL_NV_vertex_program",
+
+   /* Required by GLES2 */
+   "GL_ARB_fragment_program",
+   "GL_ARB_fragment_shader",
+   "GL_ARB_multitexture",
+   "GL_ARB_shader_objects",
+   "GL_ARB_texture_cube_map",
+   "GL_ARB_texture_mirrored_repeat",
+   "GL_ARB_texture_non_power_of_two",
+   "GL_ARB_vertex_shader",
+   "GL_EXT_blend_color",
+   "GL_EXT_blend_equation_separate",
+   "GL_EXT_blend_minmax",
+   "GL_EXT_blend_subtract",
+   "GL_EXT_stencil_wrap",
+
+   /* Optional GLES2 */
+   "GL_ARB_framebuffer_object",
+   "GL_EXT_texture_filter_anisotropic",
+   "GL_ARB_depth_texture",
+   "GL_EXT_packed_depth_stencil",
+   "GL_EXT_framebuffer_object",
+   NULL,
+};
+
+static void
+InitExtensionsES2(struct gl_context *ctx)
+{
+   int i;
+
+   /* Can't use driInitExtensions() since it uses extensions from
+    * main/remap_helper.h when called the first time. */
+
+   for (i = 0; es2_extensions[i]; i++)
+      _mesa_enable_extension(ctx, es2_extensions[i]);
+}
 
 /**
  * Context-related functions.
@@ -597,7 +651,7 @@ dri_create_context(gl_api api,
     mesaCtx = &ctx->Base;
 
     /* basic context setup */
-    if (!_mesa_initialize_context(mesaCtx, visual, sharedCtx, &functions, (void *) cPriv)) {
+    if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions, (void *) cPriv)) {
        goto context_fail;
     }
 
@@ -617,16 +671,29 @@ dri_create_context(gl_api api,
        tnl->Driver.RunPipeline = _tnl_run_pipeline;
     }
 
-    _mesa_enable_sw_extensions(mesaCtx);
-    _mesa_enable_1_3_extensions(mesaCtx);
-    _mesa_enable_1_4_extensions(mesaCtx);
-    _mesa_enable_1_5_extensions(mesaCtx);
-    _mesa_enable_2_0_extensions(mesaCtx);
-    _mesa_enable_2_1_extensions(mesaCtx);
-
     _mesa_meta_init(mesaCtx);
+    _mesa_enable_sw_extensions(mesaCtx);
 
-    driInitExtensions( mesaCtx, NULL, GL_FALSE );
+    switch (api) {
+    case API_OPENGL:
+        _mesa_enable_1_3_extensions(mesaCtx);
+        _mesa_enable_1_4_extensions(mesaCtx);
+        _mesa_enable_1_5_extensions(mesaCtx);
+        _mesa_enable_2_0_extensions(mesaCtx);
+        _mesa_enable_2_1_extensions(mesaCtx);
+
+        driInitExtensions( mesaCtx, NULL, GL_FALSE );
+        break;
+    case API_OPENGLES:
+        _mesa_enable_1_3_extensions(mesaCtx);
+        _mesa_enable_1_4_extensions(mesaCtx);
+        _mesa_enable_1_5_extensions(mesaCtx);
+
+        break;
+    case API_OPENGLES2:
+        InitExtensionsES2( mesaCtx);
+        break;
+    }
 
     return GL_TRUE;
 
index 63dfa5ae746687e139339f60354da475f9164da7..ad151359e67546ca4b4a4a0f34783d4bd35b222c 100644 (file)
@@ -194,7 +194,7 @@ GLboolean tdfxCreateContext( gl_api api,
    else 
       shareCtx = NULL;
 
-   fxMesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
+   fxMesa->glCtx = _mesa_create_context(api, mesaVis, shareCtx,
                                         &functions, (void *) fxMesa);
    if (!fxMesa->glCtx) {
       FREE(fxMesa);
index 963609bde4aaff99ddd1513cca6622485e56eede..77d7116611a9539cbd07b849824e14f2a01627af 100644 (file)
@@ -542,7 +542,7 @@ viaCreateContext(gl_api api,
     else
         shareCtx = NULL;
 
-    vmesa->glCtx = _mesa_create_context(visual, shareCtx, &functions,
+    vmesa->glCtx = _mesa_create_context(API_OPENGL, visual, shareCtx, &functions,
                                        (void*) vmesa);
     
     vmesa->shareCtx = shareCtx;
index 5195bca97fa5e5437f4aaa5ddc742200d19e9bdf..1e0ac4c7a1f6c34fc7d84f4f53898d6ae037737e 100644 (file)
@@ -722,7 +722,7 @@ glFBDevCreateContext( const GLFBDevVisualPtr visual, GLFBDevContextPtr share )
    functions.GetBufferSize = get_buffer_size;
    functions.Viewport = viewport;
 
-   if (!_mesa_initialize_context(&ctx->glcontext, &visual->glvisual,
+   if (!_mesa_initialize_context(&ctx->glcontext, API_OPENGL, &visual->glvisual,
                                  share ? &share->glcontext : NULL,
                                  &functions, (void *) ctx)) {
       free(ctx);
index 50dd4526e19d8a57e0807fb50d6ee5001ba0cc02..39ab09af805bf4c79804c2471b4b9f78f31a7fe4 100644 (file)
@@ -40,7 +40,7 @@ $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_NAME): $(OBJECTS) $(CORE_MESA)
                -major $(MESA_MAJOR) -minor $(MESA_MINOR) -patch $(MESA_TINY) \
                -install $(TOP)/$(LIB_DIR) -cplusplus $(MKLIB_OPTIONS) \
                -id $(INSTALL_LIB_DIR)/lib$(OSMESA_LIB).$(MESA_MAJOR).dylib \
-               $(OSMESA_LIB_DEPS) $(OBJECTS) $(CORE_MESA) $(TALLOC_LIBS)
+               $(OSMESA_LIB_DEPS) $(OBJECTS) $(CORE_MESA)
 
 
 
index e1f0c69bacfb10446ae3292325a6f9ec4a757920..98f01fe057ea20385166c764451ed76237411002 100644 (file)
@@ -1155,6 +1155,7 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
       functions.GetBufferSize = NULL;
 
       if (!_mesa_initialize_context(&osmesa->mesa,
+                                    API_OPENGL,
                                     osmesa->gl_visual,
                                     sharelist ? &sharelist->mesa
                                               : (struct gl_context *) NULL,
index 833e2526f3c12359083455d57288a10fed0c36bd..4a8b1b283d50135a169ba47f16e7c59555f05926 100644 (file)
@@ -1479,7 +1479,8 @@ WMesaContext WMesaCreateContext(HDC hDC,
 
     /* initialize the Mesa context data */
     ctx = &c->gl_ctx;
-    _mesa_initialize_context(ctx, visual, NULL, &functions, (void *)c);
+    _mesa_initialize_context(ctx, API_OPENGL, visual,
+                             NULL, &functions, (void *)c);
 
     /* visual no longer needed - it was copied by _mesa_initialize_context() */
     _mesa_destroy_visual(visual);
index 10ea05785060d4efa377e88ace1e3f015154f690..9aedd2e3c4d91e03cc700fa60875e486f6287d0f 100644 (file)
@@ -1414,7 +1414,7 @@ SkipPrimaryCreate:
        }
 
 #ifdef _USE_GLD3_WGL
-       lpCtx->glCtx = _mesa_create_context(lpCtx->glVis, NULL, (void *)lpCtx, GL_TRUE);
+       lpCtx->glCtx = _mesa_create_context(API_OPENGL, lpCtx->glVis, NULL, (void *)lpCtx, GL_TRUE);
 #else
        // Create the Mesa context
        lpCtx->glCtx = (*mesaFuncs.gl_create_context)(
index 1c43a38557d8f93e93290c4286becf993eb69f04..1b070f0a11e32a80dd142b1f6ba29f04d1001e0a 100644 (file)
@@ -944,7 +944,6 @@ void gld_update_state_DX7(
 // Stubs for future use.
 /*     _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX);
        _GLD_TEST_STATE(_NEW_COLOR_MATRIX);
-       _GLD_TEST_STATE(_NEW_ACCUM);
        _GLD_TEST_STATE(_NEW_EVAL);
        _GLD_TEST_STATE(_NEW_HINT);
        _GLD_TEST_STATE(_NEW_LINE);
@@ -967,7 +966,6 @@ void gld_update_state_DX7(
        }
        _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX);
        _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX);
-       _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM);
        _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL);
        _GLD_TEST_UNHANDLED_STATE(_NEW_HINT);
        _GLD_TEST_UNHANDLED_STATE(_NEW_LINE);
index 7fc50004de89cfe81b376e1df28cf780b8bf3a49..d66318e1149824ad597a43b0e045d77d634554ad 100644 (file)
@@ -62,7 +62,6 @@
 #include "swrast/s_depth.h"
 #include "swrast/s_lines.h"
 #include "swrast/s_triangle.h"
-#include "swrast/s_trispan.h"
 #include "tnl/tnl.h"
 #include "tnl/t_context.h"
 #include "tnl/t_pipeline.h"
index c4c2e0b5676969dae03351051003b097ef41902f..4c272c95d6c90ecbe7d02c7ad8b4d18f1f0fd9f9 100644 (file)
@@ -924,7 +924,6 @@ void gld_update_state_DX8(
 // Stubs for future use.
 /*     _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX);
        _GLD_TEST_STATE(_NEW_COLOR_MATRIX);
-       _GLD_TEST_STATE(_NEW_ACCUM);
        _GLD_TEST_STATE(_NEW_EVAL);
        _GLD_TEST_STATE(_NEW_HINT);
        _GLD_TEST_STATE(_NEW_LINE);
@@ -947,7 +946,6 @@ void gld_update_state_DX8(
        }
        _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX);
        _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX);
-       _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM);
        _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL);
        _GLD_TEST_UNHANDLED_STATE(_NEW_HINT);
        _GLD_TEST_UNHANDLED_STATE(_NEW_LINE);
index 5b9dac09c6d6dcf94961f035b0befc01f1e4998d..a2c5d87ecd5dc18f9098b00db486b9df97084908 100644 (file)
@@ -62,7 +62,6 @@
 #include "swrast/s_depth.h"
 #include "swrast/s_lines.h"
 #include "swrast/s_triangle.h"
-#include "swrast/s_trispan.h"
 #include "tnl/tnl.h"
 #include "tnl/t_context.h"
 #include "tnl/t_pipeline.h"
index aab708520165a6084f914344ef6e2310ec3f6b62..171585dcf81fce8aefe21938e7f2be5d06865e20 100644 (file)
@@ -955,7 +955,6 @@ void gld_update_state_DX9(
 // Stubs for future use.
 /*     _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX);
        _GLD_TEST_STATE(_NEW_COLOR_MATRIX);
-       _GLD_TEST_STATE(_NEW_ACCUM);
        _GLD_TEST_STATE(_NEW_EVAL);
        _GLD_TEST_STATE(_NEW_HINT);
        _GLD_TEST_STATE(_NEW_LINE);
@@ -977,7 +976,6 @@ void gld_update_state_DX9(
        }
        _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX);
        _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX);
-       _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM);
        _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL);
        _GLD_TEST_UNHANDLED_STATE(_NEW_HINT);
        _GLD_TEST_UNHANDLED_STATE(_NEW_LINE);
index 99edd26e9d289e96cf9b48fe2aa2e3dfa16ba370..65a00ae1b59962b562ec7f39f1c744c30120e7c5 100644 (file)
@@ -62,7 +62,6 @@
 #include "swrast/s_depth.h"
 #include "swrast/s_lines.h"
 #include "swrast/s_triangle.h"
-#include "swrast/s_trispan.h"
 #include "tnl/tnl.h"
 #include "tnl/t_context.h"
 #include "tnl/t_pipeline.h"
index 7a26df8071e6cdda564e93a0723d49331cd2893d..bc66ec798884ade882bf20c2893f266078a887f2 100644 (file)
@@ -61,7 +61,6 @@
 #include "swrast/s_depth.h"
 #include "swrast/s_lines.h"
 #include "swrast/s_triangle.h"
-#include "swrast/s_trispan.h"
 #include "tnl/tnl.h"
 #include "tnl/t_context.h"
 #include "tnl/t_pipeline.h"
index 577e27d4da3fc8f808a440dd73724e84e4ce80a7..48657b44be1caba6a235fcadf9da7f4184096d90 100644 (file)
@@ -1292,7 +1292,7 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
 
    /* deallocate unused windows/buffers */
 #if 0
-   XMesaGarbageCollect();
+   XMesaGarbageCollect(dpy);
 #endif
 
    xmvis = find_glx_visual( dpy, visinfo );
@@ -1533,7 +1533,7 @@ Fake_glXDestroyContext( Display *dpy, GLXContext ctx )
    MakeCurrent_PrevDrawBuffer = 0;
    MakeCurrent_PrevReadBuffer = 0;
    XMesaDestroyContext( glxCtx->xmesaContext );
-   XMesaGarbageCollect();
+   XMesaGarbageCollect(dpy);
    free(glxCtx);
 }
 
@@ -2327,7 +2327,7 @@ Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config,
       return 0;
 
    /* deallocate unused windows/buffers */
-   XMesaGarbageCollect();
+   XMesaGarbageCollect(dpy);
 
    glxCtx->xmesaContext = XMesaCreateContext(xmvis,
                                    shareCtx ? shareCtx->xmesaContext : NULL);
@@ -2542,7 +2542,7 @@ Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int re
       return 0;
 
    /* deallocate unused windows/buffers */
-   XMesaGarbageCollect();
+   XMesaGarbageCollect(dpy);
 
    glxCtx->xmesaContext = XMesaCreateContext(xmvis,
                                    shareCtx ? shareCtx->xmesaContext : NULL);
index b5eabadf486b5158f1efb3cbc38b332af2b1f962..aad902d1eda0eda482a47848bc0f536c3ef2db89 100644 (file)
@@ -1398,7 +1398,7 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
    /* initialize with default driver functions, then plug in XMesa funcs */
    _mesa_init_driver_functions(&functions);
    xmesa_init_driver_functions(v, &functions);
-   if (!_mesa_initialize_context(mesaCtx, &v->mesa_visual,
+   if (!_mesa_initialize_context(mesaCtx, API_OPENGL, &v->mesa_visual,
                       share_list ? &(share_list->mesa) : (struct gl_context *) NULL,
                       &functions, (void *) c)) {
       free(c);
@@ -2064,12 +2064,12 @@ void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy)
  * Look for XMesaBuffers whose X window has been destroyed.
  * Deallocate any such XMesaBuffers.
  */
-void XMesaGarbageCollect( void )
+void XMesaGarbageCollect( XMesaDisplay* dpy )
 {
    XMesaBuffer b, next;
    for (b=XMesaBufferList; b; b=next) {
       next = b->Next;
-      if (b->display && b->frontxrb->drawable && b->type == WINDOW) {
+      if (b->display && b->display == dpy && b->frontxrb->drawable && b->type == WINDOW) {
          XSync(b->display, False);
          if (!window_exists( b->display, b->frontxrb->drawable )) {
             /* found a dead window, free the ancillary info */
index 98737fab248e06ebcbfe83bc91829d1721a4d9f7..347394e0a26f930a0a27776a689d58bd1580d70c 100644 (file)
@@ -324,7 +324,7 @@ extern const char *XMesaGetString( XMesaContext c, int name );
  *
  * New in Mesa 2.3.
  */
-extern void XMesaGarbageCollect( void );
+extern void XMesaGarbageCollect( XMesaDisplay* dpy );
 
 
 
index 50446a9093a21c8f395acd507118178e60f3270f..0f82d0a38e16d70e2dfd96d8013759d3f17a90f1 100644 (file)
                <value name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES" category="OES_texture_cube_map"/>
        </desc>
 
-       <desc name="internalFormat" error="GL_INVALID_VALUE">
+       <desc name="internalFormat">
                <value name="GL_ALPHA"/>
+
+               <desc name="format" error="GL_INVALID_VALUE">
+                       <value name="GL_ALPHA"/>
+               </desc>
+       </desc>
+
+       <desc name="internalFormat">
                <value name="GL_RGB"/>
+
+               <desc name="format" error="GL_INVALID_VALUE">
+                       <value name="GL_RGB"/>
+               </desc>
+       </desc>
+
+       <desc name="internalFormat">
                <value name="GL_RGBA"/>
-               <value name="GL_BGRA_EXT"/>
+
+               <desc name="format" error="GL_INVALID_VALUE">
+                       <value name="GL_RGBA"/>
+               </desc>
+       </desc>
+
+       <desc name="internalFormat">
                <value name="GL_LUMINANCE"/>
+
+               <desc name="format" error="GL_INVALID_VALUE">
+                       <value name="GL_LUMINANCE"/>
+               </desc>
+       </desc>
+
+       <desc name="internalFormat">
                <value name="GL_LUMINANCE_ALPHA"/>
-               <value name="GL_DEPTH_COMPONENT" category="OES_depth_texture"/>
-               <value name="GL_DEPTH_STENCIL_OES" category="OES_packed_depth_stencil"/>
+
+               <desc name="format" error="GL_INVALID_VALUE">
+                       <value name="GL_LUMINANCE_ALPHA"/>
+               </desc>
+       </desc>
+
+       <desc name="internalFormat" category="OES_depth_texture">
+               <value name="GL_DEPTH_COMPONENT"/>
+
+               <desc name="format" error="GL_INVALID_VALUE">
+                       <value name="GL_DEPTH_COMPONENT"/>
+               </desc>
+       </desc>
+
+       <desc name="internalFormat" category="OES_packed_depth_stencil">
+               <value name="GL_DEPTH_STENCIL_OES"/>
+
+               <desc name="format" error="GL_INVALID_VALUE">
+                       <value name="GL_DEPTH_STENCIL_OES"/>
+               </desc>
+       </desc>
+
+       <desc name="internalFormat" category="EXT_texture_format_BGRA8888">
+               <value name="GL_BGRA_EXT"/>
+
+               <desc name="format" error="GL_INVALID_VALUE">
+                       <value name="GL_BGRA_EXT"/>
+               </desc>
        </desc>
 
        <desc name="border" error="GL_INVALID_VALUE">
index 940f398f0230bac4b16953e6e2fae796f093cdec..6a83930a13dca0494f522e0ebaa02c5751ac67da 100644 (file)
@@ -51,7 +51,6 @@ _mesa_ClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
    if (TEST_EQ_4V(tmp, ctx->Accum.ClearColor))
       return;
 
-   FLUSH_VERTICES(ctx, _NEW_ACCUM);
    COPY_4FV( ctx->Accum.ClearColor, tmp );
 }
 
index 9e9728c2c62480131622206a18e14bc53a6719d3..46010223370398ab9cc9f33e25190b4a9f5d4406 100644 (file)
@@ -234,7 +234,7 @@ _mesa_initialize_array_object( struct gl_context *ctx,
    init_array(ctx, &obj->Weight, 1, GL_FLOAT);
    init_array(ctx, &obj->Normal, 3, GL_FLOAT);
    init_array(ctx, &obj->Color, 4, GL_FLOAT);
-   init_array(ctx, &obj->SecondaryColor, 4, GL_FLOAT);
+   init_array(ctx, &obj->SecondaryColor, 3, GL_FLOAT);
    init_array(ctx, &obj->FogCoord, 1, GL_FLOAT);
    init_array(ctx, &obj->Index, 1, GL_FLOAT);
    for (i = 0; i < Elements(obj->TexCoord); i++) {
index 43e2f7f8617518ca043c60b414891123ac229cff..c74a168036a7c5aac49f6ccf3c0750febbe4a546 100644 (file)
@@ -317,7 +317,7 @@ _mesa_BlendEquation( GLenum mode )
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "glBlendEquation %s\n",
+      _mesa_debug(ctx, "glBlendEquation(%s)\n",
                   _mesa_lookup_enum_by_nr(mode));
 
    if (!legal_blend_equation(ctx, mode, GL_FALSE)) {
@@ -398,7 +398,7 @@ _mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA )
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "glBlendEquationSeparateEXT %s %s\n",
+      _mesa_debug(ctx, "glBlendEquationSeparateEXT(%s %s)\n",
                   _mesa_lookup_enum_by_nr(modeRGB),
                   _mesa_lookup_enum_by_nr(modeA));
 
@@ -454,7 +454,7 @@ _mesa_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeA)
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "glBlendEquationSeparatei %u, %s %s\n", buf,
+      _mesa_debug(ctx, "glBlendEquationSeparatei(%u, %s %s)\n", buf,
                   _mesa_lookup_enum_by_nr(modeRGB),
                   _mesa_lookup_enum_by_nr(modeA));
 
@@ -545,6 +545,10 @@ _mesa_AlphaFunc( GLenum func, GLclampf ref )
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glAlphaFunc(%s, %f)\n",
+                  _mesa_lookup_enum_by_nr(func), ref);
+
    switch (func) {
    case GL_NEVER:
    case GL_LESS:
@@ -590,6 +594,9 @@ _mesa_LogicOp( GLenum opcode )
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glLogicOp(%s)\n", _mesa_lookup_enum_by_nr(opcode));
+
    switch (opcode) {
       case GL_CLEAR:
       case GL_SET:
@@ -664,7 +671,8 @@ _mesa_ColorMask( GLboolean red, GLboolean green,
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "glColorMask %d %d %d %d\n", red, green, blue, alpha);
+      _mesa_debug(ctx, "glColorMask(%d, %d, %d, %d)\n",
+                  red, green, blue, alpha);
 
    /* Shouldn't have any information about channel depth in core mesa
     * -- should probably store these as the native booleans:
index 1f9a5212c0415f08ac678cee267779d512c3e241..75afae0add12f3e10541bae23975778553bf7cb0 100644 (file)
@@ -970,6 +970,10 @@ _mesa_BindBufferARB(GLenum target, GLuint buffer)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glBindBuffer(%s, %u)\n",
+                  _mesa_lookup_enum_by_nr(target), buffer);
+
    bind_buffer_object(ctx, target, buffer);
 }
 
@@ -1064,6 +1068,9 @@ _mesa_GenBuffersARB(GLsizei n, GLuint *buffer)
    GLint i;
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glGenBuffers(%d)\n", n);
+
    if (n < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB");
       return;
@@ -1121,6 +1128,12 @@ _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size,
    struct gl_buffer_object *bufObj;
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glBufferData(%s, %ld, %p, %s)\n",
+                  _mesa_lookup_enum_by_nr(target),
+                  (long int) size, data,
+                  _mesa_lookup_enum_by_nr(usage));
+
    if (size < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)");
       return;
index e017939a45c55275b59b6ebce0591dc489145c7c..a942314552e07b1ab48d3dbb321b57fd1feb522b 100644 (file)
@@ -886,12 +886,12 @@ _mesa_alloc_dispatch_table(int size)
  * \param driverContext pointer to driver-specific context data
  */
 GLboolean
-_mesa_initialize_context_for_api(struct gl_context *ctx,
-                                gl_api api,
-                                const struct gl_config *visual,
-                                struct gl_context *share_list,
-                                const struct dd_function_table *driverFunctions,
-                                void *driverContext)
+_mesa_initialize_context(struct gl_context *ctx,
+                         gl_api api,
+                         const struct gl_config *visual,
+                         struct gl_context *share_list,
+                         const struct dd_function_table *driverFunctions,
+                         void *driverContext)
 {
    struct gl_shared_state *shared;
    int i;
@@ -1028,25 +1028,6 @@ _mesa_initialize_context_for_api(struct gl_context *ctx,
 }
 
 
-/**
- * Initialize an OpenGL context.
- */
-GLboolean
-_mesa_initialize_context(struct gl_context *ctx,
-                         const struct gl_config *visual,
-                         struct gl_context *share_list,
-                         const struct dd_function_table *driverFunctions,
-                         void *driverContext)
-{
-   return _mesa_initialize_context_for_api(ctx,
-                                          API_OPENGL,
-                                          visual,
-                                          share_list,
-                                          driverFunctions,
-                                          driverContext);
-}
-
-
 /**
  * Allocate and initialize a struct gl_context structure.
  * Note that the driver needs to pass in its dd_function_table here since
@@ -1063,11 +1044,11 @@ _mesa_initialize_context(struct gl_context *ctx,
  * \return pointer to a new __struct gl_contextRec or NULL if error.
  */
 struct gl_context *
-_mesa_create_context_for_api(gl_api api,
-                            const struct gl_config *visual,
-                            struct gl_context *share_list,
-                            const struct dd_function_table *driverFunctions,
-                            void *driverContext)
+_mesa_create_context(gl_api api,
+                     const struct gl_config *visual,
+                     struct gl_context *share_list,
+                     const struct dd_function_table *driverFunctions,
+                     void *driverContext)
 {
    struct gl_context *ctx;
 
@@ -1078,8 +1059,8 @@ _mesa_create_context_for_api(gl_api api,
    if (!ctx)
       return NULL;
 
-   if (_mesa_initialize_context_for_api(ctx, api, visual, share_list,
-                                       driverFunctions, driverContext)) {
+   if (_mesa_initialize_context(ctx, api, visual, share_list,
+                                driverFunctions, driverContext)) {
       return ctx;
    }
    else {
@@ -1089,22 +1070,6 @@ _mesa_create_context_for_api(gl_api api,
 }
 
 
-/**
- * Create an OpenGL context.
- */
-struct gl_context *
-_mesa_create_context(const struct gl_config *visual,
-                    struct gl_context *share_list,
-                    const struct dd_function_table *driverFunctions,
-                    void *driverContext)
-{
-   return _mesa_create_context_for_api(API_OPENGL, visual,
-                                      share_list,
-                                      driverFunctions,
-                                      driverContext);
-}
-
-
 /**
  * Free the data associated with the given context.
  * 
index 8fb9b4c6b7a6a99aae843bd91b7e0e1ac63e0619..4e391dde4946a3d106d28131f0ec198318a5a8ae 100644 (file)
@@ -99,33 +99,20 @@ _mesa_destroy_visual( struct gl_config *vis );
 /** \name Context-related functions */
 /*@{*/
 
-extern struct gl_context *
-_mesa_create_context( const struct gl_config *visual,
-                      struct gl_context *share_list,
-                      const struct dd_function_table *driverFunctions,
-                      void *driverContext );
-
 extern GLboolean
 _mesa_initialize_context( struct gl_context *ctx,
+                          gl_api api,
                           const struct gl_config *visual,
                           struct gl_context *share_list,
                           const struct dd_function_table *driverFunctions,
                           void *driverContext );
 
 extern struct gl_context *
-_mesa_create_context_for_api(gl_api api,
-                            const struct gl_config *visual,
-                            struct gl_context *share_list,
-                            const struct dd_function_table *driverFunctions,
-                            void *driverContext);
-
-extern GLboolean
-_mesa_initialize_context_for_api(struct gl_context *ctx,
-                                gl_api api,
-                                const struct gl_config *visual,
-                                struct gl_context *share_list,
-                                const struct dd_function_table *driverFunctions,
-                                void *driverContext);
+_mesa_create_context(gl_api api,
+                     const struct gl_config *visual,
+                     struct gl_context *share_list,
+                     const struct dd_function_table *driverFunctions,
+                     void *driverContext);
 
 extern void
 _mesa_free_context_data( struct gl_context *ctx );
index a6a909b48ced8d5e4b8e4a75036db0bdd1164757..78881668e4953684168cd3abde15bd18ca56f201 100644 (file)
@@ -65,13 +65,12 @@ void
 _mesa_print_state( const char *msg, GLuint state )
 {
    _mesa_debug(NULL,
-          "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+          "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
           msg,
           state,
           (state & _NEW_MODELVIEW)       ? "ctx->ModelView, " : "",
           (state & _NEW_PROJECTION)      ? "ctx->Projection, " : "",
           (state & _NEW_TEXTURE_MATRIX)  ? "ctx->TextureMatrix, " : "",
-          (state & _NEW_ACCUM)           ? "ctx->Accum, " : "",
           (state & _NEW_COLOR)           ? "ctx->Color, " : "",
           (state & _NEW_DEPTH)           ? "ctx->Depth, " : "",
           (state & _NEW_EVAL)            ? "ctx->Eval/EvalMap, " : "",
@@ -214,16 +213,6 @@ void
 _mesa_init_debug( struct gl_context *ctx )
 {
    char *c;
-
-   /* Dither disable */
-   ctx->NoDither = _mesa_getenv("MESA_NO_DITHER") ? GL_TRUE : GL_FALSE;
-   if (ctx->NoDither) {
-      if (_mesa_getenv("MESA_DEBUG")) {
-         _mesa_debug(ctx, "MESA_NO_DITHER set - dithering disabled\n");
-      }
-      ctx->Color.DitherFlag = GL_FALSE;
-   }
-
    c = _mesa_getenv("MESA_DEBUG");
    if (c)
       add_debug_flags(c);
@@ -307,8 +296,8 @@ write_texture_image(struct gl_texture_object *texObj,
 /**
  * Write renderbuffer image to a ppm file.
  */
-static void
-write_renderbuffer_image(const struct gl_renderbuffer *rb)
+void
+_mesa_write_renderbuffer_image(const struct gl_renderbuffer *rb)
 {
    GET_CURRENT_CONTEXT(ctx);
    GLubyte *buffer;
@@ -325,6 +314,10 @@ write_renderbuffer_image(const struct gl_renderbuffer *rb)
       type = GL_UNSIGNED_INT_24_8;
    }
    else {
+      _mesa_debug(NULL,
+                  "Unsupported BaseFormat 0x%x in "
+                  "_mesa_write_renderbuffer_image()\n",
+                  rb->_BaseFormat);
       return;
    }
 
@@ -335,8 +328,12 @@ write_renderbuffer_image(const struct gl_renderbuffer *rb)
 
    /* make filename */
    _mesa_snprintf(s, sizeof(s), "/tmp/renderbuffer%u.ppm", rb->Name);
+   _mesa_snprintf(s, sizeof(s), "C:\\renderbuffer%u.ppm", rb->Name);
 
    printf("  Writing renderbuffer image to %s\n", s);
+
+   _mesa_debug(NULL, "  Writing renderbuffer image to %s\n", s);
+
    write_ppm(s, buffer, rb->Width, rb->Height, 4, 0, 1, 2, GL_TRUE);
 
    free(buffer);
@@ -423,7 +420,7 @@ dump_renderbuffer(const struct gl_renderbuffer *rb, GLboolean writeImage)
          rb->Name, rb->Width, rb->Height,
          _mesa_lookup_enum_by_nr(rb->InternalFormat));
    if (writeImage) {
-      write_renderbuffer_image(rb);
+      _mesa_write_renderbuffer_image(rb);
    }
 }
 
index 17aa897e8d121443252ae6d4f84161419e054a59..4968a9f197911419b866b28e022e3d00337268e7 100644 (file)
@@ -63,6 +63,9 @@ extern void _mesa_init_debug( struct gl_context *ctx );
 
 #endif
 
+extern void
+_mesa_write_renderbuffer_image(const struct gl_renderbuffer *rb);
+
 extern void
 _mesa_dump_texture(GLuint texture, GLuint writeImages);
 
index 0bb47731ea39c7e7539974646fceb2b49c78ea66..52c69a6bcd9c4cc7cd1df19bf6f5b9be6629a27c 100644 (file)
@@ -44,6 +44,9 @@ _mesa_ClearDepth( GLclampd depth )
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glClearDepth(%f)\n", depth);
+
    depth = CLAMP( depth, 0.0, 1.0 );
 
    if (ctx->Depth.Clear == depth)
@@ -133,6 +136,9 @@ _mesa_DepthBoundsEXT( GLclampd zmin, GLclampd zmax )
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glDepthBounds(%f, %f)\n", zmin, zmax);
+
    if (zmin > zmax) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glDepthBoundsEXT(zmin > zmax)");
       return;
index cdf349104a4010b93f5d2d0e3c5d61a066899b9b..8e904c7787aa6b59ff06f7e31000fd626140d608 100644 (file)
@@ -8419,8 +8419,6 @@ _mesa_CallList(GLuint list)
    GLboolean save_compile_flag;
    GET_CURRENT_CONTEXT(ctx);
    FLUSH_CURRENT(ctx, 0);
-   /* VERY IMPORTANT:  Save the CompileFlag status, turn it off, */
-   /* execute the display list, and restore the CompileFlag. */
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glCallList %d\n", list);
@@ -8430,8 +8428,12 @@ _mesa_CallList(GLuint list)
       return;
    }
 
-/*     mesa_print_display_list( list ); */
+   if (0)
+      mesa_print_display_list( list );
 
+   /* VERY IMPORTANT:  Save the CompileFlag status, turn it off,
+    * execute the display list, and restore the CompileFlag.
+    */
    save_compile_flag = ctx->CompileFlag;
    if (save_compile_flag) {
       ctx->CompileFlag = GL_FALSE;
index 6fda3c5665c69577a03359485145827a5036fc0b..df4712de894622416c442cd8913a9e7c4cc9addb 100644 (file)
@@ -49,6 +49,17 @@ _mesa_DrawPixels( GLsizei width, GLsizei height,
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glDrawPixels(%d, %d, %s, %s, %p) // to %s at %d, %d\n",
+                  width, height,
+                  _mesa_lookup_enum_by_nr(format),
+                  _mesa_lookup_enum_by_nr(type),
+                  pixels,
+                  _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]),
+                  IROUND(ctx->Current.RasterPos[0]),
+                  IROUND(ctx->Current.RasterPos[1]));
+
+
    if (width < 0 || height < 0) {
       _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" );
       return;
@@ -124,6 +135,18 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
+   _mesa_finish(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx,
+                  "glCopyPixels(%d, %d, %d, %d, %s) // from %s to %s at %d, %d\n",
+                  srcx, srcy, width, height,
+                  _mesa_lookup_enum_by_nr(type),
+                  _mesa_lookup_enum_by_nr(ctx->ReadBuffer->ColorReadBuffer),
+                  _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]),
+                  IROUND(ctx->Current.RasterPos[0]),
+                  IROUND(ctx->Current.RasterPos[1]));
+
    if (width < 0 || height < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)");
       return;
index c4c4e1bb29d7acd602a4ad45faa4c926701e97f6..ea3b8214c3b28a5d4438a22d98a5980d72850dcd 100644 (file)
@@ -352,9 +352,6 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
          ctx->Depth.Test = state;
          break;
       case GL_DITHER:
-         if (ctx->NoDither) {
-            state = GL_FALSE; /* MESA_NO_DITHER env var */
-         }
          if (ctx->Color.DitherFlag == state)
             return;
          FLUSH_VERTICES(ctx, _NEW_COLOR);
@@ -970,9 +967,10 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
 
       /* GL3.0 - GL_framebuffer_sRGB */
       case GL_FRAMEBUFFER_SRGB_EXT:
-        CHECK_EXTENSION(EXT_framebuffer_sRGB, cap);
-        ctx->Color.sRGBEnabled = state;
-        break;
+         CHECK_EXTENSION(EXT_framebuffer_sRGB, cap);
+         FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+         ctx->Color.sRGBEnabled = state;
+         break;
 
       default:
          goto invalid_enum_error;
index 113ac4050735dee90198cbd6712b4088fde9059b..7504b8a85db6589724e729a6cec81f8aac684d4b 100644 (file)
@@ -89,6 +89,7 @@ static const struct extension extension_table[] = {
    { "GL_ARB_fragment_program_shadow",             o(ARB_fragment_program_shadow),             GL             },
    { "GL_ARB_fragment_shader",                     o(ARB_fragment_shader),                     GL             },
    { "GL_ARB_framebuffer_object",                  o(ARB_framebuffer_object),                  GL             },
+   { "GL_ARB_framebuffer_sRGB",                    o(EXT_framebuffer_sRGB),                    GL             },
    { "GL_ARB_half_float_pixel",                    o(ARB_half_float_pixel),                    GL             },
    { "GL_ARB_half_float_vertex",                   o(ARB_half_float_vertex),                   GL             },
    { "GL_ARB_instanced_arrays",                    o(ARB_instanced_arrays),                    GL             },
@@ -249,6 +250,7 @@ static const struct extension extension_table[] = {
 
    /* Vendor extensions */
    { "GL_3DFX_texture_compression_FXT1",           o(TDFX_texture_compression_FXT1),           GL             },
+   { "GL_AMD_conservative_depth",                  o(AMD_conservative_depth),                  GL             },
    { "GL_APPLE_client_storage",                    o(APPLE_client_storage),                    GL             },
    { "GL_APPLE_object_purgeable",                  o(APPLE_object_purgeable),                  GL             },
    { "GL_APPLE_packed_pixels",                     o(APPLE_packed_pixels),                     GL             },
@@ -729,78 +731,67 @@ _mesa_extension_is_enabled( struct gl_context *ctx, const char *name )
 
 
 /**
- * Append string 'b' onto string 'a'.  Free 'a' and return new string.
- */
-static char *
-append(const char *a, const char *b)
-{
-   const GLuint aLen = a ? strlen(a) : 0;
-   const GLuint bLen = b ? strlen(b) : 0;
-   char *s = calloc(1, aLen + bLen + 1);
-   if (s) {
-      if (a)
-         memcpy(s, a, aLen);
-      if (b)
-         memcpy(s + aLen, b, bLen);
-      s[aLen + bLen] = '\0';
-   }
-   if (a)
-      free((void *) a);
-   return s;
-}
-
-
-/**
- * Check the MESA_EXTENSION_OVERRIDE env var.
- * For extension names that are recognized, turn them on.  For extension
- * names that are recognized and prefixed with '-', turn them off.
- * Return a string of the unknown/leftover names.
+ * \brief Apply the \c MESA_EXTENSION_OVERRIDE environment variable.
+ *
+ * \c MESA_EXTENSION_OVERRIDE is a space-separated list of extensions to
+ * enable or disable. The list is processed thus:
+ *    - Enable recognized extension names that are prefixed with '+'.
+ *    - Disable recognized extension names that are prefixed with '-'.
+ *    - Enable recognized extension names that are not prefixed.
+ *    - Collect unrecognized extension names in a new string.
  *
- * Returnd string needs to be freed.
+ * \return Space-separated list of unrecognized extension names (which must
+ *    be freed). Does not return \c NULL.
  */
 static char *
 get_extension_override( struct gl_context *ctx )
 {
-   const char *envExt = _mesa_getenv("MESA_EXTENSION_OVERRIDE");
-   char *extraExt = NULL;
-   char ext[1000];
-   GLuint extLen = 0;
-   GLuint i;
-   GLboolean disableExt = GL_FALSE;
-
-   if (!envExt)
-      return NULL;
+   const char *env_const= _mesa_getenv("MESA_EXTENSION_OVERRIDE");
+   char *env;
+   char *ext;
+   char *extra_exts;
+   int len;
+
+   if (env_const == NULL) {
+      /* Return the empty string rather than NULL. This simplifies the logic
+       * of client functions. */
+      return calloc(1, sizeof(char));
+   }
 
-   for (i = 0; ; i++) {
-      if (envExt[i] == '\0' || envExt[i] == ' ') {
-         /* terminate/process 'ext' if extLen > 0 */
-         if (extLen > 0) {
-            assert(extLen < sizeof(ext));
-            /* enable extension named by 'ext' */
-            ext[extLen] = 0;
-            if (!set_extension(ctx, ext, !disableExt)) {
-               /* unknown extension name, append it to extraExt */
-               if (extraExt) {
-                  extraExt = append(extraExt, " ");
-               }
-               extraExt = append(extraExt, ext);
-            }
-            extLen = 0;
-            disableExt = GL_FALSE;
-         }
-         if (envExt[i] == '\0')
-            break;
-      }
-      else if (envExt[i] == '-') {
-         disableExt = GL_TRUE;
+   /* extra_exts: List of unrecognized extensions. */
+   extra_exts = calloc(strlen(env_const), sizeof(char));
+
+   /* Copy env_const because strtok() is destructive. */
+   env = strdup(env_const);
+   for (ext = strtok(env, " "); ext != NULL; ext = strtok(NULL, " ")) {
+      int enable;
+      int recognized;
+      switch (ext[0]) {
+      case '+':
+         enable = 1;
+         ++ext;
+         break;
+      case '-':
+         enable = 0;
+         ++ext;
+         break;
+      default:
+         enable = 1;
+         break;
       }
-      else {
-         /* accumulate this non-space character */
-         ext[extLen++] = envExt[i];
+      recognized = set_extension(ctx, ext, enable);
+      if (!recognized) {
+         strcat(extra_exts, ext);
+         strcat(extra_exts, " ");
       }
    }
 
-   return extraExt;
+   /* Remove trailing space. */
+   len  = strlen(extra_exts);
+   if (extra_exts[len - 1] == ' ')
+      extra_exts[len - 1] = '\0';
+
+   return extra_exts;
 }
 
 
index f31d8b36db8ffbde680bc3753636b7bbe2cbcac6..ab6b2a9b17bde577918554171938f92d36459dba 100644 (file)
@@ -372,6 +372,37 @@ _mesa_framebuffer_renderbuffer(struct gl_context *ctx,
 }
 
 
+/**
+ * Fallback for ctx->Driver.ValidateFramebuffer()
+ * Check if the renderbuffer's formats are supported by the software
+ * renderer.
+ * Drivers should probably override this.
+ */
+void
+_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
+{
+   gl_buffer_index buf;
+   for (buf = 0; buf < BUFFER_COUNT; buf++) {
+      const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer;
+      if (rb) {
+         switch (rb->_BaseFormat) {
+         case GL_ALPHA:
+         case GL_LUMINANCE_ALPHA:
+         case GL_LUMINANCE:
+         case GL_INTENSITY:
+         case GL_RED:
+         case GL_RG:
+            fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
+            return;
+         default:
+            /* render buffer format is supported by software rendering */
+            ;
+         }
+      }
+   }
+}
+
+
 /**
  * For debug only.
  */
@@ -960,42 +991,104 @@ _mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers)
 
 
 /**
- * Given an internal format token for a renderbuffer, return the
- * corresponding base format.
+ * Given an internal format token for a render buffer, return the
+ * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
+ * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE,
+ * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc).
+ *
+ * This is similar to _mesa_base_tex_format() but the set of valid
+ * internal formats is different.
+ *
+ * Note that even if a format is determined to be legal here, validation
+ * of the FBO may fail if the format is not supported by the driver/GPU.
+ *
+ * \param internalFormat  as passed to glRenderbufferStorage()
+ * \return the base internal format, or 0 if internalFormat is illegal
  */
 GLenum
 _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat)
 {
-   GLenum baseFormat;
-
+   /*
+    * Notes: some formats such as alpha, luminance, etc. were added
+    * with GL_ARB_framebuffer_object.
+    */
    switch (internalFormat) {
+   case GL_ALPHA:
+   case GL_ALPHA4:
+   case GL_ALPHA8:
+   case GL_ALPHA12:
+   case GL_ALPHA16:
+      return ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
+   case GL_LUMINANCE:
+   case GL_LUMINANCE4:
+   case GL_LUMINANCE8:
+   case GL_LUMINANCE12:
+   case GL_LUMINANCE16:
+      return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
+   case GL_LUMINANCE_ALPHA:
+   case GL_LUMINANCE4_ALPHA4:
+   case GL_LUMINANCE6_ALPHA2:
+   case GL_LUMINANCE8_ALPHA8:
+   case GL_LUMINANCE12_ALPHA4:
+   case GL_LUMINANCE12_ALPHA12:
+   case GL_LUMINANCE16_ALPHA16:
+      return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
+   case GL_INTENSITY:
+   case GL_INTENSITY4:
+   case GL_INTENSITY8:
+   case GL_INTENSITY12:
+   case GL_INTENSITY16:
+      return ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
+   case GL_RGB:
+   case GL_R3_G3_B2:
+   case GL_RGB4:
+   case GL_RGB5:
+   case GL_RGB8:
+   case GL_RGB10:
+   case GL_RGB12:
+   case GL_RGB16:
+   case GL_SRGB8_EXT:
+      return GL_RGB;
+   case GL_RGBA:
+   case GL_RGBA2:
+   case GL_RGBA4:
+   case GL_RGB5_A1:
+   case GL_RGBA8:
+   case GL_RGB10_A2:
+   case GL_RGBA12:
+   case GL_RGBA16:
    case GL_RGBA16_SNORM:
-      /* This is used internally by Mesa for accum buffers. */
+   case GL_SRGB8_ALPHA8_EXT:
       return GL_RGBA;
    case GL_STENCIL_INDEX:
    case GL_STENCIL_INDEX1_EXT:
    case GL_STENCIL_INDEX4_EXT:
    case GL_STENCIL_INDEX8_EXT:
    case GL_STENCIL_INDEX16_EXT:
-      /* This is not a valid texture internalFormat, but valid for
-       * renderbuffers.
-       */
       return GL_STENCIL_INDEX;
    case GL_DEPTH_COMPONENT:
    case GL_DEPTH_COMPONENT16:
    case GL_DEPTH_COMPONENT24:
    case GL_DEPTH_COMPONENT32:
-      /* This is an override of _mesa_base_tex_format's check that
-       * ARB_depth_texture is present.  We allow depth RBs without it.
-       */
       return GL_DEPTH_COMPONENT;
-   }
-
-   baseFormat = _mesa_base_tex_format(ctx, internalFormat);
-   if (baseFormat < 0)
+   case GL_DEPTH_STENCIL_EXT:
+   case GL_DEPTH24_STENCIL8_EXT:
+      if (ctx->Extensions.EXT_packed_depth_stencil)
+         return GL_DEPTH_STENCIL_EXT;
+      else
+         return 0;
+   case GL_RED:
+   case GL_R8:
+   case GL_R16:
+      return ctx->Extensions.ARB_texture_rg ? GL_RED : 0;
+   case GL_RG:
+   case GL_RG8:
+   case GL_RG16:
+      return ctx->Extensions.ARB_texture_rg ? GL_RG : 0;
+   /* XXX add floating point and integer formats eventually */
+   default:
       return 0;
-
-   return baseFormat;
+   }
 }
 
 
@@ -1031,14 +1124,6 @@ renderbuffer_storage(GLenum target, GLenum internalFormat,
       return;
    }
 
-   if (baseFormat != GL_DEPTH_COMPONENT &&
-       baseFormat != GL_STENCIL_INDEX &&
-       baseFormat != GL_DEPTH_STENCIL &&
-       !_mesa_is_legal_color_format(ctx, baseFormat)) {
-      _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat)", func);
-      return;
-   }
-
    if (width < 1 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
       _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func);
       return;
@@ -2072,7 +2157,14 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
                      "glGetFramebufferAttachmentParameterivEXT(pname)");
       }
       else {
-         *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format);
+         if (ctx->Extensions.EXT_framebuffer_sRGB && ctx->Const.sRGBCapable) {
+            *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format);
+         }
+         else {
+            /* According to ARB_framebuffer_sRGB, we should return LINEAR
+             * if the sRGB conversion is unsupported. */
+            *params = GL_LINEAR;
+         }
       }
       return;
    case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
@@ -2184,7 +2276,8 @@ _mesa_GenerateMipmapEXT(GLenum target)
 #if FEATURE_EXT_framebuffer_blit
 
 static const struct gl_renderbuffer_attachment *
-find_attachment(const struct gl_framebuffer *fb, const struct gl_renderbuffer *rb)
+find_attachment(const struct gl_framebuffer *fb,
+                const struct gl_renderbuffer *rb)
 {
    GLuint i;
    for (i = 0; i < Elements(fb->Attachment); i++) {
@@ -2217,6 +2310,13 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
    ASSERT_OUTSIDE_BEGIN_END(ctx);
    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx,
+                  "glBlitFramebuffer(%d, %d, %d, %d,  %d, %d, %d, %d, 0x%x, %s)\n",
+                  srcX0, srcY0, srcX1, srcY1,
+                  dstX0, dstY0, dstX1, dstY1,
+                  mask, _mesa_lookup_enum_by_nr(filter));
+
    if (ctx->NewState) {
       _mesa_update_state(ctx);
    }
index 8763f99c4a7312b3cef5b2db97aaf35f8e18a3ff..ba74a95b74c85f6ff9e83a58cec5899092818a09 100644 (file)
@@ -68,6 +68,9 @@ extern void
 _mesa_framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
                                GLenum attachment, struct gl_renderbuffer *rb);
 
+extern void
+_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb);
+
 extern void
 _mesa_test_framebuffer_completeness(struct gl_context *ctx, struct gl_framebuffer *fb);
 
index b8fed182570a573ed03504457149064d6cbad8f7..1e395363475d2c6b21d0223004389e6f432d9c58 100644 (file)
@@ -1372,7 +1372,11 @@ _mesa_format_to_type_and_comps(gl_format format,
       *comps = 4;
       return;
 
-   case MESA_FORMAT_AL44: /* XXX this isn't plain GL_UNSIGNED_BYTE */
+   case MESA_FORMAT_AL44:
+      *datatype = MESA_UNSIGNED_BYTE_4_4;
+      *comps = 2;
+      return;
+
    case MESA_FORMAT_AL88:
    case MESA_FORMAT_AL88_REV:
    case MESA_FORMAT_RG88:
index d4dc5eac03e44d0349f3dba4412b5f18b9db7cbd..9a5cef37788ccd6837c197efcf25d030f32e5f7d 100644 (file)
@@ -35,6 +35,9 @@
 
 #include <GL/gl.h>
 
+/* OpenGL doesn't have GL_UNSIGNED_BYTE_4_4, so we must define our own type
+ * for GL_LUMINANCE4_ALPHA4. */
+#define MESA_UNSIGNED_BYTE_4_4 (GL_UNSIGNED_BYTE<<1)
 
 
 /**
index 63da71c95b4bd9609173f099e432bed07431da2c..948b3b7b5a23623e4a0e0533df1a0deef5af9b91 100644 (file)
@@ -553,6 +553,8 @@ _mesa_update_framebuffer_visual(struct gl_context *ctx,
                + fb->Visual.greenBits + fb->Visual.blueBits;
             fb->Visual.floatMode = GL_FALSE;
             fb->Visual.samples = rb->NumSamples;
+            if (_mesa_get_format_color_encoding(fmt) == GL_SRGB)
+                fb->Visual.sRGBCapable = ctx->Const.sRGBCapable;
             break;
          }
       }
index bdbd7519d37410cceb740cc9058f8ab7df73ddf5..ff8d88fffe0e3c30911d7e985ef99f37cf1d5668 100644 (file)
@@ -40,8 +40,9 @@ _mesa_Hint( GLenum target, GLenum mode )
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
-      _mesa_debug(ctx, "glHint %s %d\n",
-                  _mesa_lookup_enum_by_nr(target), mode);
+      _mesa_debug(ctx, "glHint %s %s\n",
+                  _mesa_lookup_enum_by_nr(target),
+                  _mesa_lookup_enum_by_nr(mode));
 
    if (mode != GL_NICEST && mode != GL_FASTEST && mode != GL_DONT_CARE) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glHint(mode)");
index 909c18e7e60606792742bd37050160b1bc827e2f..63936132f98bd3e1cacd3de54037f6cbc9516a29 100644 (file)
@@ -68,6 +68,7 @@ _mesa_type_is_packed(GLenum type)
    switch (type) {
    case GL_UNSIGNED_BYTE_3_3_2:
    case GL_UNSIGNED_BYTE_2_3_3_REV:
+   case MESA_UNSIGNED_BYTE_4_4:
    case GL_UNSIGNED_SHORT_5_6_5:
    case GL_UNSIGNED_SHORT_5_6_5_REV:
    case GL_UNSIGNED_SHORT_4_4_4_4:
@@ -194,6 +195,8 @@ _mesa_sizeof_packed_type( GLenum type )
          return sizeof(GLubyte);
       case GL_UNSIGNED_BYTE_2_3_3_REV:
          return sizeof(GLubyte);
+      case MESA_UNSIGNED_BYTE_4_4:
+         return sizeof(GLubyte);
       case GL_UNSIGNED_SHORT_5_6_5:
          return sizeof(GLushort);
       case GL_UNSIGNED_SHORT_5_6_5_REV:
@@ -1581,8 +1584,8 @@ _mesa_clip_drawpixels(const struct gl_context *ctx,
  * scissor box is ignored, and we use the bounds of the current readbuffer
  * surface.
  *
- * \return  GL_TRUE if image is ready for drawing or
- *          GL_FALSE if image was completely clipped away (draw nothing)
+ * \return  GL_TRUE if region to read is in bounds
+ *          GL_FALSE if region is completely out of bounds (nothing to read)
  */
 GLboolean
 _mesa_clip_readpixels(const struct gl_context *ctx,
index bd1fd7cfbf8d359b730b5563ce97b623b2c5e5a1..bf89815f2d3ecf378842663226ce8d5920afcbd0 100644 (file)
@@ -453,6 +453,7 @@ _mesa_inv_sqrtf(float n)
 #endif
 }
 
+#ifndef __GNUC__
 /**
  * Find the first bit set in a word.
  */
@@ -496,9 +497,6 @@ _mesa_ffs(int32_t i)
 int
 _mesa_ffsll(int64_t val)
 {
-#ifdef ffsll
-   return ffsll(val);
-#else
    int bit;
 
    assert(sizeof(val) == 8);
@@ -512,27 +510,24 @@ _mesa_ffsll(int64_t val)
       return 32 + bit;
 
    return 0;
-#endif
 }
 
 
+#if ((_GNUC__ == 3 && __GNUC_MINOR__ < 4) || __GNUC__ < 4)
 /**
  * Return number of bits set in given GLuint.
  */
 unsigned int
 _mesa_bitcount(unsigned int n)
 {
-#if defined(__GNUC__) && \
-       ((_GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4)
-   return __builtin_popcount(n);
-#else
    unsigned int bits;
    for (bits = 0; n > 0; n = n >> 1) {
       bits += (n & 1);
    }
    return bits;
-#endif
 }
+#endif
+#endif
 
 
 /**
@@ -942,7 +937,7 @@ _mesa_problem( const struct gl_context *ctx, const char *fmtString, ... )
    va_end( args );
 
    fprintf(stderr, "Mesa %s implementation error: %s\n", MESA_VERSION_STRING, str);
-   fprintf(stderr, "Please report at bugzilla.freedesktop.org\n");
+   fprintf(stderr, "Please report at bugs.freedesktop.org\n");
 }
 
 
index 5ea647ad8d73a038e6fc2f8b1817f8fa5c08f793..ce7baabe2c7a7b7f8c5682b8a91dee1e7aad781a 100644 (file)
@@ -539,6 +539,24 @@ _mesa_inv_sqrtf(float x);
 extern void
 _mesa_init_sqrt_table(void);
 
+#ifdef __GNUC__
+
+#ifdef __MINGW32__
+#define ffs __builtin_ffs
+#define ffsll __builtin_ffsll
+#endif
+
+#define _mesa_ffs(i)  ffs(i)
+#define _mesa_ffsll(i)  ffsll(i)
+
+#if ((_GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4)
+#define _mesa_bitcount(i) __builtin_popcount(i)
+#else
+extern unsigned int
+_mesa_bitcount(unsigned int n);
+#endif
+
+#else
 extern int
 _mesa_ffs(int32_t i);
 
@@ -547,6 +565,7 @@ _mesa_ffsll(int64_t i);
 
 extern unsigned int
 _mesa_bitcount(unsigned int n);
+#endif
 
 extern GLhalfARB
 _mesa_float_to_half(float f);
index 81e179a9254880f25417f968d97ebf5497d65952..79bf5679d8a04515f8a21f2fd9d171ec91424c72 100644 (file)
@@ -43,6 +43,9 @@ _mesa_LineWidth( GLfloat width )
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glLineWidth %f\n", width);
+
    if (width<=0.0) {
       _mesa_error( ctx, GL_INVALID_VALUE, "glLineWidth" );
       return;
@@ -77,6 +80,9 @@ _mesa_LineStipple( GLint factor, GLushort pattern )
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glLineStipple %d %u\n", factor, pattern);
+
    factor = CLAMP( factor, 1, 256 );
 
    if (ctx->Line.StippleFactor == factor &&
index e073e17039f4c93dfba65d608e8e8dc26600e56f..d8a56103800a2301704c795dea66b8711cb9fd10 100644 (file)
@@ -612,6 +612,28 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth,
          dst[i] = (blue << 5) | (green << 2) | red;
       }
    }
+
+   else if (datatype == MESA_UNSIGNED_BYTE_4_4 && comps == 2) {
+      GLuint i, j, k;
+      const GLubyte *rowA = (const GLubyte *) srcRowA;
+      const GLubyte *rowB = (const GLubyte *) srcRowB;
+      GLubyte *dst = (GLubyte *) dstRow;
+      for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+           i++, j += colStride, k += colStride) {
+         const GLint rowAr0 = rowA[j] & 0xf;
+         const GLint rowAr1 = rowA[k] & 0xf;
+         const GLint rowBr0 = rowB[j] & 0xf;
+         const GLint rowBr1 = rowB[k] & 0xf;
+         const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
+         const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
+         const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
+         const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
+         const GLint r = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
+         const GLint g = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
+         dst[i] = (g << 4) | r;
+      }
+   }
+
    else {
       _mesa_problem(NULL, "bad format in do_row()");
    }
@@ -1078,7 +1100,7 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth,
       }
    }
    else if ((datatype == GL_UNSIGNED_BYTE_3_3_2) && (comps == 3)) {
-      DECLARE_ROW_POINTERS0(GLushort);
+      DECLARE_ROW_POINTERS0(GLubyte);
 
       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
            i++, j += colStride, k += colStride) {
@@ -1115,6 +1137,34 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth,
          dst[i] = (b << 5) | (g << 2) | r;
       }
    }
+   else if (datatype == MESA_UNSIGNED_BYTE_4_4 && comps == 2) {
+      DECLARE_ROW_POINTERS0(GLubyte);
+
+      for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+           i++, j += colStride, k += colStride) {
+         const GLint rowAr0 = rowA[j] & 0xf;
+         const GLint rowAr1 = rowA[k] & 0xf;
+         const GLint rowBr0 = rowB[j] & 0xf;
+         const GLint rowBr1 = rowB[k] & 0xf;
+         const GLint rowCr0 = rowC[j] & 0xf;
+         const GLint rowCr1 = rowC[k] & 0xf;
+         const GLint rowDr0 = rowD[j] & 0xf;
+         const GLint rowDr1 = rowD[k] & 0xf;
+         const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
+         const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
+         const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
+         const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
+         const GLint rowCg0 = (rowC[j] >> 4) & 0xf;
+         const GLint rowCg1 = (rowC[k] >> 4) & 0xf;
+         const GLint rowDg0 = (rowD[j] >> 4) & 0xf;
+         const GLint rowDg1 = (rowD[k] >> 4) & 0xf;
+         const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
+                                       rowCr0, rowCr1, rowDr0, rowDr1);
+         const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
+                                       rowCg0, rowCg1, rowDg0, rowDg1);
+         dst[i] = (g << 4) | r;
+      }
+   }
    else {
       _mesa_problem(NULL, "bad format in do_row()");
    }
index 34003b4b6fb55dd47e665fb760bdefe7b373cb80..b237063a6d8066849ad15bd5683fe42256fa750f 100644 (file)
 /*@{*/
 typedef GLuint64 GLbitfield64;
 
-#define BITFIELD64_ONE         1ULL
-#define BITFIELD64_ALLONES     ~0ULL
-
 /** Set a single bit */
-#define BITFIELD64_BIT(b)      (BITFIELD64_ONE << (b))
-
-/** Set a mask of the least significant \c b bits */
-#define BITFIELD64_MASK(b)     (((b) >= 64) ? BITFIELD64_ALLONES : \
-                               (BITFIELD64_BIT(b) - 1))
-
-/**
- * Set all bits from l (low bit) to h (high bit), inclusive.
- *
- * \note \C BITFIELD_64_RANGE(0, 63) return 64 set bits.
- */
-#define BITFIELD64_RANGE(l, h) (BITFIELD64_MASK((h) + 1) & ~BITFIELD64_MASK(l))
-/*@}*/
+#define BITFIELD64_BIT(b)      (1ULL << (b))
 
 
 /**
@@ -867,6 +852,23 @@ struct gl_fog_attrib
 };
 
 
+/**
+ * \brief Layout qualifiers for gl_FragDepth.
+ *
+ * Extension AMD_conservative_depth allows gl_FragDepth to be redeclared with
+ * a layout qualifier.
+ *
+ * \see enum ir_depth_layout
+ */
+enum gl_frag_depth_layout {
+    FRAG_DEPTH_LAYOUT_NONE, /**< No layout is specified. */
+    FRAG_DEPTH_LAYOUT_ANY,
+    FRAG_DEPTH_LAYOUT_GREATER,
+    FRAG_DEPTH_LAYOUT_LESS,
+    FRAG_DEPTH_LAYOUT_UNCHANGED
+};
+
+
 /** 
  * Hint attribute group (GL_HINT_BIT).
  * 
@@ -1238,7 +1240,7 @@ struct gl_texture_image
                                 *   GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL_EXT
                                  *   only. Used for choosing TexEnv arithmetic.
                                 */
-   GLuint TexFormat;            /**< The actual format: MESA_FORMAT_x */
+   gl_format TexFormat;         /**< The actual texture memory format */
 
    GLuint Border;              /**< 0 or 1 */
    GLuint Width;               /**< = 2^WidthLog2 + 2*Border */
@@ -1641,6 +1643,7 @@ struct gl_array_attrib
    GLuint RestartIndex;
 
    GLbitfield NewState;                /**< mask of _NEW_ARRAY_* values */
+   GLboolean RebindArrays; /**< whether the VBO module should rebind arrays */
 
    /* GL_ARB_vertex_buffer_object */
    struct gl_buffer_object *ArrayBufferObj;
@@ -1889,6 +1892,7 @@ struct gl_fragment_program
    GLboolean UsesKill;          /**< shader uses KIL instruction */
    GLboolean OriginUpperLeft;
    GLboolean PixelCenterInteger;
+   enum gl_frag_depth_layout FragDepthLayout;
 };
 
 
@@ -2100,8 +2104,6 @@ struct gl_shader
    GLint RefCount;  /**< Reference count */
    GLboolean DeletePending;
    GLboolean CompileStatus;
-   GLboolean Main;  /**< shader defines main() */
-   GLboolean UnresolvedRefs;
    const GLchar *Source;  /**< Source code string */
    GLuint SourceChecksum;       /**< for debug/logging purposes */
    struct gl_program *Program;  /**< Post-compile assembly code */
@@ -2378,7 +2380,7 @@ struct gl_renderbuffer
    GLenum InternalFormat; /**< The user-specified format */
    GLenum _BaseFormat;    /**< Either GL_RGB, GL_RGBA, GL_DEPTH_COMPONENT or
                                GL_STENCIL_INDEX. */
-   GLuint Format;         /**< The actual format: MESA_FORMAT_x */
+   gl_format Format;      /**< The actual renderbuffer memory format */
 
    GLubyte NumSamples;
 
@@ -2692,6 +2694,9 @@ struct gl_constants
 
    /** GL_EXT_gpu_shader4 */
    GLint MinProgramTexelOffset, MaxProgramTexelOffset;
+
+   /* GL_EXT_framebuffer_sRGB */
+   GLboolean sRGBCapable; /* can enable sRGB blend/update on FBOs */
 };
 
 
@@ -2824,6 +2829,7 @@ struct gl_extensions
    GLboolean EXT_vertex_array_set;
    GLboolean OES_standard_derivatives;
    /* vendor extensions */
+   GLboolean AMD_conservative_depth;
    GLboolean APPLE_client_storage;
    GLboolean APPLE_packed_pixels;
    GLboolean APPLE_vertex_array_object;
@@ -2901,40 +2907,37 @@ struct gl_matrix_stack
 
 /**
  * \name Bits to indicate what state has changed.  
- *
- * 4 unused flags.
  */
 /*@{*/
-#define _NEW_MODELVIEW         0x1        /**< __struct gl_contextRec::ModelView */
-#define _NEW_PROJECTION                0x2        /**< __struct gl_contextRec::Projection */
-#define _NEW_TEXTURE_MATRIX    0x4        /**< __struct gl_contextRec::TextureMatrix */
-#define _NEW_ACCUM             0x10       /**< __struct gl_contextRec::Accum */
-#define _NEW_COLOR             0x20       /**< __struct gl_contextRec::Color */
-#define _NEW_DEPTH             0x40       /**< __struct gl_contextRec::Depth */
-#define _NEW_EVAL              0x80       /**< __struct gl_contextRec::Eval, __struct gl_contextRec::EvalMap */
-#define _NEW_FOG               0x100      /**< __struct gl_contextRec::Fog */
-#define _NEW_HINT              0x200      /**< __struct gl_contextRec::Hint */
-#define _NEW_LIGHT             0x400      /**< __struct gl_contextRec::Light */
-#define _NEW_LINE              0x800      /**< __struct gl_contextRec::Line */
-#define _NEW_PIXEL             0x1000     /**< __struct gl_contextRec::Pixel */
-#define _NEW_POINT             0x2000     /**< __struct gl_contextRec::Point */
-#define _NEW_POLYGON           0x4000     /**< __struct gl_contextRec::Polygon */
-#define _NEW_POLYGONSTIPPLE    0x8000     /**< __struct gl_contextRec::PolygonStipple */
-#define _NEW_SCISSOR           0x10000    /**< __struct gl_contextRec::Scissor */
-#define _NEW_STENCIL           0x20000    /**< __struct gl_contextRec::Stencil */
-#define _NEW_TEXTURE           0x40000    /**< __struct gl_contextRec::Texture */
-#define _NEW_TRANSFORM         0x80000    /**< __struct gl_contextRec::Transform */
-#define _NEW_VIEWPORT          0x100000   /**< __struct gl_contextRec::Viewport */
-#define _NEW_PACKUNPACK                0x200000   /**< __struct gl_contextRec::Pack, __struct gl_contextRec::Unpack */
-#define _NEW_ARRAY             0x400000   /**< __struct gl_contextRec::Array */
-#define _NEW_RENDERMODE                0x800000   /**< __struct gl_contextRec::RenderMode, __struct gl_contextRec::Feedback, __struct gl_contextRec::Select */
-#define _NEW_BUFFERS            0x1000000  /**< __struct gl_contextRec::Visual, __struct gl_contextRec::DrawBuffer, */
-#define _NEW_MULTISAMPLE        0x2000000  /**< __struct gl_contextRec::Multisample */
-#define _NEW_TRACK_MATRIX       0x4000000  /**< __struct gl_contextRec::VertexProgram */
-#define _NEW_PROGRAM            0x8000000  /**< __struct gl_contextRec::VertexProgram */
-#define _NEW_CURRENT_ATTRIB     0x10000000  /**< __struct gl_contextRec::Current */
-#define _NEW_PROGRAM_CONSTANTS  0x20000000
-#define _NEW_BUFFER_OBJECT      0x40000000
+#define _NEW_MODELVIEW         (1 << 0)   /**< gl_context::ModelView */
+#define _NEW_PROJECTION        (1 << 1)   /**< gl_context::Projection */
+#define _NEW_TEXTURE_MATRIX    (1 << 2)   /**< gl_context::TextureMatrix */
+#define _NEW_COLOR             (1 << 3)   /**< gl_context::Color */
+#define _NEW_DEPTH             (1 << 4)   /**< gl_context::Depth */
+#define _NEW_EVAL              (1 << 5)   /**< gl_context::Eval, EvalMap */
+#define _NEW_FOG               (1 << 6)   /**< gl_context::Fog */
+#define _NEW_HINT              (1 << 7)   /**< gl_context::Hint */
+#define _NEW_LIGHT             (1 << 8)   /**< gl_context::Light */
+#define _NEW_LINE              (1 << 9)   /**< gl_context::Line */
+#define _NEW_PIXEL             (1 << 10)  /**< gl_context::Pixel */
+#define _NEW_POINT             (1 << 11)  /**< gl_context::Point */
+#define _NEW_POLYGON           (1 << 12)  /**< gl_context::Polygon */
+#define _NEW_POLYGONSTIPPLE    (1 << 13)  /**< gl_context::PolygonStipple */
+#define _NEW_SCISSOR           (1 << 14)  /**< gl_context::Scissor */
+#define _NEW_STENCIL           (1 << 15)  /**< gl_context::Stencil */
+#define _NEW_TEXTURE           (1 << 16)  /**< gl_context::Texture */
+#define _NEW_TRANSFORM         (1 << 17)  /**< gl_context::Transform */
+#define _NEW_VIEWPORT          (1 << 18)  /**< gl_context::Viewport */
+#define _NEW_PACKUNPACK        (1 << 19)  /**< gl_context::Pack, Unpack */
+#define _NEW_ARRAY             (1 << 20)  /**< gl_context::Array */
+#define _NEW_RENDERMODE        (1 << 21)  /**< gl_context::RenderMode, etc */
+#define _NEW_BUFFERS           (1 << 22)  /**< gl_context::Visual, DrawBuffer, */
+#define _NEW_CURRENT_ATTRIB    (1 << 23)  /**< gl_context::Current */
+#define _NEW_MULTISAMPLE       (1 << 24)  /**< gl_context::Multisample */
+#define _NEW_TRACK_MATRIX      (1 << 25)  /**< gl_context::VertexProgram */
+#define _NEW_PROGRAM           (1 << 26)  /**< New program/shader state */
+#define _NEW_PROGRAM_CONSTANTS (1 << 27)
+#define _NEW_BUFFER_OBJECT     (1 << 28)
 #define _NEW_ALL ~0
 /*@}*/
 
@@ -3292,9 +3295,6 @@ struct gl_context
    GLboolean FirstTimeCurrent;
    /*@}*/
 
-   /** Dither disable via MESA_NO_DITHER env var */
-   GLboolean NoDither;
-
    /** software compression/decompression supported or not */
    GLboolean Mesa_DXTn;
 
index ef6460b2f97fd213eafe7cabe0582d286667f18f..fa35c6ce58a546a1698f3ba5c59320aefecdc4ba 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "glheader.h"
 #include "context.h"
+#include "enums.h"
 #include "hash.h"
 #include "imports.h"
 #include "queryobj.h"
@@ -179,6 +180,9 @@ _mesa_GenQueriesARB(GLsizei n, GLuint *ids)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glGenQueries(%d)\n", n);
+
    if (n < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)");
       return;
@@ -215,6 +219,9 @@ _mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glDeleeteQueries(%d)\n", n);
+
    if (n < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)");
       return;
@@ -246,6 +253,9 @@ _mesa_IsQueryARB(GLuint id)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glIsQuery(%u)\n", id);
+
    if (id && _mesa_lookup_query_object(ctx, id))
       return GL_TRUE;
    else
@@ -260,6 +270,10 @@ _mesa_BeginQueryARB(GLenum target, GLuint id)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glBeginQuery(%s, %u)\n",
+                  _mesa_lookup_enum_by_nr(target), id);
+
    FLUSH_VERTICES(ctx, _NEW_DEPTH);
 
    bindpt = get_query_binding_point(ctx, target);
@@ -311,6 +325,9 @@ _mesa_EndQueryARB(GLenum target)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glEndQuery(%s)\n", _mesa_lookup_enum_by_nr(target));
+
    FLUSH_VERTICES(ctx, _NEW_DEPTH);
 
    bindpt = get_query_binding_point(ctx, target);
@@ -341,6 +358,11 @@ _mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glGetQueryiv(%s, %s)\n",
+                  _mesa_lookup_enum_by_nr(target),
+                  _mesa_lookup_enum_by_nr(pname));
+
    bindpt = get_query_binding_point(ctx, target);
    if (!bindpt) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryARB(target)");
@@ -370,6 +392,10 @@ _mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glGetQueryObjectiv(%u, %s)\n", id,
+                  _mesa_lookup_enum_by_nr(pname));
+
    if (id)
       q = _mesa_lookup_query_object(ctx, id);
 
@@ -417,6 +443,10 @@ _mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glGetQueryObjectuiv(%u, %s)\n", id,
+                  _mesa_lookup_enum_by_nr(pname));
+
    if (id)
       q = _mesa_lookup_query_object(ctx, id);
 
@@ -467,6 +497,10 @@ _mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glGetQueryObjecti64v(%u, %s)\n", id,
+                  _mesa_lookup_enum_by_nr(pname));
+
    if (id)
       q = _mesa_lookup_query_object(ctx, id);
 
@@ -504,6 +538,10 @@ _mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glGetQueryObjectui64v(%u, %s)\n", id,
+                  _mesa_lookup_enum_by_nr(pname));
+
    if (id)
       q = _mesa_lookup_query_object(ctx, id);
 
index e5b85ca32b47b04643ababcee2250990150fff30..9a4f15f7279645e9bcf3cf6706c659bdd27dbdd9 100644 (file)
@@ -26,6 +26,7 @@
 #include "imports.h"
 #include "bufferobj.h"
 #include "context.h"
+#include "enums.h"
 #include "readpix.h"
 #include "framebuffer.h"
 #include "formats.h"
@@ -173,6 +174,13 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
 
    FLUSH_CURRENT(ctx, 0);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
+                  width, height,
+                  _mesa_lookup_enum_by_nr(format),
+                  _mesa_lookup_enum_by_nr(type),
+                  pixels);
+
    if (width < 0 || height < 0) {
       _mesa_error( ctx, GL_INVALID_VALUE,
                    "glReadPixels(width=%d height=%d)", width, height );
index 23c662bab7fe1b02140b7cf691993cd51cf48895..67ee589d77665def695658dc2c1be90b7feec5a9 100644 (file)
@@ -1086,7 +1086,7 @@ _mesa_soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *
       pixelSize = sizeof(GLuint);
       break;
    default:
-      _mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage");
+      /* unsupported format */
       return GL_FALSE;
    }
 
index a5e90d7cbd1b947dab1e968c929e71494549a637..11b0f884fa4db6a0ad3119d08440e257cf2cea5b 100644 (file)
@@ -48,7 +48,7 @@
 #include "program/program.h"
 #include "program/prog_parameter.h"
 #include "program/prog_uniform.h"
-#include "talloc.h"
+#include "ralloc.h"
 #include <stdbool.h>
 #include "../glsl/glsl_parser_extras.h"
 
@@ -1137,9 +1137,9 @@ validate_program(struct gl_context *ctx, GLuint program)
    if (!shProg->Validated) {
       /* update info log */
       if (shProg->InfoLog) {
-         talloc_free(shProg->InfoLog);
+         ralloc_free(shProg->InfoLog);
       }
-      shProg->InfoLog = talloc_strdup(shProg, errMsg);
+      shProg->InfoLog = ralloc_strdup(shProg, errMsg);
    }
 }
 
@@ -1184,6 +1184,8 @@ void GLAPIENTRY
 _mesa_CompileShaderARB(GLhandleARB shaderObj)
 {
    GET_CURRENT_CONTEXT(ctx);
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glCompileShader %u\n", shaderObj);
    compile_shader(ctx, shaderObj);
 }
 
@@ -1192,6 +1194,8 @@ GLuint GLAPIENTRY
 _mesa_CreateShader(GLenum type)
 {
    GET_CURRENT_CONTEXT(ctx);
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glCreateShader %s\n", _mesa_lookup_enum_by_nr(type));
    return create_shader(ctx, type);
 }
 
@@ -1208,6 +1212,8 @@ GLuint GLAPIENTRY
 _mesa_CreateProgram(void)
 {
    GET_CURRENT_CONTEXT(ctx);
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glCreateProgram\n");
    return create_shader_program(ctx);
 }
 
@@ -1223,6 +1229,11 @@ _mesa_CreateProgramObjectARB(void)
 void GLAPIENTRY
 _mesa_DeleteObjectARB(GLhandleARB obj)
 {
+   if (MESA_VERBOSE & VERBOSE_API) {
+      GET_CURRENT_CONTEXT(ctx);
+      _mesa_debug(ctx, "glDeleteObjectARB(%u)\n", obj);
+   }
+
    if (obj) {
       GET_CURRENT_CONTEXT(ctx);
       if (is_program(ctx, obj)) {
@@ -1855,7 +1866,7 @@ _mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string)
 #endif
         }
 
-        shProg->InfoLog = talloc_strdup_append(shProg->InfoLog, sh->InfoLog);
+        ralloc_strcat(&shProg->InfoLog, sh->InfoLog);
       }
 
       delete_shader(ctx, shader);
index 647fd31cab42fd2a18a184724c4d614ce46a9ca9..1d75845590f07f2c9456e0ee66191ce5bcd8ab69 100644 (file)
@@ -38,7 +38,7 @@
 #include "program/program.h"
 #include "program/prog_parameter.h"
 #include "program/prog_uniform.h"
-#include "talloc.h"
+#include "ralloc.h"
 
 /**********************************************************************/
 /*** Shader object functions                                        ***/
@@ -105,7 +105,7 @@ _mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type)
    struct gl_shader *shader;
    assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER ||
           type == GL_GEOMETRY_SHADER_ARB);
-   shader = talloc_zero(NULL, struct gl_shader);
+   shader = rzalloc(NULL, struct gl_shader);
    if (shader) {
       shader->Type = type;
       shader->Name = name;
@@ -125,7 +125,7 @@ _mesa_delete_shader(struct gl_context *ctx, struct gl_shader *sh)
    if (sh->Source)
       free((void *) sh->Source);
    _mesa_reference_program(ctx, &sh->Program, NULL);
-   talloc_free(sh);
+   ralloc_free(sh);
 }
 
 
@@ -252,7 +252,7 @@ static struct gl_shader_program *
 _mesa_new_shader_program(struct gl_context *ctx, GLuint name)
 {
    struct gl_shader_program *shProg;
-   shProg = talloc_zero(NULL, struct gl_shader_program);
+   shProg = rzalloc(NULL, struct gl_shader_program);
    if (shProg) {
       shProg->Name = name;
       _mesa_init_shader_program(ctx, shProg);
@@ -316,7 +316,7 @@ _mesa_free_shader_program_data(struct gl_context *ctx,
    }
 
    if (shProg->InfoLog) {
-      talloc_free(shProg->InfoLog);
+      ralloc_free(shProg->InfoLog);
       shProg->InfoLog = NULL;
    }
 
@@ -347,7 +347,7 @@ _mesa_delete_shader_program(struct gl_context *ctx, struct gl_shader_program *sh
 {
    _mesa_free_shader_program_data(ctx, shProg);
 
-   talloc_free(shProg);
+   ralloc_free(shProg);
 }
 
 
index cce1b464f0cae2ccb56ff1d1f02717b776539188..502c429294cc556667e9176abcf2110c8b444bf4 100644 (file)
@@ -662,6 +662,8 @@ _mesa_update_state_locked( struct gl_context *ctx )
    ctx->NewState = 0;
    ctx->Driver.UpdateState(ctx, new_state);
    ctx->Array.NewState = 0;
+   if (!ctx->Array.RebindArrays)
+      ctx->Array.RebindArrays = (new_state & (_NEW_ARRAY | _NEW_PROGRAM)) != 0;
 }
 
 
index 93e2e97ce0c724d31cc0eaed9e2804c0c0c281d2..d898bf1d7499acc6540eaeebda0daa175c8a9471 100644 (file)
@@ -147,6 +147,9 @@ _mesa_StencilFuncSeparateATI( GLenum frontfunc, GLenum backfunc, GLint ref, GLui
    const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glStencilFuncSeparateATI()\n");
+
    if (!validate_stencil_func(ctx, frontfunc)) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                   "glStencilFuncSeparateATI(frontfunc)");
@@ -203,6 +206,9 @@ _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
    const GLint face = ctx->Stencil.ActiveFace;
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glStencilFunc()\n");
+
    if (!validate_stencil_func(ctx, func)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)");
       return;
@@ -267,6 +273,9 @@ _mesa_StencilMask( GLuint mask )
    GET_CURRENT_CONTEXT(ctx);
    const GLint face = ctx->Stencil.ActiveFace;
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glStencilMask()\n");
+
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (face != 0) {
@@ -321,6 +330,9 @@ _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
    GET_CURRENT_CONTEXT(ctx);
    const GLint face = ctx->Stencil.ActiveFace;
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glStencilOp()\n");
+
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (!validate_stencil_op(ctx, fail)) {
@@ -386,6 +398,9 @@ _mesa_ActiveStencilFaceEXT(GLenum face)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glActiveStencilFaceEXT()\n");
+
    if (!ctx->Extensions.EXT_stencil_two_side) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT");
       return;
@@ -416,6 +431,9 @@ _mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glStencilOpSeparate()\n");
+
    if (!validate_stencil_op(ctx, sfail)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)");
       return;
@@ -471,6 +489,9 @@ _mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
    const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glStencilFuncSeparate()\n");
+
    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)");
       return;
@@ -509,6 +530,9 @@ _mesa_StencilMaskSeparate(GLenum face, GLuint mask)
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glStencilMaskSeparate()\n");
+
    if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)");
       return;
index 146b2b340e7102e3537b02632c2ea6d83e4fff7c..2542cea856b65154e1b15504bc523b1b65b2b7f0 100644 (file)
@@ -591,6 +591,17 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat,
       }
    }
 
+   if (ctx->Extensions.EXT_texture_format_BGRA8888) {
+      switch (internalFormat) {
+      case GL_BGRA:
+        RETURN_IF_SUPPORTED(MESA_FORMAT_ARGB8888);
+        break;
+
+      default:
+         ; /* fallthrough */
+      }
+   }
+
    _mesa_problem(ctx, "unexpected format in _mesa_choose_tex_format()");
    return MESA_FORMAT_NONE;
 }
index da610798e1232822da5eb0d6e7416731bc68197e..28829694153e50979adc372e7867f8814040cc43 100644 (file)
@@ -805,8 +805,8 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
  * \return GL_TRUE if any error, GL_FALSE if no errors.
  */
 static GLboolean
-getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, GLint level,
-                                  GLvoid *img)
+getcompressedteximage_error_check(struct gl_context *ctx, GLenum target,
+                                  GLint level, GLvoid *img)
 {
    struct gl_texture_object *texObj;
    struct gl_texture_image *texImage;
index 47d509396a788857a4e2a4d3416b4053cb4229fb..1f2ad7f266b4f8910401474d2fae83db221b1100 100644 (file)
@@ -183,6 +183,15 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat )
          ; /* fallthrough */
    }
 
+   if (ctx->Extensions.EXT_texture_format_BGRA8888) {
+      switch (internalFormat) {
+         case GL_BGRA_EXT:
+            return GL_RGBA;
+         default:
+            ; /* fallthrough */
+      }
+   }
+
    if (ctx->Extensions.EXT_paletted_texture) {
       switch (internalFormat) {
          case GL_COLOR_INDEX:
@@ -694,6 +703,9 @@ _mesa_select_tex_object(struct gl_context *ctx,
                         const struct gl_texture_unit *texUnit,
                         GLenum target)
 {
+   const GLboolean arrayTex = (ctx->Extensions.MESA_texture_array ||
+                               ctx->Extensions.EXT_texture_array);
+
    switch (target) {
       case GL_TEXTURE_1D:
          return texUnit->CurrentTex[TEXTURE_1D_INDEX];
@@ -726,17 +738,13 @@ _mesa_select_tex_object(struct gl_context *ctx,
          return ctx->Extensions.NV_texture_rectangle
                 ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL;
       case GL_TEXTURE_1D_ARRAY_EXT:
-         return ctx->Extensions.MESA_texture_array
-                ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
+         return arrayTex ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
       case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
-         return ctx->Extensions.MESA_texture_array
-                ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
+         return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
       case GL_TEXTURE_2D_ARRAY_EXT:
-         return ctx->Extensions.MESA_texture_array
-                ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
+         return arrayTex ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
       case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
-         return ctx->Extensions.MESA_texture_array
-                ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
+         return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
       default:
          _mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
          return NULL;
@@ -921,7 +929,8 @@ _mesa_max_texture_levels(struct gl_context *ctx, GLenum target)
    case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
    case GL_TEXTURE_2D_ARRAY_EXT:
    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
-      return ctx->Extensions.MESA_texture_array
+      return (ctx->Extensions.MESA_texture_array ||
+              ctx->Extensions.EXT_texture_array)
          ? ctx->Const.MaxTextureLevels : 0;
    default:
       return 0; /* bad target */
@@ -1373,7 +1382,8 @@ target_can_be_compressed(const struct gl_context *ctx, GLenum target,
       return ctx->Extensions.ARB_texture_cube_map;
    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
    case GL_TEXTURE_2D_ARRAY_EXT:
-      return ctx->Extensions.MESA_texture_array;
+      return (ctx->Extensions.MESA_texture_array ||
+              ctx->Extensions.EXT_texture_array);
    default:
       return GL_FALSE;
    }      
@@ -1414,7 +1424,8 @@ legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target)
          return ctx->Extensions.NV_texture_rectangle;
       case GL_TEXTURE_1D_ARRAY_EXT:
       case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
-         return ctx->Extensions.MESA_texture_array;
+         return (ctx->Extensions.MESA_texture_array ||
+                 ctx->Extensions.EXT_texture_array);
       default:
          return GL_FALSE;
       }
@@ -1425,7 +1436,8 @@ legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target)
          return GL_TRUE;
       case GL_TEXTURE_2D_ARRAY_EXT:
       case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
-         return ctx->Extensions.MESA_texture_array;
+         return (ctx->Extensions.MESA_texture_array ||
+                 ctx->Extensions.EXT_texture_array);
       default:
          return GL_FALSE;
       }
@@ -1462,7 +1474,8 @@ legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target)
       case GL_TEXTURE_RECTANGLE_NV:
          return ctx->Extensions.NV_texture_rectangle;
       case GL_TEXTURE_1D_ARRAY_EXT:
-         return ctx->Extensions.MESA_texture_array;
+         return (ctx->Extensions.MESA_texture_array ||
+                 ctx->Extensions.EXT_texture_array);
       default:
          return GL_FALSE;
       }
@@ -1471,7 +1484,8 @@ legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target)
       case GL_TEXTURE_3D:
          return GL_TRUE;
       case GL_TEXTURE_2D_ARRAY_EXT:
-         return ctx->Extensions.MESA_texture_array;
+         return (ctx->Extensions.MESA_texture_array ||
+                 ctx->Extensions.EXT_texture_array);
       default:
          return GL_FALSE;
       }
index 29e409d0b8c5a0f2fef051e1522aad3f88dc7620..6e14face4dd35b43532ed5c4da23c4e17c54d808 100644 (file)
@@ -33,6 +33,7 @@
 #include "main/glheader.h"
 #include "main/colormac.h"
 #include "main/context.h"
+#include "main/enums.h"
 #include "main/formats.h"
 #include "main/macros.h"
 #include "main/mfeatures.h"
@@ -116,12 +117,14 @@ get_texobj(struct gl_context *ctx, GLenum target, GLboolean get)
       }
       break;
    case GL_TEXTURE_1D_ARRAY_EXT:
-      if (ctx->Extensions.MESA_texture_array) {
+      if (ctx->Extensions.MESA_texture_array ||
+          ctx->Extensions.EXT_texture_array) {
          return texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX];
       }
       break;
    case GL_TEXTURE_2D_ARRAY_EXT:
-      if (ctx->Extensions.MESA_texture_array) {
+      if (ctx->Extensions.MESA_texture_array ||
+          ctx->Extensions.EXT_texture_array) {
          return texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX];
       }
       break;
@@ -175,13 +178,26 @@ set_swizzle_component(GLuint *swizzle, GLuint comp, GLuint swz)
 
 
 /**
- * This is called just prior to changing any texture object state.
+ * This is called just prior to changing any texture object state which
+ * will not effect texture completeness.
+ */
+static INLINE void
+flush(struct gl_context *ctx)
+{
+   FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+}
+
+
+/**
+ * This is called just prior to changing any texture object state which
+ * can effect texture completeness (texture base level, max level,
+ * minification filter).
  * Any pending rendering will be flushed out, we'll set the _NEW_TEXTURE
  * state flag and then mark the texture object as 'incomplete' so that any
  * per-texture derived state gets recomputed.
  */
 static INLINE void
-flush(struct gl_context *ctx, struct gl_texture_object *texObj)
+incomplete(struct gl_context *ctx, struct gl_texture_object *texObj)
 {
    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
    texObj->_Complete = GL_FALSE;
@@ -204,7 +220,7 @@ set_tex_parameteri(struct gl_context *ctx,
       switch (params[0]) {
       case GL_NEAREST:
       case GL_LINEAR:
-         flush(ctx, texObj);
+         incomplete(ctx, texObj);
          texObj->MinFilter = params[0];
          return GL_TRUE;
       case GL_NEAREST_MIPMAP_NEAREST:
@@ -212,14 +228,13 @@ set_tex_parameteri(struct gl_context *ctx,
       case GL_NEAREST_MIPMAP_LINEAR:
       case GL_LINEAR_MIPMAP_LINEAR:
          if (texObj->Target != GL_TEXTURE_RECTANGLE_NV) {
-            flush(ctx, texObj);
+            incomplete(ctx, texObj);
             texObj->MinFilter = params[0];
             return GL_TRUE;
          }
          /* fall-through */
       default:
-         _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(param=0x%x)",
-                      params[0] );
+         goto invalid_param;
       }
       return GL_FALSE;
 
@@ -229,12 +244,11 @@ set_tex_parameteri(struct gl_context *ctx,
       switch (params[0]) {
       case GL_NEAREST:
       case GL_LINEAR:
-         flush(ctx, texObj);
+         flush(ctx); /* does not effect completeness */
          texObj->MagFilter = params[0];
          return GL_TRUE;
       default:
-         _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(param=0x%x)",
-                      params[0]);
+         goto invalid_param;
       }
       return GL_FALSE;
 
@@ -242,7 +256,7 @@ set_tex_parameteri(struct gl_context *ctx,
       if (texObj->WrapS == params[0])
          return GL_FALSE;
       if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
-         flush(ctx, texObj);
+         flush(ctx);
          texObj->WrapS = params[0];
          return GL_TRUE;
       }
@@ -252,7 +266,7 @@ set_tex_parameteri(struct gl_context *ctx,
       if (texObj->WrapT == params[0])
          return GL_FALSE;
       if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
-         flush(ctx, texObj);
+         flush(ctx);
          texObj->WrapT = params[0];
          return GL_TRUE;
       }
@@ -262,7 +276,7 @@ set_tex_parameteri(struct gl_context *ctx,
       if (texObj->WrapR == params[0])
          return GL_FALSE;
       if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
-         flush(ctx, texObj);
+         flush(ctx);
          texObj->WrapR = params[0];
          return GL_TRUE;
       }
@@ -277,7 +291,7 @@ set_tex_parameteri(struct gl_context *ctx,
                      "glTexParameter(param=%d)", params[0]);
          return GL_FALSE;
       }
-      flush(ctx, texObj);
+      incomplete(ctx, texObj);
       texObj->BaseLevel = params[0];
       return GL_TRUE;
 
@@ -289,34 +303,31 @@ set_tex_parameteri(struct gl_context *ctx,
                      "glTexParameter(param=%d)", params[0]);
          return GL_FALSE;
       }
-      flush(ctx, texObj);
+      incomplete(ctx, texObj);
       texObj->MaxLevel = params[0];
       return GL_TRUE;
 
    case GL_GENERATE_MIPMAP_SGIS:
       if (texObj->GenerateMipmap != params[0]) {
-        flush(ctx, texObj);
+         /* no flush() */
         texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
         return GL_TRUE;
       }
       return GL_FALSE;
 
    case GL_TEXTURE_COMPARE_MODE_ARB:
-      if (ctx->Extensions.ARB_shadow &&
-          (params[0] == GL_NONE ||
-           params[0] == GL_COMPARE_R_TO_TEXTURE_ARB)) {
-         if (texObj->CompareMode != params[0]) {
-            flush(ctx, texObj);
+      if (ctx->Extensions.ARB_shadow) {
+         if (texObj->CompareMode == params[0])
+            return GL_FALSE;
+         if (params[0] == GL_NONE ||
+             params[0] == GL_COMPARE_R_TO_TEXTURE_ARB) {
+            flush(ctx);
             texObj->CompareMode = params[0];
             return GL_TRUE;
          }
-         return GL_FALSE;
-      }
-      else {
-         _mesa_error(ctx, GL_INVALID_ENUM,
-                     "glTexParameter(GL_TEXTURE_COMPARE_MODE_ARB)");
+         goto invalid_param;
       }
-      return GL_FALSE;
+      goto invalid_pname;
 
    case GL_TEXTURE_COMPARE_FUNC_ARB:
       if (ctx->Extensions.ARB_shadow) {
@@ -325,7 +336,7 @@ set_tex_parameteri(struct gl_context *ctx,
          switch (params[0]) {
          case GL_LEQUAL:
          case GL_GEQUAL:
-            flush(ctx, texObj);
+            flush(ctx);
             texObj->CompareFunc = params[0];
             return GL_TRUE;
          case GL_EQUAL:
@@ -335,38 +346,32 @@ set_tex_parameteri(struct gl_context *ctx,
          case GL_ALWAYS:
          case GL_NEVER:
             if (ctx->Extensions.EXT_shadow_funcs) {
-               flush(ctx, texObj);
+               flush(ctx);
                texObj->CompareFunc = params[0];
                return GL_TRUE;
             }
             /* fall-through */
          default:
-            _mesa_error(ctx, GL_INVALID_ENUM,
-                        "glTexParameter(GL_TEXTURE_COMPARE_FUNC_ARB)");
+            goto invalid_param;
          }
       }
-      else {
-         _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
-      }
-      return GL_FALSE;
+      goto invalid_pname;
 
    case GL_DEPTH_TEXTURE_MODE_ARB:
-      if (ctx->Extensions.ARB_depth_texture &&
-          (params[0] == GL_LUMINANCE ||
-           params[0] == GL_INTENSITY ||
-           params[0] == GL_ALPHA ||
-          (ctx->Extensions.ARB_texture_rg && params[0] == GL_RED))) {
-         if (texObj->DepthMode != params[0]) {
-            flush(ctx, texObj);
+      if (ctx->Extensions.ARB_depth_texture) {
+         if (texObj->DepthMode == params[0])
+            return GL_FALSE;
+         if (params[0] == GL_LUMINANCE ||
+             params[0] == GL_INTENSITY ||
+             params[0] == GL_ALPHA ||
+             (ctx->Extensions.ARB_texture_rg && params[0] == GL_RED)) {
+            flush(ctx);
             texObj->DepthMode = params[0];
             return GL_TRUE;
          }
+         goto invalid_param;
       }
-      else {
-         _mesa_error(ctx, GL_INVALID_ENUM,
-                     "glTexParameter(GL_DEPTH_TEXTURE_MODE_ARB)");
-      }
-      return GL_FALSE;
+      goto invalid_pname;
 
 #if FEATURE_OES_draw_texture
    case GL_TEXTURE_CROP_RECT_OES:
@@ -391,19 +396,18 @@ set_tex_parameteri(struct gl_context *ctx,
          }
          ASSERT(comp < 4);
          if (swz >= 0) {
-            flush(ctx, texObj);
+            flush(ctx);
             texObj->Swizzle[comp] = params[0];
             set_swizzle_component(&texObj->_Swizzle, comp, swz);
             return GL_TRUE;
          }
       }
-      _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
-      return GL_FALSE;
+      goto invalid_pname;
 
    case GL_TEXTURE_SWIZZLE_RGBA_EXT:
       if (ctx->Extensions.EXT_texture_swizzle) {
          GLuint comp;
-         flush(ctx, texObj);
+         flush(ctx);
          for (comp = 0; comp < 4; comp++) {
             const GLint swz = comp_to_swizzle(params[comp]);
             if (swz >= 0) {
@@ -418,25 +422,34 @@ set_tex_parameteri(struct gl_context *ctx,
          }
          return GL_TRUE;
       }
-      _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
-      return GL_FALSE;
+      goto invalid_pname;
+
    case GL_TEXTURE_SRGB_DECODE_EXT:
       if (ctx->Extensions.EXT_texture_sRGB_decode) {
         GLenum decode = params[0];
         if (decode == GL_DECODE_EXT || decode == GL_SKIP_DECODE_EXT) {
            if (texObj->sRGBDecode != decode) {
-              flush(ctx, texObj);
+              flush(ctx);
               texObj->sRGBDecode = decode;
               _mesa_update_fetch_functions(texObj);
            }
            return GL_TRUE;
         }
       }
-      _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
-      return GL_FALSE;
+      goto invalid_pname;
+
    default:
-      _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
+      goto invalid_pname;
    }
+
+invalid_pname:
+   _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=%s)",
+               _mesa_lookup_enum_by_nr(pname));
+   return GL_FALSE;
+
+invalid_param:
+   _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param=%s)",
+               _mesa_lookup_enum_by_nr(params[0]));
    return GL_FALSE;
 }
 
@@ -454,19 +467,19 @@ set_tex_parameterf(struct gl_context *ctx,
    case GL_TEXTURE_MIN_LOD:
       if (texObj->MinLod == params[0])
          return GL_FALSE;
-      flush(ctx, texObj);
+      flush(ctx);
       texObj->MinLod = params[0];
       return GL_TRUE;
 
    case GL_TEXTURE_MAX_LOD:
       if (texObj->MaxLod == params[0])
          return GL_FALSE;
-      flush(ctx, texObj);
+      flush(ctx);
       texObj->MaxLod = params[0];
       return GL_TRUE;
 
    case GL_TEXTURE_PRIORITY:
-      flush(ctx, texObj);
+      flush(ctx);
       texObj->Priority = CLAMP(params[0], 0.0F, 1.0F);
       return GL_TRUE;
 
@@ -478,7 +491,7 @@ set_tex_parameterf(struct gl_context *ctx,
             _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
             return GL_FALSE;
          }
-         flush(ctx, texObj);
+         flush(ctx);
          /* clamp to max, that's what NVIDIA does */
          texObj->MaxAnisotropy = MIN2(params[0],
                                       ctx->Const.MaxTextureMaxAnisotropy);
@@ -495,7 +508,7 @@ set_tex_parameterf(struct gl_context *ctx,
    case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
       if (ctx->Extensions.ARB_shadow_ambient) {
          if (texObj->CompareFailValue != params[0]) {
-            flush(ctx, texObj);
+            flush(ctx);
             texObj->CompareFailValue = CLAMP(params[0], 0.0F, 1.0F);
             return GL_TRUE;
          }
@@ -510,7 +523,7 @@ set_tex_parameterf(struct gl_context *ctx,
       /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias */
       if (ctx->Extensions.EXT_texture_lod_bias) {
          if (texObj->LodBias != params[0]) {
-            flush(ctx, texObj);
+            flush(ctx);
             texObj->LodBias = params[0];
             return GL_TRUE;
          }
@@ -519,7 +532,7 @@ set_tex_parameterf(struct gl_context *ctx,
       break;
 
    case GL_TEXTURE_BORDER_COLOR:
-      flush(ctx, texObj);
+      flush(ctx);
       texObj->BorderColor.f[RCOMP] = params[0];
       texObj->BorderColor.f[GCOMP] = params[1];
       texObj->BorderColor.f[BCOMP] = params[2];
@@ -821,7 +834,6 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
    const struct gl_texture_unit *texUnit;
    struct gl_texture_object *texObj;
    const struct gl_texture_image *img = NULL;
-   GLboolean isProxy;
    GLint maxLevels;
    gl_format texFormat;
    GET_CURRENT_CONTEXT(ctx);
@@ -849,7 +861,6 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
    }
 
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
-   _mesa_lock_texture(ctx, texObj);
 
    img = _mesa_select_tex_image(ctx, texObj, target, level);
    if (!img || !img->TexFormat) {
@@ -858,13 +869,11 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
          *params = 1;
       else
          *params = 0;
-      goto out;
+      return;
    }
 
    texFormat = img->TexFormat;
 
-   isProxy = _mesa_is_proxy_texture(target);
-
    switch (pname) {
       case GL_TEXTURE_WIDTH:
          *params = img->Width;
@@ -876,9 +885,9 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
          *params = img->Depth;
          break;
       case GL_TEXTURE_INTERNAL_FORMAT:
-         if (_mesa_is_format_compressed(img->TexFormat)) {
+         if (_mesa_is_format_compressed(texFormat)) {
             /* need to return the actual compressed format */
-            *params = _mesa_compressed_format_to_glenum(ctx, img->TexFormat);
+            *params = _mesa_compressed_format_to_glenum(ctx, texFormat);
          }
          else {
             /* return the user's requested internal format */
@@ -949,8 +958,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
          if (ctx->Extensions.ARB_depth_texture)
             *params = _mesa_get_format_bits(texFormat, pname);
          else
-            _mesa_error(ctx, GL_INVALID_ENUM,
-                        "glGetTexLevelParameter[if]v(pname)");
+            goto invalid_pname;
          break;
       case GL_TEXTURE_STENCIL_SIZE_EXT:
          if (ctx->Extensions.EXT_packed_depth_stencil ||
@@ -958,8 +966,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             *params = _mesa_get_format_bits(texFormat, pname);
          }
          else {
-            _mesa_error(ctx, GL_INVALID_ENUM,
-                        "glGetTexLevelParameter[if]v(pname)");
+            goto invalid_pname;
          }
          break;
       case GL_TEXTURE_SHARED_SIZE:
@@ -970,14 +977,14 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             *params = 0;
          }
          else {
-            _mesa_error(ctx, GL_INVALID_ENUM,
-                        "glGetTexLevelParameter[if]v(pname)");
+            goto invalid_pname;
          }
          break;
 
       /* GL_ARB_texture_compression */
       case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
-        if (_mesa_is_format_compressed(img->TexFormat) && !isProxy) {
+        if (_mesa_is_format_compressed(texFormat) &&
+             !_mesa_is_proxy_texture(target)) {
             *params = _mesa_format_image_size(texFormat, img->Width,
                                               img->Height, img->Depth);
         }
@@ -987,7 +994,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
         }
          break;
       case GL_TEXTURE_COMPRESSED:
-         *params = (GLint) _mesa_is_format_compressed(img->TexFormat);
+         *params = (GLint) _mesa_is_format_compressed(texFormat);
          break;
 
       /* GL_ARB_texture_float */
@@ -997,8 +1004,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
                _mesa_get_format_datatype(texFormat) : GL_NONE;
          }
          else {
-            _mesa_error(ctx, GL_INVALID_ENUM,
-                        "glGetTexLevelParameter[if]v(pname)");
+            goto invalid_pname;
          }
          break;
       case GL_TEXTURE_GREEN_TYPE_ARB:
@@ -1007,8 +1013,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
                _mesa_get_format_datatype(texFormat) : GL_NONE;
          }
          else {
-            _mesa_error(ctx, GL_INVALID_ENUM,
-                        "glGetTexLevelParameter[if]v(pname)");
+            goto invalid_pname;
          }
          break;
       case GL_TEXTURE_BLUE_TYPE_ARB:
@@ -1017,8 +1022,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
                _mesa_get_format_datatype(texFormat) : GL_NONE;
          }
          else {
-            _mesa_error(ctx, GL_INVALID_ENUM,
-                        "glGetTexLevelParameter[if]v(pname)");
+            goto invalid_pname;
          }
          break;
       case GL_TEXTURE_ALPHA_TYPE_ARB:
@@ -1027,8 +1031,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
                _mesa_get_format_datatype(texFormat) : GL_NONE;
          }
          else {
-            _mesa_error(ctx, GL_INVALID_ENUM,
-                        "glGetTexLevelParameter[if]v(pname)");
+            goto invalid_pname;
          }
          break;
       case GL_TEXTURE_LUMINANCE_TYPE_ARB:
@@ -1037,8 +1040,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
                _mesa_get_format_datatype(texFormat) : GL_NONE;
          }
          else {
-            _mesa_error(ctx, GL_INVALID_ENUM,
-                        "glGetTexLevelParameter[if]v(pname)");
+            goto invalid_pname;
          }
          break;
       case GL_TEXTURE_INTENSITY_TYPE_ARB:
@@ -1047,8 +1049,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
                _mesa_get_format_datatype(texFormat) : GL_NONE;
          }
          else {
-            _mesa_error(ctx, GL_INVALID_ENUM,
-                        "glGetTexLevelParameter[if]v(pname)");
+            goto invalid_pname;
          }
          break;
       case GL_TEXTURE_DEPTH_TYPE_ARB:
@@ -1057,18 +1058,21 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
                _mesa_get_format_datatype(texFormat) : GL_NONE;
          }
          else {
-            _mesa_error(ctx, GL_INVALID_ENUM,
-                        "glGetTexLevelParameter[if]v(pname)");
+            goto invalid_pname;
          }
          break;
 
       default:
-         _mesa_error(ctx, GL_INVALID_ENUM,
-                     "glGetTexLevelParameter[if]v(pname)");
+         goto invalid_pname;
    }
 
- out:
-   _mesa_unlock_texture(ctx, texObj);
+   /* no error if we get here */
+   return;
+
+invalid_pname:
+   _mesa_error(ctx, GL_INVALID_ENUM,
+               "glGetTexLevelParameter[if]v(pname=%s)",
+               _mesa_lookup_enum_by_nr(pname));
 }
 
 
index aee2e6b4e9bc52579e3154c6a3204f733e8c76a8..eb289722d1ac36d2aae34d2ecf93b675a01efa98 100644 (file)
@@ -450,6 +450,36 @@ _mesa_get_active_uniform(struct gl_context *ctx, GLuint program, GLuint index,
 }
 
 
+static unsigned
+get_vector_elements(GLenum type)
+{
+   switch (type) {
+   case GL_FLOAT:
+   case GL_INT:
+   case GL_BOOL:
+   case GL_UNSIGNED_INT:
+   default: /* Catch all the various sampler types. */
+      return 1;
+
+   case GL_FLOAT_VEC2:
+   case GL_INT_VEC2:
+   case GL_BOOL_VEC2:
+   case GL_UNSIGNED_INT_VEC2:
+      return 2;
+
+   case GL_FLOAT_VEC3:
+   case GL_INT_VEC3:
+   case GL_BOOL_VEC3:
+   case GL_UNSIGNED_INT_VEC3:
+      return 3;
+
+   case GL_FLOAT_VEC4:
+   case GL_INT_VEC4:
+   case GL_BOOL_VEC4:
+   case GL_UNSIGNED_INT_VEC4:
+      return 4;
+   }
+}
 
 static void
 get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
@@ -508,17 +538,8 @@ get_uniform_rows_cols(const struct gl_program_parameter *p,
    get_matrix_dims(p->DataType, rows, cols);
    if (*rows == 0 && *cols == 0) {
       /* not a matrix type, probably a float or vector */
-      if (p->Size <= 4) {
-         *rows = 1;
-         *cols = p->Size;
-      }
-      else {
-         *rows = (p->Size + 3) / 4;
-         if (p->Size % 4 == 0)
-            *cols = 4;
-         else
-            *cols = p->Size % 4;
-      }
+      *rows = 1;
+      *cols = get_vector_elements(p->DataType);
    }
 }
 
@@ -642,8 +663,10 @@ _mesa_get_uniformfv(struct gl_context *ctx, GLuint program, GLint location,
 
       k = 0;
       for (i = 0; i < rows; i++) {
+        const int base = paramPos + offset + i;
+
          for (j = 0; j < cols; j++ ) {
-            params[k++] = prog->Parameters->ParameterValues[paramPos+i][j];
+            params[k++] = prog->Parameters->ParameterValues[base][j];
          }
       }
    }
@@ -675,8 +698,10 @@ _mesa_get_uniformiv(struct gl_context *ctx, GLuint program, GLint location,
 
       k = 0;
       for (i = 0; i < rows; i++) {
+        const int base = paramPos + offset + i;
+
          for (j = 0; j < cols; j++ ) {
-            params[k++] = (GLint) prog->Parameters->ParameterValues[paramPos+i][j];
+            params[k++] = (GLint) prog->Parameters->ParameterValues[base][j];
          }
       }
    }
@@ -709,8 +734,10 @@ _mesa_get_uniformuiv(struct gl_context *ctx, GLuint program, GLint location,
 
       k = 0;
       for (i = 0; i < rows; i++) {
+        const int base = paramPos + offset + i;
+
          for (j = 0; j < cols; j++ ) {
-            params[k++] = (GLuint) prog->Parameters->ParameterValues[paramPos+i][j];
+            params[k++] = (GLuint) prog->Parameters->ParameterValues[base][j];
          }
       }
    }
index 29d8a8827e385d78e35a5af0db259f13aab3082d..cfed4b506a5a86478b7f3f44ea6b49ff4b99a4f3 100644 (file)
@@ -508,7 +508,7 @@ get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
 {
    const struct gl_client_array *array;
 
-   if (index >= MAX_VERTEX_GENERIC_ATTRIBS) {
+   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
       _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index);
       return 0;
    }
@@ -550,6 +550,25 @@ error:
 }
 
 
+static const GLfloat *
+get_current_attrib(struct gl_context *ctx, GLuint index, const char *function)
+{
+   if (index == 0) {
+      if (ctx->API != API_OPENGLES2) {
+        _mesa_error(ctx, GL_INVALID_OPERATION, "%s(index==0)", function);
+        return NULL;
+      }
+   }
+   else if (index >= ctx->Const.VertexProgram.MaxAttribs) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                 "%s(index>=GL_MAX_VERTEX_ATTRIBS)", function);
+      return NULL;
+   }
+
+   FLUSH_CURRENT(ctx, 0);
+   return ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
+}
+
 void GLAPIENTRY
 _mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
 {
@@ -557,13 +576,8 @@ _mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
-      if (index == 0) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glGetVertexAttribfv(index==0)");
-      }
-      else {
-         const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
-         FLUSH_CURRENT(ctx, 0);
+      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribfv");
+      if (v != NULL) {
          COPY_4V(params, v);
       }
    }
@@ -581,13 +595,8 @@ _mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
-      if (index == 0) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glGetVertexAttribdv(index==0)");
-      }
-      else {
-         const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
-         FLUSH_CURRENT(ctx, 0);
+      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribdv");
+      if (v != NULL) {
          params[0] = (GLdouble) v[0];
          params[1] = (GLdouble) v[1];
          params[2] = (GLdouble) v[2];
@@ -608,13 +617,8 @@ _mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params)
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
-      if (index == 0) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glGetVertexAttribiv(index==0)");
-      }
-      else {
-         const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
-         FLUSH_CURRENT(ctx, 0);
+      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribiv");
+      if (v != NULL) {
          /* XXX should floats in[0,1] be scaled to full int range? */
          params[0] = (GLint) v[0];
          params[1] = (GLint) v[1];
@@ -637,13 +641,9 @@ _mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
-      if (index == 0) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glGetVertexAttribIiv(index==0)");
-      }
-      else {
-         const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
-         FLUSH_CURRENT(ctx, 0);
+      const GLfloat *v =
+        get_current_attrib(ctx, index, "glGetVertexAttribIiv");
+      if (v != NULL) {
          /* XXX we don't have true integer-valued vertex attribs yet */
          params[0] = (GLint) v[0];
          params[1] = (GLint) v[1];
@@ -666,13 +666,9 @@ _mesa_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
-      if (index == 0) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glGetVertexAttribIuiv(index==0)");
-      }
-      else {
-         const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
-         FLUSH_CURRENT(ctx, 0);
+      const GLfloat *v =
+        get_current_attrib(ctx, index, "glGetVertexAttribIuiv");
+      if (v != NULL) {
          /* XXX we don't have true integer-valued vertex attribs yet */
          params[0] = (GLuint) v[0];
          params[1] = (GLuint) v[1];
index 786fdfbd231d9b71e84d1c82f8f66de6b0ff712d..33c262f8ca4cea2833bc838a80f9551020ed0a8d 100644 (file)
@@ -105,13 +105,13 @@ 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). */
+   /* Callers of this ralloc-based new need not call delete. It's
+    * easier to just ralloc_free 'ctx' (or any of its ancestors). */
    static void* operator new(size_t size, void *ctx)
    {
       void *node;
 
-      node = talloc_zero_size(ctx, size);
+      node = rzalloc_size(ctx, size);
       assert(node != NULL);
 
       return node;
@@ -318,7 +318,7 @@ 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);
+   ralloc_vasprintf_append(&prog->InfoLog, fmt, args);
    va_end(args);
 
    prog->LinkStatus = GL_FALSE;
@@ -651,6 +651,7 @@ type_size(const struct glsl_type *type)
         return 1;
       }
    case GLSL_TYPE_ARRAY:
+      assert(type->length > 0);
       return type_size(type->fields.array) * type->length;
    case GLSL_TYPE_STRUCT:
       size = 0;
@@ -726,6 +727,29 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
 
       fp->OriginUpperLeft = ir->origin_upper_left;
       fp->PixelCenterInteger = ir->pixel_center_integer;
+
+   } else if (strcmp(ir->name, "gl_FragDepth") == 0) {
+      struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog;
+      switch (ir->depth_layout) {
+      case ir_depth_layout_none:
+        fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_NONE;
+        break;
+      case ir_depth_layout_any:
+        fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_ANY;
+        break;
+      case ir_depth_layout_greater:
+        fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_GREATER;
+        break;
+      case ir_depth_layout_less:
+        fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_LESS;
+        break;
+      case ir_depth_layout_unchanged:
+        fp->FragDepthLayout = FRAG_DEPTH_LAYOUT_UNCHANGED;
+        break;
+      default:
+        assert(0);
+        break;
+      }
    }
 
    if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) {
@@ -1451,18 +1475,17 @@ void
 ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
 {
    variable_storage *entry = find_variable_storage(ir->var);
+   ir_variable *var = ir->var;
 
    if (!entry) {
-      switch (ir->var->mode) {
+      switch (var->mode) {
       case ir_var_uniform:
-        entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_UNIFORM,
-                                              ir->var->location);
+        entry = new(mem_ctx) variable_storage(var, PROGRAM_UNIFORM,
+                                              var->location);
         this->variables.push_tail(entry);
         break;
       case ir_var_in:
-      case ir_var_out:
       case ir_var_inout:
-      case ir_var_system_value:
         /* The linker assigns locations for varyings and attributes,
          * including deprecated builtins (like gl_Color), user-assign
          * generic attributes (glBindVertexLocation), and
@@ -1470,49 +1493,47 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
          *
          * 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 if (ir->var->mode == ir_var_system_value) {
-           entry = new(mem_ctx) variable_storage(ir->var,
-                                                 PROGRAM_SYSTEM_VALUE,
-                                                 ir->var->location);
-        } else {
-           entry = new(mem_ctx) variable_storage(ir->var,
-                                                 PROGRAM_OUTPUT,
-                                                 ir->var->location);
-        }
-
+        assert(var->location != -1);
+         entry = new(mem_ctx) variable_storage(var,
+                                               PROGRAM_INPUT,
+                                               var->location);
+         if (this->prog->Target == GL_VERTEX_PROGRAM_ARB &&
+             var->location >= VERT_ATTRIB_GENERIC0) {
+            _mesa_add_attribute(this->prog->Attributes,
+                                var->name,
+                                _mesa_sizeof_glsl_type(var->type->gl_type),
+                                var->type->gl_type,
+                                var->location - VERT_ATTRIB_GENERIC0);
+         }
+         break;
+      case ir_var_out:
+        assert(var->location != -1);
+         entry = new(mem_ctx) variable_storage(var,
+                                               PROGRAM_OUTPUT,
+                                               var->location);
         break;
+      case ir_var_system_value:
+         entry = new(mem_ctx) variable_storage(var,
+                                               PROGRAM_SYSTEM_VALUE,
+                                               var->location);
+         break;
       case ir_var_auto:
       case ir_var_temporary:
-        entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_TEMPORARY,
+        entry = new(mem_ctx) variable_storage(var, PROGRAM_TEMPORARY,
                                               this->next_temp);
         this->variables.push_tail(entry);
 
-        next_temp += type_size(ir->var->type);
+        next_temp += type_size(var->type);
         break;
       }
 
       if (!entry) {
-        printf("Failed to make storage for %s\n", ir->var->name);
+        printf("Failed to make storage for %s\n", var->name);
         exit(1);
       }
    }
 
-   this->result = ir_to_mesa_src_reg(entry->file, entry->index, ir->var->type);
+   this->result = ir_to_mesa_src_reg(entry->file, entry->index, var->type);
 }
 
 void
@@ -1549,7 +1570,7 @@ ir_to_mesa_visitor::visit(ir_dereference_array *ir)
                             this->result, src_reg_for_float(element_size));
       }
 
-      src_reg.reladdr = talloc(mem_ctx, ir_to_mesa_src_reg);
+      src_reg.reladdr = ralloc(mem_ctx, ir_to_mesa_src_reg);
       memcpy(src_reg.reladdr, &index_reg, sizeof(index_reg));
    }
 
@@ -1906,7 +1927,7 @@ ir_to_mesa_visitor::get_function_signature(ir_function_signature *sig)
         return entry;
    }
 
-   entry = talloc(mem_ctx, function_entry);
+   entry = ralloc(mem_ctx, function_entry);
    entry->sig = sig;
    entry->sig_id = this->next_signature_id++;
    entry->bgn_inst = NULL;
@@ -2243,12 +2264,12 @@ ir_to_mesa_visitor::ir_to_mesa_visitor()
    next_temp = 1;
    next_signature_id = 1;
    current_function = NULL;
-   mem_ctx = talloc_new(NULL);
+   mem_ctx = ralloc_context(NULL);
 }
 
 ir_to_mesa_visitor::~ir_to_mesa_visitor()
 {
-   talloc_free(mem_ctx);
+   ralloc_free(mem_ctx);
 }
 
 static struct prog_src_register
@@ -2297,8 +2318,8 @@ set_branchtargets(ir_to_mesa_visitor *v,
       }
    }
 
-   if_stack = talloc_zero_array(v->mem_ctx, int, if_count);
-   loop_stack = talloc_zero_array(v->mem_ctx, int, loop_count);
+   if_stack = rzalloc_array(v->mem_ctx, int, if_count);
+   loop_stack = rzalloc_array(v->mem_ctx, int, loop_count);
 
    for (i = 0; i < num_instructions; i++) {
       switch (mesa_instructions[i].Opcode) {
@@ -2441,7 +2462,7 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program,
    unsigned int next_sampler = 0, num_uniforms = 0;
    struct uniform_sort *sorted_uniforms;
 
-   sorted_uniforms = talloc_array(NULL, struct uniform_sort,
+   sorted_uniforms = ralloc_array(NULL, struct uniform_sort,
                                  shader_program->Uniforms->NumUniforms);
 
    for (i = 0; i < shader_program->Uniforms->NumUniforms; i++) {
@@ -2520,7 +2541,7 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program,
       }
    }
 
-   talloc_free(sorted_uniforms);
+   ralloc_free(sorted_uniforms);
 }
 
 static void
@@ -2536,7 +2557,7 @@ set_uniform_initializer(struct gl_context *ctx, void *mem_ctx,
 
       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,
+        const char *field_name = ralloc_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);
@@ -2567,7 +2588,7 @@ set_uniform_initializer(struct gl_context *ctx, void *mem_ctx,
       void *values;
 
       if (element_type->base_type == GLSL_TYPE_BOOL) {
-        int *conv = talloc_array(mem_ctx, int, element_type->components());
+        int *conv = ralloc_array(mem_ctx, int, element_type->components());
         for (unsigned int j = 0; j < element_type->components(); j++) {
            conv[j] = element->value.b[j];
         }
@@ -2613,14 +2634,14 @@ set_uniform_initializers(struct gl_context *ctx,
            continue;
 
         if (!mem_ctx)
-           mem_ctx = talloc_new(NULL);
+           mem_ctx = ralloc_context(NULL);
 
         set_uniform_initializer(ctx, mem_ctx, shader_program, var->name,
                                 var->type, var->constant_value);
       }
    }
 
-   talloc_free(mem_ctx);
+   ralloc_free(mem_ctx);
 }
 
 /*
@@ -2646,13 +2667,18 @@ set_uniform_initializers(struct gl_context *ctx,
 void
 ir_to_mesa_visitor::copy_propagate(void)
 {
-   ir_to_mesa_instruction **acp = talloc_zero_array(mem_ctx,
+   ir_to_mesa_instruction **acp = rzalloc_array(mem_ctx,
                                                    ir_to_mesa_instruction *,
                                                    this->next_temp * 4);
+   int *acp_level = rzalloc_array(mem_ctx, int, this->next_temp * 4);
+   int level = 0;
 
    foreach_iter(exec_list_iterator, iter, this->instructions) {
       ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get();
 
+      assert(inst->dst_reg.file != PROGRAM_TEMPORARY
+            || inst->dst_reg.index < this->next_temp);
+
       /* First, do any copy propagation possible into the src regs. */
       for (int r = 0; r < 3; r++) {
         ir_to_mesa_instruction *first = NULL;
@@ -2676,6 +2702,8 @@ ir_to_mesa_visitor::copy_propagate(void)
               break;
            }
 
+           assert(acp_level[acp_base + src_chan] <= level);
+
            if (!first) {
               first = copy_chan;
            } else {
@@ -2708,23 +2736,79 @@ ir_to_mesa_visitor::copy_propagate(void)
       switch (inst->op) {
       case OPCODE_BGNLOOP:
       case OPCODE_ENDLOOP:
-      case OPCODE_ELSE:
-      case OPCODE_ENDIF:
         /* End of a basic block, clear the ACP entirely. */
         memset(acp, 0, sizeof(*acp) * this->next_temp * 4);
         break;
 
+      case OPCODE_IF:
+        ++level;
+        break;
+
+      case OPCODE_ENDIF:
+      case OPCODE_ELSE:
+        /* Clear all channels written inside the block from the ACP, but
+         * leaving those that were not touched.
+         */
+        for (int r = 0; r < this->next_temp; r++) {
+           for (int c = 0; c < 4; c++) {
+              if (!acp[4 * r + c])
+                 continue;
+
+              if (acp_level[4 * r + c] >= level)
+                 acp[4 * r + c] = NULL;
+           }
+        }
+        if (inst->op == OPCODE_ENDIF)
+           --level;
+        break;
+
       default:
         /* Continuing the block, clear any written channels from
          * the ACP.
          */
-        if (inst->dst_reg.file == PROGRAM_TEMPORARY) {
-           if (inst->dst_reg.reladdr) {
-              memset(acp, 0, sizeof(*acp) * this->next_temp * 4);
-           } else {
-              for (int i = 0; i < 4; i++) {
-                 if (inst->dst_reg.writemask & (1 << i)) {
-                    acp[4 * inst->dst_reg.index + i] = NULL;
+        if (inst->dst_reg.file == PROGRAM_TEMPORARY && inst->dst_reg.reladdr) {
+           /* Any temporary might be written, so no copy propagation
+            * across this instruction.
+            */
+           memset(acp, 0, sizeof(*acp) * this->next_temp * 4);
+        } else if (inst->dst_reg.file == PROGRAM_OUTPUT &&
+                   inst->dst_reg.reladdr) {
+           /* Any output might be written, so no copy propagation
+            * from outputs across this instruction.
+            */
+           for (int r = 0; r < this->next_temp; r++) {
+              for (int c = 0; c < 4; c++) {
+                 if (!acp[4 * r + c])
+                    continue;
+
+                 if (acp[4 * r + c]->src_reg[0].file == PROGRAM_OUTPUT)
+                    acp[4 * r + c] = NULL;
+              }
+           }
+        } else if (inst->dst_reg.file == PROGRAM_TEMPORARY ||
+                   inst->dst_reg.file == PROGRAM_OUTPUT) {
+           /* Clear where it's used as dst. */
+           if (inst->dst_reg.file == PROGRAM_TEMPORARY) {
+              for (int c = 0; c < 4; c++) {
+                 if (inst->dst_reg.writemask & (1 << c)) {
+                    acp[4 * inst->dst_reg.index + c] = NULL;
+                 }
+              }
+           }
+
+           /* Clear where it's used as src. */
+           for (int r = 0; r < this->next_temp; r++) {
+              for (int c = 0; c < 4; c++) {
+                 if (!acp[4 * r + c])
+                    continue;
+
+                 int src_chan = GET_SWZ(acp[4 * r + c]->src_reg[0].swizzle, c);
+
+                 if (acp[4 * r + c]->src_reg[0].file == inst->dst_reg.file &&
+                     acp[4 * r + c]->src_reg[0].index == inst->dst_reg.index &&
+                     inst->dst_reg.writemask & (1 << src_chan))
+                 {
+                    acp[4 * r + c] = NULL;
                  }
               }
            }
@@ -2742,12 +2826,14 @@ ir_to_mesa_visitor::copy_propagate(void)
         for (int i = 0; i < 4; i++) {
            if (inst->dst_reg.writemask & (1 << i)) {
               acp[4 * inst->dst_reg.index + i] = inst;
+              acp_level[4 * inst->dst_reg.index + i] = level;
            }
         }
       }
    }
 
-   talloc_free(acp);
+   ralloc_free(acp_level);
+   ralloc_free(acp);
 }
 
 
@@ -2846,7 +2932,7 @@ get_mesa_program(struct gl_context *ctx,
    mesa_instructions =
       (struct prog_instruction *)calloc(num_instructions,
                                        sizeof(*mesa_instructions));
-   mesa_instruction_annotation = talloc_array(v.mem_ctx, ir_instruction *,
+   mesa_instruction_annotation = ralloc_array(v.mem_ctx, ir_instruction *,
                                              num_instructions);
 
    v.copy_propagate();
@@ -3103,7 +3189,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader)
      _mesa_glsl_lexer_dtor(state);
    }
 
-   talloc_free(shader->ir);
+   ralloc_free(shader->ir);
    shader->ir = new(shader) exec_list;
    if (!state->error && !state->translation_unit.is_empty())
       _mesa_ast_to_hir(shader->ir, state);
@@ -3150,7 +3236,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader)
    /* Retain any live IR, but trash the rest. */
    reparent_ir(shader->ir, shader->ir);
 
-   talloc_free(state);
+   ralloc_free(state);
 
    if (shader->CompileStatus) {
       if (!ctx->Driver.CompileShader(ctx, shader))
index f984e2f1402f536015b23e3818841bd6f7126429..95a9bde401a8bafd2b5bbc687b8bf7f7317e6b09 100644 (file)
@@ -30,7 +30,7 @@
  * Graph-coloring register allocator.
  */
 
-#include <talloc.h>
+#include <ralloc.h>
 
 #include "main/imports.h"
 #include "main/macros.h"
@@ -96,15 +96,15 @@ ra_alloc_reg_set(unsigned int count)
    unsigned int i;
    struct ra_regs *regs;
 
-   regs = talloc_zero(NULL, struct ra_regs);
+   regs = rzalloc(NULL, struct ra_regs);
    regs->count = count;
-   regs->regs = talloc_zero_array(regs, struct ra_reg, count);
+   regs->regs = rzalloc_array(regs, struct ra_reg, count);
 
    for (i = 0; i < count; i++) {
-      regs->regs[i].conflicts = talloc_zero_array(regs->regs, GLboolean, count);
+      regs->regs[i].conflicts = rzalloc_array(regs->regs, GLboolean, count);
       regs->regs[i].conflicts[i] = GL_TRUE;
 
-      regs->regs[i].conflict_list = talloc_array(regs->regs, unsigned int, 4);
+      regs->regs[i].conflict_list = ralloc_array(regs->regs, unsigned int, 4);
       regs->regs[i].conflict_list_size = 4;
       regs->regs[i].conflict_list[0] = i;
       regs->regs[i].num_conflicts = 1;
@@ -120,10 +120,8 @@ ra_add_conflict_list(struct ra_regs *regs, unsigned int r1, unsigned int r2)
 
    if (reg1->conflict_list_size == reg1->num_conflicts) {
       reg1->conflict_list_size *= 2;
-      reg1->conflict_list = talloc_realloc(regs,
-                                          reg1->conflict_list,
-                                          unsigned int,
-                                          reg1->conflict_list_size);
+      reg1->conflict_list = reralloc(regs->regs, reg1->conflict_list,
+                                    unsigned int, reg1->conflict_list_size);
    }
    reg1->conflict_list[reg1->num_conflicts++] = r2;
    reg1->conflicts[r2] = GL_TRUE;
@@ -143,14 +141,13 @@ ra_alloc_reg_class(struct ra_regs *regs)
 {
    struct ra_class *class;
 
-   regs->classes = talloc_realloc(regs, regs->classes,
-                                 struct ra_class *,
-                                 regs->class_count + 1);
+   regs->classes = reralloc(regs->regs, regs->classes, struct ra_class *,
+                           regs->class_count + 1);
 
-   class = talloc_zero(regs, struct ra_class);
+   class = rzalloc(regs, struct ra_class);
    regs->classes[regs->class_count] = class;
 
-   class->regs = talloc_zero_array(class, GLboolean, regs->count);
+   class->regs = rzalloc_array(class, GLboolean, regs->count);
 
    return regs->class_count++;
 }
@@ -174,7 +171,7 @@ ra_set_finalize(struct ra_regs *regs)
    unsigned int b, c;
 
    for (b = 0; b < regs->class_count; b++) {
-      regs->classes[b]->q = talloc_array(regs, unsigned int, regs->class_count);
+      regs->classes[b]->q = ralloc_array(regs, unsigned int, regs->class_count);
    }
 
    /* Compute, for each class B and C, how many regs of B an
@@ -218,16 +215,16 @@ ra_alloc_interference_graph(struct ra_regs *regs, unsigned int count)
    struct ra_graph *g;
    unsigned int i;
 
-   g = talloc_zero(regs, struct ra_graph);
+   g = rzalloc(regs, struct ra_graph);
    g->regs = regs;
-   g->nodes = talloc_zero_array(g, struct ra_node, count);
+   g->nodes = rzalloc_array(g, struct ra_node, count);
    g->count = count;
 
-   g->stack = talloc_zero_array(g, unsigned int, count);
+   g->stack = rzalloc_array(g, unsigned int, count);
 
    for (i = 0; i < count; i++) {
-      g->nodes[i].adjacency = talloc_zero_array(g, GLboolean, count);
-      g->nodes[i].adjacency_list = talloc_array(g, unsigned int, count);
+      g->nodes[i].adjacency = rzalloc_array(g, GLboolean, count);
+      g->nodes[i].adjacency_list = ralloc_array(g, unsigned int, count);
       g->nodes[i].adjacency_count = 0;
       ra_add_node_adjacency(g, i, i);
       g->nodes[i].reg = ~0;
index 9a813c87955e0fb613342808eb014ee799367238..1457d1199fac036d291be67e628c15bd88e458d2 100644 (file)
@@ -23,7 +23,6 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-#include <cstdio>
 #include "ir.h"
 #include "glsl_types.h"
 #include "ir_visitor.h"
@@ -40,7 +39,7 @@ 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);
+   ralloc_vasprintf_append(&prog->InfoLog, fmt, args);
    va_end(args);
 
    prog->LinkStatus = GL_FALSE;
@@ -52,7 +51,7 @@ public:
    get_sampler_name(ir_dereference *last,
                    struct gl_shader_program *shader_program)
    {
-      this->mem_ctx = talloc_new(NULL);
+      this->mem_ctx = ralloc_context(NULL);
       this->shader_program = shader_program;
       this->name = NULL;
       this->offset = 0;
@@ -61,7 +60,7 @@ public:
 
    ~get_sampler_name()
    {
-      talloc_free(this->mem_ctx);
+      ralloc_free(this->mem_ctx);
    }
 
    virtual ir_visitor_status visit(ir_dereference_variable *ir)
@@ -72,7 +71,7 @@ public:
 
    virtual ir_visitor_status visit_leave(ir_dereference_record *ir)
    {
-      this->name = talloc_asprintf(mem_ctx, "%s.%s", name, ir->field);
+      this->name = ralloc_asprintf(mem_ctx, "%s.%s", name, ir->field);
       return visit_continue;
    }
 
@@ -91,16 +90,14 @@ public:
          * all that would work would be an unrolled loop counter that ends
          * up being constant above.
          */
-        shader_program->InfoLog =
-           talloc_asprintf_append(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");
+        ralloc_strcat(&shader_program->InfoLog,
+                      "warning: Variable sampler array index unsupported.\n"
+                      "This 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);
+        this->name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i);
       } else {
         offset = i;
       }
index 8a3609e569f48f9d6c2cfc82cefe75e355bb2016..fb1c7a4efee6e222fb891311cf6eee8e3e83e541 100644 (file)
@@ -191,7 +191,7 @@ update_blend( struct st_context *st )
 {
    struct pipe_blend_state *blend = &st->state.blend;
    unsigned num_state = 1;
-   unsigned i;
+   unsigned i, j;
 
    memset(blend, 0, sizeof(*blend));
 
@@ -214,12 +214,15 @@ update_blend( struct st_context *st )
    }
    else if (st->ctx->Color.BlendEnabled) {
       /* blending enabled */
-      for (i = 0; i < num_state; i++) {
+      for (i = 0, j = 0; i < num_state; i++) {
 
          blend->rt[i].blend_enable = (st->ctx->Color.BlendEnabled >> i) & 0x1;
 
+         if (st->ctx->Extensions.ARB_draw_buffers_blend)
+            j = i;
+
          blend->rt[i].rgb_func =
-            translate_blend(st->ctx->Color.Blend[i].EquationRGB);
+            translate_blend(st->ctx->Color.Blend[j].EquationRGB);
 
          if (st->ctx->Color.Blend[i].EquationRGB == GL_MIN ||
              st->ctx->Color.Blend[i].EquationRGB == GL_MAX) {
@@ -229,13 +232,13 @@ update_blend( struct st_context *st )
          }
          else {
             blend->rt[i].rgb_src_factor =
-               translate_blend(st->ctx->Color.Blend[i].SrcRGB);
+               translate_blend(st->ctx->Color.Blend[j].SrcRGB);
             blend->rt[i].rgb_dst_factor =
-               translate_blend(st->ctx->Color.Blend[i].DstRGB);
+               translate_blend(st->ctx->Color.Blend[j].DstRGB);
          }
 
          blend->rt[i].alpha_func =
-            translate_blend(st->ctx->Color.Blend[i].EquationA);
+            translate_blend(st->ctx->Color.Blend[j].EquationA);
 
          if (st->ctx->Color.Blend[i].EquationA == GL_MIN ||
              st->ctx->Color.Blend[i].EquationA == GL_MAX) {
@@ -245,9 +248,9 @@ update_blend( struct st_context *st )
          }
          else {
             blend->rt[i].alpha_src_factor =
-               translate_blend(st->ctx->Color.Blend[i].SrcA);
+               translate_blend(st->ctx->Color.Blend[j].SrcA);
             blend->rt[i].alpha_dst_factor =
-               translate_blend(st->ctx->Color.Blend[i].DstA);
+               translate_blend(st->ctx->Color.Blend[j].DstA);
          }
       }
    }
index 2843b7b1764b321878f058bba1f833950d5eae73..76386fe017a9df28cf4cca42f9c8ccc8d58e9404 100644 (file)
@@ -39,7 +39,7 @@
 #include "cso_cache/cso_context.h"
 #include "util/u_math.h"
 #include "util/u_inlines.h"
-
+#include "util/u_format.h"
 
 
 /**
@@ -55,8 +55,10 @@ update_renderbuffer_surface(struct st_context *st,
    struct pipe_resource *resource = strb->rtt->pt;
    int rtt_width = strb->Base.Width;
    int rtt_height = strb->Base.Height;
+   enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format : util_format_linear(resource->format);
 
    if (!strb->surface ||
+       strb->surface->format != format ||
        strb->surface->texture != resource ||
        strb->surface->width != rtt_width ||
        strb->surface->height != rtt_height) {
@@ -67,7 +69,7 @@ update_renderbuffer_surface(struct st_context *st,
              u_minify(resource->height0, level) == rtt_height) {
             struct pipe_surface surf_tmpl;
             memset(&surf_tmpl, 0, sizeof(surf_tmpl));
-            surf_tmpl.format = resource->format;
+            surf_tmpl.format = format;
             surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
             surf_tmpl.u.tex.level = level;
             surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
index 378b30e57ccf406fd9f2f1037302063c8a332053..739a2eaab7e0fde72701c344e626e65cbd3ff563 100644 (file)
@@ -99,7 +99,7 @@ create_color_map_texture(struct gl_context *ctx)
 
    /* create texture for color map/table */
    pt = st_texture_create(st, PIPE_TEXTURE_2D, format, 0,
-                          texSize, texSize, 1, PIPE_BIND_SAMPLER_VIEW);
+                          texSize, texSize, 1, 1, PIPE_BIND_SAMPLER_VIEW);
    return pt;
 }
 
index f92ca13d5e4df085750d5e702bdeb0de21d52a97..8bccceeec53cb3076356b5d4e6953036803c6acf 100644 (file)
@@ -70,14 +70,16 @@ static void update_raster_state( struct st_context *st )
    {
       raster->front_ccw = (ctx->Polygon.FrontFace == GL_CCW);
 
-      /* XXX
-       * I think the intention here is that user-created framebuffer objects
-       * use Y=0=TOP layout instead of OpenGL's normal Y=0=bottom layout.
-       * Flipping Y changes CW to CCW and vice-versa.
-       * But this is an implementation/driver-specific artifact - remove...
+      /*
+       * Gallium's surfaces are Y=0=TOP orientation.  OpenGL is the
+       * opposite.  Window system surfaces are Y=0=TOP.  Mesa's FBOs
+       * must match OpenGL conventions so FBOs use Y=0=BOTTOM.  In that
+       * case, we must invert Y and flip the notion of front vs. back.
        */
-      if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0)
+      if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) {
+         /* Drawing to an FBO.  The viewport will be inverted. */
          raster->front_ccw ^= 1;
+      }
    }
 
    /* _NEW_LIGHT
index b67068df373d7a358c701a08b7714efceda81404..474cbd5897d1861c8f4584d3cf7be7d0d8f52bac 100644 (file)
@@ -36,6 +36,7 @@
 
 #include "st_context.h"
 #include "st_cb_texture.h"
+#include "st_format.h"
 #include "st_atom.h"
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
@@ -117,49 +118,6 @@ gl_filter_to_img_filter(GLenum filter)
 }
 
 
-static void
-xlate_border_color(const GLfloat *colorIn, GLenum baseFormat, GLfloat *colorOut)
-{
-   switch (baseFormat) {
-   case GL_RED:
-      colorOut[0] = colorIn[0];
-      colorOut[1] = 0.0F;
-      colorOut[2] = 0.0F;
-      colorOut[3] = 1.0F;
-      break;
-   case GL_RG:
-      colorOut[0] = colorIn[0];
-      colorOut[1] = colorIn[1];
-      colorOut[2] = 0.0F;
-      colorOut[3] = 1.0F;
-      break;
-   case GL_RGB:
-      colorOut[0] = colorIn[0];
-      colorOut[1] = colorIn[1];
-      colorOut[2] = colorIn[2];
-      colorOut[3] = 1.0F;
-      break;
-   case GL_ALPHA:
-      colorOut[0] = colorOut[1] = colorOut[2] = 0.0;
-      colorOut[3] = colorIn[3];
-      break;
-   case GL_LUMINANCE:
-      colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0];
-      colorOut[3] = 1.0;
-      break;
-   case GL_LUMINANCE_ALPHA:
-      colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0];
-      colorOut[3] = colorIn[3];
-      break;
-   case GL_INTENSITY:
-      colorOut[0] = colorOut[1] = colorOut[2] = colorOut[3] = colorIn[0];
-      break;
-   default:
-      COPY_4V(colorOut, colorIn);
-   }
-}
-
-
 static void 
 update_samplers(struct st_context *st)
 {
@@ -223,7 +181,7 @@ update_samplers(struct st_context *st)
             assert(sampler->min_lod <= sampler->max_lod);
          }
 
-         xlate_border_color(texobj->BorderColor.f,
+         st_translate_color(texobj->BorderColor.f,
                             teximg ? teximg->_BaseFormat : GL_RGBA,
                             sampler->border_color);
 
index d10f1840df6ac3db0210a04d7fc07a2ee8f3c627..133cc49eaf05798b34d7d15dee18e595c261dd87 100644 (file)
@@ -47,10 +47,14 @@ update_viewport( struct st_context *st )
    /* _NEW_BUFFERS
     */
    if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+      /* Drawing to a window.  The corresponding gallium surface uses
+       * Y=0=TOP but OpenGL is Y=0=BOTTOM.  So we need to invert the viewport.
+       */
       yScale = -1;
       yBias = (GLfloat)ctx->DrawBuffer->Height;
    }
    else {
+      /* Drawing to an FBO where Y=0=BOTTOM, like OpenGL - don't invert */
       yScale = 1.0;
       yBias = 0.0;
    }
index 35921f4f614dfd9156a4b1e53c525c34e96bd664..3e01c440bdad0f8a700b6ab90c115dfa28f64216 100644 (file)
@@ -42,6 +42,7 @@
 #include "st_texture.h"
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
+#include "util/u_format.h"
 #include "util/u_inlines.h"
 #include "util/u_tile.h"
 
@@ -146,7 +147,9 @@ accum_accum(struct st_context *st, GLfloat value,
 
    buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
 
-   pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf);
+   pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height,
+                             util_format_linear(color_strb->texture->format),
+                             buf);
 
    switch (acc_strb->format) {
    case PIPE_FORMAT_R16G16B16A16_SNORM:
@@ -183,7 +186,6 @@ accum_load(struct st_context *st, GLfloat value,
    GLubyte *data = acc_strb->data;
    GLfloat *buf;
 
-
    if (ST_DEBUG & DEBUG_FALLBACK)
       debug_printf("%s: fallback processing\n", __FUNCTION__);
 
@@ -194,7 +196,9 @@ accum_load(struct st_context *st, GLfloat value,
 
    buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
 
-   pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf);
+   pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height,
+                             util_format_linear(color_strb->texture->format),
+                             buf);
 
    switch (acc_strb->format) {
    case PIPE_FORMAT_R16G16B16A16_SNORM:
@@ -232,6 +236,7 @@ accum_return(struct gl_context *ctx, GLfloat value,
    size_t stride = acc_strb->stride;
    const GLubyte *data = acc_strb->data;
    GLfloat *buf;
+   enum pipe_format format = util_format_linear(color_strb->texture->format);
 
    if (ST_DEBUG & DEBUG_FALLBACK)
       debug_printf("%s: fallback processing\n", __FUNCTION__);
@@ -250,7 +255,8 @@ accum_return(struct gl_context *ctx, GLfloat value,
                                    width, height);
 
    if (usage & PIPE_TRANSFER_READ)
-      pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf);
+      pipe_get_tile_rgba_format(pipe, color_trans, 0, 0, width, height,
+                                format, buf);
 
    switch (acc_strb->format) {
    case PIPE_FORMAT_R16G16B16A16_SNORM:
@@ -279,7 +285,8 @@ accum_return(struct gl_context *ctx, GLfloat value,
       _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
    }
 
-   pipe_put_tile_rgba(pipe, color_trans, 0, 0, width, height, buf);
+   pipe_put_tile_rgba_format(pipe, color_trans, 0, 0, width, height,
+                             format, buf);
 
    free(buf);
    pipe->transfer_destroy(pipe, color_trans);
index e23fe86daebc3a88a07ca9b8a3adbd87a7a31ff9..0ea5671557c5f3de0e133b3f6694f0c8f44500bc 100644 (file)
@@ -276,7 +276,7 @@ make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
     * Create texture to hold bitmap pattern.
     */
    pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format,
-                          0, width, height, 1,
+                          0, width, height, 1, 1,
                           PIPE_BIND_SAMPLER_VIEW);
    if (!pt) {
       _mesa_unmap_pbo_source(ctx, unpack);
@@ -349,6 +349,7 @@ setup_bitmap_vertex_data(struct st_context *st, bool normalized,
    if (!st->bitmap.vbuf) {
       st->bitmap.vbuf = pipe_buffer_create(pipe->screen, 
                                            PIPE_BIND_VERTEX_BUFFER,
+                                           PIPE_USAGE_STREAM,
                                            max_slots *
                                            sizeof(st->bitmap.vertices));
    }
@@ -456,6 +457,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    cso_save_fragment_shader(cso);
    cso_save_vertex_shader(cso);
    cso_save_vertex_elements(cso);
+   cso_save_vertex_buffers(cso);
 
    /* rasterizer state: just scissor */
    st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled;
@@ -517,7 +519,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
                                      sv->texture->target != PIPE_TEXTURE_RECT,
                                      x, y, width, height, z, color);
 
-   util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset,
+   util_draw_vertex_buffer(pipe, st->cso_context, st->bitmap.vbuf, offset,
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
                            3); /* attribs/vert */
@@ -531,6 +533,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    cso_restore_fragment_shader(cso);
    cso_restore_vertex_shader(cso);
    cso_restore_vertex_elements(cso);
+   cso_restore_vertex_buffers(cso);
 }
 
 
@@ -559,7 +562,7 @@ reset_cache(struct st_context *st)
    cache->texture = st_texture_create(st, PIPE_TEXTURE_2D,
                                       st->bitmap.tex_format, 0,
                                       BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
-                                      1,
+                                      1, 1,
                                      PIPE_BIND_SAMPLER_VIEW);
 }
 
index d4d9af4ada385fb15e2c759e42307f4e97293e58..12528f49ff7ea8c13cf0c16cec14eb147ae67af0 100644 (file)
@@ -171,7 +171,7 @@ st_bufferobj_data(struct gl_context *ctx,
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
    struct st_buffer_object *st_obj = st_buffer_object(obj);
-   unsigned buffer_usage;
+   unsigned bind, pipe_usage;
 
    st_obj->Base.Size = size;
    st_obj->Base.Usage = usage;
@@ -179,22 +179,43 @@ st_bufferobj_data(struct gl_context *ctx,
    switch(target) {
    case GL_PIXEL_PACK_BUFFER_ARB:
    case GL_PIXEL_UNPACK_BUFFER_ARB:
-      buffer_usage = PIPE_BIND_RENDER_TARGET;
+      bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
       break;
    case GL_ARRAY_BUFFER_ARB:
-      buffer_usage = PIPE_BIND_VERTEX_BUFFER;
+      bind = PIPE_BIND_VERTEX_BUFFER;
       break;
    case GL_ELEMENT_ARRAY_BUFFER_ARB:
-      buffer_usage = PIPE_BIND_INDEX_BUFFER;
+      bind = PIPE_BIND_INDEX_BUFFER;
       break;
    default:
-      buffer_usage = 0;
+      bind = 0;
+   }
+
+   switch (usage) {
+   case GL_STATIC_DRAW:
+   case GL_STATIC_READ:
+   case GL_STATIC_COPY:
+      pipe_usage = PIPE_USAGE_STATIC;
+      break;
+   case GL_DYNAMIC_DRAW:
+   case GL_DYNAMIC_READ:
+   case GL_DYNAMIC_COPY:
+      pipe_usage = PIPE_USAGE_DYNAMIC;
+      break;
+   case GL_STREAM_DRAW:
+   case GL_STREAM_READ:
+   case GL_STREAM_COPY:
+      pipe_usage = PIPE_USAGE_STREAM;
+      break;
+   default:
+      pipe_usage = PIPE_USAGE_DEFAULT;
    }
 
    pipe_resource_reference( &st_obj->buffer, NULL );
 
    if (size != 0) {
-      st_obj->buffer = pipe_buffer_create(pipe->screen, buffer_usage, size);
+      st_obj->buffer = pipe_buffer_create(pipe->screen, bind,
+                                          pipe_usage, size);
 
       if (!st_obj->buffer) {
          return GL_FALSE;
index 6571bf237fbd6e969643bc0f7c5f91dc5cfad45f..0e0c4326ed711e4676df575c38e1f16c399755d3 100644 (file)
@@ -42,6 +42,7 @@
 #include "st_cb_accum.h"
 #include "st_cb_clear.h"
 #include "st_cb_fbo.h"
+#include "st_format.h"
 #include "st_program.h"
 
 #include "pipe/p_context.h"
@@ -138,6 +139,7 @@ draw_quad(struct st_context *st,
    if (!st->clear.vbuf) {
       st->clear.vbuf = pipe_buffer_create(pipe->screen,
                                           PIPE_BIND_VERTEX_BUFFER,
+                                          PIPE_USAGE_STREAM,
                                           max_slots * sizeof(st->clear.vertices));
    }
 
@@ -172,7 +174,8 @@ draw_quad(struct st_context *st,
                                            st->clear.vertices);
 
    /* draw */
-   util_draw_vertex_buffer(pipe, 
+   util_draw_vertex_buffer(pipe,
+                           st->cso_context,
                            st->clear.vbuf, 
                            st->clear.vbuf_slot * sizeof(st->clear.vertices),
                            PIPE_PRIM_TRIANGLE_FAN,
@@ -202,6 +205,7 @@ clear_with_quad(struct gl_context *ctx,
    const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f;
    const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f;
    const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f;
+   float clearColor[4];
 
    /*
    printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, 
@@ -221,6 +225,7 @@ clear_with_quad(struct gl_context *ctx,
    cso_save_fragment_shader(st->cso_context);
    cso_save_vertex_shader(st->cso_context);
    cso_save_vertex_elements(st->cso_context);
+   cso_save_vertex_buffers(st->cso_context);
 
    /* blend state: RGBA masking */
    {
@@ -295,9 +300,14 @@ clear_with_quad(struct gl_context *ctx,
    cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
    cso_set_vertex_shader_handle(st->cso_context, st->clear.vs);
 
-   /* draw quad matching scissor rect (XXX verify coord round-off) */
-   draw_quad(st, x0, y0, x1, y1,
-             (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor);
+   if (ctx->DrawBuffer->_ColorDrawBuffers[0]) {
+      st_translate_color(ctx->Color.ClearColor,
+                         ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat,
+                         clearColor);
+   }
+
+   /* draw quad matching scissor rect */
+   draw_quad(st, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, clearColor);
 
    /* Restore pipe state */
    cso_restore_blend(st->cso_context);
@@ -309,6 +319,7 @@ clear_with_quad(struct gl_context *ctx,
    cso_restore_fragment_shader(st->cso_context);
    cso_restore_vertex_shader(st->cso_context);
    cso_restore_vertex_elements(st->cso_context);
+   cso_restore_vertex_buffers(st->cso_context);
 }
 
 
@@ -537,12 +548,21 @@ st_Clear(struct gl_context *ctx, GLbitfield mask)
        * required from the visual. Hence fix this up to avoid potential
        * read-modify-write in the driver.
        */
+      float clearColor[4];
+
       if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) &&
           ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
           (depthRb == stencilRb) &&
           (ctx->DrawBuffer->Visual.depthBits == 0 ||
            ctx->DrawBuffer->Visual.stencilBits == 0))
          clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
+
+      if (ctx->DrawBuffer->_ColorDrawBuffers[0]) {
+         st_translate_color(ctx->Color.ClearColor,
+                            ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat,
+                            clearColor);
+      }
+
       st->pipe->clear(st->pipe, clear_buffers, ctx->Color.ClearColor,
                       ctx->Depth.Clear, ctx->Stencil.Clear);
    }
index d128ff98f02d0da7e4b73501478017ffb6c85a67..c0da169624768305b91cccba1591a35739a752cc 100644 (file)
@@ -343,7 +343,7 @@ alloc_texture(struct st_context *st, GLsizei width, GLsizei height,
    struct pipe_resource *pt;
 
    pt = st_texture_create(st, st->internal_target, texFormat, 0,
-                          width, height, 1, PIPE_BIND_SAMPLER_VIEW);
+                          width, height, 1, 1, PIPE_BIND_SAMPLER_VIEW);
 
    return pt;
 }
@@ -522,10 +522,11 @@ draw_quad(struct gl_context *ctx, GLfloat x0, GLfloat y0, GLfloat z,
       /* allocate/load buffer object with vertex data */
       buf = pipe_buffer_create(pipe->screen,
                               PIPE_BIND_VERTEX_BUFFER,
+                              PIPE_USAGE_STATIC,
                                sizeof(verts));
       pipe_buffer_write(st->pipe, buf, 0, sizeof(verts), verts);
 
-      util_draw_vertex_buffer(pipe, buf, 0,
+      util_draw_vertex_buffer(pipe, st->cso_context, buf, 0,
                               PIPE_PRIM_QUADS,
                               4,  /* verts */
                               3); /* attribs/vert */
@@ -570,6 +571,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    cso_save_fragment_shader(cso);
    cso_save_vertex_shader(cso);
    cso_save_vertex_elements(cso);
+   cso_save_vertex_buffers(cso);
    if (write_stencil) {
       cso_save_depth_stencil_alpha(cso);
       cso_save_blend(cso);
@@ -686,6 +688,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    cso_restore_fragment_shader(cso);
    cso_restore_vertex_shader(cso);
    cso_restore_vertex_elements(cso);
+   cso_restore_vertex_buffers(cso);
    if (write_stencil) {
       cso_restore_depth_stencil_alpha(cso);
       cso_restore_blend(cso);
@@ -1139,6 +1142,110 @@ copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
 }
 
 
+/** Do the src/dest regions overlap? */
+static GLboolean
+regions_overlap(GLint srcX, GLint srcY, GLint dstX, GLint dstY,
+                GLsizei width, GLsizei height)
+{
+   if (srcX + width <= dstX ||
+       dstX + width <= srcX ||
+       srcY + height <= dstY ||
+       dstY + height <= srcY)
+      return GL_FALSE;
+   else
+      return GL_TRUE;
+}
+
+
+/**
+ * Try to do a glCopyPixels for simple cases with a blit by calling
+ * pipe->resource_copy_region().
+ *
+ * We can do this when we're copying color pixels (depth/stencil
+ * eventually) with no pixel zoom, no pixel transfer ops, no
+ * per-fragment ops, the src/dest regions don't overlap and the
+ * src/dest pixel formats are the same.
+ */
+static GLboolean
+blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
+                 GLsizei width, GLsizei height,
+                 GLint dstx, GLint dsty, GLenum type)
+{
+   struct st_context *st = st_context(ctx);
+   struct pipe_context *pipe = st->pipe;
+   struct gl_pixelstore_attrib pack, unpack;
+   GLint readX, readY, readW, readH;
+
+   if (type == GL_COLOR &&
+       ctx->Pixel.ZoomX == 1.0 &&
+       ctx->Pixel.ZoomY == 1.0 &&
+       ctx->_ImageTransferState == 0x0 &&
+       !ctx->Color.BlendEnabled &&
+       !ctx->Color.AlphaEnabled &&
+       !ctx->Depth.Test &&
+       !ctx->Fog.Enabled &&
+       !ctx->Stencil.Enabled &&
+       !ctx->FragmentProgram.Enabled &&
+       !ctx->VertexProgram.Enabled &&
+       !ctx->Shader.CurrentFragmentProgram &&
+       st_fb_orientation(ctx->ReadBuffer) == st_fb_orientation(ctx->DrawBuffer) &&
+       ctx->DrawBuffer->_NumColorDrawBuffers == 1) {
+      struct st_renderbuffer *rbRead, *rbDraw;
+      GLint drawX, drawY;
+
+      /*
+       * Clip the read region against the src buffer bounds.
+       * We'll still allocate a temporary buffer/texture for the original
+       * src region size but we'll only read the region which is on-screen.
+       * This may mean that we draw garbage pixels into the dest region, but
+       * that's expected.
+       */
+      readX = srcx;
+      readY = srcy;
+      readW = width;
+      readH = height;
+      pack = ctx->DefaultPacking;
+      if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack))
+         return GL_TRUE; /* all done */
+
+      /* clip against dest buffer bounds and scissor box */
+      drawX = dstx + pack.SkipPixels;
+      drawY = dsty + pack.SkipRows;
+      unpack = pack;
+      if (!_mesa_clip_drawpixels(ctx, &drawX, &drawY, &readW, &readH, &unpack))
+         return GL_TRUE; /* all done */
+
+      readX = readX - pack.SkipPixels + unpack.SkipPixels;
+      readY = readY - pack.SkipRows + unpack.SkipRows;
+
+      rbRead = st_get_color_read_renderbuffer(ctx);
+      rbDraw = st_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]);
+
+      if ((rbRead != rbDraw ||
+           !regions_overlap(readX, readY, drawX, drawY, readW, readH)) &&
+          rbRead->Base.Format == rbDraw->Base.Format) {
+         struct pipe_box srcBox;
+
+         /* flip src/dst position if needed */
+         if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
+            /* both buffers will have the same orientation */
+            readY = ctx->ReadBuffer->Height - readY - readH;
+            drawY = ctx->DrawBuffer->Height - drawY - readH;
+         }
+
+         u_box_2d(readX, readY, readW, readH, &srcBox);
+
+         pipe->resource_copy_region(pipe,
+                                    rbDraw->texture, 0, drawX, drawY, 0,
+                                    rbRead->texture, 0, &srcBox);
+         return GL_TRUE;
+      }
+   }
+
+   return GL_FALSE;
+}
+
+
 static void
 st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
               GLsizei width, GLsizei height,
@@ -1168,6 +1275,17 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
       return;
    }
 
+   if (blit_copy_pixels(ctx, srcx, srcy, width, height, dstx, dsty, type))
+      return;
+
+   /*
+    * The subsequent code implements glCopyPixels by copying the source
+    * pixels into a temporary texture that's then applied to a textured quad.
+    * When we draw the textured quad, all the usual per-fragment operations
+    * are handled.
+    */
+
+
    /*
     * Get vertex/fragment shaders
     */
@@ -1268,7 +1386,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
    if (srcFormat == texFormat) {
       struct pipe_box src_box;
       u_box_2d(readX, readY, readW, readH, &src_box);
-    /* copy source framebuffer surface into mipmap/texture */
+      /* copy source framebuffer surface into mipmap/texture */
       pipe->resource_copy_region(pipe,
                                  pt,                                /* dest tex */
                                  0,
@@ -1281,7 +1399,8 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
    else {
       /* CPU-based fallback/conversion */
       struct pipe_transfer *ptRead =
-         pipe_get_transfer(st->pipe, rbRead->texture, 0, 0,
+         pipe_get_transfer(st->pipe, rbRead->texture,
+                           0, 0, /* level, layer */
                            PIPE_TRANSFER_READ,
                            readX, readY, readW, readH);
       struct pipe_transfer *ptTex;
@@ -1302,15 +1421,19 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
       if (type == GL_COLOR) {
          /* alternate path using get/put_tile() */
          GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
-         pipe_get_tile_rgba(pipe, ptRead, readX, readY, readW, readH, buf);
-         pipe_put_tile_rgba(pipe, ptTex, pack.SkipPixels, pack.SkipRows,
-                            readW, readH, buf);
+         enum pipe_format readFormat, drawFormat;
+         readFormat = util_format_linear(rbRead->texture->format);
+         drawFormat = util_format_linear(pt->format);
+         pipe_get_tile_rgba_format(pipe, ptRead, 0, 0, readW, readH,
+                                   readFormat, buf);
+         pipe_put_tile_rgba_format(pipe, ptTex, pack.SkipPixels, pack.SkipRows,
+                                   readW, readH, drawFormat, buf);
          free(buf);
       }
       else {
          /* GL_DEPTH */
          GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint));
-         pipe_get_tile_z(pipe, ptRead, readX, readY, readW, readH, buf);
+         pipe_get_tile_z(pipe, ptRead, 0, 0, readW, readH, buf);
          pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows,
                          readW, readH, buf);
          free(buf);
index b540a79331bb05b6fac13beeb340a8194ca02e57..86ceb9d78b32abc294efb7203db3c95abfa8cab6 100644 (file)
@@ -139,6 +139,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
 
    /* create the vertex buffer */
    vbuffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER,
+                                PIPE_USAGE_STREAM,
                                 numAttribs * 4 * 4 * sizeof(GLfloat));
 
    /* load vertex buffer */
@@ -230,6 +231,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
    cso_save_viewport(cso);
    cso_save_vertex_shader(cso);
    cso_save_vertex_elements(cso);
+   cso_save_vertex_buffers(cso);
 
    {
       void *vs = lookup_shader(pipe, numAttribs,
@@ -264,7 +266,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
    }
 
 
-   util_draw_vertex_buffer(pipe, vbuffer,
+   util_draw_vertex_buffer(pipe, cso, vbuffer,
                            0,  /* offset */
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
@@ -277,6 +279,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
    cso_restore_viewport(cso);
    cso_restore_vertex_shader(cso);
    cso_restore_vertex_elements(cso);
+   cso_restore_vertex_buffers(cso);
 }
 
 
index 0c7641f86236266dd2904b944d9d22a62f3f8f06..5eda2346c60ca8b71f218e7fc2d86dfd52c72e6c 100644 (file)
@@ -84,6 +84,7 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx,
    strb->Base.Width  = width;
    strb->Base.Height = height;
    strb->Base.Format = st_pipe_format_to_mesa_format(format);
+   strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
    strb->Base.DataType = st_format_datatype(format);
 
    strb->defined = GL_FALSE;  /* undefined contents now */
@@ -234,6 +235,7 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
    strb->Base.ClassID = 0x4242; /* just a unique value */
    strb->Base.NumSamples = samples;
    strb->Base.Format = st_pipe_format_to_mesa_format(format);
+   strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format);
    strb->Base.DataType = st_format_datatype(format);
    strb->format = format;
    strb->software = sw;
@@ -390,7 +392,7 @@ st_render_texture(struct gl_context *ctx,
 
    /* new surface for rendering into the texture */
    memset(&surf_tmpl, 0, sizeof(surf_tmpl));
-   surf_tmpl.format = strb->texture->format;
+   surf_tmpl.format = ctx->Color.sRGBEnabled ? strb->texture->format : util_format_linear(strb->texture->format);
    surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
    surf_tmpl.u.tex.level = strb->rtt_level;
    surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
@@ -448,11 +450,14 @@ st_finish_render_texture(struct gl_context *ctx,
  * Validate a renderbuffer attachment for a particular set of bindings.
  */
 static GLboolean
-st_validate_attachment(struct pipe_screen *screen,
+st_validate_attachment(struct gl_context *ctx,
+                      struct pipe_screen *screen,
                       const struct gl_renderbuffer_attachment *att,
                       unsigned bindings)
 {
    const struct st_texture_object *stObj = st_texture_object(att->Texture);
+   enum pipe_format format;
+   gl_format texFormat;
 
    /* Only validate texture attachments for now, since
     * st_renderbuffer_alloc_storage makes sure that
@@ -464,7 +469,20 @@ st_validate_attachment(struct pipe_screen *screen,
    if (!stObj)
       return GL_FALSE;
 
-   return screen->is_format_supported(screen, stObj->pt->format,
+   format = stObj->pt->format;
+   texFormat =
+      stObj->base.Image[att->CubeMapFace][att->TextureLevel]->TexFormat;
+
+   /* If the encoding is sRGB and sRGB rendering cannot be enabled,
+    * check for linear format support instead.
+    * Later when we create a surface, we change the format to a linear one. */
+   if (!ctx->Const.sRGBCapable &&
+       _mesa_get_format_color_encoding(texFormat) == GL_SRGB) {
+      const gl_format linearFormat = _mesa_get_srgb_format_linear(texFormat);
+      format = st_mesa_format_to_pipe_format(linearFormat);
+   }
+
+   return screen->is_format_supported(screen, format,
                                       PIPE_TEXTURE_2D,
                                       stObj->pt->nr_samples, bindings, 0);
 }
@@ -528,20 +546,23 @@ st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
       return;
    }
 
-   if (!st_validate_attachment(screen,
+   if (!st_validate_attachment(ctx,
+                               screen,
                                depth,
                               PIPE_BIND_DEPTH_STENCIL)) {
       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
       return;
    }
-   if (!st_validate_attachment(screen,
+   if (!st_validate_attachment(ctx,
+                               screen,
                                stencil,
                               PIPE_BIND_DEPTH_STENCIL)) {
       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
       return;
    }
    for (i = 0; i < ctx->Const.MaxColorAttachments; i++) {
-      if (!st_validate_attachment(screen,
+      if (!st_validate_attachment(ctx,
+                                  screen,
                                  &fb->Attachment[BUFFER_COLOR0 + i],
                                  PIPE_BIND_RENDER_TARGET)) {
         fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
index 0507be745783be12d689ce7c19eabe5d01876a63..4689a0032b72145cca033f7ad67835f6a2d30497 100644 (file)
@@ -41,6 +41,7 @@
 
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
+#include "util/u_format.h"
 #include "util/u_inlines.h"
 #include "util/u_tile.h"
 
@@ -336,6 +337,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h
    struct st_renderbuffer *strb;
    struct gl_pixelstore_attrib clippedPacking = *pack;
    struct pipe_transfer *trans;
+   enum pipe_format pformat;
 
    assert(ctx->ReadBuffer->Width > 0);
 
@@ -421,6 +423,9 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h
       yStep = 1;
    }
 
+   /* possibly convert sRGB format to linear RGB format */
+   pformat = util_format_linear(trans->resource->format);
+
    if (ST_DEBUG & DEBUG_FALLBACK)
       debug_printf("%s: fallback processing\n", __FUNCTION__);
 
@@ -435,8 +440,8 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h
       const GLint dstStride = _mesa_image_row_stride(&clippedPacking, width,
                                                      format, type);
 
-      if (trans->resource->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED ||
-          trans->resource->format == PIPE_FORMAT_Z24X8_UNORM) {
+      if (pformat == PIPE_FORMAT_Z24_UNORM_S8_USCALED ||
+          pformat == PIPE_FORMAT_Z24X8_UNORM) {
          if (format == GL_DEPTH_COMPONENT) {
             for (i = 0; i < height; i++) {
                GLuint ztemp[MAX_WIDTH];
@@ -467,8 +472,8 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h
             }
          }
       }
-      else if (trans->resource->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM ||
-               trans->resource->format == PIPE_FORMAT_X8Z24_UNORM) {
+      else if (pformat == PIPE_FORMAT_S8_USCALED_Z24_UNORM ||
+               pformat == PIPE_FORMAT_X8Z24_UNORM) {
          if (format == GL_DEPTH_COMPONENT) {
             for (i = 0; i < height; i++) {
                GLuint ztemp[MAX_WIDTH];
@@ -494,7 +499,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h
             }
          }
       }
-      else if (trans->resource->format == PIPE_FORMAT_Z16_UNORM) {
+      else if (pformat == PIPE_FORMAT_Z16_UNORM) {
          for (i = 0; i < height; i++) {
             GLushort ztemp[MAX_WIDTH];
             GLfloat zfloat[MAX_WIDTH];
@@ -509,7 +514,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h
             dst += dstStride;
          }
       }
-      else if (trans->resource->format == PIPE_FORMAT_Z32_UNORM) {
+      else if (pformat == PIPE_FORMAT_Z32_UNORM) {
          for (i = 0; i < height; i++) {
             GLuint ztemp[MAX_WIDTH];
             GLfloat zfloat[MAX_WIDTH];
@@ -528,7 +533,8 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h
          /* RGBA format */
          /* Do a row at a time to flip image data vertically */
          for (i = 0; i < height; i++) {
-            pipe_get_tile_rgba(pipe, trans, 0, y, width, 1, df);
+            pipe_get_tile_rgba_format(pipe, trans, 0, y, width, 1,
+                                      pformat, df);
             y += yStep;
             df += dfStride;
             if (!dfStride) {
index 09a10ba58196d121fb6c48013094043a16b30d82..08c498b149198eb323a32e4475cbef3e820e2948 100644 (file)
@@ -74,19 +74,18 @@ gl_target_to_pipe(GLenum target)
    switch (target) {
    case GL_TEXTURE_1D:
       return PIPE_TEXTURE_1D;
-
    case GL_TEXTURE_2D:
       return PIPE_TEXTURE_2D;
-
    case GL_TEXTURE_RECTANGLE_NV:
       return PIPE_TEXTURE_RECT;
-
    case GL_TEXTURE_3D:
       return PIPE_TEXTURE_3D;
-
    case GL_TEXTURE_CUBE_MAP_ARB:
       return PIPE_TEXTURE_CUBE;
-
+   case GL_TEXTURE_1D_ARRAY_EXT:
+      return PIPE_TEXTURE_1D_ARRAY;
+   case GL_TEXTURE_2D_ARRAY_EXT:
+      return PIPE_TEXTURE_2D_ARRAY;
    default:
       assert(0);
       return 0;
@@ -260,6 +259,55 @@ get_texture_dims(GLenum target)
 }
 
 
+/**
+ * Given the size of a mipmap image, try to compute the size of the level=0
+ * mipmap image.
+ *
+ * Note that this isn't always accurate for odd-sized, non-POW textures.
+ * For example, if level=1 and width=40 then the level=0 width may be 80 or 81.
+ *
+ * \return GL_TRUE for success, GL_FALSE for failure
+ */
+static GLboolean
+guess_base_level_size(GLenum target,
+                      GLuint width, GLuint height, GLuint depth, GLuint level,
+                      GLuint *width0, GLuint *height0, GLuint *depth0)
+{ 
+   const GLuint dims = get_texture_dims(target);
+
+   assert(width >= 1);
+   assert(height >= 1);
+   assert(depth >= 1);
+
+   if (level > 0) {
+      /* Depending on the image's size, we can't always make a guess here */
+      if ((dims >= 1 && width == 1) ||
+          (dims >= 2 && height == 1) ||
+          (dims >= 3 && depth == 1)) {
+         /* we can't determine the image size at level=0 */
+         return GL_FALSE;
+      }
+
+      /* grow the image size until we hit level = 0 */
+      while (level > 0) {
+         if (width > 1)
+            width <<= 1;
+         if (height > 1)
+            height <<= 1;
+         if (depth > 1)
+            depth <<= 1;
+         level--;
+      }
+   }      
+
+   *width0 = width;
+   *height0 = height;
+   *depth0 = depth;
+
+   return GL_TRUE;
+}
+
+
 /**
  * Try to allocate a pipe_resource object for the given st_texture_object.
  *
@@ -273,50 +321,27 @@ guess_and_alloc_texture(struct st_context *st,
                        struct st_texture_object *stObj,
                        const struct st_texture_image *stImage)
 {
-   const GLuint dims = get_texture_dims(stObj->base.Target);
-   GLuint level, lastLevel, width, height, depth;
+   GLuint lastLevel, width, height, depth;
    GLuint bindings;
+   GLuint ptWidth, ptHeight, ptDepth, ptLayers;
    enum pipe_format fmt;
 
    DBG("%s\n", __FUNCTION__);
 
    assert(!stObj->pt);
 
-   level = stImage->level;
-   width = stImage->base.Width2;  /* size w/out border */
-   height = stImage->base.Height2;
-   depth = stImage->base.Depth2;
-
-   assert(width > 0);
-   assert(height > 0);
-   assert(depth > 0);
-
-   /* Depending on the image's size, we can't always make a guess here.
-    */
-   if (level > 0) {
-      if ( (dims >= 1 && width == 1) ||
-           (dims >= 2 && height == 1) ||
-           (dims >= 3 && depth == 1) ) {
-         /* we can't determine the image size at level=0 */
-         stObj->width0 = stObj->height0 = stObj->depth0 = 0;
-         /* this is not an out of memory error */
-         return GL_TRUE;
-      }
+   if (!guess_base_level_size(stObj->base.Target,
+                              stImage->base.Width2,
+                              stImage->base.Height2,
+                              stImage->base.Depth2,
+                              stImage->level,
+                              &width, &height, &depth)) {
+      /* we can't determine the image size at level=0 */
+      stObj->width0 = stObj->height0 = stObj->depth0 = 0;
+      /* this is not an out of memory error */
+      return GL_TRUE;
    }
 
-   /* grow the image size until we hit level = 0 */
-   while (level > 0) {
-      if (width != 1)
-         width <<= 1;
-      if (height != 1)
-         height <<= 1;
-      if (depth != 1)
-         depth <<= 1;
-      level--;
-   }      
-
-   assert(level == 0);
-
    /* At this point, (width x height x depth) is the expected size of
     * the level=0 mipmap image.
     */
@@ -353,13 +378,18 @@ guess_and_alloc_texture(struct st_context *st,
 
    bindings = default_bindings(st, fmt);
 
+   st_gl_texture_dims_to_pipe_dims(stObj->base.Target,
+                                   width, height, depth,
+                                   &ptWidth, &ptHeight, &ptDepth, &ptLayers);
+
    stObj->pt = st_texture_create(st,
                                  gl_target_to_pipe(stObj->base.Target),
                                  fmt,
                                  lastLevel,
-                                 width,
-                                 height,
-                                 depth,
+                                 ptWidth,
+                                 ptHeight,
+                                 ptDepth,
+                                 ptLayers,
                                  bindings);
 
    DBG("%s returning %d\n", __FUNCTION__, (stObj->pt != NULL));
@@ -406,125 +436,6 @@ strip_texture_border(GLint border,
 }
 
 
-/**
- * Try to do texture compression via rendering.  If the Gallium driver
- * can render into a compressed surface this will allow us to do texture
- * compression.
- * \return GL_TRUE for success, GL_FALSE for failure
- */
-static GLboolean
-compress_with_blit(struct gl_context * ctx,
-                   GLenum target, GLint level,
-                   GLint xoffset, GLint yoffset, GLint zoffset,
-                   GLint width, GLint height, GLint depth,
-                   GLenum format, GLenum type, const void *pixels,
-                   const struct gl_pixelstore_attrib *unpack,
-                   struct gl_texture_image *texImage)
-{
-   const GLuint dstImageOffsets[1] = {0};
-   struct st_texture_image *stImage = st_texture_image(texImage);
-   struct st_context *st = st_context(ctx);
-   struct pipe_context *pipe = st->pipe;
-   struct pipe_screen *screen = pipe->screen;
-   gl_format mesa_format;
-   struct pipe_resource templ;
-   struct pipe_resource *src_tex;
-   struct pipe_sampler_view view_templ;
-   struct pipe_sampler_view *src_view;
-   struct pipe_surface *dst_surface, surf_tmpl;
-   struct pipe_transfer *tex_xfer;
-   void *map;
-
-   if (!stImage->pt) {
-      /* XXX: Can this happen? Should we assert? */
-      return GL_FALSE;
-   }
-
-   /* get destination surface (in the compressed texture) */
-   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
-   surf_tmpl.format = stImage->pt->format;
-   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
-   surf_tmpl.u.tex.level = stImage->level;
-   surf_tmpl.u.tex.first_layer = stImage->face;
-   surf_tmpl.u.tex.last_layer = stImage->face;
-   dst_surface = pipe->create_surface(pipe, stImage->pt, &surf_tmpl);
-   if (!dst_surface) {
-      /* can't render into this format (or other problem) */
-      return GL_FALSE;
-   }
-
-   /* Choose format for the temporary RGBA texture image.
-    */
-   mesa_format = st_ChooseTextureFormat(ctx, GL_RGBA, format, type);
-   assert(mesa_format);
-   if (!mesa_format)
-      return GL_FALSE;
-
-   /* Create the temporary source texture
-    */
-   memset(&templ, 0, sizeof(templ));
-   templ.target = st->internal_target;
-   templ.format = st_mesa_format_to_pipe_format(mesa_format);
-   templ.width0 = width;
-   templ.height0 = height;
-   templ.depth0 = 1;
-   templ.array_size = 1;
-   templ.last_level = 0;
-   templ.usage = PIPE_USAGE_DEFAULT;
-   templ.bind = PIPE_BIND_SAMPLER_VIEW;
-   src_tex = screen->resource_create(screen, &templ);
-
-   if (!src_tex)
-      return GL_FALSE;
-
-   /* Put user's tex data into the temporary texture
-    */
-   tex_xfer = pipe_get_transfer(st_context(ctx)->pipe, src_tex,
-                                0, 0, /* layer, level are zero */
-                                PIPE_TRANSFER_WRITE,
-                                0, 0, width, height); /* x, y, w, h */
-   map = pipe_transfer_map(pipe, tex_xfer);
-
-   _mesa_texstore(ctx, 2, GL_RGBA, mesa_format,
-                  map,              /* dest ptr */
-                  0, 0, 0,          /* dest x/y/z offset */
-                  tex_xfer->stride, /* dest row stride (bytes) */
-                  dstImageOffsets,  /* image offsets (for 3D only) */
-                  width, height, 1, /* size */
-                  format, type,     /* source format/type */
-                  pixels,           /* source data */
-                  unpack);          /* source data packing */
-
-   pipe_transfer_unmap(pipe, tex_xfer);
-   pipe->transfer_destroy(pipe, tex_xfer);
-
-   /* Create temporary sampler view */
-   u_sampler_view_default_template(&view_templ,
-                                   src_tex,
-                                   src_tex->format);
-   src_view = pipe->create_sampler_view(pipe, src_tex, &view_templ);
-
-
-   /* copy / compress image */
-   util_blit_pixels_tex(st->blit,
-                        src_view,         /* sampler view (src) */
-                        0, 0,             /* src x0, y0 */
-                        width, height,    /* src x1, y1 */
-                        dst_surface,      /* pipe_surface (dst) */
-                        xoffset, yoffset, /* dst x0, y0 */
-                        xoffset + width,  /* dst x1 */
-                        yoffset + height, /* dst y1 */
-                        0.0,              /* z */
-                        PIPE_TEX_MIPFILTER_NEAREST);
-
-   pipe_surface_reference(&dst_surface, NULL);
-   pipe_resource_reference(&src_tex, NULL);
-   pipe_sampler_view_reference(&src_view, NULL);
-
-   return GL_TRUE;
-}
-
-
 /**
  * Do glTexImage1/2/3D().
  */
@@ -542,7 +453,6 @@ st_TexImage(struct gl_context * ctx,
             GLsizei imageSize, GLboolean compressed_src)
 {
    struct st_context *st = st_context(ctx);
-   struct pipe_screen *screen = st->pipe->screen;
    struct st_texture_object *stObj = st_texture_object(texObj);
    struct st_texture_image *stImage = st_texture_image(texImage);
    GLuint dstRowStride = 0;
@@ -669,22 +579,10 @@ st_TexImage(struct gl_context * ctx,
                                           pixels, unpack, "glTexImage");
    }
 
-   /* See if we can do texture compression with a blit/render.
-    */
-   if (!compressed_src &&
-       !ctx->Mesa_DXTn &&
-       _mesa_is_format_compressed(texImage->TexFormat) &&
-       screen->is_format_supported(screen,
-                                   stImage->pt->format,
-                                   stImage->pt->target, 0,
-                                   PIPE_BIND_RENDER_TARGET, 0)) {
-      if (!pixels)
-         goto done;
-
-      if (compress_with_blit(ctx, target, level, 0, 0, 0, width, height, depth,
-                             format, type, pixels, unpack, texImage)) {
-         goto done;
-      }
+   /* for a 1D array upload the image as a series of layer with height = 1 */
+   if (target == GL_TEXTURE_1D_ARRAY) {
+      depth = height;
+      height = 1;
    }
 
    /*
@@ -918,6 +816,7 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level,
    else {
       /* format translation via floats */
       GLuint row;
+      enum pipe_format format = util_format_linear(dst_texture->format);
       for (row = 0; row < height; row++) {
          const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */
          GLfloat rgba[4 * MAX_WIDTH];
@@ -928,7 +827,8 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level,
             debug_printf("%s: fallback format translation\n", __FUNCTION__);
 
          /* get float[4] rgba row from surface */
-         pipe_get_tile_rgba(pipe, tex_xfer, 0, row, width, 1, rgba);
+         pipe_get_tile_rgba_format(pipe, tex_xfer, 0, row, width, 1,
+                                   format, rgba);
 
          _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
                                     type, dest, &ctx->Pack, transferOps);
@@ -1073,7 +973,6 @@ st_TexSubimage(struct gl_context *ctx, GLint dims, GLenum target, GLint level,
                struct gl_texture_image *texImage)
 {
    struct st_context *st = st_context(ctx);
-   struct pipe_screen *screen = st->pipe->screen;
    struct st_texture_image *stImage = st_texture_image(texImage);
    GLuint dstRowStride;
    const GLuint srcImageStride =
@@ -1093,20 +992,10 @@ st_TexSubimage(struct gl_context *ctx, GLint dims, GLenum target, GLint level,
    if (!pixels)
       return;
 
-   /* See if we can do texture compression with a blit/render.
-    */
-   if (!ctx->Mesa_DXTn &&
-       _mesa_is_format_compressed(texImage->TexFormat) &&
-       screen->is_format_supported(screen,
-                                   stImage->pt->format,
-                                   stImage->pt->target, 0,
-                                   PIPE_BIND_RENDER_TARGET, 0)) {
-      if (compress_with_blit(ctx, target, level,
-                             xoffset, yoffset, zoffset,
-                             width, height, depth,
-                             format, type, pixels, packing, texImage)) {
-         goto done;
-      }
+   /* for a 1D array upload the image as a series of layer with height = 1 */
+   if (target == GL_TEXTURE_1D_ARRAY) {
+      depth = height;
+      height = 1;
    }
 
    /* Map buffer if necessary.  Need to lock to prevent other contexts
@@ -1387,7 +1276,9 @@ fallback_copy_texsubimage(struct gl_context *ctx, GLenum target, GLint level,
          /* XXX this usually involves a lot of int/float conversion.
           * try to avoid that someday.
           */
-         pipe_get_tile_rgba(pipe, src_trans, 0, 0, width, height, tempSrc);
+         pipe_get_tile_rgba_format(pipe, src_trans, 0, 0, width, height,
+                                   util_format_linear(strb->texture->format),
+                                   tempSrc);
 
          /* Store into texture memory.
           * Note that this does some special things such as pixel transfer
@@ -1834,6 +1725,7 @@ st_finalize_texture(struct gl_context *ctx,
    GLuint face;
    struct st_texture_image *firstImage;
    enum pipe_format firstImageFormat;
+   GLuint ptWidth, ptHeight, ptDepth, ptLayers;
 
    if (stObj->base._Complete) {
       /* The texture is complete and we know exactly how many mipmap levels
@@ -1867,6 +1759,24 @@ st_finalize_texture(struct gl_context *ctx,
    /* Find gallium format for the Mesa texture */
    firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat);
 
+   /* Find size of level=0 Gallium mipmap image, plus number of texture layers */
+   {
+      GLuint width, height, depth;
+      if (!guess_base_level_size(stObj->base.Target,
+                                 firstImage->base.Width2,
+                                 firstImage->base.Height2,
+                                 firstImage->base.Depth2,
+                                 stObj->base.BaseLevel,
+                                 &width, &height, &depth)) {
+         width = stObj->width0;
+         height = stObj->height0;
+         depth = stObj->depth0;
+      }
+      /* convert GL dims to Gallium dims */
+      st_gl_texture_dims_to_pipe_dims(stObj->base.Target, width, height, depth,
+                                      &ptWidth, &ptHeight, &ptDepth, &ptLayers);
+   }
+
    /* If we already have a gallium texture, check that it matches the texture
     * object's format, target, size, num_levels, etc.
     */
@@ -1874,9 +1784,10 @@ st_finalize_texture(struct gl_context *ctx,
       if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||
           !st_sampler_compat_formats(stObj->pt->format, firstImageFormat) ||
           stObj->pt->last_level < stObj->lastLevel ||
-          stObj->pt->width0 != stObj->width0 ||
-          stObj->pt->height0 != stObj->height0 ||
-          stObj->pt->depth0 != stObj->depth0)
+          stObj->pt->width0 != ptWidth ||
+          stObj->pt->height0 != ptHeight ||
+          stObj->pt->depth0 != ptDepth ||
+          stObj->pt->array_size != ptLayers)
       {
          /* The gallium texture does not match the Mesa texture so delete the
           * gallium texture now.  We'll make a new one below.
@@ -1896,9 +1807,10 @@ st_finalize_texture(struct gl_context *ctx,
                                     gl_target_to_pipe(stObj->base.Target),
                                     firstImageFormat,
                                     stObj->lastLevel,
-                                    stObj->width0,
-                                    stObj->height0,
-                                    stObj->depth0,
+                                    ptWidth,
+                                    ptHeight,
+                                    ptDepth,
+                                    ptLayers,
                                     bindings);
 
       if (!stObj->pt) {
index c7f3949bf9e64b827e5b8a08f918d150a479f759..7a19f35bbf5418a24cbbf406c2a1fdb8e540c718 100644 (file)
@@ -178,7 +178,7 @@ struct st_context *st_create_context(gl_api api, struct pipe_context *pipe,
    memset(&funcs, 0, sizeof(funcs));
    st_init_driver_functions(&funcs);
 
-   ctx = _mesa_create_context_for_api(api, visual, shareCtx, &funcs, NULL);
+   ctx = _mesa_create_context(api, visual, shareCtx, &funcs, NULL);
 
    /* XXX: need a capability bit in gallium to query if the pipe
     * driver prefers DP4 or MUL/MAD for vertex transformation.
@@ -203,6 +203,11 @@ static void st_destroy_context_priv( struct st_context *st )
    st_destroy_drawpix(st);
    st_destroy_drawtex(st);
 
+   /* Unreference any user vertex buffers. */
+   for (i = 0; i < st->num_user_vbs; i++) {
+      pipe_resource_reference(&st->user_vb[i], NULL);
+   }
+
    for (i = 0; i < Elements(st->state.sampler_views); i++) {
       pipe_sampler_view_reference(&st->state.sampler_views[i], NULL);
    }
index 64a8f790e22bc20e481fa9db984c4869f1c41812..77765f0237967d08621165baa5ce7440bda96b04 100644 (file)
@@ -185,6 +185,11 @@ struct st_context
 
    int force_msaa;
    void *winsys_drawable_handle;
+
+   /* User vertex buffers. */
+   struct pipe_resource *user_vb[PIPE_MAX_ATTRIBS];
+   unsigned user_vb_stride[PIPE_MAX_ATTRIBS];
+   unsigned num_user_vbs;
 };
 
 
index 8e1263fe84eace4068fba31fd5a3138724070a81..6530a06ade43b7ecde4386e047a64baa57f14af3 100644 (file)
@@ -243,14 +243,13 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
 static GLboolean
 is_interleaved_arrays(const struct st_vertex_program *vp,
                       const struct st_vp_variant *vpv,
-                      const struct gl_client_array **arrays,
-                      GLboolean *userSpace)
+                      const struct gl_client_array **arrays)
 {
    GLuint attr;
    const struct gl_buffer_object *firstBufObj = NULL;
    GLint firstStride = -1;
-   GLuint num_client_arrays = 0;
    const GLubyte *client_addr = NULL;
+   GLboolean user_memory;
 
    for (attr = 0; attr < vpv->num_inputs; attr++) {
       const GLuint mesaAttr = vp->index_to_input[attr];
@@ -259,16 +258,19 @@ is_interleaved_arrays(const struct st_vertex_program *vp,
 
       if (firstStride < 0) {
          firstStride = stride;
+         user_memory = !bufObj || !bufObj->Name;
       }
       else if (firstStride != stride) {
          return GL_FALSE;
       }
-         
+
       if (!bufObj || !bufObj->Name) {
-         num_client_arrays++;
          /* Try to detect if the client-space arrays are
           * "close" to each other.
           */
+         if (!user_memory) {
+            return GL_FALSE;
+         }
          if (!client_addr) {
             client_addr = arrays[mesaAttr]->Ptr;
          }
@@ -278,6 +280,9 @@ is_interleaved_arrays(const struct st_vertex_program *vp,
          }
       }
       else if (!firstBufObj) {
+         if (user_memory) {
+            return GL_FALSE;
+         }
          firstBufObj = bufObj;
       }
       else if (bufObj != firstBufObj) {
@@ -285,56 +290,10 @@ is_interleaved_arrays(const struct st_vertex_program *vp,
       }
    }
 
-   *userSpace = (num_client_arrays == vpv->num_inputs);
-   /* debug_printf("user space: %s (%d arrays, %d inputs)\n",
-      (int)*userSpace ? "Yes" : "No", num_client_arrays, vp->num_inputs); */
-
    return GL_TRUE;
 }
 
 
-/**
- * Compute the memory range occupied by the arrays.
- */
-static void
-get_arrays_bounds(const struct st_vertex_program *vp,
-                  const struct st_vp_variant *vpv,
-                  const struct gl_client_array **arrays,
-                  GLuint max_index,
-                  const GLubyte **low, const GLubyte **high)
-{
-   const GLubyte *low_addr = NULL;
-   const GLubyte *high_addr = NULL;
-   GLuint attr;
-
-   /* debug_printf("get_arrays_bounds: Handling %u attrs\n", vpv->num_inputs); */
-
-   for (attr = 0; attr < vpv->num_inputs; attr++) {
-      const GLuint mesaAttr = vp->index_to_input[attr];
-      const GLint stride = arrays[mesaAttr]->StrideB;
-      const GLubyte *start = arrays[mesaAttr]->Ptr;
-      const unsigned sz = (arrays[mesaAttr]->Size * 
-                           _mesa_sizeof_type(arrays[mesaAttr]->Type));
-      const GLubyte *end = start + (max_index * stride) + sz;
-
-      /* debug_printf("attr %u: stride %d size %u start %p end %p\n",
-         attr, stride, sz, start, end); */
-
-      if (attr == 0) {
-         low_addr = start;
-         high_addr = end;
-      }
-      else {
-         low_addr = MIN2(low_addr, start);
-         high_addr = MAX2(high_addr, end);
-      }
-   }
-
-   *low = low_addr;
-   *high = high_addr;
-}
-
-
 /**
  * Set up for drawing interleaved arrays that all live in one VBO
  * or all live in user space.
@@ -346,15 +305,24 @@ setup_interleaved_attribs(struct gl_context *ctx,
                           const struct st_vertex_program *vp,
                           const struct st_vp_variant *vpv,
                           const struct gl_client_array **arrays,
-                          GLuint max_index,
-                          GLboolean userSpace,
                           struct pipe_vertex_buffer *vbuffer,
-                          struct pipe_vertex_element velements[])
+                          struct pipe_vertex_element velements[],
+                          unsigned max_index)
 {
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
    GLuint attr;
-   const GLubyte *offset0 = NULL;
+   const GLubyte *low_addr = NULL;
+
+   /* Find the lowest address. */
+   if(vpv->num_inputs) {
+      low_addr = arrays[vp->index_to_input[0]]->Ptr;
+
+      for (attr = 1; attr < vpv->num_inputs; attr++) {
+         const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr;
+         low_addr = MIN2(low_addr, start);
+      }
+   }
 
    for (attr = 0; attr < vpv->num_inputs; attr++) {
       const GLuint mesaAttr = vp->index_to_input[attr];
@@ -362,40 +330,28 @@ setup_interleaved_attribs(struct gl_context *ctx,
       struct st_buffer_object *stobj = st_buffer_object(bufobj);
       GLsizei stride = arrays[mesaAttr]->StrideB;
 
-      /*printf("stobj %u = %p\n", attr, (void*)stobj);*/
-
       if (attr == 0) {
-         const GLubyte *low, *high;
-
-         get_arrays_bounds(vp, vpv, arrays, max_index, &low, &high);
-         /* debug_printf("buffer range: %p %p range %d max index %u\n",
-            low, high, high - low, max_index); */
-
-         offset0 = low;
-         if (userSpace) {
+         if (bufobj && bufobj->Name) {
+            vbuffer->buffer = NULL;
+            pipe_resource_reference(&vbuffer->buffer, stobj->buffer);
+            vbuffer->buffer_offset = pointer_to_offset(low_addr);
+         } else {
             vbuffer->buffer =
-               pipe_user_buffer_create(pipe->screen, (void *) low, high - low,
+               pipe_user_buffer_create(pipe->screen, (void*)low_addr,
+                                       stride * (max_index + 1),
                                       PIPE_BIND_VERTEX_BUFFER);
             vbuffer->buffer_offset = 0;
-         }
-         else {
-            vbuffer->buffer = NULL;
-            pipe_resource_reference(&vbuffer->buffer, stobj->buffer);
-            vbuffer->buffer_offset = pointer_to_offset(low);
+
+            /* Track user vertex buffers. */
+            pipe_resource_reference(&st->user_vb[0], vbuffer->buffer);
+            st->user_vb_stride[0] = stride;
+            st->num_user_vbs = 1;
          }
          vbuffer->stride = stride; /* in bytes */
-         vbuffer->max_index = max_index;
       }
 
-      /*
-      if (arrays[mesaAttr]->InstanceDivisor)
-         vbuffer[attr].max_index = arrays[mesaAttr]->_MaxElement;
-      else
-         vbuffer[attr].max_index = max_index;
-      */
-
       velements[attr].src_offset =
-         (unsigned) (arrays[mesaAttr]->Ptr - offset0);
+         (unsigned) (arrays[mesaAttr]->Ptr - low_addr);
       velements[attr].instance_divisor = arrays[mesaAttr]->InstanceDivisor;
       velements[attr].vertex_buffer_index = 0;
       velements[attr].src_format =
@@ -419,10 +375,9 @@ setup_non_interleaved_attribs(struct gl_context *ctx,
                               const struct st_vertex_program *vp,
                               const struct st_vp_variant *vpv,
                               const struct gl_client_array **arrays,
-                              GLuint max_index,
-                              GLboolean *userSpace,
                               struct pipe_vertex_buffer vbuffer[],
-                              struct pipe_vertex_element velements[])
+                              struct pipe_vertex_element velements[],
+                              unsigned max_index)
 {
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
@@ -433,8 +388,6 @@ setup_non_interleaved_attribs(struct gl_context *ctx,
       struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
       GLsizei stride = arrays[mesaAttr]->StrideB;
 
-      *userSpace = GL_FALSE;
-
       if (bufobj && bufobj->Name) {
          /* Attribute data is in a VBO.
           * Recall that for VBOs, the gl_client_array->Ptr field is
@@ -442,37 +395,23 @@ setup_non_interleaved_attribs(struct gl_context *ctx,
           */
          struct st_buffer_object *stobj = st_buffer_object(bufobj);
          assert(stobj->buffer);
-         /*printf("stobj %u = %p\n", attr, (void*) stobj);*/
 
          vbuffer[attr].buffer = NULL;
          pipe_resource_reference(&vbuffer[attr].buffer, stobj->buffer);
          vbuffer[attr].buffer_offset = pointer_to_offset(arrays[mesaAttr]->Ptr);
       }
       else {
-         /* attribute data is in user-space memory, not a VBO */
-         uint bytes;
-         /*printf("user-space array %d stride %d\n", attr, stride);*/
-       
-         *userSpace = GL_TRUE;
-
          /* wrap user data */
          if (arrays[mesaAttr]->Ptr) {
-            /* user's vertex array */
-            if (arrays[mesaAttr]->StrideB) {
-               bytes = arrays[mesaAttr]->StrideB * (max_index + 1);
-            }
-            else {
-               bytes = arrays[mesaAttr]->Size
-                  * _mesa_sizeof_type(arrays[mesaAttr]->Type);
-            }
             vbuffer[attr].buffer = 
               pipe_user_buffer_create(pipe->screen,
-                                      (void *) arrays[mesaAttr]->Ptr, bytes,
+                                      (void *) arrays[mesaAttr]->Ptr,
+                                      stride * (max_index + 1),
                                       PIPE_BIND_VERTEX_BUFFER);
          }
          else {
             /* no array, use ctx->Current.Attrib[] value */
-            bytes = sizeof(ctx->Current.Attrib[0]);
+            uint bytes = sizeof(ctx->Current.Attrib[0]);
             vbuffer[attr].buffer = 
               pipe_user_buffer_create(pipe->screen,
                                       (void *) ctx->Current.Attrib[mesaAttr],
@@ -482,16 +421,15 @@ setup_non_interleaved_attribs(struct gl_context *ctx,
          }
 
          vbuffer[attr].buffer_offset = 0;
-      }
 
-      assert(velements[attr].src_offset <= 2048); /* 11-bit field */
+         /* Track user vertex buffers. */
+         pipe_resource_reference(&st->user_vb[attr], vbuffer->buffer);
+         st->user_vb_stride[attr] = stride;
+         st->num_user_vbs = MAX2(st->num_user_vbs, attr+1);
+      }
 
       /* common-case setup */
       vbuffer[attr].stride = stride; /* in bytes */
-      if (arrays[mesaAttr]->InstanceDivisor)
-         vbuffer[attr].max_index = arrays[mesaAttr]->_MaxElement;
-      else
-         vbuffer[attr].max_index = max_index;
 
       velements[attr].src_offset = 0;
       velements[attr].instance_divisor = arrays[mesaAttr]->InstanceDivisor;
@@ -609,6 +547,62 @@ translate_prim(const struct gl_context *ctx, unsigned prim)
 }
 
 
+static void
+st_validate_varrays(struct gl_context *ctx,
+                    const struct gl_client_array **arrays,
+                    unsigned max_index)
+{
+   struct st_context *st = st_context(ctx);
+   const struct st_vertex_program *vp;
+   const struct st_vp_variant *vpv;
+   struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
+   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
+   unsigned num_vbuffers, num_velements;
+   GLuint attr;
+   unsigned i;
+
+   /* must get these after state validation! */
+   vp = st->vp;
+   vpv = st->vp_variant;
+
+   memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs);
+
+   /* Unreference any user vertex buffers. */
+   for (i = 0; i < st->num_user_vbs; i++) {
+      pipe_resource_reference(&st->user_vb[i], NULL);
+   }
+   st->num_user_vbs = 0;
+
+   /*
+    * Setup the vbuffer[] and velements[] arrays.
+    */
+   if (is_interleaved_arrays(vp, vpv, arrays)) {
+      setup_interleaved_attribs(ctx, vp, vpv, arrays, vbuffer, velements,
+                                max_index);
+      num_vbuffers = 1;
+      num_velements = vpv->num_inputs;
+      if (num_velements == 0)
+         num_vbuffers = 0;
+   }
+   else {
+      setup_non_interleaved_attribs(ctx, vp, vpv, arrays,
+                                    vbuffer, velements, max_index);
+      num_vbuffers = vpv->num_inputs;
+      num_velements = vpv->num_inputs;
+   }
+
+   cso_set_vertex_buffers(st->cso_context, num_vbuffers, vbuffer);
+   cso_set_vertex_elements(st->cso_context, num_velements, velements);
+
+   /* unreference buffers (frees wrapped user-space buffer objects)
+    * This is OK, because the pipe driver should reference buffers by itself
+    * in set_vertex_buffers. */
+   for (attr = 0; attr < num_vbuffers; attr++) {
+      pipe_resource_reference(&vbuffer[attr].buffer, NULL);
+      assert(!vbuffer[attr].buffer);
+   }
+}
+
 
 /**
  * This function gets plugged into the VBO module and is called when
@@ -627,90 +621,81 @@ st_draw_vbo(struct gl_context *ctx,
 {
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
-   const struct st_vertex_program *vp;
-   const struct st_vp_variant *vpv;
-   struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
-   GLuint attr;
-   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
-   unsigned num_vbuffers, num_velements;
    struct pipe_index_buffer ibuffer;
-   GLboolean userSpace = GL_FALSE;
-   GLboolean vertDataEdgeFlags;
    struct pipe_draw_info info;
    unsigned i;
+   GLboolean new_array = GL_TRUE;
+   /* Fix this (Bug 34378):
+   GLboolean new_array =
+         st->dirty.st && (st->dirty.mesa & (_NEW_ARRAY | _NEW_PROGRAM)) != 0;*/
 
    /* Mesa core state should have been validated already */
    assert(ctx->NewState == 0x0);
 
-   /* Gallium probably doesn't want this in some cases. */
-   if (!index_bounds_valid)
-      if (!vbo_all_varyings_in_vbos(arrays))
-        vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
+   if (ib) {
+      /* Gallium probably doesn't want this in some cases. */
+      if (!index_bounds_valid)
+         if (!vbo_all_varyings_in_vbos(arrays))
+            vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
+   } else {
+      /* Get min/max index for non-indexed drawing. */
+      min_index = ~0;
+      max_index = 0;
+
+      for (i = 0; i < nr_prims; i++) {
+         min_index = MIN2(min_index, prims[i].start);
+         max_index = MAX2(max_index, prims[i].start + prims[i].count - 1);
+      }
+   }
+
+   /* Validate state. */
+   if (st->dirty.st) {
+      GLboolean vertDataEdgeFlags;
 
-   /* sanity check for pointer arithmetic below */
-   assert(sizeof(arrays[0]->Ptr[0]) == 1);
+      /* sanity check for pointer arithmetic below */
+      assert(sizeof(arrays[0]->Ptr[0]) == 1);
 
-   vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj &&
-                       arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name;
-   if (vertDataEdgeFlags != st->vertdata_edgeflags) {
-      st->vertdata_edgeflags = vertDataEdgeFlags;
-      st->dirty.st |= ST_NEW_EDGEFLAGS_DATA;
-   }
+      vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj &&
+                          arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name;
+      if (vertDataEdgeFlags != st->vertdata_edgeflags) {
+         st->vertdata_edgeflags = vertDataEdgeFlags;
+         st->dirty.st |= ST_NEW_EDGEFLAGS_DATA;
+      }
 
-   st_validate_state(st);
+      st_validate_state(st);
 
-   /* must get these after state validation! */
-   vp = st->vp;
-   vpv = st->vp_variant;
+      if (new_array) {
+         st_validate_varrays(ctx, arrays, max_index);
+      }
 
 #if 0
-   if (MESA_VERBOSE & VERBOSE_GLSL) {
-      check_uniforms(ctx);
-   }
+      if (MESA_VERBOSE & VERBOSE_GLSL) {
+         check_uniforms(ctx);
+      }
 #else
-   (void) check_uniforms;
+      (void) check_uniforms;
 #endif
-
-   memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs);
-   /*
-    * Setup the vbuffer[] and velements[] arrays.
-    */
-   if (is_interleaved_arrays(vp, vpv, arrays, &userSpace)) {
-      /*printf("Draw interleaved\n");*/
-      setup_interleaved_attribs(ctx, vp, vpv, arrays, max_index, userSpace,
-                                vbuffer, velements);
-      num_vbuffers = 1;
-      num_velements = vpv->num_inputs;
-      if (num_velements == 0)
-         num_vbuffers = 0;
-   }
-   else {
-      /*printf("Draw non-interleaved\n");*/
-      setup_non_interleaved_attribs(ctx, vp, vpv, arrays, max_index,
-                                    &userSpace, vbuffer, velements);
-      num_vbuffers = vpv->num_inputs;
-      num_velements = vpv->num_inputs;
    }
 
-#if 0
-   {
-      GLuint i;
-      for (i = 0; i < num_vbuffers; i++) {
-         printf("buffers[%d].stride = %u\n", i, vbuffer[i].stride);
-         printf("buffers[%d].max_index = %u\n", i, vbuffer[i].max_index);
-         printf("buffers[%d].buffer_offset = %u\n", i, vbuffer[i].buffer_offset);
-         printf("buffers[%d].buffer = %p\n", i, (void*) vbuffer[i].buffer);
-      }
-      for (i = 0; i < num_velements; i++) {
-         printf("vlements[%d].vbuffer_index = %u\n", i, velements[i].vertex_buffer_index);
-         printf("vlements[%d].src_offset = %u\n", i, velements[i].src_offset);
-         printf("vlements[%d].format = %s\n", i, util_format_name(velements[i].src_format));
+   /* Notify the driver that the content of user buffers may have been
+    * changed. */
+   if (!new_array && st->num_user_vbs) {
+      for (i = 0; i < st->num_user_vbs; i++) {
+         if (st->user_vb[i]) {
+            unsigned stride = st->user_vb_stride[i];
+
+            if (stride) {
+               pipe->redefine_user_buffer(pipe, st->user_vb[i],
+                                          min_index * stride,
+                                          (max_index + 1 - min_index) * stride);
+            } else {
+               /* stride == 0 */
+               pipe->redefine_user_buffer(pipe, st->user_vb[i],
+                                          0, st->user_vb[i]->width0);
+            }
+         }
       }
    }
-#endif
-
-   pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer);
-   cso_set_vertex_elements(st->cso_context, num_velements, velements);
 
    setup_index_buffer(ctx, ib, &ibuffer);
    pipe->set_index_buffer(pipe, &ibuffer);
@@ -744,17 +729,6 @@ st_draw_vbo(struct gl_context *ctx,
    }
 
    pipe_resource_reference(&ibuffer.buffer, NULL);
-
-   /* unreference buffers (frees wrapped user-space buffer objects) */
-   for (attr = 0; attr < num_vbuffers; attr++) {
-      pipe_resource_reference(&vbuffer[attr].buffer, NULL);
-      assert(!vbuffer[attr].buffer);
-   }
-
-   if (userSpace) 
-   {
-      pipe->set_vertex_buffers(pipe, 0, NULL);
-   }
 }
 
 
index 4e76a050701cf837ac51edd684f1099a659a2092..1e1220bfe5279a4339d78ed96610f3780edc67ff 100644 (file)
@@ -179,7 +179,6 @@ st_feedback_draw_vbo(struct gl_context *ctx,
 
       /* common-case setup */
       vbuffers[attr].stride = arrays[mesaAttr]->StrideB; /* in bytes */
-      vbuffers[attr].max_index = max_index;
       velements[attr].instance_divisor = 0;
       velements[attr].vertex_buffer_index = attr;
       velements[attr].src_format = 
@@ -220,7 +219,7 @@ st_feedback_draw_vbo(struct gl_context *ctx,
          break;
       default:
          assert(0);
-        return;
+        goto out_unref_vertex;
       }
 
       if (bufobj && bufobj->Name) {
@@ -256,14 +255,6 @@ st_feedback_draw_vbo(struct gl_context *ctx,
    /*
     * unmap vertex/index buffers
     */
-   for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
-      if (draw->pt.vertex_buffer[i].buffer) {
-         pipe_buffer_unmap(pipe, vb_transfer[i]);
-         pipe_resource_reference(&draw->pt.vertex_buffer[i].buffer, NULL);
-         draw_set_mapped_vertex_buffer(draw, i, NULL);
-      }
-   }
-
    if (ib) {
       draw_set_mapped_index_buffer(draw, NULL);
       draw_set_index_buffer(draw, NULL);
@@ -272,6 +263,14 @@ st_feedback_draw_vbo(struct gl_context *ctx,
          pipe_buffer_unmap(pipe, ib_transfer);
       pipe_resource_reference(&ibuffer.buffer, NULL);
    }
+
+ out_unref_vertex:
+   for (attr = 0; attr < vp->num_inputs; attr++) {
+      pipe_buffer_unmap(pipe, vb_transfer[attr]);
+      draw_set_mapped_vertex_buffer(draw, attr, NULL);
+      pipe_resource_reference(&vbuffers[attr].buffer, NULL);
+   }
+   draw_set_vertex_buffers(draw, 0, NULL);
 }
 
 #endif /* FEATURE_feedback || FEATURE_rastpos */
index 974fd78d7c8cfd185f9ef0b56e4351af707eb549..2f45f470334ee5574fcc3af6c9f5e8b269d3ef72 100644 (file)
@@ -260,6 +260,8 @@ void st_init_extensions(struct st_context *st)
    ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE;
    ctx->Extensions.EXT_texture_lod_bias = GL_TRUE;
    ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE;
+   if (ctx->API == API_OPENGLES || ctx->API == API_OPENGLES2)
+          ctx->Extensions.EXT_texture_format_BGRA8888 = GL_TRUE;
 
    ctx->Extensions.APPLE_vertex_array_object = GL_TRUE;
 
@@ -388,6 +390,15 @@ void st_init_extensions(struct st_context *st)
                                    PIPE_BIND_SAMPLER_VIEW, 0)) {
       ctx->Extensions.EXT_texture_sRGB = GL_TRUE;
       ctx->Extensions.EXT_texture_sRGB_decode = GL_TRUE;
+      if (screen->is_format_supported(screen, PIPE_FORMAT_A8B8G8R8_SRGB,
+                                   PIPE_TEXTURE_2D, 0,
+                                   PIPE_BIND_RENDER_TARGET, 0) ||
+          screen->is_format_supported(screen, PIPE_FORMAT_B8G8R8A8_SRGB,
+                                   PIPE_TEXTURE_2D, 0,
+                                   PIPE_BIND_RENDER_TARGET, 0)) {
+         ctx->Extensions.EXT_framebuffer_sRGB = GL_TRUE;
+         ctx->Const.sRGBCapable = GL_TRUE;
+      }
    }
 
    if (screen->is_format_supported(screen, PIPE_FORMAT_R8G8_UNORM,
@@ -400,10 +411,7 @@ void st_init_extensions(struct st_context *st)
    if (screen->is_format_supported(screen, PIPE_FORMAT_DXT5_RGBA,
                                    PIPE_TEXTURE_2D, 0,
                                    PIPE_BIND_SAMPLER_VIEW, 0) &&
-       (ctx->Mesa_DXTn ||
-        screen->is_format_supported(screen, PIPE_FORMAT_DXT5_RGBA,
-                                    PIPE_TEXTURE_2D, 0,
-                                    PIPE_BIND_RENDER_TARGET, 0))) {
+       ctx->Mesa_DXTn) {
       ctx->Extensions.EXT_texture_compression_s3tc = GL_TRUE;
       ctx->Extensions.S3_s3tc = GL_TRUE;
    }
@@ -418,6 +426,12 @@ void st_init_extensions(struct st_context *st)
       ctx->Extensions.MESA_ycbcr_texture = GL_TRUE;
    }
 
+   /* GL_EXT_texture_array */
+   if (screen->get_param(screen, PIPE_CAP_ARRAY_TEXTURES)) {
+      ctx->Extensions.EXT_texture_array = GL_TRUE;
+      ctx->Extensions.MESA_texture_array = GL_TRUE;
+   }
+
    /* GL_ARB_framebuffer_object */
    if (ctx->Extensions.EXT_packed_depth_stencil) {
       /* we support always support GL_EXT_framebuffer_blit */
index 2e0a664dd01f52d2c8c616535a2ea764d58fd068..577ee6189bdc819e1bf5083f61bdea71a834f1ff 100644 (file)
@@ -113,12 +113,9 @@ st_format_datatype(enum pipe_format format)
       return GL_UNSIGNED_SHORT;
    }
    else {
-      /* compressed format? */
-      assert(0);
+      /* probably a compressed format, unsupported anyway */
+      return GL_NONE;
    }
-
-   assert(0);
-   return GL_NONE;
 }
 
 
@@ -511,6 +508,14 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat,
       return default_rgba_format( screen, target, sample_count, bindings,
                                   geom_flags );
 
+   case GL_BGRA:
+      if (screen->is_format_supported( screen, PIPE_FORMAT_B8G8R8A8_UNORM,
+                                       target, sample_count, bindings,
+                                       geom_flags ))
+         return PIPE_FORMAT_B8G8R8A8_UNORM;
+      return default_rgba_format( screen, target, sample_count, bindings,
+                                  geom_flags );
+
    case 3:
    case GL_RGB:
    case GL_RGB8:
@@ -1032,7 +1037,8 @@ st_ChooseTextureFormat(struct gl_context *ctx, GLint internalFormat,
    boolean want_renderable =
       internalFormat == 3 || internalFormat == 4 ||
       internalFormat == GL_RGB || internalFormat == GL_RGBA ||
-      internalFormat == GL_RGB8 || internalFormat == GL_RGBA8;
+      internalFormat == GL_RGB8 || internalFormat == GL_RGBA8 ||
+      internalFormat == GL_BGRA;
 
    return st_ChooseTextureFormat_renderable(ctx, internalFormat,
                                            format, type, want_renderable);
@@ -1089,3 +1095,55 @@ st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2)
 
    return GL_FALSE;
 }
+
+
+
+/**
+ * This is used for translating texture border color and the clear
+ * color.  For example, the clear color is interpreted according to
+ * the renderbuffer's base format.  For example, if clearing a
+ * GL_LUMINANCE buffer, ClearColor[0] = luminance and ClearColor[1] =
+ * alpha.  Similarly for texture border colors.
+ */
+void
+st_translate_color(const GLfloat colorIn[4], GLenum baseFormat,
+                   GLfloat colorOut[4])
+{
+   switch (baseFormat) {
+   case GL_RED:
+      colorOut[0] = colorIn[0];
+      colorOut[1] = 0.0F;
+      colorOut[2] = 0.0F;
+      colorOut[3] = 1.0F;
+      break;
+   case GL_RG:
+      colorOut[0] = colorIn[0];
+      colorOut[1] = colorIn[1];
+      colorOut[2] = 0.0F;
+      colorOut[3] = 1.0F;
+      break;
+   case GL_RGB:
+      colorOut[0] = colorIn[0];
+      colorOut[1] = colorIn[1];
+      colorOut[2] = colorIn[2];
+      colorOut[3] = 1.0F;
+      break;
+   case GL_ALPHA:
+      colorOut[0] = colorOut[1] = colorOut[2] = 0.0;
+      colorOut[3] = colorIn[3];
+      break;
+   case GL_LUMINANCE:
+      colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0];
+      colorOut[3] = 1.0;
+      break;
+   case GL_LUMINANCE_ALPHA:
+      colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0];
+      colorOut[3] = colorIn[3];
+      break;
+   case GL_INTENSITY:
+      colorOut[0] = colorOut[1] = colorOut[2] = colorOut[3] = colorIn[0];
+      break;
+   default:
+      COPY_4V(colorOut, colorIn);
+   }
+}
index fe195c1069b1d04d688bb8a8e60db3a6f1eeac00..0fb570f6ee495299777c5df4413f6485becb11e6 100644 (file)
@@ -77,4 +77,10 @@ st_equal_formats(enum pipe_format pFormat, GLenum format, GLenum type);
 extern GLboolean
 st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2);
 
+
+extern void
+st_translate_color(const GLfloat colorIn[4], GLenum baseFormat,
+                   GLfloat colorOut[4]);
+
+
 #endif /* ST_FORMAT_H */
index c5f6008a22224870e814db924ff9d9da262d1881..4bf682808390f631b47c75f71da007ce64c75c9d 100644 (file)
@@ -105,13 +105,12 @@ st_render_mipmap(struct st_context *st,
 static void
 decompress_image(enum pipe_format format,
                  const uint8_t *src, uint8_t *dst,
-                 unsigned width, unsigned height)
+                 unsigned width, unsigned height, unsigned src_stride)
 {
    const struct util_format_description *desc = util_format_description(format);
    const uint bw = util_format_get_blockwidth(format);
    const uint bh = util_format_get_blockheight(format);
    const uint dst_stride = 4 * MAX2(width, bw);
-   const uint src_stride = util_format_get_stride(format, width);
 
    desc->unpack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height);
 
@@ -144,10 +143,9 @@ decompress_image(enum pipe_format format,
 static void
 compress_image(enum pipe_format format,
                const uint8_t *src, uint8_t *dst,
-               unsigned width, unsigned height)
+               unsigned width, unsigned height, unsigned dst_stride)
 {
    const struct util_format_description *desc = util_format_description(format);
-   const uint dst_stride = util_format_get_stride(format, width);
    const uint src_stride = 4 * width;
 
    desc->pack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height);
@@ -236,7 +234,7 @@ fallback_generate_mipmap(struct gl_context *ctx, GLenum target,
          dstTemp = malloc(dstWidth2 * dstHeight2 * comps + 000);
 
          /* decompress the src image: srcData -> srcTemp */
-         decompress_image(format, srcData, srcTemp, srcWidth, srcHeight);
+         decompress_image(format, srcData, srcTemp, srcWidth, srcHeight, srcTrans->stride);
 
          _mesa_generate_mipmap_level(target, datatype, comps,
                                      0 /*border*/,
@@ -248,7 +246,7 @@ fallback_generate_mipmap(struct gl_context *ctx, GLenum target,
                                      dstWidth2); /* stride in texels */
 
          /* compress the new image: dstTemp -> dstData */
-         compress_image(format, dstTemp, dstData, dstWidth, dstHeight);
+         compress_image(format, dstTemp, dstData, dstWidth, dstHeight, dstTrans->stride);
 
          free(srcTemp);
          free(dstTemp);
@@ -338,6 +336,11 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target,
    if (lastLevel == 0)
       return;
 
+   /* The texture isn't in a "complete" state yet so set the expected
+    * lastLevel here, since it won't get done in st_finalize_texture().
+    */
+   stObj->lastLevel = lastLevel;
+
    if (pt->last_level < lastLevel) {
       /* The current gallium texture doesn't have space for all the
        * mipmap levels we need to generate.  So allocate a new texture.
@@ -352,13 +355,9 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target,
                                     oldTex->width0,
                                     oldTex->height0,
                                     oldTex->depth0,
+                                    oldTex->array_size,
                                     oldTex->bind);
 
-      /* The texture isn't in a "complete" state yet so set the expected
-       * lastLevel here, since it won't get done in st_finalize_texture().
-       */
-      stObj->lastLevel = lastLevel;
-
       /* This will copy the old texture's base image into the new texture
        * which we just allocated.
        */
@@ -367,8 +366,6 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target,
       /* release the old tex (will likely be freed too) */
       pipe_resource_reference(&oldTex, NULL);
       pipe_sampler_view_reference(&stObj->sampler_view, NULL);
-
-      pt = stObj->pt;
    }
    else {
       /* Make sure that the base texture image data is present in the
@@ -377,6 +374,8 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target,
       st_finalize_texture(ctx, st->pipe, texObj);
    }
 
+   pt = stObj->pt;
+
    assert(pt->last_level >= lastLevel);
 
    /* Try to generate the mipmap by rendering/texturing.  If that fails,
index 179e5dc83926712dd7559e754af787e984cffa89..5c8853cfadb399ef92b14ac4dddda5feccf7acfe 100644 (file)
@@ -426,19 +426,13 @@ st_framebuffer_create(struct st_framebuffer_iface *stfbi)
    struct gl_config mode;
    gl_buffer_index idx;
 
+   if (!stfbi)
+      return NULL;
+
    stfb = CALLOC_STRUCT(st_framebuffer);
    if (!stfb)
       return NULL;
 
-   /* for FBO-only context */
-   if (!stfbi) {
-      struct gl_framebuffer *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);
 
@@ -764,7 +758,8 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
          ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base);
       }
       else {
-         ret = FALSE;
+         struct gl_framebuffer *incomplete = _mesa_get_incomplete_framebuffer();
+         ret = _mesa_make_current(st->ctx, incomplete, incomplete);
       }
 
       st_framebuffer_reference(&stdraw, NULL);
index 42f1c2017f8479a2bdc3ab1b80025d44df9afcd9..5c68fd78c30fe946cb2dd48f14f202406597a2e5 100644 (file)
@@ -286,6 +286,8 @@ translate_texture_target( GLuint textarget,
    case TEXTURE_3D_INDEX:   return TGSI_TEXTURE_3D;
    case TEXTURE_CUBE_INDEX: return TGSI_TEXTURE_CUBE;
    case TEXTURE_RECT_INDEX: return TGSI_TEXTURE_RECT;
+   case TEXTURE_1D_ARRAY_INDEX:   return TGSI_TEXTURE_1D_ARRAY;
+   case TEXTURE_2D_ARRAY_INDEX:   return TGSI_TEXTURE_2D_ARRAY;
    default:
       debug_assert( 0 );
       return TGSI_TEXTURE_1D;
@@ -751,10 +753,12 @@ compile_instruction(
 
 /**
  * Emit the TGSI instructions to adjust the WPOS pixel center convention
+ * Basically, add (adjX, adjY) to the fragment position.
  */
 static void
 emit_adjusted_wpos( struct st_translate *t,
-                    const struct gl_program *program, GLfloat value)
+                    const struct gl_program *program,
+                    GLfloat adjX, GLfloat adjY)
 {
    struct ureg_program *ureg = t->ureg;
    struct ureg_dst wpos_temp = ureg_DECL_temporary(ureg);
@@ -764,7 +768,7 @@ emit_adjusted_wpos( struct st_translate *t,
     * The shader might also use gl_FragCoord.w and .z.
     */
    ureg_ADD(ureg, wpos_temp, wpos_input,
-            ureg_imm4f(ureg, value, value, 0.0f, 0.0f));
+            ureg_imm4f(ureg, adjX, adjY, 0.0f, 0.0f));
 
    t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]] = ureg_src(wpos_temp);
 }
@@ -848,9 +852,12 @@ emit_wpos(struct st_context *st,
    boolean invert = FALSE;
 
    if (fp->OriginUpperLeft) {
+      /* Fragment shader wants origin in upper-left */
       if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT)) {
+         /* the driver supports upper-left origin */
       }
       else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT)) {
+         /* the driver supports lower-left origin, need to invert Y */
          ureg_property_fs_coord_origin(ureg, TGSI_FS_COORD_ORIGIN_LOWER_LEFT);
          invert = TRUE;
       }
@@ -858,28 +865,37 @@ emit_wpos(struct st_context *st,
          assert(0);
    }
    else {
+      /* Fragment shader wants origin in lower-left */
       if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT))
+         /* the driver supports lower-left origin */
          ureg_property_fs_coord_origin(ureg, TGSI_FS_COORD_ORIGIN_LOWER_LEFT);
       else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT))
+         /* the driver supports upper-left origin, need to invert Y */
          invert = TRUE;
       else
          assert(0);
    }
    
    if (fp->PixelCenterInteger) {
+      /* Fragment shader wants pixel center integer */
       if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER))
+         /* the driver supports pixel center integer */
          ureg_property_fs_coord_pixel_center(ureg, TGSI_FS_COORD_PIXEL_CENTER_INTEGER);
       else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER))
-         emit_adjusted_wpos(t, program, invert ? 0.5f : -0.5f);
+         /* the driver supports pixel center half integer, need to bias X,Y */
+         emit_adjusted_wpos(t, program, 0.5f, invert ? 0.5f : -0.5f);
       else
          assert(0);
    }
    else {
+      /* Fragment shader wants pixel center half integer */
       if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER)) {
+         /* the driver supports pixel center half integer */
       }
       else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) {
+         /* the driver supports pixel center integer, need to bias X,Y */
          ureg_property_fs_coord_pixel_center(ureg, TGSI_FS_COORD_PIXEL_CENTER_INTEGER);
-         emit_adjusted_wpos(t, program, invert ? -0.5f : 0.5f);
+         emit_adjusted_wpos(t, program, 0.5f, invert ? -0.5f : 0.5f);
       }
       else
          assert(0);
index 7b32b46838a1ac9beb347a7e17f09c4508d06492..fc1dfb3ef9e618c4952e056d475d44b121a3d6a6 100644 (file)
@@ -108,6 +108,8 @@ delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv)
 {
    if (fpv->driver_shader) 
       cso_delete_fragment_shader(st->cso_context, fpv->driver_shader);
+   if (fpv->parameters)
+      _mesa_free_parameter_list(fpv->parameters);
       
    FREE(fpv);
 }
@@ -404,6 +406,7 @@ st_translate_fragment_program(struct st_context *st,
 {
    struct pipe_context *pipe = st->pipe;
    struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant);
+   GLboolean deleteFP = GL_FALSE;
 
    if (!variant)
       return NULL;
@@ -413,17 +416,18 @@ st_translate_fragment_program(struct st_context *st,
 #if FEATURE_drawpix
    if (key->bitmap) {
       /* glBitmap drawing */
-      struct gl_fragment_program *fp;
+      struct gl_fragment_program *fp; /* we free this temp program below */
 
       st_make_bitmap_fragment_program(st, &stfp->Base,
                                       &fp, &variant->bitmap_sampler);
 
       variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
       stfp = st_fragment_program(fp);
+      deleteFP = GL_TRUE;
    }
    else if (key->drawpixels) {
       /* glDrawPixels drawing */
-      struct gl_fragment_program *fp;
+      struct gl_fragment_program *fp; /* we free this temp program below */
 
       if (key->drawpixels_z || key->drawpixels_stencil) {
          fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z,
@@ -433,6 +437,7 @@ st_translate_fragment_program(struct st_context *st,
          /* RGBA */
          st_make_drawpix_fragment_program(st, &stfp->Base, &fp);
          variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
+         deleteFP = GL_TRUE;
       }
       stfp = st_fragment_program(fp);
    }
@@ -630,6 +635,12 @@ st_translate_fragment_program(struct st_context *st,
       debug_printf("\n");
    }
 
+   if (deleteFP) {
+      /* Free the temporary program made above */
+      struct gl_fragment_program *fp = &stfp->Base;
+      _mesa_reference_fragprog(st->ctx, &fp, NULL);
+   }
+
    return variant;
 }
 
index 155ea39f18c07d9537b0c45355c69329f974b81f..1e0a8323ab830cd5d9c2bc427f6dd2fa3dc6793c 100644 (file)
@@ -59,6 +59,7 @@ st_texture_create(struct st_context *st,
                  GLuint width0,
                  GLuint height0,
                  GLuint depth0,
+                  GLuint layers,
                   GLuint bind )
 {
    struct pipe_resource pt, *newtex;
@@ -68,6 +69,8 @@ st_texture_create(struct st_context *st,
    assert(width0 > 0);
    assert(height0 > 0);
    assert(depth0 > 0);
+   if (target == PIPE_TEXTURE_CUBE)
+      assert(layers == 6);
 
    DBG("%s target %s format %s last_level %d\n", __FUNCTION__,
        _mesa_lookup_enum_by_nr(target),
@@ -84,7 +87,7 @@ st_texture_create(struct st_context *st,
    pt.width0 = width0;
    pt.height0 = height0;
    pt.depth0 = depth0;
-   pt.array_size = (target == PIPE_TEXTURE_CUBE ? 6 : 1);
+   pt.array_size = (target == PIPE_TEXTURE_CUBE ? 6 : layers);
    pt.usage = PIPE_USAGE_DEFAULT;
    pt.bind = bind;
    pt.flags = 0;
@@ -97,6 +100,72 @@ st_texture_create(struct st_context *st,
 }
 
 
+/**
+ * In OpenGL the number of 1D array texture layers is the "height" and
+ * the number of 2D array texture layers is the "depth".  In Gallium the
+ * number of layers in an array texture is a separate 'array_size' field.
+ * This function converts dimensions from the former to the later.
+ */
+void
+st_gl_texture_dims_to_pipe_dims(GLenum texture,
+                                GLuint widthIn,
+                                GLuint heightIn,
+                                GLuint depthIn,
+                                GLuint *widthOut,
+                                GLuint *heightOut,
+                                GLuint *depthOut,
+                                GLuint *layersOut)
+{
+   switch (texture) {
+   case GL_TEXTURE_1D:
+      assert(heightIn == 1);
+      assert(depthIn == 1);
+      *widthOut = widthIn;
+      *heightOut = 1;
+      *depthOut = 1;
+      *layersOut = 1;
+      break;
+   case GL_TEXTURE_1D_ARRAY:
+      assert(depthIn == 1);
+      *widthOut = widthIn;
+      *heightOut = 1;
+      *depthOut = 1;
+      *layersOut = heightIn;
+      break;
+   case GL_TEXTURE_2D:
+   case GL_TEXTURE_RECTANGLE:
+      assert(depthIn == 1);
+      *widthOut = widthIn;
+      *heightOut = heightIn;
+      *depthOut = 1;
+      *layersOut = 1;
+      break;
+   case GL_TEXTURE_CUBE_MAP:
+      assert(depthIn == 1);
+      *widthOut = widthIn;
+      *heightOut = heightIn;
+      *depthOut = 1;
+      *layersOut = 6;
+      break;
+   case GL_TEXTURE_2D_ARRAY:
+      *widthOut = widthIn;
+      *heightOut = heightIn;
+      *depthOut = 1;
+      *layersOut = depthIn;
+      break;
+   default:
+      assert(0 && "Unexpected texture in st_gl_texture_dims_to_pipe_dims()");
+      /* fall-through */
+   case GL_TEXTURE_3D:
+      *widthOut = widthIn;
+      *heightOut = heightIn;
+      *depthOut = depthIn;
+      *layersOut = 1;
+      break;
+   }
+}
+
+
 /**
  * Check if a texture image can be pulled into a unified mipmap texture.
  */
@@ -105,6 +174,8 @@ st_texture_match_image(const struct pipe_resource *pt,
                        const struct gl_texture_image *image,
                        GLuint face, GLuint level)
 {
+   GLuint ptWidth, ptHeight, ptDepth, ptLayers;
+
    /* Images with borders are never pulled into mipmap textures. 
     */
    if (image->Border) 
@@ -115,12 +186,17 @@ st_texture_match_image(const struct pipe_resource *pt,
    if (st_mesa_format_to_pipe_format(image->TexFormat) != pt->format)
       return GL_FALSE;
 
+   st_gl_texture_dims_to_pipe_dims(image->TexObject->Target,
+                                   image->Width, image->Height, image->Depth,
+                                   &ptWidth, &ptHeight, &ptDepth, &ptLayers);
+
    /* Test if this image's size matches what's expected in the
     * established texture.
     */
-   if (image->Width != u_minify(pt->width0, level) ||
-       image->Height != u_minify(pt->height0, level) ||
-       image->Depth != u_minify(pt->depth0, level))
+   if (ptWidth != u_minify(pt->width0, level) ||
+       ptHeight != u_minify(pt->height0, level) ||
+       ptDepth != u_minify(pt->depth0, level) ||
+       ptLayers != pt->array_size)
       return GL_FALSE;
 
    return GL_TRUE;
@@ -212,14 +288,20 @@ st_texture_image_data(struct st_context *st,
                       GLuint src_row_stride, GLuint src_image_stride)
 {
    struct pipe_context *pipe = st->pipe;
-   GLuint depth = u_minify(dst->depth0, level);
    GLuint i;
    const GLubyte *srcUB = src;
    struct pipe_transfer *dst_transfer;
+   GLuint layers;
+
+   if (dst->target == PIPE_TEXTURE_1D_ARRAY ||
+       dst->target == PIPE_TEXTURE_2D_ARRAY)
+      layers = dst->array_size;
+   else
+      layers = u_minify(dst->depth0, level);
 
    DBG("%s\n", __FUNCTION__);
 
-   for (i = 0; i < depth; i++) {
+   for (i = 0; i < layers; i++) {
       dst_transfer = pipe_get_transfer(st->pipe, dst, level, face + i,
                                        PIPE_TRANSFER_WRITE, 0, 0,
                                        u_minify(dst->width0, level),
index bca856d71428a7b243b3c6f02875c35dde393ff1..d50c3c9af79a01b743d0f109b1afa58b548bd5d8 100644 (file)
@@ -71,7 +71,10 @@ struct st_texture_object
     */
    GLuint lastLevel;
 
-   /** The size of the level=0 mipmap image */
+   /** The size of the level=0 mipmap image.
+    * Note that the number of 1D array layers will be in height0 and the
+    * number of 2D array layers will be in depth0, as in GL.
+    */
    GLuint width0, height0, depth0;
 
    /* On validation any active images held in main memory or in other
@@ -168,9 +171,20 @@ st_texture_create(struct st_context *st,
                   GLuint width0,
                   GLuint height0,
                   GLuint depth0,
+                  GLuint layers,
                   GLuint tex_usage );
 
 
+extern void
+st_gl_texture_dims_to_pipe_dims(GLenum texture,
+                                GLuint widthIn,
+                                GLuint heightIn,
+                                GLuint depthIn,
+                                GLuint *widthOut,
+                                GLuint *heightOut,
+                                GLuint *depthOut,
+                                GLuint *layersOut);
+
 /* Check if an image fits into an existing texture object.
  */
 extern GLboolean
diff --git a/src/mesa/swrast/s_trispan.h b/src/mesa/swrast/s_trispan.h
deleted file mode 100644 (file)
index 15207e8..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-
-/*
- * Mesa 3-D graphics library
- * Version:  3.5
- *
- * Copyright (C) 1999-2001  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 S_TRISPAN_H
-#define S_TRISPAN_H
-
-
-#endif /* S_TRISPAN_H */
index 858b8281da3d9f029deb808d0ecc5982898916da..b1967e6541799584e53ad489cd0eb2e33a39975b 100644 (file)
@@ -125,6 +125,43 @@ convert_half_to_float(const struct gl_client_array *input,
    }
 }
 
+/**
+ * \brief Convert fixed-point to floating-point.
+ *
+ * In OpenGL, a fixed-point number is a "signed 2's complement 16.16 scaled
+ * integer" (Table 2.2 of the OpenGL ES 2.0 spec).
+ *
+ * If the buffer has the \c normalized flag set, the formula
+ *     \code normalize(x) := (2*x + 1) / (2^16 - 1) \endcode
+ * is used to map the fixed-point numbers into the range [-1, 1].
+ */
+static void
+convert_fixed_to_float(const struct gl_client_array *input,
+                       const GLubyte *ptr, GLfloat *fptr,
+                       GLuint count)
+{
+   GLuint i, j;
+   const GLint size = input->Size;
+
+   if (input->Normalized) {
+      for (i = 0; i < count; ++i) {
+         const GLfixed *in = (GLfixed *) ptr;
+         for (j = 0; j < size; ++j) {
+            *fptr++ = (GLfloat) (2 * in[j] + 1) / (GLfloat) ((1 << 16) - 1);
+         }
+         ptr += input->StrideB;
+      }
+   } else {
+      for (i = 0; i < count; ++i) {
+         const GLfixed *in = (GLfixed *) ptr;
+         for (j = 0; j < size; ++j) {
+            *fptr++ = in[j] / (GLfloat) (1 << 16);
+         }
+         ptr += input->StrideB;
+      }
+   }
+}
+
 /* Adjust pointer to point at first requested element, convert to
  * floating point, populate VB->AttribPtr[].
  */
@@ -174,6 +211,9 @@ static void _tnl_import_array( struct gl_context *ctx,
       case GL_HALF_FLOAT:
         convert_half_to_float(input, ptr, fptr, count, sz);
         break;
+      case GL_FIXED:
+         convert_fixed_to_float(input, ptr, fptr, count);
+         break;
       default:
         assert(0);
         break;
index 37940efdc111c9368a67d162f708e616dc09177d..6834f3b5aa58072b5ec9711eebcac6931f315a98 100644 (file)
@@ -130,6 +130,8 @@ void vbo_use_buffer_objects(struct gl_context *ctx);
 
 void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func);
 
+void vbo_check_buffers_are_unmapped(struct gl_context *ctx);
+
 
 void GLAPIENTRY
 _es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
index d56c91cd0946d3d981f084c66243e91bc1e49152..1b0ed79473b362b44e6b91a6cb31e95939c16d61 100644 (file)
@@ -40,13 +40,16 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "vbo_attrib.h"
 
 
+/**
+ * Max number of primitives (number of glBegin/End pairs) per VBO.
+ */
 #define VBO_MAX_PRIM 64
 
-/* Wierd implementation stuff:
+
+/**
+ * Size of the VBO to use for glBegin/glVertex/glEnd-style rendering.
  */
 #define VBO_VERT_BUFFER_SIZE (1024*64) /* bytes */
-#define VBO_MAX_ATTR_CODEGEN 16 
-#define ERROR_ATTRIB 16
 
 
 /** Current vertex program mode */
@@ -152,7 +155,6 @@ struct vbo_exec_context
 void vbo_exec_init( struct gl_context *ctx );
 void vbo_exec_destroy( struct gl_context *ctx );
 void vbo_exec_invalidate_state( struct gl_context *ctx, GLuint new_state );
-void vbo_exec_FlushVertices_internal( struct gl_context *ctx, GLboolean unmap );
 
 void vbo_exec_BeginVertices( struct gl_context *ctx );
 void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags );
index 03d6bb4aefe1602c931b822b7887627057d138bb..2f9f3ec7c465797ffde23b81317a7c4726860b2e 100644 (file)
@@ -159,8 +159,7 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
                        exec->vtx.attrsz[i], 
                        exec->vtx.attrptr[i]);
          
-         if (memcmp(current, tmp, sizeof(tmp)) != 0)
-         { 
+         if (memcmp(current, tmp, sizeof(tmp)) != 0) { 
             memcpy(current, tmp, sizeof(tmp));
         
             /* Given that we explicitly state size here, there is no need
@@ -192,14 +191,18 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
 }
 
 
-static void vbo_exec_copy_from_current( struct vbo_exec_context *exec )
+/**
+ * Copy current vertex attribute values into the current vertex.
+ */
+static void
+vbo_exec_copy_from_current(struct vbo_exec_context *exec)
 {
    struct gl_context *ctx = exec->ctx;
    struct vbo_context *vbo = vbo_context(ctx);
    GLint i;
 
-   for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
-      const GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
+   for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) {
+      const GLfloat *current = (GLfloat *) vbo->currval[i].Ptr;
       switch (exec->vtx.attrsz[i]) {
       case 4: exec->vtx.attrptr[i][3] = current[3];
       case 3: exec->vtx.attrptr[i][2] = current[2];
@@ -213,17 +216,21 @@ static void vbo_exec_copy_from_current( struct vbo_exec_context *exec )
 
 /**
  * Flush existing data, set new attrib size, replay copied vertices.
+ * This is called when we transition from a small vertex attribute size
+ * to a larger one.  Ex: glTexCoord2f -> glTexCoord4f.
+ * We need to go back over the previous 2-component texcoords and insert
+ * zero and one values.
  */ 
-static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
-                                         GLuint attr,
-                                         GLuint newsz )
+static void
+vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
+                             GLuint attr, GLuint newSize )
 {
    struct gl_context *ctx = exec->ctx;
    struct vbo_context *vbo = vbo_context(ctx);
-   GLint lastcount = exec->vtx.vert_count;
+   const GLint lastcount = exec->vtx.vert_count;
    GLfloat *old_attrptr[VBO_ATTRIB_MAX];
-   GLuint old_vtx_size = exec->vtx.vertex_size;
-   GLuint oldsz = exec->vtx.attrsz[attr];
+   const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */
+   const GLuint oldSize = exec->vtx.attrsz[attr];
    GLuint i;
 
    /* Run pipeline on current vertices, copy wrapped vertices
@@ -239,7 +246,7 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
       memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr));
    }
 
-   if (unlikely(oldsz)) {
+   if (unlikely(oldSize)) {
       /* Do a COPY_TO_CURRENT to ensure back-copying works for the
        * case when the attribute already exists in the vertex and is
        * having its size increased.
@@ -251,21 +258,21 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
     * begin/end so that they don't bloat the vertices.
     */
    if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END &&
-       !oldsz && lastcount > 8 && exec->vtx.vertex_size) {
+       !oldSize && lastcount > 8 && exec->vtx.vertex_size) {
       vbo_exec_copy_to_current( exec );
       reset_attrfv( exec );
    }
 
    /* Fix up sizes:
     */
-   exec->vtx.attrsz[attr] = newsz;
-   exec->vtx.vertex_size += newsz - oldsz;
+   exec->vtx.attrsz[attr] = newSize;
+   exec->vtx.vertex_size += newSize - oldSize;
    exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) / 
                          (exec->vtx.vertex_size * sizeof(GLfloat)));
    exec->vtx.vert_count = 0;
    exec->vtx.buffer_ptr = exec->vtx.buffer_map;
 
-   if (unlikely(oldsz)) {
+   if (unlikely(oldSize)) {
       /* Size changed, recalculate all the attrptr[] values
        */
       GLfloat *tmp = exec->vtx.vertex;
@@ -283,11 +290,11 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
        * values.
        */
       vbo_exec_copy_from_current( exec );
-
-   else {
+   }
+   else {
       /* Just have to append the new attribute at the end */
       exec->vtx.attrptr[attr] = exec->vtx.vertex +
-        exec->vtx.vertex_size - newsz;
+        exec->vtx.vertex_size - newSize;
    }
 
    /* Replay stored vertices to translate them
@@ -311,10 +318,10 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
               GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex;
 
               if (j == attr) {
-                 if (oldsz) {
+                 if (oldSize) {
                     GLfloat tmp[4];
-                    COPY_CLEAN_4V(tmp, oldsz, data + old_offset);
-                    COPY_SZ_4V(dest + new_offset, newsz, tmp);
+                    COPY_CLEAN_4V(tmp, oldSize, data + old_offset);
+                    COPY_SZ_4V(dest + new_offset, newSize, tmp);
                  } else {
                     GLfloat *current = (GLfloat *)vbo->currval[j].Ptr;
                     COPY_SZ_4V(dest + new_offset, sz, current);
@@ -337,70 +344,82 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
 }
 
 
-static void vbo_exec_fixup_vertex( struct gl_context *ctx,
-                                  GLuint attr, GLuint sz )
+/**
+ * This is when a vertex attribute transitions to a different size.
+ * For example, we saw a bunch of glTexCoord2f() calls and now we got a
+ * glTexCoord4f() call.  We promote the array from size=2 to size=4.
+ */
+static void
+vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize)
 {
    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
-   int i;
 
-   if (sz > exec->vtx.attrsz[attr]) {
+   if (newSize > exec->vtx.attrsz[attr]) {
       /* New size is larger.  Need to flush existing vertices and get
        * an enlarged vertex format.
        */
-      vbo_exec_wrap_upgrade_vertex( exec, attr, sz );
+      vbo_exec_wrap_upgrade_vertex( exec, attr, newSize );
    }
-   else if (sz < exec->vtx.active_sz[attr]) {
+   else if (newSize < exec->vtx.active_sz[attr]) {
       static const GLfloat id[4] = { 0, 0, 0, 1 };
+      GLuint i;
 
       /* New size is smaller - just need to fill in some
        * zeros.  Don't need to flush or wrap.
        */
-      for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++)
+      for (i = newSize; i <= exec->vtx.attrsz[attr]; i++)
         exec->vtx.attrptr[attr][i-1] = id[i-1];
    }
 
-   exec->vtx.active_sz[attr] = sz;
+   exec->vtx.active_sz[attr] = newSize;
 
    /* Does setting NeedFlush belong here?  Necessitates resetting
     * vtxfmt on each flush (otherwise flags won't get reset
     * afterwards).
     */
    if (attr == 0) 
-      exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+      ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
 }
 
 
-/* 
+/**
+ * This macro is used to implement all the glVertex, glColor, glTexCoord,
+ * glVertexAttrib, etc functions.
  */
-#define ATTR( A, N, V0, V1, V2, V3 )                           \
-do {                                                           \
-   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;    \
+#define ATTR( A, N, V0, V1, V2, V3 )                                   \
+do {                                                                   \
+   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;            \
                                                                        \
-   if (unlikely(!(exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT))) \
-      ctx->Driver.BeginVertices( ctx );                                 \
+   if (unlikely(!(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT)))      \
+      ctx->Driver.BeginVertices( ctx );                                        \
+                                                                       \
    if (unlikely(exec->vtx.active_sz[A] != N))                          \
       vbo_exec_fixup_vertex(ctx, A, N);                                        \
                                                                        \
-   {                                                           \
-      GLfloat *dest = exec->vtx.attrptr[A];                    \
-      if (N>0) dest[0] = V0;                                   \
-      if (N>1) dest[1] = V1;                                   \
-      if (N>2) dest[2] = V2;                                   \
-      if (N>3) dest[3] = V3;                                   \
-   }                                                           \
-                                                               \
-   if ((A) == 0) {                                             \
-      GLuint i;                                                        \
-                                                               \
-      for (i = 0; i < exec->vtx.vertex_size; i++)              \
-        exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i];         \
-                                                               \
+   {                                                                   \
+      GLfloat *dest = exec->vtx.attrptr[A];                            \
+      if (N>0) dest[0] = V0;                                           \
+      if (N>1) dest[1] = V1;                                           \
+      if (N>2) dest[2] = V2;                                           \
+      if (N>3) dest[3] = V3;                                           \
+   }                                                                   \
+                                                                       \
+   if ((A) == 0) {                                                     \
+      /* This is a glVertex call */                                    \
+      GLuint i;                                                                \
+                                                                       \
+      for (i = 0; i < exec->vtx.vertex_size; i++)                      \
+        exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i];                 \
+                                                                       \
       exec->vtx.buffer_ptr += exec->vtx.vertex_size;                   \
-      exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;    \
-                                                               \
-      if (++exec->vtx.vert_count >= exec->vtx.max_vert)                \
-        vbo_exec_vtx_wrap( exec );                             \
-   }                                                           \
+                                                                       \
+      /* Set FLUSH_STORED_VERTICES to indicate that there's now */     \
+      /* something to draw (not just updating a color or texcoord).*/  \
+      ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;                  \
+                                                                       \
+      if (++exec->vtx.vert_count >= exec->vtx.max_vert)                        \
+        vbo_exec_vtx_wrap( exec );                                     \
+   }                                                                   \
 } while (0)
 
 
@@ -513,6 +532,24 @@ static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j )
 #endif /* FEATURE_evaluators */
 
 
+/**
+ * Flush (draw) vertices.
+ * \param  unmap - leave VBO unmapped after flushing?
+ */
+static void
+vbo_exec_FlushVertices_internal(struct vbo_exec_context *exec, GLboolean unmap)
+{
+   if (exec->vtx.vert_count || unmap) {
+      vbo_exec_vtx_flush( exec, unmap );
+   }
+
+   if (exec->vtx.vertex_size) {
+      vbo_exec_copy_to_current( exec );
+      reset_attrfv( exec );
+   }
+}
+
+
 /**
  * Called via glBegin.
  */
@@ -539,7 +576,7 @@ static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
        * begin/end pairs.
        */
       if (exec->vtx.vertex_size && !exec->vtx.attrsz[0]) 
-        vbo_exec_FlushVertices_internal( ctx, GL_FALSE );
+        vbo_exec_FlushVertices_internal(exec, GL_FALSE);
 
       i = exec->vtx.prim_count++;
       exec->vtx.prim[i].mode = mode;
@@ -825,7 +862,7 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec )
 
    /* Hook our functions into the dispatch table.
     */
-   _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt );
+   _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt );
 
    for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
       ASSERT(i < Elements(exec->vtx.attrsz));
@@ -894,32 +931,23 @@ void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
    _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
 }
 
-void vbo_exec_BeginVertices( struct gl_context *ctx )
-{
-   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
-   if (0) printf("%s\n", __FUNCTION__);
-   vbo_exec_vtx_map( exec );
 
-   assert((exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0);
-   exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
-}
-
-void vbo_exec_FlushVertices_internal( struct gl_context *ctx, GLboolean unmap )
+/**
+ * Called upon first glVertex, glColor, glTexCoord, etc.
+ */
+void vbo_exec_BeginVertices( struct gl_context *ctx )
 {
    struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
 
-   if (exec->vtx.vert_count || unmap) {
-      vbo_exec_vtx_flush( exec, unmap );
-   }
+   vbo_exec_vtx_map( exec );
 
-   if (exec->vtx.vertex_size) {
-      vbo_exec_copy_to_current( exec );
-      reset_attrfv( exec );
-   }
+   assert((ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0);
+   ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
 }
 
 
 /**
+ * Called via ctx->Driver.FlushVertices()
  * \param flags  bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT
  */
 void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags )
@@ -932,10 +960,8 @@ void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags )
    assert(exec->flush_call_depth == 1);
 #endif
 
-   if (0) printf("%s\n", __FUNCTION__);
-
-   if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
-      if (0) printf("%s - inside begin/end\n", __FUNCTION__);
+   if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
+      /* We've had glBegin but not glEnd! */
 #ifdef DEBUG
       exec->flush_call_depth--;
       assert(exec->flush_call_depth == 0);
@@ -943,14 +969,12 @@ void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags )
       return;
    }
 
-   vbo_exec_FlushVertices_internal( ctx, GL_TRUE );
+   /* Flush (draw), and make sure VBO is left unmapped when done */
+   vbo_exec_FlushVertices_internal(exec, GL_TRUE);
 
    /* Need to do this to ensure BeginVertices gets called again:
     */
-   if (exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT)
-      exec->ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
-
-   exec->ctx->Driver.NeedFlush &= ~flags;
+   ctx->Driver.NeedFlush &= ~(FLUSH_UPDATE_CURRENT | flags);
 
 #ifdef DEBUG
    exec->flush_call_depth--;
index 80085c17c5cd13aa4712a6b28935e31d81e65703..457343a1a5c3c51a0a18136e394581015f968f47 100644 (file)
 #include "vbo_context.h"
 
 
+/**
+ * All vertex buffers should be in an unmapped state when we're about
+ * to draw.  This debug function checks that.
+ */
+static void
+check_buffers_are_unmapped(const struct gl_client_array **inputs)
+{
+#ifdef DEBUG
+   GLuint i;
+
+   for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+      if (inputs[i]) {
+         struct gl_buffer_object *obj = inputs[i]->BufferObj;
+         assert(!_mesa_bufferobj_mapped(obj));
+      }
+   }
+#endif
+}
+
+
+/**
+ * A debug function that may be called from other parts of Mesa as
+ * needed during debugging.
+ */
+void
+vbo_check_buffers_are_unmapped(struct gl_context *ctx)
+{
+   struct vbo_context *vbo = vbo_context(ctx);
+   struct vbo_exec_context *exec = &vbo->exec;
+   /* check the current vertex arrays */
+   check_buffers_are_unmapped(exec->array.inputs);
+   /* check the current glBegin/glVertex/glEnd-style VBO */
+   assert(!_mesa_bufferobj_mapped(exec->vtx.bufferobj));
+}
+
+
+
 /**
  * Compute min and max elements by scanning the index buffer for
  * glDraw[Range]Elements() calls.
@@ -502,8 +539,13 @@ recalculate_input_bindings(struct gl_context *ctx)
 static void
 bind_arrays(struct gl_context *ctx)
 {
+   if (!ctx->Array.RebindArrays) {
+      return;
+   }
+
    bind_array_obj(ctx);
    recalculate_input_bindings(ctx);
+   ctx->Array.RebindArrays = GL_FALSE;
 }
 
 
@@ -576,6 +618,7 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
 
       if (primCount > 0) {
          /* draw one or two prims */
+         check_buffers_are_unmapped(exec->array.inputs);
          vbo->draw_prims(ctx, exec->array.inputs, prim, primCount, NULL,
                          GL_TRUE, start, start + count - 1);
       }
@@ -585,6 +628,7 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
       prim[0].start = start;
       prim[0].count = count;
 
+      check_buffers_are_unmapped(exec->array.inputs);
       vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL,
                       GL_TRUE, start, start + count - 1);
    }
@@ -790,6 +834,7 @@ vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
     * for the latter case elsewhere.
     */
 
+   check_buffers_are_unmapped(exec->array.inputs);
    vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib,
                    index_bounds_valid, start, end );
 }
@@ -1106,6 +1151,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
            prim[i].basevertex = 0;
       }
 
+      check_buffers_are_unmapped(exec->array.inputs);
       vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib,
                      GL_FALSE, ~0, ~0);
    } else {
@@ -1130,6 +1176,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
         else
            prim[0].basevertex = 0;
 
+         check_buffers_are_unmapped(exec->array.inputs);
          vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib,
                          GL_FALSE, ~0, ~0);
       }
index 87f6431056113706c524cd3b4db7c25a4e8cf282..539658021e3868210bba0b608c9dbdd561882411 100644 (file)
@@ -245,6 +245,7 @@ vbo_exec_bind_arrays( struct gl_context *ctx )
         arrays[attr]._MaxElement = count; /* ??? */
 
          varying_inputs |= 1 << attr;
+         ctx->NewState |= _NEW_ARRAY;
       }
    }
 
@@ -252,6 +253,9 @@ vbo_exec_bind_arrays( struct gl_context *ctx )
 }
 
 
+/**
+ * Unmap the VBO.  This is called before drawing.
+ */
 static void
 vbo_exec_vtx_unmap( struct vbo_exec_context *exec )
 {
@@ -284,6 +288,9 @@ vbo_exec_vtx_unmap( struct vbo_exec_context *exec )
 }
 
 
+/**
+ * Map the vertex buffer to begin storing glVertex, glColor, etc data.
+ */
 void
 vbo_exec_vtx_map( struct vbo_exec_context *exec )
 {
@@ -300,14 +307,12 @@ vbo_exec_vtx_map( struct vbo_exec_context *exec )
    if (!_mesa_is_bufferobj(exec->vtx.bufferobj))
       return;
 
-   if (exec->vtx.buffer_map != NULL) {
-      assert(0);
-      exec->vtx.buffer_map = NULL;
-      exec->vtx.buffer_ptr = NULL;
-   }
+   assert(!exec->vtx.buffer_map);
+   assert(!exec->vtx.buffer_ptr);
 
    if (VBO_VERT_BUFFER_SIZE > exec->vtx.buffer_used + 1024 &&
        ctx->Driver.MapBufferRange) {
+      /* The VBO exists and there's room for more */
       exec->vtx.buffer_map = 
          (GLfloat *)ctx->Driver.MapBufferRange(ctx, 
                                                target, 
@@ -320,6 +325,7 @@ vbo_exec_vtx_map( struct vbo_exec_context *exec )
    }
    
    if (!exec->vtx.buffer_map) {
+      /* Need to allocate a new VBO */
       exec->vtx.buffer_used = 0;
 
       ctx->Driver.BufferData(ctx, target, 
@@ -348,9 +354,10 @@ vbo_exec_vtx_map( struct vbo_exec_context *exec )
 
 /**
  * Execute the buffer and save copied verts.
+ * \param keep_unmapped  if true, leave the VBO unmapped when we're done.
  */
 void
-vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap )
+vbo_exec_vtx_flush(struct vbo_exec_context *exec, GLboolean keepUnmapped)
 {
    if (0)
       vbo_exec_debug_verts( exec );
@@ -390,7 +397,7 @@ vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap )
 
         /* If using a real VBO, get new storage -- unless asked not to.
           */
-         if (_mesa_is_bufferobj(exec->vtx.bufferobj) && !unmap) {
+         if (_mesa_is_bufferobj(exec->vtx.bufferobj) && !keepUnmapped) {
             vbo_exec_vtx_map( exec );
          }
       }
@@ -398,14 +405,13 @@ vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap )
 
    /* May have to unmap explicitly if we didn't draw:
     */
-   if (unmap && 
+   if (keepUnmapped &&
        _mesa_is_bufferobj(exec->vtx.bufferobj) &&
        exec->vtx.buffer_map) {
       vbo_exec_vtx_unmap( exec );
    }
 
-
-   if (unmap || exec->vtx.vertex_size == 0)
+   if (keepUnmapped || exec->vtx.vertex_size == 0)
       exec->vtx.max_vert = 0;
    else
       exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) / 
index 4ee78e9e1037f9eef67b5fc5d9de198d03f496cc..c8199544526d7264aac2b482f04ccd70738237e1 100644 (file)
@@ -646,11 +646,11 @@ static void _save_reset_vertex( struct gl_context *ctx )
 do {                                                           \
    struct vbo_save_context *save = &vbo_context(ctx)->save;    \
                                                                \
-   if (save->active_sz[A] != N)                                \
+   if (save->active_sz[A] != N)                                        \
       save_fixup_vertex(ctx, A, N);                            \
                                                                \
    {                                                           \
-      GLfloat *dest = save->attrptr[A];                        \
+      GLfloat *dest = save->attrptr[A];                                \
       if (N>0) dest[0] = V0;                                   \
       if (N>1) dest[1] = V1;                                   \
       if (N>2) dest[2] = V2;                                   \
@@ -663,7 +663,7 @@ do {                                                                \
       for (i = 0; i < save->vertex_size; i++)                  \
         save->buffer_ptr[i] = save->vertex[i];                 \
                                                                \
-      save->buffer_ptr += save->vertex_size;                           \
+      save->buffer_ptr += save->vertex_size;                   \
                                                                \
       if (++save->vert_count >= save->max_vert)                        \
         _save_wrap_filled_vertex( ctx );                       \
index d0454bf6212da8bf8d03b0c47266cbe36235fd78..634a6d3f84b6725a9ccff0c8891da526bd4f54df 100644 (file)
@@ -202,6 +202,7 @@ static void vbo_bind_vertex_list(struct gl_context *ctx,
 
         buffer_offset += node->attrsz[src] * sizeof(GLfloat);
          varying_inputs |= 1<<attr;
+         ctx->NewState |= _NEW_ARRAY;
       }
    }
 
index e52a6118c31bdd3624cd90314ce4863541fa6b18..6141e43467905273c8164fb856b457e655f32ea0 100644 (file)
@@ -55,7 +55,7 @@ _mesa_x86_64_transform_points4_general:
  *     rdx = source
  */
        movl V4F_COUNT(%rdx), %ecx      /* count */
-       movzx V4F_STRIDE(%rdx), %eax    /* stride */
+       movzbl V4F_STRIDE(%rdx), %eax   /* stride */
 
        movl %ecx, V4F_COUNT(%rdi)      /* set dest count */
        movl $4, V4F_SIZE(%rdi)         /* set dest size */
@@ -138,7 +138,7 @@ _mesa_x86_64_transform_points4_3d:
        movaps 16(%rax), %xmm10
 
        movl V4F_COUNT(%rdx), %ecx      /* count */
-       movzx V4F_STRIDE(%rdx), %eax    /* stride */
+       movzbl V4F_STRIDE(%rdx), %eax   /* stride */
 
        movl %ecx, V4F_COUNT(%rdi)      /* set dest count */
        movl $4, V4F_SIZE(%rdi)         /* set dest size */
@@ -199,7 +199,7 @@ p4_3d_done:
 _mesa_x86_64_transform_points4_identity:
 
        movl V4F_COUNT(%rdx), %ecx      /* count */
-       movzx V4F_STRIDE(%rdx), %eax    /* stride */
+       movzbl V4F_STRIDE(%rdx), %eax   /* stride */
 
        movl %ecx, V4F_COUNT(%rdi)      /* set dest count */
        movl $4, V4F_SIZE(%rdi)         /* set dest size */
@@ -228,7 +228,7 @@ p4_identity_done:
 _mesa_3dnow_transform_points4_3d_no_rot:
 
        movl V4F_COUNT(%rdx), %ecx      /* count */
-       movzx V4F_STRIDE(%rdx), %eax    /* stride */
+       movzbl V4F_STRIDE(%rdx), %eax   /* stride */
 
        movl %ecx, V4F_COUNT(%rdi)      /* set dest count */
        movl $4, V4F_SIZE(%rdi)         /* set dest size */
@@ -293,7 +293,7 @@ p4_3d_no_rot_done:
 _mesa_3dnow_transform_points4_perspective:
 
        movl V4F_COUNT(%rdx), %ecx      /* count */
-       movzx V4F_STRIDE(%rdx), %eax    /* stride */
+       movzbl V4F_STRIDE(%rdx), %eax   /* stride */
 
        movl %ecx, V4F_COUNT(%rdi)      /* set dest count */
        movl $4, V4F_SIZE(%rdi)         /* set dest size */
@@ -360,7 +360,7 @@ p4_perspective_done:
 _mesa_3dnow_transform_points4_2d_no_rot:
 
        movl V4F_COUNT(%rdx), %ecx      /* count */
-       movzx V4F_STRIDE(%rdx), %eax    /* stride */
+       movzbl V4F_STRIDE(%rdx), %eax   /* stride */
 
        movl %ecx, V4F_COUNT(%rdi)      /* set dest count */
        movl $4, V4F_SIZE(%rdi)         /* set dest size */
@@ -416,7 +416,7 @@ p4_2d_no_rot_done:
 _mesa_3dnow_transform_points4_2d:
 
        movl V4F_COUNT(%rdx), %ecx      /* count */
-       movzx V4F_STRIDE(%rdx), %eax    /* stride */
+       movzbl V4F_STRIDE(%rdx), %eax   /* stride */
 
        movl %ecx, V4F_COUNT(%rdi)      /* set dest count */
        movl $4, V4F_SIZE(%rdi)         /* set dest size */
index 3886a510bbc789743f67988881787c48551dd227..3be4515b114f94f53638c93aa391d4bacc52ffc2 100644 (file)
@@ -77,7 +77,9 @@
  */
 
 .globl _generic_read_RGBA_span_BGRA8888_REV_MMX
+#ifndef USE_DRICORE
 .hidden _generic_read_RGBA_span_BGRA8888_REV_MMX
+#endif
        .type   _generic_read_RGBA_span_BGRA8888_REV_MMX, @function
 _generic_read_RGBA_span_BGRA8888_REV_MMX:
        pushl   %ebx
@@ -172,7 +174,9 @@ _generic_read_RGBA_span_BGRA8888_REV_MMX:
  */
 
 .globl _generic_read_RGBA_span_BGRA8888_REV_SSE
+#ifndef USE_DRICORE
 .hidden _generic_read_RGBA_span_BGRA8888_REV_SSE
+#endif
        .type   _generic_read_RGBA_span_BGRA8888_REV_SSE, @function
 _generic_read_RGBA_span_BGRA8888_REV_SSE:
        pushl   %esi
@@ -335,7 +339,9 @@ _generic_read_RGBA_span_BGRA8888_REV_SSE:
 
        .text
 .globl _generic_read_RGBA_span_BGRA8888_REV_SSE2
+#ifndef USE_DRICORE
 .hidden _generic_read_RGBA_span_BGRA8888_REV_SSE2
+#endif
        .type   _generic_read_RGBA_span_BGRA8888_REV_SSE2, @function
 _generic_read_RGBA_span_BGRA8888_REV_SSE2:
        pushl   %esi
@@ -494,7 +500,9 @@ _generic_read_RGBA_span_BGRA8888_REV_SSE2:
 
        .text
        .globl  _generic_read_RGBA_span_RGB565_MMX
+#ifndef USE_DRICORE
         .hidden _generic_read_RGBA_span_RGB565_MMX
+#endif
        .type   _generic_read_RGBA_span_RGB565_MMX, @function
 
 _generic_read_RGBA_span_RGB565_MMX:
@@ -648,7 +656,7 @@ _generic_read_RGBA_span_RGB565_MMX:
        testl   $0x01, %ecx
        je      .L01
 
-       movzxw  (%eax), %ecx
+       movzwl  (%eax), %ecx
        movd    %ecx, %mm4
 
        pshufw  $0x00, %mm4, %mm0
diff --git a/src/talloc/SConscript b/src/talloc/SConscript
deleted file mode 100644 (file)
index 3bf7029..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-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
deleted file mode 100644 (file)
index 94a9ed0..0000000
+++ /dev/null
@@ -1,674 +0,0 @@
-                    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
deleted file mode 100644 (file)
index 65c5ca8..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-                   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
deleted file mode 100644 (file)
index cc01346..0000000
+++ /dev/null
@@ -1,2034 +0,0 @@
-/* 
-   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
deleted file mode 100644 (file)
index 13d7a15..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-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
deleted file mode 100644 (file)
index f549a17..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-#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
deleted file mode 100644 (file)
index 01de806..0000000
+++ /dev/null
@@ -1,757 +0,0 @@
-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