summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian König <[email protected]>2011-02-24 22:02:42 +0100
committerChristian König <[email protected]>2011-02-24 22:02:42 +0100
commitb922a0ce12916a91cfc3e56714913fcf63279ff2 (patch)
treee24fa039925220882d155ccb987f7914e83f4372 /src
parentf013b4f8f1329982727691a55cc263e3011d02bf (diff)
parentc0ad70ae31ee5501281b434d56e389fc92b13a3a (diff)
Merge remote branch 'origin/master' into pipe-video
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
Diffstat (limited to 'src')
-rw-r--r--src/SConscript19
-rw-r--r--src/egl/Makefile4
-rw-r--r--src/egl/drivers/dri2/Makefile13
-rw-r--r--src/egl/drivers/dri2/egl_dri2.c1693
-rw-r--r--src/egl/drivers/dri2/egl_dri2.h195
-rw-r--r--src/egl/drivers/dri2/platform_drm.c683
-rw-r--r--src/egl/drivers/dri2/platform_wayland.c673
-rw-r--r--src/egl/drivers/dri2/platform_x11.c1058
-rw-r--r--src/egl/main/Makefile5
-rw-r--r--src/egl/main/egldisplay.c1
-rw-r--r--src/egl/main/egldisplay.h1
-rw-r--r--src/egl/main/egldriver.c29
-rw-r--r--src/egl/wayland/Makefile67
-rw-r--r--src/egl/wayland/wayland-egl-priv.h60
-rw-r--r--src/egl/wayland/wayland-egl.c226
-rw-r--r--src/egl/wayland/wayland-egl.pc.in12
-rw-r--r--src/gallium/SConscript1
-rw-r--r--src/gallium/auxiliary/Makefile1
-rw-r--r--src/gallium/auxiliary/SConscript2
-rw-r--r--src/gallium/auxiliary/cso_cache/cso_context.c665
-rw-r--r--src/gallium/auxiliary/cso_cache/cso_context.h7
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c17
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.c17
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.h5
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe.c4
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_aaline.c18
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_pstipple.c34
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_validate.c5
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h1
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c3
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch.c4
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_emit.c2
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c2
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_conv.c59
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_init.c6
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr.h4
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c17
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_x86sse.c3
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_build.c59
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_dump.c36
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.c241
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.h1
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_info.c15
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h17
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_parse.c4
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_parse.h3
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sanity.c3
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sse2.c2
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_text.c135
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_ureg.c91
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_ureg.h69
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_util.c7
-rw-r--r--src/gallium/auxiliary/translate/translate_cache.c4
-rw-r--r--src/gallium/auxiliary/util/dbghelp.h1265
-rw-r--r--src/gallium/auxiliary/util/u_blit.c9
-rw-r--r--src/gallium/auxiliary/util/u_blitter.c128
-rw-r--r--src/gallium/auxiliary/util/u_blitter.h16
-rw-r--r--src/gallium/auxiliary/util/u_debug.c80
-rw-r--r--src/gallium/auxiliary/util/u_debug.h37
-rw-r--r--src/gallium/auxiliary/util/u_debug_refcnt.c12
-rw-r--r--src/gallium/auxiliary/util/u_debug_symbol.c95
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.c14
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.h5
-rw-r--r--src/gallium/auxiliary/util/u_dump_state.c1
-rw-r--r--src/gallium/auxiliary/util/u_format.h42
-rw-r--r--src/gallium/auxiliary/util/u_gen_mipmap.c4
-rw-r--r--src/gallium/auxiliary/util/u_index_modify.c18
-rw-r--r--src/gallium/auxiliary/util/u_inlines.h19
-rw-r--r--src/gallium/auxiliary/util/u_math.h14
-rw-r--r--src/gallium/auxiliary/util/u_resource.c2
-rw-r--r--src/gallium/auxiliary/util/u_tile.c81
-rw-r--r--src/gallium/auxiliary/util/u_tile.h24
-rw-r--r--src/gallium/auxiliary/util/u_transfer.c7
-rw-r--r--src/gallium/auxiliary/util/u_transfer.h12
-rw-r--r--src/gallium/auxiliary/util/u_upload_mgr.c13
-rw-r--r--src/gallium/auxiliary/util/u_vbuf_mgr.c601
-rw-r--r--src/gallium/auxiliary/util/u_vbuf_mgr.h121
-rw-r--r--src/gallium/auxiliary/vl/vl_compositor.c3
-rw-r--r--src/gallium/auxiliary/vl/vl_idct.c4
-rw-r--r--src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c2
-rw-r--r--src/gallium/auxiliary/vl/vl_vertex_buffers.c6
-rw-r--r--src/gallium/docs/d3d11ddi.txt1
-rw-r--r--src/gallium/docs/source/context.rst113
-rw-r--r--src/gallium/docs/source/screen.rst2
-rw-r--r--src/gallium/docs/source/tgsi.rst170
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_vertex.c2
-rw-r--r--src/gallium/drivers/failover/fo_state.c2
-rw-r--r--src/gallium/drivers/galahad/glhd_context.c14
-rw-r--r--src/gallium/drivers/i915/TODO8
-rw-r--r--src/gallium/drivers/i915/i915_context.c27
-rw-r--r--src/gallium/drivers/i915/i915_context.h4
-rw-r--r--src/gallium/drivers/i915/i915_debug.c11
-rw-r--r--src/gallium/drivers/i915/i915_debug.h1
-rw-r--r--src/gallium/drivers/i915/i915_flush.c4
-rw-r--r--src/gallium/drivers/i915/i915_resource_texture.c24
-rw-r--r--src/gallium/drivers/i915/i915_screen.c92
-rw-r--r--src/gallium/drivers/i915/i915_screen.h5
-rw-r--r--src/gallium/drivers/i915/i915_state.c59
-rw-r--r--src/gallium/drivers/i915/i915_state_dynamic.c69
-rw-r--r--src/gallium/drivers/i915/i915_state_emit.c57
-rw-r--r--src/gallium/drivers/i915/i915_state_immediate.c68
-rw-r--r--src/gallium/drivers/i915/i915_winsys.h3
-rw-r--r--src/gallium/drivers/i965/brw_pipe_vertex.c2
-rw-r--r--src/gallium/drivers/identity/id_context.c14
-rw-r--r--src/gallium/drivers/llvmpipe/SConscript9
-rw-r--r--src/gallium/drivers/llvmpipe/lp_flush.c2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_vertex.c3
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_main.c13
-rw-r--r--src/gallium/drivers/noop/noop_state.c2
-rw-r--r--src/gallium/drivers/nv50/nv50_pc_optimize.c2
-rw-r--r--src/gallium/drivers/nv50/nv50_query.c2
-rw-r--r--src/gallium/drivers/nv50/nv50_state.c2
-rw-r--r--src/gallium/drivers/nv50/nv50_tgsi_to_nc.c2
-rw-r--r--src/gallium/drivers/nvc0/nvc0_3d.xml.h130
-rw-r--r--src/gallium/drivers/nvc0/nvc0_buffer.c25
-rw-r--r--src/gallium/drivers/nvc0/nvc0_context.c32
-rw-r--r--src/gallium/drivers/nvc0/nvc0_context.h12
-rw-r--r--src/gallium/drivers/nvc0/nvc0_fence.c37
-rw-r--r--src/gallium/drivers/nvc0/nvc0_fence.h3
-rw-r--r--src/gallium/drivers/nvc0/nvc0_miptree.c6
-rw-r--r--src/gallium/drivers/nvc0/nvc0_mm.c4
-rw-r--r--src/gallium/drivers/nvc0/nvc0_pc.c35
-rw-r--r--src/gallium/drivers/nvc0/nvc0_pc.h19
-rw-r--r--src/gallium/drivers/nvc0/nvc0_pc_emit.c76
-rw-r--r--src/gallium/drivers/nvc0/nvc0_pc_optimize.c370
-rw-r--r--src/gallium/drivers/nvc0/nvc0_pc_print.c40
-rw-r--r--src/gallium/drivers/nvc0/nvc0_pc_regalloc.c276
-rw-r--r--src/gallium/drivers/nvc0/nvc0_program.c45
-rw-r--r--src/gallium/drivers/nvc0/nvc0_program.h5
-rw-r--r--src/gallium/drivers/nvc0/nvc0_push.c4
-rw-r--r--src/gallium/drivers/nvc0/nvc0_query.c2
-rw-r--r--src/gallium/drivers/nvc0/nvc0_resource.h8
-rw-r--r--src/gallium/drivers/nvc0/nvc0_screen.c27
-rw-r--r--src/gallium/drivers/nvc0/nvc0_screen.h14
-rw-r--r--src/gallium/drivers/nvc0/nvc0_shader_state.c73
-rw-r--r--src/gallium/drivers/nvc0/nvc0_state.c153
-rw-r--r--src/gallium/drivers/nvc0/nvc0_state_validate.c155
-rw-r--r--src/gallium/drivers/nvc0/nvc0_stateobj.h11
-rw-r--r--src/gallium/drivers/nvc0/nvc0_surface.c46
-rw-r--r--src/gallium/drivers/nvc0/nvc0_tex.c7
-rw-r--r--src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c141
-rw-r--r--src/gallium/drivers/nvc0/nvc0_transfer.c44
-rw-r--r--src/gallium/drivers/nvc0/nvc0_vbo.c95
-rw-r--r--src/gallium/drivers/nvc0/nvc0_winsys.h2
-rw-r--r--src/gallium/drivers/nvfx/nvfx_vbo.c3
-rw-r--r--src/gallium/drivers/r300/r300_blit.c308
-rw-r--r--src/gallium/drivers/r300/r300_cb.h54
-rw-r--r--src/gallium/drivers/r300/r300_chipset.c2
-rw-r--r--src/gallium/drivers/r300/r300_chipset.h13
-rw-r--r--src/gallium/drivers/r300/r300_context.c136
-rw-r--r--src/gallium/drivers/r300/r300_context.h150
-rw-r--r--src/gallium/drivers/r300/r300_cs.h51
-rw-r--r--src/gallium/drivers/r300/r300_debug.c3
-rw-r--r--src/gallium/drivers/r300/r300_emit.c293
-rw-r--r--src/gallium/drivers/r300/r300_flush.c49
-rw-r--r--src/gallium/drivers/r300/r300_fs.c126
-rw-r--r--src/gallium/drivers/r300/r300_hyperz.c128
-rw-r--r--src/gallium/drivers/r300/r300_hyperz.h2
-rw-r--r--src/gallium/drivers/r300/r300_query.c23
-rw-r--r--src/gallium/drivers/r300/r300_reg.h9
-rw-r--r--src/gallium/drivers/r300/r300_render.c444
-rw-r--r--src/gallium/drivers/r300/r300_render_translate.c237
-rw-r--r--src/gallium/drivers/r300/r300_resource.c20
-rw-r--r--src/gallium/drivers/r300/r300_screen.c49
-rw-r--r--src/gallium/drivers/r300/r300_screen.h4
-rw-r--r--src/gallium/drivers/r300/r300_screen_buffer.c180
-rw-r--r--src/gallium/drivers/r300/r300_screen_buffer.h37
-rw-r--r--src/gallium/drivers/r300/r300_state.c306
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c130
-rw-r--r--src/gallium/drivers/r300/r300_state_inlines.h22
-rw-r--r--src/gallium/drivers/r300/r300_texture.c229
-rw-r--r--src/gallium/drivers/r300/r300_texture.h13
-rw-r--r--src/gallium/drivers/r300/r300_texture_desc.c343
-rw-r--r--src/gallium/drivers/r300/r300_texture_desc.h14
-rw-r--r--src/gallium/drivers/r300/r300_tgsi_to_rc.c9
-rw-r--r--src/gallium/drivers/r300/r300_tgsi_to_rc.h3
-rw-r--r--src/gallium/drivers/r300/r300_transfer.c61
-rw-r--r--src/gallium/drivers/r300/r300_vs.c7
-rw-r--r--src/gallium/drivers/r300/r300_winsys.h110
-rw-r--r--src/gallium/drivers/r600/Makefile3
-rw-r--r--src/gallium/drivers/r600/SConscript1
-rw-r--r--src/gallium/drivers/r600/eg_state_inlines.h37
-rw-r--r--src/gallium/drivers/r600/evergreen_state.c388
-rw-r--r--src/gallium/drivers/r600/evergreend.h15
-rw-r--r--src/gallium/drivers/r600/r600.h2
-rw-r--r--src/gallium/drivers/r600/r600_asm.c181
-rw-r--r--src/gallium/drivers/r600/r600_asm.h4
-rw-r--r--src/gallium/drivers/r600/r600_blit.c159
-rw-r--r--src/gallium/drivers/r600/r600_buffer.c328
-rw-r--r--src/gallium/drivers/r600/r600_pipe.c112
-rw-r--r--src/gallium/drivers/r600/r600_pipe.h78
-rw-r--r--src/gallium/drivers/r600/r600_resource.h43
-rw-r--r--src/gallium/drivers/r600/r600_shader.c817
-rw-r--r--src/gallium/drivers/r600/r600_shader.h3
-rw-r--r--src/gallium/drivers/r600/r600_state.c385
-rw-r--r--src/gallium/drivers/r600/r600_state_common.c371
-rw-r--r--src/gallium/drivers/r600/r600_state_inlines.h75
-rw-r--r--src/gallium/drivers/r600/r600_texture.c373
-rw-r--r--src/gallium/drivers/r600/r600_translate.c182
-rw-r--r--src/gallium/drivers/r600/r600_upload.c114
-rw-r--r--src/gallium/drivers/r600/r600d.h27
-rw-r--r--src/gallium/drivers/rbug/rbug_context.c14
-rw-r--r--src/gallium/drivers/rbug/rbug_objects.c6
-rw-r--r--src/gallium/drivers/softpipe/sp_context.c4
-rw-r--r--src/gallium/drivers/softpipe/sp_context.h6
-rw-r--r--src/gallium/drivers/softpipe/sp_flush.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_screen.c4
-rw-r--r--src/gallium/drivers/softpipe/sp_setup.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_state_sampler.c18
-rw-r--r--src/gallium/drivers/softpipe/sp_state_vertex.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_tex_sample.c238
-rw-r--r--src/gallium/drivers/softpipe/sp_tex_tile_cache.c42
-rw-r--r--src/gallium/drivers/softpipe/sp_tex_tile_cache.h2
-rw-r--r--src/gallium/drivers/softpipe/sp_texture.c37
-rw-r--r--src/gallium/drivers/softpipe/sp_tile_cache.c22
-rw-r--r--src/gallium/drivers/svga/svga_context.c71
-rw-r--r--src/gallium/drivers/svga/svga_context.h23
-rw-r--r--src/gallium/drivers/svga/svga_draw.c7
-rw-r--r--src/gallium/drivers/svga/svga_draw_arrays.c1
-rw-r--r--src/gallium/drivers/svga/svga_draw_elements.c1
-rw-r--r--src/gallium/drivers/svga/svga_pipe_blit.c4
-rw-r--r--src/gallium/drivers/svga/svga_pipe_draw.c8
-rw-r--r--src/gallium/drivers/svga/svga_pipe_flush.c37
-rw-r--r--src/gallium/drivers/svga/svga_pipe_misc.c2
-rw-r--r--src/gallium/drivers/svga/svga_pipe_rasterizer.c35
-rw-r--r--src/gallium/drivers/svga/svga_pipe_sampler.c16
-rw-r--r--src/gallium/drivers/svga/svga_pipe_vertex.c1
-rw-r--r--src/gallium/drivers/svga/svga_resource.c1
-rw-r--r--src/gallium/drivers/svga/svga_resource_buffer.c15
-rw-r--r--src/gallium/drivers/svga/svga_resource_buffer.h6
-rw-r--r--src/gallium/drivers/svga/svga_resource_buffer_upload.c68
-rw-r--r--src/gallium/drivers/svga/svga_resource_texture.c36
-rw-r--r--src/gallium/drivers/svga/svga_sampler_view.c26
-rw-r--r--src/gallium/drivers/svga/svga_sampler_view.h6
-rw-r--r--src/gallium/drivers/svga/svga_screen.c18
-rw-r--r--src/gallium/drivers/svga/svga_state.h4
-rw-r--r--src/gallium/drivers/svga/svga_state_framebuffer.c49
-rw-r--r--src/gallium/drivers/svga/svga_state_need_swtnl.c23
-rw-r--r--src/gallium/drivers/svga/svga_state_tss.c78
-rw-r--r--src/gallium/drivers/svga/svga_state_vs.c2
-rw-r--r--src/gallium/drivers/svga/svga_surface.c30
-rw-r--r--src/gallium/drivers/svga/svga_surface.h5
-rw-r--r--src/gallium/drivers/svga/svga_swtnl_backend.c4
-rw-r--r--src/gallium/drivers/svga/svga_swtnl_draw.c1
-rw-r--r--src/gallium/drivers/svga/svga_swtnl_state.c2
-rw-r--r--src/gallium/drivers/svga/svga_tgsi_insn.c236
-rw-r--r--src/gallium/drivers/svga/svgadump/svga_shader_op.c4
-rw-r--r--src/gallium/drivers/trace/tr_context.c23
-rw-r--r--src/gallium/drivers/trace/tr_dump_state.c1
-rw-r--r--src/gallium/include/pipe/p_context.h8
-rw-r--r--src/gallium/include/pipe/p_defines.h30
-rw-r--r--src/gallium/include/pipe/p_format.h10
-rw-r--r--src/gallium/include/pipe/p_shader_tokens.h30
-rw-r--r--src/gallium/include/pipe/p_state.h10
-rw-r--r--src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp4
-rw-r--r--src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h1
-rw-r--r--src/gallium/state_trackers/dri/common/dri_context.c18
-rw-r--r--src/gallium/state_trackers/dri/common/dri_drawable.c1
-rw-r--r--src/gallium/state_trackers/dri/common/dri_drawable.h3
-rw-r--r--src/gallium/state_trackers/dri/common/dri_screen.c6
-rw-r--r--src/gallium/state_trackers/dri/drm/dri2.c93
-rw-r--r--src/gallium/state_trackers/dri/drm/dri2_buffer.h22
-rw-r--r--src/gallium/state_trackers/egl/Makefile14
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d.c9
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_image.c4
-rw-r--r--src/gallium/state_trackers/egl/common/native.h3
-rw-r--r--src/gallium/state_trackers/egl/common/native_helper.c8
-rw-r--r--src/gallium/state_trackers/egl/common/native_helper.h5
-rw-r--r--src/gallium/state_trackers/egl/drm/native_drm.c2
-rw-r--r--src/gallium/state_trackers/egl/wayland/native_wayland.c626
-rw-r--r--src/gallium/state_trackers/egl/wayland/native_wayland.h97
-rw-r--r--src/gallium/state_trackers/egl/x11/native_dri2.c2
-rw-r--r--src/gallium/state_trackers/python/p_context.i4
-rw-r--r--src/gallium/state_trackers/python/p_device.i4
-rw-r--r--src/gallium/state_trackers/vega/Makefile26
-rw-r--r--src/gallium/state_trackers/vega/SConscript23
-rw-r--r--src/gallium/state_trackers/vega/api_filters.c29
-rw-r--r--src/gallium/state_trackers/vega/api_images.c43
-rw-r--r--src/gallium/state_trackers/vega/api_masks.c31
-rw-r--r--src/gallium/state_trackers/vega/api_paint.c56
-rw-r--r--src/gallium/state_trackers/vega/api_params.c178
-rw-r--r--src/gallium/state_trackers/vega/api_path.c48
-rw-r--r--src/gallium/state_trackers/vega/api_text.c29
-rw-r--r--src/gallium/state_trackers/vega/handle.c93
-rw-r--r--src/gallium/state_trackers/vega/handle.h171
-rw-r--r--src/gallium/state_trackers/vega/image.c2
-rw-r--r--src/gallium/state_trackers/vega/paint.c7
-rw-r--r--src/gallium/state_trackers/vega/paint.h1
-rw-r--r--src/gallium/state_trackers/vega/polygon.c2
-rw-r--r--src/gallium/state_trackers/vega/renderer.c15
-rw-r--r--src/gallium/state_trackers/vega/shader.c2
-rw-r--r--src/gallium/state_trackers/vega/vg_context.c25
-rw-r--r--src/gallium/state_trackers/vega/vg_context.h17
-rw-r--r--src/gallium/state_trackers/vega/vg_manager.c4
-rw-r--r--src/gallium/state_trackers/vega/vgu.c13
-rw-r--r--src/gallium/state_trackers/wgl/SConscript3
-rw-r--r--src/gallium/state_trackers/wgl/stw_device.c3
-rw-r--r--src/gallium/state_trackers/xorg/xorg_crtc.c6
-rw-r--r--src/gallium/state_trackers/xorg/xorg_renderer.c5
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/subpicture.c5
-rw-r--r--src/gallium/state_trackers/xorg/xvmc/surface.c2
-rw-r--r--src/gallium/targets/SConscript.dri1
-rw-r--r--src/gallium/targets/dri-r300/Makefile2
-rw-r--r--src/gallium/targets/dri-r300/SConscript2
-rw-r--r--src/gallium/targets/dri-r600/SConscript2
-rw-r--r--src/gallium/targets/dri-vmwgfx/Makefile1
-rw-r--r--src/gallium/targets/egl-static/SConscript17
-rw-r--r--src/gallium/targets/egl/Makefile5
-rw-r--r--src/gallium/targets/libgl-gdi/SConscript7
-rw-r--r--src/gallium/targets/libgl-xlib/SConscript7
-rw-r--r--src/gallium/targets/xorg-radeon/Makefile2
-rw-r--r--src/gallium/tests/graw/SConscript1
-rw-r--r--src/gallium/tests/graw/fs-test.c1
-rw-r--r--src/gallium/tests/graw/gs-test.c2
-rw-r--r--src/gallium/tests/graw/quad-sample.c414
-rw-r--r--src/gallium/tests/graw/quad-tex.c1
-rw-r--r--src/gallium/tests/graw/shader-leak.c1
-rw-r--r--src/gallium/tests/graw/tri-gs.c1
-rw-r--r--src/gallium/tests/graw/tri-instanced.c2
-rw-r--r--src/gallium/tests/graw/tri.c1
-rw-r--r--src/gallium/tests/graw/vs-test.c1
-rw-r--r--src/gallium/tests/trivial/quad-tex.c3
-rw-r--r--src/gallium/tests/trivial/tri.c3
-rw-r--r--src/gallium/winsys/SConscript4
-rw-r--r--src/gallium/winsys/i915/drm/i915_drm_batchbuffer.c24
-rw-r--r--src/gallium/winsys/i915/sw/i915_sw_batchbuffer.c11
-rw-r--r--src/gallium/winsys/i915/sw/i915_sw_buffer.c2
-rw-r--r--src/gallium/winsys/r600/drm/SConscript7
-rw-r--r--src/gallium/winsys/r600/drm/evergreen_hw_context.c2
-rw-r--r--src/gallium/winsys/r600/drm/r600_bo.c7
-rw-r--r--src/gallium/winsys/r600/drm/r600_drm.c109
-rw-r--r--src/gallium/winsys/r600/drm/r600_hw_context.c88
-rw-r--r--src/gallium/winsys/r600/drm/r600_priv.h1
-rw-r--r--src/gallium/winsys/r600/drm/radeon_bo.c4
-rw-r--r--src/gallium/winsys/r600/drm/radeon_pciid.c2
-rw-r--r--src/gallium/winsys/radeon/drm/Makefile5
-rw-r--r--src/gallium/winsys/radeon/drm/SConscript10
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_bo.c599
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_bo.h (renamed from src/gallium/winsys/radeon/drm/radeon_drm_buffer.h)54
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_buffer.c532
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_common.c116
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_cs.c293
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_cs.h93
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_r300.c169
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_winsys.h18
-rw-r--r--src/gallium/winsys/svga/drm/vmw_buffer.c3
-rw-r--r--src/gallium/winsys/svga/drm/vmw_context.c2
-rw-r--r--src/gallium/winsys/sw/xlib/SConscript2
-rw-r--r--src/glsl/Makefile54
-rw-r--r--src/glsl/SConscript29
-rw-r--r--src/glsl/ast.h37
-rw-r--r--src/glsl/ast_expr.cpp3
-rw-r--r--src/glsl/ast_function.cpp167
-rw-r--r--src/glsl/ast_to_hir.cpp112
-rw-r--r--src/glsl/ast_type.cpp1
-rw-r--r--src/glsl/builtins/profiles/130.frag10
-rw-r--r--src/glsl/builtins/profiles/130.vert10
-rwxr-xr-xsrc/glsl/builtins/tools/generate_builtins.py10
-rwxr-xr-xsrc/glsl/builtins/tools/texture_builtins.py210
-rw-r--r--src/glsl/configure.ac69
-rw-r--r--src/glsl/glcpp/glcpp-lex.c22
-rw-r--r--src/glsl/glcpp/glcpp-lex.l14
-rw-r--r--src/glsl/glcpp/glcpp-parse.c616
-rw-r--r--src/glsl/glcpp/glcpp-parse.y176
-rw-r--r--src/glsl/glcpp/glcpp.c10
-rw-r--r--src/glsl/glcpp/glcpp.h4
-rw-r--r--src/glsl/glcpp/pp.c30
-rw-r--r--src/glsl/glsl_lexer.cpp478
-rw-r--r--src/glsl/glsl_lexer.lpp22
-rw-r--r--src/glsl/glsl_parser.cpp3084
-rw-r--r--src/glsl/glsl_parser.h238
-rw-r--r--src/glsl/glsl_parser.ypp206
-rw-r--r--src/glsl/glsl_parser_extras.cpp60
-rw-r--r--src/glsl/glsl_parser_extras.h40
-rw-r--r--src/glsl/glsl_symbol_table.cpp14
-rw-r--r--src/glsl/glsl_symbol_table.h20
-rw-r--r--src/glsl/glsl_types.cpp26
-rw-r--r--src/glsl/glsl_types.h23
-rw-r--r--src/glsl/ir.cpp52
-rw-r--r--src/glsl/ir.h65
-rw-r--r--src/glsl/ir_clone.cpp6
-rw-r--r--src/glsl/ir_constant_expression.cpp36
-rw-r--r--src/glsl/ir_expression_flattening.cpp2
-rw-r--r--src/glsl/ir_function.cpp1
-rw-r--r--src/glsl/ir_hv_accept.cpp6
-rw-r--r--src/glsl/ir_import_prototypes.cpp3
-rw-r--r--src/glsl/ir_optimization.h1
-rw-r--r--src/glsl/ir_print_visitor.cpp12
-rw-r--r--src/glsl/ir_reader.cpp50
-rw-r--r--src/glsl/ir_rvalue_visitor.cpp1
-rw-r--r--src/glsl/ir_validate.cpp4
-rw-r--r--src/glsl/ir_variable.cpp1
-rw-r--r--src/glsl/ir_variable_refcount.h4
-rw-r--r--src/glsl/link_functions.cpp20
-rw-r--r--src/glsl/linker.cpp111
-rw-r--r--src/glsl/list.h28
-rw-r--r--src/glsl/loop_analysis.cpp14
-rw-r--r--src/glsl/loop_controls.cpp6
-rw-r--r--src/glsl/loop_unroll.cpp4
-rw-r--r--src/glsl/lower_discard.cpp2
-rw-r--r--src/glsl/lower_if_to_cond_assign.cpp2
-rw-r--r--src/glsl/lower_mat_op_to_vec.cpp2
-rw-r--r--src/glsl/lower_noise.cpp2
-rw-r--r--src/glsl/lower_texture_projection.cpp2
-rw-r--r--src/glsl/lower_variable_index_to_cond_assign.cpp9
-rw-r--r--src/glsl/lower_vec_index_to_cond_assign.cpp4
-rw-r--r--src/glsl/lower_vec_index_to_swizzle.cpp2
-rw-r--r--src/glsl/lower_vector.cpp2
-rw-r--r--src/glsl/main.cpp32
-rw-r--r--src/glsl/opt_algebraic.cpp2
-rw-r--r--src/glsl/opt_constant_folding.cpp2
-rw-r--r--src/glsl/opt_constant_propagation.cpp13
-rw-r--r--src/glsl/opt_constant_variable.cpp7
-rw-r--r--src/glsl/opt_copy_propagation.cpp15
-rw-r--r--src/glsl/opt_copy_propagation_elements.cpp458
-rw-r--r--src/glsl/opt_dead_code_local.cpp13
-rw-r--r--src/glsl/opt_dead_functions.cpp4
-rw-r--r--src/glsl/opt_function_inlining.cpp7
-rw-r--r--src/glsl/opt_structure_splitting.cpp16
-rw-r--r--src/glsl/opt_tree_grafting.cpp3
-rw-r--r--src/glsl/ralloc.c458
-rw-r--r--src/glsl/ralloc.h345
-rw-r--r--src/glsl/s_expression.cpp5
-rw-r--r--src/glsl/s_expression.h2
-rw-r--r--src/glx/dri2_glx.c16
-rw-r--r--src/glx/dri_glx.c39
-rw-r--r--src/glx/drisw_glx.c7
-rw-r--r--src/glx/glx_pbuffer.c11
-rw-r--r--src/glx/glxclient.h2
-rw-r--r--src/glx/glxcmds.c8
-rw-r--r--src/glx/glxext.c30
-rw-r--r--src/mapi/es1api/.gitignore1
-rw-r--r--src/mapi/es1api/Makefile7
-rw-r--r--src/mapi/es2api/.gitignore1
-rw-r--r--src/mapi/glapi/Makefile18
-rw-r--r--src/mapi/glapi/SConscript5
-rw-r--r--src/mapi/glapi/gen/gl_x86-64_asm.py3
-rw-r--r--src/mapi/glapi/gen/gl_x86_asm.py2
-rw-r--r--src/mapi/glapi/glapi.h5
-rw-r--r--src/mapi/glapi/glapi_x86-64.S3
-rw-r--r--src/mapi/glapi/glapi_x86.S2
-rw-r--r--src/mapi/mapi/entry.c2
-rw-r--r--src/mapi/shared-glapi/.gitignore2
-rw-r--r--src/mapi/shared-glapi/Makefile7
-rw-r--r--src/mapi/shared-glapi/SConscript116
-rw-r--r--src/mapi/vgapi/Makefile5
-rw-r--r--src/mesa/Makefile54
-rw-r--r--src/mesa/SConscript63
-rw-r--r--src/mesa/drivers/beos/GLView.cpp4
-rw-r--r--src/mesa/drivers/common/driverfuncs.c1
-rw-r--r--src/mesa/drivers/dri/Makefile.template15
-rw-r--r--src/mesa/drivers/dri/common/dri_metaops.c291
-rw-r--r--src/mesa/drivers/dri/common/dri_metaops.h81
-rw-r--r--src/mesa/drivers/dri/common/dri_util.c20
-rw-r--r--src/mesa/drivers/dri/common/dri_util.h6
-rw-r--r--src/mesa/drivers/dri/common/drisw_util.c45
-rw-r--r--src/mesa/drivers/dri/i810/i810context.c2
-rw-r--r--src/mesa/drivers/dri/i915/i830_vtbl.c10
-rw-r--r--src/mesa/drivers/dri/i915/i915_context.c14
-rw-r--r--src/mesa/drivers/dri/i915/i915_context.h37
-rw-r--r--src/mesa/drivers/dri/i915/i915_fragprog.c40
-rw-r--r--src/mesa/drivers/dri/i915/i915_program.c51
-rw-r--r--src/mesa/drivers/dri/i915/i915_reg.h7
-rw-r--r--src/mesa/drivers/dri/i915/i915_state.c275
-rw-r--r--src/mesa/drivers/dri/i915/i915_vtbl.c33
-rw-r--r--src/mesa/drivers/dri/i915/intel_render.c2
-rw-r--r--src/mesa/drivers/dri/i915/intel_tris.c70
-rw-r--r--src/mesa/drivers/dri/i965/brw_cc.c116
-rw-r--r--src/mesa/drivers/dri/i965/brw_context.h50
-rw-r--r--src/mesa/drivers/dri/i965/brw_cubemap_normalize.cpp2
-rw-r--r--src/mesa/drivers/dri/i965/brw_curbe.c20
-rw-r--r--src/mesa/drivers/dri/i965/brw_defines.h4
-rw-r--r--src/mesa/drivers/dri/i965/brw_draw.c52
-rw-r--r--src/mesa/drivers/dri/i965/brw_draw_upload.c412
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.cpp126
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.h19
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp2
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp9
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_schedule_instructions.cpp15
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp14
-rw-r--r--src/mesa/drivers/dri/i965/brw_misc_state.c80
-rw-r--r--src/mesa/drivers/dri/i965/brw_program.c4
-rw-r--r--src/mesa/drivers/dri/i965/brw_queryobj.c4
-rw-r--r--src/mesa/drivers/dri/i965/brw_state.h10
-rw-r--r--src/mesa/drivers/dri/i965/brw_state_batch.c82
-rw-r--r--src/mesa/drivers/dri/i965/brw_state_cache.c2
-rw-r--r--src/mesa/drivers/dri/i965/brw_state_dump.c49
-rw-r--r--src/mesa/drivers/dri/i965/brw_state_upload.c23
-rw-r--r--src/mesa/drivers/dri/i965/brw_util.c10
-rw-r--r--src/mesa/drivers/dri/i965/brw_util.h9
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs_surface_state.c17
-rw-r--r--src/mesa/drivers/dri/i965/brw_vtbl.c23
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm.c3
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_state.c4
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_surface_state.c197
-rw-r--r--src/mesa/drivers/dri/i965/gen6_cc.c12
-rw-r--r--src/mesa/drivers/dri/i965/gen6_sf_state.c4
-rw-r--r--src/mesa/drivers/dri/intel/intel_batchbuffer.c226
-rw-r--r--src/mesa/drivers/dri/intel/intel_batchbuffer.h124
-rw-r--r--src/mesa/drivers/dri/intel/intel_blit.c40
-rw-r--r--src/mesa/drivers/dri/intel/intel_buffer_objects.c319
-rw-r--r--src/mesa/drivers/dri/intel/intel_buffer_objects.h22
-rw-r--r--src/mesa/drivers/dri/intel/intel_context.c35
-rw-r--r--src/mesa/drivers/dri/intel/intel_context.h28
-rw-r--r--src/mesa/drivers/dri/intel/intel_extensions.c1
-rw-r--r--src/mesa/drivers/dri/intel/intel_fbo.c83
-rw-r--r--src/mesa/drivers/dri/intel/intel_pixel_bitmap.c2
-rw-r--r--src/mesa/drivers/dri/intel/intel_pixel_read.c15
-rw-r--r--src/mesa/drivers/dri/intel/intel_regions.c2
-rw-r--r--src/mesa/drivers/dri/intel/intel_screen.c51
-rw-r--r--src/mesa/drivers/dri/intel/intel_syncobj.c4
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex.h8
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_copy.c41
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_image.c10
-rw-r--r--src/mesa/drivers/dri/mach64/mach64_context.c2
-rw-r--r--src/mesa/drivers/dri/mga/mga_xmesa.c2
-rw-r--r--src/mesa/drivers/dri/nouveau/nouveau_context.c3
-rw-r--r--src/mesa/drivers/dri/r128/r128_context.c2
-rw-r--r--src/mesa/drivers/dri/r200/r200_vertprog.c2
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r300_fragprog.c43
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c133
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c9
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c2
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c69
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c2
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_code.h16
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_compiler.c15
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_compiler.h4
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c28
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h4
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c10
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c45
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_optimize.c1
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c17
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c12
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program.h6
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c1
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c22
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h2
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_print.c4
-rw-r--r--src/mesa/drivers/dri/r300/r300_blit.c3
-rw-r--r--src/mesa/drivers/dri/r300/r300_fragprog_common.c1
-rw-r--r--src/mesa/drivers/dri/r300/r300_reg.h44
-rw-r--r--src/mesa/drivers/dri/r300/radeon_mesa_to_rc.c1
-rw-r--r--src/mesa/drivers/dri/r600/evergreen_fragprog.c25
-rw-r--r--src/mesa/drivers/dri/r600/r700_fragprog.c20
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_chipset.h1
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common.c2
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common_context.c5
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common_context.h3
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_fbo.c2
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_screen.c1
-rw-r--r--src/mesa/drivers/dri/savage/savage_xmesa.c2
-rw-r--r--src/mesa/drivers/dri/sis/sis_context.c2
-rw-r--r--src/mesa/drivers/dri/swrast/swrast.c85
-rw-r--r--src/mesa/drivers/dri/tdfx/tdfx_context.c2
-rw-r--r--src/mesa/drivers/dri/unichrome/via_context.c2
-rw-r--r--src/mesa/drivers/fbdev/glfbdev.c2
-rw-r--r--src/mesa/drivers/osmesa/Makefile2
-rw-r--r--src/mesa/drivers/osmesa/osmesa.c1
-rw-r--r--src/mesa/drivers/windows/gdi/wmesa.c3
-rw-r--r--src/mesa/drivers/windows/gldirect/dglcontext.c2
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c2
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c1
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c2
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c1
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c2
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c1
-rw-r--r--src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c1
-rw-r--r--src/mesa/drivers/x11/fakeglx.c8
-rw-r--r--src/mesa/drivers/x11/xm_api.c6
-rw-r--r--src/mesa/drivers/x11/xmesa.h2
-rw-r--r--src/mesa/main/APIspec.xml61
-rw-r--r--src/mesa/main/accum.c1
-rw-r--r--src/mesa/main/arrayobj.c2
-rw-r--r--src/mesa/main/blend.c16
-rw-r--r--src/mesa/main/bufferobj.c13
-rw-r--r--src/mesa/main/context.c61
-rw-r--r--src/mesa/main/context.h25
-rw-r--r--src/mesa/main/debug.c27
-rw-r--r--src/mesa/main/debug.h3
-rw-r--r--src/mesa/main/depth.c6
-rw-r--r--src/mesa/main/dlist.c8
-rw-r--r--src/mesa/main/drawpix.c23
-rw-r--r--src/mesa/main/enable.c10
-rw-r--r--src/mesa/main/extensions.c115
-rw-r--r--src/mesa/main/fbobject.c154
-rw-r--r--src/mesa/main/fbobject.h3
-rw-r--r--src/mesa/main/formats.c6
-rw-r--r--src/mesa/main/formats.h3
-rw-r--r--src/mesa/main/framebuffer.c2
-rw-r--r--src/mesa/main/hint.c5
-rw-r--r--src/mesa/main/image.c7
-rw-r--r--src/mesa/main/imports.c15
-rw-r--r--src/mesa/main/imports.h19
-rw-r--r--src/mesa/main/lines.c6
-rw-r--r--src/mesa/main/mipmap.c52
-rw-r--r--src/mesa/main/mtypes.h110
-rw-r--r--src/mesa/main/queryobj.c38
-rw-r--r--src/mesa/main/readpix.c8
-rw-r--r--src/mesa/main/renderbuffer.c2
-rw-r--r--src/mesa/main/shaderapi.c19
-rw-r--r--src/mesa/main/shaderobj.c12
-rw-r--r--src/mesa/main/state.c2
-rw-r--r--src/mesa/main/stencil.c24
-rw-r--r--src/mesa/main/texformat.c11
-rw-r--r--src/mesa/main/texgetimage.c4
-rw-r--r--src/mesa/main/teximage.c42
-rw-r--r--src/mesa/main/texparam.c200
-rw-r--r--src/mesa/main/uniforms.c55
-rw-r--r--src/mesa/main/varray.c68
-rw-r--r--src/mesa/program/ir_to_mesa.cpp214
-rw-r--r--src/mesa/program/register_allocate.c37
-rw-r--r--src/mesa/program/sampler.cpp21
-rw-r--r--src/mesa/state_tracker/st_atom_blend.c19
-rw-r--r--src/mesa/state_tracker/st_atom_framebuffer.c6
-rw-r--r--src/mesa/state_tracker/st_atom_pixeltransfer.c2
-rw-r--r--src/mesa/state_tracker/st_atom_rasterizer.c14
-rw-r--r--src/mesa/state_tracker/st_atom_sampler.c46
-rw-r--r--src/mesa/state_tracker/st_atom_viewport.c4
-rw-r--r--src/mesa/state_tracker/st_cb_accum.c17
-rw-r--r--src/mesa/state_tracker/st_cb_bitmap.c9
-rw-r--r--src/mesa/state_tracker/st_cb_bufferobjects.c33
-rw-r--r--src/mesa/state_tracker/st_cb_clear.c28
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c139
-rw-r--r--src/mesa/state_tracker/st_cb_drawtex.c5
-rw-r--r--src/mesa/state_tracker/st_cb_fbo.c33
-rw-r--r--src/mesa/state_tracker/st_cb_readpixels.c20
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c316
-rw-r--r--src/mesa/state_tracker/st_context.c7
-rw-r--r--src/mesa/state_tracker/st_context.h5
-rw-r--r--src/mesa/state_tracker/st_draw.c342
-rw-r--r--src/mesa/state_tracker/st_draw_feedback.c19
-rw-r--r--src/mesa/state_tracker/st_extensions.c22
-rw-r--r--src/mesa/state_tracker/st_format.c70
-rw-r--r--src/mesa/state_tracker/st_format.h6
-rw-r--r--src/mesa/state_tracker/st_gen_mipmap.c25
-rw-r--r--src/mesa/state_tracker/st_manager.c15
-rw-r--r--src/mesa/state_tracker/st_mesa_to_tgsi.c24
-rw-r--r--src/mesa/state_tracker/st_program.c15
-rw-r--r--src/mesa/state_tracker/st_texture.c94
-rw-r--r--src/mesa/state_tracker/st_texture.h16
-rw-r--r--src/mesa/swrast/s_trispan.h31
-rw-r--r--src/mesa/tnl/t_draw.c40
-rw-r--r--src/mesa/vbo/vbo.h2
-rw-r--r--src/mesa/vbo/vbo_exec.h10
-rw-r--r--src/mesa/vbo/vbo_exec_api.c192
-rw-r--r--src/mesa/vbo/vbo_exec_array.c47
-rw-r--r--src/mesa/vbo/vbo_exec_draw.c26
-rw-r--r--src/mesa/vbo/vbo_save_api.c6
-rw-r--r--src/mesa/vbo/vbo_save_draw.c1
-rw-r--r--src/mesa/x86-64/xform4.S14
-rw-r--r--src/mesa/x86/read_rgba_span_x86.S10
-rw-r--r--src/talloc/SConscript20
-rw-r--r--src/talloc/gpl-3.0.txt674
-rw-r--r--src/talloc/lgpl-3.0.txt165
-rw-r--r--src/talloc/talloc.c2034
-rw-r--r--src/talloc/talloc.def63
-rw-r--r--src/talloc/talloc.h202
-rw-r--r--src/talloc/talloc_guide.txt757
660 files changed, 25415 insertions, 18482 deletions
diff --git a/src/SConscript b/src/SConscript
index 201812c5ac3..f11894f2990 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -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')
diff --git a/src/egl/Makefile b/src/egl/Makefile
index 50f227f07da..52daf2efa7e 100644
--- a/src/egl/Makefile
+++ b/src/egl/Makefile
@@ -5,6 +5,10 @@ include $(TOP)/configs/current
SUBDIRS = drivers main
+ifneq ($(findstring wayland, $(EGL_PLATFORMS)),)
+SUBDIRS += wayland
+endif
+
default: subdirs
diff --git a/src/egl/drivers/dri2/Makefile b/src/egl/drivers/dri2/Makefile
index 553ee8771f8..89e9dd7970a 100644
--- a/src/egl/drivers/dri2/Makefile
+++ b/src/egl/drivers/dri2/Makefile
@@ -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
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 6fc1e49e773..99f87f076c1 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -36,93 +36,12 @@
#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().
*/
@@ -1907,33 +746,6 @@ dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine)
}
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)
{
@@ -2009,94 +821,6 @@ dri2_release_tex_image(_EGLDriver *drv,
}
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,
const EGLint *attr_list)
@@ -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
index 00000000000..235e30df3d8
--- /dev/null
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -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 <[email protected]>
+ */
+
+#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
index 00000000000..3dab899decb
--- /dev/null
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -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 <[email protected]>
+ */
+
+#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
index 00000000000..21b440624ff
--- /dev/null
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -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 <[email protected]>
+ * Benjamin Franzke <[email protected]>
+ */
+
+#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
index 00000000000..50310eec5a9
--- /dev/null
+++ b/src/egl/drivers/dri2/platform_x11.c
@@ -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 <[email protected]>
+ */
+
+#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;
+}
+
diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile
index c710631688c..a5b92995020 100644
--- a/src/egl/main/Makefile
+++ b/src/egl/main/Makefile
@@ -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
diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c
index 565e44d2d23..30592947297 100644
--- a/src/egl/main/egldisplay.c
+++ b/src/egl/main/egldisplay.c
@@ -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" }
};
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index dbc5d32d910..ce035eb2ef1 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -11,6 +11,7 @@
enum _egl_platform_type {
_EGL_PLATFORM_WINDOWS,
_EGL_PLATFORM_X11,
+ _EGL_PLATFORM_WAYLAND,
_EGL_PLATFORM_DRM,
_EGL_PLATFORM_FBDEV,
diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c
index e133c220f5c..b75e8b6a2cb 100644
--- a/src/egl/main/egldriver.c
+++ b/src/egl/main/egldriver.c
@@ -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
index 00000000000..4cd036519db
--- /dev/null
+++ b/src/egl/wayland/Makefile
@@ -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
index 00000000000..38b21c25be2
--- /dev/null
+++ b/src/egl/wayland/wayland-egl-priv.h
@@ -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
index 00000000000..12fbdfa29c1
--- /dev/null
+++ b/src/egl/wayland/wayland-egl.c
@@ -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
index 00000000000..3c2067c2a77
--- /dev/null
+++ b/src/egl/wayland/wayland-egl.pc.in
@@ -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@
diff --git a/src/gallium/SConscript b/src/gallium/SConscript
index 2265f1de46c..31580556f03 100644
--- a/src/gallium/SConscript
+++ b/src/gallium/SConscript
@@ -42,6 +42,7 @@ if env['drm']:
# SConscript([
# 'drivers/nouveau/SConscript',
# 'drivers/nv50/SConscript',
+ # 'drivers/nvc0/SConscript',
# 'drivers/nvfx/SConscript',
# ])
diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile
index 6cf1ddd43fe..e40f546929d 100644
--- a/src/gallium/auxiliary/Makefile
+++ b/src/gallium/auxiliary/Makefile
@@ -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 \
diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript
index e6806d9a723..11024d41923 100644
--- a/src/gallium/auxiliary/SConscript
+++ b/src/gallium/auxiliary/SConscript
@@ -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']:
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c
index 58b022d531d..fdd40fca126 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.c
+++ b/src/gallium/auxiliary/cso_cache/cso_context.c
@@ -47,41 +47,45 @@
#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);
}
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h
index f0b07f73765..00edc9f8dd4 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.h
+++ b/src/gallium/auxiliary/cso_cache/cso_context.h
@@ -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
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index e045313b94f..95d96719873 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -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);
}
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index 0c51aa85b37..a5217c1d4ec 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -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");
diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h
index 9f038f1f04d..e8623e7bcdc 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.h
+++ b/src/gallium/auxiliary/draw/draw_llvm.h
@@ -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
diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c
index 6206197dae9..f1b0171f520 100644
--- a/src/gallium/auxiliary/draw/draw_pipe.c
+++ b/src/gallium/auxiliary/draw/draw_pipe.c
@@ -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;
diff --git a/src/gallium/auxiliary/draw/draw_pipe_aaline.c b/src/gallium/auxiliary/draw/draw_pipe_aaline.c
index 0851b9acc0d..32af29ae144 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_aaline.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_aaline.c
@@ -55,9 +55,16 @@
/**
+ * 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)
diff --git a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c
index f5515c1df76..ea62c9739fd 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c
@@ -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);
}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_validate.c b/src/gallium/auxiliary/draw/draw_pipe_validate.c
index c575a8ac7ca..27afba5af3d 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_validate.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_validate.c
@@ -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)? */
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 06ed4d60ef2..db2e3c5410d 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -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];
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index 4078b2a07d0..c3d7e871f7a 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -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]);
}
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c b/src/gallium/auxiliary/draw/draw_pt_fetch.c
index ae12ee24bdc..4fa3b265e10 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c
@@ -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,
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
index e706b7796f8..51043102a61 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
@@ -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 /
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
index c98fb3d5205..1e926fb028e 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
@@ -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 /
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.c b/src/gallium/auxiliary/gallivm/lp_bld_conv.c
index c43ee8ac638..c261d761161 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_conv.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.c
@@ -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;
}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.c b/src/gallium/auxiliary/gallivm/lp_bld_init.c
index 7504cb5cf2f..45addee8fab 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_init.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_init.c
@@ -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
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
index 2ef02160f23..960068c494d 100644
--- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
@@ -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 );
};
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c
index a6eb4039621..25accefa8d6 100644
--- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c
@@ -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;
}
diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c
index 75b0f6a68ea..b03dd3a0cf8 100644
--- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c
+++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c
@@ -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 */
}
}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c
index 16a205f2068..d2cb98e84af 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_build.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_build.c
@@ -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;
}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c
index 82cd8eaa969..c12662076b1 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_dump.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c
@@ -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)
{
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
index 35b27423513..cbb090b2803 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -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 );
}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h
index 6c204c73714..4a423b5bb4e 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h
@@ -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 *
diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c
index e59e964ffa7..14ed56a1f6a 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_info.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_info.c
@@ -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 *
diff --git a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
index b3123ed016d..b5d4504425b 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
@@ -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
diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.c b/src/gallium/auxiliary/tgsi/tgsi_parse.c
index 1891203abe1..fb36f9de32d 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_parse.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_parse.c
@@ -128,6 +128,10 @@ tgsi_parse_token(
}
}
+ if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
+ next_token(ctx, &decl->Resource);
+ }
+
break;
}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.h b/src/gallium/auxiliary/tgsi/tgsi_parse.h
index 2aafa2a6e83..b7a3c9bc0e6 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_parse.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_parse.h
@@ -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
{
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.c b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
index acbff103efe..509c5346837 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_sanity.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
@@ -258,7 +258,8 @@ static const char *file_names[TGSI_FILE_COUNT] =
"PRED",
"SV",
"IMMX",
- "TEMPX"
+ "TEMPX",
+ "RES"
};
static boolean
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/tgsi_sse2.c
index 3f2cda860e0..92ba8b8f033 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_sse2.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.c
@@ -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:
diff --git a/src/gallium/auxiliary/tgsi/tgsi_text.c b/src/gallium/auxiliary/tgsi/tgsi_text.c
index 819b0725a1f..1eac762e6e5 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_text.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_text.c
@@ -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) {
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
index 02de12d77d5..4564ab81f99 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
@@ -1,6 +1,6 @@
/**************************************************************************
*
- * Copyright 2009 VMware, Inc.
+ * Copyright 2009-2010 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -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;
@@ -1206,6 +1253,36 @@ emit_decl_range2D(struct ureg_program *ureg,
}
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,
unsigned type )
@@ -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,
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
index 807128a5e52..b8d193f3f89 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
@@ -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:
*/
diff --git a/src/gallium/auxiliary/tgsi/tgsi_util.c b/src/gallium/auxiliary/tgsi/tgsi_util.c
index 08e7e89bd67..aa9a886d4a9 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_util.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_util.c
@@ -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;
diff --git a/src/gallium/auxiliary/translate/translate_cache.c b/src/gallium/auxiliary/translate/translate_cache.c
index d8069a149cf..3f1ecb630f2 100644
--- a/src/gallium/auxiliary/translate/translate_cache.c
+++ b/src/gallium/auxiliary/translate/translate_cache.c
@@ -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
index 00000000000..bc7c53cf9f2
--- /dev/null
+++ b/src/gallium/auxiliary/util/dbghelp.h
@@ -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
diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c
index c11f7d383db..76bd7ace526 100644
--- a/src/gallium/auxiliary/util/u_blit.c
+++ b/src/gallium/auxiliary/util/u_blit.c
@@ -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);
}
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index 545021d2642..fd1c2b72d04 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -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);
-}
diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h
index 922a8580ac1..41470d92bba 100644
--- a/src/gallium/auxiliary/util/u_blitter.h
+++ b/src/gallium/auxiliary/util/u_blitter.h
@@ -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,
diff --git a/src/gallium/auxiliary/util/u_debug.c b/src/gallium/auxiliary/util/u_debug.c
index f4ad545bee7..36ce4b57713 100644
--- a/src/gallium/auxiliary/util/u_debug.c
+++ b/src/gallium/auxiliary/util/u_debug.c
@@ -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
/**
diff --git a/src/gallium/auxiliary/util/u_debug.h b/src/gallium/auxiliary/util/u_debug.h
index 1c9624ea3ed..c47c13c64cf 100644
--- a/src/gallium/auxiliary/util/u_debug.h
+++ b/src/gallium/auxiliary/util/u_debug.h
@@ -280,6 +280,43 @@ debug_dump_flags(const struct debug_named_value *names,
/**
+ * 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.
*
* It is an alias for getenv on Linux.
diff --git a/src/gallium/auxiliary/util/u_debug_refcnt.c b/src/gallium/auxiliary/util/u_debug_refcnt.c
index 40a26c9c697..6f706a35fda 100644
--- a/src/gallium/auxiliary/util/u_debug_refcnt.c
+++ b/src/gallium/auxiliary/util/u_debug_refcnt.c
@@ -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);
diff --git a/src/gallium/auxiliary/util/u_debug_symbol.c b/src/gallium/auxiliary/util/u_debug_symbol.c
index 44d437747a1..bae9be87a26 100644
--- a/src/gallium/auxiliary/util/u_debug_symbol.c
+++ b/src/gallium/auxiliary/util/u_debug_symbol.c
@@ -40,20 +40,43 @@
#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);
diff --git a/src/gallium/auxiliary/util/u_draw_quad.c b/src/gallium/auxiliary/util/u_draw_quad.c
index 0b6dc5880f3..0defd919974 100644
--- a/src/gallium/auxiliary/util/u_draw_quad.c
+++ b/src/gallium/auxiliary/util/u_draw_quad.c
@@ -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)
diff --git a/src/gallium/auxiliary/util/u_draw_quad.h b/src/gallium/auxiliary/util/u_draw_quad.h
index 52994fe05c3..f1167786f0e 100644
--- a/src/gallium/auxiliary/util/u_draw_quad.h
+++ b/src/gallium/auxiliary/util/u_draw_quad.h
@@ -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);
diff --git a/src/gallium/auxiliary/util/u_dump_state.c b/src/gallium/auxiliary/util/u_dump_state.c
index b471d59eebf..5ecf8cbb067 100644
--- a/src/gallium/auxiliary/util/u_dump_state.c
+++ b/src/gallium/auxiliary/util/u_dump_state.c
@@ -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);
diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h
index 03b73c0e98f..7659a802a41 100644
--- a/src/gallium/auxiliary/util/u_format.h
+++ b/src/gallium/auxiliary/util/u_format.h
@@ -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)
@@ -711,6 +712,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).
*/
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c
index d22ae8b375b..3b6342ad8d1 100644
--- a/src/gallium/auxiliary/util/u_gen_mipmap.c
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.c
@@ -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,
diff --git a/src/gallium/auxiliary/util/u_index_modify.c b/src/gallium/auxiliary/util/u_index_modify.c
index f2c9db3caf1..d0a28b5fdfa 100644
--- a/src/gallium/auxiliary/util/u_index_modify.c
+++ b/src/gallium/auxiliary/util/u_index_modify.c
@@ -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,
diff --git a/src/gallium/auxiliary/util/u_inlines.h b/src/gallium/auxiliary/util/u_inlines.h
index b4870bce981..98889fb70ac 100644
--- a/src/gallium/auxiliary/util/u_inlines.h
+++ b/src/gallium/auxiliary/util/u_inlines.h
@@ -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;
}
diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h
index 37294b7203f..30555f92a6d 100644
--- a/src/gallium/auxiliary/util/u_math.h
+++ b/src/gallium/auxiliary/util/u_math.h
@@ -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 */
diff --git a/src/gallium/auxiliary/util/u_resource.c b/src/gallium/auxiliary/util/u_resource.c
index 443c9f8067e..ea6896b430f 100644
--- a/src/gallium/auxiliary/util/u_resource.c
+++ b/src/gallium/auxiliary/util/u_resource.c
@@ -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);
diff --git a/src/gallium/auxiliary/util/u_tile.c b/src/gallium/auxiliary/util/u_tile.c
index 44cadbfcdd0..e3c7085ba92 100644
--- a/src/gallium/auxiliary/util/u_tile.c
+++ b/src/gallium/auxiliary/util/u_tile.c
@@ -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;
- }
}
@@ -465,9 +408,19 @@ pipe_put_tile_rgba(struct pipe_context *pipe,
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;
diff --git a/src/gallium/auxiliary/util/u_tile.h b/src/gallium/auxiliary/util/u_tile.h
index 558351d0ce5..0ba274308fe 100644
--- a/src/gallium/auxiliary/util/u_tile.h
+++ b/src/gallium/auxiliary/util/u_tile.h
@@ -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,
diff --git a/src/gallium/auxiliary/util/u_transfer.c b/src/gallium/auxiliary/util/u_transfer.c
index e2828cfd99e..b6c63d9642f 100644
--- a/src/gallium/auxiliary/util/u_transfer.c
+++ b/src/gallium/auxiliary/util/u_transfer.c
@@ -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);
+}
diff --git a/src/gallium/auxiliary/util/u_transfer.h b/src/gallium/auxiliary/util/u_transfer.h
index 3412e13c3cc..8cf9c418b04 100644
--- a/src/gallium/auxiliary/util/u_transfer.h
+++ b/src/gallium/auxiliary/util/u_transfer.h
@@ -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
diff --git a/src/gallium/auxiliary/util/u_upload_mgr.c b/src/gallium/auxiliary/util/u_upload_mgr.c
index 3b3d5b418fe..dcf800a1e8e 100644
--- a/src/gallium/auxiliary/util/u_upload_mgr.c
+++ b/src/gallium/auxiliary/util/u_upload_mgr.c
@@ -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
index 00000000000..dec8dd717e8
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_vbuf_mgr.c
@@ -0,0 +1,601 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Marek Olšák <[email protected]>
+ * 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
index 00000000000..8b241854c83
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_vbuf_mgr.h
@@ -0,0 +1,121 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Marek Olšák <[email protected]>
+ * 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
diff --git a/src/gallium/auxiliary/vl/vl_compositor.c b/src/gallium/auxiliary/vl/vl_compositor.c
index d7b29497ace..d1ba5faf788 100644
--- a/src/gallium/auxiliary/vl/vl_compositor.c
+++ b/src/gallium/auxiliary/vl/vl_compositor.c
@@ -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)
);
diff --git a/src/gallium/auxiliary/vl/vl_idct.c b/src/gallium/auxiliary/vl/vl_idct.c
index 5d472f93481..89463a5c75c 100644
--- a/src/gallium/auxiliary/vl/vl_idct.c
+++ b/src/gallium/auxiliary/vl/vl_idct.c
@@ -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;
diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c
index de83b6a5338..484e781f0cb 100644
--- a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c
+++ b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c
@@ -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);
diff --git a/src/gallium/auxiliary/vl/vl_vertex_buffers.c b/src/gallium/auxiliary/vl/vl_vertex_buffers.c
index 8599ed3533d..552a0451fef 100644
--- a/src/gallium/auxiliary/vl/vl_vertex_buffers.c
+++ b/src/gallium/auxiliary/vl/vl_vertex_buffers.c
@@ -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
);
diff --git a/src/gallium/docs/d3d11ddi.txt b/src/gallium/docs/d3d11ddi.txt
index 11e77190895..0a9e7e50f1d 100644
--- a/src/gallium/docs/d3d11ddi.txt
+++ b/src/gallium/docs/d3d11ddi.txt
@@ -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
diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst
index 6760e7be4b9..c6812cd309e 100644
--- a/src/gallium/docs/source/context.rst
+++ b/src/gallium/docs/source/context.rst
@@ -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``.
diff --git a/src/gallium/docs/source/screen.rst b/src/gallium/docs/source/screen.rst
index ab90097add6..976e75bed04 100644
--- a/src/gallium/docs/source/screen.rst
+++ b/src/gallium/docs/source/screen.rst
@@ -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.
diff --git a/src/gallium/docs/source/tgsi.rst b/src/gallium/docs/source/tgsi.rst
index d986e6601e6..4debcc6ecc4 100644
--- a/src/gallium/docs/source/tgsi.rst
+++ b/src/gallium/docs/source/tgsi.rst
@@ -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
^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/gallium/drivers/cell/ppu/cell_state_vertex.c b/src/gallium/drivers/cell/ppu/cell_state_vertex.c
index eb22a09a913..7f65b82619e 100644
--- a/src/gallium/drivers/cell/ppu/cell_state_vertex.c
+++ b/src/gallium/drivers/cell/ppu/cell_state_vertex.c
@@ -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;
}
diff --git a/src/gallium/drivers/failover/fo_state.c b/src/gallium/drivers/failover/fo_state.c
index af1fd953aaf..b4da1b8b901 100644
--- a/src/gallium/drivers/failover/fo_state.c
+++ b/src/gallium/drivers/failover/fo_state.c
@@ -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;
}
diff --git a/src/gallium/drivers/galahad/glhd_context.c b/src/gallium/drivers/galahad/glhd_context.c
index 8cbf0b1de4a..75e4c253dd9 100644
--- a/src/gallium/drivers/galahad/glhd_context.c
+++ b/src/gallium/drivers/galahad/glhd_context.c
@@ -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;
diff --git a/src/gallium/drivers/i915/TODO b/src/gallium/drivers/i915/TODO
index 94c428bebf8..f4e1423fa59 100644
--- a/src/gallium/drivers/i915/TODO
+++ b/src/gallium/drivers/i915/TODO
@@ -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.
diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c
index ea3c10b5e78..707b2e9f956 100644
--- a/src/gallium/drivers/i915/i915_context.c
+++ b/src/gallium/drivers/i915/i915_context.c
@@ -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;
@@ -64,14 +66,6 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
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
*/
if (info->indexed && i915->index_buffer.buffer)
@@ -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:
*/
diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h
index b7f1fb22221..2cf53424f06 100644
--- a/src/gallium/drivers/i915/i915_context.h
+++ b/src/gallium/drivers/i915/i915_context.h
@@ -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;
};
diff --git a/src/gallium/drivers/i915/i915_debug.c b/src/gallium/drivers/i915/i915_debug.c
index 845e92cf5c6..1713bf131f2 100644
--- a/src/gallium/drivers/i915/i915_debug.c
+++ b/src/gallium/drivers/i915/i915_debug.c
@@ -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();
}
diff --git a/src/gallium/drivers/i915/i915_debug.h b/src/gallium/drivers/i915/i915_debug.h
index 11af7662f0a..fa60799d0c5 100644
--- a/src/gallium/drivers/i915/i915_debug.h
+++ b/src/gallium/drivers/i915/i915_debug.h
@@ -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
diff --git a/src/gallium/drivers/i915/i915_flush.c b/src/gallium/drivers/i915/i915_flush.c
index a2c70b11991..911c051d1f2 100644
--- a/src/gallium/drivers/i915/i915_flush.c
+++ b/src/gallium/drivers/i915/i915_flush.c
@@ -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;
}
diff --git a/src/gallium/drivers/i915/i915_resource_texture.c b/src/gallium/drivers/i915/i915_resource_texture.c
index e793d126ade..aad5235a6ad 100644
--- a/src/gallium/drivers/i915/i915_resource_texture.c
+++ b/src/gallium/drivers/i915/i915_resource_texture.c
@@ -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;
diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c
index bdbc08e8086..77febbf5012 100644
--- a/src/gallium/drivers/i915/i915_screen.c
+++ b/src/gallium/drivers/i915/i915_screen.c
@@ -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;
}
}
@@ -321,6 +344,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)
{
struct i915_screen *is = i915_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;
diff --git a/src/gallium/drivers/i915/i915_screen.h b/src/gallium/drivers/i915/i915_screen.h
index bb4d255a3b3..60f0e2971e0 100644
--- a/src/gallium/drivers/i915/i915_screen.h
+++ b/src/gallium/drivers/i915/i915_screen.h
@@ -45,6 +45,11 @@ struct i915_screen
struct i915_winsys *iws;
boolean is_i945;
+
+ struct {
+ boolean tiling;
+ boolean lie;
+ } debug;
};
diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c
index 4a1a4a04f6d..58bbbd1de2c 100644
--- a/src/gallium/drivers/i915/i915_state.c
+++ b/src/gallium/drivers/i915/i915_state.c
@@ -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;
}
diff --git a/src/gallium/drivers/i915/i915_state_dynamic.c b/src/gallium/drivers/i915/i915_state_dynamic.c
index d61a8c3407f..204cee6fe9e 100644
--- a/src/gallium/drivers/i915/i915_state_dynamic.c
+++ b/src/gallium/drivers/i915/i915_state_dynamic.c
@@ -46,18 +46,34 @@
* (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 = {
diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c
index 5a89977c26c..509d487b498 100644
--- a/src/gallium/drivers/i915/i915_state_emit.c
+++ b/src/gallium/drivers/i915/i915_state_emit.c
@@ -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;
}
diff --git a/src/gallium/drivers/i915/i915_state_immediate.c b/src/gallium/drivers/i915/i915_state_immediate.c
index f9ade7077f2..81348647399 100644
--- a/src/gallium/drivers/i915/i915_state_immediate.c
+++ b/src/gallium/drivers/i915/i915_state_immediate.c
@@ -36,12 +36,20 @@
#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 = {
diff --git a/src/gallium/drivers/i915/i915_winsys.h b/src/gallium/drivers/i915/i915_winsys.h
index 24ea416f015..e915a886c9b 100644
--- a/src/gallium/drivers/i915/i915_winsys.h
+++ b/src/gallium/drivers/i915/i915_winsys.h
@@ -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.
diff --git a/src/gallium/drivers/i965/brw_pipe_vertex.c b/src/gallium/drivers/i965/brw_pipe_vertex.c
index b23454b5808..570ea23ff45 100644
--- a/src/gallium/drivers/i965/brw_pipe_vertex.c
+++ b/src/gallium/drivers/i965/brw_pipe_vertex.c
@@ -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;
}
diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c
index 3efbd6a246d..b533abe24c6 100644
--- a/src/gallium/drivers/identity/id_context.c
+++ b/src/gallium/drivers/identity/id_context.c
@@ -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;
diff --git a/src/gallium/drivers/llvmpipe/SConscript b/src/gallium/drivers/llvmpipe/SConscript
index 26b258b9569..c10a8cbc12c 100644
--- a/src/gallium/drivers/llvmpipe/SConscript
+++ b/src/gallium/drivers/llvmpipe/SConscript
@@ -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')
diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c
index 85e3cdec82c..849db06acdf 100644
--- a/src/gallium/drivers/llvmpipe/lp_flush.c
+++ b/src/gallium/drivers/llvmpipe/lp_flush.c
@@ -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) {
diff --git a/src/gallium/drivers/llvmpipe/lp_state_vertex.c b/src/gallium/drivers/llvmpipe/lp_state_vertex.c
index fffdeb6ccde..be86f66de91 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_vertex.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_vertex.c
@@ -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;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_test_main.c b/src/gallium/drivers/llvmpipe/lp_test_main.c
index 149ee6f1256..d229c620310 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_main.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_main.c
@@ -35,24 +35,13 @@
#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)
diff --git a/src/gallium/drivers/noop/noop_state.c b/src/gallium/drivers/noop/noop_state.c
index ad324774c03..00a4c1eb01e 100644
--- a/src/gallium/drivers/noop/noop_state.c
+++ b/src/gallium/drivers/noop/noop_state.c
@@ -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;
}
diff --git a/src/gallium/drivers/nv50/nv50_pc_optimize.c b/src/gallium/drivers/nv50/nv50_pc_optimize.c
index 27eb3817bf1..679e5ea1485 100644
--- a/src/gallium/drivers/nv50/nv50_pc_optimize.c
+++ b/src/gallium/drivers/nv50/nv50_pc_optimize.c
@@ -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
diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c
index 53f94820ce0..f3418df8381 100644
--- a/src/gallium/drivers/nv50/nv50_query.c
+++ b/src/gallium/drivers/nv50/nv50_query.c
@@ -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,
diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c
index b4eda0f617d..ba2c3e8c281 100644
--- a/src/gallium/drivers/nv50/nv50_state.c
+++ b/src/gallium/drivers/nv50/nv50_state.c
@@ -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;
}
diff --git a/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c b/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c
index d6b80c3ea79..ce9300ad8fd 100644
--- a/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c
+++ b/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c
@@ -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];
diff --git a/src/gallium/drivers/nvc0/nvc0_3d.xml.h b/src/gallium/drivers/nvc0/nvc0_3d.xml.h
index 61932ff2b6a..73a605f94e1 100644
--- a/src/gallium/drivers/nvc0/nvc0_3d.xml.h
+++ b/src/gallium/drivers/nvc0/nvc0_3d.xml.h
@@ -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
diff --git a/src/gallium/drivers/nvc0/nvc0_buffer.c b/src/gallium/drivers/nvc0/nvc0_buffer.c
index ea3e642a448..aa949bdfa36 100644
--- a/src/gallium/drivers/nvc0/nvc0_buffer.c
+++ b/src/gallium/drivers/nvc0/nvc0_buffer.c
@@ -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);
}
}
diff --git a/src/gallium/drivers/nvc0/nvc0_context.c b/src/gallium/drivers/nvc0/nvc0_context.c
index 2118abb5d5d..f02de4d044a 100644
--- a/src/gallium/drivers/nvc0/nvc0_context.c
+++ b/src/gallium/drivers/nvc0/nvc0_context.c
@@ -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);
diff --git a/src/gallium/drivers/nvc0/nvc0_context.h b/src/gallium/drivers/nvc0/nvc0_context.h
index 94117988e50..1ce5554f7b7 100644
--- a/src/gallium/drivers/nvc0/nvc0_context.h
+++ b/src/gallium/drivers/nvc0/nvc0_context.h
@@ -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 *);
diff --git a/src/gallium/drivers/nvc0/nvc0_fence.c b/src/gallium/drivers/nvc0/nvc0_fence.c
index 9d2c48cf14d..f2d4b1451bf 100644
--- a/src/gallium/drivers/nvc0/nvc0_fence.c
+++ b/src/gallium/drivers/nvc0/nvc0_fence.c
@@ -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);
}
diff --git a/src/gallium/drivers/nvc0/nvc0_fence.h b/src/gallium/drivers/nvc0/nvc0_fence.h
index e63c164bda4..3d8c3f8ba60 100644
--- a/src/gallium/drivers/nvc0/nvc0_fence.h
+++ b/src/gallium/drivers/nvc0/nvc0_fence.h
@@ -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;
diff --git a/src/gallium/drivers/nvc0/nvc0_miptree.c b/src/gallium/drivers/nvc0/nvc0_miptree.c
index 7c7e134146e..ea3ed9e0225 100644
--- a/src/gallium/drivers/nvc0/nvc0_miptree.c
+++ b/src/gallium/drivers/nvc0/nvc0_miptree.c
@@ -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;
diff --git a/src/gallium/drivers/nvc0/nvc0_mm.c b/src/gallium/drivers/nvc0/nvc0_mm.c
index 0629dad19c9..516d2e31b55 100644
--- a/src/gallium/drivers/nvc0/nvc0_mm.c
+++ b/src/gallium/drivers/nvc0/nvc0_mm.c
@@ -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];
}
diff --git a/src/gallium/drivers/nvc0/nvc0_pc.c b/src/gallium/drivers/nvc0/nvc0_pc.c
index 304a1919768..f51d289e8cd 100644
--- a/src/gallium/drivers/nvc0/nvc0_pc.c
+++ b/src/gallium/drivers/nvc0/nvc0_pc.c
@@ -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
diff --git a/src/gallium/drivers/nvc0/nvc0_pc.h b/src/gallium/drivers/nvc0/nvc0_pc.h
index 969cc68c596..efa073a9201 100644
--- a/src/gallium/drivers/nvc0/nvc0_pc.h
+++ b/src/gallium/drivers/nvc0/nvc0_pc.h
@@ -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.
*/
@@ -204,6 +205,10 @@
#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;
diff --git a/src/gallium/drivers/nvc0/nvc0_pc_emit.c b/src/gallium/drivers/nvc0/nvc0_pc_emit.c
index db8055d91cd..c10f920e6f1 100644
--- a/src/gallium/drivers/nvc0/nvc0_pc_emit.c
+++ b/src/gallium/drivers/nvc0/nvc0_pc_emit.c
@@ -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);
@@ -808,6 +818,15 @@ emit_ld_const(struct nv_pc *pc, struct nv_instruction *i)
}
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)
{
if (SFILE(i, 0) >= NV_FILE_MEM_C(0) &&
@@ -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
diff --git a/src/gallium/drivers/nvc0/nvc0_pc_optimize.c b/src/gallium/drivers/nvc0/nvc0_pc_optimize.c
index acc72bff14c..c5a7367a5fd 100644
--- a/src/gallium/drivers/nvc0/nvc0_pc_optimize.c
+++ b/src/gallium/drivers/nvc0/nvc0_pc_optimize.c
@@ -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;
diff --git a/src/gallium/drivers/nvc0/nvc0_pc_print.c b/src/gallium/drivers/nvc0/nvc0_pc_print.c
index b03826484e4..90c669cc4b8 100644
--- a/src/gallium/drivers/nvc0/nvc0_pc_print.c
+++ b/src/gallium/drivers/nvc0/nvc0_pc_print.c
@@ -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 },
diff --git a/src/gallium/drivers/nvc0/nvc0_pc_regalloc.c b/src/gallium/drivers/nvc0/nvc0_pc_regalloc.c
index d24f09a1507..f4afe083e2d 100644
--- a/src/gallium/drivers/nvc0/nvc0_pc_regalloc.c
+++ b/src/gallium/drivers/nvc0/nvc0_pc_regalloc.c
@@ -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;
diff --git a/src/gallium/drivers/nvc0/nvc0_program.c b/src/gallium/drivers/nvc0/nvc0_program.c
index aefaf7b98ad..899fe147c6a 100644
--- a/src/gallium/drivers/nvc0/nvc0_program.c
+++ b/src/gallium/drivers/nvc0/nvc0_program.c
@@ -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;
}
diff --git a/src/gallium/drivers/nvc0/nvc0_program.h b/src/gallium/drivers/nvc0/nvc0_program.h
index e6b210d1355..f6fea29780b 100644
--- a/src/gallium/drivers/nvc0/nvc0_program.h
+++ b/src/gallium/drivers/nvc0/nvc0_program.h
@@ -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;
diff --git a/src/gallium/drivers/nvc0/nvc0_push.c b/src/gallium/drivers/nvc0/nvc0_push.c
index 74c3451c19a..fcbb7da41a3 100644
--- a/src/gallium/drivers/nvc0/nvc0_push.c
+++ b/src/gallium/drivers/nvc0/nvc0_push.c
@@ -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);
diff --git a/src/gallium/drivers/nvc0/nvc0_query.c b/src/gallium/drivers/nvc0/nvc0_query.c
index cc83fbe771c..e5e43c0e7a5 100644
--- a/src/gallium/drivers/nvc0/nvc0_query.c
+++ b/src/gallium/drivers/nvc0/nvc0_query.c
@@ -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);
diff --git a/src/gallium/drivers/nvc0/nvc0_resource.h b/src/gallium/drivers/nvc0/nvc0_resource.h
index 17e79642a6d..599823c0dc9 100644
--- a/src/gallium/drivers/nvc0/nvc0_resource.h
+++ b/src/gallium/drivers/nvc0/nvc0_resource.h
@@ -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) ||
diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c
index f608b32e1cb..f7f1fd09a12 100644
--- a/src/gallium/drivers/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nvc0/nvc0_screen.c
@@ -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
diff --git a/src/gallium/drivers/nvc0/nvc0_screen.h b/src/gallium/drivers/nvc0/nvc0_screen.h
index 1fac142e2be..d952ff1f9b1 100644
--- a/src/gallium/drivers/nvc0/nvc0_screen.h
+++ b/src/gallium/drivers/nvc0/nvc0_screen.h
@@ -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)
diff --git a/src/gallium/drivers/nvc0/nvc0_shader_state.c b/src/gallium/drivers/nvc0/nvc0_shader_state.c
index 981b5488d08..357f8b80deb 100644
--- a/src/gallium/drivers/nvc0/nvc0_shader_state.c
+++ b/src/gallium/drivers/nvc0/nvc0_shader_state.c
@@ -27,6 +27,16 @@
#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);
+}
diff --git a/src/gallium/drivers/nvc0/nvc0_state.c b/src/gallium/drivers/nvc0/nvc0_state.c
index c08f3693f5e..aa437195764 100644
--- a/src/gallium/drivers/nvc0/nvc0_state.c
+++ b/src/gallium/drivers/nvc0/nvc0_state.c
@@ -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;
}
diff --git a/src/gallium/drivers/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nvc0/nvc0_state_validate.c
index 25aec0244db..70c418fad9b 100644
--- a/src/gallium/drivers/nvc0/nvc0_state_validate.c
+++ b/src/gallium/drivers/nvc0/nvc0_state_validate.c
@@ -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);
@@ -281,6 +290,32 @@ nvc0_validate_rasterizer(struct nvc0_context *nvc0)
}
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)
{
struct nouveau_channel *chan = nvc0->screen->base.channel;
@@ -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]))
diff --git a/src/gallium/drivers/nvc0/nvc0_stateobj.h b/src/gallium/drivers/nvc0/nvc0_stateobj.h
index 6c8028aba13..57566128ab5 100644
--- a/src/gallium/drivers/nvc0/nvc0_stateobj.h
+++ b/src/gallium/drivers/nvc0/nvc0_stateobj.h
@@ -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
diff --git a/src/gallium/drivers/nvc0/nvc0_surface.c b/src/gallium/drivers/nvc0/nvc0_surface.c
index cc0a65687dc..8898bc733a3 100644
--- a/src/gallium/drivers/nvc0/nvc0_surface.c
+++ b/src/gallium/drivers/nvc0/nvc0_surface.c
@@ -33,25 +33,15 @@
#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;
}
diff --git a/src/gallium/drivers/nvc0/nvc0_tex.c b/src/gallium/drivers/nvc0/nvc0_tex.c
index b219f82c903..968558a5869 100644
--- a/src/gallium/drivers/nvc0/nvc0_tex.c
+++ b/src/gallium/drivers/nvc0/nvc0_tex.c
@@ -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);
diff --git a/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c b/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c
index 950bee2eda4..a44d330c731 100644
--- a/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c
+++ b/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c
@@ -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);
@@ -979,14 +993,6 @@ bld_new_block(struct bld_context *bld, struct nv_basic_block *b)
}
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)
{
unsigned cent = mode & NVC0_INTERP_CENTROID;
@@ -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) {
diff --git a/src/gallium/drivers/nvc0/nvc0_transfer.c b/src/gallium/drivers/nvc0/nvc0_transfer.c
index 286b382f58e..b279bdc6e7d 100644
--- a/src/gallium/drivers/nvc0/nvc0_transfer.c
+++ b/src/gallium/drivers/nvc0/nvc0_transfer.c
@@ -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)
diff --git a/src/gallium/drivers/nvc0/nvc0_vbo.c b/src/gallium/drivers/nvc0/nvc0_vbo.c
index a51a887ed89..2db43d8704b 100644
--- a/src/gallium/drivers/nvc0/nvc0_vbo.c
+++ b/src/gallium/drivers/nvc0/nvc0_vbo.c
@@ -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);
}
diff --git a/src/gallium/drivers/nvc0/nvc0_winsys.h b/src/gallium/drivers/nvc0/nvc0_winsys.h
index 1544fb7a1de..45f71967eff 100644
--- a/src/gallium/drivers/nvc0/nvc0_winsys.h
+++ b/src/gallium/drivers/nvc0/nvc0_winsys.h
@@ -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);
}
diff --git a/src/gallium/drivers/nvfx/nvfx_vbo.c b/src/gallium/drivers/nvfx/nvfx_vbo.c
index 01dacb43dad..b72379d6536 100644
--- a/src/gallium/drivers/nvfx/nvfx_vbo.c
+++ b/src/gallium/drivers/nvfx/nvfx_vbo.c
@@ -2,6 +2,7 @@
#include "pipe/p_state.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
+#include "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;
}
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index a43e83c0d36..4f86db39926 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -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);
}
}
diff --git a/src/gallium/drivers/r300/r300_cb.h b/src/gallium/drivers/r300/r300_cb.h
index 9d3d4fc1b19..b373937a1f9 100644
--- a/src/gallium/drivers/r300/r300_cb.h
+++ b/src/gallium/drivers/r300/r300_cb.h
@@ -61,40 +61,52 @@
* 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.
@@ -103,13 +115,13 @@
#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) \
diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c
index 2b183f62c56..1968d0feb35 100644
--- a/src/gallium/drivers/r300/r300_chipset.c
+++ b/src/gallium/drivers/r300/r300_chipset.c
@@ -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;
}
diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h
index f2035d20092..0be161fa07a 100644
--- a/src/gallium/drivers/r300/r300_chipset.h
+++ b/src/gallium/drivers/r300/r300_chipset.h
@@ -33,6 +33,13 @@
#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
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index 91263ad7bcd..9f85bd4ce5f 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -35,26 +35,24 @@
#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);
- }
- }
-}
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index e09cf87f733..30073759476 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -30,11 +30,11 @@
#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
};
diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h
index 6726f100e1b..2e52dfa43c6 100644
--- a/src/gallium/drivers/r300/r300_cs.h
+++ b/src/gallium/drivers/r300/r300_cs.h
@@ -35,12 +35,6 @@
* 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.
*/
@@ -50,22 +44,29 @@
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)
@@ -106,27 +107,11 @@
* 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)
@@ -135,7 +120,7 @@
*/
#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)
diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c
index d6aa90bd053..b60cfd1f248 100644
--- a/src/gallium/drivers/r300/r300_debug.c
+++ b/src/gallium/drivers/r300/r300_debug.c
@@ -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
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index d14cdcbbaf0..e2e4719ec82 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -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)) {
diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c
index b250532ba92..c77cc08539d 100644
--- a/src/gallium/drivers/r300/r300_flush.c
+++ b/src/gallium/drivers/r300/r300_flush.c
@@ -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);
}
}
diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c
index 6d4091dc87d..cec7473009a 100644
--- a/src/gallium/drivers/r300/r300_fs.c
+++ b/src/gallium/drivers/r300/r300_fs.c
@@ -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;
diff --git a/src/gallium/drivers/r300/r300_hyperz.c b/src/gallium/drivers/r300/r300_hyperz.c
index c22e307c679..873e0209d42 100644
--- a/src/gallium/drivers/r300/r300_hyperz.c
+++ b/src/gallium/drivers/r300/r300_hyperz.c
@@ -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;
}
diff --git a/src/gallium/drivers/r300/r300_hyperz.h b/src/gallium/drivers/r300/r300_hyperz.h
index 30a23ec6493..d4c8e7c60a9 100644
--- a/src/gallium/drivers/r300/r300_hyperz.h
+++ b/src/gallium/drivers/r300/r300_hyperz.h
@@ -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
diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c
index 6223e043210..717485f43cb 100644
--- a/src/gallium/drivers/r300/r300_query.c
+++ b/src/gallium/drivers/r300/r300_query.c
@@ -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;
}
diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h
index d1154dee40a..1d93dab2ca2 100644
--- a/src/gallium/drivers/r300/r300_reg.h
+++ b/src/gallium/drivers/r300/r300_reg.h
@@ -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
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index b35822c82f8..2ead8667bda 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -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. */
diff --git a/src/gallium/drivers/r300/r300_render_translate.c b/src/gallium/drivers/r300/r300_render_translate.c
index c48062c8084..f8c7558f4b4 100644
--- a/src/gallium/drivers/r300/r300_render_translate.c
+++ b/src/gallium/drivers/r300/r300_render_translate.c
@@ -20,207 +20,64 @@
* 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;
}
}
diff --git a/src/gallium/drivers/r300/r300_resource.c b/src/gallium/drivers/r300/r300_resource.c
index dd1df970594..f3d8c5b889f 100644
--- a/src/gallium/drivers/r300/r300_resource.c
+++ b/src/gallium/drivers/r300/r300_resource.c
@@ -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;
}
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
index c75aeaa10a7..77a9c6ad86f 100644
--- a/src/gallium/drivers/r300/r300_screen.c
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -34,10 +34,6 @@
#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;
}
diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h
index 752f53b7579..576f9c1f4a9 100644
--- a/src/gallium/drivers/r300/r300_screen.h
+++ b/src/gallium/drivers/r300/r300_screen.h
@@ -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)
/*@}*/
diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c
index cc3c1d7687e..1045911f3ae 100644
--- a/src/gallium/drivers/r300/r300_screen_buffer.c
+++ b/src/gallium/drivers/r300/r300_screen_buffer.c
@@ -34,117 +34,50 @@
#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;
}
diff --git a/src/gallium/drivers/r300/r300_screen_buffer.h b/src/gallium/drivers/r300/r300_screen_buffer.h
index 58dec8539b6..14bee460d5b 100644
--- a/src/gallium/drivers/r300/r300_screen_buffer.h
+++ b/src/gallium/drivers/r300/r300_screen_buffer.h
@@ -35,39 +35,12 @@
#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
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index 3a97b76a4c8..09f18b3e624 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -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;
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index 95be7849f8f..003fe9a58cd 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -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);
}
diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h
index 7e501221b1f..06da04c7ad7 100644
--- a/src/gallium/drivers/r300/r300_state_inlines.h
+++ b/src/gallium/drivers/r300/r300_state_inlines.h
@@ -25,13 +25,9 @@
#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) {
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 6fdc504ed54..354144cac79 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -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;
diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h
index 0ab22f747e4..158a387478f 100644
--- a/src/gallium/drivers/r300/r300_texture.h
+++ b/src/gallium/drivers/r300/r300_texture.h
@@ -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,
diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c
index 7b1739142d4..2cfeec7d751 100644
--- a/src/gallium/drivers/r300/r300_texture_desc.c
+++ b/src/gallium/drivers/r300/r300_texture_desc.c
@@ -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);
diff --git a/src/gallium/drivers/r300/r300_texture_desc.h b/src/gallium/drivers/r300/r300_texture_desc.h
index 121d215b4cb..ce6e9643ec6 100644
--- a/src/gallium/drivers/r300/r300_texture_desc.h
+++ b/src/gallium/drivers/r300/r300_texture_desc.h
@@ -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
diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
index 15a323989b2..97ec0a1a1f2 100644
--- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c
+++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
@@ -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? */
diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.h b/src/gallium/drivers/r300/r300_tgsi_to_rc.h
index 97641a954b9..adb044cfe56 100644
--- a/src/gallium/drivers/r300/r300_tgsi_to_rc.h
+++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.h
@@ -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);
diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c
index ae93fab554e..30de9ec1e32 100644
--- a/src/gallium/drivers/r300/r300_transfer.c
+++ b/src/gallium/drivers/r300/r300_transfer.c
@@ -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);
}
}
diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c
index 78021e2c5d4..b319890157f 100644
--- a/src/gallium/drivers/r300/r300_vs.c
+++ b/src/gallium/drivers/r300/r300_vs.c
@@ -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;
}
diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h
index 460da77a4fb..d5c73585c81 100644
--- a/src/gallium/drivers/r300/r300_winsys.h
+++ b/src/gallium/drivers/r300/r300_winsys.h
@@ -28,38 +28,45 @@
* 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.
@@ -279,6 +271,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 */
diff --git a/src/gallium/drivers/r600/Makefile b/src/gallium/drivers/r600/Makefile
index a690b671e49..436de9c4dbd 100644
--- a/src/gallium/drivers/r600/Makefile
+++ b/src/gallium/drivers/r600/Makefile
@@ -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
diff --git a/src/gallium/drivers/r600/SConscript b/src/gallium/drivers/r600/SConscript
index e51f50c5df5..5a5fa6d65fd 100644
--- a/src/gallium/drivers/r600/SConscript
+++ b/src/gallium/drivers/r600/SConscript
@@ -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',
diff --git a/src/gallium/drivers/r600/eg_state_inlines.h b/src/gallium/drivers/r600/eg_state_inlines.h
index 5a39d7cdeec..b5fcc7106fe 100644
--- a/src/gallium/drivers/r600/eg_state_inlines.h
+++ b/src/gallium/drivers/r600/eg_state_inlines.h
@@ -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
diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index 306ca03234f..3efdbaba0c3 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -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);
+}
diff --git a/src/gallium/drivers/r600/evergreend.h b/src/gallium/drivers/r600/evergreend.h
index e09e02ca000..f0a1ee0cd02 100644
--- a/src/gallium/drivers/r600/evergreend.h
+++ b/src/gallium/drivers/r600/evergreend.h
@@ -327,6 +327,9 @@
#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
@@ -427,15 +430,6 @@
#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
@@ -939,6 +933,9 @@
#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
diff --git a/src/gallium/drivers/r600/r600.h b/src/gallium/drivers/r600/r600.h
index a852bef6156..64c52bca795 100644
--- a/src/gallium/drivers/r600/r600.h
+++ b/src/gallium/drivers/r600/r600.h
@@ -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 {
diff --git a/src/gallium/drivers/r600/r600_asm.c b/src/gallium/drivers/r600/r600_asm.c
index f4ff2fc3d43..1393df88757 100644
--- a/src/gallium/drivers/r600/r600_asm.c
+++ b/src/gallium/drivers/r600/r600_asm.c
@@ -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;
}
diff --git a/src/gallium/drivers/r600/r600_asm.h b/src/gallium/drivers/r600/r600_asm.h
index 519245f3af2..453c29790c1 100644
--- a/src/gallium/drivers/r600/r600_asm.h
+++ b/src/gallium/drivers/r600/r600_asm.h
@@ -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);
diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
index b9ec9592e35..9865ea17ae5 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -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);
+}
diff --git a/src/gallium/drivers/r600/r600_buffer.c b/src/gallium/drivers/r600/r600_buffer.c
index 469c8195fe9..0c5d7133c7a 100644
--- a/src/gallium/drivers/r600/r600_buffer.c
+++ b/src/gallium/drivers/r600/r600_buffer.c
@@ -29,85 +29,58 @@
#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;
+ }
}
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index 68b625cc3b4..34094001b75 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -30,11 +30,13 @@
#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;
}
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index 7f74fda0daf..8dc1f4ad5c3 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -30,12 +30,15 @@
#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
diff --git a/src/gallium/drivers/r600/r600_resource.h b/src/gallium/drivers/r600/r600_resource.h
index 28b3e1e5e40..836e7491f1f 100644
--- a/src/gallium/drivers/r600/r600_resource.h
+++ b/src/gallium/drivers/r600/r600_resource.h
@@ -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
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index c982471a04f..240c8f1ffd0 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -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;
diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h
index 935dd6fe3ab..8f96ce5085c 100644
--- a/src/gallium/drivers/r600/r600_shader.h
+++ b/src/gallium/drivers/r600/r600_shader.h
@@ -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
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index de2668cee16..576067ae81e 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -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);
+}
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index 3603376f738..72707fbd8b8 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -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);
+}
diff --git a/src/gallium/drivers/r600/r600_state_inlines.h b/src/gallium/drivers/r600/r600_state_inlines.h
index a0ec493fc85..3dd54f45202 100644
--- a/src/gallium/drivers/r600/r600_state_inlines.h
+++ b/src/gallium/drivers/r600/r600_state_inlines.h
@@ -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
diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c
index 1f4f453c091..03af367401d 100644
--- a/src/gallium/drivers/r600/r600_texture.c
+++ b/src/gallium/drivers/r600/r600_texture.c
@@ -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;
diff --git a/src/gallium/drivers/r600/r600_translate.c b/src/gallium/drivers/r600/r600_translate.c
index f80fa7af941..7482d15e12f 100644
--- a/src/gallium/drivers/r600/r600_translate.c
+++ b/src/gallium/drivers/r600/r600_translate.c
@@ -22,178 +22,34 @@
*
* Authors: Dave Airlie <[email protected]>
*/
-#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
index 44102ff55b6..00000000000
--- a/src/gallium/drivers/r600/r600_upload.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2010 Jerome Glisse <[email protected]>
- *
- * Permission is hereby granted, free of charge, to 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 <[email protected]>
- */
-#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;
-}
diff --git a/src/gallium/drivers/r600/r600d.h b/src/gallium/drivers/r600/r600d.h
index 8c391936db0..e8558c49a7c 100644
--- a/src/gallium/drivers/r600/r600d.h
+++ b/src/gallium/drivers/r600/r600d.h
@@ -248,6 +248,8 @@
#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)
@@ -2332,31 +2334,6 @@
#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)
diff --git a/src/gallium/drivers/rbug/rbug_context.c b/src/gallium/drivers/rbug/rbug_context.c
index 94e57e40f86..3aefb5b3bb5 100644
--- a/src/gallium/drivers/rbug/rbug_context.c
+++ b/src/gallium/drivers/rbug/rbug_context.c
@@ -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;
diff --git a/src/gallium/drivers/rbug/rbug_objects.c b/src/gallium/drivers/rbug/rbug_objects.c
index 7d7cc482ae6..15f5db40093 100644
--- a/src/gallium/drivers/rbug/rbug_objects.c
+++ b/src/gallium/drivers/rbug/rbug_objects.c
@@ -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);
}
diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c
index fe54f92addf..70fdfb7ddf3 100644
--- a/src/gallium/drivers/softpipe/sp_context.c
+++ b/src/gallium/drivers/softpipe/sp_context.c
@@ -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);
diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
index 035d712d17c..c91709aef06 100644
--- a/src/gallium/drivers/softpipe/sp_context.h
+++ b/src/gallium/drivers/softpipe/sp_context.h
@@ -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;
diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c
index d422cb17a4b..6f7addd441a 100644
--- a/src/gallium/drivers/softpipe/sp_flush.c
+++ b/src/gallium/drivers/softpipe/sp_flush.c
@@ -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++) {
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index c433405cb66..a06817c5735 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -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);
diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c
index 5d727dc00df..0ce28f4c6ee 100644
--- a/src/gallium/drivers/softpipe/sp_setup.c
+++ b/src/gallium/drivers/softpipe/sp_setup.c
@@ -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;
diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c
index 38943563800..60331bc4976 100644
--- a/src/gallium/drivers/softpipe/sp_state_sampler.c
+++ b/src/gallium/drivers/softpipe/sp_state_sampler.c
@@ -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 );
diff --git a/src/gallium/drivers/softpipe/sp_state_vertex.c b/src/gallium/drivers/softpipe/sp_state_vertex.c
index 5f4d661abde..aa0b333c7a9 100644
--- a/src/gallium/drivers/softpipe/sp_state_vertex.c
+++ b/src/gallium/drivers/softpipe/sp_state_vertex.c
@@ -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;
}
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c
index 242c27c7ebd..8a4ef934348 100644
--- a/src/gallium/drivers/softpipe/sp_tex_sample.c
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.c
@@ -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.
@@ -990,6 +1040,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],
const float t[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 )
{
@@ -1168,6 +1303,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],
const float t[QUAD_SIZE],
@@ -1215,6 +1391,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],
const float t[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;
diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c
index e42015ad498..e589ee7c841 100644
--- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c
+++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c
@@ -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;
}
diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h
index 2220955b715..9bced37990a 100644
--- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h
+++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h
@@ -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 */
};
diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c
index 509d9982b17..95374c34ec3 100644
--- a/src/gallium/drivers/softpipe/sp_texture.c
+++ b/src/gallium/drivers/softpipe/sp_texture.c
@@ -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
diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c
index 480860af63b..60870b8bee5 100644
--- a/src/gallium/drivers/softpipe/sp_tile_cache.c
+++ b/src/gallium/drivers/softpipe/sp_tile_cache.c
@@ -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);
}
}
diff --git a/src/gallium/drivers/svga/svga_context.c b/src/gallium/drivers/svga/svga_context.c
index 1e513f1039f..f0f875b2b23 100644
--- a/src/gallium/drivers/svga/svga_context.c
+++ b/src/gallium/drivers/svga/svga_context.c
@@ -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"
@@ -43,6 +44,12 @@
#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 )
{
diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h
index d4970908b1e..7b36a3606e0 100644
--- a/src/gallium/drivers/svga/svga_context.h
+++ b/src/gallium/drivers/svga/svga_context.h
@@ -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);
diff --git a/src/gallium/drivers/svga/svga_draw.c b/src/gallium/drivers/svga/svga_draw.c
index 97cbac447d6..2c873a0f7ac 100644
--- a/src/gallium/drivers/svga/svga_draw.c
+++ b/src/gallium/drivers/svga/svga_draw.c
@@ -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]);
diff --git a/src/gallium/drivers/svga/svga_draw_arrays.c b/src/gallium/drivers/svga/svga_draw_arrays.c
index be0e7abe21b..a6518042eb9 100644
--- a/src/gallium/drivers/svga/svga_draw_arrays.c
+++ b/src/gallium/drivers/svga/svga_draw_arrays.c
@@ -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;
diff --git a/src/gallium/drivers/svga/svga_draw_elements.c b/src/gallium/drivers/svga/svga_draw_elements.c
index 83527c6ef49..7d420c6b295 100644
--- a/src/gallium/drivers/svga/svga_draw_elements.c
+++ b/src/gallium/drivers/svga/svga_draw_elements.c
@@ -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;
diff --git a/src/gallium/drivers/svga/svga_pipe_blit.c b/src/gallium/drivers/svga/svga_pipe_blit.c
index 426698806c8..c87afb6946c 100644
--- a/src/gallium/drivers/svga/svga_pipe_blit.c
+++ b/src/gallium/drivers/svga/svga_pipe_blit.c
@@ -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,
diff --git a/src/gallium/drivers/svga/svga_pipe_draw.c b/src/gallium/drivers/svga/svga_pipe_draw.c
index 001ec3616c4..d98b9b0e000 100644
--- a/src/gallium/drivers/svga/svga_pipe_draw.c
+++ b/src/gallium/drivers/svga/svga_pipe_draw.c
@@ -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.
diff --git a/src/gallium/drivers/svga/svga_pipe_flush.c b/src/gallium/drivers/svga/svga_pipe_flush.c
index ab243aa6ec5..9357d827f28 100644
--- a/src/gallium/drivers/svga/svga_pipe_flush.c
+++ b/src/gallium/drivers/svga/svga_pipe_flush.c
@@ -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;
+ }
+ }
}
diff --git a/src/gallium/drivers/svga/svga_pipe_misc.c b/src/gallium/drivers/svga/svga_pipe_misc.c
index 8c24fb302f7..440919c6262 100644
--- a/src/gallium/drivers/svga/svga_pipe_misc.c
+++ b/src/gallium/drivers/svga/svga_pipe_misc.c
@@ -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
diff --git a/src/gallium/drivers/svga/svga_pipe_rasterizer.c b/src/gallium/drivers/svga/svga_pipe_rasterizer.c
index e97b4e57415..4a1a37f1765 100644
--- a/src/gallium/drivers/svga/svga_pipe_rasterizer.c
+++ b/src/gallium/drivers/svga/svga_pipe_rasterizer.c
@@ -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:
*/
diff --git a/src/gallium/drivers/svga/svga_pipe_sampler.c b/src/gallium/drivers/svga/svga_pipe_sampler.c
index f44a0e1325a..446fcc44078 100644
--- a/src/gallium/drivers/svga/svga_pipe_sampler.c
+++ b/src/gallium/drivers/svga/svga_pipe_sampler.c
@@ -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;
}
diff --git a/src/gallium/drivers/svga/svga_pipe_vertex.c b/src/gallium/drivers/svga/svga_pipe_vertex.c
index 86c79459f3e..58469910732 100644
--- a/src/gallium/drivers/svga/svga_pipe_vertex.c
+++ b/src/gallium/drivers/svga/svga_pipe_vertex.c
@@ -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"
diff --git a/src/gallium/drivers/svga/svga_resource.c b/src/gallium/drivers/svga/svga_resource.c
index ef2a0c40f03..bed15ec02e5 100644
--- a/src/gallium/drivers/svga/svga_resource.c
+++ b/src/gallium/drivers/svga/svga_resource.c
@@ -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
diff --git a/src/gallium/drivers/svga/svga_resource_buffer.c b/src/gallium/drivers/svga/svga_resource_buffer.c
index f12e2b68627..e1f07d655b9 100644
--- a/src/gallium/drivers/svga/svga_resource_buffer.c
+++ b/src/gallium/drivers/svga/svga_resource_buffer.c
@@ -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;
diff --git a/src/gallium/drivers/svga/svga_resource_buffer.h b/src/gallium/drivers/svga/svga_resource_buffer.h
index d3ec11bfd52..c559f70ec12 100644
--- a/src/gallium/drivers/svga/svga_resource_buffer.h
+++ b/src/gallium/drivers/svga/svga_resource_buffer.h
@@ -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 */
diff --git a/src/gallium/drivers/svga/svga_resource_buffer_upload.c b/src/gallium/drivers/svga/svga_resource_buffer_upload.c
index 3de5216a949..76a3803224a 100644
--- a/src/gallium/drivers/svga/svga_resource_buffer_upload.c
+++ b/src/gallium/drivers/svga/svga_resource_buffer_upload.c
@@ -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;
+}
diff --git a/src/gallium/drivers/svga/svga_resource_texture.c b/src/gallium/drivers/svga/svga_resource_texture.c
index 7c9e600b9f4..994f30719ae 100644
--- a/src/gallium/drivers/svga/svga_resource_texture.c
+++ b/src/gallium/drivers/svga/svga_resource_texture.c
@@ -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:
diff --git a/src/gallium/drivers/svga/svga_sampler_view.c b/src/gallium/drivers/svga/svga_sampler_view.c
index 6911f13f778..4f1f4b597e8 100644
--- a/src/gallium/drivers/svga/svga_sampler_view.c
+++ b/src/gallium/drivers/svga/svga_sampler_view.c
@@ -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"
@@ -41,14 +42,24 @@
#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;
}
diff --git a/src/gallium/drivers/svga/svga_sampler_view.h b/src/gallium/drivers/svga/svga_sampler_view.h
index e64665f2e58..2087c1be85e 100644
--- a/src/gallium/drivers/svga/svga_sampler_view.h
+++ b/src/gallium/drivers/svga/svga_sampler_view.h
@@ -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;
}
diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c
index d0f42c614c9..ef1d3098d51 100644
--- a/src/gallium/drivers/svga/svga_screen.c
+++ b/src/gallium/drivers/svga/svga_screen.c
@@ -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;
}
diff --git a/src/gallium/drivers/svga/svga_state.h b/src/gallium/drivers/svga/svga_state.h
index 22d5a6d552a..7f239e7a322 100644
--- a/src/gallium/drivers/svga/svga_state.h
+++ b/src/gallium/drivers/svga/svga_state.h
@@ -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
diff --git a/src/gallium/drivers/svga/svga_state_framebuffer.c b/src/gallium/drivers/svga/svga_state_framebuffer.c
index fcbb35e7972..cdadb20c178 100644
--- a/src/gallium/drivers/svga/svga_state_framebuffer.c
+++ b/src/gallium/drivers/svga/svga_state_framebuffer.c
@@ -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",
diff --git a/src/gallium/drivers/svga/svga_state_need_swtnl.c b/src/gallium/drivers/svga/svga_state_need_swtnl.c
index 8ba5ac8cdb4..68c02578789 100644
--- a/src/gallium/drivers/svga/svga_state_need_swtnl.c
+++ b/src/gallium/drivers/svga/svga_state_need_swtnl.c
@@ -35,6 +35,11 @@
/***********************************************************************
*/
+
+/**
+ * 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,
diff --git a/src/gallium/drivers/svga/svga_state_tss.c b/src/gallium/drivers/svga/svga_state_tss.c
index f8b269a101e..c502506b93b 100644
--- a/src/gallium/drivers/svga/svga_state_tss.c
+++ b/src/gallium/drivers/svga/svga_state_tss.c
@@ -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 |
diff --git a/src/gallium/drivers/svga/svga_state_vs.c b/src/gallium/drivers/svga/svga_state_vs.c
index 6682a1efe66..ae9a20ebb81 100644
--- a/src/gallium/drivers/svga/svga_state_vs.c
+++ b/src/gallium/drivers/svga/svga_state_vs.c
@@ -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);
diff --git a/src/gallium/drivers/svga/svga_surface.c b/src/gallium/drivers/svga/svga_surface.c
index 3e4bed76c05..3e8fb5f0271 100644
--- a/src/gallium/drivers/svga/svga_surface.c
+++ b/src/gallium/drivers/svga/svga_surface.c
@@ -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),
diff --git a/src/gallium/drivers/svga/svga_surface.h b/src/gallium/drivers/svga/svga_surface.h
index afb8326e1f3..bffc8c22c60 100644
--- a/src/gallium/drivers/svga/svga_surface.h
+++ b/src/gallium/drivers/svga/svga_surface.h
@@ -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,
diff --git a/src/gallium/drivers/svga/svga_swtnl_backend.c b/src/gallium/drivers/svga/svga_swtnl_backend.c
index d5db6bf641a..ac9d637f8cb 100644
--- a/src/gallium/drivers/svga/svga_swtnl_backend.c
+++ b/src/gallium/drivers/svga/svga_swtnl_backend.c
@@ -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;
}
diff --git a/src/gallium/drivers/svga/svga_swtnl_draw.c b/src/gallium/drivers/svga/svga_swtnl_draw.c
index 05d86e1fb16..ad29c1b6425 100644
--- a/src/gallium/drivers/svga/svga_swtnl_draw.c
+++ b/src/gallium/drivers/svga/svga_swtnl_draw.c
@@ -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;
}
diff --git a/src/gallium/drivers/svga/svga_swtnl_state.c b/src/gallium/drivers/svga/svga_swtnl_state.c
index a7592382936..efda2f605b9 100644
--- a/src/gallium/drivers/svga/svga_swtnl_state.c
+++ b/src/gallium/drivers/svga/svga_swtnl_state.c
@@ -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;
diff --git a/src/gallium/drivers/svga/svga_tgsi_insn.c b/src/gallium/drivers/svga/svga_tgsi_insn.c
index f2591c5721a..99600cf5c00 100644
--- a/src/gallium/drivers/svga/svga_tgsi_insn.c
+++ b/src/gallium/drivers/svga/svga_tgsi_insn.c
@@ -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;
}
diff --git a/src/gallium/drivers/svga/svgadump/svga_shader_op.c b/src/gallium/drivers/svga/svgadump/svga_shader_op.c
index 95612a80063..ad1549d9f81 100644
--- a/src/gallium/drivers/svga/svgadump/svga_shader_op.c
+++ b/src/gallium/drivers/svga/svgadump/svga_shader_op.c
@@ -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;
}
diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c
index eaabae8ce42..d24cc623c2e 100644
--- a/src/gallium/drivers/trace/tr_context.c
+++ b/src/gallium/drivers/trace/tr_context.c
@@ -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;
diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c
index 155c869fbd9..18805655bd7 100644
--- a/src/gallium/drivers/trace/tr_dump_state.c
+++ b/src/gallium/drivers/trace/tr_dump_state.c
@@ -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);
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index 589cac2ddd3..24ee3fe1175 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -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);
};
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
index a7f8503251b..8cf738fa2c0 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -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
/**
diff --git a/src/gallium/include/pipe/p_format.h b/src/gallium/include/pipe/p_format.h
index 3aa11be4b5b..e2cc32222de 100644
--- a/src/gallium/include/pipe/p_format.h
+++ b/src/gallium/include/pipe/p_format.h
@@ -33,6 +33,16 @@
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)
*/
diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h
index 0a9e14154d7..d3a3632654c 100644
--- a/src/gallium/include/pipe/p_shader_tokens.h
+++ b/src/gallium/include/pipe/p_shader_tokens.h
@@ -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
{
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index 226ae8667b7..cf6c5b50268 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -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 */
};
diff --git a/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp b/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp
index 2ff24e17d41..2e45f3f43e9 100644
--- a/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp
+++ b/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp
@@ -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);
diff --git a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h
index e1ba6c184fd..542d6591293 100644
--- a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h
+++ b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h
@@ -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;
}
}
diff --git a/src/gallium/state_trackers/dri/common/dri_context.c b/src/gallium/state_trackers/dri/common/dri_context.c
index 3d5d24e692c..fc68ee13eaa 100644
--- a/src/gallium/state_trackers/dri/common/dri_context.c
+++ b/src/gallium/state_trackers/dri/common/dri_context.c
@@ -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;
}
diff --git a/src/gallium/state_trackers/dri/common/dri_drawable.c b/src/gallium/state_trackers/dri/common/dri_drawable.c
index 060748622c9..28a33ac7d07 100644
--- a/src/gallium/state_trackers/dri/common/dri_drawable.c
+++ b/src/gallium/state_trackers/dri/common/dri_drawable.c
@@ -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;
diff --git a/src/gallium/state_trackers/dri/common/dri_drawable.h b/src/gallium/state_trackers/dri/common/dri_drawable.h
index 2ff6b713293..7f1aa512ca1 100644
--- a/src/gallium/state_trackers/dri/common/dri_drawable.h
+++ b/src/gallium/state_trackers/dri/common/dri_drawable.h
@@ -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;
diff --git a/src/gallium/state_trackers/dri/common/dri_screen.c b/src/gallium/state_trackers/dri/common/dri_screen.c
index f6e22c74b4e..69c2e7e9ec8 100644
--- a/src/gallium/state_trackers/dri/common/dri_screen.c
+++ b/src/gallium/state_trackers/dri/common/dri_screen.c
@@ -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)
diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c
index a9d05a80fbd..0181588096d 100644
--- a/src/gallium/state_trackers/dri/drm/dri2.c
+++ b/src/gallium/state_trackers/dri/drm/dri2.c
@@ -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
index 00000000000..1cd8dbbda22
--- /dev/null
+++ b/src/gallium/state_trackers/dri/drm/dri2_buffer.h
@@ -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: */
diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile
index 8cfcef968ed..98167cceeb3 100644
--- a/src/gallium/state_trackers/egl/Makefile
+++ b/src/gallium/state_trackers/egl/Makefile
@@ -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)
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c
index 9024f945b8c..6107df48822 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.c
@@ -102,6 +102,12 @@ egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat)
#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:
plat_name = "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;
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
index 78c035a2af0..81ce7ab45c7 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
@@ -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 */
diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h
index 6461b5edbdf..42889075a39 100644
--- a/src/gallium/state_trackers/egl/common/native.h
+++ b/src/gallium/state_trackers/egl/common/native.h
@@ -239,6 +239,9 @@ 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);
const struct native_platform *
diff --git a/src/gallium/state_trackers/egl/common/native_helper.c b/src/gallium/state_trackers/egl/common/native_helper.c
index 0f2d02032b5..a9d8f32e007 100644
--- a/src/gallium/state_trackers/egl/common/native_helper.c
+++ b/src/gallium/state_trackers/egl/common/native_helper.c
@@ -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,
diff --git a/src/gallium/state_trackers/egl/common/native_helper.h b/src/gallium/state_trackers/egl/common/native_helper.h
index d1569ac3ea6..03995de19ae 100644
--- a/src/gallium/state_trackers/egl/common/native_helper.h
+++ b/src/gallium/state_trackers/egl/common/native_helper.h
@@ -51,6 +51,11 @@ 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,
uint resource_mask);
diff --git a/src/gallium/state_trackers/egl/drm/native_drm.c b/src/gallium/state_trackers/egl/drm/native_drm.c
index 14c134ea1ad..6932f30a6a4 100644
--- a/src/gallium/state_trackers/egl/drm/native_drm.c
+++ b/src/gallium/state_trackers/egl/drm/native_drm.c
@@ -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
index 00000000000..d4d5f9c2ebb
--- /dev/null
+++ b/src/gallium/state_trackers/egl/wayland/native_wayland.c
@@ -0,0 +1,626 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.11
+ *
+ * Copyright (C) 2011 Benjamin Franzke <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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
index 00000000000..271c10dc113
--- /dev/null
+++ b/src/gallium/state_trackers/egl/wayland/native_wayland.h
@@ -0,0 +1,97 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.11
+ *
+ * Copyright (C) 2011 Benjamin Franzke <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to 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_ */
diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c
index c82e2da863b..b18c3132c57 100644
--- a/src/gallium/state_trackers/egl/x11/native_dri2.c
+++ b/src/gallium/state_trackers/egl/x11/native_dri2.c
@@ -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;
}
diff --git a/src/gallium/state_trackers/python/p_context.i b/src/gallium/state_trackers/python/p_context.i
index d694651eef7..b30050bf6d4 100644
--- a/src/gallium/state_trackers/python/p_context.i
+++ b/src/gallium/state_trackers/python/p_context.i
@@ -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 */
diff --git a/src/gallium/state_trackers/python/p_device.i b/src/gallium/state_trackers/python/p_device.i
index d55086fefd5..cc67da937cd 100644
--- a/src/gallium/state_trackers/python/p_device.i
+++ b/src/gallium/state_trackers/python/p_device.i
@@ -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);
}
};
diff --git a/src/gallium/state_trackers/vega/Makefile b/src/gallium/state_trackers/vega/Makefile
index 7342c124c28..3e8ad49b767 100644
--- a/src/gallium/state_trackers/vega/Makefile
+++ b/src/gallium/state_trackers/vega/Makefile
@@ -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
diff --git a/src/gallium/state_trackers/vega/SConscript b/src/gallium/state_trackers/vega/SConscript
index 4900135a1c5..f3732aa1577 100644
--- a/src/gallium/state_trackers/vega/SConscript
+++ b/src/gallium/state_trackers/vega/SConscript
@@ -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(
diff --git a/src/gallium/state_trackers/vega/api_filters.c b/src/gallium/state_trackers/vega/api_filters.c
index 724e38241b5..6be460c495c 100644
--- a/src/gallium/state_trackers/vega/api_filters.c
+++ b/src/gallium/state_trackers/vega/api_filters.c
@@ -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);
diff --git a/src/gallium/state_trackers/vega/api_images.c b/src/gallium/state_trackers/vega/api_images.c
index ad95409cd00..b993ba62c26 100644
--- a/src/gallium/state_trackers/vega/api_images.c
+++ b/src/gallium/state_trackers/vega/api_images.c
@@ -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);
diff --git a/src/gallium/state_trackers/vega/api_masks.c b/src/gallium/state_trackers/vega/api_masks.c
index d96afe66387..cdbf0026e89 100644
--- a/src/gallium/state_trackers/vega/api_masks.c
+++ b/src/gallium/state_trackers/vega/api_masks.c
@@ -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);
}
diff --git a/src/gallium/state_trackers/vega/api_paint.c b/src/gallium/state_trackers/vega/api_paint.c
index 1411806455c..2610ebe0576 100644
--- a/src/gallium/state_trackers/vega/api_paint.c
+++ b/src/gallium/state_trackers/vega/api_paint.c
@@ -29,24 +29,24 @@
#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));
}
diff --git a/src/gallium/state_trackers/vega/api_params.c b/src/gallium/state_trackers/vega/api_params.c
index a73b6c3effe..aa1e5dd280a 100644
--- a/src/gallium/state_trackers/vega/api_params.c
+++ b/src/gallium/state_trackers/vega/api_params.c
@@ -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:
diff --git a/src/gallium/state_trackers/vega/api_path.c b/src/gallium/state_trackers/vega/api_path.c
index fe57b7671d9..ab6ce958945 100644
--- a/src/gallium/state_trackers/vega/api_path.c
+++ b/src/gallium/state_trackers/vega/api_path.c
@@ -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);
}
diff --git a/src/gallium/state_trackers/vega/api_text.c b/src/gallium/state_trackers/vega/api_text.c
index 7c6b4794099..824c7630403 100644
--- a/src/gallium/state_trackers/vega/api_text.c
+++ b/src/gallium/state_trackers/vega/api_text.c
@@ -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
index 00000000000..11eedd923ed
--- /dev/null
+++ b/src/gallium/state_trackers/vega/handle.c
@@ -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
index 00000000000..9ed326d5098
--- /dev/null
+++ b/src/gallium/state_trackers/vega/handle.h
@@ -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 */
diff --git a/src/gallium/state_trackers/vega/image.c b/src/gallium/state_trackers/vega/image.c
index 318ea94bdfb..73351b671f9 100644
--- a/src/gallium/state_trackers/vega/image.c
+++ b/src/gallium/state_trackers/vega/image.c
@@ -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);
}
diff --git a/src/gallium/state_trackers/vega/paint.c b/src/gallium/state_trackers/vega/paint.c
index 2db8cbcf7c8..6e5348a1ff2 100644
--- a/src/gallium/state_trackers/vega/paint.c
+++ b/src/gallium/state_trackers/vega/paint.c
@@ -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));
+}
diff --git a/src/gallium/state_trackers/vega/paint.h b/src/gallium/state_trackers/vega/paint.h
index 3de3bbe12ed..e5357763b89 100644
--- a/src/gallium/state_trackers/vega/paint.h
+++ b/src/gallium/state_trackers/vega/paint.h
@@ -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
diff --git a/src/gallium/state_trackers/vega/polygon.c b/src/gallium/state_trackers/vega/polygon.c
index a491de27fa6..bcc5cb272ca 100644
--- a/src/gallium/state_trackers/vega/polygon.c
+++ b/src/gallium/state_trackers/vega/polygon.c
@@ -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);
diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c
index e42bad76492..9de2cb1014d 100644
--- a/src/gallium/state_trackers/vega/renderer.c
+++ b/src/gallium/state_trackers/vega/renderer.c
@@ -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;
diff --git a/src/gallium/state_trackers/vega/shader.c b/src/gallium/state_trackers/vega/shader.c
index 2a6bae8a630..bee6d84001d 100644
--- a/src/gallium/state_trackers/vega/shader.c
+++ b/src/gallium/state_trackers/vega/shader.c
@@ -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:
diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c
index f36f55d6c89..83b42609e03 100644
--- a/src/gallium/state_trackers/vega/vg_context.c
+++ b/src/gallium/state_trackers/vega/vg_context.c
@@ -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;
diff --git a/src/gallium/state_trackers/vega/vg_context.h b/src/gallium/state_trackers/vega/vg_context.h
index d616a20a3d9..71491a5aa22 100644
--- a/src/gallium/state_trackers/vega/vg_context.h
+++ b/src/gallium/state_trackers/vega/vg_context.h
@@ -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);
diff --git a/src/gallium/state_trackers/vega/vg_manager.c b/src/gallium/state_trackers/vega/vg_manager.c
index ec713b7fb1d..44d2996bb45 100644
--- a/src/gallium/state_trackers/vega/vg_manager.c
+++ b/src/gallium/state_trackers/vega/vg_manager.c
@@ -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;
diff --git a/src/gallium/state_trackers/vega/vgu.c b/src/gallium/state_trackers/vega/vgu.c
index 7dc51c5599c..4206a91e006 100644
--- a/src/gallium/state_trackers/vega/vgu.c
+++ b/src/gallium/state_trackers/vega/vgu.c
@@ -29,6 +29,7 @@
#include "matrix.h"
#include "path.h"
+#include "handle.h"
#include "util/u_debug.h"
#include "util/u_pointer.h"
@@ -36,16 +37,6 @@
#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);
diff --git a/src/gallium/state_trackers/wgl/SConscript b/src/gallium/state_trackers/wgl/SConscript
index 1b7597de440..7cb953ba742 100644
--- a/src/gallium/state_trackers/wgl/SConscript
+++ b/src/gallium/state_trackers/wgl/SConscript
@@ -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',
diff --git a/src/gallium/state_trackers/wgl/stw_device.c b/src/gallium/state_trackers/wgl/stw_device.c
index c4822d4d8aa..4ece4e4979a 100644
--- a/src/gallium/state_trackers/wgl/stw_device.c
+++ b/src/gallium/state_trackers/wgl/stw_device.c
@@ -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);
diff --git a/src/gallium/state_trackers/xorg/xorg_crtc.c b/src/gallium/state_trackers/xorg/xorg_crtc.c
index 71f7b8c21d0..d751ac18704 100644
--- a/src/gallium/state_trackers/xorg/xorg_crtc.c
+++ b/src/gallium/state_trackers/xorg/xorg_crtc.c
@@ -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;
diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.c b/src/gallium/state_trackers/xorg/xorg_renderer.c
index a3d7c5a70e2..3b3ae455c0b 100644
--- a/src/gallium/state_trackers/xorg/xorg_renderer.c
+++ b/src/gallium/state_trackers/xorg/xorg_renderer.c
@@ -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 */
diff --git a/src/gallium/state_trackers/xorg/xvmc/subpicture.c b/src/gallium/state_trackers/xorg/xvmc/subpicture.c
index 4a835c04d8a..78de154bdd7 100644
--- a/src/gallium/state_trackers/xorg/xvmc/subpicture.c
+++ b/src/gallium/state_trackers/xorg/xvmc/subpicture.c
@@ -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,
diff --git a/src/gallium/state_trackers/xorg/xvmc/surface.c b/src/gallium/state_trackers/xorg/xvmc/surface.c
index d7285a478fb..c90ad409c10 100644
--- a/src/gallium/state_trackers/xorg/xvmc/surface.c
+++ b/src/gallium/state_trackers/xorg/xvmc/surface.c
@@ -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;
diff --git a/src/gallium/targets/SConscript.dri b/src/gallium/targets/SConscript.dri
index bc3671a256b..101863a6848 100644
--- a/src/gallium/targets/SConscript.dri
+++ b/src/gallium/targets/SConscript.dri
@@ -72,7 +72,6 @@ COMMON_DRI_DRM_OBJECTS = [
drienv.AppendUnique(LIBS = [
'expat',
- 'talloc',
])
Export([
diff --git a/src/gallium/targets/dri-r300/Makefile b/src/gallium/targets/dri-r300/Makefile
index 9afbb13276d..cc77a4bc20d 100644
--- a/src/gallium/targets/dri-r300/Makefile
+++ b/src/gallium/targets/dri-r300/Makefile
@@ -22,6 +22,4 @@ DRIVER_DEFINES = \
include ../Makefile.dri
-DRI_LIB_DEPS += -ldrm_radeon
-
symlinks:
diff --git a/src/gallium/targets/dri-r300/SConscript b/src/gallium/targets/dri-r300/SConscript
index 005b4bbf7f1..683b6c6972d 100644
--- a/src/gallium/targets/dri-r300/SConscript
+++ b/src/gallium/targets/dri-r300/SConscript
@@ -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 = [
diff --git a/src/gallium/targets/dri-r600/SConscript b/src/gallium/targets/dri-r600/SConscript
index aa771db2d1a..1df11a8747b 100644
--- a/src/gallium/targets/dri-r600/SConscript
+++ b/src/gallium/targets/dri-r600/SConscript
@@ -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 = [
diff --git a/src/gallium/targets/dri-vmwgfx/Makefile b/src/gallium/targets/dri-vmwgfx/Makefile
index 38f78932e13..8c716f42fe2 100644
--- a/src/gallium/targets/dri-vmwgfx/Makefile
+++ b/src/gallium/targets/dri-vmwgfx/Makefile
@@ -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
diff --git a/src/gallium/targets/egl-static/SConscript b/src/gallium/targets/egl-static/SConscript
index 381ef4e862d..cbd98cc416a 100644
--- a/src/gallium/targets/egl-static/SConscript
+++ b/src/gallium/targets/egl-static/SConscript
@@ -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,
diff --git a/src/gallium/targets/egl/Makefile b/src/gallium/targets/egl/Makefile
index 92d971bab01..de01939e5f1 100644
--- a/src/gallium/targets/egl/Makefile
+++ b/src/gallium/targets/egl/Makefile
@@ -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
diff --git a/src/gallium/targets/libgl-gdi/SConscript b/src/gallium/targets/libgl-gdi/SConscript
index 6fa0851a1ab..49462a8e309 100644
--- a/src/gallium/targets/libgl-gdi/SConscript
+++ b/src/gallium/targets/libgl-gdi/SConscript
@@ -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,
diff --git a/src/gallium/targets/libgl-xlib/SConscript b/src/gallium/targets/libgl-xlib/SConscript
index d932736be78..ca15372f1d9 100644
--- a/src/gallium/targets/libgl-xlib/SConscript
+++ b/src/gallium/targets/libgl-xlib/SConscript
@@ -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 = [
diff --git a/src/gallium/targets/xorg-radeon/Makefile b/src/gallium/targets/xorg-radeon/Makefile
index d3bc3569929..6d5f2c3d16e 100644
--- a/src/gallium/targets/xorg-radeon/Makefile
+++ b/src/gallium/targets/xorg-radeon/Makefile
@@ -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
diff --git a/src/gallium/tests/graw/SConscript b/src/gallium/tests/graw/SConscript
index 3341b884985..565fa5279cd 100644
--- a/src/gallium/tests/graw/SConscript
+++ b/src/gallium/tests/graw/SConscript
@@ -24,6 +24,7 @@ progs = [
'gs-test',
'shader-leak',
'tri-gs',
+ 'quad-sample',
]
for name in progs:
diff --git a/src/gallium/tests/graw/fs-test.c b/src/gallium/tests/graw/fs-test.c
index d21eb44e116..ff82b607110 100644
--- a/src/gallium/tests/graw/fs-test.c
+++ b/src/gallium/tests/graw/fs-test.c
@@ -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,
diff --git a/src/gallium/tests/graw/gs-test.c b/src/gallium/tests/graw/gs-test.c
index 0c65390e109..cc05889dd05 100644
--- a/src/gallium/tests/graw/gs-test.c
+++ b/src/gallium/tests/graw/gs-test.c
@@ -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
index 00000000000..3c6458b434e
--- /dev/null
+++ b/src/gallium/tests/graw/quad-sample.c
@@ -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;
+}
diff --git a/src/gallium/tests/graw/quad-tex.c b/src/gallium/tests/graw/quad-tex.c
index 58ca639d207..4e66813b301 100644
--- a/src/gallium/tests/graw/quad-tex.c
+++ b/src/gallium/tests/graw/quad-tex.c
@@ -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,
diff --git a/src/gallium/tests/graw/shader-leak.c b/src/gallium/tests/graw/shader-leak.c
index 9af76f51ea2..a23ca73ac1d 100644
--- a/src/gallium/tests/graw/shader-leak.c
+++ b/src/gallium/tests/graw/shader-leak.c
@@ -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,
diff --git a/src/gallium/tests/graw/tri-gs.c b/src/gallium/tests/graw/tri-gs.c
index a1a00b32098..47b76530c6b 100644
--- a/src/gallium/tests/graw/tri-gs.c
+++ b/src/gallium/tests/graw/tri-gs.c
@@ -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,
diff --git a/src/gallium/tests/graw/tri-instanced.c b/src/gallium/tests/graw/tri-instanced.c
index f61d8b9844d..259b3d9527c 100644
--- a/src/gallium/tests/graw/tri-instanced.c
+++ b/src/gallium/tests/graw/tri-instanced.c
@@ -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,
diff --git a/src/gallium/tests/graw/tri.c b/src/gallium/tests/graw/tri.c
index 006d61ca88c..4266c0394d8 100644
--- a/src/gallium/tests/graw/tri.c
+++ b/src/gallium/tests/graw/tri.c
@@ -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,
diff --git a/src/gallium/tests/graw/vs-test.c b/src/gallium/tests/graw/vs-test.c
index 1358fa85dfd..dd64d8b9301 100644
--- a/src/gallium/tests/graw/vs-test.c
+++ b/src/gallium/tests/graw/vs-test.c
@@ -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,
diff --git a/src/gallium/tests/trivial/quad-tex.c b/src/gallium/tests/trivial/quad-tex.c
index 92c5b4dbb18..af93e09d8d4 100644
--- a/src/gallium/tests/trivial/quad-tex.c
+++ b/src/gallium/tests/trivial/quad-tex.c
@@ -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);
}
diff --git a/src/gallium/tests/trivial/tri.c b/src/gallium/tests/trivial/tri.c
index 37c1573051f..b89cfe0d989 100644
--- a/src/gallium/tests/trivial/tri.c
+++ b/src/gallium/tests/trivial/tri.c
@@ -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);
}
diff --git a/src/gallium/winsys/SConscript b/src/gallium/winsys/SConscript
index d74f8a2e989..9f36d225e10 100644
--- a/src/gallium/winsys/SConscript
+++ b/src/gallium/winsys/SConscript
@@ -13,6 +13,10 @@ SConscript([
'sw/gdi/SConscript',
])
+SConscript([
+ 'i915/sw/SConscript',
+])
+
if env['dri']:
SConscript([
'sw/dri/SConscript',
diff --git a/src/gallium/winsys/i915/drm/i915_drm_batchbuffer.c b/src/gallium/winsys/i915/drm/i915_drm_batchbuffer.c
index ebe86dcf196..afeab5eef42 100644
--- a/src/gallium/winsys/i915/drm/i915_drm_batchbuffer.c
+++ b/src/gallium/winsys/i915/drm/i915_drm_batchbuffer.c
@@ -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);
diff --git a/src/gallium/winsys/i915/sw/i915_sw_batchbuffer.c b/src/gallium/winsys/i915/sw/i915_sw_batchbuffer.c
index 44773ae30e7..8085591c8eb 100644
--- a/src/gallium/winsys/i915/sw/i915_sw_batchbuffer.c
+++ b/src/gallium/winsys/i915/sw/i915_sw_batchbuffer.c
@@ -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) {
diff --git a/src/gallium/winsys/i915/sw/i915_sw_buffer.c b/src/gallium/winsys/i915/sw/i915_sw_buffer.c
index 834805e621d..9a7e90e2173 100644
--- a/src/gallium/winsys/i915/sw/i915_sw_buffer.c
+++ b/src/gallium/winsys/i915/sw/i915_sw_buffer.c
@@ -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;
}
diff --git a/src/gallium/winsys/r600/drm/SConscript b/src/gallium/winsys/r600/drm/SConscript
index f97434e995d..cc9a06a2393 100644
--- a/src/gallium/winsys/r600/drm/SConscript
+++ b/src/gallium/winsys/r600/drm/SConscript
@@ -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(
diff --git a/src/gallium/winsys/r600/drm/evergreen_hw_context.c b/src/gallium/winsys/r600/drm/evergreen_hw_context.c
index 3fdafc39283..aa4035a302b 100644
--- a/src/gallium/winsys/r600/drm/evergreen_hw_context.c
+++ b/src/gallium/winsys/r600/drm/evergreen_hw_context.c
@@ -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 */
diff --git a/src/gallium/winsys/r600/drm/r600_bo.c b/src/gallium/winsys/r600/drm/r600_bo.c
index 339d5dc47f4..06e8f6910f3 100644
--- a/src/gallium/winsys/r600/drm/r600_bo.c
+++ b/src/gallium/winsys/r600/drm/r600_bo.c
@@ -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;
}
diff --git a/src/gallium/winsys/r600/drm/r600_drm.c b/src/gallium/winsys/r600/drm/r600_drm.c
index 69b0a1dcd72..f5cd48d39c6 100644
--- a/src/gallium/winsys/r600/drm/r600_drm.c
+++ b/src/gallium/winsys/r600/drm/r600_drm.c
@@ -41,6 +41,10 @@
#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;
diff --git a/src/gallium/winsys/r600/drm/r600_hw_context.c b/src/gallium/winsys/r600/drm/r600_hw_context.c
index f10e2fda6f2..f170640407d 100644
--- a/src/gallium/winsys/r600/drm/r600_hw_context.c
+++ b/src/gallium/winsys/r600/drm/r600_hw_context.c
@@ -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;
}
diff --git a/src/gallium/winsys/r600/drm/r600_priv.h b/src/gallium/winsys/r600/drm/r600_priv.h
index a38a6481b4f..2d91cd97d68 100644
--- a/src/gallium/winsys/r600/drm/r600_priv.h
+++ b/src/gallium/winsys/r600/drm/r600_priv.h
@@ -49,6 +49,7 @@ struct radeon {
unsigned fence;
unsigned *cfence;
struct r600_bo *fence_bo;
+ unsigned clock_crystal_freq;
};
struct r600_reg {
diff --git a/src/gallium/winsys/r600/drm/radeon_bo.c b/src/gallium/winsys/r600/drm/radeon_bo.c
index 999de82646d..3643ddbcb93 100644
--- a/src/gallium/winsys/r600/drm/radeon_bo.c
+++ b/src/gallium/winsys/r600/drm/radeon_bo.c
@@ -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;
diff --git a/src/gallium/winsys/r600/drm/radeon_pciid.c b/src/gallium/winsys/r600/drm/radeon_pciid.c
index 06681791e57..f19956931de 100644
--- a/src/gallium/winsys/r600/drm/radeon_pciid.c
+++ b/src/gallium/winsys/r600/drm/radeon_pciid.c
@@ -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},
diff --git a/src/gallium/winsys/radeon/drm/Makefile b/src/gallium/winsys/radeon/drm/Makefile
index 7e339a2ecfe..e63ae6f5006 100644
--- a/src/gallium/winsys/radeon/drm/Makefile
+++ b/src/gallium/winsys/radeon/drm/Makefile
@@ -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)
diff --git a/src/gallium/winsys/radeon/drm/SConscript b/src/gallium/winsys/radeon/drm/SConscript
index 80816621848..b16e03556d3 100644
--- a/src/gallium/winsys/radeon/drm/SConscript
+++ b/src/gallium/winsys/radeon/drm/SConscript
@@ -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
index 00000000000..3094337a3cd
--- /dev/null
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
@@ -0,0 +1,599 @@
+/*
+ * Copyright © 2011 Marek Olšák <[email protected]>
+ * 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_buffer.h b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h
index 494abdc0b48..a26866b7e75 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.h
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h
@@ -1,5 +1,6 @@
/*
* Copyright © 2008 Jérôme Glisse
+ * Copyright © 2011 Marek Olšák <[email protected]>
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
@@ -26,28 +27,61 @@
/*
* Authors:
* Jérôme Glisse <[email protected]>
+ * Marek Olšák <[email protected]>
*/
#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_VERTEX (1 << 28)
+#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 *
-radeon_pb_buffer(struct r300_winsys_buffer *buffer)
+pb_buffer(struct r300_winsys_bo *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
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
index 5e14287ec2d..00000000000
--- a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
+++ /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_common.c b/src/gallium/winsys/radeon/drm/radeon_drm_common.c
index fe71f080592..4676c2a1ea9 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_common.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_common.c
@@ -1,5 +1,6 @@
/*
* Copyright © 2009 Corbin Simpson
+ * Copyright © 2011 Marek Olšák <[email protected]>
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
@@ -27,38 +28,35 @@
* Authors:
* Corbin Simpson <[email protected]>
* Joakim Sindholt <[email protected]>
+ * Marek Olšák <[email protected]>
*/
#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;
}
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
index 60bc36b0929..a38b01048b2 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
@@ -63,17 +63,73 @@
*/
#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;
}
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h
index 76046534b65..4cc97f37e09 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h
@@ -1,42 +1,103 @@
+/*
+ * Copyright © 2011 Marek Olšák <[email protected]>
+ * 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
index bacf181b47c..00000000000
--- a/src/gallium/winsys/radeon/drm/radeon_r300.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright 2008 Corbin Simpson <[email protected]>
- *
- * Permission is hereby granted, free of charge, to 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;
-}
diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h
index 492edfef8c3..f8a89abcfe4 100644
--- a/src/gallium/winsys/radeon/drm/radeon_winsys.h
+++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h
@@ -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
diff --git a/src/gallium/winsys/svga/drm/vmw_buffer.c b/src/gallium/winsys/svga/drm/vmw_buffer.c
index eca174a6c56..80d5dfc3ed4 100644
--- a/src/gallium/winsys/svga/drm/vmw_buffer.c
+++ b/src/gallium/winsys/svga/drm/vmw_buffer.c
@@ -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;
diff --git a/src/gallium/winsys/svga/drm/vmw_context.c b/src/gallium/winsys/svga/drm/vmw_context.c
index 11626ee637d..f2124c1bf65 100644
--- a/src/gallium/winsys/svga/drm/vmw_context.c
+++ b/src/gallium/winsys/svga/drm/vmw_context.c
@@ -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;
}
diff --git a/src/gallium/winsys/sw/xlib/SConscript b/src/gallium/winsys/sw/xlib/SConscript
index df01a9ec2bf..f6c47411831 100644
--- a/src/gallium/winsys/sw/xlib/SConscript
+++ b/src/gallium/winsys/sw/xlib/SConscript
@@ -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()
diff --git a/src/glsl/Makefile b/src/glsl/Makefile
index c9525446633..876f0dfc2a5 100644
--- a/src/glsl/Makefile
+++ b/src/glsl/Makefile
@@ -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)/[email protected] \
+ $(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
diff --git a/src/glsl/SConscript b/src/glsl/SConscript
index 88a83fdb6fa..7c6b6ae8c4d 100644
--- a/src/glsl/SConscript
+++ b/src/glsl/SConscript
@@ -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',
diff --git a/src/glsl/ast.h b/src/glsl/ast.h
index 0e2811ca665..878f48b2070 100644
--- a/src/glsl/ast.h
+++ b/src/glsl/ast.h
@@ -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 *);
diff --git a/src/glsl/ast_expr.cpp b/src/glsl/ast_expr.cpp
index 4e83decb924..e624d11cf3b 100644
--- a/src/glsl/ast_expr.cpp
+++ b/src/glsl/ast_expr.cpp
@@ -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 *
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index 6ecf779c935..e5cb8733952 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -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);
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 7a171f3a2bb..bef099cca3b 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -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;
diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp
index d14077473f0..c680ae5f671 100644
--- a/src/glsl/ast_type.cpp
+++ b/src/glsl/ast_type.cpp
@@ -21,7 +21,6 @@
* DEALINGS IN THE SOFTWARE.
*/
-#include <cstdio>
#include "ast.h"
extern "C" {
#include "program/symbol_table.h"
diff --git a/src/glsl/builtins/profiles/130.frag b/src/glsl/builtins/profiles/130.frag
index 329116f2a28..43653a906f8 100644
--- a/src/glsl/builtins/profiles/130.frag
+++ b/src/glsl/builtins/profiles/130.frag
@@ -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:
diff --git a/src/glsl/builtins/profiles/130.vert b/src/glsl/builtins/profiles/130.vert
index 1c212ebb3c5..742dec6e6d5 100644
--- a/src/glsl/builtins/profiles/130.vert
+++ b/src/glsl/builtins/profiles/130.vert
@@ -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:
diff --git a/src/glsl/builtins/tools/generate_builtins.py b/src/glsl/builtins/tools/generate_builtins.py
index 3a938a022da..edd3c70e00b 100755
--- a/src/glsl/builtins/tools/generate_builtins.py
+++ b/src/glsl/builtins/tools/generate_builtins.py
@@ -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));
}
diff --git a/src/glsl/builtins/tools/texture_builtins.py b/src/glsl/builtins/tools/texture_builtins.py
index 8bf708b5aac..8017e943b1b 100755
--- a/src/glsl/builtins/tools/texture_builtins.py
+++ b/src/glsl/builtins/tools/texture_builtins.py
@@ -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
index 73ce67de3d1..00000000000
--- a/src/glsl/configure.ac
+++ /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, [email protected], glsl)
-AC_CONFIG_SRCDIR([Makefile.am])
-AM_CONFIG_HEADER([config.h])
-AC_CONFIG_FILES([glcpp/Makefile])
-
-AM_INIT_AUTOMAKE
-LT_INIT
-
-AM_MAINTAINER_MODE
-
-# Checks for programs.
-AC_PROG_CXX
-AC_PROG_CC
-AC_PROG_MAKE_SET
-AC_PROG_YACC
-AC_PROG_LEX
-
-m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
-
-# Checks for libraries.
-
-# Checks for header files.
-
-# Checks for typedefs, structures, and compiler characteristics.
-
-# Checks for library functions.
-AC_HEADER_STDC
-
-AH_TOP([#ifndef GLSL_CONFIG_H
-#define GLSL_CONFIG_H])
-AH_BOTTOM([#endif /* GLSL_CONFIG_H */])
-
-PKG_CHECK_MODULES([talloc], [talloc >= 2.0])
-
-AC_ARG_ENABLE([debug],
- [AS_HELP_STRING([--enable-debug],
- [use debug compiler flags and macros @<:@default=disabled@:>@])],
- [enable_debug="$enableval"],
- [enable_debug=no]
-)
-if test "x$enable_debug" = xyes; then
- DEFINES="$DEFINES -DDEBUG"
- if test "x$GCC" = xyes; then
- # Remove any -g or -O flags from the command line
- CFLAGS=[`echo $CFLAGS | sed 's/-g[^ \t]*[ \t]*//g;s/-O[^ \t]*[ \t]*//g'`]
- CFLAGS="$CFLAGS -O0 -ggdb3 -fstack-protector -D_FORTIFY_SOURCE=2"
- fi
- if test "x$GXX" = xyes; then
- # Remove any -g flags from the command line
- CXXFLAGS=[`echo $CXXFLAGS | sed 's/-g[^ \t]*[ \t]*//g;s/-O[^ \t]*[ \t]*//g'`]
- CXXFLAGS="$CXXFLAGS -O0 -ggdb3 -fstack-protector -D_FORTIFY_SOURCE=2"
- fi
-fi
-
-if test "x$GXX" = xyes ; then
- WARN="-Wall -Wextra -Wunsafe-loop-optimizations -Wstack-protector"
-else
- WARN=""
-fi
-
-CFLAGS="$CFLAGS $WARN"
-CXXFLAGS="$CXXFLAGS $WARN"
-YFLAGS="-d -v"
-
-AC_OUTPUT([Makefile])
diff --git a/src/glsl/glcpp/glcpp-lex.c b/src/glsl/glcpp/glcpp-lex.c
index 156af3008c0..b53bea6271d 100644
--- a/src/glsl/glcpp/glcpp-lex.c
+++ b/src/glsl/glcpp/glcpp-lex.c
@@ -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):
diff --git a/src/glsl/glcpp/glcpp-lex.l b/src/glsl/glcpp/glcpp-lex.l
index e936854cf2c..11b73aea88b 100644
--- a/src/glsl/glcpp/glcpp-lex.l
+++ b/src/glsl/glcpp/glcpp-lex.l
@@ -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;
}
diff --git a/src/glsl/glcpp/glcpp-parse.c b/src/glsl/glcpp/glcpp-parse.c
index a5566dc0aaf..1e71b18c4cb 100644
--- a/src/glsl/glcpp/glcpp-parse.c
+++ b/src/glsl/glcpp/glcpp-parse.c
@@ -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"
@@ -103,10 +102,6 @@
#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);
}
diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y
index e71c0e8b382..1f6e67fa062 100644
--- a/src/glsl/glcpp/glcpp-parse.y
+++ b/src/glsl/glcpp/glcpp-parse.y
@@ -32,10 +32,6 @@
#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);
}
diff --git a/src/glsl/glcpp/glcpp.c b/src/glsl/glcpp/glcpp.c
index 062eb6b72d4..564194caac2 100644
--- a/src/glsl/glcpp/glcpp.c
+++ b/src/glsl/glcpp/glcpp.c
@@ -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;
}
diff --git a/src/glsl/glcpp/glcpp.h b/src/glsl/glcpp/glcpp.h
index 7125d325dff..dc816e90ee7 100644
--- a/src/glsl/glcpp/glcpp.h
+++ b/src/glsl/glcpp/glcpp.h
@@ -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 */
diff --git a/src/glsl/glcpp/pp.c b/src/glsl/glcpp/pp.c
index e1a3a88a3e5..3640896a2c2 100644
--- a/src/glsl/glcpp/pp.c
+++ b/src/glsl/glcpp/pp.c
@@ -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;
diff --git a/src/glsl/glsl_lexer.cpp b/src/glsl/glsl_lexer.cpp
index 7c0a51b99bf..40d2294ef8c 100644
--- a/src/glsl/glsl_lexer.cpp
+++ b/src/glsl/glsl_lexer.cpp
@@ -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)
diff --git a/src/glsl/glsl_lexer.lpp b/src/glsl/glsl_lexer.lpp
index d30759be2b8..e4c469f9e0a 100644
--- a/src/glsl/glsl_lexer.lpp
+++ b/src/glsl/glsl_lexer.lpp
@@ -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)
{
diff --git a/src/glsl/glsl_parser.cpp b/src/glsl/glsl_parser.cpp
index 8b196ae7fc6..1db7e901a96 100644
--- a/src/glsl/glsl_parser.cpp
+++ b/src/glsl/glsl_parser.cpp
@@ -214,123 +214,125 @@
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,
+ 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, 73, 74, 75, 76, 0, 77, 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,
- 83, 0, 0, 0, 0, 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, 84, 0, 85, 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, 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, 76, 77, 78, 79, 0, 80,
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, 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, 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, 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, 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, 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, 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,
- 0, 0, 73, 74, 75, 76, 0, 77, 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,
- 83, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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, 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, 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,
+ 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, 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,
+ 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, 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, 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, 77, 78, 79, 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, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 84, 0, 85
+ 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,
+ 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, -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, 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,
- -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, -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, 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, -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, -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, 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, -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 451 "glsl_parser.ypp"
+#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 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);
diff --git a/src/glsl/glsl_parser.h b/src/glsl/glsl_parser.h
index 1bf3b3538c7..7f36492f7a1 100644
--- a/src/glsl/glsl_parser.h
+++ b/src/glsl/glsl_parser.h
@@ -112,123 +112,125 @@
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 */
diff --git a/src/glsl/glsl_parser.ypp b/src/glsl/glsl_parser.ypp
index 3982167c482..2c0498ece7a 100644
--- a/src/glsl/glsl_parser.ypp
+++ b/src/glsl/glsl_parser.ypp
@@ -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
@@ -184,6 +185,10 @@
%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();
}
;
diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
index 77885d4e1e3..d7a37aef46d 100644
--- a/src/glsl/glsl_parser_extras.cpp
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -26,10 +26,10 @@
#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
diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h
index 030d27a2627..10cb673c694 100644
--- a/src/glsl/glsl_parser_extras.h
+++ b/src/glsl/glsl_parser_extras.h
@@ -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;
@@ -73,6 +73,16 @@ struct _mesa_glsl_parse_state {
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.
*
* \sa struct gl_constants (in mtypes.h)
@@ -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. */
diff --git a/src/glsl/glsl_symbol_table.cpp b/src/glsl/glsl_symbol_table.cpp
index 6fcfe07b9c2..2f291d4f97f 100644
--- a/src/glsl/glsl_symbol_table.cpp
+++ b/src/glsl/glsl_symbol_table.cpp
@@ -26,19 +26,19 @@
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()
diff --git a/src/glsl/glsl_symbol_table.h b/src/glsl/glsl_symbol_table.h
index 28a44ebe91c..637bc033b93 100644
--- a/src/glsl/glsl_symbol_table.h
+++ b/src/glsl/glsl_symbol_table.h
@@ -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();
diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp
index 95b85926482..76b4f3e4cb0 100644
--- a/src/glsl/glsl_types.cpp
+++ b/src/glsl/glsl_types.cpp
@@ -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);
diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h
index 57e7b09d98c..61bf5e0cfd2 100644
--- a/src/glsl/glsl_types.h
+++ b/src/glsl/glsl_types.h
@@ -26,14 +26,15 @@
#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,
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
index 460d43b02e1..fc356ba5275 100644
--- a/src/glsl/ir.cpp
+++ b/src/glsl/ir.cpp
@@ -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);
}
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 7b83c2836ee..f2f902c0a77 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -26,13 +26,10 @@
#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:
@@ -335,6 +352,14 @@ public:
/*@}*/
/**
+ * \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?
*
* If the location is explicitly set in the shader, it \b cannot be changed
@@ -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 */
diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp
index 1522af682bb..2c0574dc6bf 100644
--- a/src/glsl/ir_clone.cpp
+++ b/src/glsl/ir_clone.cpp
@@ -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);
}
diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp
index 4fd6d09a3af..2a308489656 100644
--- a/src/glsl/ir_constant_expression.cpp
+++ b/src/glsl/ir_constant_expression.cpp
@@ -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;
diff --git a/src/glsl/ir_expression_flattening.cpp b/src/glsl/ir_expression_flattening.cpp
index 7b1b8dbfef1..0b7c537bd8a 100644
--- a/src/glsl/ir_expression_flattening.cpp
+++ b/src/glsl/ir_expression_flattening.cpp
@@ -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);
diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp
index 8db70119ec2..caee9296af9 100644
--- a/src/glsl/ir_function.cpp
+++ b/src/glsl/ir_function.cpp
@@ -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;
diff --git a/src/glsl/ir_hv_accept.cpp b/src/glsl/ir_hv_accept.cpp
index be8b36a7cf8..4a607dc8749 100644
--- a/src/glsl/ir_hv_accept.cpp
+++ b/src/glsl/ir_hv_accept.cpp
@@ -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;
diff --git a/src/glsl/ir_import_prototypes.cpp b/src/glsl/ir_import_prototypes.cpp
index 4e0b30aa90e..3585bf6b24b 100644
--- a/src/glsl/ir_import_prototypes.cpp
+++ b/src/glsl/ir_import_prototypes.cpp
@@ -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,
diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h
index dbc9f4ab975..dd265673c55 100644
--- a/src/glsl/ir_optimization.h
+++ b/src/glsl/ir_optimization.h
@@ -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);
diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp
index c56bafd00c5..82ccc722fa2 100644
--- a/src/glsl/ir_print_visitor.cpp
+++ b/src/glsl/ir_print_visitor.cpp
@@ -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)
diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp
index 40901dc6c92..af85e06ae0e 100644
--- a/src/glsl/ir_reader.cpp
+++ b/src/glsl/ir_reader.cpp
@@ -21,10 +21,6 @@
* 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);
diff --git a/src/glsl/ir_rvalue_visitor.cpp b/src/glsl/ir_rvalue_visitor.cpp
index 773bfcfa3ec..ed6c7cb6a1a 100644
--- a/src/glsl/ir_rvalue_visitor.cpp
+++ b/src/glsl/ir_rvalue_visitor.cpp
@@ -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:
diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp
index 5b055f64d38..44d7549ea28 100644
--- a/src/glsl/ir_validate.cpp
+++ b/src/glsl/ir_validate.cpp
@@ -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;
diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp
index 73da28faf4f..18a3e0fb0d9 100644
--- a/src/glsl/ir_variable.cpp
+++ b/src/glsl/ir_variable.cpp
@@ -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;
diff --git a/src/glsl/ir_variable_refcount.h b/src/glsl/ir_variable_refcount.h
index 8b43bad71f8..906135a9e1e 100644
--- a/src/glsl/ir_variable_refcount.h
+++ b/src/glsl/ir_variable_refcount.h
@@ -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 *);
diff --git a/src/glsl/link_functions.cpp b/src/glsl/link_functions.cpp
index 05930edb80e..5851c14d624 100644
--- a/src/glsl/link_functions.cpp
+++ b/src/glsl/link_functions.cpp
@@ -21,14 +21,6 @@
* 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;
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index c906d744212..7db5c5e8d53 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -63,14 +63,6 @@
*
* \author Ian Romanick <[email protected]>
*/
-#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);
}
diff --git a/src/glsl/list.h b/src/glsl/list.h
index 3197b03cf28..1d46365faec 100644
--- a/src/glsl/list.h
+++ b/src/glsl/list.h
@@ -66,37 +66,33 @@
#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()
diff --git a/src/glsl/loop_analysis.cpp b/src/glsl/loop_analysis.cpp
index 3cf86ebaa38..9bba6a97c48 100644
--- a/src/glsl/loop_analysis.cpp
+++ b/src/glsl/loop_analysis.cpp
@@ -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,
diff --git a/src/glsl/loop_controls.cpp b/src/glsl/loop_controls.cpp
index b528810f40d..9acbadc50ea 100644
--- a/src/glsl/loop_controls.cpp
+++ b/src/glsl/loop_controls.cpp
@@ -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;
}
diff --git a/src/glsl/loop_unroll.cpp b/src/glsl/loop_unroll.cpp
index 46000524ba1..5b84e101477 100644
--- a/src/glsl/loop_unroll.cpp
+++ b/src/glsl/loop_unroll.cpp
@@ -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;
diff --git a/src/glsl/lower_discard.cpp b/src/glsl/lower_discard.cpp
index b95313df8c8..cafd2dd3b44 100644
--- a/src/glsl/lower_discard.cpp
+++ b/src/glsl/lower_discard.cpp
@@ -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",
diff --git a/src/glsl/lower_if_to_cond_assign.cpp b/src/glsl/lower_if_to_cond_assign.cpp
index 40ffc45c86c..e3a1065d996 100644
--- a/src/glsl/lower_if_to_cond_assign.cpp
+++ b/src/glsl/lower_if_to_cond_assign.cpp
@@ -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.
diff --git a/src/glsl/lower_mat_op_to_vec.cpp b/src/glsl/lower_mat_op_to_vec.cpp
index 7065fdec35f..8cbbfa713c9 100644
--- a/src/glsl/lower_mat_op_to_vec.cpp
+++ b/src/glsl/lower_mat_op_to_vec.cpp
@@ -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();
diff --git a/src/glsl/lower_noise.cpp b/src/glsl/lower_noise.cpp
index cb32d283486..85f59b675e0 100644
--- a/src/glsl/lower_noise.cpp
+++ b/src/glsl/lower_noise.cpp
@@ -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;
}
}
diff --git a/src/glsl/lower_texture_projection.cpp b/src/glsl/lower_texture_projection.cpp
index 1fd26a7a2b5..6e3aaecceee 100644
--- a/src/glsl/lower_texture_projection.cpp
+++ b/src/glsl/lower_texture_projection.cpp
@@ -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);
diff --git a/src/glsl/lower_variable_index_to_cond_assign.cpp b/src/glsl/lower_variable_index_to_cond_assign.cpp
index 7b4e4ad07cb..8eb1612f0a0 100644
--- a/src/glsl/lower_variable_index_to_cond_assign.cpp
+++ b/src/glsl/lower_variable_index_to_cond_assign.cpp
@@ -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;
}
}
diff --git a/src/glsl/lower_vec_index_to_cond_assign.cpp b/src/glsl/lower_vec_index_to_cond_assign.cpp
index f8011a16e5b..3c4d93201d2 100644
--- a/src/glsl/lower_vec_index_to_cond_assign.cpp
+++ b/src/glsl/lower_vec_index_to_cond_assign.cpp
@@ -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);
diff --git a/src/glsl/lower_vec_index_to_swizzle.cpp b/src/glsl/lower_vec_index_to_swizzle.cpp
index 9ae43c0db17..c7630c28a83 100644
--- a/src/glsl/lower_vec_index_to_swizzle.cpp
+++ b/src/glsl/lower_vec_index_to_swizzle.cpp
@@ -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);
diff --git a/src/glsl/lower_vector.cpp b/src/glsl/lower_vector.cpp
index 93c37638bbd..57963a121ad 100644
--- a/src/glsl/lower_vector.cpp
+++ b/src/glsl/lower_vector.cpp
@@ -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;
diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp
index 9b041aafe42..096da93dcef 100644
--- a/src/glsl/main.cpp
+++ b/src/glsl/main.cpp
@@ -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();
diff --git a/src/glsl/opt_algebraic.cpp b/src/glsl/opt_algebraic.cpp
index 20f6159f0e6..cade9611dbb 100644
--- a/src/glsl/opt_algebraic.cpp
+++ b/src/glsl/opt_algebraic.cpp
@@ -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: {
diff --git a/src/glsl/opt_constant_folding.cpp b/src/glsl/opt_constant_folding.cpp
index d69ca75fe03..599b21525de 100644
--- a/src/glsl/opt_constant_folding.cpp
+++ b/src/glsl/opt_constant_folding.cpp
@@ -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);
diff --git a/src/glsl/opt_constant_propagation.cpp b/src/glsl/opt_constant_propagation.cpp
index 6719fc81863..4425f421193 100644
--- a/src/glsl/opt_constant_propagation.cpp
+++ b/src/glsl/opt_constant_propagation.cpp
@@ -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;
diff --git a/src/glsl/opt_constant_variable.cpp b/src/glsl/opt_constant_variable.cpp
index 8068d0c1435..3fa7c3badc8 100644
--- a/src/glsl/opt_constant_variable.cpp
+++ b/src/glsl/opt_constant_variable.cpp
@@ -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)
diff --git a/src/glsl/opt_copy_propagation.cpp b/src/glsl/opt_copy_propagation.cpp
index 8d07fefbfd0..efa3afda35a 100644
--- a/src/glsl/opt_copy_propagation.cpp
+++ b/src/glsl/opt_copy_propagation.cpp
@@ -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
index 00000000000..8541d9a8ee1
--- /dev/null
+++ b/src/glsl/opt_copy_propagation_elements.cpp
@@ -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;
+}
diff --git a/src/glsl/opt_dead_code_local.cpp b/src/glsl/opt_dead_code_local.cpp
index 5689e7d20db..39962bd602e 100644
--- a/src/glsl/opt_dead_code_local.cpp
+++ b/src/glsl/opt_dead_code_local.cpp
@@ -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);
}
/**
diff --git a/src/glsl/opt_dead_functions.cpp b/src/glsl/opt_dead_functions.cpp
index cf91cb6d368..ceb79080a75 100644
--- a/src/glsl/opt_dead_functions.cpp
+++ b/src/glsl/opt_dead_functions.cpp
@@ -49,12 +49,12 @@
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 *);
diff --git a/src/glsl/opt_function_inlining.cpp b/src/glsl/opt_function_inlining.cpp
index 169fd826882..2e7831dcbdb 100644
--- a/src/glsl/opt_function_inlining.cpp
+++ b/src/glsl/opt_function_inlining.cpp
@@ -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);
}
}
diff --git a/src/glsl/opt_structure_splitting.cpp b/src/glsl/opt_structure_splitting.cpp
index d6191002c2f..014407c0be2 100644
--- a/src/glsl/opt_structure_splitting.cpp
+++ b/src/glsl/opt_structure_splitting.cpp
@@ -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;
}
diff --git a/src/glsl/opt_tree_grafting.cpp b/src/glsl/opt_tree_grafting.cpp
index 9917c045b1d..1ef940f9c72 100644
--- a/src/glsl/opt_tree_grafting.cpp
+++ b/src/glsl/opt_tree_grafting.cpp
@@ -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
index 00000000000..6a5eac6b9a3
--- /dev/null
+++ b/src/glsl/ralloc.c
@@ -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
index 00000000000..d5338152f10
--- /dev/null
+++ b/src/glsl/ralloc.h
@@ -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
diff --git a/src/glsl/s_expression.cpp b/src/glsl/s_expression.cpp
index 6edbf62e488..a922a50d3b9 100644
--- a/src/glsl/s_expression.cpp
+++ b/src/glsl/s_expression.cpp
@@ -22,15 +22,12 @@
* 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);
}
diff --git a/src/glsl/s_expression.h b/src/glsl/s_expression.h
index 795f3fccea7..c9dc676b319 100644
--- a/src/glsl/s_expression.h
+++ b/src/glsl/s_expression.h
@@ -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);
diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c
index 75b1a103f01..a275ba5b9fe 100644
--- a/src/glx/dri2_glx.c
+++ b/src/glx/dri2_glx.c
@@ -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;
}
diff --git a/src/glx/dri_glx.c b/src/glx/dri_glx.c
index 42b263c6377..ff027dc9e9c 100644
--- a/src/glx/dri_glx.c
+++ b/src/glx/dri_glx.c
@@ -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.
diff --git a/src/glx/drisw_glx.c b/src/glx/drisw_glx.c
index 237ce176176..5c7f40cdffa 100644
--- a/src/glx/drisw_glx.c
+++ b/src/glx/drisw_glx.c
@@ -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");
diff --git a/src/glx/glx_pbuffer.c b/src/glx/glx_pbuffer.c
index 34892e8b1a2..5f91bc623a9 100644
--- a/src/glx/glx_pbuffer.c
+++ b/src/glx/glx_pbuffer.c
@@ -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;
diff --git a/src/glx/glxclient.h b/src/glx/glxclient.h
index 36a0808c048..fdcef8075a8 100644
--- a/src/glx/glxclient.h
+++ b/src/glx/glxclient.h
@@ -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 *
diff --git a/src/glx/glxcmds.c b/src/glx/glxcmds.c
index d12ff9684e2..80eaf72b7d5 100644
--- a/src/glx/glxcmds.c
+++ b/src/glx/glxcmds.c
@@ -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;
diff --git a/src/glx/glxext.c b/src/glx/glxext.c
index c5e9d0510b6..25d266e18e1 100644
--- a/src/glx/glxext.c
+++ b/src/glx/glxext.c
@@ -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.
diff --git a/src/mapi/es1api/.gitignore b/src/mapi/es1api/.gitignore
index 7c9ca37247b..b21f1d14c6f 100644
--- a/src/mapi/es1api/.gitignore
+++ b/src/mapi/es1api/.gitignore
@@ -1,3 +1,4 @@
+glapi_mapi_tmp.h
glapi-stamp
glapi
main
diff --git a/src/mapi/es1api/Makefile b/src/mapi/es1api/Makefile
index 4fa68e5c39d..aef694866c2 100644
--- a/src/mapi/es1api/Makefile
+++ b/src/mapi/es1api/Makefile
@@ -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
diff --git a/src/mapi/es2api/.gitignore b/src/mapi/es2api/.gitignore
index 7c9ca37247b..b21f1d14c6f 100644
--- a/src/mapi/es2api/.gitignore
+++ b/src/mapi/es2api/.gitignore
@@ -1,3 +1,4 @@
+glapi_mapi_tmp.h
glapi-stamp
glapi
main
diff --git a/src/mapi/glapi/Makefile b/src/mapi/glapi/Makefile
index 203a8abd018..bb4ed6585d9 100644
--- a/src/mapi/glapi/Makefile
+++ b/src/mapi/glapi/Makefile
@@ -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
diff --git a/src/mapi/glapi/SConscript b/src/mapi/glapi/SConscript
index 4057991ec8d..276b2160246 100644
--- a/src/mapi/glapi/SConscript
+++ b/src/mapi/glapi/SConscript
@@ -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',
diff --git a/src/mapi/glapi/gen/gl_x86-64_asm.py b/src/mapi/glapi/gen/gl_x86-64_asm.py
index 2fa140dc308..11cd9af4061 100644
--- a/src/mapi/glapi/gen/gl_x86-64_asm.py
+++ b/src/mapi/glapi/gen/gl_x86-64_asm.py
@@ -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)'
diff --git a/src/mapi/glapi/gen/gl_x86_asm.py b/src/mapi/glapi/gen/gl_x86_asm.py
index 21996a39421..4ef4acb564e 100644
--- a/src/mapi/glapi/gen/gl_x86_asm.py
+++ b/src/mapi/glapi/gen/gl_x86_asm.py
@@ -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'
diff --git a/src/mapi/glapi/glapi.h b/src/mapi/glapi/glapi.h
index 8cca50487c4..e909cf892ab 100644
--- a/src/mapi/glapi/glapi.h
+++ b/src/mapi/glapi/glapi.h
@@ -45,11 +45,6 @@
#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 */
diff --git a/src/mapi/glapi/glapi_x86-64.S b/src/mapi/glapi/glapi_x86-64.S
index 469fac31ae6..c42646f0165 100644
--- a/src/mapi/glapi/glapi_x86-64.S
+++ b/src/mapi/glapi/glapi_x86-64.S
@@ -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)
diff --git a/src/mapi/glapi/glapi_x86.S b/src/mapi/glapi/glapi_x86.S
index fa448c1704f..8d85f61ce00 100644
--- a/src/mapi/glapi/glapi_x86.S
+++ b/src/mapi/glapi/glapi_x86.S
@@ -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
diff --git a/src/mapi/mapi/entry.c b/src/mapi/mapi/entry.c
index f378ccfda95..3d9168a7243 100644
--- a/src/mapi/mapi/entry.c
+++ b/src/mapi/mapi/entry.c
@@ -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
index 00000000000..c3e0647dd81
--- /dev/null
+++ b/src/mapi/shared-glapi/.gitignore
@@ -0,0 +1,2 @@
+glapi_mapi_tmp.h
+
diff --git a/src/mapi/shared-glapi/Makefile b/src/mapi/shared-glapi/Makefile
index ee937bd681b..c928f822c81 100644
--- a/src/mapi/shared-glapi/Makefile
+++ b/src/mapi/shared-glapi/Makefile
@@ -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
index 00000000000..b7c43a73476
--- /dev/null
+++ b/src/mapi/shared-glapi/SConscript
@@ -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'])
diff --git a/src/mapi/vgapi/Makefile b/src/mapi/vgapi/Makefile
index e239e20987e..68cf26e83c3 100644
--- a/src/mapi/vgapi/Makefile
+++ b/src/mapi/vgapi/Makefile
@@ -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
diff --git a/src/mesa/Makefile b/src/mesa/Makefile
index 25e7cce425c..48f79a5d550 100644
--- a/src/mesa/Makefile
+++ b/src/mesa/Makefile
@@ -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)/[email protected] \
+ $(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
diff --git a/src/mesa/SConscript b/src/mesa/SConscript
index cc4ad09fa33..ea04fb1a0ee 100644
--- a/src/mesa/SConscript
+++ b/src/mesa/SConscript
@@ -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
#
diff --git a/src/mesa/drivers/beos/GLView.cpp b/src/mesa/drivers/beos/GLView.cpp
index ee3415b3d1a..57c4614f32d 100644
--- a/src/mesa/drivers/beos/GLView.cpp
+++ b/src/mesa/drivers/beos/GLView.cpp
@@ -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;
diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c
index 3c6ecb83f0a..5389a500111 100644
--- a/src/mesa/drivers/common/driverfuncs.c
+++ b/src/mesa/drivers/common/driverfuncs.c
@@ -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;
diff --git a/src/mesa/drivers/dri/Makefile.template b/src/mesa/drivers/dri/Makefile.template
index 4ecddbc0483..d1a119379ed 100644
--- a/src/mesa/drivers/dri/Makefile.template
+++ b/src/mesa/drivers/dri/Makefile.template
@@ -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 [email protected] -noprefix -linker '$(CXX)' -ldflags '$(LDFLAGS)' \
- $(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) $(DRI_LIB_DEPS)
+ $(OBJECTS) $(EXTRA_MODULES) $(DRI_LIB_DEPS)
$(CXX) $(CFLAGS) -o [email protected] $(TOP)/src/mesa/drivers/dri/common/dri_test.o [email protected] $(DRI_LIB_DEPS)
diff --git a/src/mesa/drivers/dri/common/dri_metaops.c b/src/mesa/drivers/dri/common/dri_metaops.c
deleted file mode 100644
index e0bc3b88ecd..00000000000
--- a/src/mesa/drivers/dri/common/dri_metaops.c
+++ /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
index aa7d4baa6e9..00000000000
--- a/src/mesa/drivers/dri/common/dri_metaops.h
+++ /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
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
index bf8cf6eec07..82638fa7207 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -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 = {
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
index ffffb99b301..3d3d5c9cd24 100644
--- a/src/mesa/drivers/dri/common/dri_util.h
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -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;
diff --git a/src/mesa/drivers/dri/common/drisw_util.c b/src/mesa/drivers/dri/common/drisw_util.c
index 1529c23b16d..1bdb6d8939e 100644
--- a/src/mesa/drivers/dri/common/drisw_util.c
+++ b/src/mesa/drivers/dri/common/drisw_util.c
@@ -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
};
diff --git a/src/mesa/drivers/dri/i810/i810context.c b/src/mesa/drivers/dri/i810/i810context.c
index dc58e91e8c1..90dbb6bbe80 100644
--- a/src/mesa/drivers/dri/i810/i810context.c
+++ b/src/mesa/drivers/dri/i810/i810context.c
@@ -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);
diff --git a/src/mesa/drivers/dri/i915/i830_vtbl.c b/src/mesa/drivers/dri/i915/i830_vtbl.c
index ebdefeac874..19f08077599 100644
--- a/src/mesa/drivers/dri/i915/i830_vtbl.c
+++ b/src/mesa/drivers/dri/i915/i830_vtbl.c
@@ -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
diff --git a/src/mesa/drivers/dri/i915/i915_context.c b/src/mesa/drivers/dri/i915/i915_context.c
index 474252b640d..7389a1d57a9 100644
--- a/src/mesa/drivers/dri/i915/i915_context.c
+++ b/src/mesa/drivers/dri/i915/i915_context.c
@@ -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;
diff --git a/src/mesa/drivers/dri/i915/i915_context.h b/src/mesa/drivers/dri/i915/i915_context.h
index 2c80ded075b..601620275f4 100644
--- a/src/mesa/drivers/dri/i915/i915_context.h
+++ b/src/mesa/drivers/dri/i915/i915_context.h
@@ -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
@@ -77,17 +77,19 @@
#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;
};
diff --git a/src/mesa/drivers/dri/i915/i915_fragprog.c b/src/mesa/drivers/dri/i915/i915_fragprog.c
index 1c6e9845172..25f4fc3c8b1 100644
--- a/src/mesa/drivers/dri/i915/i915_fragprog.c
+++ b/src/mesa/drivers/dri/i915/i915_fragprog.c
@@ -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;
diff --git a/src/mesa/drivers/dri/i915/i915_program.c b/src/mesa/drivers/dri/i915/i915_program.c
index ca1949b223e..507adf1d3dc 100644
--- a/src/mesa/drivers/dri/i915/i915_program.c
+++ b/src/mesa/drivers/dri/i915/i915_program.c
@@ -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;
diff --git a/src/mesa/drivers/dri/i915/i915_reg.h b/src/mesa/drivers/dri/i915/i915_reg.h
index 7f31ff674f2..766547a4c6a 100644
--- a/src/mesa/drivers/dri/i915/i915_reg.h
+++ b/src/mesa/drivers/dri/i915/i915_reg.h
@@ -361,13 +361,6 @@
/* 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.
diff --git a/src/mesa/drivers/dri/i915/i915_state.c b/src/mesa/drivers/dri/i915/i915_state.c
index 63c6e78ebe9..58d4f5daffd 100644
--- a/src/mesa/drivers/dri/i915/i915_state.c
+++ b/src/mesa/drivers/dri/i915/i915_state.c
@@ -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);
diff --git a/src/mesa/drivers/dri/i915/i915_vtbl.c b/src/mesa/drivers/dri/i915/i915_vtbl.c
index a94b9571275..921183b81df 100644
--- a/src/mesa/drivers/dri/i915/i915_vtbl.c
+++ b/src/mesa/drivers/dri/i915/i915_vtbl.c
@@ -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
diff --git a/src/mesa/drivers/dri/i915/intel_render.c b/src/mesa/drivers/dri/i915/intel_render.c
index 0d8ab4b507e..2d361ca0a9a 100644
--- a/src/mesa/drivers/dri/i915/intel_render.c
+++ b/src/mesa/drivers/dri/i915/intel_render.c
@@ -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);
diff --git a/src/mesa/drivers/dri/i915/intel_tris.c b/src/mesa/drivers/dri/i915/intel_tris.c
index b9a8aeb12f2..cf9291cdfca 100644
--- a/src/mesa/drivers/dri/i915/intel_tris.c
+++ b/src/mesa/drivers/dri/i915/intel_tris.c
@@ -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);
diff --git a/src/mesa/drivers/dri/i965/brw_cc.c b/src/mesa/drivers/dri/i965/brw_cc.c
index c986970a757..412d82ab3ca 100644
--- a/src/mesa/drivers/dri/i965/brw_cc.c
+++ b/src/mesa/drivers/dri/i965/brw_cc.c
@@ -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 = {
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index 7069724466a..3e52304f6ab 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -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
-
diff --git a/src/mesa/drivers/dri/i965/brw_cubemap_normalize.cpp b/src/mesa/drivers/dri/i965/brw_cubemap_normalize.cpp
index 35bea681214..8574169e472 100644
--- a/src/mesa/drivers/dri/i965/brw_cubemap_normalize.cpp
+++ b/src/mesa/drivers/dri/i965/brw_cubemap_normalize.cpp
@@ -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);
diff --git a/src/mesa/drivers/dri/i965/brw_curbe.c b/src/mesa/drivers/dri/i965/brw_curbe.c
index 877b22fec19..ae11c487a2c 100644
--- a/src/mesa/drivers/dri/i965/brw_curbe.c
+++ b/src/mesa/drivers/dri/i965/brw_curbe.c
@@ -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] = {
diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h
index 2f7dcc2dda7..a413c02b573 100644
--- a/src/mesa/drivers/dri/i965/brw_defines.h
+++ b/src/mesa/drivers/dri/i965/brw_defines.h
@@ -817,8 +817,8 @@
#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)
diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c
index 7eb16b71f4a..f5abe021c43 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.c
+++ b/src/mesa/drivers/dri/i965/brw_draw.c
@@ -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;
diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c
index 2cefe614dd2..7234ce210b5 100644
--- a/src/mesa/drivers/dri/i965/brw_draw_upload.c
+++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c
@@ -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 = {
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 9a71e5377df..30e3bd54469 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -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
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index f0497957bc4..8352760acf7 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -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);
diff --git a/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp
index 20bfa4c3ea3..7f3f52854d2 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp
@@ -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()) {
diff --git a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp
index 078a349abdf..f0277423170 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp
@@ -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;
}
diff --git a/src/mesa/drivers/dri/i965/brw_fs_schedule_instructions.cpp b/src/mesa/drivers/dri/i965/brw_fs_schedule_instructions.cpp
index c8f0b27b76f..bff8f82f3f7 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_schedule_instructions.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_schedule_instructions.cpp
@@ -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;
diff --git a/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp b/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp
index 2be6b08b5c7..530ffa26580 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp
@@ -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;
}
diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c
index 79afe19deba..c768be23fa7 100644
--- a/src/mesa/drivers/dri/i965/brw_misc_state.c
+++ b/src/mesa/drivers/dri/i965/brw_misc_state.c
@@ -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 */
diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c
index 94efa791091..7d653327e30 100644
--- a/src/mesa/drivers/dri/i965/brw_program.c
+++ b/src/mesa/drivers/dri/i965/brw_program.c
@@ -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;
}
}
diff --git a/src/mesa/drivers/dri/i965/brw_queryobj.c b/src/mesa/drivers/dri/i965/brw_queryobj.c
index 656aad630a1..b41d05dd438 100644
--- a/src/mesa/drivers/dri/i965/brw_queryobj.c
+++ b/src/mesa/drivers/dri/i965/brw_queryobj.c
@@ -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;
diff --git a/src/mesa/drivers/dri/i965/brw_state.h b/src/mesa/drivers/dri/i965/brw_state.h
index 4bb93e73369..86b0caa4a4e 100644
--- a/src/mesa/drivers/dri/i965/brw_state.h
+++ b/src/mesa/drivers/dri/i965/brw_state.h
@@ -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
diff --git a/src/mesa/drivers/dri/i965/brw_state_batch.c b/src/mesa/drivers/dri/i965/brw_state_batch.c
index a21af13caa3..213c7a38d8c 100644
--- a/src/mesa/drivers/dri/i965/brw_state_batch.c
+++ b/src/mesa/drivers/dri/i965/brw_state_batch.c
@@ -29,75 +29,10 @@
* Keith Whitwell <[email protected]>
*/
-
-
#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);
}
diff --git a/src/mesa/drivers/dri/i965/brw_state_cache.c b/src/mesa/drivers/dri/i965/brw_state_cache.c
index 7045888ad4a..01eeb19a684 100644
--- a/src/mesa/drivers/dri/i965/brw_state_cache.c
+++ b/src/mesa/drivers/dri/i965/brw_state_cache.c
@@ -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.
*/
diff --git a/src/mesa/drivers/dri/i965/brw_state_dump.c b/src/mesa/drivers/dri/i965/brw_state_dump.c
index e2628874712..fdce79da2f4 100644
--- a/src/mesa/drivers/dri/i965/brw_state_dump.c
+++ b/src/mesa/drivers/dri/i965/brw_state_dump.c
@@ -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) {
diff --git a/src/mesa/drivers/dri/i965/brw_state_upload.c b/src/mesa/drivers/dri/i965/brw_state_upload.c
index eba4411ca70..2d6fb37355d 100644
--- a/src/mesa/drivers/dri/i965/brw_state_upload.c
+++ b/src/mesa/drivers/dri/i965/brw_state_upload.c
@@ -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 */
diff --git a/src/mesa/drivers/dri/i965/brw_util.c b/src/mesa/drivers/dri/i965/brw_util.c
index e878da3850d..d28d9abcb33 100644
--- a/src/mesa/drivers/dri/i965/brw_util.c
+++ b/src/mesa/drivers/dri/i965/brw_util.c
@@ -37,16 +37,6 @@
#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) {
diff --git a/src/mesa/drivers/dri/i965/brw_util.h b/src/mesa/drivers/dri/i965/brw_util.h
index 04f3175d3e1..940a8715502 100644
--- a/src/mesa/drivers/dri/i965/brw_util.h
+++ b/src/mesa/drivers/dri/i965/brw_util.h
@@ -35,7 +35,14 @@
#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 );
diff --git a/src/mesa/drivers/dri/i965/brw_vs_surface_state.c b/src/mesa/drivers/dri/i965/brw_vs_surface_state.c
index b0b05445eb9..48cf265e51b 100644
--- a/src/mesa/drivers/dri/i965/brw_vs_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_vs_surface_state.c
@@ -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;
diff --git a/src/mesa/drivers/dri/i965/brw_vtbl.c b/src/mesa/drivers/dri/i965/brw_vtbl.c
index 100a21b59d7..152ee141568 100644
--- a/src/mesa/drivers/dri/i965/brw_vtbl.c
+++ b/src/mesa/drivers/dri/i965/brw_vtbl.c
@@ -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 )
diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c
index 656501b4f79..ee8212f6f16 100644
--- a/src/mesa/drivers/dri/i965/brw_wm.c
+++ b/src/mesa/drivers/dri/i965/brw_wm.c
@@ -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;
diff --git a/src/mesa/drivers/dri/i965/brw_wm_state.c b/src/mesa/drivers/dri/i965/brw_wm_state.c
index e9ef635bca2..5b5afc4626b 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_state.c
@@ -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;
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index a372554555c..1010d9f6f9c 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -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;
diff --git a/src/mesa/drivers/dri/i965/gen6_cc.c b/src/mesa/drivers/dri/i965/gen6_cc.c
index f51afa40716..d1648a102d4 100644
--- a/src/mesa/drivers/dri/i965/gen6_cc.c
+++ b/src/mesa/drivers/dri/i965/gen6_cc.c
@@ -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);
}
diff --git a/src/mesa/drivers/dri/i965/gen6_sf_state.c b/src/mesa/drivers/dri/i965/gen6_sf_state.c
index f27782935d4..50a5ad38c6f 100644
--- a/src/mesa/drivers/dri/i965/gen6_sf_state.c
+++ b/src/mesa/drivers/dri/i965/gen6_sf_state.c
@@ -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;
diff --git a/src/mesa/drivers/dri/intel/intel_batchbuffer.c b/src/mesa/drivers/dri/intel/intel_batchbuffer.c
index 67ce8a4da02..42b4f923e0c 100644
--- a/src/mesa/drivers/dri/intel/intel_batchbuffer.c
+++ b/src/mesa/drivers/dri/intel/intel_batchbuffer.c
@@ -27,89 +27,89 @@
#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);
diff --git a/src/mesa/drivers/dri/intel/intel_batchbuffer.h b/src/mesa/drivers/dri/intel/intel_batchbuffer.h
index 635708587a6..a0a5c9841c6 100644
--- a/src/mesa/drivers/dri/intel/intel_batchbuffer.h
+++ b/src/mesa/drivers/dri/intel/intel_batchbuffer.h
@@ -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
diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c
index 6232e479cb6..e1ab7f16371 100644
--- a/src/mesa/drivers/dri/intel/intel_blit.c
+++ b/src/mesa/drivers/dri/intel/intel_blit.c
@@ -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);
}
diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.c b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
index d917161c4be..2f750a768af 100644
--- a/src/mesa/drivers/dri/intel/intel_buffer_objects.c
+++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
@@ -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
diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.h b/src/mesa/drivers/dri/intel/intel_buffer_objects.h
index b15c1921061..3ec3a521382 100644
--- a/src/mesa/drivers/dri/intel/intel_buffer_objects.h
+++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.h
@@ -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);
diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c
index 2a5029964be..c2e2a98af5e 100644
--- a/src/mesa/drivers/dri/intel/intel_context.c
+++ b/src/mesa/drivers/dri/intel/intel_context.c
@@ -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);
diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h
index fd3c3ba58fc..772b2fba5a8 100644
--- a/src/mesa/drivers/dri/intel/intel_context.h
+++ b/src/mesa/drivers/dri/intel/intel_context.h
@@ -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:
diff --git a/src/mesa/drivers/dri/intel/intel_extensions.c b/src/mesa/drivers/dri/intel/intel_extensions.c
index 747e9dcb717..febc1d4f859 100644
--- a/src/mesa/drivers/dri/intel/intel_extensions.c
+++ b/src/mesa/drivers/dri/intel/intel_extensions.c
@@ -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 },
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c
index 0db5a491c8f..8b57eb19f56 100644
--- a/src/mesa/drivers/dri/intel/intel_fbo.c
+++ b/src/mesa/drivers/dri/intel/intel_fbo.c
@@ -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 =
diff --git a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
index e7356a6da0d..d7561ee689d 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
+++ b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
@@ -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 */
diff --git a/src/mesa/drivers/dri/intel/intel_pixel_read.c b/src/mesa/drivers/dri/intel/intel_pixel_read.c
index 54da29236d2..b2e77c7986a 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel_read.c
+++ b/src/mesa/drivers/dri/intel/intel_pixel_read.c
@@ -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
diff --git a/src/mesa/drivers/dri/intel/intel_regions.c b/src/mesa/drivers/dri/intel/intel_regions.c
index e87e29462c3..0857fa8ad70 100644
--- a/src/mesa/drivers/dri/intel/intel_regions.c
+++ b/src/mesa/drivers/dri/intel/intel_regions.c
@@ -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:
*/
diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
index 5d14bcd34c0..356d5f72d89 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -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. */
diff --git a/src/mesa/drivers/dri/intel/intel_syncobj.c b/src/mesa/drivers/dri/intel/intel_syncobj.c
index bbfac74b605..b303ea84dd8 100644
--- a/src/mesa/drivers/dri/intel/intel_syncobj.c
+++ b/src/mesa/drivers/dri/intel/intel_syncobj.c
@@ -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);
diff --git a/src/mesa/drivers/dri/intel/intel_tex.h b/src/mesa/drivers/dri/intel/intel_tex.h
index 6552ed0d332..52462f39d54 100644
--- a/src/mesa/drivers/dri/intel/intel_tex.h
+++ b/src/mesa/drivers/dri/intel/intel_tex.h
@@ -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
diff --git a/src/mesa/drivers/dri/intel/intel_tex_copy.c b/src/mesa/drivers/dri/intel/intel_tex_copy.c
index a40011ab40c..136d8e1d0a9 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_copy.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_copy.c
@@ -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);
diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c
index cd8c4c22e5a..9dba529c58d 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_image.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_image.c
@@ -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);
}
diff --git a/src/mesa/drivers/dri/mach64/mach64_context.c b/src/mesa/drivers/dri/mach64/mach64_context.c
index 7c989df5ec0..35b01a97402 100644
--- a/src/mesa/drivers/dri/mach64/mach64_context.c
+++ b/src/mesa/drivers/dri/mach64/mach64_context.c
@@ -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);
diff --git a/src/mesa/drivers/dri/mga/mga_xmesa.c b/src/mesa/drivers/dri/mga/mga_xmesa.c
index d1b281a2c05..eb7df9785c1 100644
--- a/src/mesa/drivers/dri/mga/mga_xmesa.c
+++ b/src/mesa/drivers/dri/mga/mga_xmesa.c
@@ -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);
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c
index 53a121420d3..71dde413873 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c
@@ -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);
diff --git a/src/mesa/drivers/dri/r128/r128_context.c b/src/mesa/drivers/dri/r128/r128_context.c
index 274108005f3..247d86ca008 100644
--- a/src/mesa/drivers/dri/r128/r128_context.c
+++ b/src/mesa/drivers/dri/r128/r128_context.c
@@ -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);
diff --git a/src/mesa/drivers/dri/r200/r200_vertprog.c b/src/mesa/drivers/dri/r200/r200_vertprog.c
index 5d69012a81f..63e03b0e0c7 100644
--- a/src/mesa/drivers/dri/r200/r200_vertprog.c
+++ b/src/mesa/drivers/dri/r200/r200_vertprog.c
@@ -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;
}
diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c
index 782671bac01..deba9ca834d 100644
--- a/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c
+++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog.c
@@ -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 ",
diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c
index 1db8678e890..28d132a5fe3 100644
--- a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c
+++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c
@@ -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;
+ }
}
diff --git a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c
index 05d3da8a10d..fa906f2fdde 100644
--- a/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c
+++ b/src/mesa/drivers/dri/r300/compiler/r300_fragprog_swizzle.c
@@ -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;
diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
index e0d349b98ce..1616306afbd 100644
--- a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
+++ b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
@@ -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},
diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
index 472029f63d0..8ad2175eadf 100644
--- a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
+++ b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
@@ -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;
}
diff --git a/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c
index 5da82d90f67..1febc19cc2d 100644
--- a/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c
+++ b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c
@@ -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;
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.h b/src/mesa/drivers/dri/r300/compiler/radeon_code.h
index b69e81698ae..d1451668947 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_code.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_code.h
@@ -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;
};
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c
index 65548604bcc..79cd7996f78 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.c
@@ -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);
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
index e6633395895..2d8e415f350 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
@@ -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);
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c
index 2482fc68beb..15ec4418cb8 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.c
@@ -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);
}
}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h
index 461ab9ffb10..dd0f6c66156 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler_util.h
@@ -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);
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
index d0a64d936e0..c080d5aecc6 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
@@ -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;
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c
index 87906f37b12..678e1475883 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c
@@ -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);
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c
index 44f4c0fbdc7..5caff91b00e 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c
@@ -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;
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c b/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c
index 9beb5d63579..8e10813ff06 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c
@@ -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;
}
}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c b/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c
index fc05366f50e..6d7263b4ab6 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c
@@ -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;
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program.h b/src/mesa/drivers/dri/r300/compiler/radeon_program.h
index df6c94b35f9..a07f6b63c6e 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program.h
@@ -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;
};
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c
index c8063171b81..9fc991166a3 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c
@@ -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;
}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c
index 5905d26e521..68874795b8a 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.c
@@ -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];
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h
index ccf7a0070cd..6708b16d29a 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h
@@ -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;
};
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c
index ae13f6742f8..390d1319460 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c
@@ -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");
}
diff --git a/src/mesa/drivers/dri/r300/r300_blit.c b/src/mesa/drivers/dri/r300/r300_blit.c
index 9fd8e8fde5f..14e60866d93 100644
--- a/src/mesa/drivers/dri/r300/r300_blit.c
+++ b/src/mesa/drivers/dri/r300/r300_blit.c
@@ -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;
diff --git a/src/mesa/drivers/dri/r300/r300_fragprog_common.c b/src/mesa/drivers/dri/r300/r300_fragprog_common.c
index 4e457b51eba..a0a26f1b38d 100644
--- a/src/mesa/drivers/dri/r300/r300_fragprog_common.c
+++ b/src/mesa/drivers/dri/r300/r300_fragprog_common.c
@@ -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;
diff --git a/src/mesa/drivers/dri/r300/r300_reg.h b/src/mesa/drivers/dri/r300/r300_reg.h
index f7705b0f6fe..2b9d85fae8b 100644
--- a/src/mesa/drivers/dri/r300/r300_reg.h
+++ b/src/mesa/drivers/dri/r300/r300_reg.h
@@ -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)
diff --git a/src/mesa/drivers/dri/r300/radeon_mesa_to_rc.c b/src/mesa/drivers/dri/r300/radeon_mesa_to_rc.c
index 471a3723cb9..232603ece59 100644
--- a/src/mesa/drivers/dri/r300/radeon_mesa_to_rc.c
+++ b/src/mesa/drivers/dri/r300/radeon_mesa_to_rc.c
@@ -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;
}
diff --git a/src/mesa/drivers/dri/r600/evergreen_fragprog.c b/src/mesa/drivers/dri/r600/evergreen_fragprog.c
index cfb923efdd5..e527c379b62 100644
--- a/src/mesa/drivers/dri/r600/evergreen_fragprog.c
+++ b/src/mesa/drivers/dri/r600/evergreen_fragprog.c
@@ -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);
}
}
diff --git a/src/mesa/drivers/dri/r600/r700_fragprog.c b/src/mesa/drivers/dri/r600/r700_fragprog.c
index 0323e32d705..40494cd6af0 100644
--- a/src/mesa/drivers/dri/r600/r700_fragprog.c
+++ b/src/mesa/drivers/dri/r600/r700_fragprog.c
@@ -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);
}
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_chipset.h b/src/mesa/drivers/dri/radeon/radeon_chipset.h
index 399052cbcbd..bd6f1c79504 100644
--- a/src/mesa/drivers/dri/radeon/radeon_chipset.h
+++ b/src/mesa/drivers/dri/radeon/radeon_chipset.h
@@ -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
diff --git a/src/mesa/drivers/dri/radeon/radeon_common.c b/src/mesa/drivers/dri/radeon/radeon_common.c
index 7361adffcf7..0d73c0e3b1b 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common.c
+++ b/src/mesa/drivers/dri/radeon/radeon_common.c
@@ -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);
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.c b/src/mesa/drivers/dri/radeon/radeon_common_context.c
index 819d9dd5750..405aecb19ec 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common_context.c
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.c
@@ -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 );
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h
index c62913afd0c..3895ab8c4d8 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common_context.h
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h
@@ -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;
diff --git a/src/mesa/drivers/dri/radeon/radeon_fbo.c b/src/mesa/drivers/dri/radeon/radeon_fbo.c
index 6656d391e09..d3c9257fb66 100644
--- a/src/mesa/drivers/dri/radeon/radeon_fbo.c
+++ b/src/mesa/drivers/dri/radeon/radeon_fbo.c
@@ -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);
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c
index a35fcfe9d7f..56c5959b0aa 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.c
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.c
@@ -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:
diff --git a/src/mesa/drivers/dri/savage/savage_xmesa.c b/src/mesa/drivers/dri/savage/savage_xmesa.c
index 92fb4f44884..681ed9aae34 100644
--- a/src/mesa/drivers/dri/savage/savage_xmesa.c
+++ b/src/mesa/drivers/dri/savage/savage_xmesa.c
@@ -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;
diff --git a/src/mesa/drivers/dri/sis/sis_context.c b/src/mesa/drivers/dri/sis/sis_context.c
index c5a9fdfb2a0..26ecfc463ca 100644
--- a/src/mesa/drivers/dri/sis/sis_context.c
+++ b/src/mesa/drivers/dri/sis/sis_context.c
@@ -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);
diff --git a/src/mesa/drivers/dri/swrast/swrast.c b/src/mesa/drivers/dri/swrast/swrast.c
index c7940e9c0da..719b406ec05 100644
--- a/src/mesa/drivers/dri/swrast/swrast.c
+++ b/src/mesa/drivers/dri/swrast/swrast.c
@@ -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;
diff --git a/src/mesa/drivers/dri/tdfx/tdfx_context.c b/src/mesa/drivers/dri/tdfx/tdfx_context.c
index 63dfa5ae746..ad151359e67 100644
--- a/src/mesa/drivers/dri/tdfx/tdfx_context.c
+++ b/src/mesa/drivers/dri/tdfx/tdfx_context.c
@@ -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);
diff --git a/src/mesa/drivers/dri/unichrome/via_context.c b/src/mesa/drivers/dri/unichrome/via_context.c
index 963609bde4a..77d7116611a 100644
--- a/src/mesa/drivers/dri/unichrome/via_context.c
+++ b/src/mesa/drivers/dri/unichrome/via_context.c
@@ -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;
diff --git a/src/mesa/drivers/fbdev/glfbdev.c b/src/mesa/drivers/fbdev/glfbdev.c
index 5195bca97fa..1e0ac4c7a1f 100644
--- a/src/mesa/drivers/fbdev/glfbdev.c
+++ b/src/mesa/drivers/fbdev/glfbdev.c
@@ -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);
diff --git a/src/mesa/drivers/osmesa/Makefile b/src/mesa/drivers/osmesa/Makefile
index 50dd4526e19..39ab09af805 100644
--- a/src/mesa/drivers/osmesa/Makefile
+++ b/src/mesa/drivers/osmesa/Makefile
@@ -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)
diff --git a/src/mesa/drivers/osmesa/osmesa.c b/src/mesa/drivers/osmesa/osmesa.c
index e1f0c69bacf..98f01fe057e 100644
--- a/src/mesa/drivers/osmesa/osmesa.c
+++ b/src/mesa/drivers/osmesa/osmesa.c
@@ -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,
diff --git a/src/mesa/drivers/windows/gdi/wmesa.c b/src/mesa/drivers/windows/gdi/wmesa.c
index 833e2526f3c..4a8b1b283d5 100644
--- a/src/mesa/drivers/windows/gdi/wmesa.c
+++ b/src/mesa/drivers/windows/gdi/wmesa.c
@@ -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);
diff --git a/src/mesa/drivers/windows/gldirect/dglcontext.c b/src/mesa/drivers/windows/gldirect/dglcontext.c
index 10ea0578506..9aedd2e3c4d 100644
--- a/src/mesa/drivers/windows/gldirect/dglcontext.c
+++ b/src/mesa/drivers/windows/gldirect/dglcontext.c
@@ -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)(
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c
index 1c43a38557d..1b070f0a11e 100644
--- a/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c
@@ -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);
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c
index 7fc50004de8..d66318e1149 100644
--- a/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c
@@ -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"
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c
index c4c2e0b5676..4c272c95d6c 100644
--- a/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c
@@ -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);
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c
index 5b9dac09c6d..a2c5d87ecd5 100644
--- a/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c
@@ -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"
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c
index aab70852016..171585dcf81 100644
--- a/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c
@@ -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);
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c
index 99edd26e9d2..65a00ae1b59 100644
--- a/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c
@@ -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"
diff --git a/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c b/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c
index 7a26df8071e..bc66ec79888 100644
--- a/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c
+++ b/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c
@@ -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"
diff --git a/src/mesa/drivers/x11/fakeglx.c b/src/mesa/drivers/x11/fakeglx.c
index 577e27d4da3..48657b44be1 100644
--- a/src/mesa/drivers/x11/fakeglx.c
+++ b/src/mesa/drivers/x11/fakeglx.c
@@ -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);
diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c
index b5eabadf486..aad902d1eda 100644
--- a/src/mesa/drivers/x11/xm_api.c
+++ b/src/mesa/drivers/x11/xm_api.c
@@ -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 */
diff --git a/src/mesa/drivers/x11/xmesa.h b/src/mesa/drivers/x11/xmesa.h
index 98737fab248..347394e0a26 100644
--- a/src/mesa/drivers/x11/xmesa.h
+++ b/src/mesa/drivers/x11/xmesa.h
@@ -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 );
diff --git a/src/mesa/main/APIspec.xml b/src/mesa/main/APIspec.xml
index 50446a9093a..0f82d0a38e1 100644
--- a/src/mesa/main/APIspec.xml
+++ b/src/mesa/main/APIspec.xml
@@ -379,15 +379,68 @@
<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">
diff --git a/src/mesa/main/accum.c b/src/mesa/main/accum.c
index 940f398f023..6a83930a13d 100644
--- a/src/mesa/main/accum.c
+++ b/src/mesa/main/accum.c
@@ -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 );
}
diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c
index 9e9728c2c62..46010223370 100644
--- a/src/mesa/main/arrayobj.c
+++ b/src/mesa/main/arrayobj.c
@@ -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++) {
diff --git a/src/mesa/main/blend.c b/src/mesa/main/blend.c
index 43e2f7f8617..c74a168036a 100644
--- a/src/mesa/main/blend.c
+++ b/src/mesa/main/blend.c
@@ -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:
diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c
index 1f9a5212c04..75afae0add1 100644
--- a/src/mesa/main/bufferobj.c
+++ b/src/mesa/main/bufferobj.c
@@ -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;
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index e017939a45c..a942314552e 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -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;
@@ -1029,25 +1029,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
* we need to at least call driverFunctions->NewTextureObject to initialize
@@ -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 {
@@ -1090,22 +1071,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.
*
* But doesn't free the struct gl_context struct itself.
diff --git a/src/mesa/main/context.h b/src/mesa/main/context.h
index 8fb9b4c6b7a..4e391dde494 100644
--- a/src/mesa/main/context.h
+++ b/src/mesa/main/context.h
@@ -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 );
diff --git a/src/mesa/main/debug.c b/src/mesa/main/debug.c
index a6a909b48ce..78881668e49 100644
--- a/src/mesa/main/debug.c
+++ b/src/mesa/main/debug.c
@@ -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);
}
}
diff --git a/src/mesa/main/debug.h b/src/mesa/main/debug.h
index 17aa897e8d1..4968a9f1979 100644
--- a/src/mesa/main/debug.h
+++ b/src/mesa/main/debug.h
@@ -64,6 +64,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);
extern void
diff --git a/src/mesa/main/depth.c b/src/mesa/main/depth.c
index 0bb47731ea3..52c69a6bcd9 100644
--- a/src/mesa/main/depth.c
+++ b/src/mesa/main/depth.c
@@ -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;
diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c
index cdf349104a4..8e904c7787a 100644
--- a/src/mesa/main/dlist.c
+++ b/src/mesa/main/dlist.c
@@ -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;
diff --git a/src/mesa/main/drawpix.c b/src/mesa/main/drawpix.c
index 6fda3c5665c..df4712de894 100644
--- a/src/mesa/main/drawpix.c
+++ b/src/mesa/main/drawpix.c
@@ -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;
diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c
index c4c4e1bb29d..ea3b8214c3b 100644
--- a/src/mesa/main/enable.c
+++ b/src/mesa/main/enable.c
@@ -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;
diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
index 113ac405073..7504b8a85db 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -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;
}
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index f31d8b36db8..ab6b2a9b17b 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -373,6 +373,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.
*/
static void
@@ -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);
}
diff --git a/src/mesa/main/fbobject.h b/src/mesa/main/fbobject.h
index 8763f99c4a7..ba74a95b74c 100644
--- a/src/mesa/main/fbobject.h
+++ b/src/mesa/main/fbobject.h
@@ -69,6 +69,9 @@ _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);
extern GLboolean
diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c
index b8fed182570..1e395363475 100644
--- a/src/mesa/main/formats.c
+++ b/src/mesa/main/formats.c
@@ -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:
diff --git a/src/mesa/main/formats.h b/src/mesa/main/formats.h
index d4dc5eac03e..9a5cef37788 100644
--- a/src/mesa/main/formats.h
+++ b/src/mesa/main/formats.h
@@ -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)
/**
diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c
index 63da71c95b4..948b3b7b5a2 100644
--- a/src/mesa/main/framebuffer.c
+++ b/src/mesa/main/framebuffer.c
@@ -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;
}
}
diff --git a/src/mesa/main/hint.c b/src/mesa/main/hint.c
index bdbd7519d37..ff8d88fffe0 100644
--- a/src/mesa/main/hint.c
+++ b/src/mesa/main/hint.c
@@ -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)");
diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c
index 909c18e7e60..63936132f98 100644
--- a/src/mesa/main/image.c
+++ b/src/mesa/main/image.c
@@ -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,
diff --git a/src/mesa/main/imports.c b/src/mesa/main/imports.c
index bd1fd7cfbf8..bf89815f2d3 100644
--- a/src/mesa/main/imports.c
+++ b/src/mesa/main/imports.c
@@ -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");
}
diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h
index 5ea647ad8d7..ce7baabe2c7 100644
--- a/src/mesa/main/imports.h
+++ b/src/mesa/main/imports.h
@@ -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);
diff --git a/src/mesa/main/lines.c b/src/mesa/main/lines.c
index 81e179a9254..79bf5679d8a 100644
--- a/src/mesa/main/lines.c
+++ b/src/mesa/main/lines.c
@@ -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 &&
diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c
index e073e17039f..d8a56103800 100644
--- a/src/mesa/main/mipmap.c
+++ b/src/mesa/main/mipmap.c
@@ -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()");
}
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 34003b4b6fb..b237063a6d8 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -84,23 +84,8 @@
/*@{*/
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;
diff --git a/src/mesa/main/queryobj.c b/src/mesa/main/queryobj.c
index ef6460b2f97..fa35c6ce58a 100644
--- a/src/mesa/main/queryobj.c
+++ b/src/mesa/main/queryobj.c
@@ -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);
diff --git a/src/mesa/main/readpix.c b/src/mesa/main/readpix.c
index e5b85ca32b4..9a4f15f7279 100644
--- a/src/mesa/main/readpix.c
+++ b/src/mesa/main/readpix.c
@@ -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 );
diff --git a/src/mesa/main/renderbuffer.c b/src/mesa/main/renderbuffer.c
index 23c662bab7f..67ee589d776 100644
--- a/src/mesa/main/renderbuffer.c
+++ b/src/mesa/main/renderbuffer.c
@@ -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;
}
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index a5e90d7cbd1..11b0f884fa4 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -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);
diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c
index 647fd31cab4..1d75845590f 100644
--- a/src/mesa/main/shaderobj.c
+++ b/src/mesa/main/shaderobj.c
@@ -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);
}
diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c
index cce1b464f0c..502c429294c 100644
--- a/src/mesa/main/state.c
+++ b/src/mesa/main/state.c
@@ -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;
}
diff --git a/src/mesa/main/stencil.c b/src/mesa/main/stencil.c
index 93e2e97ce0c..d898bf1d749 100644
--- a/src/mesa/main/stencil.c
+++ b/src/mesa/main/stencil.c
@@ -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;
diff --git a/src/mesa/main/texformat.c b/src/mesa/main/texformat.c
index 146b2b340e7..2542cea856b 100644
--- a/src/mesa/main/texformat.c
+++ b/src/mesa/main/texformat.c
@@ -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;
}
diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c
index da610798e12..28829694153 100644
--- a/src/mesa/main/texgetimage.c
+++ b/src/mesa/main/texgetimage.c
@@ -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;
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index 47d509396a7..1f2ad7f266b 100644
--- a/src/mesa/main/teximage.c
+++ b/src/mesa/main/teximage.c
@@ -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;
}
diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c
index 29e409d0b8c..6e14face4dd 100644
--- a/src/mesa/main/texparam.c
+++ b/src/mesa/main/texparam.c
@@ -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));
}
diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c
index aee2e6b4e9b..eb289722d1a 100644
--- a/src/mesa/main/uniforms.c
+++ b/src/mesa/main/uniforms.c
@@ -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];
}
}
}
diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c
index 29d8a8827e3..cfed4b506a5 100644
--- a/src/mesa/main/varray.c
+++ b/src/mesa/main/varray.c
@@ -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];
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 786fdfbd231..33c262f8ca4 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -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))
diff --git a/src/mesa/program/register_allocate.c b/src/mesa/program/register_allocate.c
index f984e2f1402..95a9bde401a 100644
--- a/src/mesa/program/register_allocate.c
+++ b/src/mesa/program/register_allocate.c
@@ -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;
diff --git a/src/mesa/program/sampler.cpp b/src/mesa/program/sampler.cpp
index 9a813c87955..1457d1199fa 100644
--- a/src/mesa/program/sampler.cpp
+++ b/src/mesa/program/sampler.cpp
@@ -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;
}
diff --git a/src/mesa/state_tracker/st_atom_blend.c b/src/mesa/state_tracker/st_atom_blend.c
index 8a3609e569f..fb1c7a4efee 100644
--- a/src/mesa/state_tracker/st_atom_blend.c
+++ b/src/mesa/state_tracker/st_atom_blend.c
@@ -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);
}
}
}
diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c
index 2843b7b1764..76386fe017a 100644
--- a/src/mesa/state_tracker/st_atom_framebuffer.c
+++ b/src/mesa/state_tracker/st_atom_framebuffer.c
@@ -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;
diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c
index 378b30e57cc..739a2eaab7e 100644
--- a/src/mesa/state_tracker/st_atom_pixeltransfer.c
+++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c
@@ -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;
}
diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c
index f92ca13d5e4..8bccceeec53 100644
--- a/src/mesa/state_tracker/st_atom_rasterizer.c
+++ b/src/mesa/state_tracker/st_atom_rasterizer.c
@@ -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
diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c
index b67068df373..474cbd5897d 100644
--- a/src/mesa/state_tracker/st_atom_sampler.c
+++ b/src/mesa/state_tracker/st_atom_sampler.c
@@ -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);
diff --git a/src/mesa/state_tracker/st_atom_viewport.c b/src/mesa/state_tracker/st_atom_viewport.c
index d10f1840df6..133cc49eaf0 100644
--- a/src/mesa/state_tracker/st_atom_viewport.c
+++ b/src/mesa/state_tracker/st_atom_viewport.c
@@ -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;
}
diff --git a/src/mesa/state_tracker/st_cb_accum.c b/src/mesa/state_tracker/st_cb_accum.c
index 35921f4f614..3e01c440bda 100644
--- a/src/mesa/state_tracker/st_cb_accum.c
+++ b/src/mesa/state_tracker/st_cb_accum.c
@@ -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);
diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c
index e23fe86daeb..0ea5671557c 100644
--- a/src/mesa/state_tracker/st_cb_bitmap.c
+++ b/src/mesa/state_tracker/st_cb_bitmap.c
@@ -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);
}
diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c b/src/mesa/state_tracker/st_cb_bufferobjects.c
index d4d9af4ada3..12528f49ff7 100644
--- a/src/mesa/state_tracker/st_cb_bufferobjects.c
+++ b/src/mesa/state_tracker/st_cb_bufferobjects.c
@@ -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;
diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c
index 6571bf237fb..0e0c4326ed7 100644
--- a/src/mesa/state_tracker/st_cb_clear.c
+++ b/src/mesa/state_tracker/st_cb_clear.c
@@ -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);
}
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index d128ff98f02..c0da1696247 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -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);
diff --git a/src/mesa/state_tracker/st_cb_drawtex.c b/src/mesa/state_tracker/st_cb_drawtex.c
index b540a79331b..86ceb9d78b3 100644
--- a/src/mesa/state_tracker/st_cb_drawtex.c
+++ b/src/mesa/state_tracker/st_cb_drawtex.c
@@ -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);
}
diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c
index 0c7641f8623..5eda2346c60 100644
--- a/src/mesa/state_tracker/st_cb_fbo.c
+++ b/src/mesa/state_tracker/st_cb_fbo.c
@@ -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;
diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c
index 0507be74578..4689a0032b7 100644
--- a/src/mesa/state_tracker/st_cb_readpixels.c
+++ b/src/mesa/state_tracker/st_cb_readpixels.c
@@ -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) {
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 09a10ba5819..08c498b1491 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -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;
@@ -261,6 +260,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.
*
* We use the given st_texture_image as a clue to determine the size of the
@@ -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));
@@ -407,125 +437,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().
*/
static void
@@ -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) {
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index c7f3949bf9e..7a19f35bbf5 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -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);
}
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index 64a8f790e22..77765f02379 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -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;
};
diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c
index 8e1263fe84e..6530a06ade4 100644
--- a/src/mesa/state_tracker/st_draw.c
+++ b/src/mesa/state_tracker/st_draw.c
@@ -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,57 +290,11 @@ 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.
* \param vbuffer returns vertex buffer info
@@ -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);
- }
}
diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c
index 4e76a050701..1e1220bfe52 100644
--- a/src/mesa/state_tracker/st_draw_feedback.c
+++ b/src/mesa/state_tracker/st_draw_feedback.c
@@ -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 */
diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c
index 974fd78d7c8..2f45f470334 100644
--- a/src/mesa/state_tracker/st_extensions.c
+++ b/src/mesa/state_tracker/st_extensions.c
@@ -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 */
diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c
index 2e0a664dd01..577ee6189bd 100644
--- a/src/mesa/state_tracker/st_format.c
+++ b/src/mesa/state_tracker/st_format.c
@@ -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);
+ }
+}
diff --git a/src/mesa/state_tracker/st_format.h b/src/mesa/state_tracker/st_format.h
index fe195c1069b..0fb570f6ee4 100644
--- a/src/mesa/state_tracker/st_format.h
+++ b/src/mesa/state_tracker/st_format.h
@@ -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 */
diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c
index c5f6008a222..4bf68280839 100644
--- a/src/mesa/state_tracker/st_gen_mipmap.c
+++ b/src/mesa/state_tracker/st_gen_mipmap.c
@@ -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,
diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c
index 179e5dc8392..5c8853cfadb 100644
--- a/src/mesa/state_tracker/st_manager.c
+++ b/src/mesa/state_tracker/st_manager.c
@@ -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);
diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c
index 42f1c2017f8..5c68fd78c30 100644
--- a/src/mesa/state_tracker/st_mesa_to_tgsi.c
+++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c
@@ -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);
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 7b32b46838a..fc1dfb3ef9e 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -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;
}
diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c
index 155ea39f18c..1e0a8323ab8 100644
--- a/src/mesa/state_tracker/st_texture.c
+++ b/src/mesa/state_tracker/st_texture.c
@@ -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;
@@ -98,6 +101,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.
*/
GLboolean
@@ -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),
diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
index bca856d7142..d50c3c9af79 100644
--- a/src/mesa/state_tracker/st_texture.h
+++ b/src/mesa/state_tracker/st_texture.h
@@ -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
index 15207e863e3..00000000000
--- a/src/mesa/swrast/s_trispan.h
+++ /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 */
diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c
index 858b8281da3..b1967e65417 100644
--- a/src/mesa/tnl/t_draw.c
+++ b/src/mesa/tnl/t_draw.c
@@ -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;
diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
index 37940efdc11..6834f3b5aa5 100644
--- a/src/mesa/vbo/vbo.h
+++ b/src/mesa/vbo/vbo.h
@@ -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);
diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h
index d56c91cd094..1b0ed79473b 100644
--- a/src/mesa/vbo/vbo_exec.h
+++ b/src/mesa/vbo/vbo_exec.h
@@ -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 );
diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
index 03d6bb4aefe..2f9f3ec7c46 100644
--- a/src/mesa/vbo/vbo_exec_api.c
+++ b/src/mesa/vbo/vbo_exec_api.c
@@ -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)
@@ -514,6 +533,24 @@ static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j )
/**
+ * 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.
*/
static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
@@ -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--;
diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
index 80085c17c5c..457343a1a5c 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -39,6 +39,43 @@
/**
+ * 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.
* If primitive restart is enabled, we need to ignore restart
@@ -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);
}
diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c
index 87f64310561..539658021e3 100644
--- a/src/mesa/vbo/vbo_exec_draw.c
+++ b/src/mesa/vbo/vbo_exec_draw.c
@@ -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) /
diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
index 4ee78e9e103..c8199544526 100644
--- a/src/mesa/vbo/vbo_save_api.c
+++ b/src/mesa/vbo/vbo_save_api.c
@@ -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 ); \
diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c
index d0454bf6212..634a6d3f84b 100644
--- a/src/mesa/vbo/vbo_save_draw.c
+++ b/src/mesa/vbo/vbo_save_draw.c
@@ -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;
}
}
diff --git a/src/mesa/x86-64/xform4.S b/src/mesa/x86-64/xform4.S
index e52a6118c31..6141e434679 100644
--- a/src/mesa/x86-64/xform4.S
+++ b/src/mesa/x86-64/xform4.S
@@ -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 */
diff --git a/src/mesa/x86/read_rgba_span_x86.S b/src/mesa/x86/read_rgba_span_x86.S
index 3886a510bbc..3be4515b114 100644
--- a/src/mesa/x86/read_rgba_span_x86.S
+++ b/src/mesa/x86/read_rgba_span_x86.S
@@ -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
index 3bf7029bb25..00000000000
--- a/src/talloc/SConscript
+++ /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
index 94a9ed024d3..00000000000
--- a/src/talloc/gpl-3.0.txt
+++ /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
index 65c5ca88a67..00000000000
--- a/src/talloc/lgpl-3.0.txt
+++ /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
index cc01346a7f0..00000000000
--- a/src/talloc/talloc.c
+++ /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
index 13d7a159cef..00000000000
--- a/src/talloc/talloc.def
+++ /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
index f549a17fba2..00000000000
--- a/src/talloc/talloc.h
+++ /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
index 01de806662d..00000000000
--- a/src/talloc/talloc_guide.txt
+++ /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